From a02ebae07ddd874898ce1a8cb339af586ba1b18f Mon Sep 17 00:00:00 2001 From: Taylor Bantle Date: Mon, 23 Oct 2023 13:40:28 -0700 Subject: [PATCH 1/4] web: Fix docs link --- .../AddItemDropdown/DocItem.tsx | 39 ++++++++++++------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/packages/web/components/DatabaseHeaderAndNav/AddItemDropdown/DocItem.tsx b/packages/web/components/DatabaseHeaderAndNav/AddItemDropdown/DocItem.tsx index 1027d1de..8970055b 100644 --- a/packages/web/components/DatabaseHeaderAndNav/AddItemDropdown/DocItem.tsx +++ b/packages/web/components/DatabaseHeaderAndNav/AddItemDropdown/DocItem.tsx @@ -1,24 +1,26 @@ import SmallLoader from "@components/SmallLoader"; -import { - DocListForDocPageFragment, - useDocsRowsForDocPageQuery, -} from "@gen/graphql-types"; +import { useDocsRowsForDocPageQuery } from "@gen/graphql-types"; import { RefParams } from "@lib/params"; import { newDoc } from "@lib/urls"; import { HiOutlineDocumentAdd } from "@react-icons/all-files/hi/HiOutlineDocumentAdd"; import DropdownItem from "./Item"; -type Props = { +type InnerProps = { params: RefParams; - doltDisabled?: boolean; }; -type InnerProps = Props & { - docs?: DocListForDocPageFragment; +type Props = InnerProps & { + doltDisabled?: boolean; }; function Inner(props: InnerProps) { - const canCreateNewDoc = !props.docs || props.docs.list.length < 2; + const res = useDocsRowsForDocPageQuery({ + variables: props.params, + }); + + if (res.loading) return ; + + const canCreateNewDoc = !res.data?.docs || res.data?.docs.list.length < 2; return ( } hide={!canCreateNewDoc} data-cy="add-dropdown-new-docs-link" - doltDisabled={props.doltDisabled} > New README/LICENSE @@ -34,10 +35,18 @@ function Inner(props: InnerProps) { } export default function DocsDropdownItem(props: Props) { - const res = useDocsRowsForDocPageQuery({ - variables: props.params, - }); + if (props.doltDisabled) { + return ( + } + data-cy="add-dropdown-new-docs-link" + doltDisabled={props.doltDisabled} + > + New README/LICENSE + + ); + } - if (res.loading) return ; - return ; + return ; } From a5515c3bb00344bbdaaf3757b5ab512dc06281ad Mon Sep 17 00:00:00 2001 From: Taylor Bantle Date: Mon, 23 Oct 2023 13:53:53 -0700 Subject: [PATCH 2/4] web: Add HideForNoWritesWrapper --- .../CellButtons/DeleteRowButton.tsx | 13 ++-- .../CellButtons/DropColumnButton.tsx | 13 ++-- .../web/components/CellButtons/EditCell.tsx | 19 ++--- .../components/CellButtons/MakeNullButton.tsx | 21 +++--- .../DataTable/AddRowsButton/index.tsx | 27 +++---- .../CreateViewButton/index.tsx | 15 ++-- .../web/components/DatabaseTableNav/index.tsx | 5 +- .../components/DatabasesDropdown/index.tsx | 19 ++--- packages/web/components/DocMarkdown/index.tsx | 15 ++-- packages/web/components/TableList/index.tsx | 11 +-- .../DatabasePage/CreateTableOptions.tsx | 38 +++++----- .../ForBranches/BranchesPage/BranchRow.tsx | 19 ++--- .../ForBranches/BranchesPage/index.tsx | 9 ++- .../ForDocs/DocsPage/DocList/NewDocButton.tsx | 19 ++--- .../ForDocs/NewDocPage/NewDocForm.tsx | 70 ++++++++++--------- .../DatabasePage/ForDocs/NoDocsMsg/index.tsx | 18 +++-- .../ReleaseList/ReleaseListItem.tsx | 19 ++--- .../ForReleases/ReleaseList/index.tsx | 25 ++++--- .../util/HideForNoWritesWrapper.tsx | 51 ++++++++++++++ 19 files changed, 272 insertions(+), 154 deletions(-) create mode 100644 packages/web/components/util/HideForNoWritesWrapper.tsx diff --git a/packages/web/components/CellButtons/DeleteRowButton.tsx b/packages/web/components/CellButtons/DeleteRowButton.tsx index cef8a288..ddb6a852 100644 --- a/packages/web/components/CellButtons/DeleteRowButton.tsx +++ b/packages/web/components/CellButtons/DeleteRowButton.tsx @@ -1,4 +1,5 @@ import Button from "@components/Button"; +import HideForNoWritesWrapper from "@components/util/HideForNoWritesWrapper"; import { useDataTableContext } from "@contexts/dataTable"; import { useSqlEditorContext } from "@contexts/sqleditor"; import { @@ -38,10 +39,12 @@ export default function DeleteRowButton(props: Props): JSX.Element | null { }; return ( -
- - Delete row - -
+ +
+ + Delete row + +
+
); } diff --git a/packages/web/components/CellButtons/DropColumnButton.tsx b/packages/web/components/CellButtons/DropColumnButton.tsx index 83bb5366..46c89e9e 100644 --- a/packages/web/components/CellButtons/DropColumnButton.tsx +++ b/packages/web/components/CellButtons/DropColumnButton.tsx @@ -1,4 +1,5 @@ import Button from "@components/Button"; +import HideForNoWritesWrapper from "@components/util/HideForNoWritesWrapper"; import { useDataTableContext } from "@contexts/dataTable"; import { useSqlEditorContext } from "@contexts/sqleditor"; import { ColumnForDataTableFragment } from "@gen/graphql-types"; @@ -29,10 +30,12 @@ export default function DropColumnButton({ col, refName }: Props) { }; return ( -
- - Drop column - -
+ +
+ + Drop column + +
+
); } diff --git a/packages/web/components/CellButtons/EditCell.tsx b/packages/web/components/CellButtons/EditCell.tsx index 63d6e498..6aa3c5f6 100644 --- a/packages/web/components/CellButtons/EditCell.tsx +++ b/packages/web/components/CellButtons/EditCell.tsx @@ -1,4 +1,5 @@ import Button from "@components/Button"; +import HideForNoWritesWrapper from "@components/util/HideForNoWritesWrapper"; import { useDataTableContext } from "@contexts/dataTable"; import { ColumnForDataTableFragment } from "@gen/graphql-types"; import { isUneditableDoltSystemTable } from "@lib/doltSystemTables"; @@ -21,13 +22,15 @@ export default function EditCell(props: Props) { } return ( -
- props.setEditing(true)} - className={css.button} - > - Edit Cell Value - -
+ +
+ props.setEditing(true)} + className={css.button} + > + Edit Cell Value + +
+
); } diff --git a/packages/web/components/CellButtons/MakeNullButton.tsx b/packages/web/components/CellButtons/MakeNullButton.tsx index ce60d7b2..dcce5abf 100644 --- a/packages/web/components/CellButtons/MakeNullButton.tsx +++ b/packages/web/components/CellButtons/MakeNullButton.tsx @@ -1,4 +1,5 @@ import Button from "@components/Button"; +import HideForNoWritesWrapper from "@components/util/HideForNoWritesWrapper"; import { useDataTableContext } from "@contexts/dataTable"; import { useSqlEditorContext } from "@contexts/sqleditor"; import { @@ -57,14 +58,16 @@ export default function MakeNullButton(props: Props): JSX.Element | null { }; return ( -
- - Make NULL - -
+ +
+ + Make NULL + +
+
); } diff --git a/packages/web/components/DataTable/AddRowsButton/index.tsx b/packages/web/components/DataTable/AddRowsButton/index.tsx index 6fabaada..d42f5779 100644 --- a/packages/web/components/DataTable/AddRowsButton/index.tsx +++ b/packages/web/components/DataTable/AddRowsButton/index.tsx @@ -1,5 +1,6 @@ import Link from "@components/links/Link"; +import HideForNoWritesWrapper from "@components/util/HideForNoWritesWrapper"; import { TableParams } from "@lib/params"; import { editTable } from "@lib/urls"; import { AiOutlinePlus } from "@react-icons/all-files/ai/AiOutlinePlus"; @@ -8,17 +9,19 @@ import css from "./index.module.css"; export default function AddRowsButton(props: { params: TableParams }) { return ( -
- - -
- - Add More Rows -
- -
+ +
+ + +
+ + Add More Rows +
+ +
+
); } diff --git a/packages/web/components/DatabaseTableHeader/CreateViewButton/index.tsx b/packages/web/components/DatabaseTableHeader/CreateViewButton/index.tsx index 74c864f3..510a7527 100644 --- a/packages/web/components/DatabaseTableHeader/CreateViewButton/index.tsx +++ b/packages/web/components/DatabaseTableHeader/CreateViewButton/index.tsx @@ -1,4 +1,5 @@ import Button from "@components/Button"; +import HideForNoWritesWrapper from "@components/util/HideForNoWritesWrapper"; import { DatabaseParams } from "@lib/params"; import { useState } from "react"; import CreateViewModal from "./CreateViewModal"; @@ -13,11 +14,13 @@ export default function CreateViewButton(props: Props) { const [isOpen, setIsOpen] = useState(false); return ( -
- - -
+ +
+ + +
+
); } diff --git a/packages/web/components/DatabaseTableNav/index.tsx b/packages/web/components/DatabaseTableNav/index.tsx index 37e6a5f2..aebff04e 100644 --- a/packages/web/components/DatabaseTableNav/index.tsx +++ b/packages/web/components/DatabaseTableNav/index.tsx @@ -1,6 +1,7 @@ import CustomFormSelect from "@components/CustomFormSelect"; import Tooltip from "@components/Tooltip"; import Link from "@components/links/Link"; +import HideForNoWritesWrapper from "@components/util/HideForNoWritesWrapper"; import NotDoltWrapper from "@components/util/NotDoltWrapper"; import { OptionalRefParams } from "@lib/params"; import { RefUrl, newBranch } from "@lib/urls"; @@ -59,7 +60,9 @@ function Nav({ /> - + + + ))} -
  • - -
  • + +
  • + +
  • +
    diff --git a/packages/web/components/DocMarkdown/index.tsx b/packages/web/components/DocMarkdown/index.tsx index f4f62ef6..60abe5e9 100644 --- a/packages/web/components/DocMarkdown/index.tsx +++ b/packages/web/components/DocMarkdown/index.tsx @@ -1,3 +1,4 @@ +import HideForNoWritesWrapper from "@components/util/HideForNoWritesWrapper"; import { DocForDocPageFragment } from "@gen/graphql-types"; import Maybe from "@lib/Maybe"; import { RefParams } from "@lib/params"; @@ -26,12 +27,14 @@ export default function DocMarkdown({ params, rowData }: Props) { doltDocsQueryDocName={doltDocsQueryDocName} docName={params.docName} > - + + +
    diff --git a/packages/web/components/TableList/index.tsx b/packages/web/components/TableList/index.tsx index 7d9e2f7f..5e132789 100644 --- a/packages/web/components/TableList/index.tsx +++ b/packages/web/components/TableList/index.tsx @@ -1,6 +1,7 @@ import Section from "@components/DatabaseTableNav/Section"; import SchemaDiagramButton from "@components/SchemaDiagramButton"; import Link from "@components/links/Link"; +import HideForNoWritesWrapper from "@components/util/HideForNoWritesWrapper"; import QueryHandler from "@components/util/QueryHandler"; import useTableNames from "@hooks/useTableNames"; import Maybe from "@lib/Maybe"; @@ -42,10 +43,12 @@ function Inner(props: InnerProps) { No tables found for {props.params.refName}

    )} - - - Add new table - + + + + Add new table + +
    ); } diff --git a/packages/web/components/pageComponents/DatabasePage/CreateTableOptions.tsx b/packages/web/components/pageComponents/DatabasePage/CreateTableOptions.tsx index 99076ffc..67c67e25 100644 --- a/packages/web/components/pageComponents/DatabasePage/CreateTableOptions.tsx +++ b/packages/web/components/pageComponents/DatabasePage/CreateTableOptions.tsx @@ -1,6 +1,7 @@ import Button from "@components/Button"; import { sampleCreateQueryForEmpty } from "@components/DatabaseTableHeader/utils"; import Link from "@components/links/Link"; +import HideForNoWritesWrapper from "@components/util/HideForNoWritesWrapper"; import { useSqlEditorContext } from "@contexts/sqleditor"; import { OptionalRefParams } from "@lib/params"; import { database } from "@lib/urls"; @@ -31,23 +32,28 @@ export default function CreateTableOptions(props: Props) {

    Create a new table

    -
    - } - link={ - - SQL Query - - } - /> -
    +
    + } + link={ + + SQL Query + + } + /> +
    + ) : ( - - - + + + + + )} diff --git a/packages/web/components/pageComponents/DatabasePage/ForBranches/BranchesPage/index.tsx b/packages/web/components/pageComponents/DatabasePage/ForBranches/BranchesPage/index.tsx index 7a1e79af..711dc0ef 100644 --- a/packages/web/components/pageComponents/DatabasePage/ForBranches/BranchesPage/index.tsx +++ b/packages/web/components/pageComponents/DatabasePage/ForBranches/BranchesPage/index.tsx @@ -4,6 +4,7 @@ import DeleteModal from "@components/DeleteModal"; import FormSelect from "@components/FormSelect"; import Loader from "@components/Loader"; import Link from "@components/links/Link"; +import HideForNoWritesWrapper from "@components/util/HideForNoWritesWrapper"; import QueryHandler from "@components/util/QueryHandler"; import { BranchFragment, @@ -65,9 +66,11 @@ function Inner(props: InnerProps): JSX.Element { isClearable horizontal /> - - - + + + + +
    diff --git a/packages/web/components/pageComponents/DatabasePage/ForDocs/DocsPage/DocList/NewDocButton.tsx b/packages/web/components/pageComponents/DatabasePage/ForDocs/DocsPage/DocList/NewDocButton.tsx index 3be0823a..3c2e3c09 100644 --- a/packages/web/components/pageComponents/DatabasePage/ForDocs/DocsPage/DocList/NewDocButton.tsx +++ b/packages/web/components/pageComponents/DatabasePage/ForDocs/DocsPage/DocList/NewDocButton.tsx @@ -1,5 +1,6 @@ import Button from "@components/Button"; import Link from "@components/links/Link"; +import HideForNoWritesWrapper from "@components/util/HideForNoWritesWrapper"; import { RefParams } from "@lib/params"; import { newDoc } from "@lib/urls"; import { FiPlus } from "@react-icons/all-files/fi/FiPlus"; @@ -11,13 +12,15 @@ type Props = { export default function NewDocButton(props: Props) { return ( - - - + + + + + ); } diff --git a/packages/web/components/pageComponents/DatabasePage/ForDocs/NewDocPage/NewDocForm.tsx b/packages/web/components/pageComponents/DatabasePage/ForDocs/NewDocPage/NewDocForm.tsx index 97082388..52b65b4b 100644 --- a/packages/web/components/pageComponents/DatabasePage/ForDocs/NewDocPage/NewDocForm.tsx +++ b/packages/web/components/pageComponents/DatabasePage/ForDocs/NewDocPage/NewDocForm.tsx @@ -2,6 +2,7 @@ import Button from "@components/Button"; import FormSelect, { Option } from "@components/FormSelect"; import Loader from "@components/Loader"; import TextareaWithMarkdown from "@components/TextareaWithMarkdown"; +import HideForNoWritesWrapper from "@components/util/HideForNoWritesWrapper"; import { DocForDocPageFragment, DocType, @@ -34,40 +35,45 @@ function Inner(props: InnerProps) {
    -
    -
    -
    Type
    - setState({ docType: d })} - /> -
    - {!invalidDocType ? ( -
    - setState({ markdown: m })} - placeholder="Add markdown here" + + +
    +
    Type
    + setState({ docType: d })} />
    - ) : ( -

    - Both README and LICENSE exist. Click on an individual document in - the About section to edit. -

    - )} - - + {!invalidDocType ? ( +
    + setState({ markdown: m })} + placeholder="Add markdown here" + /> +
    + ) : ( +

    + Both README and LICENSE exist. Click on an individual document + in the About section to edit. +

    + )} + + +
    ); diff --git a/packages/web/components/pageComponents/DatabasePage/ForDocs/NoDocsMsg/index.tsx b/packages/web/components/pageComponents/DatabasePage/ForDocs/NoDocsMsg/index.tsx index e224e836..5ca406bd 100644 --- a/packages/web/components/pageComponents/DatabasePage/ForDocs/NoDocsMsg/index.tsx +++ b/packages/web/components/pageComponents/DatabasePage/ForDocs/NoDocsMsg/index.tsx @@ -2,6 +2,7 @@ import Button from "@components/Button"; import CodeBlock from "@components/CodeBlock"; import DocsLink from "@components/links/DocsLink"; import Link from "@components/links/Link"; +import HideForNoWritesWrapper from "@components/util/HideForNoWritesWrapper"; import { RefParams } from "@lib/params"; import { newDoc } from "@lib/urls"; import css from "./index.module.css"; @@ -20,9 +21,11 @@ export default function NoDocsMsg(props: Props) {

    {props.params.docName ? `${props.params.docName} not` : "No docs"} found for {props.params.databaseName}. - - - + + + + +

    @@ -41,7 +44,14 @@ function AddFromWorkbench(props: Props) { <>

    Adding a doc through the Workbench

    - Click here to add a doc. + + <> + Click here to add a doc. + +

    ); diff --git a/packages/web/components/pageComponents/DatabasePage/ForReleases/ReleaseList/ReleaseListItem.tsx b/packages/web/components/pageComponents/DatabasePage/ForReleases/ReleaseList/ReleaseListItem.tsx index 2900d97e..788ec215 100644 --- a/packages/web/components/pageComponents/DatabasePage/ForReleases/ReleaseList/ReleaseListItem.tsx +++ b/packages/web/components/pageComponents/DatabasePage/ForReleases/ReleaseList/ReleaseListItem.tsx @@ -1,6 +1,7 @@ import Button from "@components/Button"; import CommitLink from "@components/links/CommitLink"; import RefLink from "@components/links/RefLink"; +import HideForNoWritesWrapper from "@components/util/HideForNoWritesWrapper"; import { TagForListFragment } from "@gen/graphql-types"; import { DatabaseParams } from "@lib/params"; import { FaRegTrashAlt } from "@react-icons/all-files/fa/FaRegTrashAlt"; @@ -35,14 +36,16 @@ export default function ReleaseListItem({
    )} - - - + + + + +
    {tag.message && ( diff --git a/packages/web/components/pageComponents/DatabasePage/ForReleases/ReleaseList/index.tsx b/packages/web/components/pageComponents/DatabasePage/ForReleases/ReleaseList/index.tsx index a88da3ab..2ae868d8 100644 --- a/packages/web/components/pageComponents/DatabasePage/ForReleases/ReleaseList/index.tsx +++ b/packages/web/components/pageComponents/DatabasePage/ForReleases/ReleaseList/index.tsx @@ -4,6 +4,7 @@ import DeleteModal from "@components/DeleteModal"; import Loader from "@components/Loader"; import Page404 from "@components/Page404"; import Link from "@components/links/Link"; +import HideForNoWritesWrapper from "@components/util/HideForNoWritesWrapper"; import { TagForListFragment, useDeleteTagMutation } from "@gen/graphql-types"; import { gqlDepNotFound } from "@lib/errors/graphql"; import { errorMatches } from "@lib/errors/helpers"; @@ -38,17 +39,19 @@ function Inner({ tags, ...props }: InnerProps) {

    Releases

    - - - + + + + +
    {tags?.length ? ( diff --git a/packages/web/components/util/HideForNoWritesWrapper.tsx b/packages/web/components/util/HideForNoWritesWrapper.tsx new file mode 100644 index 00000000..71987aef --- /dev/null +++ b/packages/web/components/util/HideForNoWritesWrapper.tsx @@ -0,0 +1,51 @@ +import { DatabaseParams } from "@lib/params"; + +type Props = { + params: DatabaseParams; + children: JSX.Element; + noWritesAction?: string; + noWritesClassName?: string; +}; + +export default function HideForNoWritesWrapper(props: Props) { + // const { userHasWritePerms, writesEnabled, readOnlyConfig, canWriteToDB } = + // useDeploymentRole(props.params); + + // if (!canWriteToDB) { + // return props.noWritesAction ? ( + //
    + // You must{" "} + // {getAction( + // props.params, + // userHasWritePerms, + // writesEnabled, + // readOnlyConfig, + // )}{" "} + // to {props.noWritesAction}. + //
    + // ) : null; + // } + return props.children; +} + +// function getAction( +// params: DeploymentParams, +// userHasWritePerms: boolean, +// writesEnabled: boolean, +// readOnlyConfig: boolean, +// ) { +// if (readOnlyConfig) { +// return ( +// +// disable the read-only behavior configuration +// +// ); +// } +// if (!writesEnabled) { +// return ( +// enable writes +// ); +// } +// if (!userHasWritePerms) return "have write permissions"; +// return "allow writes"; +// } From 49b369818dcd3d6ae0782508013546b03cdf60fd Mon Sep 17 00:00:00 2001 From: Taylor Bantle Date: Mon, 23 Oct 2023 14:11:03 -0700 Subject: [PATCH 3/4] web: Add component/hook for roles/writes --- .../components/CreateDatabase/InnerModal.tsx | 21 ++++ .../AddItemDropdown/DocItem.tsx | 46 +++++---- .../AddItemDropdown/index.tsx | 7 ++ .../components/DatabaseHeaderAndNav/Full.tsx | 2 + .../DatabaseHeaderAndNav/index.module.css | 7 ++ .../PermissionLabel/index.module.css | 7 ++ .../web/components/PermissionLabel/index.tsx | 46 +++++++++ .../components/StatusWithOptions/index.tsx | 97 ++++++++++--------- .../util/HideForNoWritesWrapper.tsx | 68 ++++++------- packages/web/hooks/useRole.ts | 72 ++++++++++++++ 10 files changed, 274 insertions(+), 99 deletions(-) create mode 100644 packages/web/components/PermissionLabel/index.module.css create mode 100644 packages/web/components/PermissionLabel/index.tsx create mode 100644 packages/web/hooks/useRole.ts diff --git a/packages/web/components/CreateDatabase/InnerModal.tsx b/packages/web/components/CreateDatabase/InnerModal.tsx index fddeeef6..d967f7a6 100644 --- a/packages/web/components/CreateDatabase/InnerModal.tsx +++ b/packages/web/components/CreateDatabase/InnerModal.tsx @@ -1,6 +1,7 @@ import Button from "@components/Button"; import ButtonsWithError from "@components/ButtonsWithError"; import FormInput from "@components/FormInput"; +import useRole from "@hooks/useRole"; import { ApolloErrorType } from "@lib/errors/types"; import { SyntheticEvent } from "react"; @@ -13,6 +14,26 @@ type InnerProps = { }; export default function InnerModal(props: InnerProps) { + const { userHasWritePerms, writesEnabled } = useRole(); + + if (!userHasWritePerms) { + return ( +
    +

    You must have write permissions to create a new database.

    + +
    + ); + } + + if (!writesEnabled) { + return ( +
    +

    You must enable writes to create a new database.

    + +
    + ); + } + return (
    ; - const canCreateNewDoc = !res.data?.docs || res.data?.docs.list.length < 2; + const canCreateNewDoc = + !props.userHasWritePerms || + !res.data?.docs || + res.data?.docs.list.length < 2; - return ( - } - hide={!canCreateNewDoc} - data-cy="add-dropdown-new-docs-link" - > - New README/LICENSE - - ); + return ; } export default function DocsDropdownItem(props: Props) { if (props.doltDisabled) { return ( - } - data-cy="add-dropdown-new-docs-link" + - New README/LICENSE - + hide={!props.userHasWritePerms} + /> ); } return ; } + +function NewDocLink(props: { + params: RefParams; + doltDisabled?: boolean; + hide?: boolean; +}) { + return ( + } + data-cy="add-dropdown-new-docs-link" + doltDisabled={props.doltDisabled} + hide={props.hide} + > + New README/LICENSE + + ); +} diff --git a/packages/web/components/DatabaseHeaderAndNav/AddItemDropdown/index.tsx b/packages/web/components/DatabaseHeaderAndNav/AddItemDropdown/index.tsx index bd608317..5a532a45 100644 --- a/packages/web/components/DatabaseHeaderAndNav/AddItemDropdown/index.tsx +++ b/packages/web/components/DatabaseHeaderAndNav/AddItemDropdown/index.tsx @@ -1,5 +1,6 @@ import Popup from "@components/Popup"; import NotDoltWrapper from "@components/util/NotDoltWrapper"; +import useRole from "@hooks/useRole"; import { DatabaseParams } from "@lib/params"; import { newRelease } from "@lib/urls"; import { AiOutlineTag } from "@react-icons/all-files/ai/AiOutlineTag"; @@ -15,6 +16,10 @@ type Props = { }; export default function AddItemDropdown(props: Props) { + const { userHasWritePerms, canWriteToDB } = useRole(); + + if (!canWriteToDB) return null; + return (
    } data-cy="add-dropdown-new-release-link" + hide={!userHasWritePerms} > New release @@ -53,6 +59,7 @@ export default function AddItemDropdown(props: Props) { )} diff --git a/packages/web/components/DatabaseHeaderAndNav/Full.tsx b/packages/web/components/DatabaseHeaderAndNav/Full.tsx index 960971c1..4d0ad6ff 100644 --- a/packages/web/components/DatabaseHeaderAndNav/Full.tsx +++ b/packages/web/components/DatabaseHeaderAndNav/Full.tsx @@ -1,4 +1,5 @@ import DatabaseNav from "@components/DatabaseNav"; +import PermissionLabel from "@components/PermissionLabel"; import DatabaseBreadcrumbs from "@components/breadcrumbs/DatabaseBreadcrumbs"; import { OptionalRefParams } from "@lib/params"; import cx from "classnames"; @@ -32,6 +33,7 @@ export default function Full(props: Props) { className={css.databaseBreadcrumbs} params={props.params} /> +
    + Read Only +
    + ); + } + + return ( +
    + Admin +
    + ); +} + +// export function getDeploymentRole(r: DeploymentRole): string { +// switch (r) { +// case DeploymentRole.Reader: +// return "Read"; +// case DeploymentRole.Writer: +// return "Write"; +// default: +// return r; +// } +// } diff --git a/packages/web/components/StatusWithOptions/index.tsx b/packages/web/components/StatusWithOptions/index.tsx index bc57fdc4..d359fe08 100644 --- a/packages/web/components/StatusWithOptions/index.tsx +++ b/packages/web/components/StatusWithOptions/index.tsx @@ -2,7 +2,9 @@ import Button from "@components/Button"; import Loader from "@components/Loader"; import Tooltip from "@components/Tooltip"; import Link from "@components/links/Link"; +import HideForNoWritesWrapper from "@components/util/HideForNoWritesWrapper"; import { StatusFragment, useGetStatusQuery } from "@gen/graphql-types"; +import useRole from "@hooks/useRole"; import { RefParams } from "@lib/params"; import { diff } from "@lib/urls"; import { IoArrowUndoOutline } from "@react-icons/all-files/io5/IoArrowUndoOutline"; @@ -25,53 +27,60 @@ type InnerProps = Props & { function Inner(props: InnerProps) { const [commitIsOpen, setCommitIsOpen] = useState(false); const [resetIsOpen, setResetIsOpen] = useState(false); + const { canWriteToDB } = useRole(); return ( - <> -
    - {!props.forDiffPage && ( - - Uncommitted changes. - - )} - setCommitIsOpen(true)} - className={css.commitButton} - > - Create commit - - setResetIsOpen(true)} - className={css.resetButton} - data-tooltip-id="reset-changes" - data-tooltip-content="Reset uncommitted changes" +
    + {!props.forDiffPage && ( + - - - -
    - - - + Uncommitted changes. + + )} + + <> + setCommitIsOpen(true)} + className={css.commitButton} + > + Create commit + + setResetIsOpen(true)} + className={css.resetButton} + data-tooltip-id="reset-changes" + data-tooltip-content="Reset uncommitted changes" + > + + + + + + + +
    ); } diff --git a/packages/web/components/util/HideForNoWritesWrapper.tsx b/packages/web/components/util/HideForNoWritesWrapper.tsx index 71987aef..1355999f 100644 --- a/packages/web/components/util/HideForNoWritesWrapper.tsx +++ b/packages/web/components/util/HideForNoWritesWrapper.tsx @@ -1,3 +1,4 @@ +import useRole from "@hooks/useRole"; import { DatabaseParams } from "@lib/params"; type Props = { @@ -8,44 +9,37 @@ type Props = { }; export default function HideForNoWritesWrapper(props: Props) { - // const { userHasWritePerms, writesEnabled, readOnlyConfig, canWriteToDB } = - // useDeploymentRole(props.params); + const { userHasWritePerms, canWriteToDB } = useRole(); - // if (!canWriteToDB) { - // return props.noWritesAction ? ( - //
    - // You must{" "} - // {getAction( - // props.params, - // userHasWritePerms, - // writesEnabled, - // readOnlyConfig, - // )}{" "} - // to {props.noWritesAction}. - //
    - // ) : null; - // } + if (!canWriteToDB) { + return props.noWritesAction ? ( +
    + You must {getAction(props.params, userHasWritePerms)} to{" "} + {props.noWritesAction}. +
    + ) : null; + } return props.children; } -// function getAction( -// params: DeploymentParams, -// userHasWritePerms: boolean, -// writesEnabled: boolean, -// readOnlyConfig: boolean, -// ) { -// if (readOnlyConfig) { -// return ( -// -// disable the read-only behavior configuration -// -// ); -// } -// if (!writesEnabled) { -// return ( -// enable writes -// ); -// } -// if (!userHasWritePerms) return "have write permissions"; -// return "allow writes"; -// } +function getAction( + _: DatabaseParams, + userHasWritePerms: boolean, + // writesEnabled: boolean, + // readOnlyConfig: boolean, +) { + // if (readOnlyConfig) { + // return ( + // + // disable the read-only behavior configuration + // + // ); + // } + // if (!writesEnabled) { + // return ( + // enable writes + // ); + // } + if (!userHasWritePerms) return "have write permissions"; + return "allow writes"; +} diff --git a/packages/web/hooks/useRole.ts b/packages/web/hooks/useRole.ts new file mode 100644 index 00000000..4a0dc91e --- /dev/null +++ b/packages/web/hooks/useRole.ts @@ -0,0 +1,72 @@ +type ReturnType = { + // depRole: DeploymentRole | undefined; + userIsAdmin: boolean; + userHasReadPerms: boolean; + userHasWritePerms: boolean; + canWriteToDB: boolean; + writesEnabled: boolean; + readOnlyConfig: boolean; +}; + +export default function useRole(): ReturnType { + // const { data, ...res } = useDepForDepRoleQuery({ + // variables: { + // deploymentName: params.deploymentName, + // ownerName: params.ownerName, + // }, + // }); + // const settingsQuery = useWorkbenchSettingsQuery({ + // variables: { + // deploymentName: params.deploymentName, + // ownerName: params.ownerName, + // }, + // }); + + // const [depRole, setDeploymentRole] = useState(data?.deployment.role); + // const [enableWrites, setEnableWrites] = useState( + // !!settingsQuery.data?.workbenchSettings.enableWrites, + // ); + // const [readOnlyConfig, setReadOnlyConfig] = useState( + // getIsReadOnlyConfig(data?.deployment.currentConfigItems), + // ); + + // useEffect(() => { + // if (!data) return; + // setDeploymentRole(data.deployment.role); + // setReadOnlyConfig(getIsReadOnlyConfig(data.deployment.currentConfigItems)); + // }, [data, setDeploymentRole]); + + // useEffect(() => { + // if (!settingsQuery.data) return; + // setEnableWrites(settingsQuery.data.workbenchSettings.enableWrites); + // }, [settingsQuery.data, setEnableWrites]); + + // const userIsAdmin = depRole === DeploymentRole.Admin; + // const userHasWritePerms = userIsAdmin || depRole === DeploymentRole.Writer; + // const userHasReadPerms = + // userHasWritePerms || depRole === DeploymentRole.Reader; + const userIsAdmin = true; + const userHasWritePerms = true; + const userHasReadPerms = true; + const enableWrites = true; + const readOnlyConfig = false; + + return { + // ...res, + // depRole, + userIsAdmin, + userHasWritePerms, + userHasReadPerms, + writesEnabled: enableWrites, + readOnlyConfig, + canWriteToDB: true, + }; +} + +// function getIsReadOnlyConfig( +// overrides: Maybe, +// ): boolean { +// if (!overrides) return false; +// const readOnlyConfig = overrides.find(o => o.key === "behavior_read_only"); +// return !!readOnlyConfig && readOnlyConfig.value === "true"; +// } From af522e7f2d08b2e8e1d481732603acde39151259 Mon Sep 17 00:00:00 2001 From: Taylor Bantle Date: Mon, 23 Oct 2023 14:48:37 -0700 Subject: [PATCH 4/4] web: Fix lint --- .../DatabaseHeaderAndNav/AddItemDropdown/DocItem.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/web/components/DatabaseHeaderAndNav/AddItemDropdown/DocItem.tsx b/packages/web/components/DatabaseHeaderAndNav/AddItemDropdown/DocItem.tsx index affbbd86..66aee81e 100644 --- a/packages/web/components/DatabaseHeaderAndNav/AddItemDropdown/DocItem.tsx +++ b/packages/web/components/DatabaseHeaderAndNav/AddItemDropdown/DocItem.tsx @@ -22,9 +22,8 @@ function Inner(props: InnerProps) { if (res.loading) return ; const canCreateNewDoc = - !props.userHasWritePerms || - !res.data?.docs || - res.data?.docs.list.length < 2; + props.userHasWritePerms && + (!res.data?.docs || res.data.docs.list.length < 2); return ; }