mirror of
https://github.com/SecurityBrewery/catalyst.git
synced 2025-12-16 12:12:45 +01:00
Add global settings (#40)
This commit is contained in:
@@ -22,6 +22,23 @@
|
||||
</v-list>
|
||||
</v-menu>
|
||||
·
|
||||
Kind:
|
||||
<v-menu offset-y class="mr-2">
|
||||
<template v-slot:activator="{ on, attrs }">
|
||||
<span v-bind="attrs" v-on="on">
|
||||
<v-icon small class="mr-1" :color="kindColor(artifact.kind)">{{ kindIcon(artifact.kind) }}</v-icon>
|
||||
<span :class="kindColor(artifact.kind) + '--text'">{{ artifact.kind | capitalize }}</span>
|
||||
</span>
|
||||
</template>
|
||||
<v-list>
|
||||
<v-list-item dense link v-for="state in otherKinds" :key="state.id" @click="setKind(state.id)">
|
||||
<v-list-item-title>
|
||||
Set kind to <v-icon small>{{ kindIcon(state.id) }}</v-icon> {{ state.name }}
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
·
|
||||
Type:
|
||||
<v-menu
|
||||
:close-on-content-click="false"
|
||||
@@ -148,6 +165,14 @@ export default Vue.extend({
|
||||
return state.id !== this.artifact.status;
|
||||
})
|
||||
},
|
||||
otherKinds: function (): Array<Type> {
|
||||
return this.lodash.filter(this.$store.state.settings.artifactKinds, (state: Type) => {
|
||||
if (!this.artifact || !this.artifact.status) {
|
||||
return true;
|
||||
}
|
||||
return state.id !== this.artifact.status;
|
||||
})
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
setArtifactType() {
|
||||
@@ -229,6 +254,42 @@ export default Vue.extend({
|
||||
}
|
||||
});
|
||||
},
|
||||
kindIcon: function (kind: string): string {
|
||||
let icon = "mdi-help";
|
||||
this.lodash.forEach(this.$store.state.settings.artifactKinds, (state: Type) => {
|
||||
if (kind === state.id) {
|
||||
icon = state.icon;
|
||||
}
|
||||
})
|
||||
return icon;
|
||||
},
|
||||
kindColor: function (kind: string) {
|
||||
let color = TypeColorEnum.Info as TypeColorEnum;
|
||||
this.lodash.forEach(this.$store.state.settings.artifactKinds, (state: Type) => {
|
||||
if (kind === state.id && state.color) {
|
||||
color = state.color
|
||||
}
|
||||
})
|
||||
return color;
|
||||
},
|
||||
setKind(kind: string) {
|
||||
if (!this.artifact || !this.artifact.name || this.ticketID === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
let artifact = this.artifact
|
||||
artifact.kind = kind
|
||||
API.setArtifact(this.ticketID, this.artifact.name, artifact).then((response) => {
|
||||
this.$store.dispatch("alertSuccess", { name: "Artifact kind changed", type: "success" })
|
||||
if (response.data.artifacts) {
|
||||
this.lodash.forEach(response.data.artifacts, (artifact) => {
|
||||
if (artifact.name == this.name) {
|
||||
this.artifact = artifact;
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
},
|
||||
load() {
|
||||
this.loadArtifact(this.ticketID, this.name);
|
||||
}
|
||||
|
||||
177
ui/src/views/Settings.vue
Normal file
177
ui/src/views/Settings.vue
Normal file
@@ -0,0 +1,177 @@
|
||||
<template>
|
||||
<v-main class="ma-4">
|
||||
<div v-if="settings !== undefined">
|
||||
<v-text-field label="Time Format" v-model="settings.timeformat"></v-text-field>
|
||||
|
||||
<v-subheader class="mx-0 px-0">Artifact States</v-subheader>
|
||||
<v-card v-for="state in settings.artifactStates" :key="state.id" class="d-flex mb-2">
|
||||
<v-row class="px-4 pt-2" dense>
|
||||
<v-col>
|
||||
<v-text-field label="ID" v-model="state.id"></v-text-field>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-text-field label="Name" v-model="state.name"></v-text-field>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-text-field label="Icon" v-model="state.icon"></v-text-field>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-select label="Color" v-model="state.color" :items="['info', 'error', 'success', 'warning']" clearable></v-select>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-btn icon class="mt-6 mr-4" @click="removeState(state.id)"><v-icon>mdi-close</v-icon></v-btn>
|
||||
</v-card>
|
||||
<v-card class="d-flex mb-2">
|
||||
<v-row class="px-4 pt-2" dense>
|
||||
<v-col>
|
||||
<v-text-field label="ID" v-model="newState.id"></v-text-field>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-text-field label="Name" v-model="newState.name"></v-text-field>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-text-field label="Icon" v-model="newState.icon"></v-text-field>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-select label="Color" v-model="newState.color" :items="['info', 'error', 'success', 'warning']" clearable></v-select>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-btn icon class="mt-6 mr-4" @click="addState"><v-icon>mdi-plus</v-icon></v-btn>
|
||||
</v-card>
|
||||
|
||||
<v-subheader class="mx-0 px-0">Artifact Types</v-subheader>
|
||||
<v-card v-for="state in settings.artifactKinds" :key="state.id" class="d-flex mb-2">
|
||||
<v-row class="px-4 pt-2" dense>
|
||||
<v-col>
|
||||
<v-text-field label="ID" v-model="state.id"></v-text-field>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-text-field label="Name" v-model="state.name"></v-text-field>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-text-field label="Icon" v-model="state.icon"></v-text-field>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-select label="Color" v-model="state.color" :items="['info', 'error', 'success', 'warning']" clearable></v-select>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-btn icon class="mt-6 mr-4" @click="removeKind(state.id)"><v-icon>mdi-close</v-icon></v-btn>
|
||||
</v-card>
|
||||
<v-card class="d-flex mb-2">
|
||||
<v-row class="px-4 pt-2" dense>
|
||||
<v-col>
|
||||
<v-text-field label="ID" v-model="newKind.id"></v-text-field>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-text-field label="Name" v-model="newKind.name"></v-text-field>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-text-field label="Icon" v-model="newKind.icon"></v-text-field>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-select label="Color" v-model="newKind.color" :items="['info', 'error', 'success', 'warning']" clearable></v-select>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-btn icon class="mt-6 mr-4" @click="addKind"><v-icon>mdi-plus</v-icon></v-btn>
|
||||
</v-card>
|
||||
|
||||
<v-btn color="success" @click="save" outlined class="mt-2">
|
||||
<v-icon>mdi-content-save</v-icon>
|
||||
Save
|
||||
</v-btn>
|
||||
</div>
|
||||
</v-main>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import {DateTime} from "luxon";
|
||||
import Vue from "vue";
|
||||
import {Settings, SettingsResponse, Type} from "@/client";
|
||||
import {API} from "@/services/api";
|
||||
import {AxiosResponse} from "axios";
|
||||
|
||||
interface State {
|
||||
valid: boolean;
|
||||
settings?: Settings;
|
||||
newState: Type;
|
||||
newKind: Type;
|
||||
}
|
||||
|
||||
export default Vue.extend({
|
||||
name: "Settings",
|
||||
data: (): State => ({
|
||||
valid: true,
|
||||
settings: undefined,
|
||||
newState: {} as Type,
|
||||
newKind: {} as Type,
|
||||
}),
|
||||
methods: {
|
||||
save: function () {
|
||||
if (this.settings === undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
API.saveSettings(this.settings).then((response) => {
|
||||
this.settings = response.data;
|
||||
this.$store.dispatch("getSettings");
|
||||
})
|
||||
},
|
||||
addState: function () {
|
||||
if (this.settings === undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
this.settings.artifactStates.push(this.newState);
|
||||
this.newState = {} as Type;
|
||||
},
|
||||
removeState: function (id: string) {
|
||||
if (this.settings === undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
this.settings.artifactStates = this.lodash.filter(this.settings.artifactStates, function (t) { return t.id !== id });
|
||||
},
|
||||
addKind: function () {
|
||||
if (this.settings === undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
this.settings.artifactKinds.push(this.newKind);
|
||||
this.newKind = {} as Type;
|
||||
},
|
||||
removeKind: function (id: string) {
|
||||
if (this.settings === undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
this.settings.artifactKinds = this.lodash.filter(this.settings.artifactKinds, function (t) { return t.id !== id });
|
||||
},
|
||||
timeformat: function (s: string) {
|
||||
let format = this.$store.state.settings.timeformat;
|
||||
if (!format) {
|
||||
return DateTime.fromISO(s).toLocaleString(DateTime.DATETIME_SHORT);
|
||||
}
|
||||
return DateTime.fromISO(s).toFormat(format);
|
||||
},
|
||||
dateformat: function (s: string) {
|
||||
let format = this.$store.state.settings.timeformat;
|
||||
if (!format) {
|
||||
return DateTime.fromISO(s).toLocaleString(DateTime.DATETIME_SHORT);
|
||||
}
|
||||
return DateTime.fromISO(s).toFormat(format);
|
||||
},
|
||||
datetimeformat: function (s: string) {
|
||||
let format = this.$store.state.settings.timeformat;
|
||||
if (!format) {
|
||||
return DateTime.fromISO(s).toLocaleString(DateTime.DATETIME_SHORT);
|
||||
}
|
||||
return DateTime.fromISO(s).toFormat(format);
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
API.getSettings().then((response: AxiosResponse<SettingsResponse>) => {
|
||||
this.settings = response.data;
|
||||
})
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -181,7 +181,7 @@
|
||||
<v-jsf
|
||||
v-model="ticket.details"
|
||||
:schema="schema"
|
||||
:options="{ initialValidation: 'all', formats: { time: timeformat, date: dateformat, 'date-time': datetimeformat } }"
|
||||
:options="{ initialValidation: 'all', formats: { time: timeformat, date: dateformat, 'date-time': datetimeformat }, editMode: 'inline' }"
|
||||
/>
|
||||
</v-form>
|
||||
<v-btn small class="float-right mb-2" color="card" @click="saveTicket" outlined>
|
||||
|
||||
Reference in New Issue
Block a user