183 lines
4.8 KiB
JavaScript
183 lines
4.8 KiB
JavaScript
import { derived } from "svelte/store"
|
|
import { AppStatus } from "constants"
|
|
import { API } from "api"
|
|
import { auth } from "./auth"
|
|
import BudiStore from "../BudiStore" // move this
|
|
|
|
// properties that should always come from the dev app, not the deployed
|
|
const DEV_PROPS = ["updatedBy", "updatedAt"]
|
|
|
|
export const INITIAL_APPS_STATE = {
|
|
apps: [],
|
|
sortBy: "name",
|
|
}
|
|
|
|
export class AppsStore extends BudiStore {
|
|
constructor() {
|
|
super({ ...INITIAL_APPS_STATE })
|
|
|
|
this.extractAppId = this.extractAppId.bind(this)
|
|
this.getProdAppID = this.getProdAppID.bind(this)
|
|
this.updateSort = this.updateSort.bind(this)
|
|
this.load = this.load.bind(this)
|
|
this.save = this.save.bind(this)
|
|
}
|
|
|
|
extractAppId(id) {
|
|
const split = id?.split("_") || []
|
|
return split.length ? split[split.length - 1] : null
|
|
}
|
|
|
|
getProdAppID(appId) {
|
|
if (!appId) {
|
|
return appId
|
|
}
|
|
let rest,
|
|
separator = ""
|
|
if (appId.startsWith("app_dev")) {
|
|
// split to take off the app_dev element, then join it together incase any other app_ exist
|
|
const split = appId.split("app_dev")
|
|
split.shift()
|
|
rest = split.join("app_dev")
|
|
} else if (!appId.startsWith("app")) {
|
|
rest = appId
|
|
separator = "_"
|
|
} else {
|
|
return appId
|
|
}
|
|
return `app${separator}${rest}`
|
|
}
|
|
|
|
updateSort(sortBy) {
|
|
this.update(state => ({
|
|
...state,
|
|
sortBy,
|
|
}))
|
|
}
|
|
|
|
async load() {
|
|
const json = await API.getApps()
|
|
if (Array.isArray(json)) {
|
|
// Merge apps into one sensible list
|
|
let appMap = {}
|
|
let devApps = json.filter(app => app.status === AppStatus.DEV)
|
|
let deployedApps = json.filter(app => app.status === AppStatus.DEPLOYED)
|
|
|
|
// First append all dev app version
|
|
devApps.forEach(app => {
|
|
const id = this.extractAppId(app.appId)
|
|
appMap[id] = {
|
|
...app,
|
|
devId: app.appId,
|
|
devRev: app._rev,
|
|
}
|
|
})
|
|
|
|
// Then merge with all prod app versions
|
|
deployedApps.forEach(app => {
|
|
const id = this.extractAppId(app.appId)
|
|
|
|
// Skip any deployed apps which don't have a dev counterpart
|
|
if (!appMap[id]) {
|
|
return
|
|
}
|
|
|
|
let devProps = {}
|
|
if (appMap[id]) {
|
|
const entries = Object.entries(appMap[id]).filter(
|
|
([key]) => DEV_PROPS.indexOf(key) !== -1
|
|
)
|
|
entries.forEach(entry => {
|
|
devProps[entry[0]] = entry[1]
|
|
})
|
|
}
|
|
appMap[id] = {
|
|
...appMap[id],
|
|
...app,
|
|
...devProps,
|
|
prodId: app.appId,
|
|
prodRev: app._rev,
|
|
}
|
|
})
|
|
|
|
// Transform into an array and clean up
|
|
const apps = Object.values(appMap)
|
|
apps.forEach(app => {
|
|
app.appId = this.extractAppId(app.devId)
|
|
delete app._id
|
|
delete app._rev
|
|
})
|
|
this.update(state => ({
|
|
...state,
|
|
apps,
|
|
}))
|
|
} else {
|
|
this.update(state => ({
|
|
...state,
|
|
apps: [],
|
|
}))
|
|
}
|
|
}
|
|
|
|
async save(appId, value) {
|
|
await API.saveAppMetadata({
|
|
appId,
|
|
metadata: value,
|
|
})
|
|
this.update(state => {
|
|
const updatedAppIndex = state.apps.findIndex(
|
|
app => app.instance._id === appId
|
|
)
|
|
if (updatedAppIndex !== -1) {
|
|
let updatedApp = state.apps[updatedAppIndex]
|
|
updatedApp = { ...updatedApp, ...value }
|
|
state.apps.splice(updatedAppIndex, 1, updatedApp)
|
|
}
|
|
return state
|
|
})
|
|
}
|
|
}
|
|
|
|
export const appsStore = new AppsStore()
|
|
|
|
// Centralise any logic that enriches the apps list
|
|
export const enrichedApps = derived([appsStore, auth], ([$store, $auth]) => {
|
|
const enrichedApps = $store.apps
|
|
? $store.apps.map(app => ({
|
|
...app,
|
|
deployed: app.status === AppStatus.DEPLOYED,
|
|
lockedYou: app.lockedBy && app.lockedBy.email === $auth.user?.email,
|
|
lockedOther: app.lockedBy && app.lockedBy.email !== $auth.user?.email,
|
|
favourite: $auth.user?.appFavourites?.includes(app.appId),
|
|
}))
|
|
: []
|
|
|
|
if ($store.sortBy === "status") {
|
|
return enrichedApps.sort((a, b) => {
|
|
if (a.favourite === b.favourite) {
|
|
if (a.status === b.status) {
|
|
return a.name?.toLowerCase() < b.name?.toLowerCase() ? -1 : 1
|
|
}
|
|
return a.status === AppStatus.DEPLOYED ? -1 : 1
|
|
}
|
|
return a.favourite ? -1 : 1
|
|
})
|
|
} else if ($store.sortBy === "updated") {
|
|
return enrichedApps?.sort((a, b) => {
|
|
if (a.favourite === b.favourite) {
|
|
const aUpdated = a.updatedAt || "9999"
|
|
const bUpdated = b.updatedAt || "9999"
|
|
return aUpdated < bUpdated ? 1 : -1
|
|
}
|
|
return a.favourite ? -1 : 1
|
|
})
|
|
} else {
|
|
return enrichedApps?.sort((a, b) => {
|
|
if (a.favourite === b.favourite) {
|
|
return a.name?.toLowerCase() < b.name?.toLowerCase() ? -1 : 1
|
|
}
|
|
return a.favourite ? -1 : 1
|
|
})
|
|
}
|
|
})
|