From f0f9c458a56fbd001afb9be8e12f3f5690dfc11d Mon Sep 17 00:00:00 2001 From: avele <34437766+avele@users.noreply.github.com> Date: Sat, 13 Jul 2019 17:29:23 +0400 Subject: [PATCH] Front/fix/category sections enabling (#335) * Formatting * Category sections enabling fixes #317; Warning when disabling editing secitons; * Removed unused import --- front/client/components/Category.vue | 1 + front/client/components/CategoryInfoEdit.vue | 57 +++++++++++++------ front/client/components/CategoryItem.vue | 39 ++++++++++++- .../client/components/CategoryItemSection.vue | 2 +- .../client/components/CategoryItemTraits.vue | 18 +++--- front/client/store/modules/category.ts | 49 ++++++++++++++-- 6 files changed, 134 insertions(+), 32 deletions(-) diff --git a/front/client/components/Category.vue b/front/client/components/Category.vue index 480bea3..0c6239e 100644 --- a/front/client/components/Category.vue +++ b/front/client/components/Category.vue @@ -30,6 +30,7 @@ :toc="value.toc" :notes="value.notes" :kind="value.kind" + :sections="category.sections" /> @@ -83,7 +86,6 @@ import Vue from 'vue' import Component from 'vue-class-component' import { Prop, Watch } from 'vue-property-decorator' -import { CategoryStatus } from 'client/service/Category' @Component export default class CategoryInfoEdit extends Vue { @@ -95,6 +97,13 @@ export default class CategoryInfoEdit extends Vue { checkboxSections: any[] = [] isValid: boolean = false + // TODO replace ItemProsConsSection and other to constants + sectionDisableWarningAgreed = { + ItemProsConsSection: false, + ItemEcosystemSection: false, + ItemNotesSection: false + } + categoryStatuses = [ { name: 'Complete', value: 'CategoryFinished' }, { name: 'Work in progress', value: 'CategoryWIP' }, @@ -118,19 +127,35 @@ export default class CategoryInfoEdit extends Vue { } this.title = category.title this.group = category.group - this.checkboxSections = category.sections + this.checkboxSections = category.sections.slice() this.categoryStatus = category.status + this.sectionDisableWarningAgreed = { + ItemProsConsSection: false, + ItemEcosystemSection: false, + ItemNotesSection: false + } } - transformCategoryStatus (status: string) { - switch (status) { - case CategoryStatus.finished: - return 'Complete' - case CategoryStatus.inProgress: - return 'Work in progress' - default: - return 'Stub' + async updateSectionEnabling (sectionValue, sectionName) { + const index = this.checkboxSections.indexOf(sectionValue) + const isSectionRemoved = index !== -1 + if (!isSectionRemoved) { + this.checkboxSections.push(sectionValue) + return } + + const isOriginallyEnabled = this.category.sections.includes(sectionValue) + const isSectionInEdit = this.$store.state.category.itemsSectionsInEdit[sectionValue].length + const wasAgreedOnce = this.sectionDisableWarningAgreed[sectionValue] + if (isOriginallyEnabled && isSectionInEdit && !wasAgreedOnce) { + const isConfirmed = await this._confirm({ fullText: `You have unsaved changes in one of items’ ${sectionName} section. If you disable this section, your changes will be lost.` }) + if (!isConfirmed) { + return + } + this.sectionDisableWarningAgreed[sectionValue] = true + } + + this.checkboxSections.splice(index, 1) } close () { diff --git a/front/client/components/CategoryItem.vue b/front/client/components/CategoryItem.vue index e27b0c0..a40c0d4 100644 --- a/front/client/components/CategoryItem.vue +++ b/front/client/components/CategoryItem.vue @@ -27,31 +27,40 @@ /> -
+
import Vue from 'vue' import Component from 'vue-class-component' -import { Prop } from 'vue-property-decorator' +import { Prop, Watch } from 'vue-property-decorator' import { ICategoryItem } from 'client/service/CategoryItem.ts' import CategoryItemToolbar from 'client/components/CategoryItemToolbar.vue' import CategoryItemSection from 'client/components/CategoryItemSection.vue' @@ -132,8 +141,26 @@ export default class CategoryItem extends Vue { @Prop(String) itemUid!: string @Prop(String) link!: string @Prop(String) hackage!: string + @Prop(Array) sections!: string[] isNoteExpanded: boolean = false + isPropsEditing: boolean = false + isConsEditing: boolean = false + + get isAnyTraitEditing () { + return this.isPropsEditing || this.isConsEditing + } + + @Watch('isAnyTraitEditing', { immediate: true }) + updateItemTraitEditingState (newVal, prevVal) { + if (newVal !== prevVal) { + this.$store.dispatch('category/toggleItemProsConsSectionEdit', this.itemUid) + } + } + + isSectionEnabled (section) { + return this.sections.includes(section) + } expandNotes (): void { this.isNoteExpanded = true @@ -143,6 +170,14 @@ export default class CategoryItem extends Vue { this.isNoteExpanded = false } + toggleItemEcosystemEditState () { + this.$store.dispatch('category/toggleItemEcosystemSectionEdit', this.itemUid) + } + + toggleItemNotesEditState () { + this.$store.dispatch('category/toggleItemNotesSectionEdit', this.itemUid) + } + @CatchConflictDecorator async updateSummary ({ original, modified }): Promise { await this.$store.dispatch('categoryItem/updateItemSummary', { diff --git a/front/client/components/CategoryItemSection.vue b/front/client/components/CategoryItemSection.vue index 20819b7..3a0cff8 100644 --- a/front/client/components/CategoryItemSection.vue +++ b/front/client/components/CategoryItemSection.vue @@ -64,8 +64,8 @@ export default class CategoryItemSection extends Vue { isEdit: boolean = false toggleEdit (): void { + this.$emit('toggleEdit') if (this.customEdit) { - this.$emit('toggleEdit') return } this.isEdit = !this.isEdit diff --git a/front/client/components/CategoryItemTraits.vue b/front/client/components/CategoryItemTraits.vue index 19d80d5..fd2591a 100644 --- a/front/client/components/CategoryItemTraits.vue +++ b/front/client/components/CategoryItemTraits.vue @@ -118,27 +118,29 @@ export default class CategoryItemTraits extends Vue { @Prop(Array) traits!: any[] @Prop(String) type!: string @Prop(String) itemId: string + @Prop(Boolean) isAnyTraitEditing: boolean - isEdit: boolean = false isAddTrait: boolean = false traitsModel = [] get title () { return this.type + 's' } + get isAnyTraitEditingOrAdding () { + return this.traitsModel.some(x => x.isEdit) || this.isAddTrait + } - @Watch('traits', { - immediate: true - }) + @Watch('isAnyTraitEditingOrAdding', { immediate: true }) + updateIsEditing (newVal) { + this.$emit('update:isAnyTraitEditing', newVal) + } + + @Watch('traits', { immediate: true }) setTraitsModel (traits) { this.traitsModel = _cloneDeep(traits) this.traitsModel.forEach(x => this.$set(x, 'isEdit', false)) } - toggleEdit () { - this.isEdit = !this.isEdit - } - @CatchConflictDecorator async saveEdit ({ trait, original, modified }) { await this.$store.dispatch('categoryItem/updateItemTrait', { diff --git a/front/client/store/modules/category.ts b/front/client/store/modules/category.ts index 0f8a216..0dc5fd5 100644 --- a/front/client/store/modules/category.ts +++ b/front/client/store/modules/category.ts @@ -1,14 +1,25 @@ import { ActionTree, GetterTree, MutationTree, ActionContext, Module } from 'vuex' import { ICategoryInfo, ICategoryFull, CategoryService } from 'client/service/Category' +import { ICategoryItem } from 'client/service/CategoryItem' interface ICategoryState { categoryList: ICategoryInfo[], - category: ICategoryFull + category: ICategoryFull, + itemsSectionsInEdit: { + ItemProsConsSection: Array + ItemEcosystemSection: Array + ItemNotesSection: Array + } } const state = (): ICategoryState => ({ categoryList: [], - category: null + category: null, + itemsSectionsInEdit: { + ItemProsConsSection: [], + ItemEcosystemSection: [], + ItemNotesSection: [] + } }) const getters: GetterTree = {} @@ -44,15 +55,33 @@ const actions: ActionTree = { dispatch('loadCategoryList') return createdId }, - async updateCategoryInfo (context: ActionContext, {id, title, group, status, sections}) { - await CategoryService.updateCategoryInfo({id, title, group, status, sections}) + async updateCategoryInfo (context: ActionContext, { id, title, group, status, sections }) { + await CategoryService.updateCategoryInfo({ id, title, group, status, sections }) }, async deleteCategory ( { dispatch }: ActionContext, id: ICategoryInfo['id'] ): Promise { await CategoryService.deleteCategory(id) - } + }, + toggleItemProsConsSectionEdit ( + { commit }: ActionContext, + itemId: ICategoryItem['id'] + ) { + commit('toggleSectionEditState', { sectionName: 'ItemProsConsSection', itemId }) + }, + toggleItemEcosystemSectionEdit ( + { commit }: ActionContext, + itemId: ICategoryItem['id'] + ) { + commit('toggleSectionEditState', { sectionName: 'ItemEcosystemSection', itemId }) + }, + toggleItemNotesSectionEdit ( + { commit }: ActionContext, + itemId: ICategoryItem['id'] + ) { + commit('toggleSectionEditState', { sectionName: 'ItemNotesSection', itemId }) + }, } const mutations: MutationTree = { @@ -61,6 +90,16 @@ const mutations: MutationTree = { }, setCategory: (state: ICategoryState, payload: ICategoryFull) => { state.category = payload + }, + toggleSectionEditState (state, { sectionName, itemId }) { + const sectionEditState = state.itemsSectionsInEdit[sectionName] + + if (sectionEditState.includes(itemId)) { + const index = sectionEditState.indexOf(itemId) + sectionEditState.splice(index, 1) + } else { + sectionEditState.push(itemId) + } } }