mirror of
https://github.com/maputnik/editor.git
synced 2026-08-26 06:57:26 +00:00
App style is now single source of truth
This commit is contained in:
+70
-81
@@ -1,4 +1,12 @@
|
||||
import { colorizeLayers } from './style.js'
|
||||
import Immutable from 'immutable'
|
||||
|
||||
const storage = {
|
||||
prefix: 'mapolo',
|
||||
keys: {
|
||||
latest: 'mapolo:latest_style'
|
||||
}
|
||||
}
|
||||
|
||||
const emptyStyle = {
|
||||
version: 8,
|
||||
@@ -6,96 +14,77 @@ const emptyStyle = {
|
||||
layers: []
|
||||
}
|
||||
|
||||
// Return style ids and dates of all styles stored in local storage
|
||||
function loadStoredStyles() {
|
||||
const styles = []
|
||||
for (let i = 0; i < localStorage.length; i++) {
|
||||
const key = localStorage.key(i)
|
||||
if(isStyleKey(key)) {
|
||||
styles.push(fromKey(key))
|
||||
}
|
||||
}
|
||||
return styles
|
||||
}
|
||||
|
||||
function isStyleKey(key) {
|
||||
const parts = key.split(":")
|
||||
return parts.length == 2 && parts[0] === storage.prefix
|
||||
}
|
||||
|
||||
// Load style id from key
|
||||
function fromKey(key) {
|
||||
if(!isStyleKey(key)) {
|
||||
throw "Key is not a valid style key"
|
||||
}
|
||||
|
||||
const parts = key.split(":")
|
||||
const styleId = parts[1]
|
||||
return styleId
|
||||
}
|
||||
|
||||
// Calculate key that identifies the style with a version
|
||||
function styleKey(styleId) {
|
||||
return [storage.prefix, styleId].join(":")
|
||||
}
|
||||
|
||||
// Ensure a style has a unique id and a created date
|
||||
function ensureOptionalStyleProps(mapStyle) {
|
||||
if(!('id' in mapStyle)) {
|
||||
mapStyle = mapStyle.set('id', Math.random().toString(36).substr(2, 9))
|
||||
}
|
||||
if(!("created" in mapStyle)) {
|
||||
mapStyle = mapStyle.set('created', new Date())
|
||||
}
|
||||
return mapStyle
|
||||
}
|
||||
|
||||
// Manages many possible styles that are stored in the local storage
|
||||
export class StyleStore {
|
||||
// By default the style store will use the last edited style
|
||||
// as current working style if no explicit style is set
|
||||
constructor(mapStyle) {
|
||||
if(mapStyle) {
|
||||
this.load(mapStyle)
|
||||
} else {
|
||||
try {
|
||||
const latestStyle = this.latestStyle()
|
||||
console.log("Loading latest stlye " + latestStyle.id + " from " + latestStyle.modified)
|
||||
this.load(latestStyle)
|
||||
} catch(err) {
|
||||
console.log(err)
|
||||
this.load(emptyStyle)
|
||||
}
|
||||
}
|
||||
// Tile store will load all items from local storage and
|
||||
// assume they do not change will working on it
|
||||
constructor() {
|
||||
this.mapStyles = loadStoredStyles()
|
||||
}
|
||||
|
||||
// Find the last edited style
|
||||
latestStyle() {
|
||||
const styles = this.loadStoredStyles()
|
||||
|
||||
if(styles.length == 0) {
|
||||
throw "No existing style found"
|
||||
if(this.mapStyles.length == 0) {
|
||||
return Immutable.fromJS(emptyStyle)
|
||||
}
|
||||
|
||||
let maxStyle = styles[0]
|
||||
styles.forEach(s => {
|
||||
if(s.date > maxStyle.date) {
|
||||
maxStyle = s
|
||||
}
|
||||
})
|
||||
|
||||
return JSON.parse(window.localStorage.getItem(this.styleKey(maxStyle.styleId, maxStyle.date)))
|
||||
const styleId = window.localStorage.getItem(storage.keys.latest)
|
||||
const styleItem = window.localStorage.getItem(styleKey(styleId))
|
||||
return Immutable.fromJS(JSON.parse(styleItem))
|
||||
}
|
||||
|
||||
// Return style ids and dates of all styles stored in local storage
|
||||
loadStoredStyles() {
|
||||
const styles = []
|
||||
for (let i = 0; i < localStorage.length; i++) {
|
||||
const key = localStorage.key(i)
|
||||
if(this.isStyleKey(key)) {
|
||||
styles.push(this.fromKey(key))
|
||||
}
|
||||
// Save current style replacing previous version
|
||||
save(mapStyle) {
|
||||
if(!(mapStyle instanceof Immutable.Map)) {
|
||||
mapStyle = Immutable.fromJS(mapStyle)
|
||||
}
|
||||
return styles
|
||||
}
|
||||
|
||||
isStyleKey(key) {
|
||||
const parts = key.split(":")
|
||||
return parts.length >= 3 && parts[0] === "mapolo"
|
||||
}
|
||||
|
||||
// Load style from local storage by key
|
||||
fromKey(key) {
|
||||
if(!this.isStyleKey(key)) {
|
||||
throw "Key is not a valid style key"
|
||||
}
|
||||
|
||||
const parts = key.split(":")
|
||||
const styleId = parts[1]
|
||||
const date = new Date(parts.slice(2).join(":"))
|
||||
return {styleId, date}
|
||||
}
|
||||
|
||||
// Calculate key that identifies the style with a version
|
||||
styleKey(styleId, modifiedDate) {
|
||||
return ["mapolo", styleId, modifiedDate.toJSON()].join(":")
|
||||
}
|
||||
|
||||
// Take snapshot of current style and load it
|
||||
backup(mapStyle) {
|
||||
mapStyle.modified = new Date()
|
||||
const key = this.styleKey(mapStyle.id, mapStyle.modified)
|
||||
window.localStorage.setItem(key, JSON.stringify(mapStyle))
|
||||
}
|
||||
|
||||
// Load a style from external into the store
|
||||
// replacing the previous version
|
||||
load(mapStyle) {
|
||||
if(!("id" in mapStyle)) {
|
||||
mapStyle.id = Math.random().toString(36).substr(2, 9)
|
||||
}
|
||||
if(!("created" in mapStyle)) {
|
||||
mapStyle.created = new Date()
|
||||
}
|
||||
mapStyle.layers = colorizeLayers(mapStyle.layers)
|
||||
|
||||
this.backup(mapStyle)
|
||||
this.currentStyle = mapStyle
|
||||
mapStyle = ensureOptionalStyleProps(mapStyle)
|
||||
const key = styleKey(mapStyle.get('id'))
|
||||
window.localStorage.setItem(key, JSON.stringify(mapStyle.toJS()))
|
||||
window.localStorage.setItem(storage.keys.latest, mapStyle.get('id'))
|
||||
return mapStyle
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user