Files
supabase/studio/stores/projectContentStore.ts
2022-04-28 18:16:19 +02:00

200 lines
4.8 KiB
TypeScript

import { makeObservable, action, observable, computed, toJS, makeAutoObservable } from 'mobx'
import { get, patch, post, delete_ } from 'lib/common/fetch'
import { keyBy, isEmpty } from 'lodash'
import { UserContent } from 'types'
import { API_URL } from 'lib/constants'
/**
* Singleton
* Usage:
* import { useProjectContentStore } from 'stores/userContent/projectContentStore'
* const contentStore = useProjectContentStore(projectRef)
* contentStore.load() // inside usEffect()
* @deprecated use content store on RootStore instead.
*/
let store: any = null
let projectRef: any = null
export function useProjectContentStore(ref: any) {
if (store === null || ref !== projectRef) {
// set the current ref
projectRef = ref
const baseUrl = `${API_URL}/projects/${ref}/content`
store = new ProjectContent(baseUrl)
}
return store
}
/**
* Local type declarations
*/
interface UserContentMap {
[key: string]: UserContent
}
/**
* MobX Store
* @deprecated
*/
export default class ProjectContent {
STATES = {
INITIAL: 'initial',
LOADING: 'loading',
ERROR: 'error',
LOADED: 'loaded',
}
rootStore = null
url = ''
state = this.STATES.INITIAL
data: UserContentMap = {}
error = null
/**
* @param connectionString And encrypted database connection string to pass to the API
*/
constructor(dataUrl: any) {
this.url = dataUrl
makeObservable(this, {
state: observable,
data: observable,
list: observable,
hasError: computed,
isLoading: computed,
})
}
async fetchData() {
const headers = {
'Content-Type': 'application/json',
}
const res = await get(this.url, { headers })
if (res.error) {
throw res.error
}
this.data = res.data.length > 0 ? keyBy(res.data, 'id') : res.data
return res
}
async load() {
let { LOADING, ERROR, LOADED } = this.STATES
try {
this.error = null
this.state = LOADING
await this.fetchData()
this.state = LOADED
return this.data
} catch (e: any) {
console.error('e.message', e.message)
this.error = e
this.state = ERROR
}
}
get hasError() {
return this.state === this.STATES.ERROR
}
get isLoading() {
return this.state === this.STATES.INITIAL || this.state === this.STATES.LOADING
}
list(filter: any) {
let arr = Object.values(this.data)
if (!!filter) {
return arr.filter(filter).sort((a, b) => a.name.localeCompare(b.name))
} else {
return arr.sort((a, b) => a.name.localeCompare(b.name))
}
}
reports(filter: any) {
let arr = Object.values(this.data)
if (!!filter) {
return arr
.filter((x) => x.type == 'report')
.filter(filter)
.sort((a, b) => a.name.localeCompare(b.name))
} else {
return arr.filter((x) => x.type == 'report').sort((a, b) => a.name.localeCompare(b.name))
}
}
sqlSnippets(filter: any) {
let arr = Object.values(this.data)
if (!!filter) {
const arr_filtered = arr
.filter((x) => x.type == 'sql')
.filter(filter)
.sort((a, b) => a.name.localeCompare(b.name))
return arr_filtered
} else {
const arr_filtered = arr
.filter((x) => x.type == 'sql')
.sort((a, b) => a.name.localeCompare(b.name))
return arr_filtered
}
}
byId(id: any) {
return this.data[id]
}
async create(payload: any) {
try {
const headers = {
'Content-Type': 'application/json',
}
const created = await post(this.url, payload, { headers })
if (created.error) throw created.error
this.data[created['id']] = created
return { data: created, error: null }
} catch (error) {
return { data: null, error }
}
}
async update(id: any, updates: any, type: any) {
try {
const headers = {
'Content-Type': 'application/json',
}
let payload = {
...updates,
type,
id,
}
const url = `${this.url}?id=${id}`
const updated = await patch(url, payload, { headers })
if (updated.error) throw updated.error
this.data[id] = updated
return { data: updated, error: null }
} catch (error) {
return { data: null, error }
}
}
async updateSql(id: any, updates: any) {
return this.update(id, updates, 'sql')
}
async updateReport(id: any, updates: any) {
return this.update(id, updates, 'report')
}
async del(id: any) {
try {
const headers = {
'Content-Type': 'application/json',
}
const url = `${this.url}?id=${id}`
const deleted = await delete_(url, {}, { headers })
if (deleted.error) throw deleted.error
delete this.data[id]
return { data: true, error: null }
} catch (error) {
return { data: false, error }
}
}
}