diff --git a/src/DevHub/entity/community/Activity.jsx b/src/DevHub/entity/community/Activity.jsx new file mode 100644 index 000000000..4c2e932b0 --- /dev/null +++ b/src/DevHub/entity/community/Activity.jsx @@ -0,0 +1,56 @@ +const { + nearDevGovGigsWidgetsAccountId, + nearDevGovGigsContractAccountId, + handle, +} = props; + +const { getCommunity } = VM.require( + `${nearDevGovGigsWidgetsAccountId}/widget/DevHub.modules.contract-sdk` +); + +const communityData = getCommunity(nearDevGovGigsContractAccountId, { handle }); + +if (communityData === null) { + return
Loading...
; +} + +return ( +
+
+
+ + Required tags: + + + +
+ +
+
+ +
+
+); diff --git a/src/DevHub/entity/community/BrandingConfigurator.jsx b/src/DevHub/entity/community/BrandingConfigurator.jsx index e35970822..1462dc382 100644 --- a/src/DevHub/entity/community/BrandingConfigurator.jsx +++ b/src/DevHub/entity/community/BrandingConfigurator.jsx @@ -76,21 +76,34 @@ const cidToURL = (cid) => `https://ipfs.near.social/ipfs/${cid}`; const { data, onSubmit, hasConfigurePermissions, link } = props; -State.init({ - banner: { cid: data.banner_url.split("/").at(-1) }, - logo: { cid: data.logo_url.split("/").at(-1) }, -}) - -// const [banner, setBanner] = useState(data.banner_url.split("/").at(-1)); -// const [logo, setLogo] = useState(data.logo_url.split("/").at(-1)); - -useEffect(() => { - // console.log(state.banner); - onSubmit({ - banner_url: cidToURL(state.banner.cid), - logo_url: cidToURL(state.logo.cid), +const initialInput = { banner: null, logo: null }; + + const initialValues = { + banner: { cid: data.banner_url.split("/").at(-1) }, + logo: { cid: data.logo_url.split("/").at(-1) }, + }; + + State.init({ + input: initialInput, }); -}, [state.logo, state.banner]); + + const hasUnsubmittedChanges = Object.values(state.input).some( + (value) => value !== null + ); + + const isSynced = state.input === initialValues; + + if (hasUnsubmittedChanges && !isSynced) { + onSubmit({ + banner_url: cidToURL(state.input.banner?.cid ?? initialValues.banner.cid), + logo_url: cidToURL(state.input.logo?.cid ?? initialValues.logo.cid), + }); + + State.update((lastKnownState) => ({ + ...lastKnownState, + input: initialInput, + })); + } return (
@@ -98,10 +111,12 @@ return ( alt="Community banner preview" className="card-img-top d-flex flex-column justify-content-end align-items-end p-4" style={{ - background: `center / cover no-repeat url(${cidToURL(state.banner.cid)})`, + background: `center / cover no-repeat url(${cidToURL( + initialValues.banner.cid + )})`, }} > - {hasConfigurePermissions && } + {hasConfigurePermissions && } - {hasConfigurePermissions && } + {hasConfigurePermissions && }
Loading...
; +} + +const UserList = ({ name, users }) => ( +
+ {(users ?? []).map((user, i) => ( +
+
+ {name + " #" + (i + 1)} +
+ +
+ + + +
+
+ ))} +
+); + +return ( +
+ +
+
+ Admins +
+
+ +
+ ), + }} + /> +
+); diff --git a/src/DevHub/modules/Struct.jsx b/src/DevHub/modules/utils.jsx similarity index 80% rename from src/DevHub/modules/Struct.jsx rename to src/DevHub/modules/utils.jsx index e53a4b9cd..0dc0879dd 100644 --- a/src/DevHub/modules/Struct.jsx +++ b/src/DevHub/modules/utils.jsx @@ -48,4 +48,15 @@ const Struct = { input !== null && typeof input === "object" && !Array.isArray(input), }; -return { Struct }; +function href({ gateway, widgetSrc, params }) { + params = Object.entries(params) + .filter(([_key, nullable]) => (nullable ?? null) !== null) + .map(([key, value]) => `${key}=${value}`) + .join("&"); + + return `${gateway ? `https://${gateway}` : ""}/${widgetSrc}/${ + params ? `?${params}` : "" + }`; +} + +return { href, Struct }; diff --git a/src/DevHub/pages/Communities.jsx b/src/DevHub/pages/Communities.jsx index 86831cadb..cf8fd8589 100644 --- a/src/DevHub/pages/Communities.jsx +++ b/src/DevHub/pages/Communities.jsx @@ -1,31 +1,28 @@ -const { - nearDevGovGigsWidgetsAccountId, - nearDevGovGigsContractAccountId, - createCommunity, -} = props; +const { nearDevGovGigsWidgetsAccountId, nearDevGovGigsContractAccountId } = + props; -const { getAllCommunitiesMetadata } = VM.require( +const { getAllCommunitiesMetadata, createCommunity } = VM.require( `${nearDevGovGigsWidgetsAccountId}/widget/DevHub.modules.contract-sdk` ); -if (!getAllCommunitiesMetadata) { +if (!getAllCommunitiesMetadata || !createCommunity) { return

Loading modules...

; } const { Struct } = VM.require( - `${nearDevGovGigsWidgetsAccountId}/widget/DevHub.modules.Struct` + `${nearDevGovGigsWidgetsAccountId}/widget/DevHub.modules.utils` ); if (!Struct) { return

Loading modules...

; } -const CommunityInputsDefaults = { +State.init({ handle: "", name: "", tag: "", description: "", -}; +}); const CommunityInputsPartialSchema = { handle: { @@ -114,20 +111,31 @@ const [showSpawner, setShowSpawner] = useState(false); const CommunitySpawner = () => ( setShowSpawner(false), + className: "p-3", + children: ( + setShowSpawner(false), + nearDevGovGigsWidgetsAccountId, + }} + /> + ), }} /> ); @@ -248,19 +256,20 @@ return ( Discover NEAR developer communities

- -
- setShowSpawner(!showSpawner), - className: "btn btn-primary", - label: "Create Community", - nearDevGovGigsWidgetsAccountId, - }} - /> -
+ {context.accountId && ( +
+ setShowSpawner(!showSpawner), + className: "btn btn-primary", + label: "Create Community", + nearDevGovGigsWidgetsAccountId, + }} + /> +
+ )} {/* // TODO: Align centers */}
diff --git a/src/DevHub/pages/community/configuration.jsx b/src/DevHub/pages/community/configuration.jsx index 10cc1f94b..1621d4c04 100644 --- a/src/DevHub/pages/community/configuration.jsx +++ b/src/DevHub/pages/community/configuration.jsx @@ -1,15 +1,10 @@ -// Pulls community data -// Cycles through the addons -// Creates a tile -// Supplies the onSubmit and data - const { nearDevGovGigsWidgetsAccountId, permissions, handle, community, - communityAddonConfigs, - availableAddons, + // communityAddonConfigs, Commenting out to reduce scope on root merge + // availableAddons, deleteCommunity, updateCommunity, } = props; @@ -19,6 +14,7 @@ const [selectedAddon, setSelectedAddon] = useState(null); const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false); const sectionSubmit = (sectionData) => { + console.log(sectionData); const updatedCommunityData = { ...Object.entries(sectionData).reduce( (update, [propertyKey, propertyValue]) => ({ @@ -79,21 +75,6 @@ function CommunityAddonConfigurator({ addonConfig }) { ); } -function handleCreateAddon(addonId, value) { - console.log(value); - // const uuid = UUID.generate("xxxxxxx"); - // addCommunityAddon({ - // handle, - // config: { - // name: "Wiki", - // config_id: uuid, - // addon_id: addonId, - // parameters: JSON.stringify(value), - // enabled: true, - // }, - // }); -} - return (
( ))} - {hasConfigurePermissions && ( + {/* {hasConfigurePermissions && ( - )} + )} */} {hasDeletePermissions && (
deleteCommunity({ handle }), + onClick: () => deleteCommunity(nearDevGovGigsContractAccountId, { handle }), }} />
diff --git a/src/DevHub/pages/community/index.jsx b/src/DevHub/pages/community/index.jsx index 83107f09b..bb02e9b41 100644 --- a/src/DevHub/pages/community/index.jsx +++ b/src/DevHub/pages/community/index.jsx @@ -37,6 +37,7 @@ const NavUnderline = styled.ul` const { nearDevGovGigsWidgetsAccountId, + nearDevGovGigsContractAccountId, handle, tab, permissions, @@ -45,6 +46,14 @@ const { availableAddons, } = props; +const { href } = VM.require( + `${nearDevGovGigsWidgetsAccountId}/widget/DevHub.modules.utils` +); + +if (!href) { + return <>; +} + if (!tab) { tab = "Activity"; } @@ -53,32 +62,50 @@ const [isLinkCopied, setLinkCopied] = useState(false); const tabs = [ { - iconClass: "bi bi-house-door", - viewer: "devgovgigs.near/widget/gigs-board.pages.community.activity", title: "Activity", + iconClass: "bi bi-house-door", + view: `${nearDevGovGigsWidgetsAccountId}/widget/DevHub.entity.community.Activity`, + params: { + handle, + }, }, - ...(communityAddonConfigs || []).map((addon) => ({ - title: addon.name, - route: availableAddons.find((it) => it.id === addon.config_id).viewer, - viewer: availableAddons.find((it) => it.id === addon.config_id).viewer, - iconClass: addon.icon, + { + title: "Teams", + iconClass: "bi bi-people-fill", + view: `${nearDevGovGigsWidgetsAccountId}/widget/DevHub.entity.community.Teams`, params: { - viewer: availableAddons.find((it) => it.id === addon.config_id).viewer, - data: addon.parameters || "", // @elliotBraem not sure which will work better I guess this is needed for the wiki data but we can also add another data object inside the addon's parameters - ...JSON.parse(addon.parameters), // this seems to work witht the wiki for now + handle, }, - })), + }, + + // Commenting the below out to reduce scope + + // ...(communityAddonConfigs || []).map((addon) => ({ + // title: addon.name, + // route: availableAddons.find((it) => it.id === addon.config_id).viewer, + // viewer: availableAddons.find((it) => it.id === addon.config_id).viewer, + // iconClass: addon.icon, + // params: { + // viewer: availableAddons.find((it) => it.id === addon.config_id).viewer, + // data: addon.parameters || "", // @elliotBraem not sure which will work better I guess this is needed for the wiki data but we can also add another data object inside the addon's parameters + // ...JSON.parse(addon.parameters), // this seems to work witht the wiki for now + // }, + // })), ]; const onShareClick = () => clipboard .writeText( - `https://near.org/${nearDevGovGigsWidgetsAccountId}/widget/DevHub.App?page=community?handle=${handle}` - ) // TODO: how should this be determined? + href({ + gateway: "near.org", + widgetSrc: `${nearDevGovGigsWidgetsAccountId}/widget/DevHub.App`, + params: { page: "community", handle }, + }) + ) .then(setLinkCopied(true)); -// TODO; -let currentTab = tabs.find((tab) => tab.title == props.tab); -console.log(currentTab); + +let currentTab = tabs.find((it) => it.title === tab); + return (
{community.name} {community.description} - {props.tab}
{permissions.can_configure && ( - + + + )}
- {tabs.map(({ defaultActive, params, route, title }) => - title ? ( -
  • - - {title} - -
  • - ) : null + {tabs.map( + ({ title }) => + title && ( +
  • + + {title} + +
  • + ) )}
    - {/* TODO: remove */} -
    {tabs.find((tab) => tab.viewer == props.tab)[0]}
    -
    {tabs.map((tab) => tab.viewer).join(",")}
    - +
    + {currentTab && ( + + )} +
    );