big pagination update - split models into pages
This commit is contained in:
@ -141,9 +141,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import Sortable from 'sortablejs'
|
import Sortable from 'sortablejs'
|
||||||
import { mapState, mapGetters, mapActions } from 'vuex'
|
import { mapState, mapGetters, mapActions } from 'vuex'
|
||||||
import arrayMove from 'array-move'
|
|
||||||
//import RawDisplayer from './RawDisplayer'
|
//import RawDisplayer from './RawDisplayer'
|
||||||
import { paginateModels } from '@/pagination'
|
|
||||||
import DragListHeading from './DragListHeading'
|
import DragListHeading from './DragListHeading'
|
||||||
import AddProductDialog from './AddProductDialog'
|
import AddProductDialog from './AddProductDialog'
|
||||||
import AddSectionDialog from './AddSectionDialog'
|
import AddSectionDialog from './AddSectionDialog'
|
||||||
@ -244,19 +242,6 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
reorderModel(fromIndex, toIndex) {
|
|
||||||
let models = this.selectedModels
|
|
||||||
arrayMove.mutate(models, fromIndex, toIndex)
|
|
||||||
let pages = paginateModels(models)
|
|
||||||
this.setSectionPages({ section: this.selectedSection, pages: pages })
|
|
||||||
},
|
|
||||||
|
|
||||||
reorderMaterial(fromIndex, toIndex) {
|
|
||||||
let mats = this.selectedMaterials
|
|
||||||
arrayMove.mutate(mats, fromIndex, toIndex)
|
|
||||||
this.setModelMaterials({ model: this.selectedModel, materials: mats })
|
|
||||||
},
|
|
||||||
|
|
||||||
popSectionInfo(id) {
|
popSectionInfo(id) {
|
||||||
this.selectSection(id)
|
this.selectSection(id)
|
||||||
this.showSectionInfoDialog = true
|
this.showSectionInfoDialog = true
|
||||||
@ -287,8 +272,8 @@ export default {
|
|||||||
'selectModel',
|
'selectModel',
|
||||||
'selectMaterial',
|
'selectMaterial',
|
||||||
'reorderSection',
|
'reorderSection',
|
||||||
'setSectionPages',
|
'reorderModel',
|
||||||
'setModelMaterials',
|
'reorderMaterial',
|
||||||
'moveModelToSection',
|
'moveModelToSection',
|
||||||
'moveMaterialToSection',
|
'moveMaterialToSection',
|
||||||
]),
|
]),
|
||||||
@ -318,7 +303,9 @@ export default {
|
|||||||
},
|
},
|
||||||
onEnd: function(evt) {
|
onEnd: function(evt) {
|
||||||
if (evt.from === evt.to) {
|
if (evt.from === evt.to) {
|
||||||
me.reorderModel(evt.oldIndex, evt.newIndex)
|
me.reorderModel({ section: me.selectedSection,
|
||||||
|
fromIndex: evt.oldIndex,
|
||||||
|
toIndex: evt.newIndex })
|
||||||
} else {
|
} else {
|
||||||
// dropped on a section.
|
// dropped on a section.
|
||||||
let models = me.selectedModels
|
let models = me.selectedModels
|
||||||
@ -349,7 +336,10 @@ export default {
|
|||||||
},
|
},
|
||||||
onEnd: function(evt) {
|
onEnd: function(evt) {
|
||||||
if (evt.from === evt.to) {
|
if (evt.from === evt.to) {
|
||||||
me.reorderMaterial(evt.oldIndex, evt.newIndex)
|
me.reorderMaterial({ section: me.selectedSection,
|
||||||
|
model: me.selectedModel,
|
||||||
|
fromIndex: evt.oldIndex,
|
||||||
|
toIndex: evt.newIndex })
|
||||||
} else {
|
} else {
|
||||||
// dropped on a section.
|
// dropped on a section.
|
||||||
let mats = me.selectedMaterials
|
let mats = me.selectedMaterials
|
||||||
@ -360,6 +350,7 @@ export default {
|
|||||||
|
|
||||||
if (me.selectedSection.id !== newSection.id) {
|
if (me.selectedSection.id !== newSection.id) {
|
||||||
me.moveMaterialToSection({ material: mat,
|
me.moveMaterialToSection({ material: mat,
|
||||||
|
oldSection: me.selectedSection,
|
||||||
oldModel: me.selectedModel,
|
oldModel: me.selectedModel,
|
||||||
newSection: newSection })
|
newSection: newSection })
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -85,7 +85,6 @@ export default {
|
|||||||
|
|
||||||
doDelete() {
|
doDelete() {
|
||||||
this.deleteModelMaterial({ section: this.selectedSection,
|
this.deleteModelMaterial({ section: this.selectedSection,
|
||||||
model: this.selectedModel,
|
|
||||||
material: this.selectedMaterial })
|
material: this.selectedMaterial })
|
||||||
this.show = false
|
this.show = false
|
||||||
},
|
},
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import Vue from 'vue'
|
|||||||
import Vuex from 'vuex'
|
import Vuex from 'vuex'
|
||||||
import arrayMove from 'array-move'
|
import arrayMove from 'array-move'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { paginateModels, sectionTitle, extendModelFromMaterial } from '@/pagination'
|
import { modelsFromSection, paginateModels, sectionTitle, extendModelFromMaterial } from '@/pagination'
|
||||||
|
|
||||||
Vue.use(Vuex)
|
Vue.use(Vuex)
|
||||||
|
|
||||||
@ -47,35 +47,25 @@ export const store = new Vuex.Store({
|
|||||||
},
|
},
|
||||||
|
|
||||||
selectedModel: (state, getters) => {
|
selectedModel: (state, getters) => {
|
||||||
if (state.catalog && state.selectedModelID) {
|
if (state.selectedModelID) {
|
||||||
let section = getters.selectedSection
|
let section = getters.selectedSection
|
||||||
let models = getters.sectionModels(section)
|
return getters.sectionModel(section, state.selectedModelID)
|
||||||
return models.find(s => s.model === state.selectedModelID)
|
|
||||||
} else {
|
} else {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// find a model within a section
|
||||||
|
// NOTE: returns copies of the original catalog data
|
||||||
|
sectionModel: (state, getters) => (section, model) => {
|
||||||
|
let modelID = (typeof model === 'object') ? model.model : model
|
||||||
|
let models = getters.sectionModels(section)
|
||||||
|
return models.find(m => m.model === modelID)
|
||||||
|
},
|
||||||
|
|
||||||
|
// NOTE: returns copies of the original catalog data
|
||||||
sectionModels: (state, getters) => (section) => {
|
sectionModels: (state, getters) => (section) => {
|
||||||
// remove pages, return models (blocks) in order
|
return modelsFromSection(section, getters)
|
||||||
let models = []
|
|
||||||
if (section && section.pages) {
|
|
||||||
for (let page of section.pages) {
|
|
||||||
for (let model of page) {
|
|
||||||
if (model.ids && model.ids.length > 0) {
|
|
||||||
// add extra info from a material
|
|
||||||
let material = getters.material(model.ids[0])
|
|
||||||
if (material) {
|
|
||||||
model = extendModelFromMaterial(material, model)
|
|
||||||
} else {
|
|
||||||
console.log('no material found for id', model.ids[0])
|
|
||||||
}
|
|
||||||
models.push(model)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return models
|
|
||||||
},
|
},
|
||||||
|
|
||||||
modelMaterials: (state, getters) => (model) => {
|
modelMaterials: (state, getters) => (model) => {
|
||||||
@ -150,6 +140,7 @@ export const store = new Vuex.Store({
|
|||||||
section.name = name
|
section.name = name
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// move a section in the section list
|
||||||
reorderSection(state, { from, to }) {
|
reorderSection(state, { from, to }) {
|
||||||
if (from === to) return
|
if (from === to) return
|
||||||
state.catalog.sections = arrayMove(state.catalog.sections, from, to)
|
state.catalog.sections = arrayMove(state.catalog.sections, from, to)
|
||||||
@ -157,7 +148,13 @@ export const store = new Vuex.Store({
|
|||||||
|
|
||||||
setSectionPages(state, { section, pages }) {
|
setSectionPages(state, { section, pages }) {
|
||||||
if (section) {
|
if (section) {
|
||||||
section.pages = pages
|
// update actual catalog data (we might be passed a copy)
|
||||||
|
let catSection = state.catalog.sections.find(s => s.id === section.id)
|
||||||
|
if (catSection) {
|
||||||
|
catSection.pages = pages
|
||||||
|
} else {
|
||||||
|
console.error('couldn\'t find catalog section', section.id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -165,12 +162,6 @@ export const store = new Vuex.Store({
|
|||||||
model.name = name
|
model.name = name
|
||||||
},
|
},
|
||||||
|
|
||||||
setModelMaterials(state, { model, materials }) {
|
|
||||||
if (model) {
|
|
||||||
model.ids = materials.map(m => (typeof m === 'object') ? m.id : m)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
addMaterialsToLibrary(state, materials) {
|
addMaterialsToLibrary(state, materials) {
|
||||||
console.log('adding', materials.length, 'materials')
|
console.log('adding', materials.length, 'materials')
|
||||||
let map = {}
|
let map = {}
|
||||||
@ -247,10 +238,29 @@ export const store = new Vuex.Store({
|
|||||||
commit('setSectionName', payload)
|
commit('setSectionName', payload)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// move a section in the section list
|
||||||
reorderSection({ commit }, payload) {
|
reorderSection({ commit }, payload) {
|
||||||
commit('reorderSection', payload)
|
commit('reorderSection', payload)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// move a model in the section's model list
|
||||||
|
reorderModel({ commit, getters }, { section, fromIndex, toIndex }) {
|
||||||
|
let models = getters.sectionModels(section)
|
||||||
|
arrayMove.mutate(models, fromIndex, toIndex)
|
||||||
|
let pages = paginateModels(models)
|
||||||
|
commit('setSectionPages', { section: section, pages: pages })
|
||||||
|
},
|
||||||
|
|
||||||
|
// move a material in the models's material list
|
||||||
|
reorderMaterial({ commit, getters }, { section, model, fromIndex, toIndex }) {
|
||||||
|
let models = getters.sectionModels(section)
|
||||||
|
let updateModel = models.find(m => m.model === model.model)
|
||||||
|
updateModel.ids = model.ids
|
||||||
|
arrayMove.mutate(updateModel.ids, fromIndex, toIndex)
|
||||||
|
let pages = paginateModels(models)
|
||||||
|
commit('setSectionPages', { section: section, pages: pages })
|
||||||
|
},
|
||||||
|
|
||||||
setSectionPages({ commit }, payload) {
|
setSectionPages({ commit }, payload) {
|
||||||
commit('setSectionPages', payload)
|
commit('setSectionPages', payload)
|
||||||
},
|
},
|
||||||
@ -266,10 +276,6 @@ export const store = new Vuex.Store({
|
|||||||
commit('setSectionPages', { section: section, pages: pages })
|
commit('setSectionPages', { section: section, pages: pages })
|
||||||
},
|
},
|
||||||
|
|
||||||
setModelMaterials({ commit }, payload) {
|
|
||||||
commit('setModelMaterials', payload)
|
|
||||||
},
|
|
||||||
|
|
||||||
moveModelToSection({ commit, getters }, { model, oldSection, newSection }) {
|
moveModelToSection({ commit, getters }, { model, oldSection, newSection }) {
|
||||||
// remove model from old section
|
// remove model from old section
|
||||||
let oldModels = getters.sectionModels(oldSection)
|
let oldModels = getters.sectionModels(oldSection)
|
||||||
@ -295,15 +301,18 @@ export const store = new Vuex.Store({
|
|||||||
commit('setSectionPages', { section: newSection, pages: newPages })
|
commit('setSectionPages', { section: newSection, pages: newPages })
|
||||||
},
|
},
|
||||||
|
|
||||||
moveMaterialToSection({ commit, getters }, { material, oldModel, newSection }) {
|
moveMaterialToSection({ commit, getters }, { material, oldSection, oldModel, newSection }) {
|
||||||
// ensure material, not just id
|
// ensure material, not just id
|
||||||
if (typeof material === 'string' || typeof material === 'number') {
|
if (typeof material === 'string' || typeof material === 'number') {
|
||||||
material = getters.material(material)
|
material = getters.material(material)
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove material from old model
|
// remove material from old model
|
||||||
let mats = oldModel.ids.filter(id => id !== material.id)
|
let oldModels = getters.sectionModels(oldSection)
|
||||||
commit('setModelMaterials', { model: oldModel, materials: mats })
|
let realOldModel = oldModels.find(m => m.model === oldModel.model)
|
||||||
|
realOldModel.ids = realOldModel.ids.filter(id => id !== material.id)
|
||||||
|
let oldPages = paginateModels(oldModels)
|
||||||
|
commit('setSectionPages', { section: oldSection, pages: oldPages })
|
||||||
|
|
||||||
// add material to new section
|
// add material to new section
|
||||||
let newModels = getters.sectionModels(newSection)
|
let newModels = getters.sectionModels(newSection)
|
||||||
@ -338,12 +347,10 @@ export const store = new Vuex.Store({
|
|||||||
let models = getters.sectionModels(section)
|
let models = getters.sectionModels(section)
|
||||||
let existingModel = models.find(m => m.model === material.model)
|
let existingModel = models.find(m => m.model === material.model)
|
||||||
if (existingModel) {
|
if (existingModel) {
|
||||||
// console.log('section', section.id, 'found existing model', existingModel)
|
|
||||||
// NOTE prevent duplicates here, but also allow adding the same
|
// NOTE prevent duplicates here, but also allow adding the same
|
||||||
// id again to a catalog. put in a new section so it can be
|
// id again to a catalog. put in a new section so it can be
|
||||||
// placed elsewhere? handle later.
|
// placed elsewhere? handle later.
|
||||||
let existingMaterial = existingModel.ids.find(m => m === material.id)
|
let existingMaterial = existingModel.ids.find(m => m === material.id)
|
||||||
// console.log('model', existingModel.model, 'existing material', existingMaterial)
|
|
||||||
foundSection = section
|
foundSection = section
|
||||||
foundModels = models
|
foundModels = models
|
||||||
if (!existingMaterial) {
|
if (!existingMaterial) {
|
||||||
@ -386,13 +393,10 @@ export const store = new Vuex.Store({
|
|||||||
commit('setSectionPages', { section: foundSection, pages: pages })
|
commit('setSectionPages', { section: foundSection, pages: pages })
|
||||||
},
|
},
|
||||||
|
|
||||||
deleteModelMaterial({ commit, getters }, { section, model, material }) {
|
deleteModelMaterial({ commit, getters }, { section, material }) {
|
||||||
let mats = model.ids.filter(id => id !== material.id)
|
|
||||||
|
|
||||||
commit('setModelMaterials', { model: model, materials: mats })
|
|
||||||
|
|
||||||
// repaginate section
|
|
||||||
let models = getters.sectionModels(section)
|
let models = getters.sectionModels(section)
|
||||||
|
let catalogModel = models.find(m => m.model === material.model)
|
||||||
|
catalogModel.ids = catalogModel.ids.filter(id => id !== material.id)
|
||||||
let pages = paginateModels(models)
|
let pages = paginateModels(models)
|
||||||
commit('setSectionPages', { section: section, pages: pages })
|
commit('setSectionPages', { section: section, pages: pages })
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,23 +1,111 @@
|
|||||||
|
const MAX_PAGE_MATERIALS = 16
|
||||||
|
const MATERIALS_PER_ROW = 4
|
||||||
|
const MAX_BLOCK_SIZE = 3
|
||||||
|
|
||||||
|
function chunkify(array, size) {
|
||||||
|
let chunks = []
|
||||||
|
for (let i = 0, j = array.length; i < j; i += size) {
|
||||||
|
let slice = array.slice(i, i + size)
|
||||||
|
chunks.push(slice)
|
||||||
|
}
|
||||||
|
return chunks
|
||||||
|
}
|
||||||
|
|
||||||
|
function copyModel(model) {
|
||||||
|
if (model) {
|
||||||
|
return JSON.parse(JSON.stringify(model))
|
||||||
|
} else {
|
||||||
|
console.error('no model to copy')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function copyModels(models) {
|
||||||
|
let copies = []
|
||||||
|
|
||||||
|
if (models) {
|
||||||
|
for (let model of models) {
|
||||||
|
let copy = copyModel(model)
|
||||||
|
copies.push(copy)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return copies
|
||||||
|
}
|
||||||
|
|
||||||
|
// split models with too many materials
|
||||||
|
function splitModels(models) {
|
||||||
|
let splits = []
|
||||||
|
for (let model of models) {
|
||||||
|
if (model.size > MAX_BLOCK_SIZE) {
|
||||||
|
let chunks = chunkify(model.ids, MAX_PAGE_MATERIALS)
|
||||||
|
for (let chunk of chunks) {
|
||||||
|
let splitModel = copyModel(model)
|
||||||
|
splitModel.ids = chunk
|
||||||
|
splits.push(splitModel)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
splits.push(copyModel(model))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return splits
|
||||||
|
}
|
||||||
|
|
||||||
|
// join adjacent models with the same model number
|
||||||
|
function joinModels(models) {
|
||||||
|
let joins = []
|
||||||
|
let lastModel = null
|
||||||
|
for (let model of models) {
|
||||||
|
model = copyModel(model)
|
||||||
|
if (lastModel) {
|
||||||
|
if (lastModel.model === model.model) {
|
||||||
|
// match - join
|
||||||
|
lastModel.ids.push(...model.ids)
|
||||||
|
// uniquify
|
||||||
|
lastModel.ids = lastModel.ids.filter((v, i, a) => a.indexOf(v) === i)
|
||||||
|
} else {
|
||||||
|
// no match - add
|
||||||
|
joins.push(model)
|
||||||
|
lastModel = model
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// first - add
|
||||||
|
joins.push(model)
|
||||||
|
lastModel = model
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return joins
|
||||||
|
}
|
||||||
|
|
||||||
export function paginateModels(models) {
|
export function paginateModels(models) {
|
||||||
|
models = joinModels(models)
|
||||||
|
|
||||||
for (let model of models) {
|
for (let model of models) {
|
||||||
// ensure sizes
|
model.size = modelBlockSize(model)
|
||||||
model.size = modelSize(model)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
models = splitModels(models)
|
||||||
|
|
||||||
|
for (let model of models) {
|
||||||
|
model.size = modelBlockSize(model)
|
||||||
|
}
|
||||||
|
|
||||||
|
models = copyModels(models)
|
||||||
|
|
||||||
let pages = []
|
let pages = []
|
||||||
let currentSize = 0
|
let currentSize = 0
|
||||||
let currentPage = []
|
let currentPage = []
|
||||||
for (let model of models) {
|
for (let model of models) {
|
||||||
if (model.size > 0) { // skip empty models
|
if (model.size < 1) {
|
||||||
currentSize += model.size
|
// skip empty models
|
||||||
if (currentSize > 3) {
|
continue
|
||||||
pages.push(currentPage)
|
}
|
||||||
currentPage = [model]
|
currentSize += model.size
|
||||||
currentSize = model.size
|
if (currentSize > 3) {
|
||||||
} else {
|
pages.push(currentPage)
|
||||||
currentPage.push(model)
|
currentPage = [model]
|
||||||
}
|
currentSize = model.size
|
||||||
|
} else {
|
||||||
|
currentPage.push(model)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (currentPage.length > 0) {
|
if (currentPage.length > 0) {
|
||||||
@ -27,23 +115,37 @@ export function paginateModels(models) {
|
|||||||
return pages
|
return pages
|
||||||
}
|
}
|
||||||
|
|
||||||
export function modelSize(model) {
|
export function modelBlockSize(model) {
|
||||||
if (!model || !model.ids) return 0
|
if (!model || !model.ids) return 0
|
||||||
if (model.ids.length <= 4) return 1
|
if (model.ids.length <= MATERIALS_PER_ROW) return 1
|
||||||
if (model.ids.length <= 8) return 2
|
if (model.ids.length <= MATERIALS_PER_ROW * 2) return 2
|
||||||
return 3
|
if (model.ids.length <= MATERIALS_PER_ROW * 4) return 3
|
||||||
|
return MAX_BLOCK_SIZE + 1 // generic "too big"
|
||||||
}
|
}
|
||||||
|
|
||||||
export function sectionModels(section) {
|
// de-paginate, essentially
|
||||||
// remove pages, return models (blocks) in order
|
export function modelsFromSection(section, getters) {
|
||||||
|
// remove pages, return models (blocks) in order.
|
||||||
|
// combine blocks with the same model number.
|
||||||
let models = []
|
let models = []
|
||||||
if (section && section.pages) {
|
if (section && section.pages) {
|
||||||
for (let page of section.pages) {
|
for (let page of section.pages) {
|
||||||
models.push(...page)
|
for (let model of page) {
|
||||||
|
model = copyModel(model)
|
||||||
|
if (model.ids && model.ids.length > 0) {
|
||||||
|
// add extra info from a material
|
||||||
|
let material = getters.material(model.ids[0])
|
||||||
|
if (material) {
|
||||||
|
model = extendModelFromMaterial(material, model)
|
||||||
|
} else {
|
||||||
|
console.log('no material found for id', model.ids[0])
|
||||||
|
}
|
||||||
|
models.push(model)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return joinModels(models)
|
||||||
return models
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function sectionTitle(material) {
|
export function sectionTitle(material) {
|
||||||
|
|||||||
Reference in New Issue
Block a user