feat: add title field to workspace

This commit is contained in:
Steven 2023-02-28 07:03:37 +08:00
parent 544bd3555b
commit 910e4e1678
8 changed files with 67 additions and 25 deletions

View File

@ -11,6 +11,7 @@ type Workspace struct {
// Domain specific fields // Domain specific fields
Name string `json:"name"` Name string `json:"name"`
Title string `json:"title"`
Description string `json:"description"` Description string `json:"description"`
// Related fields // Related fields
@ -21,6 +22,7 @@ type WorkspaceCreate struct {
CreatorID int CreatorID int
Name string `json:"name"` Name string `json:"name"`
Title string `json:"title"`
Description string `json:"description"` Description string `json:"description"`
} }
@ -32,6 +34,7 @@ type WorkspacePatch struct {
// Domain specific fields // Domain specific fields
Name *string `json:"name"` Name *string `json:"name"`
Title *string `json:"title"`
Description *string `json:"description"` Description *string `json:"description"`
} }

View File

@ -37,6 +37,7 @@ CREATE TABLE workspace (
updated_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now')), updated_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now')),
row_status TEXT NOT NULL CHECK (row_status IN ('NORMAL', 'ARCHIVED')) DEFAULT 'NORMAL', row_status TEXT NOT NULL CHECK (row_status IN ('NORMAL', 'ARCHIVED')) DEFAULT 'NORMAL',
name TEXT NOT NULL UNIQUE, name TEXT NOT NULL UNIQUE,
title TEXT NOT NULL,
description TEXT NOT NULL DEFAULT '' description TEXT NOT NULL DEFAULT ''
); );

View File

@ -3,6 +3,7 @@ INSERT INTO
`id`, `id`,
`creator_id`, `creator_id`,
`name`, `name`,
`title`,
`description` `description`
) )
VALUES VALUES
@ -10,6 +11,7 @@ VALUES
11, 11,
101, 101,
'minecraft', 'minecraft',
'minecraft',
'' ''
); );
@ -18,12 +20,14 @@ INSERT INTO
`id`, `id`,
`creator_id`, `creator_id`,
`name`, `name`,
`title`,
`description` `description`
) )
VALUES VALUES
( (
12, 12,
102, 102,
'bob',
'bob-room', 'bob-room',
'' ''
); );

View File

@ -22,6 +22,7 @@ type workspaceRaw struct {
// Domain specific fields // Domain specific fields
Name string Name string
Title string
Description string Description string
} }
@ -35,6 +36,7 @@ func (raw *workspaceRaw) toWorkspace() *api.Workspace {
RowStatus: raw.RowStatus, RowStatus: raw.RowStatus,
Name: raw.Name, Name: raw.Name,
Title: raw.Title,
Description: raw.Description, Description: raw.Description,
WorkspaceUserList: []*api.WorkspaceUser{}, WorkspaceUserList: []*api.WorkspaceUser{},
} }
@ -174,15 +176,17 @@ func createWorkspace(ctx context.Context, tx *sql.Tx, create *api.WorkspaceCreat
INSERT INTO workspace ( INSERT INTO workspace (
creator_id, creator_id,
name, name,
title,
description description
) )
VALUES (?, ?, ?) VALUES (?, ?, ?)
RETURNING id, creator_id, created_ts, updated_ts, row_status, name, description RETURNING id, creator_id, created_ts, updated_ts, row_status, name, title, description
` `
var workspaceRaw workspaceRaw var workspaceRaw workspaceRaw
if err := tx.QueryRowContext(ctx, query, if err := tx.QueryRowContext(ctx, query,
create.CreatorID, create.CreatorID,
create.Name, create.Name,
create.Title,
create.Description, create.Description,
).Scan( ).Scan(
&workspaceRaw.ID, &workspaceRaw.ID,
@ -191,6 +195,7 @@ func createWorkspace(ctx context.Context, tx *sql.Tx, create *api.WorkspaceCreat
&workspaceRaw.UpdatedTs, &workspaceRaw.UpdatedTs,
&workspaceRaw.RowStatus, &workspaceRaw.RowStatus,
&workspaceRaw.Name, &workspaceRaw.Name,
&workspaceRaw.Title,
&workspaceRaw.Description, &workspaceRaw.Description,
); err != nil { ); err != nil {
return nil, FormatError(err) return nil, FormatError(err)
@ -208,6 +213,9 @@ func patchWorkspace(ctx context.Context, tx *sql.Tx, patch *api.WorkspacePatch)
if v := patch.Name; v != nil { if v := patch.Name; v != nil {
set, args = append(set, "name = ?"), append(args, *v) set, args = append(set, "name = ?"), append(args, *v)
} }
if v := patch.Title; v != nil {
set, args = append(set, "title = ?"), append(args, *v)
}
if v := patch.Description; v != nil { if v := patch.Description; v != nil {
set, args = append(set, "description = ?"), append(args, *v) set, args = append(set, "description = ?"), append(args, *v)
} }
@ -218,7 +226,7 @@ func patchWorkspace(ctx context.Context, tx *sql.Tx, patch *api.WorkspacePatch)
UPDATE workspace UPDATE workspace
SET ` + strings.Join(set, ", ") + ` SET ` + strings.Join(set, ", ") + `
WHERE id = ? WHERE id = ?
RETURNING id, creator_id, created_ts, updated_ts, row_status, name, description RETURNING id, creator_id, created_ts, updated_ts, row_status, name, title, description
` `
row, err := tx.QueryContext(ctx, query, args...) row, err := tx.QueryContext(ctx, query, args...)
if err != nil { if err != nil {
@ -235,6 +243,7 @@ func patchWorkspace(ctx context.Context, tx *sql.Tx, patch *api.WorkspacePatch)
&workspaceRaw.UpdatedTs, &workspaceRaw.UpdatedTs,
&workspaceRaw.RowStatus, &workspaceRaw.RowStatus,
&workspaceRaw.Name, &workspaceRaw.Name,
&workspaceRaw.Title,
&workspaceRaw.Description, &workspaceRaw.Description,
); err != nil { ); err != nil {
return nil, FormatError(err) return nil, FormatError(err)
@ -274,6 +283,7 @@ func findWorkspaceList(ctx context.Context, tx *sql.Tx, find *api.WorkspaceFind)
updated_ts, updated_ts,
row_status, row_status,
name, name,
title,
description description
FROM workspace FROM workspace
WHERE ` + strings.Join(where, " AND ") + ` WHERE ` + strings.Join(where, " AND ") + `
@ -295,6 +305,7 @@ func findWorkspaceList(ctx context.Context, tx *sql.Tx, find *api.WorkspaceFind)
&workspaceRaw.UpdatedTs, &workspaceRaw.UpdatedTs,
&workspaceRaw.RowStatus, &workspaceRaw.RowStatus,
&workspaceRaw.Name, &workspaceRaw.Name,
&workspaceRaw.Title,
&workspaceRaw.Description, &workspaceRaw.Description,
); err != nil { ); err != nil {
return nil, FormatError(err) return nil, FormatError(err)

View File

@ -20,6 +20,7 @@ const CreateWorkspaceDialog: React.FC<Props> = (props: Props) => {
const [state, setState] = useState<State>({ const [state, setState] = useState<State>({
workspaceCreate: { workspaceCreate: {
name: "", name: "",
title: "",
description: "", description: "",
}, },
}); });
@ -33,6 +34,7 @@ const CreateWorkspaceDialog: React.FC<Props> = (props: Props) => {
...state, ...state,
workspaceCreate: Object.assign(state.workspaceCreate, { workspaceCreate: Object.assign(state.workspaceCreate, {
name: workspaceTemp.name, name: workspaceTemp.name,
title: workspaceTemp.title,
description: workspaceTemp.description, description: workspaceTemp.description,
}), }),
}); });
@ -51,17 +53,13 @@ const CreateWorkspaceDialog: React.FC<Props> = (props: Props) => {
}); });
}; };
const handleNameInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
handleInputChange(e, "name");
};
const handleDescriptionInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
handleInputChange(e, "description");
};
const handleSaveBtnClick = async () => { const handleSaveBtnClick = async () => {
if (!state.workspaceCreate.name) { if (!state.workspaceCreate.name) {
toastHelper.error("Name is required"); toastHelper.error("ID is required");
return;
}
if (!state.workspaceCreate.title) {
toastHelper.error("Title is required");
return; return;
} }
@ -102,12 +100,31 @@ const CreateWorkspaceDialog: React.FC<Props> = (props: Props) => {
</div> </div>
<div> <div>
<div className="w-full flex flex-col justify-start items-start mb-3"> <div className="w-full flex flex-col justify-start items-start mb-3">
<span className="mb-2">Name</span> <span className="mb-2">
<Input className="w-full" type="text" value={state.workspaceCreate.name} onChange={handleNameInputChange} /> ID <span className="text-red-600">*</span>
</span>
<Input
className="w-full"
type="text"
placeholder="Workspace ID is an unique identifier for your workspace."
value={state.workspaceCreate.name}
onChange={(e) => handleInputChange(e, "name")}
/>
</div>
<div className="w-full flex flex-col justify-start items-start mb-3">
<span className="mb-2">
Name <span className="text-red-600">*</span>
</span>
<Input className="w-full" type="text" value={state.workspaceCreate.title} onChange={(e) => handleInputChange(e, "title")} />
</div> </div>
<div className="w-full flex flex-col justify-start items-start mb-3"> <div className="w-full flex flex-col justify-start items-start mb-3">
<span className="mb-2">Description</span> <span className="mb-2">Description</span>
<Input className="w-full" type="text" value={state.workspaceCreate.description} onChange={handleDescriptionInputChange} /> <Input
className="w-full"
type="text"
value={state.workspaceCreate.description}
onChange={(e) => handleInputChange(e, "description")}
/>
</div> </div>
<div className="w-full flex flex-row justify-end items-center"> <div className="w-full flex flex-row justify-end items-center">
<Button color="primary" disabled={requestState.isLoading} loading={requestState.isLoading} onClick={handleSaveBtnClick}> <Button color="primary" disabled={requestState.isLoading} loading={requestState.isLoading} onClick={handleSaveBtnClick}>

View File

@ -47,7 +47,7 @@ const Header: React.FC = () => {
<Dropdown <Dropdown
trigger={ trigger={
<button className="flex flex-row justify-end items-center cursor-pointer"> <button className="flex flex-row justify-end items-center cursor-pointer">
<span className="font-mono">{activedWorkspace?.name}</span> <span className="font-mono">{activedWorkspace?.title}</span>
<Icon.ChevronDown className="ml-1 w-5 h-auto text-gray-600" /> <Icon.ChevronDown className="ml-1 w-5 h-auto text-gray-600" />
</button> </button>
} }

View File

@ -87,7 +87,10 @@ const WorkspaceSetting: React.FC<Props> = (props: Props) => {
return ( return (
<> <>
<div className="w-full flex flex-col justify-start items-start"> <div className="w-full flex flex-col justify-start items-start">
<p className="text-3xl mt-4 mb-4">{workspace.name}</p> <p className="text-3xl mt-4 mb-4">
{workspace.title}
<span className="text-lg ml-1 font-mono text-gray-400">({workspace.name})</span>
</p>
<p className="mb-4">{workspace.description || "No description."}</p> <p className="mb-4">{workspace.description || "No description."}</p>
<div className="border-t pt-4 flex flex-row justify-start items-center"> <div className="border-t pt-4 flex flex-row justify-start items-center">
<div className="flex flex-row justify-start items-center space-x-2"> <div className="flex flex-row justify-start items-center space-x-2">

View File

@ -9,6 +9,7 @@ interface Workspace {
rowStatus: RowStatus; rowStatus: RowStatus;
name: string; name: string;
title: string;
description: string; description: string;
workspaceUserList: WorkspaceUser[]; workspaceUserList: WorkspaceUser[];
@ -16,6 +17,7 @@ interface Workspace {
interface WorkspaceCreate { interface WorkspaceCreate {
name: string; name: string;
title: string;
description: string; description: string;
} }
@ -23,6 +25,7 @@ interface WorkspacePatch {
id: WorkspaceId; id: WorkspaceId;
rowStatus?: RowStatus; rowStatus?: RowStatus;
name?: string; name?: string;
title?: string;
description?: string; description?: string;
} }