mirror of
https://github.com/jorgev259/soc_site-astro.git
synced 2025-06-29 07:57:41 +00:00
Implement requests page
This commit is contained in:
parent
75eaf17346
commit
d3439321ba
14 changed files with 10333 additions and 7522 deletions
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
|
|
@ -13,7 +13,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "yarn prisma generate --watch",
|
"command": "yarn prisma generate --sql --watch",
|
||||||
"name": "Prisma",
|
"name": "Prisma",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"type": "node-terminal"
|
"type": "node-terminal"
|
||||||
|
|
|
||||||
|
|
@ -90,5 +90,10 @@
|
||||||
"variousGames": "Various Games",
|
"variousGames": "Various Games",
|
||||||
"searchResultsFor": "Search results for",
|
"searchResultsFor": "Search results for",
|
||||||
"firstResults": "Showing first {take} results",
|
"firstResults": "Showing first {take} results",
|
||||||
"moreResults": "Showing {start}-{end} results"
|
"moreResults": "Showing {start}-{end} results",
|
||||||
|
"requestID": "Request ID",
|
||||||
|
"userID": "userID",
|
||||||
|
"state": "State",
|
||||||
|
"createdAt": "Created At",
|
||||||
|
"updatedAt": "Updated At"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,11 @@
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "astro dev",
|
"dev": "astro dev",
|
||||||
"build": "yarn run prisma:build && astro build",
|
"build": "yarn run prisma:build && astro build",
|
||||||
"prisma:build": "prisma migrate deploy && prisma generate --sql && tsx ./prisma/migrate.ts"
|
"prisma:migrate": "prisma migrate deploy && tsx ./prisma/migrate.ts",
|
||||||
|
"prisma:build": "yarn prisma:migrate && prisma generate --sql && "
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@ag-grid-community/locale": "^33.3.2",
|
||||||
"@astrojs/node": "9.0.0",
|
"@astrojs/node": "9.0.0",
|
||||||
"@astrojs/react": "4.1.3",
|
"@astrojs/react": "4.1.3",
|
||||||
"@astrojs/rss": "4.0.11",
|
"@astrojs/rss": "4.0.11",
|
||||||
|
|
@ -15,6 +17,8 @@
|
||||||
"@tailwindcss/vite": "^4.0.7",
|
"@tailwindcss/vite": "^4.0.7",
|
||||||
"@types/react": "^18.3.12",
|
"@types/react": "^18.3.12",
|
||||||
"@types/react-dom": "^18.3.1",
|
"@types/react-dom": "^18.3.1",
|
||||||
|
"ag-grid-community": "^33.3.1",
|
||||||
|
"ag-grid-react": "^33.3.1",
|
||||||
"astro": "^5.3.0",
|
"astro": "^5.3.0",
|
||||||
"astro-icon": "^1.1.1",
|
"astro-icon": "^1.1.1",
|
||||||
"astro-seo": "^0.8.4",
|
"astro-seo": "^0.8.4",
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ const LIMIT_PENDING = 5
|
||||||
|
|
||||||
export default async function MigrationFn(tx: Prisma.TransactionClient) {
|
export default async function MigrationFn(tx: Prisma.TransactionClient) {
|
||||||
const donatorRequests = await tx.requests.findMany({
|
const donatorRequests = await tx.requests.findMany({
|
||||||
where: { donator: true, state: RequestState.PENDING, userID: { not: null } }
|
where: { donator: true, state: RequestState.PENDING }
|
||||||
})
|
})
|
||||||
const donatorMap = new Map<string, typeof donatorRequests>()
|
const donatorMap = new Map<string, typeof donatorRequests>()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
/*
|
||||||
|
Warnings:
|
||||||
|
|
||||||
|
- You are about to drop the column `user` on the `requests` table. All the data in the column will be lost.
|
||||||
|
- You are about to drop the column `createdAt` on the `roles` table. All the data in the column will be lost.
|
||||||
|
- You are about to drop the column `updatedAt` on the `roles` table. All the data in the column will be lost.
|
||||||
|
- Made the column `userID` on table `requests` required. This step will fail if there are existing NULL values in that column.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
DELETE FROM `requests` WHERE `userId` IS NULL;
|
||||||
|
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE `requests` DROP COLUMN `user`,
|
||||||
|
MODIFY `userID` VARCHAR(255) NOT NULL;
|
||||||
|
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE `roles` DROP COLUMN `createdAt`,
|
||||||
|
DROP COLUMN `updatedAt`;
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
# Please do not edit this file manually
|
# Please do not edit this file manually
|
||||||
# It should be added in your version-control system (e.g., Git)
|
# It should be added in your version-control system (e.g., Git)
|
||||||
provider = "mysql"
|
provider = "mysql"
|
||||||
|
|
|
||||||
|
|
@ -344,8 +344,7 @@ model requests {
|
||||||
id Int @id @default(autoincrement())
|
id Int @id @default(autoincrement())
|
||||||
title String? @db.VarChar(255)
|
title String? @db.VarChar(255)
|
||||||
link String? @db.VarChar(255)
|
link String? @db.VarChar(255)
|
||||||
user String? @db.VarChar(255)
|
userID String @db.VarChar(255)
|
||||||
userID String? @db.VarChar(255)
|
|
||||||
state RequestState
|
state RequestState
|
||||||
donator Boolean
|
donator Boolean
|
||||||
reason String? @db.VarChar(255)
|
reason String? @db.VarChar(255)
|
||||||
|
|
@ -359,8 +358,6 @@ model requests {
|
||||||
model roles {
|
model roles {
|
||||||
name String @id @db.VarChar(255)
|
name String @id @db.VarChar(255)
|
||||||
permissions Json?
|
permissions Json?
|
||||||
createdAt DateTime @db.DateTime(0)
|
|
||||||
updatedAt DateTime @db.DateTime(0)
|
|
||||||
users User_Role[]
|
users User_Role[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
45
src/components/AgGrid/AgGridTheme.tsx
Normal file
45
src/components/AgGrid/AgGridTheme.tsx
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
import {
|
||||||
|
ModuleRegistry,
|
||||||
|
ColumnAutoSizeModule,
|
||||||
|
ColumnHoverModule,
|
||||||
|
TextFilterModule,
|
||||||
|
NumberFilterModule,
|
||||||
|
DateFilterModule,
|
||||||
|
QuickFilterModule,
|
||||||
|
TextEditorModule,
|
||||||
|
LargeTextEditorModule,
|
||||||
|
SelectEditorModule,
|
||||||
|
NumberEditorModule,
|
||||||
|
DateEditorModule,
|
||||||
|
CheckboxEditorModule,
|
||||||
|
LocaleModule,
|
||||||
|
ClientSideRowModelModule,
|
||||||
|
colorSchemeDark,
|
||||||
|
themeQuartz
|
||||||
|
} from 'ag-grid-community'
|
||||||
|
|
||||||
|
ModuleRegistry.registerModules([
|
||||||
|
ColumnAutoSizeModule,
|
||||||
|
ColumnHoverModule,
|
||||||
|
TextFilterModule,
|
||||||
|
NumberFilterModule,
|
||||||
|
DateFilterModule,
|
||||||
|
QuickFilterModule,
|
||||||
|
TextEditorModule,
|
||||||
|
LargeTextEditorModule,
|
||||||
|
SelectEditorModule,
|
||||||
|
NumberEditorModule,
|
||||||
|
DateEditorModule,
|
||||||
|
CheckboxEditorModule,
|
||||||
|
LocaleModule,
|
||||||
|
ClientSideRowModelModule
|
||||||
|
])
|
||||||
|
|
||||||
|
const AgGridTheme = themeQuartz.withPart(colorSchemeDark)
|
||||||
|
export default AgGridTheme
|
||||||
|
|
||||||
|
import { AG_GRID_LOCALE_EN } from '@ag-grid-community/locale'
|
||||||
|
|
||||||
|
export const AgGridLocales = {
|
||||||
|
en: { AG_GRID_LOCALE_EN }
|
||||||
|
}
|
||||||
|
|
@ -54,7 +54,6 @@ const { session } = Astro.locals
|
||||||
<a href='/'><NavButton>{m.home()}</NavButton></a>
|
<a href='/'><NavButton>{m.home()}</NavButton></a>
|
||||||
<a href='/last-added'><NavButton>{m.lastaddednav()}</NavButton></a>
|
<a href='/last-added'><NavButton>{m.lastaddednav()}</NavButton></a>
|
||||||
<a href='/album/list'><NavButton>{m.albumlist()}</NavButton></a>
|
<a href='/album/list'><NavButton>{m.albumlist()}</NavButton></a>
|
||||||
|
|
||||||
<Dropdown>
|
<Dropdown>
|
||||||
{m.games()}
|
{m.games()}
|
||||||
<Fragment slot='items'>
|
<Fragment slot='items'>
|
||||||
|
|
@ -65,7 +64,6 @@ const { session } = Astro.locals
|
||||||
<DropdownItem href='/platform/list'>{m.platforms()}</DropdownItem>
|
<DropdownItem href='/platform/list'>{m.platforms()}</DropdownItem>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
|
|
||||||
<Dropdown>
|
<Dropdown>
|
||||||
{m.animation()}
|
{m.animation()}
|
||||||
<Fragment slot='items'>
|
<Fragment slot='items'>
|
||||||
|
|
@ -74,13 +72,13 @@ const { session } = Astro.locals
|
||||||
<DropdownItem href='/studio/list'>{m.studios()}</DropdownItem>
|
<DropdownItem href='/studio/list'>{m.studios()}</DropdownItem>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
|
<a href='/requests'>
|
||||||
|
<NavButton>{m.requests()}</NavButton>
|
||||||
|
</a>
|
||||||
|
|
||||||
{
|
{
|
||||||
session ? (
|
session ? (
|
||||||
<>
|
<>
|
||||||
<a href='/requests'>
|
|
||||||
<NavButton>{m.requests()}</NavButton>
|
|
||||||
</a>
|
|
||||||
<NavButton>{m.submitalbum()}</NavButton>
|
<NavButton>{m.submitalbum()}</NavButton>
|
||||||
<Dropdown>
|
<Dropdown>
|
||||||
{m.adminGrounds()}
|
{m.adminGrounds()}
|
||||||
|
|
|
||||||
36
src/components/requests/RequestsTable.tsx
Normal file
36
src/components/requests/RequestsTable.tsx
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
import { type ColDef, type GridOptions } from 'ag-grid-community'
|
||||||
|
import { AgGridReact } from 'ag-grid-react'
|
||||||
|
import type { Prisma } from '@prisma/client'
|
||||||
|
import { m } from 'paraglide/messages.js'
|
||||||
|
|
||||||
|
import AgGridTheme from 'components/AgGrid/AgGridTheme'
|
||||||
|
|
||||||
|
const gridOptions: GridOptions = {
|
||||||
|
ensureDomOrder: true,
|
||||||
|
enableCellTextSelection: true
|
||||||
|
}
|
||||||
|
|
||||||
|
const colDefs: ColDef[] = [
|
||||||
|
{ field: 'id', headerName: m.requestID(), filter: true },
|
||||||
|
{ field: 'title', headerName: m.requests(), filter: true },
|
||||||
|
{ field: 'userID', headerName: m.userID(), filter: true },
|
||||||
|
{ field: 'state', headerName: m.state(), filter: true },
|
||||||
|
{ field: 'createdAt', headerName: m.createdAt() },
|
||||||
|
{ field: 'updatedAt', headerName: m.updatedAt() }
|
||||||
|
]
|
||||||
|
|
||||||
|
export default function RequestsTable(props: { initial: Prisma.requestsGetPayload<{}>[] }) {
|
||||||
|
const { initial } = props
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='w-full px-4 py-4'>
|
||||||
|
<AgGridReact
|
||||||
|
gridOptions={gridOptions}
|
||||||
|
rowData={initial}
|
||||||
|
columnDefs={colDefs}
|
||||||
|
theme={AgGridTheme}
|
||||||
|
autoSizeStrategy={{ type: 'fitCellContents' }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
27
src/pages/api/request/update.ts
Normal file
27
src/pages/api/request/update.ts
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
import type { APIRoute } from 'astro'
|
||||||
|
import * as s from 'superstruct'
|
||||||
|
import prismaClient from 'utils/prisma-client'
|
||||||
|
|
||||||
|
import { Status, parseForm } from 'utils/form'
|
||||||
|
import { EditRequest } from 'schemas/requests'
|
||||||
|
|
||||||
|
export const POST: APIRoute = async ({ request, locals }) => {
|
||||||
|
const { permissions, user } = locals
|
||||||
|
if (!user || !permissions.includes('REQUESTS')) return Status(403)
|
||||||
|
|
||||||
|
let body
|
||||||
|
try {
|
||||||
|
const formData = await parseForm(await request.formData())
|
||||||
|
body = s.create(formData, EditRequest)
|
||||||
|
} catch (err) {
|
||||||
|
return Status(422, (err as Error).message)
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await prismaClient.requests.update({ where: { id: body.id }, data: { ...body, updatedAt: new Date() } })
|
||||||
|
return Status(200, body.id.toString())
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err)
|
||||||
|
return Status(500, (err as Error).message)
|
||||||
|
}
|
||||||
|
}
|
||||||
14
src/pages/requests.astro
Normal file
14
src/pages/requests.astro
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
---
|
||||||
|
import BaseLayout from 'layouts/base.astro'
|
||||||
|
import DefaultSEO from 'components/DefaultSEO.astro'
|
||||||
|
import RequestsTable from 'components/requests/RequestsTable'
|
||||||
|
|
||||||
|
import prismaClient from 'utils/prisma-client'
|
||||||
|
|
||||||
|
const initialRequests = await prismaClient.requests.findMany({ orderBy: { createdAt: 'desc' } })
|
||||||
|
---
|
||||||
|
|
||||||
|
<DefaultSEO />
|
||||||
|
<BaseLayout>
|
||||||
|
<RequestsTable client:only='react' initial={initialRequests} />
|
||||||
|
</BaseLayout>
|
||||||
12
src/schemas/requests.ts
Normal file
12
src/schemas/requests.ts
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
import { RequestState } from '@prisma/client'
|
||||||
|
import { object, string, number, optional, enums } from 'superstruct'
|
||||||
|
|
||||||
|
export const EditRequest = object({
|
||||||
|
id: number(),
|
||||||
|
title: optional(string()),
|
||||||
|
link: optional(string()),
|
||||||
|
state: enums(Object.values(RequestState)),
|
||||||
|
reason: optional(string()),
|
||||||
|
comments: optional(string()),
|
||||||
|
message: optional(string())
|
||||||
|
})
|
||||||
Loading…
Add table
Add a link
Reference in a new issue