forked from owid/owid-grapher
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathGdocsStore.tsx
124 lines (109 loc) · 3.51 KB
/
GdocsStore.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import React, { useContext, createContext, useState } from "react"
import { action, observable } from "mobx"
import {
getOwidGdocFromJSON,
OwidGdocJSON,
DbChartTagJoin,
OwidGdoc,
DbPlainTag,
OwidGdocIndexItem,
} from "@ourworldindata/utils"
import { AdminAppContext } from "./AdminAppContext.js"
import { Admin } from "./Admin.js"
import { extractGdocIndexItem } from "@ourworldindata/types"
/**
* This was originally a MobX data domain store (see
* https://mobx.js.org/defining-data-stores.html) used to store the state of the
* Google Docs index page. However, this index page currently only refreshes its
* state on mount so keeping gdocs updated through mutations is unnecessary.
* Today, this store acts as CRUD proxy for requests to API endpoints.
*/
export class GdocsStore {
@observable gdocs: OwidGdocIndexItem[] = []
@observable availableTags: DbChartTagJoin[] = []
admin: Admin
constructor(admin: Admin) {
this.admin = admin
}
@action
async create(id: string) {
await this.admin.requestJSON(`/api/gdocs/${id}`, {}, "PUT")
}
@action
async update(gdoc: OwidGdoc): Promise<OwidGdoc> {
const item: OwidGdoc = await this.admin
.requestJSON<OwidGdocJSON>(`/api/gdocs/${gdoc.id}`, gdoc, "PUT")
.then(getOwidGdocFromJSON)
const indexItem = extractGdocIndexItem(gdoc)
const gdocToUpdateIndex = this.gdocs.findIndex((g) => g.id === gdoc.id)
if (gdocToUpdateIndex >= 0) this.gdocs[gdocToUpdateIndex] = indexItem
return item
}
@action
async publish(gdoc: OwidGdoc): Promise<OwidGdoc> {
const publishedGdoc = await this.update({ ...gdoc, published: true })
return publishedGdoc
}
@action
async unpublish(gdoc: OwidGdoc): Promise<OwidGdoc> {
const unpublishedGdoc = await this.update({
...gdoc,
publishedAt: null,
published: false,
})
return unpublishedGdoc
}
@action
async delete(gdoc: OwidGdoc) {
await this.admin.requestJSON(`/api/gdocs/${gdoc.id}`, {}, "DELETE")
}
@action
async fetchGdocs() {
const gdocs = (await this.admin.getJSON(
"/api/gdocs"
)) as OwidGdocIndexItem[]
this.gdocs = gdocs
}
@action
async fetchTags() {
const json = (await this.admin.getJSON("/api/tags.json")) as any
this.availableTags = json.tags
}
@action
async updateTags(gdoc: OwidGdocIndexItem, tags: DbPlainTag[]) {
const json = await this.admin.requestJSON(
`/api/gdocs/${gdoc.id}/setTags`,
{ tagIds: tags.map((t) => t.id) },
"POST"
)
if (json.success) {
const gdocToUpdate = this.gdocs.find((g) => g.id === gdoc.id)
if (gdocToUpdate) gdocToUpdate.tags = tags
}
}
}
export const GdocsStoreContext = createContext<GdocsStore | undefined>(
undefined
)
export const GdocsStoreProvider = ({
children,
}: {
children: React.ReactNode
}) => {
const { admin } = useContext(AdminAppContext)
const [store] = useState(() => new GdocsStore(admin))
return (
<GdocsStoreContext.Provider value={store}>
{children}
</GdocsStoreContext.Provider>
)
}
export const useGdocsStore = () => {
const context = React.useContext(GdocsStoreContext)
if (context === undefined) {
throw new Error(
"useGdocsStore must be used within a GdocsStoreProvider"
)
}
return context
}