From 5e5fd99396cb55042ef49f7ddaec23df59134c3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carina=20Akaia=20=F0=9F=A6=BE=F0=9F=A6=8A=F0=9F=AA=90?= =?UTF-8?q?=F0=9F=9A=80=20root=2Eakaia=28=20=2Enear=20=7C=20=2Eeth=20=29?= Date: Thu, 20 Jul 2023 10:27:22 +0400 Subject: [PATCH 01/23] chore: Format --- .../kanban-board-editor.jsx | 66 ++++++++++--------- 1 file changed, 34 insertions(+), 32 deletions(-) diff --git a/src/gigs-board/feature/github-integration/kanban-board-editor.jsx b/src/gigs-board/feature/github-integration/kanban-board-editor.jsx index a966fd3e5..979e59d59 100644 --- a/src/gigs-board/feature/github-integration/kanban-board-editor.jsx +++ b/src/gigs-board/feature/github-integration/kanban-board-editor.jsx @@ -101,37 +101,37 @@ const useForm = ({ initialValues, stateKey: formStateKey, uninitialized }) => { hasUnsubmittedChanges: false, })); - const formUpdate = ({ path, via: customFieldUpdate, ...params }) => ( - fieldInput - ) => { - const updatedValues = Struct.deepFieldUpdate( - formState?.values ?? {}, - - { - input: fieldInput?.target?.value ?? fieldInput, - params, - path, - - via: - typeof customFieldUpdate === "function" - ? customFieldUpdate - : defaultFieldUpdate, - } - ); + const formUpdate = + ({ path, via: customFieldUpdate, ...params }) => + (fieldInput) => { + const updatedValues = Struct.deepFieldUpdate( + formState?.values ?? {}, + + { + input: fieldInput?.target?.value ?? fieldInput, + params, + path, + + via: + typeof customFieldUpdate === "function" + ? customFieldUpdate + : defaultFieldUpdate, + } + ); - State.update((lastKnownComponentState) => ({ - ...lastKnownComponentState, + State.update((lastKnownComponentState) => ({ + ...lastKnownComponentState, - [formStateKey]: { - hasUnsubmittedChanges: !Struct.isEqual( - updatedValues, - initialFormState.values - ), + [formStateKey]: { + hasUnsubmittedChanges: !Struct.isEqual( + updatedValues, + initialFormState.values + ), - values: updatedValues, - }, - })); - }; + values: updatedValues, + }, + })); + }; if ( !uninitialized && @@ -419,10 +419,12 @@ const GithubKanbanBoardEditor = ({ communityHandle, pageURL }) => { } : lastKnownValue; - const columnsDeleteById = (id) => ({ lastKnownValue }) => - Object.fromEntries( - Object.entries(lastKnownValue).filter(([columnId]) => columnId !== id) - ); + const columnsDeleteById = + (id) => + ({ lastKnownValue }) => + Object.fromEntries( + Object.entries(lastKnownValue).filter(([columnId]) => columnId !== id) + ); const onSubmit = () => DevHub.edit_community_github({ From 2d24951ae42d5e9395171e71bb55d5d39aa6a998 Mon Sep 17 00:00:00 2001 From: "Carina.Akaia.near" Date: Tue, 17 Oct 2023 00:45:50 +0400 Subject: [PATCH 02/23] wip: Create admin page --- src/gigs-board/pages/admin.jsx | 151 +++++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 src/gigs-board/pages/admin.jsx diff --git a/src/gigs-board/pages/admin.jsx b/src/gigs-board/pages/admin.jsx new file mode 100644 index 000000000..ec7254e06 --- /dev/null +++ b/src/gigs-board/pages/admin.jsx @@ -0,0 +1,151 @@ +/* INCLUDE: "common.jsx" */ +const nearDevGovGigsContractAccountId = + props.nearDevGovGigsContractAccountId || + (context.widgetSrc ?? "devgovgigs.near").split("/", 1)[0]; + +const nearDevGovGigsWidgetsAccountId = + props.nearDevGovGigsWidgetsAccountId || + (context.widgetSrc ?? "devgovgigs.near").split("/", 1)[0]; + +function widget(widgetName, widgetProps, key) { + widgetProps = { + ...widgetProps, + nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId, + nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId, + referral: props.referral, + }; + + return ( + + ); +} + +function href(widgetName, linkProps) { + linkProps = { ...linkProps }; + + if (props.nearDevGovGigsContractAccountId) { + linkProps.nearDevGovGigsContractAccountId = + props.nearDevGovGigsContractAccountId; + } + + if (props.nearDevGovGigsWidgetsAccountId) { + linkProps.nearDevGovGigsWidgetsAccountId = + props.nearDevGovGigsWidgetsAccountId; + } + + if (props.referral) { + linkProps.referral = props.referral; + } + + const linkPropsQuery = Object.entries(linkProps) + .filter(([_key, nullable]) => (nullable ?? null) !== null) + .map(([key, value]) => `${key}=${value}`) + .join("&"); + + return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${ + linkPropsQuery ? "?" : "" + }${linkPropsQuery}`; +} +/* END_INCLUDE: "common.jsx" */ +/* INCLUDE: "core/adapter/dev-hub" */ +const devHubAccountId = + props.nearDevGovGigsContractAccountId || + (context.widgetSrc ?? "devgovgigs.near").split("/", 1)[0]; + +const DevHub = { + get_root_members: () => + Near.view(devHubAccountId, "get_root_members") ?? null, + + has_moderator: ({ account_id }) => + Near.view(devHubAccountId, "has_moderator", { account_id }) ?? null, + + create_community: ({ inputs }) => + Near.call(devHubAccountId, "create_community", { inputs }), + + get_community: ({ handle }) => + Near.view(devHubAccountId, "get_community", { handle }) ?? null, + + get_account_community_permissions: ({ account_id, community_handle }) => + Near.view(devHubAccountId, "get_account_community_permissions", { + account_id, + community_handle, + }) ?? null, + + update_community: ({ handle, community }) => + Near.call(devHubAccountId, "update_community", { handle, community }), + + delete_community: ({ handle }) => + Near.call(devHubAccountId, "delete_community", { handle }), + + update_community_board: ({ handle, board }) => + Near.call(devHubAccountId, "update_community_board", { handle, board }), + + update_community_github: ({ handle, github }) => + Near.call(devHubAccountId, "update_community_github", { handle, github }), + + get_access_control_info: () => + Near.view(devHubAccountId, "get_access_control_info") ?? null, + + get_all_authors: () => Near.view(devHubAccountId, "get_all_authors") ?? null, + + get_all_communities_metadata: () => + Near.view(devHubAccountId, "get_all_communities_metadata") ?? null, + + get_all_labels: () => Near.view(devHubAccountId, "get_all_labels") ?? null, + + get_post: ({ post_id }) => + Near.view(devHubAccountId, "get_post", { post_id }) ?? null, + + get_posts_by_author: ({ author }) => + Near.view(devHubAccountId, "get_posts_by_author", { author }) ?? null, + + get_posts_by_label: ({ label }) => + Near.view(nearDevGovGigsContractAccountId, "get_posts_by_label", { + label, + }) ?? null, + + useQuery: (name, params) => { + const initialState = { data: null, error: null, isLoading: true }; + + const cacheState = useCache( + () => + Near.asyncView(devHubAccountId, ["get", name].join("_"), params ?? {}) + .then((response) => ({ + ...initialState, + data: response ?? null, + isLoading: false, + })) + .catch((error) => ({ + ...initialState, + error: props?.error ?? error, + isLoading: false, + })), + + JSON.stringify({ name, params }), + { subscribe: true } + ); + + return cacheState === null ? initialState : cacheState; + }, +}; +/* END_INCLUDE: "core/adapter/dev-hub" */ + +export const AdminPage = () => { + const featuredCommunities = DevHub.useQuery("featured_communities"); + + console.log(featuredCommunities); + + return widget("components.template.app-layout", { + children: ( +
+ <> +
+ ), + }); +}; + +return AdminPage(props); From ba5b11ad78b16e046fc3e96b8ce7811f0bc7fd43 Mon Sep 17 00:00:00 2001 From: "Carina.Akaia.near" Date: Tue, 17 Oct 2023 01:09:27 +0400 Subject: [PATCH 03/23] wip: Add navigation link to the admin page --- .../components/organism/app-header.jsx | 9 +++++++- .../components/template/app-layout.jsx | 4 ++-- src/gigs-board/pages/admin.jsx | 22 ++++++++++++++++++- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/gigs-board/components/organism/app-header.jsx b/src/gigs-board/components/organism/app-header.jsx index 65b0a9d1f..9e8ae3ba1 100644 --- a/src/gigs-board/components/organism/app-header.jsx +++ b/src/gigs-board/components/organism/app-header.jsx @@ -63,7 +63,7 @@ const Header = styled.div` } `; -const AppHeader = ({ path }) => ( +const AppHeader = ({ path, viewerRole }) => (
@@ -83,6 +83,13 @@ const AppHeader = ({ path }) => ( ) : null} + {!(path ?? []).some(({ pageId }) => pageId === "admin") && + !viewerRole.isDevHubModerator ? ( + + Admin + + ) : null} + ( +const AppLayout = ({ banner, children, path, viewerRole }) => (
- {widget("components.organism.app-header", { path })} + {widget("components.organism.app-header", { path, viewerRole })} {banner}
{children}
diff --git a/src/gigs-board/pages/admin.jsx b/src/gigs-board/pages/admin.jsx index ec7254e06..c1071a9bd 100644 --- a/src/gigs-board/pages/admin.jsx +++ b/src/gigs-board/pages/admin.jsx @@ -133,13 +133,33 @@ const DevHub = { }, }; /* END_INCLUDE: "core/adapter/dev-hub" */ +/* INCLUDE: "entity/viewer" */ +const Viewer = { + communityPermissions: ({ handle }) => + DevHub.get_account_community_permissions({ + account_id: context.accountId, + community_handle: handle, + }) ?? { + can_configure: false, + can_delete: false, + }, + + role: { + isDevHubModerator: + DevHub.has_moderator({ account_id: context.accountId }) ?? false, + }, +}; +/* END_INCLUDE: "entity/viewer" */ -export const AdminPage = () => { +const AdminPage = () => { const featuredCommunities = DevHub.useQuery("featured_communities"); console.log(featuredCommunities); return widget("components.template.app-layout", { + path: [{ label: "Administration", pageId: "admin" }], + viewerRole: Viewer.role, + children: (
<> From 69272991bd21faa863a554ed003b6dd4e8e1c261 Mon Sep 17 00:00:00 2001 From: "Carina.Akaia.near" Date: Tue, 17 Oct 2023 01:17:09 +0400 Subject: [PATCH 04/23] wip --- src/gigs-board/pages/admin.jsx | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/gigs-board/pages/admin.jsx b/src/gigs-board/pages/admin.jsx index c1071a9bd..b4360bffc 100644 --- a/src/gigs-board/pages/admin.jsx +++ b/src/gigs-board/pages/admin.jsx @@ -154,15 +154,25 @@ const Viewer = { const AdminPage = () => { const featuredCommunities = DevHub.useQuery("featured_communities"); - console.log(featuredCommunities); - return widget("components.template.app-layout", { path: [{ label: "Administration", pageId: "admin" }], viewerRole: Viewer.role, children: (
- <> + {widget("components.atom.spinner", { + isHidden: !( + featuredCommunities.data === null && featuredCommunities.isLoading + ), + })} + +
+

Featured communities

+ + {(featuredCommunities.data ?? []).map(({ name }) => ( +
{name}
+ ))} +
), }); From 700058d0dbfcfddff9afd307f26f8f776dfe78a2 Mon Sep 17 00:00:00 2001 From: "Carina.Akaia.near" Date: Wed, 18 Oct 2023 12:25:11 +0400 Subject: [PATCH 05/23] wip --- src/gigs-board/components/molecule/tile.jsx | 18 ++++--- .../components/organism/app-header.jsx | 4 +- .../components/template/app-layout.jsx | 4 +- src/gigs-board/pages/admin.jsx | 51 +++++++++++++++---- src/gigs-board/pages/communities.jsx | 6 +-- 5 files changed, 59 insertions(+), 24 deletions(-) diff --git a/src/gigs-board/components/molecule/tile.jsx b/src/gigs-board/components/molecule/tile.jsx index 6cdece662..8c7ff5a3f 100644 --- a/src/gigs-board/components/molecule/tile.jsx +++ b/src/gigs-board/components/molecule/tile.jsx @@ -27,6 +27,13 @@ const AttractableImage = styled.img` `; /* END_INCLUDE: "core/lib/gui/attractable" */ +const TileRoot = ({ children, noFrame, ...otherProps }) => + noFrame ? ( +
{children}
+ ) : ( + {children} + ); + const Tile = ({ children, borderRadius, @@ -42,7 +49,7 @@ const Tile = ({ minHeight, style, }) => ( - {
@@ -81,7 +85,7 @@ const Tile = ({ } {children} - + ); return Tile(props); diff --git a/src/gigs-board/components/organism/app-header.jsx b/src/gigs-board/components/organism/app-header.jsx index 9e8ae3ba1..25a54ec7f 100644 --- a/src/gigs-board/components/organism/app-header.jsx +++ b/src/gigs-board/components/organism/app-header.jsx @@ -63,7 +63,7 @@ const Header = styled.div` } `; -const AppHeader = ({ path, viewerRole }) => ( +const AppHeader = ({ path, viewer }) => (
@@ -84,7 +84,7 @@ const AppHeader = ({ path, viewerRole }) => ( ) : null} {!(path ?? []).some(({ pageId }) => pageId === "admin") && - !viewerRole.isDevHubModerator ? ( + viewer.role.isDevHubModerator ? ( Admin diff --git a/src/gigs-board/components/template/app-layout.jsx b/src/gigs-board/components/template/app-layout.jsx index 8a869fe94..795c8edd4 100644 --- a/src/gigs-board/components/template/app-layout.jsx +++ b/src/gigs-board/components/template/app-layout.jsx @@ -52,9 +52,9 @@ function href(widgetName, linkProps) { } /* END_INCLUDE: "common.jsx" */ -const AppLayout = ({ banner, children, path, viewerRole }) => ( +const AppLayout = ({ banner, children, path, viewer }) => (
- {widget("components.organism.app-header", { path, viewerRole })} + {widget("components.organism.app-header", { path, viewer })} {banner}
{children}
diff --git a/src/gigs-board/pages/admin.jsx b/src/gigs-board/pages/admin.jsx index b4360bffc..bf7725add 100644 --- a/src/gigs-board/pages/admin.jsx +++ b/src/gigs-board/pages/admin.jsx @@ -151,28 +151,59 @@ const Viewer = { }; /* END_INCLUDE: "entity/viewer" */ +const AdministrationSettings = { + communities: { + maxFeatured: 4, + }, +}; + +const CommunityFeaturingSchema = { + handle: { label: "Community handle", type: "text", required: true }, +}; + const AdminPage = () => { - const featuredCommunities = DevHub.useQuery("featured_communities"); + const featuredCommunitiesMeta = DevHub.useQuery( + "featured_communities_metadata" + ); return widget("components.template.app-layout", { path: [{ label: "Administration", pageId: "admin" }], - viewerRole: Viewer.role, + viewer: Viewer, children: (
{widget("components.atom.spinner", { isHidden: !( - featuredCommunities.data === null && featuredCommunities.isLoading + featuredCommunitiesMeta.data === null && + featuredCommunitiesMeta.isLoading ), })} -
-

Featured communities

- - {(featuredCommunities.data ?? []).map(({ name }) => ( -
{name}
- ))} -
+ {widget("components.molecule.tile", { + heading: "Featured communities", + + isHidden: + featuredCommunitiesMeta.data === null && + featuredCommunitiesMeta.isLoading, + + noBorder: true, + noFrame: true, + + children: ( + <> + {(featuredCommunitiesMeta.data ?? []).map((metadata) => + widget("entity.community.card", { format: "small", metadata }) + )} + + {widget("components.organism.configurator", { + heading: "Add community", + isActive: true, + isUnlocked: true, // Viewer.role.isDevHubModerator, + schema: CommunityFeaturingSchema, + })} + + ), + })}
), }); diff --git a/src/gigs-board/pages/communities.jsx b/src/gigs-board/pages/communities.jsx index c78ead930..5b04ae540 100644 --- a/src/gigs-board/pages/communities.jsx +++ b/src/gigs-board/pages/communities.jsx @@ -143,7 +143,7 @@ const CommunitiesPage = () => { isSpawnerHidden: !(forcedState ?? lastKnownState.isSpawnerHidden), })); - const communitiesMetadata = DevHub.useQuery("all_communities_metadata"); + const communitiesMeta = DevHub.useQuery("all_communities_metadata"); return widget("components.template.app-layout", { path: [{ label: "Communities", pageId: "communities", isHidden: true }], @@ -180,7 +180,7 @@ const CommunitiesPage = () => {
{widget("components.atom.spinner", { isHidden: !( - communitiesMetadata.data === null && communitiesMetadata.isLoading + communitiesMeta.data === null && communitiesMeta.isLoading ), })} @@ -189,7 +189,7 @@ const CommunitiesPage = () => { onCancel: () => spawnerToggle(false), })} - {(communitiesMetadata.data ?? []) + {(communitiesMeta.data ?? []) .reverse() .map((communityMetadata) => widget( From 1062edca5ec63136d779f5850a012d17c4c83e90 Mon Sep 17 00:00:00 2001 From: "Carina.Akaia.near" Date: Wed, 18 Oct 2023 18:24:56 +0400 Subject: [PATCH 06/23] wip --- src/gigs-board/components/molecule/button.jsx | 12 ++++- src/gigs-board/entity/community/card.jsx | 21 +++++--- src/gigs-board/pages/admin.jsx | 49 ++++++++++++++----- 3 files changed, 62 insertions(+), 20 deletions(-) diff --git a/src/gigs-board/components/molecule/button.jsx b/src/gigs-board/components/molecule/button.jsx index 43f4d5095..997e6c93c 100644 --- a/src/gigs-board/components/molecule/button.jsx +++ b/src/gigs-board/components/molecule/button.jsx @@ -109,6 +109,10 @@ const styles = ` line-height: 1.5; text-decoration: none !important; + &.vertical { + padding: 1.2rem 0.5rem !important; + } + &:not(.shadow-none) { box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075) !important; transition: box-shadow 0.6s; @@ -241,7 +245,13 @@ const Button = ({ > {Struct.typeMatch(iconProps) && widget("components.atom.icon", iconProps)} - + {label} diff --git a/src/gigs-board/entity/community/card.jsx b/src/gigs-board/entity/community/card.jsx index a41906bf8..894edaa0f 100644 --- a/src/gigs-board/entity/community/card.jsx +++ b/src/gigs-board/entity/community/card.jsx @@ -81,6 +81,7 @@ const AttractableImage = styled.img` /* END_INCLUDE: "core/lib/gui/attractable" */ const CommunityCard = ({ + actions, format, isBannerEnabled, metadata, @@ -92,12 +93,10 @@ const CommunityCard = ({ const link = href("community.activity", { handle: metadata.handle }); const formatSmall = ( - -
-
- + + + {actions} + ); const formatMedium = ( diff --git a/src/gigs-board/pages/admin.jsx b/src/gigs-board/pages/admin.jsx index bf7725add..3affe2703 100644 --- a/src/gigs-board/pages/admin.jsx +++ b/src/gigs-board/pages/admin.jsx @@ -158,14 +158,25 @@ const AdministrationSettings = { }; const CommunityFeaturingSchema = { - handle: { label: "Community handle", type: "text", required: true }, + handle: { label: "Community handle", required: true }, }; const AdminPage = () => { - const featuredCommunitiesMeta = DevHub.useQuery( - "featured_communities_metadata" + const featuredCommunities = DevHub.useQuery("featured_communities"), + featuredCommunityList = featuredCommunities.data ?? []; + + const featuredCommunityHandles = featuredCommunityList.map( + ({ handle }) => handle ); + const addFeaturedCommunity = ({ handle }) => { + console.log(handle); + }; + + const removeFeaturedCommunity = ({ handle }) => { + console.log(handle); + }; + return widget("components.template.app-layout", { path: [{ label: "Administration", pageId: "admin" }], viewer: Viewer, @@ -174,8 +185,7 @@ const AdminPage = () => {
{widget("components.atom.spinner", { isHidden: !( - featuredCommunitiesMeta.data === null && - featuredCommunitiesMeta.isLoading + featuredCommunities.data === null && featuredCommunities.isLoading ), })} @@ -183,23 +193,40 @@ const AdminPage = () => { heading: "Featured communities", isHidden: - featuredCommunitiesMeta.data === null && - featuredCommunitiesMeta.isLoading, + featuredCommunities.data === null && featuredCommunities.isLoading, noBorder: true, noFrame: true, children: ( <> - {(featuredCommunitiesMeta.data ?? []).map((metadata) => - widget("entity.community.card", { format: "small", metadata }) - )} +
+ {featuredCommunityList.map((community) => + widget("entity.community.card", { + actions: ( +
+ {widget("components.molecule.button", { + classNames: { root: "btn-outline-danger vertical" }, + icon: { type: "bootstrap_icon", variant: "bi-x-lg" }, + title: "Remove from featured", + onClick: () => removeFeaturedCommunity(community), + })} +
+ ), + + format: "small", + metadata: community, + target: "_blank", + }) + )} +
{widget("components.organism.configurator", { - heading: "Add community", + heading: "Add featured community", isActive: true, isUnlocked: true, // Viewer.role.isDevHubModerator, schema: CommunityFeaturingSchema, + onClick: addFeaturedCommunity, })} ), From e8871cbcd9cbd4772c12387e5ab32d6b5b5349ca Mon Sep 17 00:00:00 2001 From: "Carina.Akaia.near" Date: Wed, 18 Oct 2023 18:32:41 +0400 Subject: [PATCH 07/23] wip --- src/gigs-board/pages/admin.jsx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/gigs-board/pages/admin.jsx b/src/gigs-board/pages/admin.jsx index 3affe2703..11a04e8bb 100644 --- a/src/gigs-board/pages/admin.jsx +++ b/src/gigs-board/pages/admin.jsx @@ -224,6 +224,13 @@ const AdminPage = () => { {widget("components.organism.configurator", { heading: "Add featured community", isActive: true, + + // isHidden: !( + // Viewer.role.isDevHubModerator && + // featuredCommunityList.length < + // AdministrationSettings.communities.maxFeatured + // ), + isUnlocked: true, // Viewer.role.isDevHubModerator, schema: CommunityFeaturingSchema, onClick: addFeaturedCommunity, From 27471280c1977a5f6a9bc73007949c79f7ac5e35 Mon Sep 17 00:00:00 2001 From: "Carina.Akaia.near" Date: Thu, 19 Oct 2023 15:51:42 +0400 Subject: [PATCH 08/23] wip --- src/gigs-board/pages/admin.jsx | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/gigs-board/pages/admin.jsx b/src/gigs-board/pages/admin.jsx index 11a04e8bb..f74091dd3 100644 --- a/src/gigs-board/pages/admin.jsx +++ b/src/gigs-board/pages/admin.jsx @@ -158,7 +158,10 @@ const AdministrationSettings = { }; const CommunityFeaturingSchema = { - handle: { label: "Community handle", required: true }, + handle: { + label: "Community handle", + inputProps: { min: 3, max: 40, required: true }, + }, }; const AdminPage = () => { @@ -169,13 +172,15 @@ const AdminPage = () => { ({ handle }) => handle ); - const addFeaturedCommunity = ({ handle }) => { - console.log(handle); - }; + const addFeaturedCommunity = ({ handle }) => + Near.call(devHubAccountId, "set_featured_communities", { + handles: new Set(featuredCommunityHandles).add(handle).values().toArray(), + }); - const removeFeaturedCommunity = ({ handle }) => { - console.log(handle); - }; + const removeFeaturedCommunity = ({ handle: input }) => + Near.call(devHubAccountId, "set_featured_communities", { + handles: featuredCommunityHandles.filter((handle) => handle !== input), + }); return widget("components.template.app-layout", { path: [{ label: "Administration", pageId: "admin" }], @@ -184,17 +189,12 @@ const AdminPage = () => { children: (
{widget("components.atom.spinner", { - isHidden: !( - featuredCommunities.data === null && featuredCommunities.isLoading - ), + isHidden: !featuredCommunities.isLoading, })} {widget("components.molecule.tile", { heading: "Featured communities", - - isHidden: - featuredCommunities.data === null && featuredCommunities.isLoading, - + isHidden: featuredCommunities.isLoading, noBorder: true, noFrame: true, @@ -233,7 +233,7 @@ const AdminPage = () => { isUnlocked: true, // Viewer.role.isDevHubModerator, schema: CommunityFeaturingSchema, - onClick: addFeaturedCommunity, + onSubmit: addFeaturedCommunity, })} ), From 1866a1a87b91fd24700dd68d2e945c2a5d7b76ec Mon Sep 17 00:00:00 2001 From: "Carina.Akaia.near" Date: Thu, 19 Oct 2023 16:17:01 +0400 Subject: [PATCH 09/23] Apply permission control logic --- src/gigs-board/pages/admin.jsx | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/gigs-board/pages/admin.jsx b/src/gigs-board/pages/admin.jsx index f74091dd3..da7a17d6f 100644 --- a/src/gigs-board/pages/admin.jsx +++ b/src/gigs-board/pages/admin.jsx @@ -208,6 +208,7 @@ const AdminPage = () => { {widget("components.molecule.button", { classNames: { root: "btn-outline-danger vertical" }, icon: { type: "bootstrap_icon", variant: "bi-x-lg" }, + isHidden: !Viewer.role.isDevHubModerator, title: "Remove from featured", onClick: () => removeFeaturedCommunity(community), })} @@ -225,13 +226,13 @@ const AdminPage = () => { heading: "Add featured community", isActive: true, - // isHidden: !( - // Viewer.role.isDevHubModerator && - // featuredCommunityList.length < - // AdministrationSettings.communities.maxFeatured - // ), + isHidden: !( + Viewer.role.isDevHubModerator && + featuredCommunityList.length < + AdministrationSettings.communities.maxFeatured + ), - isUnlocked: true, // Viewer.role.isDevHubModerator, + isUnlocked: Viewer.role.isDevHubModerator, schema: CommunityFeaturingSchema, onSubmit: addFeaturedCommunity, })} From c8d7cf2acc53e9e416c053417be973380eba37bc Mon Sep 17 00:00:00 2001 From: "Carina.Akaia.near" Date: Thu, 19 Oct 2023 16:28:25 +0400 Subject: [PATCH 10/23] Apply permission control logic --- src/gigs-board/pages/admin.jsx | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/gigs-board/pages/admin.jsx b/src/gigs-board/pages/admin.jsx index da7a17d6f..54465e3ed 100644 --- a/src/gigs-board/pages/admin.jsx +++ b/src/gigs-board/pages/admin.jsx @@ -186,6 +186,17 @@ const AdminPage = () => { path: [{ label: "Administration", pageId: "admin" }], viewer: Viewer, + banner: Viewer.role.isDevHubModerator ? null : ( +
+

+ Your account does not have administration permissions. +

+
+ ), + children: (
{widget("components.atom.spinner", { @@ -194,7 +205,10 @@ const AdminPage = () => { {widget("components.molecule.tile", { heading: "Featured communities", - isHidden: featuredCommunities.isLoading, + + isHidden: + featuredCommunities.isLoading || !Viewer.role.isDevHubModerator, + noBorder: true, noFrame: true, @@ -208,7 +222,6 @@ const AdminPage = () => { {widget("components.molecule.button", { classNames: { root: "btn-outline-danger vertical" }, icon: { type: "bootstrap_icon", variant: "bi-x-lg" }, - isHidden: !Viewer.role.isDevHubModerator, title: "Remove from featured", onClick: () => removeFeaturedCommunity(community), })} @@ -226,13 +239,11 @@ const AdminPage = () => { heading: "Add featured community", isActive: true, - isHidden: !( - Viewer.role.isDevHubModerator && - featuredCommunityList.length < - AdministrationSettings.communities.maxFeatured - ), + isHidden: + featuredCommunityList.length >= + AdministrationSettings.communities.maxFeatured, - isUnlocked: Viewer.role.isDevHubModerator, + isUnlocked: true, schema: CommunityFeaturingSchema, onSubmit: addFeaturedCommunity, })} From e8547fafbd13b3c625516b0a34582b664354bd41 Mon Sep 17 00:00:00 2001 From: "Carina.Akaia.near" Date: Fri, 20 Oct 2023 16:31:14 +0400 Subject: [PATCH 11/23] Apply post-QA amendments --- .../components/organism/app-header.jsx | 156 ++++++++++-------- .../components/organism/configurator.jsx | 24 ++- src/gigs-board/pages/admin.jsx | 14 +- 3 files changed, 114 insertions(+), 80 deletions(-) diff --git a/src/gigs-board/components/organism/app-header.jsx b/src/gigs-board/components/organism/app-header.jsx index 25a54ec7f..5e12129e5 100644 --- a/src/gigs-board/components/organism/app-header.jsx +++ b/src/gigs-board/components/organism/app-header.jsx @@ -63,82 +63,98 @@ const Header = styled.div` } `; -const AppHeader = ({ path, viewer }) => ( -
-
- - - - - {widget("components.molecule.breadcrumbs", { - classNames: { link: "fs-5" }, - path, - })} -
- -
- {!(path ?? []).some(({ pageId }) => pageId === "communities") ? ( - +const AppHeader = ({ path, viewer }) => { + console.log(JSON.stringify(viewer, undefined, 2)); + + return ( +
+
+ + + + + {widget("components.molecule.breadcrumbs", { + classNames: { link: "fs-5" }, + path, + })} +
+ + -
-); +
+ ); +}; return AppHeader(props); diff --git a/src/gigs-board/components/organism/configurator.jsx b/src/gigs-board/components/organism/configurator.jsx index df7d019bc..71ea74536 100644 --- a/src/gigs-board/components/organism/configurator.jsx +++ b/src/gigs-board/components/organism/configurator.jsx @@ -239,7 +239,20 @@ const defaultFieldsRender = ({ schema, form, isEditable, isUnlocked }) => ( <> {Object.entries(schema).map( ( - [key, { format, inputProps, noop, label, order, style, ...fieldProps }], + [ + key, + { + format, + hints, + inputProps, + noop, + label, + order, + style, + title, + ...fieldProps + }, + ], idx ) => { const fieldKey = `${idx}-${key}`, @@ -314,10 +327,9 @@ const defaultFieldsRender = ({ schema, form, isEditable, isUnlocked }) => ( ...(inputProps ?? {}), disabled: isDisabled, - title: - noop ?? false - ? "Temporarily disabled due to technical reasons." - : inputProps.title, + title: isDisabled + ? hints.disabled + : hints.default ?? inputProps.title, ...(fieldParamsByType[fieldType].inputProps ?? {}), tabIndex: order, @@ -421,7 +433,7 @@ const Configurator = ({
{fieldsRender({ form, - isEditable: isUnlocked && isActive, + isEditable: isActive, isUnlocked, schema, })} diff --git a/src/gigs-board/pages/admin.jsx b/src/gigs-board/pages/admin.jsx index 54465e3ed..9ca5058e1 100644 --- a/src/gigs-board/pages/admin.jsx +++ b/src/gigs-board/pages/admin.jsx @@ -160,6 +160,11 @@ const AdministrationSettings = { const CommunityFeaturingSchema = { handle: { label: "Community handle", + + hints: { + disabled: `You can only add ${AdministrationSettings.communities.maxFeatured} communities at a time`, + }, + inputProps: { min: 3, max: 40, required: true }, }, }; @@ -174,7 +179,9 @@ const AdminPage = () => { const addFeaturedCommunity = ({ handle }) => Near.call(devHubAccountId, "set_featured_communities", { - handles: new Set(featuredCommunityHandles).add(handle).values().toArray(), + handles: Array.from( + new Set(featuredCommunityHandles).add(handle).values() + ), }); const removeFeaturedCommunity = ({ handle: input }) => @@ -239,11 +246,10 @@ const AdminPage = () => { heading: "Add featured community", isActive: true, - isHidden: - featuredCommunityList.length >= + isUnlocked: + featuredCommunityList.length < AdministrationSettings.communities.maxFeatured, - isUnlocked: true, schema: CommunityFeaturingSchema, onSubmit: addFeaturedCommunity, })} From eeb9719f2694d9eceae9b95231c31f1d925d0efc Mon Sep 17 00:00:00 2001 From: "Carina.Akaia.near" Date: Tue, 24 Oct 2023 04:36:14 +0400 Subject: [PATCH 12/23] chore: Format --- src/gigs-board/components/organism/app-header.jsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/gigs-board/components/organism/app-header.jsx b/src/gigs-board/components/organism/app-header.jsx index 5e12129e5..c528cde69 100644 --- a/src/gigs-board/components/organism/app-header.jsx +++ b/src/gigs-board/components/organism/app-header.jsx @@ -83,6 +83,7 @@ const AppHeader = ({ path, viewer }) => { pageId === "communities") ? "d-none" : "", @@ -95,6 +96,7 @@ const AppHeader = ({ path, viewer }) => { pageId === "admin") && viewer.role.isDevHubModerator ? "" From 2f6b36c3a7c60df77a2284a4affc47fb4c52a862 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 31 Oct 2023 13:12:42 +0200 Subject: [PATCH 13/23] move changes to devhub directory --- src/app.jsx | 8 ++ src/devhub/components/atom/Spinner.jsx | 27 ++++ src/devhub/components/molecule/Button.jsx | 14 +- src/devhub/components/templates/AppLayout.jsx | 5 + src/devhub/entity/community/Card.jsx | 17 +-- src/devhub/page/admin.jsx | 136 ++++++++++++++++++ 6 files changed, 197 insertions(+), 10 deletions(-) create mode 100644 src/devhub/components/atom/Spinner.jsx create mode 100644 src/devhub/page/admin.jsx diff --git a/src/app.jsx b/src/app.jsx index fbd9c061e..4816a0bd3 100644 --- a/src/app.jsx +++ b/src/app.jsx @@ -112,6 +112,14 @@ function Page() { /> ); } + case "admin": { + return ( + + ); + } default: { // TODO: 404 page return

404

; diff --git a/src/devhub/components/atom/Spinner.jsx b/src/devhub/components/atom/Spinner.jsx new file mode 100644 index 000000000..a10dd43ac --- /dev/null +++ b/src/devhub/components/atom/Spinner.jsx @@ -0,0 +1,27 @@ +const Spinner = ({ classNames, isHidden }) => ( +
+
+ +
+ Loading... +
+ +
+
+); + +return Spinner(props); diff --git a/src/devhub/components/molecule/Button.jsx b/src/devhub/components/molecule/Button.jsx index dc77a210f..f429a6c9f 100644 --- a/src/devhub/components/molecule/Button.jsx +++ b/src/devhub/components/molecule/Button.jsx @@ -103,6 +103,10 @@ const styles = ` &.btn-outline-info { --bs-btn-disabled-color: #6c757d8f; } + + &.vertical { + padding: 1.2rem 0.5rem !important; + } `; const rootElementByType = (type) => @@ -120,7 +124,7 @@ const Button = ({ classNames, icon: iconProps, label, type, ...restProps }) => { return ( { props={iconProps} /> )} - + {label} diff --git a/src/devhub/components/templates/AppLayout.jsx b/src/devhub/components/templates/AppLayout.jsx index 741771f15..c256b14ac 100644 --- a/src/devhub/components/templates/AppLayout.jsx +++ b/src/devhub/components/templates/AppLayout.jsx @@ -96,6 +96,11 @@ const AppHeader = ({ page }) => { )} + {(page !== "admin" && viewer.role.isDevHubModerator) || + (true && ( + Admin + ))} +
{ const renderFormat = @@ -19,12 +20,10 @@ const CommunityCard = ({ }); const formatSmall = ( - -
Community logo
-
- + + {actions} +
); const formatMedium = ( diff --git a/src/devhub/page/admin.jsx b/src/devhub/page/admin.jsx new file mode 100644 index 000000000..2b09876a6 --- /dev/null +++ b/src/devhub/page/admin.jsx @@ -0,0 +1,136 @@ +context.accountId = "theori.near"; // TODO + +const { useQuery, hasModerator } = VM.require( + "${REPL_DEVHUB}/widget/core.adapter.devhub-contract" +); + +const { Tile } = + VM.require("${REPL_DEVHUB}/widget/devhub.components.molecule.Tile") || + (() => <>); + +const { href } = VM.require("${REPL_DEVHUB}/widget/core.lib.url"); + +if (!useQuery || !hasModerator || !href) { + return

Loading modules...

; +} + +const AdministrationSettings = { + communities: { + maxFeatured: 4, + }, +}; + +const CommunityFeaturingSchema = { + handle: { + label: "Community handle", + + hints: { + disabled: `You can only add ${AdministrationSettings.communities.maxFeatured} communities at a time`, + }, + + inputProps: { min: 3, max: 40, required: true }, + }, +}; + +const featuredCommunities = useQuery("featured_communities"); +const featuredCommunityList = featuredCommunities.data ?? []; +const isDevHubModerator = hasModerator({ + account_id: context.accountId, +}); + +const noPermissionBanner = ( +
+

+ Your account does not have administration permissions. +

+
+); + +if (!isDevHubModerator) { + return noPermissionBanner; +} + +const featuredCommunityHandles = featuredCommunityList.map( + ({ handle }) => handle +); + +const addFeaturedCommunity = ({ handle }) => + Near.call(devHubAccountId, "set_featured_communities", { + handles: Array.from(new Set(featuredCommunityHandles).add(handle).values()), + }); + +const removeFeaturedCommunity = ({ handle: input }) => + Near.call(devHubAccountId, "set_featured_communities", { + handles: featuredCommunityHandles.filter((handle) => handle !== input), + }); + +return ( +
+ + {!featuredCommunities.isLoading && ( + <> +
+ {featuredCommunityList.map((community) => ( + + removeFeaturedCommunity(community), + }} + /> +
+ ), + + format: "small", + metadata: community, + target: "_blank", + }} + /> + ))} +
+ + + + + + )} +
+); From 62d0db186f16c42f15a7dead4b7fc86a05fbe044 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 31 Oct 2023 13:15:24 +0200 Subject: [PATCH 14/23] fix: remove theori.near from account.context --- src/devhub/page/admin.jsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/devhub/page/admin.jsx b/src/devhub/page/admin.jsx index 2b09876a6..830f5fbaf 100644 --- a/src/devhub/page/admin.jsx +++ b/src/devhub/page/admin.jsx @@ -1,5 +1,3 @@ -context.accountId = "theori.near"; // TODO - const { useQuery, hasModerator } = VM.require( "${REPL_DEVHUB}/widget/core.adapter.devhub-contract" ); From 16f9a7dc5aef1f18d7d62af378da97ddabed4d40 Mon Sep 17 00:00:00 2001 From: "Carina.Akaia.near" Date: Tue, 31 Oct 2023 19:06:51 +0400 Subject: [PATCH 15/23] wip --- src/gigs-board/pages/admin.jsx | 264 --------------------------------- 1 file changed, 264 deletions(-) delete mode 100644 src/gigs-board/pages/admin.jsx diff --git a/src/gigs-board/pages/admin.jsx b/src/gigs-board/pages/admin.jsx deleted file mode 100644 index 9ca5058e1..000000000 --- a/src/gigs-board/pages/admin.jsx +++ /dev/null @@ -1,264 +0,0 @@ -/* INCLUDE: "common.jsx" */ -const nearDevGovGigsContractAccountId = - props.nearDevGovGigsContractAccountId || - (context.widgetSrc ?? "devgovgigs.near").split("/", 1)[0]; - -const nearDevGovGigsWidgetsAccountId = - props.nearDevGovGigsWidgetsAccountId || - (context.widgetSrc ?? "devgovgigs.near").split("/", 1)[0]; - -function widget(widgetName, widgetProps, key) { - widgetProps = { - ...widgetProps, - nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId, - nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId, - referral: props.referral, - }; - - return ( - - ); -} - -function href(widgetName, linkProps) { - linkProps = { ...linkProps }; - - if (props.nearDevGovGigsContractAccountId) { - linkProps.nearDevGovGigsContractAccountId = - props.nearDevGovGigsContractAccountId; - } - - if (props.nearDevGovGigsWidgetsAccountId) { - linkProps.nearDevGovGigsWidgetsAccountId = - props.nearDevGovGigsWidgetsAccountId; - } - - if (props.referral) { - linkProps.referral = props.referral; - } - - const linkPropsQuery = Object.entries(linkProps) - .filter(([_key, nullable]) => (nullable ?? null) !== null) - .map(([key, value]) => `${key}=${value}`) - .join("&"); - - return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${ - linkPropsQuery ? "?" : "" - }${linkPropsQuery}`; -} -/* END_INCLUDE: "common.jsx" */ -/* INCLUDE: "core/adapter/dev-hub" */ -const devHubAccountId = - props.nearDevGovGigsContractAccountId || - (context.widgetSrc ?? "devgovgigs.near").split("/", 1)[0]; - -const DevHub = { - get_root_members: () => - Near.view(devHubAccountId, "get_root_members") ?? null, - - has_moderator: ({ account_id }) => - Near.view(devHubAccountId, "has_moderator", { account_id }) ?? null, - - create_community: ({ inputs }) => - Near.call(devHubAccountId, "create_community", { inputs }), - - get_community: ({ handle }) => - Near.view(devHubAccountId, "get_community", { handle }) ?? null, - - get_account_community_permissions: ({ account_id, community_handle }) => - Near.view(devHubAccountId, "get_account_community_permissions", { - account_id, - community_handle, - }) ?? null, - - update_community: ({ handle, community }) => - Near.call(devHubAccountId, "update_community", { handle, community }), - - delete_community: ({ handle }) => - Near.call(devHubAccountId, "delete_community", { handle }), - - update_community_board: ({ handle, board }) => - Near.call(devHubAccountId, "update_community_board", { handle, board }), - - update_community_github: ({ handle, github }) => - Near.call(devHubAccountId, "update_community_github", { handle, github }), - - get_access_control_info: () => - Near.view(devHubAccountId, "get_access_control_info") ?? null, - - get_all_authors: () => Near.view(devHubAccountId, "get_all_authors") ?? null, - - get_all_communities_metadata: () => - Near.view(devHubAccountId, "get_all_communities_metadata") ?? null, - - get_all_labels: () => Near.view(devHubAccountId, "get_all_labels") ?? null, - - get_post: ({ post_id }) => - Near.view(devHubAccountId, "get_post", { post_id }) ?? null, - - get_posts_by_author: ({ author }) => - Near.view(devHubAccountId, "get_posts_by_author", { author }) ?? null, - - get_posts_by_label: ({ label }) => - Near.view(nearDevGovGigsContractAccountId, "get_posts_by_label", { - label, - }) ?? null, - - useQuery: (name, params) => { - const initialState = { data: null, error: null, isLoading: true }; - - const cacheState = useCache( - () => - Near.asyncView(devHubAccountId, ["get", name].join("_"), params ?? {}) - .then((response) => ({ - ...initialState, - data: response ?? null, - isLoading: false, - })) - .catch((error) => ({ - ...initialState, - error: props?.error ?? error, - isLoading: false, - })), - - JSON.stringify({ name, params }), - { subscribe: true } - ); - - return cacheState === null ? initialState : cacheState; - }, -}; -/* END_INCLUDE: "core/adapter/dev-hub" */ -/* INCLUDE: "entity/viewer" */ -const Viewer = { - communityPermissions: ({ handle }) => - DevHub.get_account_community_permissions({ - account_id: context.accountId, - community_handle: handle, - }) ?? { - can_configure: false, - can_delete: false, - }, - - role: { - isDevHubModerator: - DevHub.has_moderator({ account_id: context.accountId }) ?? false, - }, -}; -/* END_INCLUDE: "entity/viewer" */ - -const AdministrationSettings = { - communities: { - maxFeatured: 4, - }, -}; - -const CommunityFeaturingSchema = { - handle: { - label: "Community handle", - - hints: { - disabled: `You can only add ${AdministrationSettings.communities.maxFeatured} communities at a time`, - }, - - inputProps: { min: 3, max: 40, required: true }, - }, -}; - -const AdminPage = () => { - const featuredCommunities = DevHub.useQuery("featured_communities"), - featuredCommunityList = featuredCommunities.data ?? []; - - const featuredCommunityHandles = featuredCommunityList.map( - ({ handle }) => handle - ); - - const addFeaturedCommunity = ({ handle }) => - Near.call(devHubAccountId, "set_featured_communities", { - handles: Array.from( - new Set(featuredCommunityHandles).add(handle).values() - ), - }); - - const removeFeaturedCommunity = ({ handle: input }) => - Near.call(devHubAccountId, "set_featured_communities", { - handles: featuredCommunityHandles.filter((handle) => handle !== input), - }); - - return widget("components.template.app-layout", { - path: [{ label: "Administration", pageId: "admin" }], - viewer: Viewer, - - banner: Viewer.role.isDevHubModerator ? null : ( -
-

- Your account does not have administration permissions. -

-
- ), - - children: ( -
- {widget("components.atom.spinner", { - isHidden: !featuredCommunities.isLoading, - })} - - {widget("components.molecule.tile", { - heading: "Featured communities", - - isHidden: - featuredCommunities.isLoading || !Viewer.role.isDevHubModerator, - - noBorder: true, - noFrame: true, - - children: ( - <> -
- {featuredCommunityList.map((community) => - widget("entity.community.card", { - actions: ( -
- {widget("components.molecule.button", { - classNames: { root: "btn-outline-danger vertical" }, - icon: { type: "bootstrap_icon", variant: "bi-x-lg" }, - title: "Remove from featured", - onClick: () => removeFeaturedCommunity(community), - })} -
- ), - - format: "small", - metadata: community, - target: "_blank", - }) - )} -
- - {widget("components.organism.configurator", { - heading: "Add featured community", - isActive: true, - - isUnlocked: - featuredCommunityList.length < - AdministrationSettings.communities.maxFeatured, - - schema: CommunityFeaturingSchema, - onSubmit: addFeaturedCommunity, - })} - - ), - })} -
- ), - }); -}; - -return AdminPage(props); From b66ed9e70979aff4901680acfd317b44224f116c Mon Sep 17 00:00:00 2001 From: "Carina.Akaia.near" Date: Wed, 1 Nov 2023 01:47:01 +0400 Subject: [PATCH 16/23] wip: Create API binding for `set_featured_communities` --- src/core/adapter/devhub-contract.jsx | 4 ++++ src/devhub/page/admin.jsx | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/core/adapter/devhub-contract.jsx b/src/core/adapter/devhub-contract.jsx index fbbac46d9..d43aae52f 100644 --- a/src/core/adapter/devhub-contract.jsx +++ b/src/core/adapter/devhub-contract.jsx @@ -25,6 +25,9 @@ function getFeaturedCommunities() { ); } +const setFeaturedCommunities = ({ handles }) => + Near.call(devHubAccountId, "set_featured_communities", { handles }); + function getAccountCommunityPermissions({ account_id, community_handle }) { return ( Near.view("${REPL_DEVHUB_CONTRACT}", "get_account_community_permissions", { @@ -237,6 +240,7 @@ return { createCommunity, getCommunity, getFeaturedCommunities, + setFeaturedCommunities, getAccountCommunityPermissions, updateCommunity, deleteCommunity, diff --git a/src/devhub/page/admin.jsx b/src/devhub/page/admin.jsx index 830f5fbaf..2bd1f96dc 100644 --- a/src/devhub/page/admin.jsx +++ b/src/devhub/page/admin.jsx @@ -1,4 +1,4 @@ -const { useQuery, hasModerator } = VM.require( +const { useQuery, hasModerator, setFeaturedCommunities } = VM.require( "${REPL_DEVHUB}/widget/core.adapter.devhub-contract" ); @@ -56,12 +56,12 @@ const featuredCommunityHandles = featuredCommunityList.map( ); const addFeaturedCommunity = ({ handle }) => - Near.call(devHubAccountId, "set_featured_communities", { + setFeaturedCommunities({ handles: Array.from(new Set(featuredCommunityHandles).add(handle).values()), }); const removeFeaturedCommunity = ({ handle: input }) => - Near.call(devHubAccountId, "set_featured_communities", { + setFeaturedCommunities({ handles: featuredCommunityHandles.filter((handle) => handle !== input), }); From 63c8abf5c475b45ea0ee9f78e5df1097d79f7228 Mon Sep 17 00:00:00 2001 From: "Carina.Akaia.near" Date: Wed, 1 Nov 2023 02:02:14 +0400 Subject: [PATCH 17/23] fix: Turn `useQuery` subscription back on --- src/core/adapter/devhub-contract.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/adapter/devhub-contract.jsx b/src/core/adapter/devhub-contract.jsx index d43aae52f..1ebbfe31c 100644 --- a/src/core/adapter/devhub-contract.jsx +++ b/src/core/adapter/devhub-contract.jsx @@ -228,7 +228,7 @@ function useQuery(name, params) { })), JSON.stringify({ name, params }), - { subscribe: false } // NOTE: I'm turning off subscribe to stop the constant re-rendering + { subscribe: true } ); return cacheState === null ? initialState : cacheState; From 1fcfae0840a831ab8b7abaf5331a6233db09085d Mon Sep 17 00:00:00 2001 From: "Carina.Akaia.near" Date: Tue, 7 Nov 2023 08:22:14 +0400 Subject: [PATCH 18/23] Target `devhub.near` account with bos-loader --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 125a64c52..e0a2461ec 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "fmt:check": "prettier --check '**/*.{js,jsx,ts,tsx,json}'", "build": "npm run fmt && node ./module/include.js", "dev:testnet": "./scripts/dev.sh", - "dev:mainnet": "./scripts/dev.sh -a devgovgigs.near -c devgovgigs.near -n mainnet", + "dev:mainnet": "./scripts/dev.sh -a devhub.near -c devhub.near -n mainnet", "build:preview": "node ./scripts/build-preview.mjs", "dev": "npm run dev:mainnet", "test": "npx playwright test" From 395ff08d3d761b9c8b8b45334d480a1fba6e2175 Mon Sep 17 00:00:00 2001 From: "Carina.Akaia.near" Date: Tue, 7 Nov 2023 11:52:35 +0400 Subject: [PATCH 19/23] wip: Declare admin route --- src/app.jsx | 8 ++++++++ src/devhub/page/admin.jsx | 1 + 2 files changed, 9 insertions(+) diff --git a/src/app.jsx b/src/app.jsx index 9c50fed30..caa4d0151 100644 --- a/src/app.jsx +++ b/src/app.jsx @@ -162,6 +162,14 @@ function Page() { /> ); } + case "admin": { + return ( + + ); + } default: { // TODO: 404 page diff --git a/src/devhub/page/admin.jsx b/src/devhub/page/admin.jsx index 2bd1f96dc..e7412b164 100644 --- a/src/devhub/page/admin.jsx +++ b/src/devhub/page/admin.jsx @@ -73,6 +73,7 @@ return ( isHidden: !featuredCommunities.isLoading, }} /> + {!featuredCommunities.isLoading && ( <>
From 2853f750376cc45c8df7cea2c459b0eb19220a57 Mon Sep 17 00:00:00 2001 From: "Carina.Akaia.near" Date: Thu, 9 Nov 2023 12:19:25 +0400 Subject: [PATCH 20/23] Fix widget account id for bos-loader --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 125a64c52..a1e4c3f8e 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "fmt:check": "prettier --check '**/*.{js,jsx,ts,tsx,json}'", "build": "npm run fmt && node ./module/include.js", "dev:testnet": "./scripts/dev.sh", - "dev:mainnet": "./scripts/dev.sh -a devgovgigs.near -c devgovgigs.near -n mainnet", + "dev:mainnet": "./scripts/dev.sh -a devhub.near -c devgovgigs.near -n mainnet", "build:preview": "node ./scripts/build-preview.mjs", "dev": "npm run dev:mainnet", "test": "npx playwright test" From 91650636234ef4b6eb6073fd72814c8fc60b0bba Mon Sep 17 00:00:00 2001 From: "Carina.Akaia.near" Date: Thu, 16 Nov 2023 22:16:47 +0400 Subject: [PATCH 21/23] Apply design amendments --- src/devhub/page/admin.jsx | 66 ++++++++++++--------------------------- 1 file changed, 20 insertions(+), 46 deletions(-) diff --git a/src/devhub/page/admin.jsx b/src/devhub/page/admin.jsx index e7412b164..f13296d2c 100644 --- a/src/devhub/page/admin.jsx +++ b/src/devhub/page/admin.jsx @@ -14,18 +14,13 @@ if (!useQuery || !hasModerator || !href) { const AdministrationSettings = { communities: { - maxFeatured: 4, + maxFeatured: 5, }, }; const CommunityFeaturingSchema = { handle: { - label: "Community handle", - - hints: { - disabled: `You can only add ${AdministrationSettings.communities.maxFeatured} communities at a time`, - }, - + label: "Pinned handle", inputProps: { min: 3, max: 40, required: true }, }, }; @@ -55,15 +50,14 @@ const featuredCommunityHandles = featuredCommunityList.map( ({ handle }) => handle ); -const addFeaturedCommunity = ({ handle }) => - setFeaturedCommunities({ - handles: Array.from(new Set(featuredCommunityHandles).add(handle).values()), - }); - -const removeFeaturedCommunity = ({ handle: input }) => - setFeaturedCommunities({ - handles: featuredCommunityHandles.filter((handle) => handle !== input), - }); +const replaceFeaturedCommunity = + ({ handle: targetHandle }) => + ({ handle: replacementHandle }) => + setFeaturedCommunities({ + handles: featuredCommunityHandles.map((handle) => + handle === targetHandle ? replacementHandle : handle + ), + }); return (
@@ -76,6 +70,8 @@ return ( {!featuredCommunities.isLoading && ( <> +

Featured communities

+
{featuredCommunityList.map((community) => ( removeFeaturedCommunity(community), + externalState: community, + isActive: true, + isUnlocked: true, + cancelLabel: "Reset", + onSubmit: replaceFeaturedCommunity(community), + submitLabel: "Replace", + schema: CommunityFeaturingSchema, }} />
@@ -109,26 +103,6 @@ return ( /> ))}
- - - - )}
From c99ef8e1fb265976c519f90976f360ae5c34b0cd Mon Sep 17 00:00:00 2001 From: "Carina.Akaia.near" Date: Thu, 16 Nov 2023 22:23:24 +0400 Subject: [PATCH 22/23] Rollback irrelevant changes --- src/devhub/components/molecule/Button.jsx | 158 ++++++++++------------ src/devhub/entity/community/Tile.jsx | 18 +-- src/devhub/page/admin.jsx | 4 - 3 files changed, 81 insertions(+), 99 deletions(-) diff --git a/src/devhub/components/molecule/Button.jsx b/src/devhub/components/molecule/Button.jsx index 3efce3ee2..6126467dd 100644 --- a/src/devhub/components/molecule/Button.jsx +++ b/src/devhub/components/molecule/Button.jsx @@ -1,41 +1,41 @@ const styles = ` - padding: 0.5rem 1.2rem !important; - min-height: 36px; - line-height: 1.5; - text-decoration: none !important; - - &:not(.shadow-none) { - box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075) !important; - transition: box-shadow 0.6s; - } - - &.btn-sm { - padding: 0.5rem 0.8rem !important; - min-height: 32px; - line-height: 1; - } - - &.btn-lg { - padding: 1rem 1.5rem !important; - min-height: 48px; - } - - &.btn-primary { - border: none; - --bs-btn-color: #ffffff; - --bs-btn-bg: #087990; - --bs-btn-border-color: #087990; - --bs-btn-hover-color: #ffffff; - --bs-btn-hover-bg: #055160; - --bs-btn-hover-border-color: #055160; - --bs-btn-focus-shadow-rgb: 49, 132, 253; - --bs-btn-active-color: #ffffff; - --bs-btn-active-bg: #055160; - --bs-btn-active-border-color: #055160; - --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); - --bs-btn-disabled-color: #ffffff; - --bs-btn-disabled-bg: #0551604a; - } + padding: 0.5rem 1.2rem !important; + min-height: 36px; + line-height: 1.5; + text-decoration: none !important; + + &:not(.shadow-none) { + box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075) !important; + transition: box-shadow 0.6s; + } + + &.btn-sm { + padding: 0.5rem 0.8rem !important; + min-height: 32px; + line-height: 1; + } + + &.btn-lg { + padding: 1rem 1.5rem !important; + min-height: 48px; + } + + &.btn-primary { + border: none; + --bs-btn-color: #ffffff; + --bs-btn-bg: #087990; + --bs-btn-border-color: #087990; + --bs-btn-hover-color: #ffffff; + --bs-btn-hover-bg: #055160; + --bs-btn-hover-border-color: #055160; + --bs-btn-focus-shadow-rgb: 49, 132, 253; + --bs-btn-active-color: #ffffff; + --bs-btn-active-bg: #055160; + --bs-btn-active-border-color: #055160; + --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --bs-btn-disabled-color: #ffffff; + --bs-btn-disabled-bg: #0551604a; + } &.btn-outline-primary { --bs-btn-color: #087990; @@ -51,57 +51,53 @@ const styles = ` --bs-btn-disabled-border-color: #0551604a; } - &[class*="btn-outline-"] { - border-width: 2px; - } - - &.btn-outline-primary { - --bs-btn-disabled-color: #6c757d8f; - } + &[class*="btn-outline-"] { + border-width: 2px; + } - &.btn-secondary { - border: none; - } + &.btn-outline-primary { + --bs-btn-disabled-color: #6c757d8f; + } - &.btn-outline-secondary { - --bs-btn-disabled-color: #6c757d8f; - } + &.btn-secondary { + border: none; + } - &.btn-success { - border: none; - --bs-btn-disabled-bg: #35482a4a; - } + &.btn-outline-secondary { + --bs-btn-disabled-color: #6c757d8f; + } - &.btn-outline-success { - --bs-btn-disabled-color: #6c757d8f; - } + &.btn-success { + border: none; + --bs-btn-disabled-bg: #35482a4a; + } - &.btn-danger { - border: none; - } + &.btn-outline-success { + --bs-btn-disabled-color: #6c757d8f; + } - &.btn-outline-danger { - --bs-btn-disabled-color: #6c757d8f; - } + &.btn-danger { + border: none; + } - &.btn-warning { - border: none; - } + &.btn-outline-danger { + --bs-btn-disabled-color: #6c757d8f; + } - &.btn-outline-warning { - --bs-btn-disabled-color: #6c757d8f; - } + &.btn-warning { + border: none; + } - &.btn-info { - border: none; - } + &.btn-outline-warning { + --bs-btn-disabled-color: #6c757d8f; + } - &.btn-outline-info { - --bs-btn-disabled-color: #6c757d8f; - } + &.btn-info { + border: none; + } - &.vertical { - padding: 1.2rem 0.5rem !important; + &.btn-outline-info { + --bs-btn-disabled-color: #6c757d8f; } `; @@ -142,13 +138,7 @@ const Button = ({ props={iconProps} /> )} - + {label} diff --git a/src/devhub/entity/community/Tile.jsx b/src/devhub/entity/community/Tile.jsx index 9b812c63a..7e5a0b472 100644 --- a/src/devhub/entity/community/Tile.jsx +++ b/src/devhub/entity/community/Tile.jsx @@ -27,13 +27,6 @@ const AttractableImage = styled.img` `; /* END_INCLUDE: "core/lib/gui/attractable" */ -const TileRoot = ({ children, noFrame, ...otherProps }) => - noFrame ? ( -
{children}
- ) : ( - {children} - ); - const Tile = ({ children, borderRadius, @@ -49,7 +42,7 @@ const Tile = ({ minHeight, style, }) => ( - {
@@ -88,7 +84,7 @@ const Tile = ({ } {children} - + ); return Tile(props); diff --git a/src/devhub/page/admin.jsx b/src/devhub/page/admin.jsx index f13296d2c..2b70d4663 100644 --- a/src/devhub/page/admin.jsx +++ b/src/devhub/page/admin.jsx @@ -2,10 +2,6 @@ const { useQuery, hasModerator, setFeaturedCommunities } = VM.require( "${REPL_DEVHUB}/widget/core.adapter.devhub-contract" ); -const { Tile } = - VM.require("${REPL_DEVHUB}/widget/devhub.components.molecule.Tile") || - (() => <>); - const { href } = VM.require("${REPL_DEVHUB}/widget/core.lib.url"); if (!useQuery || !hasModerator || !href) { From 004af4d6ee8c51722f46fc29e48eb85fa6109680 Mon Sep 17 00:00:00 2001 From: "Carina.Akaia.near" Date: Thu, 16 Nov 2023 22:26:03 +0400 Subject: [PATCH 23/23] Rollback irrelevant changes --- src/devhub/components/molecule/Button.jsx | 148 +++++++++++----------- 1 file changed, 74 insertions(+), 74 deletions(-) diff --git a/src/devhub/components/molecule/Button.jsx b/src/devhub/components/molecule/Button.jsx index 6126467dd..11368b7cc 100644 --- a/src/devhub/components/molecule/Button.jsx +++ b/src/devhub/components/molecule/Button.jsx @@ -1,41 +1,41 @@ const styles = ` - padding: 0.5rem 1.2rem !important; - min-height: 36px; - line-height: 1.5; - text-decoration: none !important; - - &:not(.shadow-none) { - box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075) !important; - transition: box-shadow 0.6s; - } - - &.btn-sm { - padding: 0.5rem 0.8rem !important; - min-height: 32px; - line-height: 1; - } - - &.btn-lg { - padding: 1rem 1.5rem !important; - min-height: 48px; - } - - &.btn-primary { - border: none; - --bs-btn-color: #ffffff; - --bs-btn-bg: #087990; - --bs-btn-border-color: #087990; - --bs-btn-hover-color: #ffffff; - --bs-btn-hover-bg: #055160; - --bs-btn-hover-border-color: #055160; - --bs-btn-focus-shadow-rgb: 49, 132, 253; - --bs-btn-active-color: #ffffff; - --bs-btn-active-bg: #055160; - --bs-btn-active-border-color: #055160; - --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); - --bs-btn-disabled-color: #ffffff; - --bs-btn-disabled-bg: #0551604a; - } + padding: 0.5rem 1.2rem !important; + min-height: 36px; + line-height: 1.5; + text-decoration: none !important; + + &:not(.shadow-none) { + box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075) !important; + transition: box-shadow 0.6s; + } + + &.btn-sm { + padding: 0.5rem 0.8rem !important; + min-height: 32px; + line-height: 1; + } + + &.btn-lg { + padding: 1rem 1.5rem !important; + min-height: 48px; + } + + &.btn-primary { + border: none; + --bs-btn-color: #ffffff; + --bs-btn-bg: #087990; + --bs-btn-border-color: #087990; + --bs-btn-hover-color: #ffffff; + --bs-btn-hover-bg: #055160; + --bs-btn-hover-border-color: #055160; + --bs-btn-focus-shadow-rgb: 49, 132, 253; + --bs-btn-active-color: #ffffff; + --bs-btn-active-bg: #055160; + --bs-btn-active-border-color: #055160; + --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --bs-btn-disabled-color: #ffffff; + --bs-btn-disabled-bg: #0551604a; + } &.btn-outline-primary { --bs-btn-color: #087990; @@ -51,54 +51,54 @@ const styles = ` --bs-btn-disabled-border-color: #0551604a; } - &[class*="btn-outline-"] { - border-width: 2px; - } + &[class*="btn-outline-"] { + border-width: 2px; + } - &.btn-outline-primary { - --bs-btn-disabled-color: #6c757d8f; - } + &.btn-outline-primary { + --bs-btn-disabled-color: #6c757d8f; + } - &.btn-secondary { - border: none; - } + &.btn-secondary { + border: none; + } - &.btn-outline-secondary { - --bs-btn-disabled-color: #6c757d8f; - } + &.btn-outline-secondary { + --bs-btn-disabled-color: #6c757d8f; + } - &.btn-success { - border: none; - --bs-btn-disabled-bg: #35482a4a; - } + &.btn-success { + border: none; + --bs-btn-disabled-bg: #35482a4a; + } - &.btn-outline-success { - --bs-btn-disabled-color: #6c757d8f; - } + &.btn-outline-success { + --bs-btn-disabled-color: #6c757d8f; + } - &.btn-danger { - border: none; - } + &.btn-danger { + border: none; + } - &.btn-outline-danger { - --bs-btn-disabled-color: #6c757d8f; - } + &.btn-outline-danger { + --bs-btn-disabled-color: #6c757d8f; + } - &.btn-warning { - border: none; - } + &.btn-warning { + border: none; + } - &.btn-outline-warning { - --bs-btn-disabled-color: #6c757d8f; - } + &.btn-outline-warning { + --bs-btn-disabled-color: #6c757d8f; + } - &.btn-info { - border: none; - } + &.btn-info { + border: none; + } - &.btn-outline-info { - --bs-btn-disabled-color: #6c757d8f; - } + &.btn-outline-info { + --bs-btn-disabled-color: #6c757d8f; + } `; const rootElementByType = (type) =>