diff --git a/src/client/pages/Settings.tsx b/src/client/pages/Settings.tsx
index 344a5ea..3f955df 100644
--- a/src/client/pages/Settings.tsx
+++ b/src/client/pages/Settings.tsx
@@ -1,6 +1,49 @@
+import { Menu, MenuProps } from 'antd';
import React from 'react';
+import { Routes, Route, useLocation, useNavigate } from 'react-router-dom';
+import { WebsiteInfo } from '../components/WebsiteInfo';
+import { WebsiteList } from '../components/WebsiteList';
+import { useEvent } from '../hooks/useEvent';
export const Settings: React.FC = React.memo(() => {
- return
Settings
;
+ const navigate = useNavigate();
+ const { pathname } = useLocation();
+
+ const items: MenuProps['items'] = [
+ {
+ key: 'websites',
+ label: 'Websites',
+ },
+ ];
+
+ const onClick: MenuProps['onClick'] = useEvent((e) => {
+ navigate(`/settings/${e.key}`);
+ });
+
+ const selectedKey =
+ (items.find((item) => pathname.startsWith(`/settings/${item?.key}`))
+ ?.key as string) ?? 'websites';
+
+ return (
+
+
+
+ {pathname}
+
+
+
+ } />
+ } />
+ } />
+
+
+
+ );
});
Settings.displayName = 'Settings';
diff --git a/src/client/pages/Website.tsx b/src/client/pages/Website.tsx
index b5af3c9..9b56fad 100644
--- a/src/client/pages/Website.tsx
+++ b/src/client/pages/Website.tsx
@@ -1,120 +1,7 @@
-import {
- BarChartOutlined,
- EditOutlined,
- PlusOutlined,
-} from '@ant-design/icons';
-import { Button, Form, Input, Modal, Table } from 'antd';
-import { ColumnsType } from 'antd/es/table';
-import React, { useMemo, useState } from 'react';
-import {
- addWorkspaceWebsite,
- refreshWorkspaceWebsites,
- useWorspaceWebsites,
- WebsiteInfo,
-} from '../api/model/website';
-import { Loading } from '../components/Loading';
-import { NoWorkspaceTip } from '../components/NoWorkspaceTip';
-import { useRequest } from '../hooks/useRequest';
-import { useUserStore } from '../store/user';
+import React from 'react';
+import { WebsiteList } from '../components/WebsiteList';
export const Website: React.FC = React.memo(() => {
- const [isModalOpen, setIsModalOpen] = useState(false);
- const currentWorkspace = useUserStore(
- (state) => state.info?.currentWorkspace
- );
- const [form] = Form.useForm();
-
- const [{ loading }, handleAddWebsite] = useRequest(async () => {
- await form.validateFields();
- const values = form.getFieldsValue();
-
- await addWorkspaceWebsite(currentWorkspace!.id, values.name, values.domain);
- refreshWorkspaceWebsites(currentWorkspace!.id);
- setIsModalOpen(false);
-
- form.resetFields();
- });
-
- if (!currentWorkspace) {
- return
;
- }
-
- return (
-
-
-
Websites
-
- }
- size="large"
- onClick={() => setIsModalOpen(true)}
- >
- Add Website
-
-
-
-
-
-
-
handleAddWebsite()}
- onCancel={() => setIsModalOpen(false)}
- >
-
-
-
-
-
-
-
-
-
- );
+ return
;
});
Website.displayName = 'Website';
-
-const WebsiteList: React.FC<{ workspaceId: string }> = React.memo((props) => {
- const { websites, isLoading } = useWorspaceWebsites(props.workspaceId);
-
- const columns = useMemo((): ColumnsType
=> {
- return [
- {
- dataIndex: 'name',
- title: 'Name',
- },
- {
- dataIndex: 'domain',
- title: 'Domain',
- },
- {
- key: 'action',
- render: () => {
- return (
-
- }>Edit
- }>View
-
- );
- },
- },
- ];
- }, []);
-
- if (isLoading) {
- return ;
- }
-
- return ;
-});
-WebsiteList.displayName = 'WebsiteList';
diff --git a/src/client/store/user.ts b/src/client/store/user.ts
index efafce1..3a28a78 100644
--- a/src/client/store/user.ts
+++ b/src/client/store/user.ts
@@ -22,3 +22,11 @@ export function setUserInfo(info: UserLoginInfo) {
info,
});
}
+
+export function useCurrentWorkspaceId() {
+ const currentWorkspaceId = useUserStore(
+ (state) => state.info?.currentWorkspace?.id
+ );
+
+ return currentWorkspaceId;
+}
diff --git a/src/server/middleware/workspace.ts b/src/server/middleware/workspace.ts
index 634d928..79bc259 100644
--- a/src/server/middleware/workspace.ts
+++ b/src/server/middleware/workspace.ts
@@ -3,7 +3,8 @@ import { checkIsWorkspaceUser } from '../model/workspace';
export function workspacePermission(): Handler {
return async (req, res, next) => {
- const workspaceId = req.body.workspaceId ?? req.query.workspaceId;
+ const workspaceId =
+ req.body.workspaceId ?? req.query.workspaceId ?? req.params.workspaceId;
if (!workspaceId) {
throw new Error('Cannot find workspace id');
diff --git a/src/server/model/workspace.ts b/src/server/model/workspace.ts
index 4ec74f0..509d3e4 100644
--- a/src/server/model/workspace.ts
+++ b/src/server/model/workspace.ts
@@ -35,6 +35,40 @@ export async function getWorkspaceWebsites(workspaceId: string) {
return workspace?.websites ?? [];
}
+export async function getWorkspaceWebsiteInfo(
+ workspaceId: string,
+ websiteId: string
+) {
+ const websiteInfo = await prisma.website.findUnique({
+ where: {
+ id: websiteId,
+ workspaceId,
+ },
+ });
+
+ return websiteInfo;
+}
+
+export async function updateWorkspaceWebsiteInfo(
+ workspaceId: string,
+ websiteId: string,
+ name: string,
+ domain: string
+) {
+ const websiteInfo = await prisma.website.update({
+ where: {
+ id: websiteId,
+ workspaceId,
+ },
+ data: {
+ name,
+ domain,
+ },
+ });
+
+ return websiteInfo;
+}
+
export async function addWorkspaceWebsite(
workspaceId: string,
name: string,
diff --git a/src/server/router/workspace.ts b/src/server/router/workspace.ts
index 1311dfe..c462b58 100644
--- a/src/server/router/workspace.ts
+++ b/src/server/router/workspace.ts
@@ -1,8 +1,13 @@
import { Router } from 'express';
import { auth } from '../middleware/auth';
-import { body, query, validate } from '../middleware/validate';
+import { body, param, query, validate } from '../middleware/validate';
import { workspacePermission } from '../middleware/workspace';
-import { addWorkspaceWebsite, getWorkspaceWebsites } from '../model/workspace';
+import {
+ addWorkspaceWebsite,
+ getWorkspaceWebsiteInfo,
+ getWorkspaceWebsites,
+ updateWorkspaceWebsiteInfo,
+} from '../model/workspace';
export const workspaceRouter = Router();
@@ -34,8 +39,16 @@ workspaceRouter.post(
.withMessage('workspaceId should be string')
.isUUID()
.withMessage('workspaceId should be UUID'),
- body('name').isString().withMessage('name should be a string'),
- body('domain').isURL().withMessage('domain should be URL')
+ body('name')
+ .isString()
+ .withMessage('name should be string')
+ .isLength({ max: 100 })
+ .withMessage('length should be under 100'),
+ body('domain')
+ .isURL()
+ .withMessage('domain should be URL')
+ .isLength({ max: 500 })
+ .withMessage('length should be under 500')
),
auth(),
workspacePermission(),
@@ -47,3 +60,71 @@ workspaceRouter.post(
res.json({ website });
}
);
+
+workspaceRouter.get(
+ '/website/:websiteId',
+ validate(
+ query('workspaceId')
+ .isString()
+ .withMessage('workspaceId should be string')
+ .isUUID()
+ .withMessage('workspaceId should be UUID'),
+ param('websiteId')
+ .isString()
+ .withMessage('workspaceId should be string')
+ .isUUID()
+ .withMessage('workspaceId should be UUID')
+ ),
+ auth(),
+ workspacePermission(),
+ async (req, res) => {
+ const workspaceId = req.query.workspaceId as string;
+ const websiteId = req.params.websiteId;
+
+ const website = await getWorkspaceWebsiteInfo(workspaceId, websiteId);
+
+ res.json({ website });
+ }
+);
+
+workspaceRouter.post(
+ '/website/:websiteId',
+ validate(
+ body('workspaceId')
+ .isString()
+ .withMessage('workspaceId should be string')
+ .isUUID()
+ .withMessage('workspaceId should be UUID'),
+ param('websiteId')
+ .isString()
+ .withMessage('workspaceId should be string')
+ .isUUID()
+ .withMessage('workspaceId should be UUID'),
+ body('name')
+ .isString()
+ .withMessage('name should be string')
+ .isLength({ max: 100 })
+ .withMessage('length should be under 100'),
+ body('domain')
+ .isURL()
+ .withMessage('domain should be URL')
+ .isLength({ max: 500 })
+ .withMessage('length should be under 500')
+ ),
+ auth(),
+ workspacePermission(),
+ async (req, res) => {
+ const workspaceId = req.query.workspaceId as string;
+ const websiteId = req.params.websiteId;
+ const { name, domain } = req.body;
+
+ const website = await updateWorkspaceWebsiteInfo(
+ workspaceId,
+ websiteId,
+ name,
+ domain
+ );
+
+ res.json({ website });
+ }
+);
diff --git a/src/server/tsconfig.json b/src/server/tsconfig.json
index 6f83eb6..63e20a2 100644
--- a/src/server/tsconfig.json
+++ b/src/server/tsconfig.json
@@ -1,3 +1,4 @@
{
"extends": "../../tsconfig.json",
+ "include": ["./**/*"]
}