Add dedicated bot, workspace and user settings pages
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
import AddModalShell from "@/src/layouts/bots/(partials)/add-modal-shell";
|
||||
import type { BUN_SQLITE_COBBLE_USERS_JOIN } from "@/src/types/sql-joins";
|
||||
import UserForm from "@/src/pages/admin/people/create/(partials)/user-form";
|
||||
|
||||
type Props = {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
onSaved: (params: { person: BUN_SQLITE_COBBLE_USERS_JOIN; msg: string }) => void;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds a user in a modal. Editing one happens on its settings page.
|
||||
*/
|
||||
export default function NewUserModal({ open, onClose, onSaved }: Props) {
|
||||
return (
|
||||
<AddModalShell
|
||||
open={open}
|
||||
setOpen={(next) => !next && onClose()}
|
||||
title="Add a user"
|
||||
description="They get their own coordinator and main computer, and sign in with this password."
|
||||
>
|
||||
{open ? <UserForm onCancel={onClose} onSaved={onSaved} /> : null}
|
||||
</AddModalShell>
|
||||
);
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
import AddModalShell from "@/src/layouts/bots/(partials)/add-modal-shell";
|
||||
import type { BUN_SQLITE_COBBLE_USERS_JOIN } from "@/src/types/sql-joins";
|
||||
import UserForm from "@/src/pages/admin/people/create/(partials)/user-form";
|
||||
|
||||
type Props = {
|
||||
/**
|
||||
* Edits this user; adds one when not given.
|
||||
*/
|
||||
person?: BUN_SQLITE_COBBLE_USERS_JOIN;
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
onSaved: (params: { person: BUN_SQLITE_COBBLE_USERS_JOIN; msg: string }) => void;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds or edits a user in a modal.
|
||||
*/
|
||||
export default function UserEditModal({ person, open, onClose, onSaved }: Props) {
|
||||
return (
|
||||
<AddModalShell
|
||||
open={open}
|
||||
setOpen={(next) => !next && onClose()}
|
||||
title={person ? `Edit ${person.first_name || "the user"}` : "Add a user"}
|
||||
description={
|
||||
person
|
||||
? "Leave the password empty to keep theirs."
|
||||
: "They get their own coordinator and main computer, and sign in with this password."
|
||||
}
|
||||
>
|
||||
{open ? <UserForm key={person?.id || "new"} person={person} onCancel={onClose} onSaved={onSaved} /> : null}
|
||||
</AddModalShell>
|
||||
);
|
||||
}
|
||||
@@ -4,7 +4,6 @@ import type { BUN_SQLITE_COBBLE_USERS_JOIN } from "@/src/types/sql-joins";
|
||||
import type { BUN_SQLITE_COBBLE_USER_TYPES } from "@/db/types/db";
|
||||
import parseUserTypes from "@/src/utils/parse-user-types";
|
||||
import canRevokeUser from "@/src/utils/rbac/can-revoke-user";
|
||||
import canUpdateUser from "@/src/utils/rbac/can-update-user";
|
||||
import SettingsListRow from "../../(partials)/settings-list-row";
|
||||
import SettingsRowAction from "../../(partials)/settings-row-action";
|
||||
|
||||
@@ -13,22 +12,20 @@ type Props = {
|
||||
actor_user_id?: number | string;
|
||||
actor_user_types?: BUN_SQLITE_COBBLE_USER_TYPES[] | null;
|
||||
busy?: boolean;
|
||||
onEdit: () => void;
|
||||
onRevoke: () => void;
|
||||
onDelete: () => void;
|
||||
};
|
||||
|
||||
/**
|
||||
* One user: their photo, name, user types and email, then Edit, Revoke
|
||||
* (not once revoked) and Delete where the actor may (`canUpdateUser`,
|
||||
* `canRevokeUser`; never revoking or deleting yourself).
|
||||
* One user: their photo, name, user types and email. The title opens
|
||||
* their settings page; Revoke (not once revoked) and Delete sit at the
|
||||
* end where the actor may (`canRevokeUser`; never yourself).
|
||||
*/
|
||||
export default function UserSettingsRow({
|
||||
person,
|
||||
actor_user_id,
|
||||
actor_user_types,
|
||||
busy,
|
||||
onEdit,
|
||||
onRevoke,
|
||||
onDelete,
|
||||
}: Props) {
|
||||
@@ -42,25 +39,17 @@ export default function UserSettingsRow({
|
||||
.join(", ");
|
||||
const is_self = person.id == actor_user_id;
|
||||
const target_user_types = user_types.map((user_type) => ({ user_type }));
|
||||
const can_edit = canUpdateUser({ actor_user_types, actor_user_id, target_user_id: person.id, target_user_types });
|
||||
const can_delete = !is_self && canRevokeUser({ user_types: actor_user_types, target_user_types });
|
||||
const can_revoke = can_delete && !user_types.includes("revoked");
|
||||
|
||||
return (
|
||||
<SettingsListRow
|
||||
avatar={<UserAvatar person={person} size="md" />}
|
||||
href={`/admin/settings/users/${person.id}`}
|
||||
title={name}
|
||||
badge={is_self ? "You" : undefined}
|
||||
subtitle={[types_title, person.email].filter(Boolean).join(" · ")}
|
||||
>
|
||||
{can_edit ? (
|
||||
<SettingsRowAction
|
||||
title={`Edit ${name}`}
|
||||
label="Edit"
|
||||
disabled={busy}
|
||||
onClick={onEdit}
|
||||
/>
|
||||
) : null}
|
||||
{can_revoke ? (
|
||||
<SettingsRowAction
|
||||
title={`Revoke ${name}`}
|
||||
|
||||
Reference in New Issue
Block a user