Skip to content

Commit

Permalink
feat: open modal on category creation (#293)
Browse files Browse the repository at this point in the history
  • Loading branch information
ErikBjare committed Jun 10, 2021
1 parent 889a911 commit b4aabfa
Show file tree
Hide file tree
Showing 5 changed files with 173 additions and 121 deletions.
152 changes: 152 additions & 0 deletions src/components/CategoryEditModal.vue
@@ -0,0 +1,152 @@
<template lang="pug">
// The category edit modal
b-modal(id="edit" ref="edit" title="Edit category" @show="resetModal" @hidden="hidden" @ok="handleOk")
div.my-1
b-input-group.my-1(prepend="Name")
b-form-input(v-model="editing.name")
b-input-group(prepend="Parent")
b-select(v-model="editing.parent", :options="allCategories")

hr
div.my-1
b Rule
b-input-group.my-1(prepend="Type")
b-select(v-model="editing.rule.type", :options="allRuleTypes")
div(v-if="editing.rule.type === 'regex'")
b-input-group.my-1(prepend="Pattern")
b-form-input(v-model="editing.rule.regex")
b-form-checkbox(v-model="editing.rule.ignore_case" switch)
| Ignore case

hr
div.my-1
b Color

b-form-checkbox(v-model="editing.inherit_color" switch)
| Inherit parent color
div.mt-1(v-show="!editing.inherit_color")
color-picker(v-model="editing.color")

//
div.my-1
b Productivity score
b-input-group.my-1(prepend="Points")
b-form-input(v-model="editing.productivity")
hr
div.my-1
b-btn(variant="danger", @click="removeClass(categoryId); $refs.edit.hide()")
icon(name="trash")
| Remove category
</template>

<script>
import _ from 'lodash';
import ColorPicker from '~/components/ColorPicker';
export default {
name: 'CategoryEditModal',
components: {
'color-picker': ColorPicker,
},
props: {
categoryId: { type: Number, required: true },
},
data: function () {
return {
editing: {
id: 0, // FIXME: Use ID assigned to category in vuex store, in order for saves to be uniquely targeted
name: null,
rule: {},
parent: [],
inherit_color: true,
color: null,
},
};
},
computed: {
allCategories: function () {
const categories = this.$store.getters['categories/all_categories'];
const entries = categories.map(c => {
return { text: c.join('->'), value: c };
});
return [{ value: [], text: 'None' }].concat(entries);
},
allRuleTypes: function () {
return [
{ value: null, text: 'None' },
{ value: 'regex', text: 'Regular Expression' },
//{ value: 'glob', text: 'Glob pattern' },
];
},
},
watch: {
categoryId: function (new_value) {
if (new_value !== null) {
this.showModal();
}
},
},
mounted: function () {
if (this.categoryId !== null) {
this.showModal();
}
},
methods: {
showModal() {
this.$refs.edit.show();
},
hidden() {
this.$emit('hidden');
},
removeClass() {
// TODO: Show a confirmation dialog
// TODO: Remove children as well?
this.$store.commit('categories/removeClass', this.categoryId);
},
checkFormValidity() {
// FIXME
return true;
},
handleOk(event) {
// Prevent modal from closing
event.preventDefault();
// Trigger submit handler
this.handleSubmit();
},
handleSubmit() {
// Exit when the form isn't valid
if (!this.checkFormValidity()) {
return;
}
// Save the category
const new_class = {
id: this.editing.id,
name: this.editing.parent.concat(this.editing.name),
rule: this.editing.rule.type !== null ? this.editing.rule : { type: null },
data: { color: this.editing.inherit_color === true ? undefined : this.editing.color },
};
this.$store.commit('categories/updateClass', new_class);
// Hide the modal manually
this.$nextTick(() => {
this.$refs.edit.hide();
});
},
resetModal() {
const cat = this.$store.getters['categories/get_category_by_id'](this.categoryId);
const color = cat.data ? cat.data.color : undefined;
const inherit_color = !color;
this.editing = {
id: cat.id,
name: cat.subname,
rule: _.cloneDeep(cat.rule),
color,
inherit_color,
parent: cat.parent ? cat.parent : [],
};
},
},
};
</script>
131 changes: 14 additions & 117 deletions src/components/CategoryEditTree.vue
Expand Up @@ -16,55 +16,16 @@ div
span(v-if="_class.rule.type === 'regex'") Rule ({{_class.rule.type}}): #[code {{_class.rule.regex}}]
span(v-else, style="color: #888") No rule
span.float-right
b-btn.ml-1(size="sm", variant="outline-secondary", @click="showEditModal()" style="border: 0;" pill)
b-btn.ml-1(size="sm", variant="outline-secondary", @click="showEditModal(_class.id)" style="border: 0;" pill)
icon(name="edit")
b-btn.ml-1(size="sm", variant="outline-success", @click="addSubclass(_class); expanded = true" style="border: 0;" pill)
icon(name="plus")
div
div.pa-2(v-for="child in _class.children", style="background: rgba(0, 0, 0, 0);", v-show="expanded")
CategoryEditTree(:_class="child", :depth="depth+1")

b-modal(id="edit" ref="edit" title="Edit category" @show="resetModal" @hidden="resetModal" @ok="handleOk")
div.my-1
b-input-group.my-1(prepend="Name")
b-form-input(v-model="editing.name")
b-input-group(prepend="Parent")
b-select(v-model="editing.parent", :options="allCategories")

hr

div.my-1
b Rule
b-input-group.my-1(prepend="Type")
b-select(v-model="editing.rule.type", :options="allRuleTypes")
div(v-if="editing.rule.type === 'regex'")
b-input-group.my-1(prepend="Pattern")
b-form-input(v-model="editing.rule.regex")
b-form-checkbox(v-model="editing.rule.ignore_case" switch)
| Ignore case

hr

div.my-1
b Color

b-form-checkbox(v-model="editing.inherit_color" switch)
| Inherit parent color
div.mt-1(v-show="!editing.inherit_color")
color-picker(v-model="editing.color")

//
div.my-1
b Productivity score
b-input-group.my-1(prepend="Points")
b-form-input(v-model="editing.productivity")
hr

div.my-1
b-btn(variant="danger", @click="removeClass(_class); $refs.edit.hide()")
icon(name="trash")
| Remove category
div(v-if="editingId !== null")
CategoryEditModal(:categoryId='editingId', @hidden="hideEditModal()")
</template>

<script>
Expand All @@ -76,14 +37,14 @@ import 'vue-awesome/icons/trash';
import 'vue-awesome/icons/plus';
import 'vue-awesome/icons/edit';
import ColorPicker from '~/components/ColorPicker';
import CategoryEditModal from './CategoryEditModal.vue';
import _ from 'lodash';
export default {
name: 'CategoryEditTree',
components: {
'color-picker': ColorPicker,
CategoryEditModal: CategoryEditModal,
},
props: {
_class: Object,
Expand All @@ -95,32 +56,10 @@ export default {
data: function () {
return {
expanded: this.depth < 1,
color_focused: false,
editing: {
id: 0, // FIXME: Use ID assigned to category in vuex store, in order for saves to be uniquely targeted
name: null,
rule: {},
parent: [],
inherit_color: true,
color: null,
},
editingId: null,
};
},
computed: {
allCategories: function () {
const categories = this.$store.getters['categories/all_categories'];
const entries = categories.map(c => {
return { text: c.join('->'), value: c };
});
return [{ value: [], text: 'None' }].concat(entries);
},
allRuleTypes: function () {
return [
{ value: null, text: 'None' },
{ value: 'regex', text: 'Regular Expression' },
//{ value: 'glob', text: 'Glob pattern' },
];
},
totalChildren: function () {
function countChildren(node) {
return node.children.length + _.sum(_.map(node.children, countChildren));
Expand All @@ -134,58 +73,16 @@ export default {
name: parent.name.concat(['New class']),
rule: { type: 'regex', regex: 'FILL ME' },
});
},
removeClass: function (_class) {
// TODO: Show a confirmation dialog
// TODO: Remove children as well?
// TODO: Move button to edit modal?
this.$store.commit('categories/removeClass', _class);
},
showEditModal() {
this.$refs.edit.show();
},
checkFormValidity() {
// FIXME
return true;
},
handleOk(event) {
// Prevent modal from closing
event.preventDefault();
// Trigger submit handler
this.handleSubmit();
},
handleSubmit() {
// Exit when the form isn't valid
if (!this.checkFormValidity()) {
return;
}
// Save the category
const new_class = {
id: this.editing.id,
name: this.editing.parent.concat(this.editing.name),
rule: this.editing.rule.type !== null ? this.editing.rule : { type: null },
data: { color: this.editing.inherit_color === true ? undefined : this.editing.color },
};
this.$store.commit('categories/updateClass', new_class);
// Hide the modal manually
this.$nextTick(() => {
this.$refs.edit.hide();
});
// Find the category with the max ID, and open an editor for it
const lastId = _.max(_.map(this.$store.state.categories.classes, 'id'));
this.editingId = lastId;
},
showEditModal: function () {
this.editingId = this._class.id;
},
resetModal() {
const color = this._class.data ? this._class.data.color : undefined;
const inherit_color = !color;
this.editing = {
id: this._class.id,
name: this._class.subname,
rule: _.cloneDeep(this._class.rule),
color,
inherit_color,
parent: this._class.parent ? this._class.parent : [],
};
//console.log(this.editing);
hideEditModal: function () {
this.editingId = null;
},
},
};
Expand Down
1 change: 0 additions & 1 deletion src/components/ColorPicker.vue
Expand Up @@ -61,7 +61,6 @@ export default {
},
},
mounted() {
console.log('setting color', this.value);
this.setColor(this.value);
},
methods: {
Expand Down
8 changes: 6 additions & 2 deletions src/store/modules/categories.js
Expand Up @@ -5,6 +5,7 @@ import {
defaultCategories,
build_category_hierarchy,
createMissingParents,
annotate,
} from '~/util/classes';

// initial state
Expand Down Expand Up @@ -37,6 +38,9 @@ const getters = {
get_category: state => category_arr => {
return state.classes.find(c => _.isEqual(c.name, category_arr));
},
get_category_by_id: state => id => {
return annotate(_.cloneDeep(state.classes.find(c => c.id == id)));
},
};

// actions
Expand Down Expand Up @@ -95,8 +99,8 @@ const mutations = {
state.classes.push(new_class);
state.classes_unsaved_changes = true;
},
removeClass(state, cls) {
state.classes = state.classes.filter(c => c.id !== cls.id);
removeClass(state, classId) {
state.classes = state.classes.filter(c => c.id !== classId);
state.classes_unsaved_changes = true;
},
restoreDefaultClasses(state) {
Expand Down
2 changes: 1 addition & 1 deletion src/util/classes.ts
Expand Up @@ -78,7 +78,7 @@ export const defaultCategories: Category[] = [
{ name: ['Uncategorized'], rule: { type: null }, data: { color: COLOR_UNCAT } },
];

function annotate(c: Category) {
export function annotate(c: Category) {
const ch = c.name;
c.name_pretty = ch.join(level_sep);
c.subname = ch.slice(-1)[0];
Expand Down

1 comment on commit b4aabfa

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here are screenshots of this commit:

Screenshots using aw-server v0.10.0 (click to expand)

Screenshots using aw-server-rust master (click to expand)

Screenshots using aw-server-rust v0.10.0 (click to expand)

CML watermark

Please sign in to comment.