Skip to content

Commit 9c867cb

Browse files
authored
Admin Tab for MAPLE News Items #2055 (#2061)
* initial ver * tweaks and changes * fix create date display * re-trigger CI * fix formatting
1 parent ccb623e commit 9c867cb

7 files changed

Lines changed: 140 additions & 3 deletions

File tree

components/db/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
export * from "./bills"
22
export * from "./createTableHook"
33
export * from "./members"
4+
export * from "./news"
45
export * from "./profile"
56
export * from "./testimony"
67
export * from "./useUpcomingBills"

components/db/news.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { collection, getDocs, orderBy, Timestamp } from "firebase/firestore"
2+
import { useAsync } from "react-async-hook"
3+
import { firestore } from "../firebase"
4+
5+
export type NewsType = "article" | "award" | "book"
6+
7+
export type NewsItem = {
8+
id: string
9+
url: string
10+
title: string
11+
author: string
12+
type: NewsType
13+
description?: string
14+
publishDate: string
15+
createdAt: Timestamp
16+
}
17+
18+
export async function listNews(): Promise<NewsItem[]> {
19+
const newsRef = collection(firestore, "news")
20+
const result = await getDocs(newsRef)
21+
return result.docs.map(d => ({ id: d.id, ...d.data() } as NewsItem))
22+
}
23+
24+
export function useNews() {
25+
return useAsync(listNews, [])
26+
}

components/moderation/News.tsx

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import React, { useEffect } from "react"
2+
import { collection, getFirestore, onSnapshot } from "firebase/firestore"
3+
import {
4+
Create,
5+
Datagrid,
6+
DateField,
7+
DateInput,
8+
Edit,
9+
EditButton,
10+
FunctionField,
11+
List,
12+
SelectInput,
13+
SimpleForm,
14+
TextField,
15+
TextInput,
16+
useRefresh
17+
} from "react-admin"
18+
19+
const typeChoices = [
20+
{ id: "article", name: "Article" },
21+
{ id: "award", name: "Award" },
22+
{ id: "book", name: "Book" }
23+
]
24+
25+
export function ListNews() {
26+
const firestore = getFirestore()
27+
const refresh = useRefresh()
28+
29+
useEffect(() => {
30+
const newsRef = collection(firestore, "news")
31+
const unsubscribe = onSnapshot(
32+
newsRef,
33+
() => refresh(),
34+
(e: Error) => console.log(e)
35+
)
36+
37+
return () => unsubscribe()
38+
}, [firestore, refresh])
39+
40+
return (
41+
<List>
42+
<Datagrid rowClick="edit" bulkActionButtons={false}>
43+
<TextField source="id" label="News ID" />
44+
<TextField source="title" label="Title" />
45+
<TextField source="author" label="Author" />
46+
<TextField source="type" label="Type" />
47+
<DateField source="publishDate" label="Publish Date" />
48+
<DateField source="createdAt" showTime />
49+
<EditButton label="Edit" />
50+
</Datagrid>
51+
</List>
52+
)
53+
}
54+
55+
export function EditNews() {
56+
return (
57+
<Edit>
58+
<SimpleForm>
59+
<TextInput source="url" fullWidth />
60+
<SelectInput source="type" choices={typeChoices} />
61+
<TextInput source="author" />
62+
<TextInput source="title" fullWidth />
63+
<TextInput source="description" multiline fullWidth />
64+
<DateInput source="publishDate" />
65+
</SimpleForm>
66+
</Edit>
67+
)
68+
}
69+
70+
export function CreateNews() {
71+
return (
72+
<Create
73+
redirect="list"
74+
transform={(data: Record<string, unknown>) => ({
75+
...data,
76+
createdAt: new Date()
77+
})}
78+
>
79+
<SimpleForm>
80+
<TextInput source="url" fullWidth />
81+
<SelectInput source="type" choices={typeChoices} />
82+
<TextInput source="author" />
83+
<TextInput source="title" fullWidth />
84+
<TextInput source="description" multiline fullWidth />
85+
<DateInput source="publishDate" />
86+
</SimpleForm>
87+
</Create>
88+
)
89+
}
90+
91+
export default { ListNews, EditNews, CreateNews }

components/moderation/dataProviderDbCalls.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,13 @@ export async function createMyOne(
136136
): Promise<CreateResult> {
137137
console.log("creating my one")
138138
const { data, meta } = params
139-
const ref = doc(firestore, resource, data.id)
140-
await setDoc(ref, data)
141-
return { data: data }
139+
const ref = data.id
140+
? doc(firestore, resource, data.id)
141+
: doc(collection(firestore, resource))
142+
const id = ref.id
143+
const newData = { ...data, id }
144+
await setDoc(ref, newData)
145+
return { data: newData }
142146
}
143147

144148
export const getMyListGroup = async (

components/moderation/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export * from "./types"
22
export * from "./ListPublishedTestimony"
3+
export * from "./News"
34
export * from "./ListReports"
45
export * from "./EditReports"
56
export * from "./ListProfiles"

components/moderation/moderation.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { QueryClient, QueryClientProvider } from "react-query"
55
import { EditReports, ListReports } from "./"
66
import { ListProfiles } from "./ListProfiles"
77
import { ScrapeHearingList } from "./ScrapeHearing"
8+
import { ListNews, EditNews, CreateNews } from "./"
89
import {
910
createMyOne,
1011
getMyListGroup,
@@ -54,6 +55,13 @@ const App = () => {
5455
list={ScrapeHearingList}
5556
options={{ label: "Scrape Hearing" }}
5657
/>
58+
<Resource
59+
name="news"
60+
list={ListNews}
61+
edit={EditNews}
62+
create={CreateNews}
63+
options={{ label: "In the News" }}
64+
/>
5765
</Admin>
5866
</QueryClientProvider>
5967
)

firestore.rules

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,12 @@ service cloud.firestore {
6969
// Only admins can do anything with it
7070
allow read, write: if request.auth.token.get("role", "user") == "admin"
7171
}
72+
73+
// Admin-managed news collection used by the admin UI and public news page
74+
match /news/{nid} {
75+
allow read: if true;
76+
allow write: if request.auth.token.get("role", "user") == "admin";
77+
}
7278
match /users/{uid} {
7379
allow read, write: if request.auth.token.get("role", "user") == "admin"
7480
match /draftTestimony/{id} {

0 commit comments

Comments
 (0)