diff --git a/cateditor/src/components/AddProductDialog.vue b/cateditor/src/components/AddProductDialog.vue new file mode 100644 index 0000000..49a6b50 --- /dev/null +++ b/cateditor/src/components/AddProductDialog.vue @@ -0,0 +1,72 @@ + + + diff --git a/cateditor/src/components/CatalogContents.vue b/cateditor/src/components/CatalogContents.vue index 4b02b25..8818014 100644 --- a/cateditor/src/components/CatalogContents.vue +++ b/cateditor/src/components/CatalogContents.vue @@ -2,8 +2,7 @@ - Add products - Auto arrange + Add products @@ -20,7 +19,7 @@ @click="selectSection(item.id)" > @@ -126,6 +125,8 @@ + + @@ -136,18 +137,17 @@ import arrayMove from 'array-move' //import RawDisplayer from './RawDisplayer' import { paginateModels } from '@/pagination' import DragListHeading from './DragListHeading' +import AddProductDialog from './AddProductDialog' export default { components: { DragListHeading, + AddProductDialog, //RawDisplayer, }, data: () => ({ - // NOTE do we need? - 'placeholderText': 'placeholder', - // NOTE do we need? - 'selected': null, + showAddProductDialog: false, }), computed: { ...mapState([ @@ -186,13 +186,23 @@ export default { this.$store.dispatch('selectModel', id) }, + sectionModelCount(sectionID) { + let section = this.section(sectionID) + if (section) { + let models = this.sectionModels(section) || [] + return models.length + } else { + return 0 + } + }, + sectionListItemClasses: function(id, hovering) { if (id === this.selectedSectionID) { return 'list-item primary' } else if (hovering) { return 'list-item grey lighten-4' } else { - return '' + return 'list-item' } }, @@ -395,6 +405,12 @@ function addSectionDrops(myvue) { } .list-item { - //border-bottom: 1px solid #ddd; + background-color: white; + border-bottom: 1px solid #ddd; +} + +.list-group { + background-color: #f0f0ff; + min-height: 200px; } diff --git a/cateditor/src/pages/editor/store/index.js b/cateditor/src/pages/editor/store/index.js index ec8817f..adae648 100644 --- a/cateditor/src/pages/editor/store/index.js +++ b/cateditor/src/pages/editor/store/index.js @@ -2,7 +2,7 @@ import Vue from 'vue' import Vuex from 'vuex' import arrayMove from 'array-move' import axios from 'axios' -import { paginateModels } from '@/pagination' +import { paginateModels, sectionTitle, extendModelFromMaterial } from '@/pagination' Vue.use(Vuex) @@ -16,6 +16,7 @@ export const store = new Vuex.Store({ selectedMaterial: null, loadingCatalog: false, savingCatalog: false, + loadingProducts: false, }, getters: { @@ -41,6 +42,18 @@ export const store = new Vuex.Store({ } }, + nextSectionID: state => { + if (state.catalog != null) { + let id = 0 + for (let section of state.catalog.sections) { + id = Math.max(id, section.id) + } + return id + 1 + } else { + return -1 + } + }, + selectedSection: (state, getters) => { if (state.catalog && state.selectedSectionID) { return getters.section(state.selectedSectionID) @@ -69,9 +82,7 @@ export const store = new Vuex.Store({ // add extra info from a material let material = getters.material(model.ids[0]) if (material) { - model['name'] = material.name - model['model'] = material.model - model['family'] = material.family + model = extendModelFromMaterial(material, model) } else { console.log('no material found for id', model.ids[0]) } @@ -152,6 +163,11 @@ export const store = new Vuex.Store({ savingCatalog(state) { return state.savingCatalog }, + + loadingProducts(state) { + return state.loadingProducts + }, + }, mutations: { // @@ -170,6 +186,10 @@ export const store = new Vuex.Store({ // manipulation // + addSection(state, section) { + state.catalog.sections.push(section) + }, + reorderSection(state, { from, to }) { if (from === to) return state.catalog.sections = arrayMove(state.catalog.sections, from, to) @@ -235,6 +255,10 @@ export const store = new Vuex.Store({ state.savingCatalog = value }, + setLoadingProducts(state, value) { + state.loadingProducts = value + }, + setCatalogProperty(state, { key, value }) { console.log('mutation set prop', key, value) if (state.catalog) { @@ -325,6 +349,73 @@ export const store = new Vuex.Store({ commit('setSectionPages', { section: newSection, pages: newPages }) }, + addMaterialToCatalog({ commit, getters, state }, material) { + if (!state.catalog) { + console.log('no catalog to add materials to') + return + } + + // ensure material, not just id + if (typeof material === 'string' || typeof material === 'number') { + material = getters.material(material) + } + + let foundSection = null + let foundModels = null + + // look for an existing model in all our sections. + // add to first one found. + for (let section of state.catalog.sections) { + let models = getters.sectionModels(section) + let existingModel = models.find(m => m.model === material.model) + console.log('section', section.id, 'existing model search', existingModel) + if (existingModel) { + // prevent duplicates here, but also allow adding the same + // id again to a catalog. put in a new section so it can be + // placed elsewhere? + let existingMaterial = existingModel.ids.find(m => m.id === material.id) + console.log('model', existingModel.model, 'existing material', existingMaterial) + if (!existingMaterial) { + existingModel.ids.push(material.id) + foundSection = section + foundModels = models + } else { + console.log('skip duplicate') + } + break + } + } + + if (!foundSection) { + // see if we match a section, add a new model at the end + let title = sectionTitle(material) + for (let section of state.catalog.sections) { + if (title === section.name) { + let newModel = extendModelFromMaterial(material) + let models = getters.sectionModels(section) + models.push(newModel) + foundSection = section + break + } + } + } + + // still nothing, add into a new section + if (!foundSection) { + let title = sectionTitle(material) + let newModel = extendModelFromMaterial(material) + foundModels = [newModel] + foundSection = { + 'id': getters.nextSectionID, + 'name': title, + } + commit('addSection', foundSection) + } + + let pages = paginateModels(foundModels) + commit('setSectionPages', { section: foundSection, pages: pages }) + }, + // SET_CAT_SECTIONS: (context, payload) => { // context.commit('SET_CAT_SECTIONS', payload) // }, @@ -356,6 +447,32 @@ export const store = new Vuex.Store({ commit('setCatalog', {}) }, + async fetchProducts({ commit, dispatch }, text) { + commit('setLoadingProducts', true) + axios.post('/api/v1/products/search', text) + .then(function(response) { + commit('setLoadingProducts', false) + + if (response.data && response.data.missing) { + // TODO display these somehow + console.log('missing ids:', response.data.missing) + } + + if (response.data && response.data.found) { + console.log('found prods:', response.data.found) + commit('addMaterialsToLibrary', response.data.found) + for (let material of response.data.found) { + dispatch('addMaterialToCatalog', material) + } + } + }) + .catch(function(error) { + commit('setLoadingProducts', false) + // TODO set saving error property + console.error('error searching for prods: ', error) + }) + }, + async loadCatalog({ commit }, id) { try { commit('setLoadingCatalog', true) diff --git a/cateditor/src/pagination.js b/cateditor/src/pagination.js index 784d6c7..89f6c8d 100644 --- a/cateditor/src/pagination.js +++ b/cateditor/src/pagination.js @@ -43,3 +43,36 @@ export function sectionModels(section) { return models } + +export function sectionTitle(material) { + // "Trailhead (Men)" + if (material) { + return `${material.category} (${material.gender})` + } else { + return '(unknown)' + } +} + +// add properties from the material to the model, +// creating it if necessary. +export function extendModelFromMaterial(material, model = {}) { + if (material) { + if (!model['name']) { + // don't overwrite possibly overridden value + model['name'] = material.name + } + model['model'] = material.model + model['family'] = material.family + model['gender'] = material.gender + model['category'] = material.category + + // make sure the material id is in the list + let ids = model['ids'] || [] + if (!ids.includes(material.id)) { + ids.push(material.id) + model['ids'] = ids + } + } + + return model +}