Skip to content

Commit

Permalink
Add settings to control feature visibility in sidebar (sketching, for…
Browse files Browse the repository at this point in the history
…ums)
  • Loading branch information
underbluewaters committed Dec 27, 2023
1 parent fb31eb3 commit 7ba3b24
Show file tree
Hide file tree
Showing 11 changed files with 366 additions and 79 deletions.
4 changes: 4 additions & 0 deletions packages/api/generated-schema-clean.gql
Original file line number Diff line number Diff line change
Expand Up @@ -9802,6 +9802,8 @@ type Project implements Node {
"""The method to use when ordering `Group`."""
orderBy: [GroupsOrderBy!]
): [Group!]!
hideForums: Boolean!
hideSketches: Boolean!
id: Int!
importedArcgisServices: [String]

Expand Down Expand Up @@ -10458,6 +10460,8 @@ input ProjectPatch {

"""Should be a short length in order to fit in the project header."""
description: String
hideForums: Boolean
hideSketches: Boolean
inviteEmailSubject: String

"""
Expand Down
4 changes: 4 additions & 0 deletions packages/api/generated-schema.gql
Original file line number Diff line number Diff line change
Expand Up @@ -9802,6 +9802,8 @@ type Project implements Node {
"""The method to use when ordering `Group`."""
orderBy: [GroupsOrderBy!]
): [Group!]!
hideForums: Boolean!
hideSketches: Boolean!
id: Int!
importedArcgisServices: [String]

Expand Down Expand Up @@ -10458,6 +10460,8 @@ input ProjectPatch {

"""Should be a short length in order to fit in the project header."""
description: String
hideForums: Boolean
hideSketches: Boolean
inviteEmailSubject: String

"""
Expand Down
8 changes: 8 additions & 0 deletions packages/api/migrations/committed/000284.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
--! Previous: sha1:02e45756b70820a4a7dbf64d7732f24c952bfcd9
--! Hash: sha1:b53d0ae122b7ae1c5a9ac6395ebd460bdf6beef3

-- Enter migration here
alter table projects add column if not exists hide_forums boolean not null default false;
alter table projects add column if not exists hide_sketches boolean not null default false;

grant update(hide_forums, hide_sketches) on projects to seasketch_user;
40 changes: 16 additions & 24 deletions packages/api/schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -5343,6 +5343,8 @@ CREATE TABLE public.projects (
translated_props jsonb DEFAULT '{}'::jsonb NOT NULL,
draft_table_of_contents_has_changes boolean DEFAULT false NOT NULL,
table_of_contents_last_published timestamp without time zone,
hide_forums boolean DEFAULT false NOT NULL,
hide_sketches boolean DEFAULT false NOT NULL,
CONSTRAINT disallow_unlisted_public_projects CHECK (((access_control <> 'public'::public.project_access_control_setting) OR (is_listed = true))),
CONSTRAINT is_public_key CHECK (((mapbox_public_key IS NULL) OR (mapbox_public_key ~* '^pk\..+'::text))),
CONSTRAINT is_secret CHECK (((mapbox_secret_key IS NULL) OR (mapbox_secret_key ~* '^sk\..+'::text))),
Expand Down Expand Up @@ -8056,23 +8058,6 @@ CREATE FUNCTION public.has_session() RETURNS boolean
COMMENT ON FUNCTION public.has_session() IS '@omit';


--
-- Name: id_lookup_get_key(integer); Type: FUNCTION; Schema: public; Owner: -
--

CREATE FUNCTION public.id_lookup_get_key(key integer) RETURNS integer
LANGUAGE plpgsql
AS $$
begin
if lookup is null then
raise exception 'lookup is null';
else
return (lookup->key)::int;
end if;
end;
$$;


--
-- Name: id_lookup_get_key(jsonb, integer); Type: FUNCTION; Schema: public; Owner: -
--
Expand Down Expand Up @@ -21074,6 +21059,20 @@ GRANT SELECT(draft_table_of_contents_has_changes) ON TABLE public.projects TO an
GRANT SELECT(table_of_contents_last_published) ON TABLE public.projects TO anon;


--
-- Name: COLUMN projects.hide_forums; Type: ACL; Schema: public; Owner: -
--

GRANT UPDATE(hide_forums) ON TABLE public.projects TO seasketch_user;


--
-- Name: COLUMN projects.hide_sketches; Type: ACL; Schema: public; Owner: -
--

GRANT UPDATE(hide_sketches) ON TABLE public.projects TO seasketch_user;


--
-- Name: FUNCTION create_project(name text, slug text, OUT project public.projects); Type: ACL; Schema: public; Owner: -
--
Expand Down Expand Up @@ -22885,13 +22884,6 @@ REVOKE ALL ON FUNCTION public.hmac(bytea, bytea, text) FROM PUBLIC;
REVOKE ALL ON FUNCTION public.hmac(text, text, text) FROM PUBLIC;


--
-- Name: FUNCTION id_lookup_get_key(key integer); Type: ACL; Schema: public; Owner: -
--

REVOKE ALL ON FUNCTION public.id_lookup_get_key(key integer) FROM PUBLIC;


--
-- Name: FUNCTION id_lookup_get_key(lookup jsonb, key integer); Type: ACL; Schema: public; Owner: -
--
Expand Down
146 changes: 114 additions & 32 deletions packages/client/src/admin/Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import {
useUpdateOfflineEnabledMutation,
useProjectHostingQuotaQuery,
useUpdateDataHostingQuotaMutation,
useUpdateHideSketchesMutation,
useUpdateHideForumsMutation,
} from "../generated/graphql";
import ProjectAutosaveInput from "./ProjectAutosaveInput";
import { useDropzone } from "react-dropzone";
Expand Down Expand Up @@ -63,7 +65,7 @@ export default function Settings() {
}, [setHeaderState]);
return (
<>
<div className="pt-2 pb-6 md:py-6 max-h-full overflow-y-auto">
<div className="pt-2 pb-6 md:py-6 max-h-full overflow-y-auto space-y-4">
<div className="mx-auto max-w-3xl px-4 sm:px-6 md:px-8">
{data && data.project && (
<BasicSettingsForm {...data.project} url={data.project.url!} />
Expand All @@ -72,6 +74,9 @@ export default function Settings() {
<div className="mx-auto max-w-3xl px-4 sm:px-6 md:px-8">
<AccessControlSettings />
</div>
<div className="mx-auto max-w-3xl px-4 sm:px-6 md:px-8">
{data && data.project && <HiddenContentSettings projectId={data.project.id} hideForums={data.project.hideForums} hideSketches={data.project.hideSketches} />}
</div>
<div className="mx-auto max-w-3xl px-4 sm:px-6 md:px-8">
<MapboxAPIKeys />
</div>
Expand Down Expand Up @@ -119,7 +124,7 @@ function BasicSettingsForm(props: {
}, [copiedToClipboard]);

return (
<div className="mt-5 md:mt-0 md:col-span-2">
<div className=" md:mt-0 md:col-span-2">
<form action="#" method="POST">
<div className="shadow sm:rounded-md sm:overflow-hidden">
<div className="px-4 py-5 bg-white sm:p-6">
Expand Down Expand Up @@ -224,9 +229,8 @@ function BasicSettingsForm(props: {
</svg>
</span>
<span
className={`text-primary-500 p-1 px-4 rounded-full text-xs absolute w-auto right-0 top-0 -mt-7 -mr-4 duration-500 transition-opacity ${
copiedToClipboard ? "opacity-100" : "opacity-0"
}`}
className={`text-primary-500 p-1 px-4 rounded-full text-xs absolute w-auto right-0 top-0 -mt-7 -mr-4 duration-500 transition-opacity ${copiedToClipboard ? "opacity-100" : "opacity-0"
}`}
>
{t("Copied URL")}
</span>
Expand All @@ -241,6 +245,88 @@ function BasicSettingsForm(props: {
);
}

function HiddenContentSettings(props: { hideSketches: boolean, hideForums: boolean, projectId: number }) {
const [hideSketches] = useUpdateHideSketchesMutation({
optimisticResponse: (data) => {
return {
__typename: "Mutation",
updateProject: {
__typename: "UpdateProjectPayload",
project: {
__typename: "Project",
id: data.projectId,
hideSketches: data.hidden,
},
}
}
}
}
);
const [hideForums] = useUpdateHideForumsMutation({
optimisticResponse: (data) => {
return {
__typename: "Mutation",
updateProject: {
__typename: "UpdateProjectPayload",
project: {
__typename: "Project",
id: data.projectId,
hideForums: data.hidden,
},
}
}
}
}
);
const { t } = useTranslation("admin");
return <div className="shadow sm:rounded-md sm:overflow-hidden">
<div className="px-4 py-5 bg-white sm:p-6">
<h3 className="text-lg font-medium leading-6 text-gray-900">
{t("Hidden Content")}
</h3>
<p className="mt-2 text-sm text-gray-500">
{t(
"If you are not using all the features of SeaSketch, as in the case of a data portal, you can hide these features from the homepage sidebar."
)}
</p>
<div className="text-base pt-4">
<InputBlock
input={
<Switch
isToggled={props.hideSketches}
onClick={() => {
hideSketches({
variables: {
projectId: props.projectId,
hidden: !props.hideSketches
}
})
}}
/>
}
title={t("Hide Sketching Tools")}
/>
<InputBlock
input={
<Switch
isToggled={props.hideForums}
onClick={() => {
hideForums({
variables: {
projectId: props.projectId,
hidden: !props.hideForums
}
})
}}
/>
}
title={t("Hide Discussion Forums")}
/>
</div>
</div>
</div>
}

function UploadLogoField(props: { slug: string; logoUrl?: string | null }) {
const [mutate, mutationState] = useUpdateProjectSettingsMutation();
const { t, i18n } = useTranslation("admin");
Expand All @@ -251,19 +337,18 @@ function UploadLogoField(props: { slug: string; logoUrl?: string | null }) {
slug: props.slug,
logoUrl: acceptedFiles[0],
},
}).catch((e) => {});
}).catch((e) => { });
}, []);
const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop });

return (
<>
<div
{...getRootProps()}
className={`-ml-1 mt-2 flex items-center ${
isDragActive
? "border-dashed border-2 rounded-lg border-gray-300 -ml-1.5 mt-1.5 -mb-0.5"
: ""
}`}
className={`-ml-1 mt-2 flex items-center ${isDragActive
? "border-dashed border-2 rounded-lg border-gray-300 -ml-1.5 mt-1.5 -mb-0.5"
: ""
}`}
>
<span className="h-16 w-16 overflow-hidden text-gray-400 flex items-center">
{props.logoUrl ? (
Expand Down Expand Up @@ -309,7 +394,7 @@ function UploadLogoField(props: { slug: string; logoUrl?: string | null }) {
logoUrl: e.target.files[0],
},
})
.catch((e) => {})
.catch((e) => { })
.then(() => {
target.value = "";
});
Expand Down Expand Up @@ -359,7 +444,7 @@ function AccessControlSettings() {
};
await mutate({
variables,
}).catch((e) => {});
}).catch((e) => { });
};

const toggleIsListed = async () => {
Expand All @@ -386,7 +471,7 @@ function AccessControlSettings() {
isListedOn === null ? data?.projectBySlug?.isListed : isListedOn;
return (
<>
<div className="mt-5">
<div className="">
<form action="#" method="POST">
<div className="shadow sm:rounded-md sm:overflow-hidden">
<div className="px-4 py-5 bg-white sm:p-6">
Expand Down Expand Up @@ -446,9 +531,8 @@ function AccessControlSettings() {
/>
</div>
<div
className={`ml-3 text-sm leading-5 ${
!showPublicOption && "opacity-50"
}`}
className={`ml-3 text-sm leading-5 ${!showPublicOption && "opacity-50"
}`}
>
<label
htmlFor="PUBLIC"
Expand All @@ -475,7 +559,7 @@ function AccessControlSettings() {
accessControl
? accessControl === "ADMINS_ONLY"
: data?.projectBySlug?.accessControl ===
"ADMINS_ONLY"
"ADMINS_ONLY"
}
type="radio"
className="form-radio h-4 w-4 text-primary-500 focus:ring focus:ring-blue-200 transition duration-150 ease-in-out"
Expand Down Expand Up @@ -507,7 +591,7 @@ function AccessControlSettings() {
accessControl
? accessControl === "INVITE_ONLY"
: data?.projectBySlug?.accessControl ===
"INVITE_ONLY"
"INVITE_ONLY"
}
type="radio"
className="form-radio h-4 w-4 text-primary-500 transition duration-150 focus:ring focus:ring-blue-200 ease-in-out"
Expand Down Expand Up @@ -679,7 +763,7 @@ function MapExtentSettings() {

return (
<>
<div className="mt-5 relative">
<div className=" relative">
<div className="shadow sm:rounded-md sm:overflow-hidden">
<div className="px-4 py-5 bg-white sm:p-6">
<h3 className="text-lg font-medium leading-6 text-gray-900">
Expand All @@ -698,9 +782,8 @@ function MapExtentSettings() {
ref={(el) => (mapContainer.current = el)}
></div>
<button
className={`${
drawing ? "hidden" : ""
} sm:absolute sm:top-28 mt-2 sm:mt-0 sm:left-10 cursor-pointer inline-flex items-center px-4 py-2 border border-gray-400 text-sm leading-5 font-medium rounded-md text-gray-700 bg-white hover:text-gray-500 focus:ring focus:ring-blue-200 active:text-gray-800 active:bg-gray-50 transition ease-in-out duration-150`}
className={`${drawing ? "hidden" : ""
} sm:absolute sm:top-28 mt-2 sm:mt-0 sm:left-10 cursor-pointer inline-flex items-center px-4 py-2 border border-gray-400 text-sm leading-5 font-medium rounded-md text-gray-700 bg-white hover:text-gray-500 focus:ring focus:ring-blue-200 active:text-gray-800 active:bg-gray-50 transition ease-in-out duration-150`}
onClick={onRedrawBounds}
>
{t("Redraw Bounds")}
Expand Down Expand Up @@ -755,12 +838,12 @@ function SuperUserSettings() {
slug,
isFeatured: featured,
},
}).catch((e) => {});
}).catch((e) => { });
};

return (
<>
<div className="mt-5">
<div className="">
<form action="#" method="POST">
<div className="shadow sm:rounded-md sm:overflow-hidden">
<div className="px-4 py-5 bg-white sm:p-6 space-y-5">
Expand Down Expand Up @@ -852,13 +935,12 @@ function SuperUserSettings() {
<span>{t("Data Hosting Quota")}</span>
{quotaQuery.data?.projectBySlug?.dataHostingQuota ? (
<span
className={` ml-5 ${
quotaQuery.data.projectBySlug.dataHostingQuota *
0.9 <=
className={` ml-5 ${quotaQuery.data.projectBySlug.dataHostingQuota *
0.9 <=
quotaQuery.data.projectBySlug.dataHostingQuotaUsed
? "text-red-800"
: "text-gray-500"
}`}
? "text-red-800"
: "text-gray-500"
}`}
>
{bytes(
parseInt(
Expand Down Expand Up @@ -965,7 +1047,7 @@ function MapboxAPIKeys() {
}

return (
<div className="mt-5 md:col-span-2" id="mapbox-tokens">
<div className=" md:col-span-2" id="mapbox-tokens">
<div className="shadow sm:rounded-md sm:overflow-hidden">
<div className="px-4 py-5 bg-white sm:p-6 space-y-4">
<h3 className="text-lg font-medium leading-6 text-gray-900 mb-5">
Expand Down
Loading

0 comments on commit 7ba3b24

Please sign in to comment.