big pagination update - split models into pages

This commit is contained in:
Seth Ladygo
2019-05-31 01:41:56 -07:00
parent 59faa47e61
commit 4ac28cceb4
4 changed files with 181 additions and 85 deletions

View File

@ -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 {

View File

@ -85,7 +85,6 @@ export default {
doDelete() {
this.deleteModelMaterial({ section: this.selectedSection,
model: this.selectedModel,
material: this.selectedMaterial })
this.show = false
},

View File

@ -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 })
},

View File

@ -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) {
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
currentSize += model.size
if (currentSize > 3) {
pages.push(currentPage)
currentPage = [model]
currentSize = model.size
} else {
currentPage.push(model)
}
if (model.size < 1) {
// skip empty models
continue
}
currentSize += model.size
if (currentSize > 3) {
pages.push(currentPage)
currentPage = [model]
currentSize = model.size
} else {
currentPage.push(model)
}
}
if (currentPage.length > 0) {
@ -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) {