cateditor contents page add lists

This commit is contained in:
Seth Ladygo
2019-04-10 15:25:25 -07:00
parent f044e939a9
commit fff6c66ada
9 changed files with 595 additions and 180 deletions

View File

@ -1,25 +1,28 @@
<template> <template>
<v-container fluid grid-list-lg> <v-container fluid grid-list-lg>
<v-layout row> <v-layout row>
<FancyList/> <SectionList/>
<ProductFamilyList/>
<!-- <ModelList/> -->
<MaterialList/>
</v-layout> </v-layout>
</v-container> </v-container>
</template> </template>
<script> <script>
import FancyList from './FancyList' import SectionList from './SectionList'
import ProductFamilyList from './ProductFamilyList'
// import ModelList from './ModelList'
import MaterialList from './MaterialList'
export default { export default {
components: { components: {
FancyList SectionList,
ProductFamilyList,
// ModelList,
MaterialList,
}, },
data: () => ({ data: () => ({
seasons: [ 'SS19', 'FW19', 'SS20' ],
regions: [ 'US', 'Canada', 'Mexico' ],
season: null,
region: null,
name: null,
ispublic: true
}) })
} }
</script> </script>

View File

@ -1,141 +0,0 @@
<template>
<v-container fluid grid-list-lg>
<v-layout row>
<v-flex xs5>
<v-card>
<v-toolbar dense>
<v-toolbar-title>Categories</v-toolbar-title>
<v-spacer></v-spacer>
<v-btn icon><v-icon>add</v-icon></v-btn>
</v-toolbar>
<draggable v-model="sections" group="categories" @choose="listChoose">
<div v-for="item in sections" :key="item.id">
<v-hover
:key="item.id"
:categoryid="item.id">
<v-list-tile
slot-scope="{ hover }"
:class="listItemClasses(item.id, hover)"
@click="selectCategory(item.id)"
>
<!-- <v-list-tile-action>
<v-icon color="black">drag_handle</v-icon>
</v-list-tile-action> -->
<v-list-tile-content>
<v-list-tile-title v-html="item.name"></v-list-tile-title>
<!-- <v-list-tile-sub-title v-html="item.name"></v-list-tile-sub-title> -->
</v-list-tile-content>
<v-list-tile-action>
<span class="group">
<v-btn icon @click="popInfo(item.id)">
<v-icon small color="grey lighten-1">info</v-icon>
</v-btn>
<v-btn icon @click="popDelete(item.id)">
<v-icon small color="grey lighten-1">delete</v-icon>
</v-btn>
</span>
</v-list-tile-action>
</v-list-tile>
</v-hover>
</div>
</draggable>
</v-card>
</v-flex>
<v-flex xs5>
<RawDisplayer :value="sections" title="Data" />
</v-flex>
<CategoryInfoDialog v-model="showCatPopup" v-bind:category="selectedCategory"/>
<CategoryDeleteDialog v-model="showDeleteCatPopup" v-bind:category="selectedCategory"/>
</v-layout>
</v-container>
</template>
<script>
import draggable from 'vuedraggable'
import RawDisplayer from './RawDisplayer'
import CategoryInfoDialog from './CategoryInfoDialog'
import CategoryDeleteDialog from './CategoryDeleteDialog'
export default {
components: {
draggable,
CategoryInfoDialog,
CategoryDeleteDialog,
RawDisplayer
},
props: {
selected: Number
},
data: () => ({
showCatPopup: false,
showDeleteCatPopup: false,
selectedCategory: null
}),
computed: {
sections: {
get () {
return this.$store.getters.CAT_SECTIONS
},
set (value) {
this.$store.dispatch('SET_CAT_SECTIONS', value)
}
}
},
methods: {
listChoose: function (evt) {
var id = Number(evt.item.firstChild.getAttribute('categoryid'))
this.selectCategory(id)
},
listItemClasses: function (id, hovering) {
if (id === this.selectedCategory) {
return 'primary'
} else if (hovering) {
return 'grey lighten-4'
} else {
return ''
}
},
selectCategory: function (id) {
this.selectedCategory = id
},
popInfo: function (id) {
this.selectCategory(id)
this.showCatPopup = true
},
popDelete: function (id) {
this.selectCategory(id)
this.showDeleteCatPopup = true
}
}
}
</script>
<style scoped>
.button {
margin-top: 35px;
}
.handle {
float: left;
padding-top: 8px;
padding-bottom: 8px;
}
.close {
float: right;
padding-top: 8px;
padding-bottom: 8px;
}
input {
display: inline-block;
width: 50%;
}
.text {
margin: 20px;
}
</style>

View File

@ -0,0 +1,114 @@
<template>
<v-container>
<v-card>
<v-card flat color="grey lighten-4" >
<v-card-title>Styles</v-card-title>
</v-card>
<!-- <v-toolbar dense>
<v-toolbar-title>Categories</v-toolbar-title>
<v-spacer></v-spacer>
<v-btn icon><v-icon>add</v-icon></v-btn>
</v-toolbar> -->
<draggable v-model="materials" group="materials">
<div v-for="item in materials" :key="item.id">
<v-hover
:key="item.id"
:materialid="item.id">
<v-list-tile
slot-scope="{ hover }"
:class="listItemClasses(item.id, hover)"
@click="selectMaterial(item.id)"
>
<v-list-tile-content>
<v-list-tile-title><b>{{ item.id }}</b> {{ item.name }}</v-list-tile-title>
<v-list-tile-sub-title v-html="item.color"></v-list-tile-sub-title>
</v-list-tile-content>
<v-list-tile-action>
<span class="group">
<v-btn icon @click="popInfo(item.id)">
<v-icon small color="grey lighten-1">info</v-icon>
</v-btn>
<v-btn icon @click="popDelete(item.id)">
<v-icon small color="grey lighten-1">delete</v-icon>
</v-btn>
</span>
</v-list-tile-action>
</v-list-tile>
</v-hover>
</div>
</draggable>
</v-card>
<!-- <v-flex xs5>
<RawDisplayer :value="materials" title="Data" />
</v-flex> -->
</v-container>
</template>
<script>
import draggable from 'vuedraggable'
import SelectionMixin from './SelectionMixin'
/* import RawDisplayer from './RawDisplayer' */
/* import SectionInfoDialog from './SectionInfoDialog'
* import SectionDeleteDialog from './SectionDeleteDialog' */
export default {
mixins: [SelectionMixin],
components: {
draggable,
/* SectionInfoDialog,
* SectionDeleteDialog, */
/* RawDisplayer */
},
/* props: {
* }, */
/* data: () => ({
* }), */
computed: {
materials: {
get () {
if (this.selectedFamilyID != null) {
let family = this.selectedFamily()
return this.findMaterials(family.materials)
} else if (this.selectedModelID != null) {
// TODO
return []
} else {
return []
}
},
/* set (value) {
* // TODO complicated logic
* } */
},
},
methods: {
listItemClasses: function (id, hovering) {
/* if (id === this.selectedMaterial) {
return 'primary'
} else */
if (hovering) {
return 'grey lighten-4'
} else {
return ''
}
},
popInfo: function (id) {
this.selectMaterial(id)
//this.showSectionPopup = true
},
popDelete: function (id) {
this.selectMaterial(id)
//this.showDeleteSectionPopup = true
},
}
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,113 @@
<template>
<v-container>
<v-card>
<v-card flat color="grey lighten-4" >
<v-card-title>Product Families</v-card-title>
</v-card>
<draggable v-model="families" group="categories">
<div v-for="item in families" :key="item.id">
<v-hover :key="item.id">
<v-list-tile
slot-scope="{ hover }"
:class="listItemClasses(item.id, hover)"
@click="selectFamily(item.id)"
>
<v-list-tile-content>
<v-list-tile-title v-html="item.name"></v-list-tile-title>
<v-list-tile-sub-title v-html="item.models.length"></v-list-tile-sub-title>
</v-list-tile-content>
<v-list-tile-action>
<span class="group">
<v-btn icon @click.stop="popInfo(item.id)">
<v-icon small color="grey lighten-1">info</v-icon>
</v-btn>
<v-btn icon @click.stop="popDelete(item.id)">
<v-icon small color="grey lighten-1">delete</v-icon>
</v-btn>
</span>
</v-list-tile-action>
</v-list-tile>
</v-hover>
</div>
</draggable>
</v-card>
<!-- <v-flex xs5>
<RawDisplayer :value="families" title="Data" />
</v-flex> -->
<!-- <SectionInfoDialog v-model="showInfoPopup" v-bind:section="selectedSectionID"/>
<SectionDeleteDialog v-model="showDeletePopup" v-bind:section="selectedSectionID"/> -->
</v-container>
</template>
<script>
import draggable from 'vuedraggable'
import SelectionMixin from './SelectionMixin'
/* import RawDisplayer from './RawDisplayer' */
/* import SectionInfoDialog from './SectionInfoDialog'
* import SectionDeleteDialog from './SectionDeleteDialog' */
export default {
mixins: [SelectionMixin],
components: {
draggable,
/* SectionInfoDialog,
* SectionDeleteDialog, */
/* RawDisplayer, */
},
props: {
selected: Number,
},
data: () => ({
showInfoPopup: false,
showDeletePopup: false,
}),
computed: {
families: {
get () {
return this.selectedFamilies()
},
set (value) {
// TODO complicated logic
//this.$store.dispatch('SET_CAT_SECTIONS', value)
}
},
/*currentSectionData: {
get () {
return this.$store.getters.SELECTED_SECTION
},
},*/
},
methods: {
listChoose: function (evt) {
var id = Number(evt.item.firstChild.getAttribute('familyid'))
this.selectFamily(id)
},
listItemClasses: function (id, hovering) {
if (id === this.selectedFamilyID) {
return 'primary'
} else if (hovering) {
return 'grey lighten-4'
} else {
return ''
}
},
popInfo: function (id) {
this.selectFamily(id)
this.showInfoPopup = true
},
popDelete: function (id) {
this.selectFamily(id)
this.showDeletePopup = true
},
}
}
</script>
<style scoped>
</style>

View File

@ -2,10 +2,10 @@
<v-layout row justify-center> <v-layout row justify-center>
<v-dialog v-model="show" max-width="250"> <v-dialog v-model="show" max-width="250">
<v-card> <v-card>
<v-card-title>Delete Category</v-card-title> <v-card-title>Delete Section</v-card-title>
<v-card-text> <v-card-text>
Really delete category: Really delete section:
<input v-model="name"/> <input v-model="name"/>
</v-card-text> </v-card-text>
@ -26,7 +26,7 @@ export default {
}), }),
props: { props: {
value: Boolean, value: Boolean,
category: { section: {
type: Number, type: Number,
required: false required: false
} }
@ -42,7 +42,8 @@ export default {
}, },
name: { name: {
get () { get () {
var section = this.$store.getters.CAT_SECTION(this.category) var sectionID = this.$store.getters.SELECTED_SECTION_ID
var section = this.$store.getters.CAT_SECTION(sectionID)
return section ? section.name : '(none)' return section ? section.name : '(none)'
} }
} }

View File

@ -3,14 +3,13 @@
<v-dialog v-model="show" width="250"> <v-dialog v-model="show" width="250">
<v-card> <v-card>
<v-toolbar dark dense> <v-toolbar dark dense>
<v-toolbar-title>Category Info</v-toolbar-title> <v-toolbar-title>Section Info</v-toolbar-title>
<v-spacer></v-spacer> <v-spacer></v-spacer>
<v-btn icon @click="show = false"><v-icon>close</v-icon></v-btn> <v-btn icon @click="show = false"><v-icon>close</v-icon></v-btn>
</v-toolbar> </v-toolbar>
<v-card-text> <v-card-text>
<v-text-field v-model="name" label="Name" required></v-text-field> <v-text-field v-model="name" label="Name" required></v-text-field>
<input v-model="category"/>
<input v-model="families"/> <input v-model="families"/>
<input v-model="models"/> <input v-model="models"/>
<input v-model="materials"/> <input v-model="materials"/>
@ -30,16 +29,11 @@
// https://stackoverflow.com/questions/48035310/open-a-vuetify-dialog-from-a-component-template-in-vuejs // https://stackoverflow.com/questions/48035310/open-a-vuetify-dialog-from-a-component-template-in-vuejs
export default { export default {
data: () => ({ data: () => ({
/* name: 'Trailhead (Men)', */
models: '5 models', models: '5 models',
materials: '12 materials' materials: '12 materials'
}), }),
props: { props: {
value: Boolean, value: Boolean,
category: {
type: Number,
required: false
}
}, },
computed: { computed: {
show: { show: {
@ -52,15 +46,18 @@ export default {
}, },
name: { name: {
get () { get () {
var section = this.$store.getters.CAT_SECTION(this.category) var sectionID = this.$store.getters.SELECTED_SECTION_ID
var section = this.$store.getters.CAT_SECTION(sectionID)
return section ? section.name : '(none)' return section ? section.name : '(none)'
}, },
set (value) { set (value) {
var sectionID = this.$store.getters.SELECTED_SECTION_ID
this.$store.dispatch('SET_CAT_SECTION_NAME', this.$store.dispatch('SET_CAT_SECTION_NAME',
{ id: this.category, name: value }) { id: sectionID, name: value })
} }
}, },
families () { families () {
// TODO
return this.$store.getters.CAT_FAMILIES return this.$store.getters.CAT_FAMILIES
} }
} }

View File

@ -0,0 +1,120 @@
<template>
<v-container>
<v-card>
<v-card flat color="grey lighten-4" >
<v-card-title>Sections</v-card-title>
</v-card>
<!-- <v-toolbar dense>
<v-toolbar-title>Sections</v-toolbar-title>
<v-spacer></v-spacer>
<v-btn icon>
<v-tooltip top>
<template v-slot:activator="{ on }">
<v-icon v-on="on">add</v-icon>
</template>
<span>Add new section</span>
</v-tooltip>
</v-btn>
</v-toolbar> -->
<draggable v-model="sections" group="categories">
<div v-for="item in sections" :key="item.id">
<v-hover :key="item.id">
<v-list-tile
slot-scope="{ hover }"
:class="listItemClasses(item.id, hover)"
@click="selectSection(item.id)"
>
<v-list-tile-content>
<v-list-tile-title v-html="item.name"></v-list-tile-title>
<v-list-tile-sub-title color="text--grey lighten-1">12 models</v-list-tile-sub-title>
</v-list-tile-content>
<v-list-tile-action>
<span class="group">
<v-btn icon @click.stop="popInfo(item.id)">
<v-icon small color="grey lighten-1">info</v-icon>
</v-btn>
<v-btn icon @click.stop="popDelete(item.id)">
<v-icon small color="grey lighten-1">delete</v-icon>
</v-btn>
</span>
</v-list-tile-action>
</v-list-tile>
</v-hover>
</div>
</draggable>
</v-card>
<!--<v-flex xs5>
<RawDisplayer :value="sections" title="Data" />
</v-flex>-->
<SectionInfoDialog v-model="showSectionPopup" v-bind:section="selectedSectionID"/>
<SectionDeleteDialog v-model="showDeleteSectionPopup" v-bind:section="selectedSectionID"/>
</v-container>
</template>
<script>
import draggable from 'vuedraggable'
import SelectionMixin from './SelectionMixin'
/* import RawDisplayer from './RawDisplayer' */
import SectionInfoDialog from './SectionInfoDialog'
import SectionDeleteDialog from './SectionDeleteDialog'
export default {
mixins: [SelectionMixin],
components: {
draggable,
SectionInfoDialog,
SectionDeleteDialog,
// RawDisplayer,
},
props: {
selected: Number
},
data: () => ({
showSectionPopup: false,
showDeleteSectionPopup: false,
}),
computed: {
sections: {
get () {
return this.$store.getters.CAT_SECTIONS
},
set (value) {
this.$store.dispatch('SET_CAT_SECTIONS', value)
}
},
},
methods: {
listChoose: function (evt) {
var id = Number(evt.item.firstChild.getAttribute('sectionid'))
this.selectSection(id)
},
listItemClasses: function (id, hovering) {
if (id === this.selectedSectionID) {
return 'primary'
} else if (hovering) {
return 'grey lighten-4'
} else {
return ''
}
},
popInfo: function (id) {
this.selectSection(id)
this.showSectionPopup = true
},
popDelete: function (id) {
this.selectSection(id)
this.showDeleteSectionPopup = true
}
}
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,111 @@
const SelectionMixin = { // eslint-disable-line no-unused-vars
computed: {
selectedSectionID: {
get () {
return this.$store.getters.SELECTED_SECTION_ID
},
set (value) {
this.$store.dispatch('SET_SELECTED_SECTION_ID', value)
}
},
selectedFamilyID: {
get () {
return this.$store.getters.SELECTED_FAMILY_ID
},
set (value) {
this.$store.dispatch('SET_SELECTED_FAMILY_ID', value)
}
},
selectedModelID: {
get () {
return this.$store.getters.SELECTED_MODEL_ID
},
set (value) {
this.$store.dispatch('SET_SELECTED_MODEL_ID', value)
}
},
selectedMaterial: {
get () {
return this.$store.getters.SELECTED_MATERIAL_ID
},
set (value) {
this.$store.dispatch('SET_SELECTED_MATERIAL_ID', value)
}
},
},
methods: {
selectSection: function (id) {
this.selectedSectionID = id
// this.selectedFamilyID = null
// this.selectedModelID = null
// this.selectedMaterial = null
},
selectFamily: function (id) {
this.selectedFamilyID = id
// this.selectedModelID = null
// this.selectedMaterial = null
},
selectModel: function (id) {
this.selectedModelID = id
// this.selectedFamilyID = null
// this.selectedMaterial = null
},
selectMaterial: function (id) {
this.selectedMaterial = id
},
selectedFamilies: function () {
let section = this.$store.getters.CAT_SECTION(this.selectedSectionID)
let ids = this.sectionIDs(section)
let materials = this.findMaterials(ids)
return this.makeFamilies(materials)
},
selectedFamily: function () {
let families = this.selectedFamilies()
return families.find(s => s.id === this.selectedFamilyID)
},
sectionIDs: function (section) {
let ids = []
if (section !== undefined) {
for (let page of section.pages) {
for (let block of page) {
ids.push(...block.ids)
}
}
}
return ids
},
findMaterials: function (ids) {
return ids.map(id => this.$store.getters.MATERIAL(id))
},
makeFamilies: function (materials) {
let families = []
for (let mat of materials) {
let family = families.length > 0 ? families[families.length - 1] : null
if (family === null || family.id !== mat.family) {
// new family
family = { id: mat.family,
name: mat.name, // TODO where does this come from?
models: [mat.model],
materials: [mat.id] }
families.push(family)
} else {
// add to existing
family.materials.push(mat.id)
family.models.push(mat.model)
family.models = this.uniquify(family.models)
}
}
return families
},
uniquify: function (arr) {
return [...new Set(arr)]
},
}
}
export default SelectionMixin

View File

@ -7,16 +7,61 @@ export const store = new Vuex.Store({
state: { state: {
catalog: { catalog: {
name: 'my catalog', name: 'my catalog',
sections: [{ id: 1, name: 'trailhead (men)' }, owner: 12,
{ id: 2, name: 'trailhead (women)' }, created: '2019-04-04T22:00:14Z',
{ id: 3, name: 'waterfront (men)' }, sections: [
{ id: 4, name: 'waterfront (women)' }], { id: 1,
families: 5, name: 'Trailhead (Men)',
models: 12, pages: [
materials: 27 [{ name: 'model name override', size: 2, ids: ['1001001', '1001002'] },
} { size: 1, ids: ['1001011', '1001012'] }], // one page, two blocks
[{ size: 1, ids: ['1001021'] }],
],
},
{ id: 2,
name: 'Waterfront (Men)',
pages: [
[{ size: 1, ids: ['1001021'] }],
],
},
],
},
materials: {
'1001001': { id: '1001001', // call them sap maybe?
model: 'AW123',
family: 'MF123',
name: 'Targhee WP',
color: 'Green / Blue' },
'1001002': { id: '1001002',
model: 'AW123',
family: 'MF123',
name: 'Targhee WP',
color: 'Red / Purple' },
'1001011': { id: '1001011',
model: 'WA999',
family: 'MF123',
name: 'Targhee WP FA',
color: 'Green / Blue' },
'1001012': { id: '1001012',
model: 'WA999',
family: 'MF123',
name: 'Targhee WP FA',
color: 'Green / Blue' },
'1001021': { id: '1001021',
model: 'BBB22',
family: 'BBBMF',
name: 'Slither',
color: 'Green / Blue' },
},
selectedSectionID: null,
selectedFamilyID: null,
selectedModelID: null,
selectedMaterial: null,
}, },
getters: { getters: {
//
// catalog info
//
CAT_NAME: state => { CAT_NAME: state => {
return state.catalog.name return state.catalog.name
}, },
@ -26,9 +71,30 @@ export const store = new Vuex.Store({
CAT_SECTION: (state) => (id) => { CAT_SECTION: (state) => (id) => {
return state.catalog.sections.find(s => s.id === id) return state.catalog.sections.find(s => s.id === id)
}, },
CAT_FAMILIES: state => { //
return state.catalog.families + ' product families' // selection info
} //
SELECTED_SECTION_ID: state => {
return state.selectedSectionID
},
// SELECTED_SECTION: state => {
// return store.getters.CAT_SECTION(state.selectedSectionID)
// },
SELECTED_FAMILY_ID: state => {
return state.selectedFamilyID
},
SELECTED_MODEL_ID: state => {
return state.selectedModelID
},
SELECTED_MATERIAL_ID: state => {
return state.selectedMaterial
},
//
// material info
//
MATERIAL: (state) => (id) => {
return state.materials[id]
},
}, },
mutations: { mutations: {
SET_CAT_SECTIONS: (state, payload) => { SET_CAT_SECTIONS: (state, payload) => {
@ -37,7 +103,26 @@ export const store = new Vuex.Store({
SET_CAT_SECTION_NAME: (state, payload) => { SET_CAT_SECTION_NAME: (state, payload) => {
var section = state.catalog.sections.find(s => s.id === payload.id) var section = state.catalog.sections.find(s => s.id === payload.id)
section.name = payload.name section.name = payload.name
} },
SET_SELECTED_SECTION_ID: (state, payload) => {
state.selectedSectionID = payload
state.selectedFamilyID = null
state.selectedModelID = null
state.selectedMaterial = null
},
SET_SELECTED_FAMILY_ID: (state, payload) => {
state.selectedFamilyID = payload
state.selectedModelID = null
state.selectedMaterial = null
},
SET_SELECTED_MODEL_ID: (state, payload) => {
state.selectedModelID = payload
state.selectedFamilyID = null
state.selectedMaterial = null
},
SET_SELECTED_MATERIAL_ID: (state, payload) => {
state.selectedMaterial = payload
},
}, },
actions: { actions: {
SET_CAT_SECTIONS: (context, payload) => { SET_CAT_SECTIONS: (context, payload) => {
@ -45,10 +130,22 @@ export const store = new Vuex.Store({
}, },
SET_CAT_SECTION_NAME: (context, payload) => { SET_CAT_SECTION_NAME: (context, payload) => {
context.commit('SET_CAT_SECTION_NAME', payload) context.commit('SET_CAT_SECTION_NAME', payload)
} },
// SAVE_TODO : async (context,payload) => { SET_SELECTED_SECTION_ID: (context, payload) => {
// let { data } = await Axios.post('http://yourwebsite.com/api/todo') context.commit('SET_SELECTED_SECTION_ID', payload)
// context.commit('ADD_TODO',payload) },
// }, SET_SELECTED_FAMILY_ID: (context, payload) => {
context.commit('SET_SELECTED_FAMILY_ID', payload)
},
SET_SELECTED_MODEL_ID: (context, payload) => {
context.commit('SET_SELECTED_MODEL_ID', payload)
},
SET_SELECTED_MATERIAL_ID: (context, payload) => {
context.commit('SET_SELECTED_MATERIAL_ID', payload)
},
// SAVE_TODO : async (context,payload) => {
// let { data } = await Axios.post('http://yourwebsite.com/api/todo')
// context.commit('ADD_TODO',payload)
// },
} }
}) })