From e98bae116f40f76bbc41b7cc31804f4b2060c6b7 Mon Sep 17 00:00:00 2001 From: Kate Noland Date: Wed, 16 Aug 2017 17:26:12 -0600 Subject: [PATCH 1/2] new import/export functions --- src/api.js | 8 +-- src/components/Modals/MapModal.vue | 10 ++-- src/components/Toolbar.vue | 2 +- src/store/index.js | 4 +- src/store/utilities/importFloorplan.js | 83 ++++++++++++++++++++++++++ src/store/utilities/importLibrary.js | 4 +- src/store/utilities/importModel.js | 83 -------------------------- 7 files changed, 97 insertions(+), 97 deletions(-) create mode 100644 src/store/utilities/importFloorplan.js delete mode 100644 src/store/utilities/importModel.js diff --git a/src/api.js b/src/api.js index 87c4b184..3333cb0f 100644 --- a/src/api.js +++ b/src/api.js @@ -1,9 +1,9 @@ window.api = { config: null, initAlreadyRun: false, - doImport: (data) => { + openFloorplan: (data) => { try { - window.application.$store.dispatch('importModel', { + window.application.$store.dispatch('importFloorplan', { clientWidth: document.getElementById('svg-grid').clientWidth, clientHeight: document.getElementById('svg-grid').clientHeight, data: JSON.parse(data), @@ -21,7 +21,7 @@ window.api = { } return true; }, - doExport: () => window.application.$store.getters['exportData'], + exportFloorplan: () => window.application.$store.getters['exportData'], setConfig: (config) => { if (this.initAlreadyRun) { throw new Error('The application has already been started, configuration cannot be changed.'); @@ -49,7 +49,7 @@ window.api = { window.application.$store.dispatch('project/setUnits', { units: window.api.config.units }); // if the map modal has been disabled, mark the map as initialized so that time travel can be initialized - // TODO: we may want to intitialize timetravel in the importModel action instead + // TODO: we may want to intitialize timetravel in the importFloorplan action instead window.application.$store.dispatch('project/setMapInitialized', { initialized: true }); this.initAlreadyRun = true; diff --git a/src/components/Modals/MapModal.vue b/src/components/Modals/MapModal.vue index 2885f0e8..4d52ebe5 100644 --- a/src/components/Modals/MapModal.vue +++ b/src/components/Modals/MapModal.vue @@ -20,7 +20,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - + @@ -50,17 +50,17 @@ export default { }, }, methods: { - importModelAsFile(event) { + importFloorplanAsFile(event) { const file = event.target.files[0]; const reader = new FileReader(); reader.addEventListener('load', () => { - this.importModel(reader.result); + this.importFloorplan(reader.result); }, false); if (file) { reader.readAsText(file); } }, - importModel(data) { - this.$store.dispatch('importModel', { + importFloorplan(data) { + this.$store.dispatch('importFloorplan', { clientWidth: document.getElementById('svg-grid').clientWidth, clientHeight: document.getElementById('svg-grid').clientHeight, data: JSON.parse(data), diff --git a/src/components/Toolbar.vue b/src/components/Toolbar.vue index b0ee7e4f..93c05b45 100644 --- a/src/components/Toolbar.vue +++ b/src/components/Toolbar.vue @@ -89,7 +89,7 @@ export default { if (type === 'library') { this.$store.dispatch('importLibrary', { data }); } else if (type === 'floorplan') { - this.$store.dispatch('importModel', { + this.$store.dispatch('importFloorplan', { clientWidth: document.getElementById('svg-grid').clientWidth, clientHeight: document.getElementById('svg-grid').clientHeight, data, diff --git a/src/store/index.js b/src/store/index.js index c79d5128..f7ea4dc4 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -8,7 +8,7 @@ import geometry from './modules/geometry/index'; import models from './modules/models/index'; import exportData from './utilities/export'; -import importModel from './utilities/importModel'; +import importFloorplan from './utilities/importFloorplan'; import importLibrary from './utilities/importLibrary'; import mutations from './mutations'; @@ -26,7 +26,7 @@ const store = new Vuex.Store({ exportData, }, actions: { - importModel, + importFloorplan, importLibrary, }, mutations, diff --git a/src/store/utilities/importFloorplan.js b/src/store/utilities/importFloorplan.js new file mode 100644 index 00000000..2ec0634a --- /dev/null +++ b/src/store/utilities/importFloorplan.js @@ -0,0 +1,83 @@ +import idFactory from './generateId'; + +export default function importModel(context, payload) { + // intializr a versionNumber if the app is running in embedded mode + if (window.api) { window.versionNumber = 0; } + + // GEOMETRY + const geometry = payload.data.stories.map((story) => { + const faces = story.geometry.faces.map((face) => { + const edgeRefs = face.edge_ids.map((id, index) => ({ + edge_id: id, + reverse: !face.edge_order[index], + })); + return { + id: face.id, + edgeRefs, + }; + }); + + const edges = story.geometry.edges.map(e => ({ + id: e.id, + v1: e.vertex_ids[0], + v2: e.vertex_ids[1], + })); + return { + id: story.geometry.id, + faces, + edges, + vertices: story.geometry.vertices, + }; + }); + + // MODELS + const stories = payload.data.stories.map((s) => { + const story = { + geometry_id: s.geometry.id, + ...s, + }; + delete story.geometry; + return story; + }); + + function forEachNestedProp(obj, func, propName = null) { + if (_.isObject(obj)) { + Object.keys(obj).forEach(k => forEachNestedProp(obj[k], func, k)); + } else if (_.isArray(obj)) { + obj.forEach(elem => forEachNestedProp(elem, func)); + } else { + func(propName, obj); + } + } + + // find the highest id in the imported floorplan + let largestId = 0; + forEachNestedProp(payload, (k, v) => { + if (k && k === 'id' && (+v > largestId)) { + largestId = v; + } + }); + + // set the idFactory to the next id + largestId += 1; + idFactory.setId(largestId); + + context.commit('importState', { + project: payload.data.project, + application: context.state.application, + models: { + stories, + library: { + building_units: payload.data.building_units, + thermal_zones: payload.data.thermal_zones, + space_types: payload.data.space_types, + construction_sets: payload.data.construction_sets, + windows: payload.data.windows, + daylighting_controls: payload.data.daylighting_controls, + }, + }, + geometry, + }); + + document.getElementById('svg-grid').dispatchEvent(new Event('reloadGrid')); +} diff --git a/src/store/utilities/importLibrary.js b/src/store/utilities/importLibrary.js index 16afe3b0..64de4b4f 100644 --- a/src/store/utilities/importLibrary.js +++ b/src/store/utilities/importLibrary.js @@ -1,10 +1,10 @@ -import idFactory from './generateId' +import idFactory from './generateId'; export default function importLibrary(context, payload) { let count = 0; const types = Object.keys(payload.data); types.forEach((type) => { - if (type === 'project') { return; } + if (type === 'project' || !context.state.models.library[type]) { return; } const existingNames = context.state.models.library[type].map((o) => { // /_\d+[\w\s]?$/ // if object name contains duplicate suffix, remove suffix diff --git a/src/store/utilities/importModel.js b/src/store/utilities/importModel.js deleted file mode 100644 index 147f7cd2..00000000 --- a/src/store/utilities/importModel.js +++ /dev/null @@ -1,83 +0,0 @@ -import idFactory from './generateId'; - -export default function importModel(context, payload) { - // intializr a versionNumber if the app is running in embedded mode - if (window.api) { window.versionNumber = 0; } - - // GEOMETRY - const geometry = JSON.parse(JSON.stringify(payload.data.stories.map(s => s.geometry))); - for (var i = 0; i < geometry.length; i++) { - geometry[i].faces = geometry[i].faces.map((f) => { - return { - id: f.id, - edgeRefs: f.edge_ids.map((edge_id, i) => { - return { - edge_id: edge_id, - reverse: !f.edge_order[i] - } - }) - } - }); - - geometry[i].edges = geometry[i].edges.map((e) => { - return { - id: e.id, - v1: e.vertex_ids[0], - v2: e.vertex_ids[1] - }; - }); - - geometry[i].vertices = geometry[i].vertices.map((v) => { - return { - id: v.id, - x: v.x, - y: v.y, - }; - }); - } - - // MODELS - payload.data.stories.forEach((story) => { - story.geometry_id = story.geometry.id; - delete story.geometry; - }); - - // APPLICATION - // update scales with new grid boundaries - payload.data.application.scale.x = context.state.application.scale.x; - payload.data.application.scale.y = context.state.application.scale.y; - - var max_id = 0; - (function loopOnObject(obj) { - for (var key in obj) { - if (obj.hasOwnProperty(key)) { - max_id = (key === 'id' && Number(obj[key]) > max_id) ? Number(obj[key]) : max_id; - if (obj[key] !== null && typeof obj[key] === 'object') { - loopOnObject(obj[key]); - } - } - } - })(payload); - - max_id++; - idFactory.setId(max_id); - context.commit('importState', { - project: payload.data.project, - application: payload.data.application, - models: { - stories: payload.data.stories, - library: { - building_units: payload.data.building_units, - thermal_zones: payload.data.thermal_zones, - space_types: payload.data.space_types, - construction_sets: payload.data.construction_sets, - windows: payload.data.windows, - daylighting_controls: payload.data.daylighting_controls - } - }, - geometry, - }); - - document.getElementById("svg-grid") - .dispatchEvent(new Event('reloadGrid')); -} From 63f91c584821c801ec16cf8df5d08eb8fab69297 Mon Sep 17 00:00:00 2001 From: Kate Noland Date: Fri, 18 Aug 2017 11:04:17 -0600 Subject: [PATCH 2/2] rename --- src/store/utilities/importFloorplan.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/store/utilities/importFloorplan.js b/src/store/utilities/importFloorplan.js index 2ec0634a..d0fdbed7 100644 --- a/src/store/utilities/importFloorplan.js +++ b/src/store/utilities/importFloorplan.js @@ -1,6 +1,6 @@ import idFactory from './generateId'; -export default function importModel(context, payload) { +export default function importFloorplan(context, payload) { // intializr a versionNumber if the app is running in embedded mode if (window.api) { window.versionNumber = 0; }