big pagination update - split models into pages
This commit is contained in:
@ -141,9 +141,7 @@
|
||||
<script>
|
||||
import Sortable from 'sortablejs'
|
||||
import { mapState, mapGetters, mapActions } from 'vuex'
|
||||
import arrayMove from 'array-move'
|
||||
//import RawDisplayer from './RawDisplayer'
|
||||
import { paginateModels } from '@/pagination'
|
||||
import DragListHeading from './DragListHeading'
|
||||
import AddProductDialog from './AddProductDialog'
|
||||
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) {
|
||||
this.selectSection(id)
|
||||
this.showSectionInfoDialog = true
|
||||
@ -287,8 +272,8 @@ export default {
|
||||
'selectModel',
|
||||
'selectMaterial',
|
||||
'reorderSection',
|
||||
'setSectionPages',
|
||||
'setModelMaterials',
|
||||
'reorderModel',
|
||||
'reorderMaterial',
|
||||
'moveModelToSection',
|
||||
'moveMaterialToSection',
|
||||
]),
|
||||
@ -318,7 +303,9 @@ export default {
|
||||
},
|
||||
onEnd: function(evt) {
|
||||
if (evt.from === evt.to) {
|
||||
me.reorderModel(evt.oldIndex, evt.newIndex)
|
||||
me.reorderModel({ section: me.selectedSection,
|
||||
fromIndex: evt.oldIndex,
|
||||
toIndex: evt.newIndex })
|
||||
} else {
|
||||
// dropped on a section.
|
||||
let models = me.selectedModels
|
||||
@ -349,7 +336,10 @@ export default {
|
||||
},
|
||||
onEnd: function(evt) {
|
||||
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 {
|
||||
// dropped on a section.
|
||||
let mats = me.selectedMaterials
|
||||
@ -360,6 +350,7 @@ export default {
|
||||
|
||||
if (me.selectedSection.id !== newSection.id) {
|
||||
me.moveMaterialToSection({ material: mat,
|
||||
oldSection: me.selectedSection,
|
||||
oldModel: me.selectedModel,
|
||||
newSection: newSection })
|
||||
} else {
|
||||
|
||||
@ -85,7 +85,6 @@ export default {
|
||||
|
||||
doDelete() {
|
||||
this.deleteModelMaterial({ section: this.selectedSection,
|
||||
model: this.selectedModel,
|
||||
material: this.selectedMaterial })
|
||||
this.show = false
|
||||
},
|
||||
|
||||
@ -2,7 +2,7 @@ import Vue from 'vue'
|
||||
import Vuex from 'vuex'
|
||||
import arrayMove from 'array-move'
|
||||
import axios from 'axios'
|
||||
import { paginateModels, sectionTitle, extendModelFromMaterial } from '@/pagination'
|
||||
import { modelsFromSection, paginateModels, sectionTitle, extendModelFromMaterial } from '@/pagination'
|
||||
|
||||
Vue.use(Vuex)
|
||||
|
||||
@ -47,35 +47,25 @@ export const store = new Vuex.Store({
|
||||
},
|
||||
|
||||
selectedModel: (state, getters) => {
|
||||
if (state.catalog && state.selectedModelID) {
|
||||
if (state.selectedModelID) {
|
||||
let section = getters.selectedSection
|
||||
let models = getters.sectionModels(section)
|
||||
return models.find(s => s.model === state.selectedModelID)
|
||||
return getters.sectionModel(section, state.selectedModelID)
|
||||
} else {
|
||||
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) => {
|
||||
// remove pages, return models (blocks) in order
|
||||
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
|
||||
return modelsFromSection(section, getters)
|
||||
},
|
||||
|
||||
modelMaterials: (state, getters) => (model) => {
|
||||
@ -150,6 +140,7 @@ export const store = new Vuex.Store({
|
||||
section.name = name
|
||||
},
|
||||
|
||||
// move a section in the section list
|
||||
reorderSection(state, { from, to }) {
|
||||
if (from === to) return
|
||||
state.catalog.sections = arrayMove(state.catalog.sections, from, to)
|
||||
@ -157,7 +148,13 @@ export const store = new Vuex.Store({
|
||||
|
||||
setSectionPages(state, { section, pages }) {
|
||||
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
|
||||
},
|
||||
|
||||
setModelMaterials(state, { model, materials }) {
|
||||
if (model) {
|
||||
model.ids = materials.map(m => (typeof m === 'object') ? m.id : m)
|
||||
}
|
||||
},
|
||||
|
||||
addMaterialsToLibrary(state, materials) {
|
||||
console.log('adding', materials.length, 'materials')
|
||||
let map = {}
|
||||
@ -247,10 +238,29 @@ export const store = new Vuex.Store({
|
||||
commit('setSectionName', payload)
|
||||
},
|
||||
|
||||
// move a section in the section list
|
||||
reorderSection({ commit }, 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) {
|
||||
commit('setSectionPages', payload)
|
||||
},
|
||||
@ -266,10 +276,6 @@ export const store = new Vuex.Store({
|
||||
commit('setSectionPages', { section: section, pages: pages })
|
||||
},
|
||||
|
||||
setModelMaterials({ commit }, payload) {
|
||||
commit('setModelMaterials', payload)
|
||||
},
|
||||
|
||||
moveModelToSection({ commit, getters }, { model, oldSection, newSection }) {
|
||||
// remove model from old section
|
||||
let oldModels = getters.sectionModels(oldSection)
|
||||
@ -295,15 +301,18 @@ export const store = new Vuex.Store({
|
||||
commit('setSectionPages', { section: newSection, pages: newPages })
|
||||
},
|
||||
|
||||
moveMaterialToSection({ commit, getters }, { material, oldModel, newSection }) {
|
||||
moveMaterialToSection({ commit, getters }, { material, oldSection, oldModel, newSection }) {
|
||||
// ensure material, not just id
|
||||
if (typeof material === 'string' || typeof material === 'number') {
|
||||
material = getters.material(material)
|
||||
}
|
||||
|
||||
// remove material from old model
|
||||
let mats = oldModel.ids.filter(id => id !== material.id)
|
||||
commit('setModelMaterials', { model: oldModel, materials: mats })
|
||||
let oldModels = getters.sectionModels(oldSection)
|
||||
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
|
||||
let newModels = getters.sectionModels(newSection)
|
||||
@ -338,12 +347,10 @@ export const store = new Vuex.Store({
|
||||
let models = getters.sectionModels(section)
|
||||
let existingModel = models.find(m => m.model === material.model)
|
||||
if (existingModel) {
|
||||
// console.log('section', section.id, 'found existing model', existingModel)
|
||||
// NOTE 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? handle later.
|
||||
let existingMaterial = existingModel.ids.find(m => m === material.id)
|
||||
// console.log('model', existingModel.model, 'existing material', existingMaterial)
|
||||
foundSection = section
|
||||
foundModels = models
|
||||
if (!existingMaterial) {
|
||||
@ -386,13 +393,10 @@ export const store = new Vuex.Store({
|
||||
commit('setSectionPages', { section: foundSection, pages: pages })
|
||||
},
|
||||
|
||||
deleteModelMaterial({ commit, getters }, { section, model, material }) {
|
||||
let mats = model.ids.filter(id => id !== material.id)
|
||||
|
||||
commit('setModelMaterials', { model: model, materials: mats })
|
||||
|
||||
// repaginate section
|
||||
deleteModelMaterial({ commit, getters }, { section, material }) {
|
||||
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)
|
||||
commit('setSectionPages', { section: section, pages: pages })
|
||||
},
|
||||
|
||||
@ -1,15 +1,104 @@
|
||||
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) {
|
||||
models = joinModels(models)
|
||||
|
||||
for (let model of models) {
|
||||
// ensure sizes
|
||||
model.size = modelSize(model)
|
||||
model.size = modelBlockSize(model)
|
||||
}
|
||||
|
||||
models = splitModels(models)
|
||||
|
||||
for (let model of models) {
|
||||
model.size = modelBlockSize(model)
|
||||
}
|
||||
|
||||
models = copyModels(models)
|
||||
|
||||
let pages = []
|
||||
let currentSize = 0
|
||||
let currentPage = []
|
||||
for (let model of models) {
|
||||
if (model.size > 0) { // skip empty models
|
||||
if (model.size < 1) {
|
||||
// skip empty models
|
||||
continue
|
||||
}
|
||||
currentSize += model.size
|
||||
if (currentSize > 3) {
|
||||
pages.push(currentPage)
|
||||
@ -19,7 +108,6 @@ export function paginateModels(models) {
|
||||
currentPage.push(model)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (currentPage.length > 0) {
|
||||
pages.push(currentPage)
|
||||
}
|
||||
@ -27,23 +115,37 @@ export function paginateModels(models) {
|
||||
return pages
|
||||
}
|
||||
|
||||
export function modelSize(model) {
|
||||
export function modelBlockSize(model) {
|
||||
if (!model || !model.ids) return 0
|
||||
if (model.ids.length <= 4) return 1
|
||||
if (model.ids.length <= 8) return 2
|
||||
return 3
|
||||
if (model.ids.length <= MATERIALS_PER_ROW) return 1
|
||||
if (model.ids.length <= MATERIALS_PER_ROW * 2) return 2
|
||||
if (model.ids.length <= MATERIALS_PER_ROW * 4) return 3
|
||||
return MAX_BLOCK_SIZE + 1 // generic "too big"
|
||||
}
|
||||
|
||||
export function sectionModels(section) {
|
||||
// remove pages, return models (blocks) in order
|
||||
// de-paginate, essentially
|
||||
export function modelsFromSection(section, getters) {
|
||||
// remove pages, return models (blocks) in order.
|
||||
// combine blocks with the same model number.
|
||||
let models = []
|
||||
if (section && 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 models
|
||||
}
|
||||
}
|
||||
return joinModels(models)
|
||||
}
|
||||
|
||||
export function sectionTitle(material) {
|
||||
|
||||
Reference in New Issue
Block a user