react-garden
Version:
React + TypeScript + ThreeJS app using Material UI on NextJS, Apollo Client, GraphQL + WordPress REST APIs, for ThreeD web development.. a part of the threed.ai code family.
1,642 lines (1,415 loc) • 106 kB
JavaScript
// ** Apollo Client 3 -- Cache Store Imports
import { ApolloClient, InMemoryCache, useApolloClient, useQuery, gql } from '@apollo/client'
import create from '~/api/graphql/createStore'
// ** GraphQL Queries + Mutations (here, locally-specific data needs)
import GetProjects from '~/api/graphql/scripts/getProjects.gql'
import GetPlans from '~/api/graphql/scripts/getPlans.gql'
import GetUIs from '~/api/graphql/scripts/getUIs.gql'
import GetThreeDs from '~/api/graphql/scripts/getThreeDs.gql'
import GetFiles from '~/api/graphql/scripts/getFiles.gql'
import GetScenes from '~/api/graphql/scripts/getScenes.gql'
import GetAllotments from '~/api/graphql/scripts/getAllotments.gql'
import GetBeds from '~/api/graphql/scripts/getBeds.gql'
import GetPlants from '~/api/graphql/scripts/getPlants.gql'
import GetPlantingPlans from '~/api/graphql/scripts/getPlantingPlans.gql'
import GetProducts from '~/api/graphql/scripts/getProducts.gql'
// ** React Imports (should not need in this script -- framework agnostic)
// import React, { FunctionComponent, useState, useEffect, useRef, useMemo } from 'react'
// ** UUID Imports
import { v4 as newUUID } from 'uuid'
// [MM] COLORFUL CONSOLE MESSAGES (ccm)
import { ccm0, ccm1, ccm2, ccm3, ccm4, ccm5, ccm6 } from '~/@core/utils/console-colors'
// ==========================================================
// IMPORTS COMPLETE
console.debug('%c====================================', ccm5)
console.debug('%cThreeDGarden<FC,R3F>: {stores}', ccm4)
// console.debug('%cApolloClient', ccm3, ApolloClient)
// console.debug('%cuseApolloClient', ccm3, useApolloClient)
// console.debug('%cuseQuery', ccm3, useQuery)
// ==============================================================
// FOR TESTING PURPOSES
// Apollo Client 3 (ac3)
export const ac3Store = create({
counter: 0,
modal: {
open: true,
},
})
// console.debug("ac3Store", ac3Store)
// console.debug("ac3Store.get", ac3Store.get("counter"))
// console.debug("ac3Store.get", ac3Store.get("modal"))
// console.debug("ac3Store.get", ac3Store.get("modal").open)
// console.debug("ac3Store.get", ac3Store.get("increase"))
// // console.debug("ac3Store.useStore", ac3Store.useStore("increase"))
export const ac3Actions = {
increase(n) {
// return (state) => state + n
return (state) => {
console.debug('STATE increase', state)
return state + n
}
},
toggle() {
// return (state) => ({ open: !state.open })
return (state) => {
console.debug('STATE toggle', state)
return { open: !state.open }
}
},
toggle2: (doOpen = true) => {
// return (state) => ({ ...state, open })
return (state) => {
console.debug('STATE toggle2', state)
const open = !state.open
return { ...state, open }
}
},
}
const clientLocal = new ApolloClient({
uri: 'http://localhost:3000/',
cache: new InMemoryCache({
typePolicies: ac3Store.getTypePolicies(),
}),
})
export const TestAC3Store = () => {
const { loading, error, data } = useQuery(
gql`
query {
counter
modal {
open
}
}
`,
// `client` here is your instantiated `ApolloClient` instance
{ client: clientLocal }
)
if (loading) {
return false
}
if (error) {
return <div>{JSON.stringify(error)}</div>
}
// destructure data
const {
counter,
modal: { open },
} = data
return (
<div>
<div>TEST counter: {counter}</div>
<button onClick={() => ac3Store.update('counter', ac3Actions.increase(1))}>+1</button>
<button onClick={() => ac3Store.update('counter', ac3Actions.increase(-1))}>-1</button>
<div>TEST is open? {open.toString()}</div>
<button onClick={() => ac3Store.update('modal', ac3Actions.toggle())}>Toggle</button>
<button onClick={() => ac3Store.update('modal', ac3Actions.toggle2())}>Toggle2</button>
</div>
)
}
// ==============================================================
// ThreeD
// aka 'Master File with Settings'
const threed = (name = 'THREED 0', layerName = 'LAYER 0') => ({
_id: newUUID(),
_ts: new Date().toISOString(),
name: name,
layers: [],
layer: {
name: layerName,
data: {},
},
// wp custom fields
data: {}, // threedStore.get("threedDB")
//
//
//
})
export const threedStore = create({
_id: newUUID(),
_ts: new Date().toISOString(),
threedCount: 0,
threeds: [],
threed: {},
// track current + history
// threedCurrent: ^this,
threedHistory: [], // from local storage
// track payload from db
threedCountDB: 0, // example counter
threedsDB: [], // from db (mysql wordpress via graphql)
threedDB: {}, // pre-this threed, ready to be mapped to 'this' threed
}) // threedStore
export const threedActions = {
increaseCount: (n = 1) => {
return (state) => state + n
},
removeAll: function () {
localStorage.removeItem('threed_threedHistory')
threedStore.update('threeds', [])
threedStore.update('threed', {})
threedStore.update('threedCount', 0)
threedStore.update('threedsDB', [])
threedStore.update('threedDB', {})
threedStore.update('threedCountDB', 0)
console.debug('%cremoveAll [threeds]', ccm2, true)
},
addNew: function () {
console.debug('%caddNew [threeds] (before)', ccm1, threedStore.get('threeds'))
// create a new one
if (Object.keys(threedStore.get('threed')).length === 0) {
threedStore.update('threed', threed())
}
// save + update old one
else {
// threedHistory (save existing before mutating, if not empty)
threedStore.update('threeds', [threedStore.get('threed'), ...threedStore.get('threeds')])
console.debug('%caddNew [threeds] (during)', ccm1, threedStore.get('threeds'))
// threedCount
// threedStore.update("threedCount", threedStore.get("threedCount") + 1) // manual
threedStore.update('threedCount', threedStore.get('threeds').length) // automatic
// console.debug('%caddNew {threedCount}', ccm3, threedStore.get("threedCount"))
// console.debug('%caddNew [threeds]', ccm3, threedStore.get("threeds").length)
// threedCurrent (overwrite -- mutate)
threedStore.update('threed', {
_id: newUUID(),
_ts: new Date().toISOString(),
name: 'THREED 1',
layers: [],
layer: {
name: 'LAYER 0',
data: {},
},
})
}
console.debug('%caddNew {threed}', ccm1, threedStore.get('threed'))
// save the new one and the old ones
// threedHistory (save recently mutated)
threedStore.update('threeds', [threedStore.get('threed'), ...threedStore.get('threeds')])
console.debug('%caddNew [threeds] (after)', ccm1, threedStore.get('threeds'))
// threedCount
// threedStore.update("threedCount", threedStore.get("threedCount") + 1) // manual
threedStore.update('threedCount', threedStore.get('threeds').length) // automatic
// console.debug('%caddNew {threedCount}', ccm3, threedStore.get("threedCount"))
// console.debug('%caddNew [threeds]', ccm3, threedStore.get("threeds").length)
// saveToDisk
this.saveToDisk()
// loadFromDisk
this.loadFromDisk()
// console.debug('%caddNew', ccm1, get().threed)
},
save: function () {
// saveToDisk
this.saveToDisk()
// saveToDB (coming soon !!!)
// this.saveToDB()
},
// save data to browser local storage
saveToDisk: function () {
try {
localStorage.setItem(
'threed_threedHistory',
JSON.stringify({
subject: 'threeds',
payload: threedStore.get('threeds'),
})
)
console.debug('%csaveToDisk [threeds]', ccm1, threedStore.get('threeds'))
return true
} catch (err) {
console.debug('%csaveToDisk [threeds] err', ccm2, err)
return false
}
},
// get data from browser local storage
loadFromDisk: function () {
try {
const query = JSON.parse(localStorage.getItem('threed_threedHistory'))
if (query) {
console.debug('%cloadFromDisk [threeds] QUERY?', ccm3, query)
const { payload } = query
console.debug('%cloadFromDisk [threeds] QUERY.PAYLOAD?', ccm3, payload)
if (payload.length) {
console.debug('%cloadFromDisk [threeds]', ccm3, true) // payload
threedStore.update('threeds', [...payload])
console.debug('%cloadFromDisk [threeds] (after)', ccm3, threedStore.get('threeds'))
threedStore.update('threed', threedStore.get('threeds')[0])
console.debug('%cloadFromDisk {threed} (after)', ccm3, threedStore.get('threed'))
return true
} else {
console.debug('%cloadFromDisk [threeds] EMPTY QUERY.PAYLOAD?', ccm3, query)
}
} else {
console.debug('%cloadFromDisk [threeds] NOTHING TO LOAD', ccm3, query)
}
return false
} catch (err) {
console.debug('%cloadFromDisk [threeds] err', ccm2, err)
return false
}
},
// save data to db via graphql mutation
saveToDB: async function (client) {
try {
// const _this = this
// console.debug('%csaveToDB this', ccm0, this)
console.debug('%csaveToDB [threeds]', ccm2, false)
return false
} catch (err) {
console.debug('%csaveToDB [threeds]: err', ccm3, err)
return false
}
},
// get data from db via graphql query
loadFromDB: async function (client) {
try {
// const _this = this
// console.debug('%cloadFromDB this', ccm0, this)
const THREEDS = GetThreeDs // .gql
const parameters = {
first: 10,
last: null,
after: null,
before: null,
}
// const {
// data,
// loading,
// error,
// fetchMore,
// refetch,
// networkStatus
// } = useQuery(THREEDS, { parameters }, { client })
// console.debug('DATA RETURNED', data, loading, error)
const query = await client.query({
query: THREEDS,
variables: { parameters },
})
// console.debug('QUERY RETURNED', query)
const { data, loading, error } = query
console.debug('DATA RETURNED', data, loading, error)
if (loading) {
return false
}
if (error) {
console.debug('%cloadFromDB [threeds]: DATA RETURNED with error', error)
return false // <div>{JSON.stringify(error)}</div>
}
if (data) {
console.debug('%cloadFromDB [threeds]: DATA RETURNED', ccm0, data, loading, error)
if (data.threeds?.edges?.length) {
// const payload = data.threeds.edges
const payload = data.threeds.edges.map(
(
{ node } // threedId, id, uri, slug, title
) =>
// <div key={node.threedId}>
// wp threedId: {node.threedId}<br />
// gql id: {node.id}<br />
// uri: {node.uri}<br />
// slug: {node.slug}<br />
// title: {node.title}<br />
// </div>
node
)
// set state threedsDB from db
threedStore.update('threedsDB', [...payload]) // edges[node]
console.debug('%cloadFromDB [threedsDB] (after)', ccm3, threedStore.get('threedsDB'))
threedStore.update('threedDB', threedStore.get('threedsDB')[0]) // node
console.debug('%cloadFromDB {threedDB}', ccm1, threedStore.get('threedDB'))
// set state threeds from threedDB
threedStore.update('threeds', [...threedStore.get('threedsDB'), ...threedStore.get('threeds')])
console.debug('%cloadFromDB [threeds] (after)', ccm3, threedStore.get('threeds'))
// threedCurrent (overwrite -- mutate)
threedStore.update('threed', {
_id: newUUID(),
_ts: new Date().toISOString(),
name: 'THREED: ' + threedStore.get('threedDB').title,
layers: [],
layer: {
name: 'LAYER 0',
data: {},
},
// wp custom fields
data: threedStore.get('threedDB').data,
})
console.debug('%cloadFromDB {threed} (after)', ccm1, threedStore.get('threed'))
threedStore.update('threedCountDB', threedStore.get('threeds').length)
console.debug('%cloadFromDB threedCountDB', ccm1, threedStore.get('threedCountDB'))
// save to disk
this.saveToDisk()
return true
} else {
console.debug('%cloadFromDB [threeds]: NO data.threeds.edges', ccm3, data)
return false
}
}
console.debug('%cloadFromDB [threeds]: OTHER ERROR', ccm3, data)
return false
} catch (err) {
console.debug('%cloadFromDB [threeds]: DATA RETURNED with err', ccm3, err)
return false
}
},
} // threedActions
// ==============================================================
// ==============================================================
// ==============================================================
// Project
const project = (name = 'PROJECT 0', layerName = 'LAYER 0') => ({
_id: newUUID(),
_ts: new Date().toISOString(),
name: name,
layers: [],
layer: {
name: layerName,
data: {},
},
// wp custom fields
data: {},
}) // project
// ** Project Store
export const projectStore = create({
_id: newUUID(),
_ts: new Date().toISOString(),
projectCount: 0,
projects: [],
project: project(), // {}
// track current + history
// projectCurrent: ^this,
projectHistory: [], // from local storage
// track payload from db
projectCountDB: 0, // example counter
projectsDB: [], // from db (mysql wordpress via graphql)
projectDB: {}, // pre-this project, ready to be mapped to 'this' project
}) // projectStore
// ** Project Actions
export const projectActions = {
increaseCount: (n = 1) => {
return (state) => state + n
},
removeAll: function () {
localStorage.removeItem('threed_projectHistory')
projectStore.update('projects', [])
projectStore.update('project', {})
projectStore.update('projectCount', 0)
projectStore.update('projectsDB', [])
projectStore.update('projectDB', {})
projectStore.update('projectCountDB', 0)
console.debug('%cremoveAll [projects]', ccm2, true)
},
// add a new current 'this' project
addNew: function () {
console.debug('%caddNew [projects] (before)', ccm1, projectStore.get('projects'))
// create a new one
if (Object.keys(projectStore.get('project')).length === 0) {
projectStore.update('project', project())
}
// save + update old one
else {
// projectHistory (save existing before mutating, if not empty)
projectStore.update('projects', [projectStore.get('project'), ...projectStore.get('projects')])
console.debug('%caddNew [projects] (during)', ccm1, projectStore.get('projects'))
// projectCount
// projectStore.update("projectCount", projectStore.get("projectCount") + 1) // manual
projectStore.update('projectCount', projectStore.get('projects').length) // automatic
// console.debug('%caddNew {projectCount}', ccm3, projectStore.get("projectCount"))
// console.debug('%caddNew [projects]', ccm3, projectStore.get("projects").length)
// projectCurrent (overwrite -- mutate)
projectStore.update('project', {
_id: newUUID(),
_ts: new Date().toISOString(),
name: 'PROJECT 1',
layers: [],
layer: {
name: 'LAYER 0',
data: {},
},
})
}
console.debug('%caddNew {project}', ccm1, projectStore.get('project'))
// save the new one and the old ones
// projectHistory (save recently mutated)
projectStore.update('projects', [projectStore.get('project'), ...projectStore.get('projects')])
console.debug('%caddNew [projects] (after)', ccm1, projectStore.get('projects'))
// projectCount
// projectStore.update("projectCount", projectStore.get("projectCount") + 1) // manual
projectStore.update('projectCount', projectStore.get('projects').length) // automatic
// console.debug('%caddNew {projectCount}', ccm3, projectStore.get("projectCount"))
// console.debug('%caddNew [projects]', ccm3, projectStore.get("projects").length)
// saveToDisk
this.saveToDisk()
// loadFromDisk
this.loadFromDisk()
// console.debug('%caddNew', ccm1, get().project)
},
save: function () {
// saveToDisk
this.saveToDisk()
// saveToDB (coming soon !!!)
// this.saveToDB()
},
// save data to browser local storage
saveToDisk: function () {
try {
localStorage.setItem(
'threed_projectHistory',
JSON.stringify({
subject: 'projects',
payload: projectStore.get('projects'),
})
)
console.debug('%csaveToDisk [projects]', ccm1, projectStore.get('projects'))
return true
} catch (err) {
console.debug('%csaveToDisk [projects] err', ccm2, err)
return false
}
},
// get data from browser local storage
loadFromDisk: function () {
try {
const query = JSON.parse(localStorage.getItem('threed_projectHistory'))
if (query) {
console.debug('%cloadFromDisk [projects] QUERY?', ccm3, query)
const { payload } = query
console.debug('%cloadFromDisk [projects] QUERY.PAYLOAD?', ccm3, payload)
if (payload.length) {
console.debug('%cloadFromDisk [projects]', ccm3, true) // payload
projectStore.update('projects', [...payload])
console.debug('%cloadFromDisk [projects] (after)', ccm3, projectStore.get('projects'))
projectStore.update('project', projectStore.get('projects')[0])
console.debug('%cloadFromDisk {project} (after)', ccm3, projectStore.get('project'))
return true
} else {
console.debug('%cloadFromDisk [projects] EMPTY QUERY.PAYLOAD?', ccm3, query)
}
} else {
console.debug('%cloadFromDisk [projects] NOTHING TO LOAD', ccm3, query)
}
return false
} catch (err) {
console.debug('%cloadFromDisk [projects] err', ccm2, err)
return false
}
},
// save data to db via graphql mutation
saveToDB: async function (client) {
try {
// const _this = this
// console.debug('%csaveToDB this', ccm0, this)
console.debug('%csaveToDB [projects]', ccm2, false)
return false
} catch (err) {
console.debug('%csaveToDB [projects]: err', ccm3, err)
return false
}
},
// get data from db via graphql query
loadFromDB: async function (client) {
try {
// const _this = this
// console.debug('%cloadFromDB this', ccm0, this)
const PROJECTS = GetProjects // .gql
const parameters = {
first: 10,
last: null,
after: null,
before: null,
}
// const {
// data,
// loading,
// error,
// fetchMore,
// refetch,
// networkStatus
// } = useQuery(PROJECTS, { parameters }, { client })
// console.debug('DATA RETURNED', data, loading, error)
const query = await client.query({
query: PROJECTS,
variables: { parameters },
})
// console.debug('QUERY RETURNED', query)
const { data, loading, error } = query
// console.debug('DATA RETURNED', data, loading, error)
if (loading) {
return false
}
if (error) {
console.debug('%cloadFromDB [projects]: DATA RETURNED with error', error)
return false // <div>{JSON.stringify(error)}</div>
}
if (data) {
console.debug('%cloadFromDB [projects]: DATA RETURNED', ccm0, data, loading, error)
if (data.projects?.edges?.length) {
// const payload = data.projects.edges
const payload = data.projects.edges.map(
(
{ node } // projectId, id, uri, slug, title
) =>
// <div key={node.projectId}>
// wp projectId: {node.projectId}<br />
// gql id: {node.id}<br />
// uri: {node.uri}<br />
// slug: {node.slug}<br />
// title: {node.title}<br />
// </div>
node
)
// set state from db
projectStore.update('projects', [...payload]) // nodes
console.debug('%cloadFromDB [projects] (after)', ccm3, projectStore.get('projects'))
projectStore.update('projectDB', projectStore.get('projects')[0]) // node
console.debug('%cloadFromDB {projectDB}', ccm1, projectStore.get('projectDB'))
this.saveToDisk()
// projectCurrent (overwrite -- mutate)
projectStore.update('project', {
_id: newUUID(),
_ts: new Date().toISOString(),
name: 'PROJECT: ' + projectStore.get('projectDB').title,
layers: [],
layer: {
name: 'LAYER 0',
data: {},
},
// wp custom fields
data: projectStore.get('projectDB').data,
})
console.debug('%cloadFromDB {project} (after)', ccm1, projectStore.get('project'))
projectStore.update('projectCountDB', projectStore.get('projects').length)
console.debug('%cloadFromDB projectCountDB', ccm1, projectStore.get('projectCountDB'))
// save to disk
this.saveToDisk()
return true
} else {
console.debug('%cloadFromDB [projects]: NO data.projects.edges', ccm3, data)
return false
}
}
console.debug('%cloadFromDB [projects]: OTHER ERROR', ccm3, data)
return false
} catch (err) {
console.debug('%cloadFromDB [projects]: err', ccm3, err)
return false
}
},
// load 'this' project into the React Three Fiber view
load: function (id = null) {
try {
project = projectStore.get('project')
console.debug('%cload {project}: this', ccm1, project, this)
if (project) {
return true
}
return false
} catch (err) {
console.debug('%cload {project}: err', ccm3, err)
return false
}
},
} // projectActions
// ==============================================================
// ==============================================================
// ==============================================================
// Plan
const plan = (name = 'PLAN 0', layerName = 'LAYER 0') => ({
_id: newUUID(),
_ts: new Date().toISOString(),
name: name,
layers: [],
layer: {
name: layerName,
data: {},
},
// wp custom fields
data: {
// {},
planId: 0,
levels: [{ id: 0, height: 0 }],
// levels[0]: { id: 0, height: 0 },
floors: [],
roofs: [],
walls: [],
dimensions: [],
texts: [],
furniture: [],
verticalGuides: [],
horizontalGuides: [],
furnitureAddedKey: null,
furnitureDirtyKey: null,
furnitureDeletedKey: null,
wallAddedKey: null,
wallDirtyKey: null,
wallDeletedKey: null,
roofAddedKey: null,
roofDirtyKey: null,
roofDeletedKey: null,
floorAddedKey: null,
floorDirtyKey: null,
floorDeletedKey: null,
dimensionAddedKey: null,
dimensionEditedKey: null,
dimensionDeletedKey: null,
textAddedKey: null,
textEditedKey: null,
textDeletedKey: null,
wallDiffuse: null,
wallOpacity: null,
wallSpecular: null,
roofDiffuse: null,
roofOpacity: null,
roofSpecular: null,
floorDiffuse: null,
floorOpacity: null,
floorSpecular: null,
groundDiffuse: null,
groundOpacity: null,
groundSpecular: null,
depthWrite: null,
sortObjects: null,
azimuth: null,
inclination: null,
},
}) // plan
// ** Plan Store
export const planStore = create({
_id: newUUID(),
_ts: new Date().toISOString(),
planCount: 0,
plans: [],
plan: plan(), // {}
// track current + history
// planCurrent: ^this,
planHistory: [], // from local storage
// track payload from db
planCountDB: 0, // example counter
plansDB: [], // from db (mysql wordpress via graphql)
planDB: {}, // pre-this plan, ready to be mapped to 'this' plan
}) // planStore
// ** Plan Actions
export const planActions = {
increaseCount: (n = 1) => {
return (state) => state + n
},
removeAll: function () {
localStorage.removeItem('threed_planHistory')
planStore.update('plans', [])
planStore.update('plan', {})
planStore.update('planCount', 0)
planStore.update('plansDB', [])
planStore.update('planDB', {})
planStore.update('planCountDB', 0)
console.debug('%cremoveAll [plans]', ccm2, true)
},
// add a new current 'this' plan
addNew: function () {
console.debug('%caddNew [plans] (before)', ccm1, planStore.get('plans'))
// create a new one
if (Object.keys(planStore.get('plan')).length === 0) {
planStore.update('plan', plan())
}
// save + update old one
else {
// planHistory (save existing before mutating, if not empty)
planStore.update('plans', [planStore.get('plan'), ...planStore.get('plans')])
console.debug('%caddNew [plans] (during)', ccm1, planStore.get('plans'))
// planCount
// planStore.update("planCount", planStore.get("planCount") + 1) // manual
planStore.update('planCount', planStore.get('plans').length) // automatic
// console.debug('%caddNew {planCount}', ccm3, planStore.get("planCount"))
// console.debug('%caddNew [plans]', ccm3, planStore.get("plans").length)
// planCurrent (overwrite -- mutate)
planStore.update('plan', {
_id: newUUID(),
_ts: new Date().toISOString(),
name: 'PLAN 1',
layers: [],
layer: {
name: 'LAYER 0',
data: {},
},
})
}
console.debug('%caddNew {plan}', ccm1, planStore.get('plan'))
// save the new one and the old ones
// planHistory (save recently mutated)
planStore.update('plans', [planStore.get('plan'), ...planStore.get('plans')])
console.debug('%caddNew [plans] (after)', ccm1, planStore.get('plans'))
// planCount
// planStore.update("planCount", planStore.get("planCount") + 1) // manual
planStore.update('planCount', planStore.get('plans').length) // automatic
// console.debug('%caddNew {planCount}', ccm3, planStore.get("planCount"))
// console.debug('%caddNew [plans]', ccm3, planStore.get("plans").length)
// saveToDisk
this.saveToDisk()
// loadFromDisk
this.loadFromDisk()
// console.debug('%caddNew', ccm1, get().plan)
},
save: function () {
// saveToDisk
this.saveToDisk()
// saveToDB (coming soon !!!)
// this.saveToDB()
},
// save data to browser local storage
saveToDisk: function () {
try {
localStorage.setItem(
'threed_planHistory',
JSON.stringify({
subject: 'plans',
payload: planStore.get('plans'),
})
)
console.debug('%csaveToDisk [plans]', ccm1, planStore.get('plans'))
return true
} catch (err) {
console.debug('%csaveToDisk [plans] err', ccm2, err)
return false
}
},
// get data from browser local storage
loadFromDisk: function () {
try {
const query = JSON.parse(localStorage.getItem('threed_planHistory'))
if (query) {
console.debug('%cloadFromDisk [plans] QUERY?', ccm3, query)
const { payload } = query
console.debug('%cloadFromDisk [plans] QUERY.PAYLOAD?', ccm3, payload)
if (payload.length) {
console.debug('%cloadFromDisk [plans]', ccm3, true) // payload
planStore.update('plans', [...payload])
console.debug('%cloadFromDisk [plans] (after)', ccm3, planStore.get('plans'))
planStore.update('plan', planStore.get('plans')[0])
console.debug('%cloadFromDisk {plan} (after)', ccm3, planStore.get('plan'))
return true
} else {
console.debug('%cloadFromDisk [plans] EMPTY QUERY.PAYLOAD?', ccm3, query)
}
} else {
console.debug('%cloadFromDisk [plans] NOTHING TO LOAD', ccm3, query)
}
return false
} catch (err) {
console.debug('%cloadFromDisk [plans] err', ccm2, err)
return false
}
},
// save data to db via graphql mutation
saveToDB: async function (client) {
try {
// const _this = this
// console.debug('%csaveToDB this', ccm0, this)
console.debug('%csaveToDB [plans]', ccm2, false)
return false
} catch (err) {
console.debug('%csaveToDB [plans]: err', ccm3, err)
return false
}
},
// get data from db via graphql query
loadFromDB: async function (client) {
try {
// const _this = this
// console.debug('%cloadFromDB this', ccm0, this)
const PLANS = GetPlans // .gql
const parameters = {
first: 10,
last: null,
after: null,
before: null,
}
// const {
// data,
// loading,
// error,
// fetchMore,
// refetch,
// networkStatus
// } = useQuery(PLANS, { parameters }, { client })
// console.debug('DATA RETURNED', data, loading, error)
const query = await client.query({
query: PLANS,
variables: { parameters },
})
// console.debug('QUERY RETURNED', query)
const { data, loading, error } = query
// console.debug('DATA RETURNED', data, loading, error)
if (loading) {
return false
}
if (error) {
console.debug('%cloadFromDB [plans]: DATA RETURNED with error', error)
return false // <div>{JSON.stringify(error)}</div>
}
if (data) {
console.debug('%cloadFromDB [plans]: DATA RETURNED', ccm0, data, loading, error)
if (data.plans?.edges?.length) {
// const payload = data.plans.edges
const payload = data.plans.edges.map(
(
{ node } // planId, id, uri, slug, title
) =>
// <div key={node.planId}>
// wp planId: {node.planId}<br />
// gql id: {node.id}<br />
// uri: {node.uri}<br />
// slug: {node.slug}<br />
// title: {node.title}<br />
// </div>
node
)
// set state from db
planStore.update('plans', [...payload]) // nodes
console.debug('%cloadFromDB [plans] (after)', ccm3, planStore.get('plans'))
planStore.update('planDB', planStore.get('plans')[0]) // node
console.debug('%cloadFromDB {planDB}', ccm1, planStore.get('planDB'))
this.saveToDisk()
// planCurrent (overwrite -- mutate)
planStore.update('plan', {
_id: newUUID(),
_ts: new Date().toISOString(),
name: 'PLAN: ' + planStore.get('planDB').title,
layers: [],
layer: {
name: 'LAYER 0',
data: {},
},
// wp custom fields
data: planStore.get('planDB').data,
})
console.debug('%cloadFromDB {plan} (after)', ccm1, planStore.get('plan'))
planStore.update('planCountDB', planStore.get('plans').length)
console.debug('%cloadFromDB planCountDB', ccm1, planStore.get('planCountDB'))
// save to disk
this.saveToDisk()
return true
} else {
console.debug('%cloadFromDB [plans]: NO data.plans.edges', ccm3, data)
return false
}
}
console.debug('%cloadFromDB [plans]: OTHER ERROR', ccm3, data)
return false
} catch (err) {
console.debug('%cloadFromDB [plans]: err', ccm3, err)
return false
}
},
// load 'this' plan into the React Three Fiber view
load: function (id = null) {
try {
plan = planStore.get('plan')
console.debug('%cload {plan}: this', ccm1, plan, this)
if (plan) {
return true
}
return false
} catch (err) {
console.debug('%cload {plan}: err', ccm3, err)
return false
}
},
} // planActions
// ==============================================================
// ==============================================================
// ==============================================================
// UI
const ui = (name = 'UI 0', layerName = 'LAYER 0') => ({
_id: newUUID(),
_ts: new Date().toISOString(),
name: name,
layers: [],
layer: {
name: 'LAYER 0',
data: {},
},
data: {
uiId: 0,
mouseMode: 0,
toolMode: 'pointer',
selectedItem: null,
defaultCursor: 'default',
// deselectAll
UILayout: 'default',
Texts: {},
Dimensions: {},
Floors: {},
Floors3d: {},
Roofs: {},
Walls: {},
Furniture: {},
textPath: '',
textIdCounter: 0,
startedDrawingText: !1,
editingTextId: -1,
dimensionPath: '',
dimensionIdCounter: 0,
dimensionHelperPath: '',
startedDrawingDimension: !1,
floorPath: '',
floorIdCounter: 0,
floorHelperPath: '',
startedDrawingFloor: !1,
wallPath: '',
wallIdCounter: 0,
wallsRectangles: {},
wallsRectangles3d: {},
wallHelperPath: '',
wallHelperRectangle: '',
startedDrawingWalls: !1,
roofPath: '',
roofIdCounter: 0,
roofHelperPath: '',
roofsRectangles: {},
roofsRectangles3d: {},
roofHelperRectangle: '',
startedDrawingRoofs: !1,
maskObjects: {},
maskObjectsApplied: {},
maskObjectsAppliedRoof: {},
clickableObjects: {},
clickableObjectsCounter: -1,
backgroundRaster: '',
backgroundRasterRatioX: 1,
backgroundRasterRatioY: 1,
levelButtons: '',
otherLayerWallsRasters: [],
otherLayerFurnitureRasters: [],
verticalGuides: {},
horizontalGuides: {},
selectedGuideId: '',
guideCounter: 0,
draggingNewGuide: !1,
snapTolerance: 1,
furnitureItems: {},
furnitureToLoadCount: 0,
loadedFurnitureCount: 0,
// THREE >>
canvas3d: null,
camera: null,
renderer: null,
container: null,
scene: {},
mesh: null,
ground: null,
controls: null,
tween: null,
raycaster: null,
mouse: null,
// lights
ambientLight: null,
dirLight: null,
hemiLight: null,
pointLight: null,
// materials
groundMaterial: {
color: { getHexString: () => '#0xFFFFFF' },
opacity: 1,
specular: { getHexString: () => '#0xCCCCCC' },
},
floorMaterial: {
color: { getHexString: () => '#0xFFFFFF' },
opacity: 1,
specular: { getHexString: () => '#0xCCCCCC' },
},
roofMaterial: {
color: { getHexString: () => '#0xFFFFFF' },
opacity: 1,
specular: { getHexString: () => '#0xCCCCCC' },
},
wallMaterial: {
color: { getHexString: () => '#0xFFFFFF' },
opacity: 1,
specular: { getHexString: () => '#0xCCCCCC' },
},
// << THREE
inclination: 0,
azimuth: 0,
// GROUPS
// Paper.Group !! 2D
// these should be arrays [] ??? YES, CHANGED
furnitureGroup: [],
// furnitureGroup[0]: new paper.Group(),
wallsGroup: [],
// wallsGroup[0]: new paper.Group(),
roofsGroup: [],
// roofsGroup[0]: new paper.Group(),
floorsGroup: [],
// floorsGroup[0]: new paper.Group(),
dimensionsGroup: [],
// dimensionsGroup[0]: new paper.Group(),
textsGroup: [],
// textsGroup[0]: new paper.Group(),
// should these 3 be arrays [] ???
guidesGroup: {}, // new paper.Group()
toolsGroup: {}, // new paper.Group()
gridGroup: {}, // new paper.Group()
}, // data
}) // ui
// ** UI Store
export const uiStore = create({
_id: newUUID(),
_ts: new Date().toISOString(),
uiCount: 0,
uis: [],
ui: ui(), // {},
// track current + history
// uiCurrent: ^this,
uiHistory: [], // from local storage
// track payload from db
uiCountDB: 0, // example counter
uisDB: [], // from db (mysql wordpress via graphql)
uiDB: {}, // pre-this ui, ready to be mapped to 'this' ui
}) // uiStore
// ** UI Actions
export const uiActions = {
increaseCount: (n = 1) => {
return (state) => state + n
},
removeAll: function () {
localStorage.removeItem('threed_uiHistory')
uiStore.update('uis', [])
uiStore.update('ui', {})
uiStore.update('uiCount', 0)
uiStore.update('uisDB', [])
uiStore.update('uiDB', {})
uiStore.update('uiCountDB', 0)
console.debug('%cremoveAll [uis]', ccm2, true)
},
// add a new current 'this' ui
addNew: function () {
console.debug('%caddNew [uis] (before)', ccm1, uiStore.get('uis'))
// create a new one
if (Object.keys(uiStore.get('ui')).length === 0) {
uiStore.update('ui', ui())
}
// save + update old one
else {
// uiHistory (save existing before mutating, if not empty)
uiStore.update('uis', [uiStore.get('ui'), ...uiStore.get('uis')])
console.debug('%caddNew [uis] (during)', ccm1, uiStore.get('uis'))
// uiCount
// uiStore.update("uiCount", uiStore.get("uiCount") + 1) // manual
uiStore.update('uiCount', uiStore.get('uis').length) // automatic
// console.debug('%caddNew {uiCount}', ccm3, uiStore.get("uiCount"))
// console.debug('%caddNew [uis]', ccm3, uiStore.get("uis").length)
// uiCurrent (overwrite -- mutate)
uiStore.update('ui', {
_id: newUUID(),
_ts: new Date().toISOString(),
name: 'UI 1',
layers: [],
layer: {
name: 'LAYER 0',
data: {},
},
})
}
console.debug('%caddNew {ui}', ccm1, uiStore.get('ui'))
// save the new one and the old ones
// uiHistory (save recently mutated)
uiStore.update('uis', [uiStore.get('ui'), ...uiStore.get('uis')])
console.debug('%caddNew [uis] (after)', ccm1, uiStore.get('uis'))
// uiCount
// uiStore.update("uiCount", uiStore.get("uiCount") + 1) // manual
uiStore.update('uiCount', uiStore.get('uis').length) // automatic
// console.debug('%caddNew {uiCount}', ccm3, uiStore.get("uiCount"))
// console.debug('%caddNew [uis]', ccm3, uiStore.get("uis").length)
// saveToDisk
this.saveToDisk()
// loadFromDisk
this.loadFromDisk()
// console.debug('%caddNew', ccm1, get().ui)
},
save: function () {
// saveToDisk
this.saveToDisk()
// saveToDB (coming soon !!!)
// this.saveToDB()
},
// save data to browser local storage
saveToDisk: function () {
try {
localStorage.setItem(
'threed_uiHistory',
JSON.stringify({
subject: 'uis',
payload: uiStore.get('uis'),
})
)
console.debug('%csaveToDisk [uis]', ccm1, uiStore.get('uis'))
return true
} catch (err) {
console.debug('%csaveToDisk [uis] err', ccm2, err)
return false
}
},
// get data from browser local storage
loadFromDisk: function () {
try {
const query = JSON.parse(localStorage.getItem('threed_uiHistory'))
if (query) {
console.debug('%cloadFromDisk [uis] QUERY?', ccm3, query)
const { payload } = query
console.debug('%cloadFromDisk [uis] QUERY.PAYLOAD?', ccm3, payload)
if (payload.length) {
console.debug('%cloadFromDisk [uis]', ccm3, true) // payload
uiStore.update('uis', [...payload])
console.debug('%cloadFromDisk [uis] (after)', ccm3, uiStore.get('uis'))
uiStore.update('ui', uiStore.get('uis')[0])
console.debug('%cloadFromDisk {ui} (after)', ccm3, uiStore.get('ui'))
return true
} else {
console.debug('%cloadFromDisk [uis] EMPTY QUERY.PAYLOAD?', ccm3, query)
}
} else {
console.debug('%cloadFromDisk [uis] NOTHING TO LOAD', ccm3, query)
}
return false
} catch (err) {
console.debug('%cloadFromDisk [uis] err', ccm2, err)
return false
}
},
// save data to db via graphql mutation
saveToDB: async function (client) {
try {
// const _this = this
// console.debug('%csaveToDB this', ccm0, this)
console.debug('%csaveToDB [uis]', ccm2, false)
return false
} catch (err) {
console.debug('%csaveToDB [uis]: err', ccm3, err)
return false
}
},
// get data from db via graphql query
loadFromDB: async function (client) {
try {
// const _this = this
// console.debug('%cloadFromDB this', ccm0, this)
const UIS = GetUIs // .gql
const parameters = {
first: 10,
last: null,
after: null,
before: null,
}
// const {
// data,
// loading,
// error,
// fetchMore,
// refetch,
// networkStatus
// } = useQuery(UIS, { parameters }, { client })
// console.debug('DATA RETURNED', data, loading, error)
const query = await client.query({
query: UIS,
variables: { parameters },
})
// console.debug('QUERY RETURNED', query)
const { data, loading, error } = query
// console.debug('DATA RETURNED', data, loading, error)
if (loading) {
return false
}
if (error) {
console.debug('%cloadFromDB [uis]: DATA RETURNED with error', error)
return false // <div>{JSON.stringify(error)}</div>
}
if (data) {
console.debug('%cloadFromDB [uis]: DATA RETURNED', ccm0, data, loading, error)
if (data.uis?.edges?.length) {
// const payload = data.uis.edges
const payload = data.uis.edges.map(
(
{ node } // uiId, id, uri, slug, title
) =>
// <div key={node.uiId}>
// wp uiId: {node.uiId}<br />
// gql id: {node.id}<br />
// uri: {node.uri}<br />
// slug: {node.slug}<br />
// title: {node.title}<br />
// </div>
node
)
// set state from db
uiStore.update('uis', [...payload]) // nodes
console.debug('%cloadFromDB [uis] (after)', ccm3, uiStore.get('uis'))
uiStore.update('uiDB', uiStore.get('uis')[0]) // node
console.debug('%cloadFromDB {uiDB}', ccm1, uiStore.get('uiDB'))
this.saveToDisk()
// uiCurrent (overwrite -- mutate)
uiStore.update('ui', {
_id: newUUID(),
_ts: new Date().toISOString(),
name: 'UI: ' + uiStore.get('uiDB').title,
layers: [],
layer: {
name: 'LAYER 0',
data: {},
},
// wp custom fields
data: uiStore.get('uiDB').data,
})
console.debug('%cloadFromDB {ui} (after)', ccm1, uiStore.get('ui'))
uiStore.update('uiCountDB', uiStore.get('uis').length)
console.debug('%cloadFromDB uiCountDB', ccm1, uiStore.get('uiCountDB'))
// save to disk
this.saveToDisk()
return true
} else {
console.debug('%cloadFromDB [uis]: NO data.uis.edges', ccm3, data)
return false
}
}
console.debug('%cloadFromDB [uis]: OTHER ERROR', ccm3, data)
return false
} catch (err) {
console.debug('%cloadFromDB [uis]: err', ccm3, err)
return false
}
},
// load 'this' ui into the React Three Fiber view
load: function (id = null) {
try {
ui = uiStore.get('ui')
console.debug('%cload {ui}: this', ccm1, ui, this)
if (ui) {
return true
}
return false
} catch (err) {
console.debug('%cload {ui}: err', ccm3, err)
return false
}
},
} // uiActions
// ==============================================================
// ==============================================================
// ==============================================================
// File
// ** ThreeDs use Files as Assets one-to-many relationships
const file = (name = 'FILE 0', layerName = 'LAYER 0') => ({
_id: newUUID(),
_ts: new Date().toISOString(),
name: name,
layers: [],
layer: {
name: layerName,
data: {},
},
})
// ** File Store
export const fileStore = create({
_id: newUUID(),
_ts: new Date().toISOString(),
fileCount: 0,
files: [],
file: file(), // {},
// track current + history
// fileCurrent: ^this,
fileHistory: [], // from local storage
// track payload from db
fileCountDB: 0, // example counter
filesDB: [], // from db (mysql wordpress via graphql)
fileDB: {}, // pre-this file, ready to be mapped to 'this' file
}) // fileStore
// ** File Actions
export const fileActions = {
increaseCount: (n = 1) => {
return (state) => state + n
},
removeAll: function () {
localStorage.removeItem('threed_fileHistory')
fileStore.update('files', [])
fileStore.update('file', {})
fileStore.update('fileCount', 0)
fileStore.update('filesDB', [])
fileStore.update('fileDB', {})
fileStore.update('fileCountDB', 0)
console.debug('%cremoveAll [files]', ccm2, true)
},
// add a new current 'this' file
addNew: function () {
console.debug('%caddNew [files] (before)', ccm1, fileStore.get('files'))
// create a new one
if (Object.keys(fileStore.get('file')).length === 0) {
fileStore.update('file', file())
}
// save + update old one
else {
// fileHistory (save existing before mutating, if not empty)
fileStore.update('files', [fileStore.get('file'), ...fileStore.get('files')])
console.debug('%caddNew [files] (during)', ccm1, fileStore.get('files'))
// fileCount
// fileStore.update("fileCount", fileStore.get("fileCount") + 1) // manual
fileStore.update('fileCount', fileStore.get('files').length) // automatic
// console.debug('%caddNew {fileCount}', ccm3, fileStore.get("fileCount"))
// console.debug('%caddNew [files]', ccm3, fileStore.get("files").length)
// fileCurrent (overwrite -- mutate)
fileStore.update('file', {
_id: newUUID(),
_ts: new Date().toISOString(),
name: 'FILE 1',
layers: [],
layer: {
name: 'LAYER 0',
data: {},
},
})
}
console.debug('%caddNew {file}', ccm1, fileStore.get('file'))
// save the new one and the old ones
// fileHistory (save recently mutated)
fileStore.update('files', [fileStore.get('file'), ...fileStore.get('files')])
console.debug('%caddNew [files] (after)', ccm1, fileStore.get('files'))
// fileCount
// fileStore.update("fileCount", fileStore.get("fileCount") + 1) // manual
fileStore.update('fileCount', fileStore.get('files').length) // automatic
// console.debug('%caddNew {fileCount}', ccm3, fileStore.get("fileCount"))
// console.debug('%caddNew [files]', ccm3, fileStore.get("files").length)
// saveToDisk
this.saveToDisk()
// loadFromDisk
this.loadFromDisk()
// console.debug('%caddNew', ccm1, get().file)
},
save: function () {
// saveToDisk
this.saveToDisk()
// saveToDB (coming soon !!!)
// this.saveToDB()
},
// save data to browser local storage
saveToDisk: function () {
try {
localStorage.setItem(
'threed_fileHistory',
JSON.stringify({
subject: 'files',
payload: fileStore.get('files'),
})
)
console.debug('%csaveToDisk [files]', ccm1, fileStore.get('files'))
return true
} catch (err) {
console.debug('%csaveToDisk [files] err', ccm2, err)
return false
}
},
// get data from browser local storage
loadFromDisk: function () {
try {
const query = JSON.parse(localStorage.getItem('threed_fileHistory'))
if (query) {
console.debug('%cloadFromDisk [files] QUERY?', ccm3, query)
const { payload } = query
console.debug('%cloadFromDisk [files] QUERY.PAYLOAD?', ccm3, payload)
if (payload.length) {
console.debug('%cloadFromDisk [files]', ccm3, true) // payload
fileStore.update('files', [...payload])
console.debug('%cloadFro