mirror of https://github.com/MaxLeiter/Drift
				
				
				
			client/server: lint and add functionality for admin to update homepage
							parent
							
								
									be6de7c796
								
							
						
					
					
						commit
						b5024e3f45
					
				@ -0,0 +1,75 @@
 | 
			
		||||
import SettingsGroup from "@components/settings-group"
 | 
			
		||||
import { Button, Input, Spacer, Textarea, useToasts } from "@geist-ui/core"
 | 
			
		||||
import { useEffect, useState } from "react"
 | 
			
		||||
import { adminFetcher } from "."
 | 
			
		||||
 | 
			
		||||
const Homepage = () => {
 | 
			
		||||
	const [description, setDescription] = useState<string>("")
 | 
			
		||||
	const [title, setTitle] = useState<string>("")
 | 
			
		||||
	const { setToast } = useToasts()
 | 
			
		||||
	useEffect(() => {
 | 
			
		||||
		const fetchServerInfo = async () => {
 | 
			
		||||
			const res = await adminFetcher("/server-info")
 | 
			
		||||
			const data = await res.json()
 | 
			
		||||
			setDescription(data.welcomeMessage)
 | 
			
		||||
			setTitle(data.welcomeTitle)
 | 
			
		||||
		}
 | 
			
		||||
		fetchServerInfo()
 | 
			
		||||
	}, [])
 | 
			
		||||
 | 
			
		||||
	const onSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
 | 
			
		||||
		e.preventDefault()
 | 
			
		||||
 | 
			
		||||
		const res = await adminFetcher("/server-info", {
 | 
			
		||||
			method: "PUT",
 | 
			
		||||
			body: {
 | 
			
		||||
				description,
 | 
			
		||||
				title
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
 | 
			
		||||
		if (res.status === 200) {
 | 
			
		||||
			setToast({
 | 
			
		||||
				type: "success",
 | 
			
		||||
				text: "Server info updated"
 | 
			
		||||
			})
 | 
			
		||||
			setDescription(description)
 | 
			
		||||
			setTitle(title)
 | 
			
		||||
		} else {
 | 
			
		||||
			setToast({
 | 
			
		||||
				text: "Something went wrong",
 | 
			
		||||
				type: "error"
 | 
			
		||||
			})
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return (
 | 
			
		||||
		<SettingsGroup title="Homepage">
 | 
			
		||||
			<form onSubmit={onSubmit}>
 | 
			
		||||
				<div>
 | 
			
		||||
					<label htmlFor="title">Title</label>
 | 
			
		||||
					<Input
 | 
			
		||||
						id="title"
 | 
			
		||||
						value={title}
 | 
			
		||||
						onChange={(e) => setTitle(e.target.value)}
 | 
			
		||||
					/>
 | 
			
		||||
				</div>
 | 
			
		||||
				<Spacer height={1} />
 | 
			
		||||
				<div>
 | 
			
		||||
					<label htmlFor="message">Description (markdown)</label>
 | 
			
		||||
					<Textarea
 | 
			
		||||
						width={"100%"}
 | 
			
		||||
						height={10}
 | 
			
		||||
						id="message"
 | 
			
		||||
						value={description}
 | 
			
		||||
						onChange={(e) => setDescription(e.target.value)}
 | 
			
		||||
					/>
 | 
			
		||||
				</div>
 | 
			
		||||
				<Spacer height={1} />
 | 
			
		||||
				<Button htmlType="submit">Update</Button>
 | 
			
		||||
			</form>
 | 
			
		||||
		</SettingsGroup>
 | 
			
		||||
	)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default Homepage
 | 
			
		||||
@ -1,24 +1,21 @@
 | 
			
		||||
import { Fieldset, Text, Divider } from "@geist-ui/core"
 | 
			
		||||
import styles from './settings-group.module.css'
 | 
			
		||||
import styles from "./settings-group.module.css"
 | 
			
		||||
 | 
			
		||||
type Props = {
 | 
			
		||||
    title: string,
 | 
			
		||||
    children: React.ReactNode | React.ReactNode[],
 | 
			
		||||
	title: string
 | 
			
		||||
	children: React.ReactNode | React.ReactNode[]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const SettingsGroup = ({
 | 
			
		||||
    title,
 | 
			
		||||
    children,
 | 
			
		||||
}: Props) => {
 | 
			
		||||
    return <Fieldset>
 | 
			
		||||
        <Fieldset.Content>
 | 
			
		||||
            <Text h4>{title}</Text>
 | 
			
		||||
        </Fieldset.Content>
 | 
			
		||||
        <Divider />
 | 
			
		||||
        <Fieldset.Content className={styles.content}>
 | 
			
		||||
            {children}
 | 
			
		||||
        </Fieldset.Content>
 | 
			
		||||
    </Fieldset>
 | 
			
		||||
const SettingsGroup = ({ title, children }: Props) => {
 | 
			
		||||
	return (
 | 
			
		||||
		<Fieldset>
 | 
			
		||||
			<Fieldset.Content>
 | 
			
		||||
				<Text h4>{title}</Text>
 | 
			
		||||
			</Fieldset.Content>
 | 
			
		||||
			<Divider />
 | 
			
		||||
			<Fieldset.Content className={styles.content}>{children}</Fieldset.Content>
 | 
			
		||||
		</Fieldset>
 | 
			
		||||
	)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default SettingsGroup
 | 
			
		||||
 | 
			
		||||
@ -1,15 +1,27 @@
 | 
			
		||||
import { Button, Divider, Text, Fieldset, Input, Page, Note, Textarea } from "@geist-ui/core"
 | 
			
		||||
import {
 | 
			
		||||
	Button,
 | 
			
		||||
	Divider,
 | 
			
		||||
	Text,
 | 
			
		||||
	Fieldset,
 | 
			
		||||
	Input,
 | 
			
		||||
	Page,
 | 
			
		||||
	Note,
 | 
			
		||||
	Textarea
 | 
			
		||||
} from "@geist-ui/core"
 | 
			
		||||
import PageSeo from "@components/page-seo"
 | 
			
		||||
import styles from "@styles/Home.module.css"
 | 
			
		||||
import SettingsPage from "@components/settings"
 | 
			
		||||
 | 
			
		||||
const Settings = () => (
 | 
			
		||||
    <Page width={"100%"}>
 | 
			
		||||
        <PageSeo title="Drift - Settings" />
 | 
			
		||||
        <Page.Content className={styles.main} style={{ gap: 'var(--gap)', display: 'flex', flexDirection: 'column' }}>
 | 
			
		||||
            <SettingsPage />
 | 
			
		||||
        </Page.Content>
 | 
			
		||||
    </Page>
 | 
			
		||||
	<Page width={"100%"}>
 | 
			
		||||
		<PageSeo title="Drift - Settings" />
 | 
			
		||||
		<Page.Content
 | 
			
		||||
			className={styles.main}
 | 
			
		||||
			style={{ gap: "var(--gap)", display: "flex", flexDirection: "column" }}
 | 
			
		||||
		>
 | 
			
		||||
			<SettingsPage />
 | 
			
		||||
		</Page.Content>
 | 
			
		||||
	</Page>
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
export default Settings
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,33 @@
 | 
			
		||||
import {
 | 
			
		||||
	Model,
 | 
			
		||||
	Column,
 | 
			
		||||
	Table,
 | 
			
		||||
	IsUUID,
 | 
			
		||||
	PrimaryKey,
 | 
			
		||||
	DataType,
 | 
			
		||||
	Unique
 | 
			
		||||
} from "sequelize-typescript"
 | 
			
		||||
 | 
			
		||||
@Table({
 | 
			
		||||
	tableName: "server-info"
 | 
			
		||||
})
 | 
			
		||||
export class ServerInfo extends Model {
 | 
			
		||||
	@IsUUID(4)
 | 
			
		||||
	@PrimaryKey
 | 
			
		||||
	@Unique
 | 
			
		||||
	@Column({
 | 
			
		||||
		type: DataType.UUID,
 | 
			
		||||
		defaultValue: DataType.UUIDV4
 | 
			
		||||
	})
 | 
			
		||||
	id!: string
 | 
			
		||||
 | 
			
		||||
	@Column({
 | 
			
		||||
		type: DataType.STRING
 | 
			
		||||
	})
 | 
			
		||||
	welcomeMessage!: string
 | 
			
		||||
 | 
			
		||||
	@Column({
 | 
			
		||||
		type: DataType.STRING
 | 
			
		||||
	})
 | 
			
		||||
	welcomeTitle!: string
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,37 @@
 | 
			
		||||
"use strict"
 | 
			
		||||
import { DataTypes } from "sequelize"
 | 
			
		||||
import type { Migration } from "../database"
 | 
			
		||||
 | 
			
		||||
export const up: Migration = async ({ context: queryInterface }) =>
 | 
			
		||||
	queryInterface.createTable("server-info", {
 | 
			
		||||
		id: {
 | 
			
		||||
			type: DataTypes.INTEGER,
 | 
			
		||||
			primaryKey: true,
 | 
			
		||||
			autoIncrement: true,
 | 
			
		||||
			defaultValue: 1
 | 
			
		||||
		},
 | 
			
		||||
		welcomeMessage: {
 | 
			
		||||
			type: DataTypes.TEXT,
 | 
			
		||||
			defaultValue:
 | 
			
		||||
				"## Drift is a self-hostable clone of GitHub Gist. \nIt is a simple way to share code and text snippets with your friends, with support for the following:\n  \n  - Render GitHub Extended Markdown (including images)\n  - User authentication\n  - Private, public, and password protected posts\n  - Markdown is rendered and stored on the server\n  - Syntax highlighting and automatic language detection\n  - Drag-and-drop file uploading\n\n  If you want to signup, you can join at [/signup](/signup) as long as you have a passcode provided by the administrator (which you don't need for this demo). **This demo is on a memory-only database, so accounts and pastes can be deleted at any time.** \n\nYou can find the source code on [GitHub](https://github.com/MaxLeiter/drift).",
 | 
			
		||||
			allowNull: true
 | 
			
		||||
		},
 | 
			
		||||
		welcomeTitle: {
 | 
			
		||||
			type: DataTypes.TEXT,
 | 
			
		||||
			defaultValue: "Welcome to Drift",
 | 
			
		||||
			allowNull: true
 | 
			
		||||
		},
 | 
			
		||||
		createdAt: {
 | 
			
		||||
			type: DataTypes.DATE,
 | 
			
		||||
			defaultValue: DataTypes.NOW,
 | 
			
		||||
			allowNull: true
 | 
			
		||||
		},
 | 
			
		||||
		updatedAt: {
 | 
			
		||||
			type: DataTypes.DATE,
 | 
			
		||||
			defaultValue: DataTypes.NOW,
 | 
			
		||||
			allowNull: true
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
export const down: Migration = async ({ context: queryInterface }) =>
 | 
			
		||||
	queryInterface.dropTable("server-info")
 | 
			
		||||
					Loading…
					
					
				
		Reference in New Issue