Search
Search

Transaction: CvEFgSR...FxBw

Signed by
Receiver
Status
Succeeded
Transaction Fee
0.00925 
Deposit Value
<0.00001 
Gas Used
92 Tgas
Attached Gas
300 Tgas
Created
June 16, 2023 at 7:28:28pm
Hash
CvEFgSRvMf9iWr9Ab2DqXKD5pC3Hhc9zo3qZQt98FxBw

Actions

Called method: 'set' in contract: social.near
Arguments:
{ "data": { "jgdev.near": { "widget": { "gigs-board.pages.Teams": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\nconst access_info =\n Near.view(nearDevGovGigsContractAccountId, \"get_access_control_info\") ?? null;\nconst root_members =\n Near.view(nearDevGovGigsContractAccountId, \"get_root_members\") ?? null;\n\nif (!access_info || !root_members) {\n return <div>Loading...</div>;\n}\n\nconst pageContent = (\n <div>\n {widget(\"components.teams.LabelsPermissions\", {\n rules: access_info.rules_list,\n })}\n {Object.keys(root_members).map((member) =>\n widget(\n \"components.teams.TeamInfo\",\n { member, members_list: access_info.members_list },\n member\n )\n )}\n </div>\n);\n\nreturn widget(\"components.layout.Page\", {\n children: pageContent,\n});\n" }, "DevGov.Notification.Item.Left": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\nif (!props.type) {\n return \"Loading ...\";\n}\n\nconst type = props.type.split(\"/\")[1];\nreturn props.type ? (\n <>\n {type == \"like\"\n ? \"liked your\"\n : type == \"reply\"\n ? \"replied to your\"\n : type == \"edit\"\n ? \"edited your\"\n : type == \"mention\"\n ? \"mentioned you in their\"\n : \"???\"}{\" \"}\n <a className=\"fw-bold text-muted\" href={href(\"Post\", { id: props.post })}>\n Developer Governance post\n </a>\n </>\n) : (\n \"Loading ...\"\n);\n" }, "gigs-board.pages.community.Sponsorship": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\n/* INCLUDE: \"shared/mocks\" */\nconst communities = {\n \"zero-knowledge\": {\n overviewId: 397,\n eventsId: 401,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreiajwq6ep3n7veddozji2djv5vviyisabhycbweslvpwhsoyuzcwi4\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreihgxg5kwts2juldaeasveyuddkm6tcabmrat2aaq5u6uyljtyt7lu\",\n\n title: \"Zero Knowledge\",\n desc: \"Building a zero knowledge ecosystem on NEAR.\",\n telegram: \"NearZeroKnowledge\",\n },\n\n protocol: {\n overviewId: 412,\n eventsId: 413,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreidpitdafcnhkp4uyomacypdgqvxr35jtfnbxa5s6crby7qjk2nv5a\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreicg4svzfz5nvllomsahndgm7u62za4sib4mmbygxzhpcl4htqwr4a\",\n\n title: \"Protocol\",\n desc: \"Supporting the ongoing innovation of the NEAR Protocol.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-protocol\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Protocol NEPs\",\n },\n },\n },\n },\n\n telegram: \"NEAR_Protocol_Community_Group\",\n },\n\n tooling: {\n overviewId: 416,\n eventsId: 417,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreie2eaj5czmpfe6pe53kojzcspgozebdsonffwvbxtpuipnwahybvi\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreiehzr7z2fhoqqmkt3z667wubccbch6sqtsnvd6msodyzpnf72cszy\",\n\n title: \"Tooling\",\n desc: \"Supporting the ongoing innovation of tooling.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-tools\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Tooling NEPs\",\n },\n },\n },\n },\n\n telegram: \"NEAR_Tools_Community_Group\",\n },\n\n \"contract-standards\": {\n overviewId: 414,\n eventsId: 415,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreiepgdnu7soc6xgbyd4adicbf3eyxiiwqawn6tguaix6aklfpir634\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreiaowjqxds24fwcliyriintjd4ucciprii2rdxjmxgi7f5dmzuscey\",\n\n title: \"Contract Standards\",\n desc: \"Coordinating the contribution to the NEAR dapp standards.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Contract Standards NEPs\",\n },\n },\n },\n },\n\n telegram: \"nearnft\",\n },\n};\n/* END_INCLUDE: \"shared/mocks\" */\n\nif (!props.label) {\n return (\n <div class=\"alert alert-danger\" role=\"alert\">\n Error: label is required\n </div>\n );\n}\n\nconst postIdsWithLabels = (labels) => {\n const ids = labels\n .map(\n (label) =>\n Near.view(nearDevGovGigsContractAccountId, \"get_posts_by_label\", {\n label,\n }) ?? []\n )\n .map((ids) => new Set(ids))\n .reduce((previous, current) => {\n let res = new Set();\n for (let id of current) {\n if (previous.has(id)) {\n res.add(id);\n }\n }\n return res;\n });\n ids.delete(communities[props.label].overviewId);\n ids.delete(communities[props.label].eventsId);\n return [...ids].reverse();\n};\n\nconst sponsorshipRequiredLabels = [\"funding\", props.label];\nconst sponsorshipRequiredPosts = postIdsWithLabels(sponsorshipRequiredLabels);\n\nconst Sponsorship = (\n <div>\n <div class=\"row mb-2 justify-content-center\">\n <div class=\"col-md-auto\">\n <small class=\"text-muted\">\n Post Type: <b>Sponsorship</b>\n </small>\n </div>\n <div class=\"col-md-auto\">\n <small class=\"text-muted\">\n Required labels:\n {sponsorshipRequiredLabels.map((label) => (\n <a href={href(\"Feed\", { label })} key={label}>\n <span class=\"badge text-bg-primary me-1\">{label}</span>\n </a>\n ))}\n </small>\n </div>\n </div>\n <div class=\"row\">\n <div class=\"col\">\n <div class=\"card\">\n <div class=\"card-body border-secondary\">\n <h6 class=\"card-title\">\n Sponsored Projects ({sponsorshipRequiredPosts.length})\n </h6>\n <div class=\"row\">\n {sponsorshipRequiredPosts.map((postId) => (\n <div class=\"col-3\">\n {widget(\n \"components.posts.CompactPost\",\n { id: postId },\n postId\n )}\n </div>\n ))}\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n);\n\nreturn widget(\"components.community.Layout\", {\n label: props.label,\n tab: \"Sponsorship\",\n children: Sponsorship,\n});\n" }, "gigs-board.entity.github-repo.board": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\n/* INCLUDE: \"shared/lib/gui\" */\nconst Card = styled.div`\n &:hover {\n box-shadow: rgba(3, 102, 214, 0.3) 0px 0px 0px 3px;\n }\n`;\n\nconst CompactContainer = styled.div`\n width: fit-content !important;\n max-width: 100%;\n`;\n/* END_INCLUDE: \"shared/lib/gui\" */\n\nconst dataToColumns = (data, columns) =>\n Object.values(columns).reduce(\n (registry, column) => ({\n ...registry,\n\n [column.id]: [\n ...(registry[column.id] ?? []),\n\n ...data.filter((ticket) =>\n column?.labelSearchTerms.every((searchTerm) =>\n searchTerm.length > 0\n ? ticket.labels.some((label) =>\n label.name.toLowerCase().includes(searchTerm.toLowerCase())\n )\n : true\n )\n ),\n ],\n }),\n\n {}\n );\n\nconst withType = (type) => (data) => ({ ...data, type });\n\nconst GithubRepoBoard = ({\n columns,\n dataTypesIncluded,\n description,\n editorTrigger,\n isEditable,\n pageURL,\n repoURL,\n ticketState,\n title,\n}) => {\n const ticketStateForSure =\n ticketState === \"open\" || ticketState === \"closed\" || ticketState === \"all\"\n ? ticketState\n : \"all\";\n\n State.init({\n ticketsByColumn: {},\n });\n\n if (repoURL) {\n const pullRequests = dataTypesIncluded.PullRequest\n ? (\n fetch(\n `https://api.github.com/repos/${repoURL\n .split(\"/\")\n .slice(-2)\n .concat([\"pulls\"])\n .join(\"/\")}?state=${ticketStateForSure}`\n ).body ?? []\n ).map(withType(\"PullRequest\"))\n : [];\n\n const issues = dataTypesIncluded.Issue\n ? (\n fetch(\n `https://api.github.com/repos/${repoURL\n .split(\"/\")\n .slice(-2)\n .concat([\"issues\"])\n .join(\"/\")}state=${ticketStateForSure}`\n ).body ?? []\n ).map(withType(\"Issue\"))\n : [];\n\n State.update({\n ticketsByColumn: dataToColumns([...issues, ...pullRequests], columns),\n });\n }\n\n return (\n <div className=\"d-flex flex-column gap-4 pb-4\">\n <div className=\"d-flex flex-column align-items-center gap-2\">\n <h5 className=\"h5 d-inline-flex gap-2 m-0\">\n <i className=\"bi bi-kanban-fill\" />\n <span>{title}</span>\n </h5>\n\n <p className=\"m-0 py-1 text-secondary text-center\">{description}</p>\n </div>\n\n <div className=\"d-flex justify-content-end gap-3\">\n {pageURL ? (\n <a\n className=\"card-link d-inline-flex me-auto\"\n href={pageURL}\n rel=\"noreferrer\"\n role=\"button\"\n target=\"_blank\"\n title=\"Link to this board\"\n >\n <span className=\"hstack gap-2\">\n <i className=\"bi bi-share\" />\n <span>Open in new tab</span>\n </span>\n </a>\n ) : null}\n\n {pageURL ? (\n <button\n className=\"btn btn-sm btn-outline-secondary d-inline-flex gap-2\"\n onClick={() => clipboard.writeText(pageURL)}\n >\n <i className=\"bi bi-clipboard-fill\" />\n <span>Copy link</span>\n </button>\n ) : null}\n\n {isEditable ? (\n <button\n className=\"btn btn-sm btn-primary d-inline-flex gap-2\"\n onClick={editorTrigger}\n >\n <i className=\"bi bi-wrench-adjustable-circle-fill\" />\n <span>Configure</span>\n </button>\n ) : null}\n </div>\n\n <div className=\"d-flex gap-3\" style={{ overflowX: \"auto\" }}>\n {Object.keys(columns).length > 0 ? (\n Object.values(columns).map((column) => (\n <div className=\"col-3\" key={column.id}>\n <div className=\"card\">\n <div\n className={[\n \"card-body d-flex flex-column gap-3\",\n \"border border-2 border-secondary rounded-2\",\n ].join(\" \")}\n >\n <h6 className=\"card-title h6 d-flex align-items-center gap-2 m-0\">\n {column.title}\n\n <span className=\"badge rounded-pill bg-secondary\">\n {(state.ticketsByColumn[column.id] ?? []).length}\n </span>\n </h6>\n\n <p class=\"text-secondary m-0\">{column.description}</p>\n\n <div class=\"d-flex flex-column gap-3\">\n {(state.ticketsByColumn[column.id] ?? []).map((data) =>\n widget(\"entity.github-repo.ticket\", { data }, data.id)\n )}\n </div>\n </div>\n </div>\n </div>\n ))\n ) : (\n <div\n className={[\n \"d-flex align-items-center justify-content-center\",\n \"w-100 text-black-50 opacity-50\",\n ].join(\" \")}\n style={{ height: 384 }}\n >\n No columns were created so far.\n </div>\n )}\n </div>\n </div>\n );\n};\n\nreturn GithubRepoBoard(props);\n" }, "gigs-board.components.community.Layout": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\n/* INCLUDE: \"shared/mocks\" */\nconst communities = {\n \"zero-knowledge\": {\n overviewId: 397,\n eventsId: 401,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreiajwq6ep3n7veddozji2djv5vviyisabhycbweslvpwhsoyuzcwi4\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreihgxg5kwts2juldaeasveyuddkm6tcabmrat2aaq5u6uyljtyt7lu\",\n\n title: \"Zero Knowledge\",\n desc: \"Building a zero knowledge ecosystem on NEAR.\",\n telegram: \"NearZeroKnowledge\",\n },\n\n protocol: {\n overviewId: 412,\n eventsId: 413,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreidpitdafcnhkp4uyomacypdgqvxr35jtfnbxa5s6crby7qjk2nv5a\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreicg4svzfz5nvllomsahndgm7u62za4sib4mmbygxzhpcl4htqwr4a\",\n\n title: \"Protocol\",\n desc: \"Supporting the ongoing innovation of the NEAR Protocol.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-protocol\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Protocol NEPs\",\n },\n },\n },\n },\n\n telegram: \"NEAR_Protocol_Community_Group\",\n },\n\n tooling: {\n overviewId: 416,\n eventsId: 417,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreie2eaj5czmpfe6pe53kojzcspgozebdsonffwvbxtpuipnwahybvi\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreiehzr7z2fhoqqmkt3z667wubccbch6sqtsnvd6msodyzpnf72cszy\",\n\n title: \"Tooling\",\n desc: \"Supporting the ongoing innovation of tooling.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-tools\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Tooling NEPs\",\n },\n },\n },\n },\n\n telegram: \"NEAR_Tools_Community_Group\",\n },\n\n \"contract-standards\": {\n overviewId: 414,\n eventsId: 415,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreiepgdnu7soc6xgbyd4adicbf3eyxiiwqawn6tguaix6aklfpir634\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreiaowjqxds24fwcliyriintjd4ucciprii2rdxjmxgi7f5dmzuscey\",\n\n title: \"Contract Standards\",\n desc: \"Coordinating the contribution to the NEAR dapp standards.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Contract Standards NEPs\",\n },\n },\n },\n },\n\n telegram: \"nearnft\",\n },\n};\n/* END_INCLUDE: \"shared/mocks\" */\n\nconst Content = styled.div`\n {\n padding: 0 32px;\n }\n`;\n\nif (!props.label) {\n return (\n <div class=\"alert alert-danger\" role=\"alert\">\n Error: label is required\n </div>\n );\n}\n\nconst community = communities[props.label];\n\nreturn (\n <>\n {widget(\"components.layout.Banner\")}\n {widget(\"components.community.CommunityHeader\", {\n title: community.title,\n icon: community.icon,\n desc: community.desc,\n label: props.label,\n tab: props.tab,\n })}\n <Content>{props.children}</Content>\n </>\n);\n" }, "gigs-board.pages.community.Telegram": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\n/* INCLUDE: \"shared/mocks\" */\nconst communities = {\n \"zero-knowledge\": {\n overviewId: 397,\n eventsId: 401,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreiajwq6ep3n7veddozji2djv5vviyisabhycbweslvpwhsoyuzcwi4\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreihgxg5kwts2juldaeasveyuddkm6tcabmrat2aaq5u6uyljtyt7lu\",\n\n title: \"Zero Knowledge\",\n desc: \"Building a zero knowledge ecosystem on NEAR.\",\n telegram: \"NearZeroKnowledge\",\n },\n\n protocol: {\n overviewId: 412,\n eventsId: 413,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreidpitdafcnhkp4uyomacypdgqvxr35jtfnbxa5s6crby7qjk2nv5a\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreicg4svzfz5nvllomsahndgm7u62za4sib4mmbygxzhpcl4htqwr4a\",\n\n title: \"Protocol\",\n desc: \"Supporting the ongoing innovation of the NEAR Protocol.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-protocol\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Protocol NEPs\",\n },\n },\n },\n },\n\n telegram: \"NEAR_Protocol_Community_Group\",\n },\n\n tooling: {\n overviewId: 416,\n eventsId: 417,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreie2eaj5czmpfe6pe53kojzcspgozebdsonffwvbxtpuipnwahybvi\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreiehzr7z2fhoqqmkt3z667wubccbch6sqtsnvd6msodyzpnf72cszy\",\n\n title: \"Tooling\",\n desc: \"Supporting the ongoing innovation of tooling.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-tools\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Tooling NEPs\",\n },\n },\n },\n },\n\n telegram: \"NEAR_Tools_Community_Group\",\n },\n\n \"contract-standards\": {\n overviewId: 414,\n eventsId: 415,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreiepgdnu7soc6xgbyd4adicbf3eyxiiwqawn6tguaix6aklfpir634\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreiaowjqxds24fwcliyriintjd4ucciprii2rdxjmxgi7f5dmzuscey\",\n\n title: \"Contract Standards\",\n desc: \"Coordinating the contribution to the NEAR dapp standards.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Contract Standards NEPs\",\n },\n },\n },\n },\n\n telegram: \"nearnft\",\n },\n};\n/* END_INCLUDE: \"shared/mocks\" */\n\nif (!props.label) {\n return (\n <div class=\"alert alert-danger\" role=\"alert\">\n Error: label is required\n </div>\n );\n}\n\nconst community = communities[props.label];\n\nconst group = community.telegram;\n\nconst Telegram = (\n <div>\n <iframe\n iframeResizer\n src={\n \"https://j96g3uepe0.execute-api.us-east-1.amazonaws.com/groups-ui/\" +\n group\n }\n frameborder=\"0\"\n // Required by iframeResizer\n style={{\n width: \"1px\",\n minWidth: \"100%\",\n }}\n ></iframe>\n </div>\n);\n\nreturn widget(\"components.community.Layout\", {\n label: props.label,\n tab: \"Telegram\",\n children: Telegram,\n});\n" }, "DevGov.Notification.Item.Right": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\nreturn props.post === undefined ? (\n \"Loading ...\"\n) : (\n <>\n <a className=\"btn btn-outline-dark\" href={href(\"Post\", { id: props.post })}>\n View Developer Governance post\n </a>\n </>\n);\n" }, "gigs-board.pages.community.Overview": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\n/* INCLUDE: \"shared/mocks\" */\nconst communities = {\n \"zero-knowledge\": {\n overviewId: 397,\n eventsId: 401,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreiajwq6ep3n7veddozji2djv5vviyisabhycbweslvpwhsoyuzcwi4\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreihgxg5kwts2juldaeasveyuddkm6tcabmrat2aaq5u6uyljtyt7lu\",\n\n title: \"Zero Knowledge\",\n desc: \"Building a zero knowledge ecosystem on NEAR.\",\n telegram: \"NearZeroKnowledge\",\n },\n\n protocol: {\n overviewId: 412,\n eventsId: 413,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreidpitdafcnhkp4uyomacypdgqvxr35jtfnbxa5s6crby7qjk2nv5a\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreicg4svzfz5nvllomsahndgm7u62za4sib4mmbygxzhpcl4htqwr4a\",\n\n title: \"Protocol\",\n desc: \"Supporting the ongoing innovation of the NEAR Protocol.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-protocol\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Protocol NEPs\",\n },\n },\n },\n },\n\n telegram: \"NEAR_Protocol_Community_Group\",\n },\n\n tooling: {\n overviewId: 416,\n eventsId: 417,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreie2eaj5czmpfe6pe53kojzcspgozebdsonffwvbxtpuipnwahybvi\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreiehzr7z2fhoqqmkt3z667wubccbch6sqtsnvd6msodyzpnf72cszy\",\n\n title: \"Tooling\",\n desc: \"Supporting the ongoing innovation of tooling.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-tools\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Tooling NEPs\",\n },\n },\n },\n },\n\n telegram: \"NEAR_Tools_Community_Group\",\n },\n\n \"contract-standards\": {\n overviewId: 414,\n eventsId: 415,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreiepgdnu7soc6xgbyd4adicbf3eyxiiwqawn6tguaix6aklfpir634\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreiaowjqxds24fwcliyriintjd4ucciprii2rdxjmxgi7f5dmzuscey\",\n\n title: \"Contract Standards\",\n desc: \"Coordinating the contribution to the NEAR dapp standards.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Contract Standards NEPs\",\n },\n },\n },\n },\n\n telegram: \"nearnft\",\n },\n};\n/* END_INCLUDE: \"shared/mocks\" */\n\nif (!props.label) {\n return (\n <div class=\"alert alert-danger\" role=\"alert\">\n Error: label is required\n </div>\n );\n}\n\nconst community = communities[props.label];\n\nconst overviewPost = Near.view(nearDevGovGigsContractAccountId, \"get_post\", {\n post_id: community.overviewId,\n});\nif (!overviewPost) {\n return <div>Loading ...</div>;\n}\n\nconst onMention = (accountId) => (\n <span key={accountId} className=\"d-inline-flex\" style={{ fontWeight: 500 }}>\n <Widget\n src=\"neardevgov.near/widget/ProfileLine\"\n props={{\n accountId: accountId.toLowerCase(),\n hideAccountId: true,\n tooltip: true,\n }}\n />\n </span>\n);\n\nconst Overview = (\n <div>\n <Markdown\n class=\"card-text\"\n text={overviewPost.snapshot.description}\n onMention={onMention}\n ></Markdown>\n </div>\n);\n\nreturn (\n <div className=\"container\">\n <div className=\"row\">\n <div className=\"col-xs-12\">\n {widget(\"components.community.Layout\", {\n label: props.label,\n tab: \"Overview\",\n })}\n </div>\n </div>\n <div className=\"row\">\n <div className=\"col-xs-12 col-lg-12\">{Overview}</div>\n </div>\n </div>\n);\n" }, "gigs-board.components.posts.Post": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n/* INCLUDE: \"shared/lib/gui\" */\nconst Card = styled.div`\n &:hover {\n box-shadow: rgba(3, 102, 214, 0.3) 0px 0px 0px 3px;\n }\n`;\n\nconst CompactContainer = styled.div`\n width: fit-content !important;\n max-width: 100%;\n`;\n/* END_INCLUDE: \"shared/lib/gui\" */\n\nconst postId = props.post.id ?? (props.id ? parseInt(props.id) : 0);\nconst post =\n props.post ??\n Near.view(nearDevGovGigsContractAccountId, \"get_post\", { post_id: postId });\nif (!post) {\n return <div>Loading ...</div>;\n}\n\nconst snapshot = post.snapshot;\n// If this post is displayed under another post. Used to limit the size.\nconst isUnderPost = props.isUnderPost ? true : false;\nconst parentId = Near.view(nearDevGovGigsContractAccountId, \"get_parent_id\", {\n post_id: postId,\n});\n\nconst childPostIdsUnordered =\n Near.view(nearDevGovGigsContractAccountId, \"get_children_ids\", {\n post_id: postId,\n }) ?? [];\n\nconst childPostIds = props.isPreview ? [] : childPostIdsUnordered.reverse();\nconst expandable = props.isPreview ? false : props.expandable ?? false;\nconst defaultExpanded = expandable ? props.defaultExpanded : true;\n\nfunction readableDate(timestamp) {\n var a = new Date(timestamp);\n return a.toDateString() + \" \" + a.toLocaleTimeString();\n}\n\nconst timestamp = readableDate(\n snapshot.timestamp ? snapshot.timestamp / 1000000 : Date.now()\n);\n\nconst postSearchKeywords = props.searchKeywords ? (\n <div\n style={{ marginLeft: \"1rem\", fontFamily: \"monospace\" }}\n key=\"post-search-keywords\"\n >\n <span>Found keywords: </span>\n {props.searchKeywords.map((label) => {\n return <span class=\"badge text-bg-info me-1\">{label}</span>;\n })}\n </div>\n) : (\n <div key=\"post-search-keywords\"></div>\n);\n\nconst searchKeywords = props.searchKeywords ? (\n <div class=\"mb-1\" key=\"search-keywords\">\n <small class=\"text-muted\" style={{ marginLeft: \"1rem\" }}>\n {postSearchKeywords}\n </small>\n </div>\n) : (\n <div key=\"search-keywords\"></div>\n);\n\nconst linkToParent =\n isUnderPost || !parentId ? (\n <div key=\"link-to-parent\"></div>\n ) : (\n <div className=\"card-header\" key=\"link-to-parent\">\n <a href={href(\"Post\", { id: parentId })}>\n <i class=\"bi bi-arrow-90deg-up\"></i>Go to parent{\" \"}\n </a>\n </div>\n );\n\nconst allowedToEdit =\n !props.isPreview &&\n Near.view(nearDevGovGigsContractAccountId, \"is_allowed_to_edit\", {\n post_id: postId,\n editor: context.accountId,\n });\n\nconst btnEditorWidget = (postType, name) => {\n return (\n <li>\n <a\n class=\"dropdown-item\"\n data-bs-toggle=\"collapse\"\n href={`#collapse${postType}Editor${postId}`}\n role=\"button\"\n aria-expanded=\"false\"\n aria-controls={`collapse${postType}Editor${postId}`}\n >\n {name}\n </a>\n </li>\n );\n};\n\nconst editControl = allowedToEdit ? (\n <div class=\"btn-group\" role=\"group\">\n <a\n class=\"card-link px-2\"\n role=\"button\"\n title=\"Edit post\"\n data-bs-toggle=\"dropdown\"\n aria-expanded=\"false\"\n type=\"button\"\n >\n <div class=\"bi bi-pencil-square\"></div>\n </a>\n <ul class=\"dropdown-menu\">\n {btnEditorWidget(\"Idea\", \"Edit as an idea\")}\n {btnEditorWidget(\"Submission\", \"Edit as a solution\")}\n {btnEditorWidget(\"Attestation\", \"Edit as an attestation\")}\n {btnEditorWidget(\"Sponsorship\", \"Edit as a sponsorship\")}\n {btnEditorWidget(\"Comment\", \"Edit as a comment\")}\n </ul>\n </div>\n) : (\n <div></div>\n);\n\nconst shareButton = props.isPreview ? (\n <div></div>\n) : (\n <a\n class=\"card-link\"\n href={href(\"Post\", { id: postId })}\n role=\"button\"\n target=\"_blank\"\n title=\"Open in new tab\"\n style={{ color: \"rgb(0,128,128)\", border: \"1em\" }}\n >\n <div class=\"bi bi-share\"></div>\n </a>\n);\n\nconst StyledLink = styled.a`\n color: rgba(0, 0, 0, 0.8);\n font-size: inherit;\n font-style: italic;\n font-weight: bold;\n opacity: 0.75;\n text-decoration: none;\n &:hover {\n text-decoration: underline;\n }\n`;\n\nconst StyledDiv = styled.div`\n display: flex;\n flex-wrap: nowrap;\n justify-content: end;\n align-items: center;\n width: 100%;\n color: rgba(0, 0, 0, 0.8);\n // padding: \"15px\";\n margin-right: 16px;\n font-size: 1.2em;\n`;\n\nconst ResponsiveDiv = styled.div`\n display: flex;\n justify-content: end;\n align-items: center;\n width: 100%;\n @media (max-width: 768px) {\n flex-direction: column;\n align-items: flex-start;\n }\n`;\n\n// start of test edits\nconst accountId = (props.accountId = post.author_id);\nconst link = props.link ?? true;\nconst hideAccountId = props.hideAccountId;\nconst hideName = props.hideName;\nconst hideImage = props.hideImage;\n\nconst profile = props.profile ?? Social.getr(`${accountId}/profile`);\n\nconst name = profile.name ?? accountId;\nconst title = props.title ?? `${name} @${accountId}`;\nconst tooltip =\n props.tooltip && (props.tooltip === true ? title : props.tooltip);\n\nlet inner = (\n <>\n {!hideName && (\n <span key=\"name\">\n {name}\n <br></br>\n </span>\n )}\n {!hideAccountId && (\n <span key=\"accountId\" className=\"text-muted ms-1 d-flex\">\n @{accountId}\n </span>\n )}\n </>\n);\n\ninner = link ? (\n <a\n href={\n link !== true\n ? link\n : `#/mob.near/widget/ProfilePage?accountId=${accountId}`\n }\n className=\"link-dark text-truncate d-flex flex-column align-items-start\"\n >\n {inner}\n </a>\n) : (\n <span className=\"text-truncate d-flex flex-column align-items-start\">\n {inner}\n </span>\n);\n\nif (props.tooltip === true) {\n return (\n <Widget\n src=\"mob.near/widget/Profile.OverlayTrigger\"\n props={{ accountId, children: inner }}\n />\n );\n}\nif (tooltip) {\n inner = (\n <OverlayTrigger placement=\"auto\" overlay={<Tooltip>{tooltip}</Tooltip>}>\n {inner}\n </OverlayTrigger>\n );\n}\n// end of test edits\n\nconst header = (\n <ResponsiveDiv\n className=\"py-1 px-3\"\n style={{ fontSize: \"1em\", alignItems: \"start\" }}\n >\n <div className=\"d-flex align-items-start justify-content-between\">\n <div\n className=\"col-auto d-flex align-items-start\"\n style={{ padding: \"1rem\" }}\n >\n <div\n className=\"square rounded-circle\"\n style={{\n overflow: \"hidden\",\n width: \"3.33em\",\n height: \"3.33em\",\n backgroundColor: \"#008080\",\n }}\n >\n <Widget\n key=\"image\"\n src=\"mob.near/widget/ProfileImage\"\n props={{\n style: { width: \"100%\", height: \"100%\" },\n profile,\n accountId,\n }}\n />\n </div>\n\n <div\n style={{\n marginLeft: \"1em\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n }}\n >\n <span\n key=\"accountId\"\n className=\"text-muted \"\n style={{\n display: \"block\",\n fontSize: \"1rem\",\n fontWeight: \"500\",\n marginTop: \"0px\",\n }}\n >\n {inner}\n </span>\n </div>\n </div>\n </div>\n <StyledDiv>\n {editControl}\n <span className=\"px-2\">{timestamp}</span>\n <div className=\"bi bi-clock-history px-2\"></div>\n {shareButton}\n </StyledDiv>\n </ResponsiveDiv>\n);\n\nconst emptyIcons = {\n Idea: \"bi-lightbulb\",\n Comment: \"bi-chat\",\n Submission: \"bi-rocket\",\n Attestation: \"bi-check-circle\",\n Sponsorship: \"bi-cash-coin\",\n Github: \"bi-github\",\n Like: \"bi-heart\",\n Reply: \"bi-reply\",\n};\n\nconst fillIcons = {\n Idea: \"bi-lightbulb-fill\",\n Comment: \"bi-chat-fill\",\n Submission: \"bi-rocket-fill\",\n Attestation: \"bi-check-circle-fill\",\n Sponsorship: \"bi-cash-coin\",\n Github: \"bi-github\",\n Like: \"bi-heart-fill\",\n Reply: \"bi-reply-fill\",\n};\n\nconst borders = {\n Idea: \"border-secondary\",\n Comment: \"border-secondary\",\n Submission: \"border-secondary\",\n Attestation: \"border-secondary\",\n Sponsorship: \"border-secondary\",\n Github: \"border-secondary\",\n};\n\nconst containsLike = props.isPreview\n ? false\n : post.likes.find((l) => l.author_id == context.accountId);\nconst likeBtnClass = containsLike ? fillIcons.Like : emptyIcons.Like;\n// This must be outside onLike, because Near.view returns null at first, and when the view call finished, it returns true/false.\n// If checking this inside onLike, it will give `null` and we cannot tell the result is true or false.\nlet grantNotify = Near.view(\"social.near\", \"is_write_permission_granted\", {\n predecessor_id: nearDevGovGigsContractAccountId,\n key: context.accountId + \"/index/notify\",\n});\nif (grantNotify === null) {\n return <div>Loading...</div>;\n}\nconst onLike = () => {\n if (!context.accountId) {\n return;\n }\n let likeTxn = [\n {\n contractName: nearDevGovGigsContractAccountId,\n methodName: \"add_like\",\n args: {\n post_id: postId,\n },\n deposit: Big(10).pow(21).mul(2),\n gas: Big(10).pow(12).mul(100),\n },\n ];\n if (grantNotify === false) {\n likeTxn.unshift({\n contractName: \"social.near\",\n methodName: \"grant_write_permission\",\n args: {\n predecessor_id: nearDevGovGigsContractAccountId,\n keys: [context.accountId + \"/index/notify\"],\n },\n deposit: Big(10).pow(23),\n gas: Big(10).pow(12).mul(30),\n });\n }\n Near.call(likeTxn);\n};\nconst btnCreatorWidget = (postType, icon, name, desc) => {\n return (\n <li class=\"py-1\">\n <a\n class=\"dropdown-item text-decoration-none d-flex align-items-center lh-sm\"\n style={{ color: \"rgb(55,109,137)\" }}\n data-bs-toggle=\"collapse\"\n href={`#collapse${postType}Creator${postId}`}\n role=\"button\"\n aria-expanded=\"false\"\n aria-controls={`collapse${postType}Creator${postId}`}\n >\n <i class={`bi ${icon}`} style={{ fontSize: \"1rem\" }}>\n {\" \"}\n </i>\n <div class=\"ps-2 text-wrap\" style={{ width: \"18rem\" }}>\n <div>{name}</div>\n <small class=\"fw-light text-secondary\">{desc}</small>\n </div>\n </a>\n </li>\n );\n};\n\nconst buttonsFooter = props.isPreview ? null : (\n <div class=\"row\" key=\"buttons-footer\" style={{ marginLeft: \"0.2rem\" }}>\n <div class=\"col-8\">\n <div\n class=\"btn-group text-sm\"\n role=\"group\"\n aria-label=\"Basic outlined example\"\n >\n <button\n type=\"button\"\n class=\"btn btn-outline-secondary\"\n style={{ border: \"0px\", opacity: \"0.7\" }}\n onClick={onLike}\n >\n <i class={`bi ${likeBtnClass}`}> </i>\n {post.likes.length == 0\n ? \"Like\"\n : widget(\"components.layout.LikeButton.Faces\", {\n likesByUsers: Object.fromEntries(\n post.likes.map(({ author_id }) => [author_id, \"\"])\n ),\n })}\n </button>\n <div class=\"btn-group text-sm\" role=\"group\">\n <button\n type=\"button\"\n class=\"btn btn-outline-secondary\"\n style={{ border: \"0px\", opacity: \"0.84\" }}\n data-bs-toggle=\"dropdown\"\n aria-expanded=\"false\"\n >\n <i class={`bi ${emptyIcons.Reply}`}> </i> Reply\n </button>\n <ul class=\"dropdown-menu\">\n {btnCreatorWidget(\n \"Idea\",\n emptyIcons.Idea,\n \"Idea\",\n \"Get feedback from the community about a problem, opportunity, or need.\"\n )}\n {btnCreatorWidget(\n \"Submission\",\n emptyIcons.Submission,\n \"Solution\",\n \"Provide a specific proposal or implementation to an idea, optionally requesting funding.\"\n )}\n {btnCreatorWidget(\n \"Attestation\",\n emptyIcons.Attestation,\n \"Attestation\",\n \"Formally review or validate a solution as a recognized expert.\"\n )}\n {btnCreatorWidget(\n \"Sponsorship\",\n emptyIcons.Sponsorship,\n \"Sponsorship\",\n \"Offer to fund projects, events, or proposals that match your needs.\"\n )}\n <li>\n <hr class=\"dropdown-divider\" />\n </li>\n {btnCreatorWidget(\n \"Comment\",\n emptyIcons.Comment,\n \"Comment\",\n \"Ask a question, provide information, or share a resource that is relevant to the thread.\"\n )}\n </ul>\n </div>\n <button\n type=\"button\"\n class=\"btn btn-outline-secondary text-sm\"\n style={{ border: \"0px\", opacity: \"0.84\" }}\n data-bs-toggle=\"collapse\"\n href={`#collapseChildPosts${postId}`}\n aria-expanded={defaultExpanded}\n aria-controls={`collapseChildPosts${postId}`}\n >\n <i class=\"bi bi-arrows-expand\"> </i>{\" \"}\n {`Expand Replies (${childPostIds.length})`}\n </button>\n </div>\n </div>\n </div>\n);\n\nconst CreatorWidget = (postType) => {\n return (\n <div\n class=\"collapse\"\n id={`collapse${postType}Creator${postId}`}\n data-bs-parent={`#accordion${postId}`}\n >\n {widget(\"components.posts.PostEditor\", {\n postType,\n parentId: postId,\n mode: \"Create\",\n })}\n </div>\n );\n};\n\nconst EditorWidget = (postType) => {\n return (\n <div\n class=\"collapse\"\n id={`collapse${postType}Editor${postId}`}\n data-bs-parent={`#accordion${postId}`}\n >\n {widget(\"components.posts.PostEditor\", {\n postType,\n postId,\n mode: \"Edit\",\n author_id: post.author_id,\n name: post.snapshot.name,\n description: post.snapshot.description,\n labels: post.snapshot.labels,\n amount: post.snapshot.amount,\n token: post.snapshot.sponsorship_token,\n supervisor: post.snapshot.supervisor,\n githubLink: post.snapshot.github_link,\n })}\n </div>\n );\n};\n\nconst editorsFooter = props.isPreview ? null : (\n <div class=\"row\" id={`accordion${postId}`} key=\"editors-footer\">\n {CreatorWidget(\"Comment\")}\n {EditorWidget(\"Comment\")}\n {CreatorWidget(\"Idea\")}\n {EditorWidget(\"Idea\")}\n {CreatorWidget(\"Submission\")}\n {EditorWidget(\"Submission\")}\n {CreatorWidget(\"Attestation\")}\n {EditorWidget(\"Attestation\")}\n {CreatorWidget(\"Sponsorship\")}\n {EditorWidget(\"Sponsorship\")}\n {CreatorWidget(\"Github\")}\n {EditorWidget(\"Github\")}\n </div>\n);\n\nconst renamedPostType =\n snapshot.post_type == \"Submission\" ? \"Solution\" : snapshot.post_type;\n\nconst postLabels = post.snapshot.labels ? (\n <div\n class=\"card-title\"\n key=\"post-labels\"\n style={{ marginLeft: \"1rem\", marginBottom: \"0.8rem\" }}\n >\n {post.snapshot.labels.map((label) => {\n return (\n <>\n <a href={href(\"Feed\", { label })} key={label}>\n <span\n className=\"badge ms-1\"\n style={{\n color: \"rgba(0, 0, 0, 0.7)\",\n fontSize: \"1em\",\n fontWeight: \"normal\",\n padding: \"0.2em 0.5em\",\n border: \"1px solid rgba(0, 80, 80, 0.2)\",\n marginTop: \"1rem\",\n }}\n >\n {label}\n </span>\n </a>\n </>\n );\n })}\n </div>\n) : (\n <div key=\"post-labels\"></div>\n);\n\nconst postTitle =\n snapshot.post_type == \"Comment\" ? (\n <div key=\"post-title\"></div>\n ) : (\n <h5 class=\"card-title\" key=\"post-title\">\n <div\n className=\"row justify-content-between\"\n style={{ fontSize: \"1.3em\", fontWeight: \"600\", marginLeft: \"0.3rem\" }}\n >\n <div class=\"col-12\">\n <i class={`bi ${emptyIcons[snapshot.post_type]}`}> </i>\n {renamedPostType}: {snapshot.name}\n </div>\n </div>\n </h5>\n );\n\nconst postExtra =\n snapshot.post_type == \"Sponsorship\" ? (\n <div key=\"post-extra\">\n <h6\n class=\"card-subtitle text-muted\"\n style={{\n marginLeft: \"1rem\",\n marginBottom: \"1rem\",\n fontSize: \"1.25em\",\n fontWeight: \"600\",\n }}\n >\n Maximum amount: {snapshot.amount} {snapshot.sponsorship_token}\n </h6>\n <h6\n class=\"card-subtitle text-muted\"\n style={{\n marginLeft: \"1rem\",\n marginBottom: \"1.5rem\",\n fontSize: \"1.25em\",\n fontWeight: \"600\",\n }}\n >\n Supervisor:{\" \"}\n <Widget\n src={`neardevgov.near/widget/ProfileLine`}\n props={{ accountId: snapshot.supervisor }}\n />\n </h6>\n </div>\n ) : (\n <div></div>\n );\n\nconst postsList =\n props.isPreview || childPostIds.length == 0 ? (\n <div key=\"posts-list\"></div>\n ) : (\n <div class=\"row\" key=\"posts-list\">\n <div\n class={`collapse ${defaultExpanded ? \"show\" : \"\"}`}\n id={`collapseChildPosts${postId}`}\n >\n {childPostIds.map((childId) =>\n widget(\n \"components.posts.Post\",\n { id: childId, isUnderPost: true },\n `subpost${childId}of${postId}`\n )\n )}\n </div>\n </div>\n );\n\n// Determine if located in the post page.\n\nconst isInList = props.isInList;\nconst contentArray = snapshot.description.split(\"\\n\");\nconst needClamp = isInList && contentArray.length > 5;\n// Initialize 'clamp' to 'true' if the content is long enough, otherwise 'false'\ninitState({\n clamp: needClamp,\n});\nconst onMention = (accountId) => (\n <span key={accountId} className=\"d-inline-flex\" style={{ fontWeight: 500 }}>\n <Widget\n src=\"neardevgov.near/widget/ProfileLine\"\n props={{\n accountId: accountId.toLowerCase(),\n hideAccountId: true,\n tooltip: true,\n }}\n />\n </span>\n);\n\n// Determine whether the content is longer than 4 lines\nconst isContentLong = contentArray.length > 5;\n\nconst clampedContent = state.clamp\n ? contentArray.slice(0, 5).join(\"\\n\")\n : snapshot.description;\n\n// Your CSS classes for styling. Make sure the names match exactly with the ones you're using in your divs.\nconst limitedMarkdown = styled.div`\n max-height: 23em;\n`;\n\nconst clampMarkdown = styled.div`\n .clamp {\n display: -webkit-box;\n -webkit-line-clamp: 5;\n -webkit-box-orient: vertical;\n overflow: hidden;\n }\n`;\n\nconst descriptionArea = isUnderPost ? (\n <limitedMarkdown\n className=\"overflow-auto\"\n key=\"description-area\"\n style={{ marginLeft: \"1rem\", paddingRight: \"15px\", marginBottom: \"1rem\" }}\n >\n <Markdown\n className=\"card-text\"\n text={snapshot.description}\n onMention={onMention}\n />\n </limitedMarkdown>\n) : (\n <clampMarkdown>\n <div\n className={state.clamp ? \"clamp\" : \"\"}\n style={{\n fontSize: \"1rem\",\n paddingLeft: \"15px\",\n paddingRight: \"15px\",\n marginBottom: \"-10px\",\n }}\n >\n <Markdown\n className=\"card-text\"\n text={state.clamp ? clampedContent : snapshot.description}\n onMention={onMention}\n key=\"description-area\"\n ></Markdown>\n </div>\n {state.clamp && isContentLong ? (\n <div className=\"d-flex justify-content-center\">\n <StyledLink>\n <a\n style={{ fontSize: \"1rem\", fontWeight: 700 }}\n className=\"btn btn-link text-black\"\n onClick={() => State.update({ clamp: false })}\n >\n <br></br>\n See More...\n </a>\n </StyledLink>\n </div>\n ) : !state.clamp && isContentLong ? (\n <div className=\"d-flex justify-content-center\">\n <StyledLink>\n <a\n style={{ fontSize: \"1rem\", fontWeight: 700 }}\n className=\"btn btn-link text-black\"\n onClick={() => State.update({ clamp: true })}\n >\n ^ Close\n </a>\n </StyledLink>\n </div>\n ) : null}\n </clampMarkdown>\n);\n\nreturn (\n <Card className={`card my-2`}>\n {linkToParent}\n {header}\n <div className=\"card-body \">\n {searchKeywords}\n {postTitle}\n <div style={{ marginTop: \"1rem\", marginBottom: \"1rem\" }}></div>\n {postExtra}\n {descriptionArea}\n {postLabels}\n {buttonsFooter}\n {editorsFooter}\n {postsList}\n </div>\n </Card>\n);\n" }, "gigs-board.pages.Boards": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\nconst selectedBoardId = props.selectedBoardId ?? \"mnwtransition\";\n\nconst boards = props.boards ?? [\n {\n name: \"near.social\",\n id: \"nearsocial\",\n config: {\n requiredLabels: [\"near-social\"],\n columns: [\n { label: \"widget\", title: \"Widget\" },\n { label: \"integration\", title: \"Integration\" },\n { label: \"feature-request\", title: \"Feature Request\" },\n ],\n excludedLabels: [],\n },\n },\n {\n name: \"Gigs Board\",\n id: \"gigsboard\",\n config: {\n requiredLabels: [\"gigs-board\"],\n columns: [\n { label: \"nep\", title: \"NEP\" },\n { label: \"badges\", title: \"Badges\" },\n { label: \"feature-request\", title: \"Feature Request\" },\n ],\n excludedLabels: [],\n },\n },\n {\n name: \"Funding\",\n id: \"funding\",\n config: {\n requiredLabels: [\"funding\"],\n columns: [\n { label: \"funding-new-request\", title: \"New Request\" },\n {\n label: \"funding-information-collection\",\n title: \"Information Collection\",\n },\n { label: \"funding-processing\", title: \"Processing\" },\n { label: \"funding-funded\", title: \"Funded\" },\n ],\n excludedLabels: [],\n },\n },\n];\n\n// Bootstrap tabs documentation: https://getbootstrap.com/docs/5.2/components/navs-tabs\nconst pageContent = (\n <div>\n <ul class=\"nav nav-tabs my-3\">\n {boards.map((board) => (\n <li class=\"nav-item\" key={board.id}>\n <a\n href={href(\"Boards\", { selectedBoardId: board.id })}\n class={`nav-link ${board.id == selectedBoardId ? \"active\" : \"\"}`}\n >\n {board.name}\n </a>\n </li>\n ))}\n </ul>\n <div class=\"tab-content\">\n {boards.map((board) => (\n <div\n class={`tab-pane fade ${\n board.id == selectedBoardId ? \"show active\" : \"\"\n }`}\n id={`board${board.id}`}\n role=\"tabpanel\"\n aria-labelledby={`${board.id}-tab`}\n tabindex=\"0\"\n key={board.id}\n >\n {widget(\"components.boards.KanbanBoard\", {\n requiredLabels: board.config.requiredLabels,\n excludedLabels: board.config.excludedLabels,\n columns: board.config.columns,\n boardId: board.id,\n })}\n </div>\n ))}\n </div>\n </div>\n);\n\nreturn widget(\"components.layout.Page\", {\n children: pageContent,\n});\n" }, "gigs-board.pages.community.github": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\nconst CommunityGithubPage = ({ label }) =>\n widget(\"components.community.Layout\", {\n label,\n tab: \"GitHub\",\n children: (\n <div className=\"d-flex flex-column\">\n {widget(\"feature.integration.github.board-config-editor\", {\n label,\n pageURL: \"near.org\" + href(\"community.github\", { label }),\n })}\n </div>\n ),\n });\n\nreturn CommunityGithubPage(props);\n" }, "gigs-board.pages.Post": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\nreturn widget(\"components.layout.Page\", {\n children: widget(\"components.posts.Post\", {\n id: props.id,\n }),\n});\n" }, "gigs-board.components.community.FeedHeader": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\n/* INCLUDE: \"shared/mocks\" */\nconst communities = {\n \"zero-knowledge\": {\n overviewId: 397,\n eventsId: 401,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreiajwq6ep3n7veddozji2djv5vviyisabhycbweslvpwhsoyuzcwi4\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreihgxg5kwts2juldaeasveyuddkm6tcabmrat2aaq5u6uyljtyt7lu\",\n\n title: \"Zero Knowledge\",\n desc: \"Building a zero knowledge ecosystem on NEAR.\",\n telegram: \"NearZeroKnowledge\",\n },\n\n protocol: {\n overviewId: 412,\n eventsId: 413,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreidpitdafcnhkp4uyomacypdgqvxr35jtfnbxa5s6crby7qjk2nv5a\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreicg4svzfz5nvllomsahndgm7u62za4sib4mmbygxzhpcl4htqwr4a\",\n\n title: \"Protocol\",\n desc: \"Supporting the ongoing innovation of the NEAR Protocol.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-protocol\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Protocol NEPs\",\n },\n },\n },\n },\n\n telegram: \"NEAR_Protocol_Community_Group\",\n },\n\n tooling: {\n overviewId: 416,\n eventsId: 417,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreie2eaj5czmpfe6pe53kojzcspgozebdsonffwvbxtpuipnwahybvi\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreiehzr7z2fhoqqmkt3z667wubccbch6sqtsnvd6msodyzpnf72cszy\",\n\n title: \"Tooling\",\n desc: \"Supporting the ongoing innovation of tooling.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-tools\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Tooling NEPs\",\n },\n },\n },\n },\n\n telegram: \"NEAR_Tools_Community_Group\",\n },\n\n \"contract-standards\": {\n overviewId: 414,\n eventsId: 415,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreiepgdnu7soc6xgbyd4adicbf3eyxiiwqawn6tguaix6aklfpir634\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreiaowjqxds24fwcliyriintjd4ucciprii2rdxjmxgi7f5dmzuscey\",\n\n title: \"Contract Standards\",\n desc: \"Coordinating the contribution to the NEAR dapp standards.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Contract Standards NEPs\",\n },\n },\n },\n },\n\n telegram: \"nearnft\",\n },\n};\n/* END_INCLUDE: \"shared/mocks\" */\n\nconst Gradient = styled.div`\n {\n margin-top: -25px;\n margin-bottom: 25px;\n height: 250px;\n text-align: center;\n background: radial-gradient(\n circle,\n rgba(29, 55, 57, 1) 30%,\n rgba(24, 24, 24, 1) 80%\n );\n\n font-family: Arial, sans-serif;\n }\n\n .text-primary-gradient {\n color: #53fdca;\n -webkit-text-fill-color: transparent;\n background-image: linear-gradient(#8e76ba, #1ed2f0);\n -webkit-background-clip: text;\n background-clip: text;\n }\n\n .subtitle-above {\n font-size: 18px;\n letter-spacing: 1px;\n font-family: Courier, monospace;\n }\n\n .subtitle-below {\n font-size: 16px;\n }\n\n .slogan {\n font-weight: 600;\n font-size: 60px;\n }\n`;\n\nreturn (\n <>\n <Gradient className=\"d-flex flex-column justify-content-center\">\n <div class=\"subtitle-above text-white opacity-75 mb-2\">\n A decentralized community of\n </div>\n <h1 class=\"mb-3 text-white slogan\">\n <span class=\"text-primary-gradient\">NEAR </span>Developers\n </h1>\n <div class=\"subtitle-below text-white opacity-75\">\n Share your ideas, match solutions, and access support and funding.\n </div>\n </Gradient>\n <div class=\"h5 pb-3\">Featured Communities</div>\n <div class=\"row\">\n {Object.entries(communities).map(([label, community]) => {\n return (\n <div class=\"col\">\n {widget(\n \"components.community.FeaturedCommunity\",\n {\n label,\n ...community,\n },\n label\n )}\n </div>\n );\n })}\n </div>\n <div class=\"h5 pb-3 pt-5\">Activity</div>\n </>\n);\n" }, "gigs-board.components.posts.PostEditor": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\nconst postType = props.postType ?? \"Sponsorship\";\nconst parentId = props.parentId ?? null;\nconst postId = props.postId ?? null;\nconst mode = props.mode ?? \"Create\";\n\nconst referralLabels = props.referral ? [`referral:${props.referral}`] : [];\nconst labelStrings = (props.labels ?? []).concat(referralLabels);\nconst labels = labelStrings.map((s) => {\n return { name: s };\n});\n\nconst initState = props.initState;\nconst handleStateChange = props.handleStateChange;\n\ninitState({\n author_id: context.accountId,\n // Should be a list of objects with field \"name\".\n labels,\n // Should be a list of labels as strings.\n // Both of the label structures should be modified together.\n labelStrings,\n postType,\n name: props.name ?? \"\",\n description: props.description ?? \"\",\n amount: props.amount ?? \"0\",\n token: props.token ?? \"Near\",\n supervisor: props.supervisor ?? \"\",\n githubLink: props.githubLink ?? \"\",\n warning: \"\",\n});\nconst savedState = Storage.getItem(\"widgetState\");\nif (savedState) {\n handleStateChange(JSON.parse(savedState));\n}\n\nlet fields = {\n Comment: [\"description\"],\n Idea: [\"name\", \"description\"],\n Submission: [\"name\", \"description\"],\n Attestation: [\"name\", \"description\"],\n Sponsorship: [\n \"name\",\n \"description\",\n \"amount\",\n \"sponsorship_token\",\n \"supervisor\",\n ],\n Github: [\"githubLink\", \"name\", \"description\"],\n}[postType];\n\n// This must be outside onClick, because Near.view returns null at first, and when the view call finished, it returns true/false.\n// If checking this inside onClick, it will give `null` and we cannot tell the result is true or false.\nlet grantNotify = Near.view(\"social.near\", \"is_write_permission_granted\", {\n predecessor_id: nearDevGovGigsContractAccountId,\n key: context.accountId + \"/index/notify\",\n});\nif (grantNotify === null) {\n return;\n}\nconst onSubmit = () => {\n let labels = state.labelStrings;\n var body = {\n Comment: { description: state.description, comment_version: \"V2\" },\n Idea: {\n name: state.name,\n description: state.description,\n idea_version: \"V1\",\n },\n Submission: {\n name: state.name,\n description: state.description,\n submission_version: \"V1\",\n },\n Attestation: {\n name: state.name,\n description: state.description,\n attestation_version: \"V1\",\n },\n Sponsorship: {\n name: state.name,\n description: state.description,\n amount: state.amount,\n sponsorship_token: state.token,\n supervisor: state.supervisor,\n sponsorship_version: \"V1\",\n },\n Github: {\n name: state.name,\n description: state.description,\n github_version: \"V0\",\n github_link: state.githubLink,\n },\n }[postType];\n body[\"post_type\"] = postType;\n if (!context.accountId) {\n return;\n }\n let txn = [];\n if (mode == \"Create\") {\n txn.push({\n contractName: nearDevGovGigsContractAccountId,\n methodName: \"add_post\",\n args: {\n parent_id: parentId,\n labels,\n body,\n },\n deposit: Big(10).pow(21).mul(2),\n gas: Big(10).pow(12).mul(100),\n });\n } else if (mode == \"Edit\") {\n txn.push({\n contractName: nearDevGovGigsContractAccountId,\n methodName: \"edit_post\",\n args: {\n id: postId,\n labels,\n body,\n },\n deposit: Big(10).pow(21).mul(2),\n gas: Big(10).pow(12).mul(100),\n });\n }\n if (mode == \"Create\" || mode == \"Edit\") {\n if (grantNotify === false) {\n txn.unshift({\n contractName: \"social.near\",\n methodName: \"grant_write_permission\",\n args: {\n predecessor_id: nearDevGovGigsContractAccountId,\n keys: [context.accountId + \"/index/notify\"],\n },\n deposit: Big(10).pow(23),\n gas: Big(10).pow(12).mul(30),\n });\n }\n Near.call(txn);\n }\n};\n\nconst githubLinkDiv = fields.includes(\"githubLink\") ? (\n <div className=\"col-lg-12 mb-2\">\n Github Issue URL:\n <input\n type=\"text\"\n value={state.githubLink}\n onChange={(event) => State.update({ githubLink: event.target.value })}\n />\n </div>\n) : null;\n\nconst nameDiv = fields.includes(\"name\") ? (\n <div className=\"col-lg-12 mb-2\">\n Name:\n <input\n type=\"text\"\n value={state.name}\n onChange={(event) => State.update({ name: event.target.value })}\n />\n </div>\n) : null;\n\nconst descriptionDiv = fields.includes(\"description\") ? (\n <div className=\"col-lg-12 mb-2\">\n Description:\n <textarea\n rows=\"5\"\n value={state.description}\n onChange={(event) => State.update({ description: event.target.value })}\n />\n </div>\n) : null;\n\nconst amountDiv = fields.includes(\"amount\") ? (\n <div className=\"col-lg-12 mb-2\">\n Amount:\n <input\n type=\"text\"\n value={state.amount}\n onChange={(event) => State.update({ amount: event.target.value })}\n />\n </div>\n) : null;\n\nconst tokenDiv = fields.includes(\"sponsorship_token\") ? (\n <div className=\"col-lg-12 mb-2\">\n Token:\n <input\n type=\"text\"\n value={state.token}\n onChange={(event) => State.update({ token: event.target.value })}\n />\n </div>\n) : null;\n\nconst supervisorDiv = fields.includes(\"supervisor\") ? (\n <div className=\"col-lg-12 mb-2\">\n Supervisor:\n <input\n type=\"text\"\n value={state.supervisor}\n onChange={(event) => State.update({ supervisor: event.target.value })}\n />\n </div>\n) : null;\n\nconst labelDiv = fields.includes(\"labels\") ? (\n <div className=\"col-lg-12 mb-2\">\n Labels:\n <input\n type=\"text\"\n value={state.labelStrings.join(\",\")}\n onChange={(event) => {\n let labels = event.target.value.split(\",\");\n labels = labels.map((o) => {\n o = o.trim();\n checkLabel(o);\n return { name: o };\n });\n State.update({ labels, labelStrings: event.target.value.split(\",\") });\n }}\n />\n </div>\n) : null;\n\nconst postTypeDiv = fields.includes(\"post_type\") ? (\n <div className=\"col-lg-12 mb-2\">\n Post Type:\n <select\n value={state.postType}\n onChange={(event) => State.update({ postType: event.target.value })}\n >\n <option value=\"Proposal\">Proposal</option>\n <option value=\"Issue\">Issue</option>\n <option value=\"Grant\">Grant</option>\n </select>\n </div>\n) : null;\n\nconst grantNotifyDiv = fields.includes(\"grantNotify\") ? (\n <div className=\"col-lg-12 mb-2\">\n Grant Notify:\n <input\n type=\"checkbox\"\n checked={state.grantNotify}\n onChange={(event) => State.update({ grantNotify: event.target.checked })}\n />\n </div>\n) : null;\n\nconst normalizeLabel = (label) =>\n label\n .replaceAll(/[- \\.]/g, \"_\")\n .replaceAll(/[^\\w]+/g, \"\")\n .replaceAll(/_+/g, \"-\")\n .replace(/^-+/, \"\")\n .replace(/-+$/, \"\")\n .toLowerCase()\n .trim(\"-\");\n\nconst checkLabel = (label) => {\n Near.asyncView(nearDevGovGigsContractAccountId, \"is_allowed_to_use_labels\", {\n editor: context.accountId,\n labels: [label],\n }).then((allowed) => {\n if (allowed) {\n State.update({ warning: \"\" });\n } else {\n State.update({\n warning:\n 'The label \"' +\n label +\n '\" is protected and can only be added by moderators',\n });\n return;\n }\n });\n};\n\nconst setLabels = (labels) => {\n labels = labels.map((o) => {\n o.name = normalizeLabel(o.name);\n return o;\n });\n if (labels.length < state.labels.length) {\n let oldLabels = new Set(state.labels.map((label) => label.name));\n for (let label of labels) {\n oldLabels.delete(label.name);\n }\n let removed = oldLabels.values().next().value;\n Near.asyncView(\n nearDevGovGigsContractAccountId,\n \"is_allowed_to_use_labels\",\n { editor: context.accountId, labels: [removed] }\n ).then((allowed) => {\n if (allowed) {\n let labelStrings = labels.map(({ name }) => name);\n State.update({ labels, labelStrings });\n } else {\n State.update({\n warning:\n 'The label \"' +\n removed +\n '\" is protected and can only be updated by moderators',\n });\n return;\n }\n });\n } else {\n let labelStrings = labels.map((o) => {\n return o.name;\n });\n State.update({ labels, labelStrings });\n }\n};\nconst existingLabelStrings =\n Near.view(nearDevGovGigsContractAccountId, \"get_all_allowed_labels\", {\n editor: context.accountId,\n }) ?? [];\nconst existingLabelSet = new Set(existingLabelStrings);\nconst existingLabels = existingLabelStrings.map((s) => {\n return { name: s };\n});\n\nconst labelEditor = (\n <div className=\"col-lg-12 mb-2\">\n Labels:\n <Typeahead\n multiple\n labelKey=\"name\"\n onInputChange={checkLabel}\n onChange={setLabels}\n options={existingLabels}\n placeholder=\"near.social, widget, NEP, standard, protocol, tool\"\n selected={state.labels}\n positionFixed\n allowNew={(results, props) => {\n return (\n !existingLabelSet.has(props.text) &&\n props.selected.filter((selected) => selected.name === props.text)\n .length == 0 &&\n Near.view(\n nearDevGovGigsContractAccountId,\n \"is_allowed_to_use_labels\",\n { editor: context.accountId, labels: [props.text] }\n )\n );\n }}\n />\n </div>\n);\n\nconst disclaimer = (\n <p>\n <i>\n * Note, all projects that were granted sponsorships are required to pass\n KYC to receive the funding.\n </i>\n </p>\n);\n\nconst renamedPostType = postType == \"Submission\" ? \"Solution\" : postType;\n// Below there is a weird code with fields.includes(\"githubLink\") ternary operator.\n// This is to hack around rendering bug of near.social.\nreturn (\n <div className=\"card\">\n <div className=\"card-header\">\n {mode} {renamedPostType}\n </div>\n\n <div class=\"card-body\">\n {state.warning ? (\n <div\n class=\"alert alert-warning alert-dismissible fade show\"\n role=\"alert\"\n >\n {state.warning}\n <button\n type=\"button\"\n class=\"btn-close\"\n data-bs-dismiss=\"alert\"\n aria-label=\"Close\"\n onClick={() => State.update({ warning: \"\" })}\n ></button>\n </div>\n ) : (\n <></>\n )}\n {fields.includes(\"githubLink\") ? (\n <div className=\"row\">\n {githubLinkDiv}\n {labelEditor}\n {nameDiv}\n {descriptionDiv}\n </div>\n ) : (\n <div className=\"row\">\n {labelEditor}\n {nameDiv}\n {amountDiv}\n {tokenDiv}\n {supervisorDiv}\n {descriptionDiv}\n </div>\n )}\n\n <a className=\"btn btn-outline-primary mb-2\" onClick={onSubmit}>\n Submit\n </a>\n {disclaimer}\n </div>\n <div class=\"card-footer\">\n Preview:\n {widget(\"components.posts.Post\", {\n isPreview: true,\n id: 0, // irrelevant\n post: {\n author_id: state.author_id,\n likes: [],\n snapshot: {\n editor_id: state.editor_id,\n labels: state.labelStrings,\n post_type: postType,\n name: state.name,\n description: state.description,\n amount: state.amount,\n sponsorship_token: state.token,\n supervisor: state.supervisor,\n github_link: state.githubLink,\n },\n },\n })}\n </div>\n </div>\n);\n" }, "gigs-board.components.boards.KanbanBoard": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\nconst requiredLabels = props.requiredLabels ?? [\"near-social\"];\nconst excludedLabels = props.excludedLabels ?? [\"nft\"];\nconst columns = props.columns ?? [\n { label: \"widget\", title: \"Widget\" },\n { label: \"integration\", title: \"Integration\" },\n { label: \"feature-request\", title: \"Feature Request\" },\n];\n\nconst labelsToIdSet = (labels) => {\n const ids = labels.map(\n (label) =>\n Near.view(nearDevGovGigsContractAccountId, \"get_posts_by_label\", {\n label,\n }) ?? []\n );\n const idsFlat = ids.flat(1);\n return new Set(idsFlat);\n};\n\nconst requiredPostsSet = labelsToIdSet(requiredLabels);\nconst excludedPostsSet = labelsToIdSet(excludedLabels);\n\nconst postsPerLabel = columns.map((column) => {\n let allIds = (\n Near.view(nearDevGovGigsContractAccountId, \"get_posts_by_label\", {\n label: column.label,\n }) ?? []\n ).reverse();\n if (requiredLabels.length > 0) {\n return {\n ...column,\n posts: allIds.filter(\n (i) => requiredPostsSet.has(i) && !excludedPostsSet.has(i)\n ),\n };\n } else {\n // No extra filtering is required.\n return { ...column, posts: allIds };\n }\n});\n\nreturn (\n <div>\n <div class=\"row mb-2\">\n {props.boardId ? (\n <div class=\"col\">\n <small class=\"text-muted\">\n <a\n class=\"card-link\"\n href={href(\"Boards\", { selectedBoardId: props.boardId })}\n role=\"button\"\n target=\"_blank\"\n title=\"Link to this board\"\n >\n <div class=\"hstack gap-3\">\n <div class=\"bi bi-share\"></div>\n <div>Link to this board</div>\n </div>\n </a>\n </small>\n </div>\n ) : null}\n\n {requiredLabels.length > 0 ? (\n <div class=\"col\">\n <small class=\"text-muted\">\n Required labels:\n {requiredLabels.map((label) => (\n <a href={href(\"Feed\", { label })} key={label}>\n <span class=\"badge text-bg-primary me-1\">{label}</span>\n </a>\n ))}\n </small>\n </div>\n ) : null}\n {excludedLabels.length > 0 ? (\n <div class=\"col\">\n <small class=\"text-muted\">\n Excluded labels:\n {excludedLabels.map((label) => (\n <a href={href(\"Feed\", { label })} key={label}>\n <span class=\"badge text-bg-primary me-1\">{label}</span>\n </a>\n ))}\n </small>\n </div>\n ) : null}\n </div>\n <div class=\"row\">\n {postsPerLabel.map((column) => (\n <div class=\"col-3\" key={column.label}>\n <div class=\"card\">\n <div class=\"card-body border-secondary\">\n <h6 class=\"card-title\">\n {column.title}({column.posts.length})\n </h6>\n {column.posts.map((postId) =>\n widget(\"components.posts.CompactPost\", { id: postId }, postId)\n )}\n </div>\n </div>\n </div>\n ))}\n </div>\n </div>\n);\n" }, "gigs-board.components.community.FeaturedCommunity": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\nconst Hover = styled.div`\n &:hover {\n box-shadow: 0px 1px 3px rgba(16, 24, 40, 0.1),\n 0px 1px 2px rgba(16, 24, 40, 0.06);\n }\n`;\n\nreturn (\n <Hover className=\"card\">\n <a\n href={href(\"community.Overview\", {\n label: props.label,\n })}\n class=\"text-decoration-none text-reset\"\n >\n <img src={props.cover} class=\"card-img-top\"></img>\n <div class=\"h5 pt-3 ps-3\">{props.title}</div>\n <div class=\"ps-3 pb-2 text-secondary\">{props.desc}</div>\n </a>\n </Hover>\n);\n" }, "gigs-board.components.posts.DiscussionFeed": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\n//////////////////////////////////////////////////////////////////////\n///STOPWORDS//////////////////////////////////////////////////////////\nconst stopWords = [\n \"about\",\n \"above\",\n \"after\",\n \"again\",\n \"against\",\n \"all\",\n \"and\",\n \"any\",\n \"are\",\n \"because\",\n \"been\",\n \"before\",\n \"being\",\n \"below\",\n \"between\",\n \"both\",\n \"but\",\n \"can\",\n \"cannot\",\n \"could\",\n \"did\",\n \"does\",\n \"doing\",\n \"down\",\n \"during\",\n \"each\",\n \"etc\",\n \"few\",\n \"for\",\n \"from\",\n \"further\",\n \"had\",\n \"has\",\n \"have\",\n \"having\",\n \"her\",\n \"hers\",\n \"herself\",\n \"him\",\n \"himself\",\n \"his\",\n \"how\",\n \"into\",\n \"its\",\n \"itself\",\n \"just\",\n \"more\",\n \"most\",\n \"myself\",\n \"nor\",\n \"not\",\n \"now\",\n \"off\",\n \"once\",\n \"only\",\n \"other\",\n \"our\",\n \"ours\",\n \"ourselves\",\n \"out\",\n \"over\",\n \"own\",\n \"same\",\n \"she\",\n \"should\",\n \"some\",\n \"still\",\n \"such\",\n \"than\",\n \"that\",\n \"the\",\n \"their\",\n \"theirs\",\n \"them\",\n \"themselves\",\n \"then\",\n \"there\",\n \"these\",\n \"they\",\n \"this\",\n \"those\",\n \"through\",\n \"too\",\n \"under\",\n \"until\",\n \"very\",\n \"was\",\n \"were\",\n \"what\",\n \"when\",\n \"where\",\n \"which\",\n \"while\",\n \"who\",\n \"whom\",\n \"why\",\n \"will\",\n \"with\",\n \"you\",\n \"your\",\n \"yours\",\n \"yourself\",\n \"yourselves\",\n \"www\",\n \"http\",\n \"com\",\n];\n\nconst stopWordsDictionary = {};\nfor (let i = 0; i < stopWords.length; i++) {\n stopWordsDictionary[stopWords[i]] = true;\n}\n\nfunction isStopWord(word) {\n return stopWordsDictionary.hasOwnProperty(word.toLowerCase());\n}\n//////////////////////////////////////////////////////////////////////\n///SYNONYMS///////////////////////////////////////////////////////////\nconst synonyms = {\n ether: \"ethereum\",\n eth: \"ethereum\",\n either: \"ethereum\",\n app: \"application\",\n cryptocyrrency: \"crypto\",\n developerdao: \"devdao\",\n dev: \"develop\",\n doc: \"document\",\n lib: \"librari\",\n saw: \"see\",\n seen: \"see\",\n tweet: \"twitter\",\n paid: \"pai\",\n src: \"sourc\",\n};\n\nconst applySynonym = (word) => {\n if (synonyms.hasOwnProperty(word.toLowerCase())) {\n return synonyms[word];\n }\n return word;\n};\n//////////////////////////////////////////////////////////////////////\n///STEMMING///////////////////////////////////////////////////////////\nconst step2list = {\n ational: \"ate\",\n tional: \"tion\",\n enci: \"ence\",\n anci: \"ance\",\n izer: \"ize\",\n bli: \"ble\",\n alli: \"al\",\n entli: \"ent\",\n eli: \"e\",\n ousli: \"ous\",\n ization: \"ize\",\n ation: \"ate\",\n ator: \"ate\",\n alism: \"al\",\n iveness: \"ive\",\n fulness: \"ful\",\n ousness: \"ous\",\n aliti: \"al\",\n iviti: \"ive\",\n biliti: \"ble\",\n logi: \"log\",\n};\n\n/** @type {Record<string, string>} */\nconst step3list = {\n icate: \"ic\",\n ative: \"\",\n alize: \"al\",\n iciti: \"ic\",\n ical: \"ic\",\n ful: \"\",\n ness: \"\",\n};\n\nconst gt0 = /^([^aeiou][^aeiouy]*)?([aeiouy][aeiou]*)([^aeiou][^aeiouy]*)/;\nconst eq1 =\n /^([^aeiou][^aeiouy]*)?([aeiouy][aeiou]*)([^aeiou][^aeiouy]*)([aeiouy][aeiou]*)?$/;\nconst gt1 =\n /^([^aeiou][^aeiouy]*)?(([aeiouy][aeiou]*)([^aeiou][^aeiouy]*)){2,}/;\nconst vowelInStem = /^([^aeiou][^aeiouy]*)?[aeiouy]/;\nconst consonantLike = /^([^aeiou][^aeiouy]*)[aeiouy][^aeiouwxy]$/;\n\n// Exception expressions.\nconst sfxLl = /ll$/;\nconst sfxE = /^(.+?)e$/;\nconst sfxY = /^(.+?)y$/;\nconst sfxIon = /^(.+?(s|t))(ion)$/;\nconst sfxEdOrIng = /^(.+?)(ed|ing)$/;\nconst sfxAtOrBlOrIz = /(at|bl|iz)$/;\nconst sfxEED = /^(.+?)eed$/;\nconst sfxS = /^.+?[^s]s$/;\nconst sfxSsesOrIes = /^.+?(ss|i)es$/;\nconst sfxMultiConsonantLike = /([^aeiouylsz])\\1$/;\nconst step2 =\n /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/;\nconst step3 = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/;\nconst step4 =\n /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/;\n\n/**\n * Get the stem from a given value.\n *\n * @param {string} value\n * Value to stem.\n * @returns {string}\n * Stem for `value`\n */\n// eslint-disable-next-line complexity\nfunction stemmer(value) {\n let result = value.toLowerCase();\n\n // Exit early.\n if (result.length < 3) {\n return result;\n }\n\n /** @type {boolean} */\n let firstCharacterWasLowerCaseY = false;\n\n // Detect initial `y`, make sure it never matches.\n if (\n result.codePointAt(0) === 121 // Lowercase Y\n ) {\n firstCharacterWasLowerCaseY = true;\n result = \"Y\" + result.slice(1);\n }\n\n // Step 1a.\n if (sfxSsesOrIes.test(result)) {\n // Remove last two characters.\n result = result.slice(0, -2);\n } else if (sfxS.test(result)) {\n // Remove last character.\n result = result.slice(0, -1);\n }\n\n /** @type {RegExpMatchArray|null} */\n let match;\n\n // Step 1b.\n if ((match = sfxEED.exec(result))) {\n if (gt0.test(match[1])) {\n // Remove last character.\n result = result.slice(0, -1);\n }\n } else if ((match = sfxEdOrIng.exec(result)) && vowelInStem.test(match[1])) {\n result = match[1];\n\n if (sfxAtOrBlOrIz.test(result)) {\n // Append `e`.\n result += \"e\";\n } else if (sfxMultiConsonantLike.test(result)) {\n // Remove last character.\n result = result.slice(0, -1);\n } else if (consonantLike.test(result)) {\n // Append `e`.\n result += \"e\";\n }\n }\n\n // Step 1c.\n if ((match = sfxY.exec(result)) && vowelInStem.test(match[1])) {\n // Remove suffixing `y` and append `i`.\n result = match[1] + \"i\";\n }\n\n // Step 2.\n if ((match = step2.exec(result)) && gt0.test(match[1])) {\n result = match[1] + step2list[match[2]];\n }\n\n // Step 3.\n if ((match = step3.exec(result)) && gt0.test(match[1])) {\n result = match[1] + step3list[match[2]];\n }\n\n // Step 4.\n if ((match = step4.exec(result))) {\n if (gt1.test(match[1])) {\n result = match[1];\n }\n } else if ((match = sfxIon.exec(result)) && gt1.test(match[1])) {\n result = match[1];\n }\n\n // Step 5.\n if (\n (match = sfxE.exec(result)) &&\n (gt1.test(match[1]) ||\n (eq1.test(match[1]) && !consonantLike.test(match[1])))\n ) {\n result = match[1];\n }\n\n if (sfxLl.test(result) && gt1.test(result)) {\n result = result.slice(0, -1);\n }\n\n // Turn initial `Y` back to `y`.\n if (firstCharacterWasLowerCaseY) {\n result = \"y\" + result.slice(1);\n }\n\n return result;\n}\n\n//////////////////////////////////////////////////////////////////////\n///SPELLCHECK/////////////////////////////////////////////////////////\nfunction levenshteinDistance(s, t, threshold) {\n const BIG_NUMBER = 10000;\n if (s == null || t == null) {\n return BIG_NUMBER;\n }\n if (threshold < 0) {\n return BIG_NUMBER;\n }\n let n = s.length;\n let m = t.length;\n if (Math.abs(n - m) >= threshold) {\n return BIG_NUMBER;\n }\n\n // if one string is empty, the edit distance is necessarily the length of the other\n if (n == 0) {\n return m <= threshold ? m : BIG_NUMBER;\n } else if (m == 0) {\n return n <= threshold ? n : BIG_NUMBER;\n }\n\n if (n > m) {\n // swap the two strings to consume less memory\n let temp = s;\n s = t;\n t = temp;\n let tempSize = n;\n n = m;\n m = tempSize;\n }\n\n let p = Array.from({ length: n + 1 }, () => 0); // 'previous' cost array, horizontally\n let d = Array.from({ length: n + 1 }, () => 0); // cost array, horizontally\n let _d; // placeholder to assist in swapping p and d\n\n // fill in starting table values\n const boundary = Math.min(n, threshold) + 1;\n for (let i = 0; i < boundary; i++) {\n p[i] = i;\n }\n // these fills ensure that the value above the rightmost entry of our\n // stripe will be ignored in following loop iterations\n for (let i = boundary; i < p.length; i++) {\n p[i] = BIG_NUMBER;\n }\n for (let i = 0; i < d.length; i++) {\n d[i] = BIG_NUMBER;\n }\n\n // iterates through t\n for (let j = 1; j <= m; j++) {\n const t_j = t.charAt(j - 1); // jth character of t\n d[0] = j;\n\n // compute stripe indices, constrain to array size\n const min = Math.max(1, j - threshold);\n const max = j > BIG_NUMBER - threshold ? n : Math.min(n, j + threshold);\n\n // the stripe may lead off of the table if s and t are of different sizes\n if (min > max) {\n return BIG_NUMBER;\n }\n\n // ignore entry left of leftmost\n if (min > 1) {\n d[min - 1] = BIG_NUMBER;\n }\n\n // iterates through [min, max] in s\n for (let i = min; i <= max; i++) {\n if (s.charAt(i - 1) == t_j) {\n // diagonally left and up\n d[i] = p[i - 1];\n } else {\n // 1 + minimum of cell to the left, to the top, diagonally left and up\n d[i] = 1 + Math.min(Math.min(d[i - 1], p[i]), p[i - 1]);\n }\n }\n\n // copy current distance counts to 'previous row' distance counts\n _d = p;\n p = d;\n d = _d;\n }\n // we don't need to check for threshold here because we did it inside the loop\n return p[n] <= threshold ? p[n] : BIG_NUMBER;\n}\n\nconst spellcheckQueryProcessing = (query, dictionary) => {\n // Split text document into words\n const words = stemAndFilterQuery(query);\n const dictionaryArray = Object.keys(dictionary);\n // Iterate over each word in the text\n for (let i = 0; i < words.length; i++) {\n let word = words[i].toLowerCase().replace(/[^a-z0-9]/g, \"\");\n\n // If the word is not in the dictionary, find the closest match\n if (!dictionary.hasOwnProperty(word)) {\n let closestMatch = undefined;\n let closestDistance = word.length;\n let allowedDistance = Math.min(word.length - 1, 3);\n // Iterate over each word in the dictionary\n if (word.length > 1) {\n for (let j = 0; j < dictionaryArray.length; j++) {\n let dictWord = dictionaryArray[j];\n let distance = levenshteinDistance(word, dictWord, allowedDistance);\n\n // If the distance is less than the closest distance, update the closest match\n if (distance <= allowedDistance && distance < closestDistance) {\n closestMatch = dictWord;\n closestDistance = distance;\n }\n }\n }\n // Replace the misspelled word with the closest match\n words[i] = closestMatch;\n }\n }\n return words.filter((word) => !!word);\n};\n\n//////////////////////////////////////////////////////////////////////\n///INDEXER&SEARCH/////////////////////////////////////////////////////\nconst fillDictionaryWith = (dict, text, id) => {\n let word = \"\";\n for (let i = 0; i < text.length; i++) {\n const char = text.charAt(i);\n const nextChar = text.charAt(i + 1);\n if (/\\w/.test(char) || (char === \".\" && /\\w/.test(nextChar))) {\n word += char.toLowerCase();\n } else if (word.length > 0) {\n const processedWord = applySynonym(stemmer(word));\n if (processedWord.length > 1 && !isStopWord(processedWord)) {\n const oldValue = dict[processedWord] || [];\n dict[processedWord] = [...oldValue, id];\n }\n word = \"\";\n }\n }\n const processedWord = applySynonym(stemmer(word));\n if (processedWord.length > 1 && !isStopWord(processedWord)) {\n const oldValue = dict[stemmer(processedWord)] || [];\n dict[stemmer(processedWord)] = [...oldValue, id];\n }\n return dict;\n};\n\nconst buildIndex = (posts) => {\n let index = {};\n\n posts.forEach((post) => {\n const title = post.snapshot.name;\n const labels = post.snapshot.labels.join(\" \");\n const text = post.snapshot.description;\n const postType = post.snapshot.post_type;\n const authorId = post.author_id;\n const postText = `${authorId} ${postType} ${title} ${labels} ${text}`;\n index = fillDictionaryWith(index, postText, post.id);\n });\n return index;\n};\n\nconst stemAndFilterQuery = (query) => {\n return Object.keys(fillDictionaryWith({}, query));\n};\n\nconst sortSearchResult = (searchResult) => {\n // create a map to count the frequency of each element\n const freq = new Map();\n for (const num of searchResult) {\n freq.set(num, (freq.get(num) || 0) + 1);\n }\n\n // define a custom comparison function to sort the array\n function compare(a, b) {\n // compare the frequency of the two elements\n const freqDiff = freq.get(b) - freq.get(a);\n if (freqDiff !== 0) {\n return freqDiff; // if they have different frequency, sort by frequency\n } else {\n return 0; // if they have the same frequency, leave as it is. Will be sorted by search term, by date\n }\n }\n\n // sort the array using the custom comparison function\n searchResult.sort(compare);\n return searchResult.filter(\n (elem, index) => searchResult.indexOf(elem) === index\n );\n};\n\nconst search = (processedQueryArray, index) => {\n return sortSearchResult(\n processedQueryArray.flatMap((queryWord) => {\n const termSearchRes = index[queryWord].reverse();\n const termSortedSearchRes = sortSearchResult(termSearchRes);\n return termSortedSearchRes;\n })\n );\n};\n\n//////////////////////////////////////////////////////////////////////\n///UI&UX//////////////////////////////////////////////////////////////\n//Run search and spelling computation every time the search bar modified\n//but no more frequent than 1 time per 1.5 seconds\nconst amountOfResultsToShowFirst = 5;\n\nconst buildPostsIndex = () => {\n return Near.asyncView(\"devgovgigs.near\", \"get_posts\").then((posts) => {\n const index = buildIndex(posts);\n const data = posts.reduce((acc, post) => {\n acc[post.id] = post;\n return acc;\n }, {});\n return { index, data };\n });\n};\n\nconst getProcessedPostsCached = () => {\n return useCache(() => buildPostsIndex(), \"processedPostsCached\");\n};\n\nif (!state.interval) {\n let termStorage = \"\";\n Storage.privateSet(\"term\", \"\");\n setInterval(() => {\n const currentInput = Storage.privateGet(\"term\");\n if (currentInput !== termStorage) {\n termStorage = currentInput;\n computeResults(termStorage);\n }\n }, 1500);\n State.update({\n interval: true,\n });\n}\n\nconst computeResults = (term) => {\n const start = new Date().getTime();\n const processedPostsCached = useCache(\n () =>\n buildPostsIndex().then((processedPosts) => {\n // Run query first time posts retrieved\n const query = term;\n const processedQuery = spellcheckQueryProcessing(\n query,\n processedPosts.index\n );\n const searchResult = search(processedQuery, processedPosts.index);\n console.log(processedQuery);\n console.log(searchResult);\n State.update({\n searchResult,\n shownSearchResults: searchResult.slice(0, amountOfResultsToShowFirst),\n processedQuery,\n loading: false,\n });\n return processedPosts;\n }),\n \"processedPostsCached\"\n );\n if (processedPostsCached) {\n // Run query every other time after data retrieved and cached\n const query = term;\n const processedQuery = spellcheckQueryProcessing(\n query,\n processedPostsCached.index\n );\n const searchResult = search(processedQuery, processedPostsCached.index);\n console.log(processedQuery);\n console.log(searchResult);\n State.update({\n searchResult,\n shownSearchResults: searchResult.slice(0, 10),\n processedQuery,\n loading: false,\n });\n }\n const end = new Date().getTime();\n console.log(\"search time: \", end - start);\n};\n\nconst updateInput = (term) => {\n Storage.privateSet(\"term\", term);\n State.update({\n term,\n loading: true,\n });\n};\n\nconst getSearchResultsKeywordsFor = (postId) => {\n const index = getProcessedPostsCached().index;\n return state.processedQuery.filter((queryWord) => {\n return index[queryWord].includes(postId);\n });\n};\n\nconst showMoreSearchResults = () => {\n const shownSearchResults = state.shownSearchResults || [];\n const newShownSearchResults = state.searchResult.slice(\n 0,\n shownSearchResults.length + amountOfResultsToShowFirst\n );\n State.update({ shownSearchResults: newShownSearchResults });\n};\n\n// Add a new state value\nif (!state.searchVisible) {\n State.update({\n searchVisible: false,\n });\n}\n\n// Conditionally render the input box\n{\n state.searchVisible && (\n <input\n type=\"search\"\n style={{\n \"padding-left\": \"40px\",\n }}\n className=\"form-control\"\n value={state.term ?? \"\"}\n onChange={(e) => updateInput(e.target.value)}\n placeholder={props.placeholder ?? `Search Posts`}\n />\n );\n}\n\nreturn (\n <div>\n {state.term && state.term.length > 1 && state.searchResult\n ? widget(\"components.posts.List\", {\n searchResult: {\n postIds: state.searchResult,\n keywords: Object.fromEntries(\n state.searchResult.map((postId) => {\n return [postId, getSearchResultsKeywordsFor(postId)];\n })\n ),\n },\n recency: props.recency,\n label: props.label,\n author: props.author,\n })\n : widget(\"components.posts.List\", {\n recency: props.recency,\n label: props.label,\n author: props.author,\n })}\n </div>\n);\n" }, "gigs-board.components.layout.Navbar": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\nreturn (\n <div class=\"card border-secondary mb-2\">\n <div class=\"nav navbar navbar-expand-lg bg-body-tertiary\">\n <div class=\"container-fluid\">\n <ul class=\"navbar-nav me-auto mb-2 mb-lg-0\">\n <li class=\"nav-item \">\n <a class=\"nav-link active\" href={href(\"Feed\")}>\n <i class=\"bi-house-fill\"> </i>\n Home\n </a>\n </li>\n <li class=\"nav-item\">\n <a class=\"nav-link active\" href={href(\"Feed\", { recency: \"all\" })}>\n <i class=\"bi-envelope-fill\"> </i>\n Recent\n </a>\n </li>\n <li class=\"nav-item\">\n <a\n class=\"nav-link active\"\n href={href(\"Feed\", { label: \"recurrent\" })}\n >\n <i class=\"bi-repeat\"> </i>\n Recurrent\n </a>\n </li>\n <li class=\"nav-item\">\n <a class=\"nav-link active\" href={href(\"Feed\", { recency: \"hot\" })}>\n <i class=\"bi-fire\"> </i>\n Hottest\n </a>\n </li>\n <li class=\"nav-item\">\n <a class=\"nav-link active\" href={href(\"Boards\")}>\n <i class=\"bi-kanban\"> </i>\n Boards\n </a>\n </li>\n <li class=\"nav-item\">\n <a\n class=\"nav-link active\"\n href={href(\"Teams\")}\n title=\"View teams and permissions\"\n >\n <i class=\"bi-people-fill\"> </i>\n Teams\n </a>\n </li>\n\n {props.children\n ? props.children.map((child) => (\n <li class=\"nav-item active ms-2\">{child}</li>\n ))\n : null}\n </ul>\n </div>\n </div>\n </div>\n);\n" }, "gigs-board.components.posts.List": { "": "// This component implementation was forked from [IndexFeed], but it does not fully implement lazy loading.\n// While this component uses InfiniteScroll, it still loads the whole list of Post IDs in one view call.\n// The contract will need to be extended with pagination support, yet, even in the current state the page loads much faster.\n// [IndexFeed]: https://near.social/#/mob.near/widget/WidgetSource?src=mob.near/widget/IndexFeed\n\n/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\ninitState({\n period: \"week\",\n});\n\nfunction defaultRenderItem(postId, additionalProps) {\n if (!additionalProps) {\n additionalProps = {};\n }\n // It is important to have a non-zero-height element as otherwise InfiniteScroll loads too many items on initial load\n return (\n <div style={{ minHeight: \"150px\" }}>\n {widget(\n `components.posts.Post`,\n {\n id: postId,\n expandable: true,\n defaultExpanded: false,\n isInList: true,\n ...additionalProps,\n },\n postId\n )}\n </div>\n );\n}\n\nconst renderItem = props.renderItem ?? defaultRenderItem;\n\nconst cachedRenderItem = (item, i) => {\n if (props.searchResult && props.searchResult.keywords[item]) {\n return renderItem(item, {\n searchKeywords: props.searchResult.keywords[item],\n });\n }\n\n const key = JSON.stringify(item);\n\n if (!(key in state.cachedItems)) {\n state.cachedItems[key] = renderItem(item);\n State.update();\n }\n return state.cachedItems[key];\n};\n\nconst initialRenderLimit = props.initialRenderLimit ?? 3;\nconst addDisplayCount = props.nextLimit ?? initialRenderLimit;\n\nfunction getPostsByLabel() {\n let postIds = Near.view(\n nearDevGovGigsContractAccountId,\n \"get_posts_by_label\",\n {\n label: props.label,\n }\n );\n if (postIds) {\n postIds.reverse();\n }\n return postIds;\n}\n\nfunction getPostsByAuthor() {\n let postIds = Near.view(\n nearDevGovGigsContractAccountId,\n \"get_posts_by_author\",\n {\n author: props.author,\n }\n );\n if (postIds) {\n postIds.reverse();\n }\n return postIds;\n}\n\nfunction intersectPostsWithLabel(postIds) {\n if (props.label) {\n let postIdLabels = getPostsByLabel();\n if (postIdLabels === null) {\n // wait until postIdLabels are loaded\n return null;\n }\n postIdLabels = new Set(postIdLabels);\n return postIds.filter((id) => postIdLabels.has(id));\n }\n return postIds;\n}\n\nfunction intersectPostsWithAuthor(postIds) {\n if (props.author) {\n let postIdsByAuthor = getPostsByAuthor();\n if (postIdsByAuthor == null) {\n // wait until postIdsByAuthor are loaded\n return null;\n } else {\n postIdsByAuthor = new Set(postIdsByAuthor);\n return postIds.filter((id) => postIdsByAuthor.has(id));\n }\n }\n return postIds;\n}\n\nconst ONE_DAY = 60 * 60 * 24 * 1000;\nconst ONE_WEEK = 60 * 60 * 24 * 1000 * 7;\nconst ONE_MONTH = 60 * 60 * 24 * 1000 * 30;\n\nfunction getHotnessScore(post) {\n //post.id - shows the age of the post, should grow exponentially, since newer posts are more important\n //post.likes.length - linear value\n const age = Math.pow(post.id, 5);\n const comments = post.comments;\n const commentAge = comments.reduce((sum, age) => sum + Math.pow(age, 5), 0);\n const totalAge = age + commentAge;\n //use log functions to make likes score and exponentially big age score close to each other\n return Math.log10(post.likes.length) + Math.log(Math.log10(totalAge));\n}\n\nconst getPeriodText = (period) => {\n let text = \"Last 24 hours\";\n if (period === \"week\") {\n text = \"Last week\";\n }\n if (period === \"month\") {\n text = \"Last month\";\n }\n return text;\n};\n\nconst findHottestsPosts = (postIds, period) => {\n let allPosts;\n if (!state.allPosts) {\n allPosts = Near.view(\"devgovgigs.near\", \"get_posts\");\n if (!allPosts) {\n return [];\n }\n State.update({ allPosts });\n } else {\n allPosts = state.allPosts;\n }\n let postIdsSet = new Set(postIds);\n let posts = allPosts.filter((post) => postIdsSet.has(post.id));\n\n let periodTime = ONE_DAY;\n if (period === \"week\") {\n periodTime = ONE_WEEK;\n }\n if (period === \"month\") {\n periodTime = ONE_MONTH;\n }\n const periodLimitedPosts = posts.filter((post) => {\n const timestamp = post.snapshot.timestamp / 1000000;\n return Date.now() - timestamp < periodTime;\n });\n const modifiedPosts = periodLimitedPosts.map((post) => {\n const comments =\n Near.view(\"devgovgigs.near\", \"get_children_ids\", {\n post_id: post.id,\n }) || [];\n post = { ...post, comments };\n return {\n ...post,\n postScore: getHotnessScore(post),\n };\n });\n modifiedPosts.sort((a, b) => b.postScore - a.postScore);\n return modifiedPosts.map((post) => post.id);\n};\n\nlet postIds;\nif (props.searchResult) {\n postIds = props.searchResult.postIds;\n postIds = intersectPostsWithLabel(postIds);\n postIds = intersectPostsWithAuthor(postIds);\n} else if (props.label) {\n postIds = getPostsByLabel();\n postIds = intersectPostsWithAuthor(postIds);\n} else if (props.author) {\n postIds = getPostsByAuthor();\n} else if (props.recency == \"all\") {\n postIds = Near.view(nearDevGovGigsContractAccountId, \"get_all_post_ids\");\n if (postIds) {\n postIds.reverse();\n }\n} else {\n postIds = Near.view(nearDevGovGigsContractAccountId, \"get_children_ids\");\n if (postIds) {\n postIds.reverse();\n }\n}\n\nif (props.recency == \"hot\") {\n postIds = findHottestsPosts(postIds, state.period);\n}\n\nconst loader = (\n <div className=\"loader\" key={\"loader\"}>\n <span\n className=\"spinner-grow spinner-grow-sm me-1\"\n role=\"status\"\n aria-hidden=\"true\"\n />\n Loading ...\n </div>\n);\n\nif (postIds === null) {\n return loader;\n}\nconst initialItems = postIds;\n//const initialItems = postIds.map(postId => ({ id: postId, ...Near.view(nearDevGovGigsContractAccountId, \"get_post\", { post_id: postId }) }));\n\n// const computeFetchFrom = (items, limit) => {\n// if (!items || items.length < limit) {\n// return false;\n// }\n// const blockHeight = items[items.length - 1].blockHeight;\n// return index.options.order === \"desc\" ? blockHeight - 1 : blockHeight + 1;\n// };\n\n// const mergeItems = (newItems) => {\n// const items = [\n// ...new Set([...newItems, ...state.items].map((i) => JSON.stringify(i))),\n// ].map((i) => JSON.parse(i));\n// items.sort((a, b) => a.blockHeight - b.blockHeight);\n// if (index.options.order === \"desc\") {\n// items.reverse();\n// }\n// return items;\n// };\n\nconst jInitialItems = JSON.stringify(initialItems);\nif (state.jInitialItems !== jInitialItems) {\n // const jIndex = JSON.stringify(index);\n // if (jIndex !== state.jIndex) {\n State.update({\n jIndex,\n jInitialItems,\n items: initialItems,\n fetchFrom: false,\n //nextFetchFrom: computeFetchFrom(initialItems, index.options.limit),\n nextFetchFrom: false,\n displayCount: initialRenderLimit,\n cachedItems: {},\n });\n // } else {\n // State.update({\n // jInitialItems,\n // items: mergeItems(initialItems),\n // });\n // }\n}\n\nif (state.fetchFrom) {\n console.log(\"TODO: fetchFrom\");\n // const limit = addDisplayCount;\n // const newItems = Social.index(\n // index.action,\n // index.key,\n // Object.assign({}, index.options, {\n // from: state.fetchFrom,\n // subscribe: undefined,\n // limit,\n // })\n // );\n // if (newItems !== null) {\n // State.update({\n // items: mergeItems(newItems),\n // fetchFrom: false,\n // nextFetchFrom: computeFetchFrom(newItems, limit),\n // });\n // }\n}\n\nconst makeMoreItems = () => {\n State.update({\n displayCount: state.displayCount + addDisplayCount,\n });\n if (\n state.items.length - state.displayCount < addDisplayCount * 2 &&\n !state.fetchFrom &&\n state.nextFetchFrom &&\n state.nextFetchFrom !== state.fetchFrom\n ) {\n State.update({\n fetchFrom: state.nextFetchFrom,\n });\n }\n};\n\nconst fetchMore =\n props.manual &&\n (state.fetchFrom && state.items.length < state.displayCount\n ? loader\n : state.displayCount < state.items.length && (\n <div key={\"loader more\"}>\n <a href=\"javascript:void\" onClick={(e) => makeMoreItems()}>\n {props.loadMoreText ?? \"Load more...\"}\n </a>\n </div>\n ));\n\nconst items = state.items ? state.items.slice(0, state.displayCount) : [];\n\nconsole.log(items);\nconst renderedItems = items.map(cachedRenderItem);\n\nconst Head =\n props.recency == \"hot\" ? (\n <div class=\"row\">\n <div class=\"fs-5 col-6 align-self-center\">\n <i class=\"bi-fire\"></i>\n <span>Hottest Posts</span>\n </div>\n <div class=\"col-6 dropdown d-flex justify-content-end\">\n <a\n class=\"btn btn-secondary dropdown-toggle\"\n href=\"#\"\n role=\"button\"\n id=\"dropdownMenuLink\"\n data-bs-toggle=\"dropdown\"\n aria-expanded=\"false\"\n >\n {getPeriodText(state.period)}\n </a>\n\n <ul class=\"dropdown-menu\" aria-labelledby=\"dropdownMenuLink\">\n <li>\n <button\n class=\"dropdown-item\"\n onClick={() => {\n State.update({ period: \"day\" });\n }}\n >\n {getPeriodText(\"day\")}\n </button>\n </li>\n <li>\n <button\n class=\"dropdown-item\"\n onClick={() => {\n State.update({ period: \"week\" });\n }}\n >\n {getPeriodText(\"week\")}\n </button>\n </li>\n <li>\n <button\n class=\"dropdown-item\"\n onClick={() => {\n State.update({ period: \"month\" });\n }}\n >\n {getPeriodText(\"month\")}\n </button>\n </li>\n </ul>\n </div>\n </div>\n ) : (\n <></>\n );\n\nreturn (\n <>\n {Head}\n {state.items.length > 0 ? (\n <InfiniteScroll\n pageStart={0}\n loadMore={makeMoreItems}\n hasMore={state.displayCount < state.items.length}\n loader={loader}\n >\n {renderedItems}\n </InfiniteScroll>\n ) : (\n <p class=\"text-secondary\">\n No posts {props.searchResult ? \"matches search\" : \"\"}\n {props.recency == \"hot\"\n ? \" in \" + getPeriodText(state.period).toLowerCase()\n : \"\"}\n </p>\n )}\n </>\n);\n" }, "gigs-board.components.posts.Search": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\n//////////////////////////////////////////////////////////////////////\n///STOPWORDS//////////////////////////////////////////////////////////\nconst stopWords = [\n \"about\",\n \"above\",\n \"after\",\n \"again\",\n \"against\",\n \"all\",\n \"and\",\n \"any\",\n \"are\",\n \"because\",\n \"been\",\n \"before\",\n \"being\",\n \"below\",\n \"between\",\n \"both\",\n \"but\",\n \"can\",\n \"cannot\",\n \"could\",\n \"did\",\n \"does\",\n \"doing\",\n \"down\",\n \"during\",\n \"each\",\n \"etc\",\n \"few\",\n \"for\",\n \"from\",\n \"further\",\n \"had\",\n \"has\",\n \"have\",\n \"having\",\n \"her\",\n \"hers\",\n \"herself\",\n \"him\",\n \"himself\",\n \"his\",\n \"how\",\n \"into\",\n \"its\",\n \"itself\",\n \"just\",\n \"more\",\n \"most\",\n \"myself\",\n \"nor\",\n \"not\",\n \"now\",\n \"off\",\n \"once\",\n \"only\",\n \"other\",\n \"our\",\n \"ours\",\n \"ourselves\",\n \"out\",\n \"over\",\n \"own\",\n \"same\",\n \"she\",\n \"should\",\n \"some\",\n \"still\",\n \"such\",\n \"than\",\n \"that\",\n \"the\",\n \"their\",\n \"theirs\",\n \"them\",\n \"themselves\",\n \"then\",\n \"there\",\n \"these\",\n \"they\",\n \"this\",\n \"those\",\n \"through\",\n \"too\",\n \"under\",\n \"until\",\n \"very\",\n \"was\",\n \"were\",\n \"what\",\n \"when\",\n \"where\",\n \"which\",\n \"while\",\n \"who\",\n \"whom\",\n \"why\",\n \"will\",\n \"with\",\n \"you\",\n \"your\",\n \"yours\",\n \"yourself\",\n \"yourselves\",\n \"www\",\n \"http\",\n \"com\",\n];\n\nconst stopWordsDictionary = {};\nfor (let i = 0; i < stopWords.length; i++) {\n stopWordsDictionary[stopWords[i]] = true;\n}\n\nfunction isStopWord(word) {\n return stopWordsDictionary.hasOwnProperty(word.toLowerCase());\n}\n//////////////////////////////////////////////////////////////////////\n///SYNONYMS///////////////////////////////////////////////////////////\nconst synonyms = {\n ether: \"ethereum\",\n eth: \"ethereum\",\n either: \"ethereum\",\n app: \"application\",\n cryptocyrrency: \"crypto\",\n developerdao: \"devdao\",\n dev: \"develop\",\n doc: \"document\",\n lib: \"librari\",\n saw: \"see\",\n seen: \"see\",\n tweet: \"twitter\",\n paid: \"pai\",\n src: \"sourc\",\n};\n\nconst applySynonym = (word) => {\n if (synonyms.hasOwnProperty(word.toLowerCase())) {\n return synonyms[word];\n }\n return word;\n};\n//////////////////////////////////////////////////////////////////////\n///STEMMING///////////////////////////////////////////////////////////\nconst step2list = {\n ational: \"ate\",\n tional: \"tion\",\n enci: \"ence\",\n anci: \"ance\",\n izer: \"ize\",\n bli: \"ble\",\n alli: \"al\",\n entli: \"ent\",\n eli: \"e\",\n ousli: \"ous\",\n ization: \"ize\",\n ation: \"ate\",\n ator: \"ate\",\n alism: \"al\",\n iveness: \"ive\",\n fulness: \"ful\",\n ousness: \"ous\",\n aliti: \"al\",\n iviti: \"ive\",\n biliti: \"ble\",\n logi: \"log\",\n};\n\n/** @type {Record<string, string>} */\nconst step3list = {\n icate: \"ic\",\n ative: \"\",\n alize: \"al\",\n iciti: \"ic\",\n ical: \"ic\",\n ful: \"\",\n ness: \"\",\n};\n\nconst gt0 = /^([^aeiou][^aeiouy]*)?([aeiouy][aeiou]*)([^aeiou][^aeiouy]*)/;\nconst eq1 =\n /^([^aeiou][^aeiouy]*)?([aeiouy][aeiou]*)([^aeiou][^aeiouy]*)([aeiouy][aeiou]*)?$/;\nconst gt1 =\n /^([^aeiou][^aeiouy]*)?(([aeiouy][aeiou]*)([^aeiou][^aeiouy]*)){2,}/;\nconst vowelInStem = /^([^aeiou][^aeiouy]*)?[aeiouy]/;\nconst consonantLike = /^([^aeiou][^aeiouy]*)[aeiouy][^aeiouwxy]$/;\n\n// Exception expressions.\nconst sfxLl = /ll$/;\nconst sfxE = /^(.+?)e$/;\nconst sfxY = /^(.+?)y$/;\nconst sfxIon = /^(.+?(s|t))(ion)$/;\nconst sfxEdOrIng = /^(.+?)(ed|ing)$/;\nconst sfxAtOrBlOrIz = /(at|bl|iz)$/;\nconst sfxEED = /^(.+?)eed$/;\nconst sfxS = /^.+?[^s]s$/;\nconst sfxSsesOrIes = /^.+?(ss|i)es$/;\nconst sfxMultiConsonantLike = /([^aeiouylsz])\\1$/;\nconst step2 =\n /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/;\nconst step3 = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/;\nconst step4 =\n /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/;\n\n/**\n * Get the stem from a given value.\n *\n * @param {string} value\n * Value to stem.\n * @returns {string}\n * Stem for `value`\n */\n// eslint-disable-next-line complexity\nfunction stemmer(value) {\n let result = value.toLowerCase();\n\n // Exit early.\n if (result.length < 3) {\n return result;\n }\n\n /** @type {boolean} */\n let firstCharacterWasLowerCaseY = false;\n\n // Detect initial `y`, make sure it never matches.\n if (\n result.codePointAt(0) === 121 // Lowercase Y\n ) {\n firstCharacterWasLowerCaseY = true;\n result = \"Y\" + result.slice(1);\n }\n\n // Step 1a.\n if (sfxSsesOrIes.test(result)) {\n // Remove last two characters.\n result = result.slice(0, -2);\n } else if (sfxS.test(result)) {\n // Remove last character.\n result = result.slice(0, -1);\n }\n\n /** @type {RegExpMatchArray|null} */\n let match;\n\n // Step 1b.\n if ((match = sfxEED.exec(result))) {\n if (gt0.test(match[1])) {\n // Remove last character.\n result = result.slice(0, -1);\n }\n } else if ((match = sfxEdOrIng.exec(result)) && vowelInStem.test(match[1])) {\n result = match[1];\n\n if (sfxAtOrBlOrIz.test(result)) {\n // Append `e`.\n result += \"e\";\n } else if (sfxMultiConsonantLike.test(result)) {\n // Remove last character.\n result = result.slice(0, -1);\n } else if (consonantLike.test(result)) {\n // Append `e`.\n result += \"e\";\n }\n }\n\n // Step 1c.\n if ((match = sfxY.exec(result)) && vowelInStem.test(match[1])) {\n // Remove suffixing `y` and append `i`.\n result = match[1] + \"i\";\n }\n\n // Step 2.\n if ((match = step2.exec(result)) && gt0.test(match[1])) {\n result = match[1] + step2list[match[2]];\n }\n\n // Step 3.\n if ((match = step3.exec(result)) && gt0.test(match[1])) {\n result = match[1] + step3list[match[2]];\n }\n\n // Step 4.\n if ((match = step4.exec(result))) {\n if (gt1.test(match[1])) {\n result = match[1];\n }\n } else if ((match = sfxIon.exec(result)) && gt1.test(match[1])) {\n result = match[1];\n }\n\n // Step 5.\n if (\n (match = sfxE.exec(result)) &&\n (gt1.test(match[1]) ||\n (eq1.test(match[1]) && !consonantLike.test(match[1])))\n ) {\n result = match[1];\n }\n\n if (sfxLl.test(result) && gt1.test(result)) {\n result = result.slice(0, -1);\n }\n\n // Turn initial `Y` back to `y`.\n if (firstCharacterWasLowerCaseY) {\n result = \"y\" + result.slice(1);\n }\n\n return result;\n}\n\n//////////////////////////////////////////////////////////////////////\n///SPELLCHECK/////////////////////////////////////////////////////////\nfunction levenshteinDistance(s, t, threshold) {\n const BIG_NUMBER = 10000;\n if (s == null || t == null) {\n return BIG_NUMBER;\n }\n if (threshold < 0) {\n return BIG_NUMBER;\n }\n let n = s.length;\n let m = t.length;\n if (Math.abs(n - m) >= threshold) {\n return BIG_NUMBER;\n }\n\n // if one string is empty, the edit distance is necessarily the length of the other\n if (n == 0) {\n return m <= threshold ? m : BIG_NUMBER;\n } else if (m == 0) {\n return n <= threshold ? n : BIG_NUMBER;\n }\n\n if (n > m) {\n // swap the two strings to consume less memory\n let temp = s;\n s = t;\n t = temp;\n let tempSize = n;\n n = m;\n m = tempSize;\n }\n\n let p = Array.from({ length: n + 1 }, () => 0); // 'previous' cost array, horizontally\n let d = Array.from({ length: n + 1 }, () => 0); // cost array, horizontally\n let _d; // placeholder to assist in swapping p and d\n\n // fill in starting table values\n const boundary = Math.min(n, threshold) + 1;\n for (let i = 0; i < boundary; i++) {\n p[i] = i;\n }\n // these fills ensure that the value above the rightmost entry of our\n // stripe will be ignored in following loop iterations\n for (let i = boundary; i < p.length; i++) {\n p[i] = BIG_NUMBER;\n }\n for (let i = 0; i < d.length; i++) {\n d[i] = BIG_NUMBER;\n }\n\n // iterates through t\n for (let j = 1; j <= m; j++) {\n const t_j = t.charAt(j - 1); // jth character of t\n d[0] = j;\n\n // compute stripe indices, constrain to array size\n const min = Math.max(1, j - threshold);\n const max = j > BIG_NUMBER - threshold ? n : Math.min(n, j + threshold);\n\n // the stripe may lead off of the table if s and t are of different sizes\n if (min > max) {\n return BIG_NUMBER;\n }\n\n // ignore entry left of leftmost\n if (min > 1) {\n d[min - 1] = BIG_NUMBER;\n }\n\n // iterates through [min, max] in s\n for (let i = min; i <= max; i++) {\n if (s.charAt(i - 1) == t_j) {\n // diagonally left and up\n d[i] = p[i - 1];\n } else {\n // 1 + minimum of cell to the left, to the top, diagonally left and up\n d[i] = 1 + Math.min(Math.min(d[i - 1], p[i]), p[i - 1]);\n }\n }\n\n // copy current distance counts to 'previous row' distance counts\n _d = p;\n p = d;\n d = _d;\n }\n // we don't need to check for threshold here because we did it inside the loop\n return p[n] <= threshold ? p[n] : BIG_NUMBER;\n}\n\nconst spellcheckQueryProcessing = (query, dictionary) => {\n // Split text document into words\n const words = stemAndFilterQuery(query);\n const dictionaryArray = Object.keys(dictionary);\n // Iterate over each word in the text\n for (let i = 0; i < words.length; i++) {\n let word = words[i].toLowerCase().replace(/[^a-z0-9]/g, \"\");\n\n // If the word is not in the dictionary, find the closest match\n if (!dictionary.hasOwnProperty(word)) {\n let closestMatch = undefined;\n let closestDistance = word.length;\n let allowedDistance = Math.min(word.length - 1, 3);\n // Iterate over each word in the dictionary\n if (word.length > 1) {\n for (let j = 0; j < dictionaryArray.length; j++) {\n let dictWord = dictionaryArray[j];\n let distance = levenshteinDistance(word, dictWord, allowedDistance);\n\n // If the distance is less than the closest distance, update the closest match\n if (distance <= allowedDistance && distance < closestDistance) {\n closestMatch = dictWord;\n closestDistance = distance;\n }\n }\n }\n // Replace the misspelled word with the closest match\n words[i] = closestMatch;\n }\n }\n return words.filter((word) => !!word);\n};\n\n//////////////////////////////////////////////////////////////////////\n///INDEXER&SEARCH/////////////////////////////////////////////////////\nconst fillDictionaryWith = (dict, text, id) => {\n let word = \"\";\n for (let i = 0; i < text.length; i++) {\n const char = text.charAt(i);\n const nextChar = text.charAt(i + 1);\n if (/\\w/.test(char) || (char === \".\" && /\\w/.test(nextChar))) {\n word += char.toLowerCase();\n } else if (word.length > 0) {\n const processedWord = applySynonym(stemmer(word));\n if (processedWord.length > 1 && !isStopWord(processedWord)) {\n const oldValue = dict[processedWord] || [];\n dict[processedWord] = [...oldValue, id];\n }\n word = \"\";\n }\n }\n const processedWord = applySynonym(stemmer(word));\n if (processedWord.length > 1 && !isStopWord(processedWord)) {\n const oldValue = dict[stemmer(processedWord)] || [];\n dict[stemmer(processedWord)] = [...oldValue, id];\n }\n return dict;\n};\n\nconst buildIndex = (posts) => {\n let index = {};\n\n posts.forEach((post) => {\n const title = post.snapshot.name;\n const labels = post.snapshot.labels.join(\" \");\n const text = post.snapshot.description;\n const postType = post.snapshot.post_type;\n const authorId = post.author_id;\n const postText = `${authorId} ${postType} ${title} ${labels} ${text}`;\n index = fillDictionaryWith(index, postText, post.id);\n });\n return index;\n};\n\nconst stemAndFilterQuery = (query) => {\n return Object.keys(fillDictionaryWith({}, query));\n};\n\nconst sortSearchResult = (searchResult) => {\n // create a map to count the frequency of each element\n const freq = new Map();\n for (const num of searchResult) {\n freq.set(num, (freq.get(num) || 0) + 1);\n }\n\n // define a custom comparison function to sort the array\n function compare(a, b) {\n // compare the frequency of the two elements\n const freqDiff = freq.get(b) - freq.get(a);\n if (freqDiff !== 0) {\n return freqDiff; // if they have different frequency, sort by frequency\n } else {\n return 0; // if they have the same frequency, leave as it is. Will be sorted by search term, by date\n }\n }\n\n // sort the array using the custom comparison function\n searchResult.sort(compare);\n return searchResult.filter(\n (elem, index) => searchResult.indexOf(elem) === index\n );\n};\n\nconst search = (processedQueryArray, index) => {\n return sortSearchResult(\n processedQueryArray.flatMap((queryWord) => {\n const termSearchRes = index[queryWord].reverse();\n const termSortedSearchRes = sortSearchResult(termSearchRes);\n return termSortedSearchRes;\n })\n );\n};\n\n//////////////////////////////////////////////////////////////////////\n///UI&UX//////////////////////////////////////////////////////////////\n//Run search and spelling computation every time the search bar modified\n//but no more frequent than 1 time per 1.5 seconds\nconst amountOfResultsToShowFirst = 5;\n\nconst buildPostsIndex = () => {\n return Near.asyncView(\"devgovgigs.near\", \"get_posts\").then((posts) => {\n const index = buildIndex(posts);\n const data = posts.reduce((acc, post) => {\n acc[post.id] = post;\n return acc;\n }, {});\n return { index, data };\n });\n};\n\nconst getProcessedPostsCached = () => {\n return useCache(() => buildPostsIndex(), \"processedPostsCached\");\n};\n\nif (!state.interval) {\n let termStorage = \"\";\n Storage.privateSet(\"term\", \"\");\n setInterval(() => {\n const currentInput = Storage.privateGet(\"term\");\n if (currentInput !== termStorage) {\n termStorage = currentInput;\n computeResults(termStorage);\n }\n }, 1500);\n State.update({\n interval: true,\n });\n}\n\nconst computeResults = (term) => {\n const start = new Date().getTime();\n const processedPostsCached = useCache(\n () =>\n buildPostsIndex().then((processedPosts) => {\n // Run query first time posts retrieved\n const query = term;\n const processedQuery = spellcheckQueryProcessing(\n query,\n processedPosts.index\n );\n const searchResult = search(processedQuery, processedPosts.index);\n console.log(processedQuery);\n console.log(searchResult);\n State.update({\n searchResult,\n shownSearchResults: searchResult.slice(0, amountOfResultsToShowFirst),\n processedQuery,\n loading: false,\n });\n return processedPosts;\n }),\n \"processedPostsCached\"\n );\n if (processedPostsCached) {\n // Run query every other time after data retrieved and cached\n const query = term;\n const processedQuery = spellcheckQueryProcessing(\n query,\n processedPostsCached.index\n );\n const searchResult = search(processedQuery, processedPostsCached.index);\n console.log(processedQuery);\n console.log(searchResult);\n State.update({\n searchResult,\n shownSearchResults: searchResult.slice(0, 10),\n processedQuery,\n loading: false,\n });\n }\n const end = new Date().getTime();\n console.log(\"search time: \", end - start);\n};\n\nconst updateInput = (term) => {\n Storage.privateSet(\"term\", term);\n State.update({\n term,\n loading: true,\n });\n};\n\nconst getSearchResultsKeywordsFor = (postId) => {\n const index = getProcessedPostsCached().index;\n return state.processedQuery.filter((queryWord) => {\n return index[queryWord].includes(postId);\n });\n};\n\nconst showMoreSearchResults = () => {\n const shownSearchResults = state.shownSearchResults || [];\n const newShownSearchResults = state.searchResult.slice(\n 0,\n shownSearchResults.length + amountOfResultsToShowFirst\n );\n State.update({ shownSearchResults: newShownSearchResults });\n};\n\nreturn (\n <>\n <div className=\"d-flex flex-row gap-4\">\n <div className=\"d-flex flex-row position-relative w-25\">\n <div className=\"position-absolute d-flex ps-3 flex-column h-100 justify-center\">\n {state.loading ? (\n <span\n className=\"spinner-grow spinner-grow-sm m-auto\"\n role=\"status\"\n aria-hidden=\"true\"\n />\n ) : (\n <i class=\"bi bi-search m-auto\"></i>\n )}\n </div>\n <input\n type=\"search\"\n className=\"ps-5 form-control border border-0 bg-light\"\n value={state.term ?? \"\"}\n onChange={(e) => updateInput(e.target.value)}\n placeholder={props.placeholder ?? `Search Posts`}\n />\n </div>\n <div class=\"dropdown\">\n <button\n class=\"btn btn-light dropdown-toggle\"\n type=\"button\"\n data-bs-toggle=\"dropdown\"\n aria-expanded=\"false\"\n >\n Sort\n </button>\n <ul class=\"dropdown-menu px-2 shadow\">\n <li>\n <a\n style={{ borderRadius: \"5px\" }}\n class=\"dropdown-item link-underline link-underline-opacity-0\"\n href={href(\"Feed\")}\n >\n Latest\n </a>\n </li>\n <li>\n <a\n style={{ borderRadius: \"5px\" }}\n class=\"dropdown-item link-underline link-underline-opacity-0\"\n href={href(\"Feed\", { recency: \"hot\" })}\n >\n Hottest\n </a>\n </li>\n <li>\n <a\n style={{ borderRadius: \"5px\" }}\n class=\"dropdown-item link-underline link-underline-opacity-0\"\n href={href(\"Feed\", { recency: \"all\" })}\n >\n All replies\n </a>\n </li>\n </ul>\n </div>\n <div class=\"dropdown\">\n {widget(\"components.layout.SearchByAuthor\", {\n authorQuery: props.authorQuery,\n onSearchAuthor: props.onSearchAuthor,\n })}\n </div>\n <div>\n {widget(\"components.layout.SearchByLabel\", {\n labelQuery: props.labelQuery,\n onSearchLabel: props.onSearchLabel,\n })}\n </div>\n <div className=\"d-flex flex-row-reverse flex-grow-1\">\n {props.children}\n </div>\n </div>\n {state.processedQuery &&\n state.processedQuery.length > 0 &&\n state.term.toLowerCase().trim() !== state.processedQuery.join(\" \") && (\n <div class=\"mb-2\" style={{ \"font-family\": \"monospace\" }}>\n Looking for\n <strong>{state.processedQuery.join(\" \")}</strong>:\n </div>\n )}\n {state.term && state.term.length > 1 && state.searchResult\n ? widget(\"components.posts.List\", {\n searchResult: {\n postIds: state.searchResult,\n keywords: Object.fromEntries(\n state.searchResult.map((postId) => {\n return [postId, getSearchResultsKeywordsFor(postId)];\n })\n ),\n },\n recency: props.recency,\n label: props.label,\n author: props.author,\n })\n : widget(\"components.posts.List\", {\n recency: props.recency,\n label: props.label,\n author: props.author,\n })}\n </>\n);\n" }, "gigs-board.pages.community.Events": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\n/* INCLUDE: \"shared/mocks\" */\nconst communities = {\n \"zero-knowledge\": {\n overviewId: 397,\n eventsId: 401,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreiajwq6ep3n7veddozji2djv5vviyisabhycbweslvpwhsoyuzcwi4\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreihgxg5kwts2juldaeasveyuddkm6tcabmrat2aaq5u6uyljtyt7lu\",\n\n title: \"Zero Knowledge\",\n desc: \"Building a zero knowledge ecosystem on NEAR.\",\n telegram: \"NearZeroKnowledge\",\n },\n\n protocol: {\n overviewId: 412,\n eventsId: 413,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreidpitdafcnhkp4uyomacypdgqvxr35jtfnbxa5s6crby7qjk2nv5a\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreicg4svzfz5nvllomsahndgm7u62za4sib4mmbygxzhpcl4htqwr4a\",\n\n title: \"Protocol\",\n desc: \"Supporting the ongoing innovation of the NEAR Protocol.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-protocol\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Protocol NEPs\",\n },\n },\n },\n },\n\n telegram: \"NEAR_Protocol_Community_Group\",\n },\n\n tooling: {\n overviewId: 416,\n eventsId: 417,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreie2eaj5czmpfe6pe53kojzcspgozebdsonffwvbxtpuipnwahybvi\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreiehzr7z2fhoqqmkt3z667wubccbch6sqtsnvd6msodyzpnf72cszy\",\n\n title: \"Tooling\",\n desc: \"Supporting the ongoing innovation of tooling.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-tools\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Tooling NEPs\",\n },\n },\n },\n },\n\n telegram: \"NEAR_Tools_Community_Group\",\n },\n\n \"contract-standards\": {\n overviewId: 414,\n eventsId: 415,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreiepgdnu7soc6xgbyd4adicbf3eyxiiwqawn6tguaix6aklfpir634\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreiaowjqxds24fwcliyriintjd4ucciprii2rdxjmxgi7f5dmzuscey\",\n\n title: \"Contract Standards\",\n desc: \"Coordinating the contribution to the NEAR dapp standards.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Contract Standards NEPs\",\n },\n },\n },\n },\n\n telegram: \"nearnft\",\n },\n};\n/* END_INCLUDE: \"shared/mocks\" */\n\nif (!props.label) {\n return (\n <div class=\"alert alert-danger\" role=\"alert\">\n Error: label is required\n </div>\n );\n}\n\nconst community = communities[props.label];\n\nconst eventsPost = Near.view(nearDevGovGigsContractAccountId, \"get_post\", {\n post_id: community.eventsId,\n});\nif (!eventsPost) {\n return <div>Loading ...</div>;\n}\n\nconst onMention = (accountId) => (\n <span key={accountId} className=\"d-inline-flex\" style={{ fontWeight: 500 }}>\n <Widget\n src=\"neardevgov.near/widget/ProfileLine\"\n props={{\n accountId: accountId.toLowerCase(),\n hideAccountId: true,\n tooltip: true,\n }}\n />\n </span>\n);\n\nconst Events = (\n <div>\n <Markdown\n class=\"card-text\"\n text={eventsPost.snapshot.description}\n onMention={onMention}\n ></Markdown>\n </div>\n);\n\nreturn widget(\"components.community.Layout\", {\n label: props.label,\n tab: \"Events\",\n children: Events,\n});\n" }, "gigs-board.pages.Create": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\nconst parentId = props.parentId ?? null;\nconst postId = props.postId ?? null;\nconst mode = props.mode ?? \"Create\";\n\nconst referralLabels = props.referral ? [`referral:${props.referral}`] : [];\nconst labelStrings = (props.labels ? props.labels.split(\",\") : []).concat(\n referralLabels\n);\nconst labels = labelStrings.map((s) => {\n return { name: s };\n});\n\ninitState({\n seekingFunding: false,\n //\n author_id: context.accountId,\n // Should be a list of objects with field \"name\".\n labels,\n // Should be a list of labels as strings.\n // Both of the label structures should be modified together.\n labelStrings,\n postType: \"Idea\",\n name: props.name ?? \"\",\n description: props.description ?? \"\",\n amount: props.amount ?? \"\",\n token: props.token ?? \"NEAR\",\n supervisor: props.supervisor ?? \"neardevgov.near\",\n githubLink: props.githubLink ?? \"\",\n warning: \"\",\n});\n\n// This must be outside onClick, because Near.view returns null at first, and when the view call finished, it returns true/false.\n// If checking this inside onClick, it will give `null` and we cannot tell the result is true or false.\nlet grantNotify = Near.view(\"social.near\", \"is_write_permission_granted\", {\n predecessor_id: nearDevGovGigsContractAccountId,\n key: context.accountId + \"/index/notify\",\n});\nif (grantNotify === null) {\n return;\n}\n\nconst onSubmit = () => {\n let labels = state.labelStrings;\n\n let body = {\n name: state.name,\n description: generateDescription(\n state.description,\n state.amount,\n state.token,\n state.supervisor\n ),\n };\n\n if (state.postType === \"Solution\") {\n body = {\n ...body,\n post_type: \"Submission\",\n submission_version: \"V1\",\n };\n } else {\n // Idea\n body = {\n ...body,\n post_type: \"Idea\",\n idea_version: \"V1\",\n };\n }\n\n if (!context.accountId) return;\n\n let txn = [];\n if (mode == \"Create\") {\n txn.push({\n contractName: nearDevGovGigsContractAccountId,\n methodName: \"add_post\",\n args: {\n parent_id: parentId,\n labels,\n body: body,\n },\n deposit: Big(10).pow(21).mul(3),\n gas: Big(10).pow(12).mul(100),\n });\n } else if (mode == \"Edit\") {\n txn.push({\n contractName: nearDevGovGigsContractAccountId,\n methodName: \"edit_post\",\n args: {\n id: postId,\n labels,\n body: body,\n },\n deposit: Big(10).pow(21).mul(2),\n gas: Big(10).pow(12).mul(100),\n });\n }\n if (mode == \"Create\" || mode == \"Edit\") {\n if (grantNotify === false) {\n txn.unshift({\n contractName: \"social.near\",\n methodName: \"grant_write_permission\",\n args: {\n predecessor_id: nearDevGovGigsContractAccountId,\n keys: [context.accountId + \"/index/notify\"],\n },\n deposit: Big(10).pow(23),\n gas: Big(10).pow(12).mul(30),\n });\n }\n Near.call(txn);\n }\n};\n\nconst onIdeaClick = () => {\n State.update({ postType: \"Idea\", seekingFunding: false });\n};\n\nconst onSolutionClick = () => {\n State.update({ postType: \"Solution\" });\n};\n\nconst normalizeLabel = (label) =>\n label\n .replaceAll(/[- \\.]/g, \"_\")\n .replaceAll(/[^\\w]+/g, \"\")\n .replaceAll(/_+/g, \"-\")\n .replace(/^-+/, \"\")\n .replace(/-+$/, \"\")\n .toLowerCase()\n .trim(\"-\");\n\nconst checkLabel = (label) => {\n Near.asyncView(nearDevGovGigsContractAccountId, \"is_allowed_to_use_labels\", {\n editor: context.accountId,\n labels: [label],\n }).then((allowed) => {\n if (allowed) {\n State.update({ warning: \"\" });\n } else {\n State.update({\n warning:\n 'The label \"' +\n label +\n '\" is protected and can only be added by moderators',\n });\n return;\n }\n });\n};\n\nconst setLabels = (labels) => {\n labels = labels.map((o) => {\n o.name = normalizeLabel(o.name);\n return o;\n });\n if (labels.length < state.labels.length) {\n let oldLabels = new Set(state.labels.map((label) => label.name));\n for (let label of labels) {\n oldLabels.delete(label.name);\n }\n let removed = oldLabels.values().next().value;\n Near.asyncView(\n nearDevGovGigsContractAccountId,\n \"is_allowed_to_use_labels\",\n { editor: context.accountId, labels: [removed] }\n ).then((allowed) => {\n if (allowed) {\n let labelStrings = labels.map(({ name }) => name);\n State.update({ labels, labelStrings });\n } else {\n State.update({\n warning:\n 'The label \"' +\n removed +\n '\" is protected and can only be updated by moderators',\n });\n return;\n }\n });\n } else {\n let labelStrings = labels.map((o) => {\n return o.name;\n });\n State.update({ labels, labelStrings });\n }\n};\nconst existingLabelStrings =\n Near.view(nearDevGovGigsContractAccountId, \"get_all_allowed_labels\", {\n editor: context.accountId,\n }) ?? [];\nconst existingLabelSet = new Set(existingLabelStrings);\nconst existingLabels = existingLabelStrings.map((s) => {\n return { name: s };\n});\n\nconst labelEditor = (\n <div className=\"col-lg-12 mb-2\">\n <p className=\"fs-6 fw-bold mb-1\">Labels</p>\n <Typeahead\n multiple\n labelKey=\"name\"\n onInputChange={checkLabel}\n onChange={setLabels}\n options={existingLabels}\n placeholder=\"near.social, widget, NEP, standard, protocol, tool\"\n selected={state.labels}\n positionFixed\n allowNew={(results, props) => {\n return (\n !existingLabelSet.has(props.text) &&\n props.selected.filter((selected) => selected.name === props.text)\n .length == 0 &&\n Near.view(\n nearDevGovGigsContractAccountId,\n \"is_allowed_to_use_labels\",\n { editor: context.accountId, labels: [props.text] }\n )\n );\n }}\n />\n </div>\n);\n\nconst nameDiv = (\n <div className=\"col-lg-6 mb-2\">\n <p className=\"fs-6 fw-bold mb-1\">Title</p>\n <input\n type=\"text\"\n value={state.name}\n onChange={(event) => State.update({ name: event.target.value })}\n />\n </div>\n);\n\nconst descriptionDiv = (\n <div className=\"col-lg-12 mb-2\">\n <p className=\"fs-6 fw-bold mb-1\">Description</p>\n <textarea\n value={state.description}\n type=\"text\"\n rows={6}\n className=\"form-control\"\n onChange={(event) => State.update({ description: event.target.value })}\n />\n </div>\n);\n\nconst isFundraisingDiv = (\n // This is jank with just btns and not radios. But the radios were glitchy af\n <>\n <div class=\"mb-2\">\n <p class=\"fs-6 fw-bold mb-1\">\n Are you seeking funding for your solution?\n <span class=\"text-muted fw-normal\">(Optional)</span>\n </p>\n <div class=\"form-check form-check-inline\">\n <label class=\"form-check-label\">\n <button\n className=\"btn btn-light p-0\"\n style={{\n backgroundColor: state.seekingFunding ? \"#0C7283\" : \"inherit\",\n color: \"#f3f3f3\",\n border: \"solid #D9D9D9\",\n borderRadius: \"100%\",\n height: \"20px\",\n width: \"20px\",\n }}\n onClick={() => State.update({ seekingFunding: true })}\n />\n Yes\n </label>\n </div>\n <div class=\"form-check form-check-inline\">\n <label class=\"form-check-label\">\n <button\n className=\"btn btn-light p-0\"\n style={{\n backgroundColor: !state.seekingFunding ? \"#0C7283\" : \"inherit\",\n color: \"#f3f3f3\",\n border: \"solid #D9D9D9\",\n borderRadius: \"100%\",\n height: \"20px\",\n width: \"20px\",\n }}\n onClick={() => State.update({ seekingFunding: false })}\n />\n No\n </label>\n </div>\n </div>\n </>\n);\n\nconst fundraisingDiv = (\n <div class=\"d-flex flex-column mb-2\">\n <div className=\"col-lg-6 mb-2\">\n Currency\n <select\n onChange={(event) => State.update({ token: event.target.value })}\n class=\"form-select\"\n aria-label=\"Default select example\"\n >\n <option selected value=\"NEAR\">\n NEAR\n </option>\n <option value=\"USDC\">USDC</option>\n <option value=\"USD\">USD</option>\n </select>\n </div>\n <div className=\"col-lg-6 mb-2\">\n Requested amount <span class=\"text-muted fw-normal\">(Numbers Only)</span>\n <input\n type=\"number\"\n value={parseInt(state.amount) > 0 ? state.amount : \"\"}\n min={0}\n onChange={(event) =>\n State.update({\n amount: Number(\n event.target.value.toString().replace(/e/g, \"\")\n ).toString(),\n })\n }\n />\n </div>\n <div className=\"col-lg-6 mb-2\">\n <p class=\"mb-1\">\n Requested sponsor <span class=\"text-muted fw-normal\">(Optional)</span>\n </p>\n <p style={{ fontSize: \"13px\" }} class=\"m-0 text-muted fw-light\">\n If you are requesting funding from a specific sponsor, please enter\n their username.\n </p>\n <div class=\"input-group flex-nowrap\">\n <span class=\"input-group-text\" id=\"addon-wrapping\">\n @\n </span>\n <input\n type=\"text\"\n class=\"form-control\"\n placeholder=\"Enter username\"\n value={state.supervisor}\n onChange={(event) => State.update({ supervisor: event.target.value })}\n />\n </div>\n </div>\n </div>\n);\n\nfunction generateDescription(text, amount, token, supervisor) {\n const funding = `###### Requested amount: ${amount} ${token}\\n###### Requested sponsor: @${supervisor}\\n`;\n if (amount > 0 && token && supervisor) return funding + text;\n return text;\n}\n\nreturn (\n <div class=\"bg-light d-flex flex-column flex-grow-1\">\n {widget(\"components.layout.Banner\")}\n <div class=\"mx-5 mb-5\">\n <div aria-label=\"breadcrumb\">\n <ol class=\"breadcrumb\">\n <li class=\"breadcrumb-item\">\n <a\n style={{\n color: \"#3252A6\",\n }}\n className=\"fw-bold\"\n href={href(\"Feed\")}\n >\n DevHub\n </a>\n </li>\n <li class=\"breadcrumb-item active\" aria-current=\"page\">\n Create new\n </li>\n </ol>\n </div>\n <h4>Create a new post</h4>\n <p>{state.seekingFunding}</p>\n <div class=\"card border-light\">\n <div class=\"card-body\">\n <p class=\"card-title fw-bold fs-6\">What do you want to create?</p>\n <div class=\"d-flex flex-row gap-2\">\n <button\n onClick={onIdeaClick}\n type=\"button\"\n class={`btn btn-outline-secondary`}\n style={\n state.postType === \"Idea\"\n ? {\n backgroundColor: \"#0C7283\",\n color: \"#f3f3f3\",\n }\n : {}\n }\n >\n <i class=\"bi bi-lightbulb\"></i>\n Idea\n </button>\n <button\n onClick={onSolutionClick}\n type=\"button\"\n class={`btn btn-outline-secondary`}\n style={\n state.postType !== \"Idea\"\n ? {\n backgroundColor: \"#0C7283\",\n color: \"#f3f3f3\",\n }\n : {}\n }\n >\n <i class=\"bi bi-rocket\"></i>\n Solution\n </button>\n </div>\n <p class=\"text-muted w-75 my-1\">\n {state.postType === \"Idea\"\n ? \"Get feedback from the community about a problem, opportunity, or need.\"\n : \"Provide a specific proposal or implementation to an idea, optionally requesting funding. If your solution relates to an existing idea, please reply to the original post with a solution.\"}\n </p>\n {state.warning && (\n <div\n class=\"alert alert-warning alert-dismissible fade show\"\n role=\"alert\"\n >\n {state.warning}\n <button\n type=\"button\"\n class=\"btn-close\"\n data-bs-dismiss=\"alert\"\n aria-label=\"Close\"\n onClick={() => State.update({ warning: \"\" })}\n ></button>\n </div>\n )}\n <div className=\"row\">\n {nameDiv}\n {descriptionDiv}\n {labelEditor}\n {state.postType === \"Solution\" && isFundraisingDiv}\n {state.seekingFunding && fundraisingDiv}\n </div>\n <button\n style={{\n width: \"7rem\",\n backgroundColor: \"#0C7283\",\n color: \"#f3f3f3\",\n }}\n className=\"btn btn-light mb-2 p-3\"\n onClick={onSubmit}\n >\n Submit\n </button>\n </div>\n <div class=\"bg-light d-flex flex-row p-1 border-bottom\"></div>\n <div class=\"card-body\">\n <p class=\"text-muted m-0\">Preview</p>\n <div>\n {widget(\"components.posts.Post\", {\n isPreview: true,\n id: 0, // irrelevant\n post: {\n author_id: state.author_id,\n likes: [],\n snapshot: {\n editor_id: state.editor_id,\n labels: state.labelStrings,\n post_type: state.postType,\n name: state.name,\n description: generateDescription(\n state.description,\n state.amount,\n state.token,\n state.supervisor\n ),\n github_link: state.githubLink,\n },\n },\n })}\n </div>\n </div>\n </div>\n </div>\n </div>\n);\n" }, "gigs-board.components.teams.TeamInfo": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n/* INCLUDE: \"shared/lib/gui\" */\nconst Card = styled.div`\n &:hover {\n box-shadow: rgba(3, 102, 214, 0.3) 0px 0px 0px 3px;\n }\n`;\n\nconst CompactContainer = styled.div`\n width: fit-content !important;\n max-width: 100%;\n`;\n/* END_INCLUDE: \"shared/lib/gui\" */\n\nconst metadata = props.members_list[props.member];\nconst isTeam = props.member.startsWith(\"team:\");\nconst memberBadge = isTeam ? \"bi-people-fill\" : \"person-fill\";\nconst header = isTeam ? (\n <div class=\"d-flex\">\n <i class=\"bi bi-people-fill me-1\"></i>\n {props.member}\n </div>\n) : (\n <Widget\n src={`neardevgov.near/widget/ProfileLine`}\n props={{ accountId: props.member }}\n />\n);\n\nconst permissionDesc = {\n \"edit-post\": \"Can edit posts with these labels\",\n \"use-labels\": \"Can assign and unassign these labels\",\n};\n\nconst permissionExplainer = (permission) => {\n if (permission.startsWith(\"starts-with:\")) {\n let s = permission.substring(\"starts-with:\".length);\n if (s == \"\") {\n return \"Any label\";\n } else {\n return `Labels that start with \"${s}\"`;\n }\n } else {\n return permission;\n }\n};\n\nconst permissionsFilter = (permissionType) => {\n let res = [];\n for (const [pattern, permissions] of Object.entries(metadata.permissions)) {\n if (permissions.includes(permissionType)) {\n res.push(pattern);\n }\n }\n return res;\n};\n\nconst permissionsRenderer = (permissionType) => {\n let permissions = permissionsFilter(permissionType);\n if (permissions.length > 0) {\n return (\n <p class=\"card-text\" key={`${permissionType}-permissions`}>\n {permissionDesc[permissionType]}:\n {permissions.map((permission) => (\n <span class=\"badge text-bg-primary\" key={permission}>\n {permissionExplainer(permission)}\n </span>\n ))}\n </p>\n );\n } else {\n return <div></div>;\n }\n};\n\nreturn (\n <Card className=\"card my-2 border-secondary\">\n <div className=\"card-header\">\n <small class=\"text-muted\">{header}</small>\n </div>\n <div className=\"card-body\">\n <p class=\"card-text\" key=\"description\">\n <Markdown class=\"card-text\" text={metadata.description}></Markdown>\n </p>\n {permissionsRenderer(\"edit-post\")}\n {permissionsRenderer(\"use-labels\")}\n {metadata.children ? (\n <div class=\"vstack\">\n {metadata.children.map((child) =>\n widget(\n \"components.teams.TeamInfo\",\n { member: child, members_list: props.members_list },\n child\n )\n )}\n </div>\n ) : null}\n </div>\n </Card>\n);\n" }, "gigs-board.components.layout.SearchByLabel": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\nconst onSearchLabel = props.onSearchLabel;\nconst selectedLabels = props.labelQuery?.label\n ? [{ name: props.labelQuery.label }]\n : [];\n\nconst labels = Near.view(nearDevGovGigsContractAccountId, \"get_all_labels\");\nif (!labels) {\n return <div>Loading ...</div>;\n}\nconst wrappedLabels = labels.map((label) => ({ name: label }));\n\nconst onChange = (selectedLabels) => {\n onSearchLabel(selectedLabels[0]?.name);\n};\n\nreturn (\n <Typeahead\n clearButton\n id=\"basic-typeahead-single\"\n labelKey=\"name\"\n onChange={onChange}\n options={wrappedLabels}\n placeholder=\"Search by tag\"\n selected={selectedLabels}\n />\n);\n" }, "gigs-board.feature.integration.github.board-config-editor": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n/* INCLUDE: \"shared/lib/form\" */\n/**\n *! TODO: Extract into separate library module\n *! once `useForm` is converted into a form factory widget\n */\nconst traversalUpdate = ({\n input,\n target: treeOrBranch,\n path: [currentBranchKey, ...remainingBranch],\n params,\n via: nodeUpdate,\n}) => ({\n ...treeOrBranch,\n\n [currentBranchKey]:\n remainingBranch.length > 0\n ? traversalUpdate({\n input,\n\n target:\n typeof treeOrBranch[currentBranchKey] === \"object\"\n ? treeOrBranch[currentBranchKey]\n : {\n ...((treeOrBranch[currentBranchKey] ?? null) !== null\n ? { __archivedLeaf__: treeOrBranch[currentBranchKey] }\n : {}),\n },\n\n path: remainingBranch,\n via: nodeUpdate,\n })\n : nodeUpdate({\n input,\n lastKnownState: treeOrBranch[currentBranchKey],\n params,\n }),\n});\n\nconst fieldDefaultUpdate = ({\n input,\n lastKnownState,\n params: { arrayDelimiter },\n}) => {\n switch (typeof input) {\n case \"boolean\":\n return input;\n\n case \"object\":\n return Array.isArray(input) && typeof lastKnownState === \"string\"\n ? input.join(arrayDelimiter ?? \",\")\n : input;\n\n case \"string\":\n return Array.isArray(lastKnownState)\n ? input.split(arrayDelimiter ?? \",\").map((string) => string.trim())\n : input;\n\n default: {\n if ((input ?? null) === null) {\n switch (typeof lastKnownState) {\n case \"boolean\":\n return !lastKnownState;\n\n default:\n return lastKnownState;\n }\n } else return input;\n }\n }\n};\n\nconst useForm = ({ stateKey: formStateKey }) => ({\n formState: state[formStateKey],\n\n formUpdate:\n ({ path: fieldPath, via: fieldCustomUpdate, ...params }) =>\n (fieldInput) =>\n State.update((lastKnownState) =>\n traversalUpdate({\n input: fieldInput?.target?.value ?? fieldInput,\n target: lastKnownState,\n path: [formStateKey, ...fieldPath],\n params,\n\n via:\n typeof fieldCustomUpdate === \"function\"\n ? fieldCustomUpdate\n : fieldDefaultUpdate,\n })\n ),\n});\n/* END_INCLUDE: \"shared/lib/form\" */\n/* INCLUDE: \"shared/lib/gui\" */\nconst Card = styled.div`\n &:hover {\n box-shadow: rgba(3, 102, 214, 0.3) 0px 0px 0px 3px;\n }\n`;\n\nconst CompactContainer = styled.div`\n width: fit-content !important;\n max-width: 100%;\n`;\n/* END_INCLUDE: \"shared/lib/gui\" */\n/* INCLUDE: \"shared/lib/uuid\" */\nconst uuid = () =>\n [Date.now().toString(16)]\n .concat(\n Array.from(\n { length: 4 },\n () => Math.floor(Math.random() * 0xffffffff) & 0xffffffff\n ).map((value) => value.toString(16))\n )\n .join(\"-\");\n\nconst uuidIndexed = (data) => {\n const id = uuid();\n\n return Object.fromEntries([[id, { ...data, id }]]);\n};\n/* END_INCLUDE: \"shared/lib/uuid\" */\n/* INCLUDE: \"shared/mocks\" */\nconst communities = {\n \"zero-knowledge\": {\n overviewId: 397,\n eventsId: 401,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreiajwq6ep3n7veddozji2djv5vviyisabhycbweslvpwhsoyuzcwi4\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreihgxg5kwts2juldaeasveyuddkm6tcabmrat2aaq5u6uyljtyt7lu\",\n\n title: \"Zero Knowledge\",\n desc: \"Building a zero knowledge ecosystem on NEAR.\",\n telegram: \"NearZeroKnowledge\",\n },\n\n protocol: {\n overviewId: 412,\n eventsId: 413,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreidpitdafcnhkp4uyomacypdgqvxr35jtfnbxa5s6crby7qjk2nv5a\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreicg4svzfz5nvllomsahndgm7u62za4sib4mmbygxzhpcl4htqwr4a\",\n\n title: \"Protocol\",\n desc: \"Supporting the ongoing innovation of the NEAR Protocol.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-protocol\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Protocol NEPs\",\n },\n },\n },\n },\n\n telegram: \"NEAR_Protocol_Community_Group\",\n },\n\n tooling: {\n overviewId: 416,\n eventsId: 417,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreie2eaj5czmpfe6pe53kojzcspgozebdsonffwvbxtpuipnwahybvi\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreiehzr7z2fhoqqmkt3z667wubccbch6sqtsnvd6msodyzpnf72cszy\",\n\n title: \"Tooling\",\n desc: \"Supporting the ongoing innovation of tooling.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-tools\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Tooling NEPs\",\n },\n },\n },\n },\n\n telegram: \"NEAR_Tools_Community_Group\",\n },\n\n \"contract-standards\": {\n overviewId: 414,\n eventsId: 415,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreiepgdnu7soc6xgbyd4adicbf3eyxiiwqawn6tguaix6aklfpir634\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreiaowjqxds24fwcliyriintjd4ucciprii2rdxjmxgi7f5dmzuscey\",\n\n title: \"Contract Standards\",\n desc: \"Coordinating the contribution to the NEAR dapp standards.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Contract Standards NEPs\",\n },\n },\n },\n },\n\n telegram: \"nearnft\",\n },\n};\n/* END_INCLUDE: \"shared/mocks\" */\n\nconst dataTypesLocked = {\n Issue: true,\n PullRequest: true,\n};\n\nconst boardConfigDefaults = {\n id: uuid(),\n columns: {},\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"\",\n repoURL: \"\",\n ticketState: \"all\",\n title: \"\",\n};\n\nconst GithubBoardConfigEditor = ({ label, pageURL }) => {\n const communityGitHubKanbanBoards =\n communities[label].integrations?.github?.boards ?? {};\n\n State.init({\n boardConfig: null,\n\n editingMode: \"form\",\n isEditingAllowed: false, // According to user permission level\n isEditorEnabled: false,\n\n ...Storage.get(\n \"state\",\n `${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.components.community.CommunityHeader`\n ),\n });\n\n const onEditorToggle = (forcedState) =>\n State.update((lastKnownState) => ({\n ...lastKnownState,\n isEditorEnabled: forcedState ?? !lastKnownState.isEditorEnabled,\n }));\n\n const onEditingModeChange = ({ target: { value } }) =>\n State.update((lastKnownState) => ({\n ...lastKnownState,\n editingMode: value,\n }));\n\n if (\n state.boardConfig === null &&\n Object.keys(communityGitHubKanbanBoards).length > 0\n ) {\n State.update((lastKnownState) => ({\n ...lastKnownState,\n boardConfig: Object.values(communityGitHubKanbanBoards)[0],\n }));\n }\n\n const boardsCreateNew = () =>\n State.update((lastKnownState) => ({\n ...lastKnownState,\n boardConfig: boardConfigDefaults,\n isEditorEnabled: true,\n }));\n\n const { formState, formUpdate } = useForm({ stateKey: \"boardConfig\" });\n\n const columnsCreateNew = ({ lastKnownState }) =>\n Object.keys(lastKnownState).length < 6\n ? {\n ...lastKnownState,\n\n ...uuidIndexed({\n description: \"\",\n labelSearchTerms: [],\n title: \"New column\",\n }),\n }\n : lastKnownState;\n\n const columnsDeleteById =\n (id) =>\n ({ lastKnownState }) =>\n Object.fromEntries(\n Object.entries(lastKnownState).filter(([columnId]) => columnId !== id)\n );\n\n const form =\n formState !== null ? (\n <>\n <div className=\"d-flex gap-3 flex-column flex-lg-row\">\n <div className=\"input-group-text border-0 d-flex flex-column flex-1 flex-shrink-0\">\n <span id={`${formState.id}-title`}>Title</span>\n\n <input\n aria-describedby={`${formState.id}-title`}\n className=\"form-control\"\n onChange={formUpdate({ path: [\"title\"] })}\n placeholder=\"NEAR Protocol NEPs\"\n type=\"text\"\n value={formState.title}\n />\n </div>\n\n <div\n className={[\n \"input-group-text border-0\",\n \"d-flex flex-column justify-content-evenly flex-4 w-100\",\n ].join(\" \")}\n >\n <span id={`${formState.id}-repoURL`}>GitHub repository URL</span>\n\n <input\n aria-describedby={`${formState.id}-repoURL`}\n className=\"form-control\"\n onChange={formUpdate({ path: [\"repoURL\"] })}\n placeholder=\"https://github.com/example-org/example-repo\"\n type=\"text\"\n value={formState.repoURL}\n />\n </div>\n </div>\n\n <div className=\"d-flex gap-3 flex-column flex-lg-row\">\n <CompactContainer className=\"d-flex gap-3 flex-column justify-content-start p-3 ps-0\">\n <span\n className=\"d-inline-flex gap-2\"\n id={`${formState.id}-dataTypesIncluded`}\n >\n <i class=\"bi bi-database-fill\" />\n <span>Tracked data</span>\n </span>\n\n {Object.entries(formState.dataTypesIncluded).map(\n ([typeName, enabled]) =>\n widget(\n \"components.atom.toggle\",\n {\n active: enabled,\n className: \"w-100\",\n disabled: dataTypesLocked[typeName],\n key: typeName,\n label: typeName,\n\n onSwitch: formUpdate({\n path: [\"dataTypesIncluded\", typeName],\n }),\n },\n\n typeName\n )\n )}\n </CompactContainer>\n\n <CompactContainer className=\"d-flex gap-3 flex-column justify-content-start p-3 ps-0\">\n <span\n className=\"d-inline-flex gap-2\"\n id={`${formState.id}-dataTypesIncluded`}\n >\n <i class=\"bi bi-database-fill\" />\n <span>Ticket state</span>\n </span>\n\n {widget(\"components.atom.button-switch\", {\n currentValue: formState.ticketState,\n key: \"ticketState\",\n onChange: formUpdate({ path: [\"ticketState\"] }),\n\n options: [\n { label: \"All\", value: \"all\" },\n { label: \"Open\", value: \"open\" },\n { label: \"Closed\", value: \"closed\" },\n ],\n\n title: \"Editing mode selection\",\n })}\n </CompactContainer>\n\n <div className=\"input-group-text border-0 d-flex flex-column w-100\">\n <span id={`${formState.id}-description`}>Description</span>\n\n <textarea\n aria-describedby={`${formState.id}-description`}\n className=\"form-control h-75\"\n onChange={formUpdate({ path: [\"description\"] })}\n placeholder=\"Latest NEAR Enhancement Proposals by status.\"\n type=\"text\"\n value={formState.description}\n />\n </div>\n </div>\n\n <div className=\"d-flex align-items-center justify-content-between\">\n <span className=\"d-inline-flex gap-2 m-0\">\n <i className=\"bi bi-list-task\" />\n <span>Columns ( max. 6 )</span>\n </span>\n </div>\n\n <div className=\"d-flex flex-column align-items-center gap-3\">\n {Object.values(formState.columns).map(\n ({ id, description, labelSearchTerms, title }) => (\n <div\n class=\"d-flex flex-column gap-3 rounded-2 p-3 w-100 bg-secondary bg-opacity-25\"\n key={id}\n >\n <div class=\"d-flex gap-3\">\n <div\n className=\"d-flex flex-column flex-grow-1\"\n style={{ width: \"inherit\" }}\n >\n <span id={`${formState.id}-column-${id}-title`}>Title</span>\n\n <input\n aria-describedby={`${formState.id}-column-${id}-title`}\n className=\"form-control\"\n onChange={formUpdate({\n path: [\"columns\", id, \"title\"],\n })}\n placeholder=\"👀 Review\"\n type=\"text\"\n value={title}\n />\n </div>\n\n <button\n class=\"btn btn-outline-danger\"\n onClick={formUpdate({\n path: [\"columns\"],\n via: columnsDeleteById(id),\n })}\n title=\"Delete column\"\n >\n <i class=\"bi bi-file-earmark-minus-fill\" />\n </button>\n </div>\n\n <div\n className=\"d-flex flex-column\"\n style={{ width: \"inherit\" }}\n >\n <span id={`${formState.id}-column-${id}-description`}>\n Description\n </span>\n\n <input\n aria-describedby={`${formState.id}-column-${id}-description`}\n className=\"form-control\"\n onChange={formUpdate({\n path: [\"columns\", id, \"description\"],\n })}\n placeholder=\"NEPs that need a review by Subject Matter Experts.\"\n type=\"text\"\n value={description}\n />\n </div>\n\n <div\n className=\"d-flex flex-column\"\n style={{ width: \"inherit\" }}\n >\n <span\n className=\"text-wrap\"\n id={`${formState.id}-column-${title}-searchTerms`}\n >\n Search terms for all the labels MUST be presented in\n included tickets, comma-separated\n </span>\n\n <input\n aria-describedby={`${formState.id}-column-${title}-searchTerms`}\n aria-label=\"Search terms for included labels\"\n className=\"form-control\"\n onChange={formUpdate({\n path: [\"columns\", id, \"labelSearchTerms\"],\n })}\n placeholder=\"WG-, draft, review, proposal, ...\"\n type=\"text\"\n value={labelSearchTerms.join(\", \")}\n />\n </div>\n </div>\n )\n )}\n </div>\n </>\n ) : null;\n\n return (\n <div className=\"d-flex flex-column gap-4\">\n {state.isEditorEnabled && formState !== null ? (\n <div\n className={[\n \"d-flex flex-column gap-3\",\n \"border border-2 border-primary rounded-2 p-3 w-100\",\n ].join(\" \")}\n >\n <div className=\"d-flex align-items-center justify-content-between gap-3\">\n <h5 className=\"h5 d-inline-flex gap-2 m-0\">\n <i className=\"bi bi-wrench-adjustable-circle-fill\" />\n <span>Board configuration</span>\n </h5>\n\n {widget(\"components.atom.button-switch\", {\n currentValue: state.editingMode,\n key: \"editingMode\",\n onChange: onEditingModeChange,\n\n options: [\n { label: \"Form\", value: \"form\" },\n { label: \"JSON\", value: \"JSON\" },\n ],\n\n title: \"Editing mode selection\",\n })}\n </div>\n\n {state.editingMode === \"form\" ? (\n form\n ) : (\n <div className=\"d-flex flex-column flex-grow-1 border-0 bg-transparent w-100\">\n <textarea\n className=\"form-control\"\n disabled\n rows=\"12\"\n type=\"text\"\n value={JSON.stringify(formState, null, \"\\t\")}\n />\n </div>\n )}\n\n <div className=\"d-flex align-items-center justify-content-end gap-3\">\n <button\n className=\"btn btn-outline-secondary d-inline-flex gap-2 me-auto\"\n disabled={Object.keys(formState.columns).length >= 6}\n onClick={formUpdate({\n path: [\"columns\"],\n via: columnsCreateNew,\n })}\n >\n <i class=\"bi bi-plus-lg\" />\n <span>New column</span>\n </button>\n\n <button\n className=\"btn btn-outline-danger d-inline-flex gap-2 align-items-center\"\n onClick={() => onEditorToggle(false)}\n style={{ width: \"fit-content\" }}\n >\n <span>Cancel</span>\n </button>\n\n <button\n disabled={!formState.hasChanges}\n className=\"btn btn-primary d-inline-flex gap-2 align-items-center\"\n style={{ width: \"fit-content\" }}\n >\n <i className=\"bi bi-file-arrow-up-fill\" />\n <span>Save</span>\n </button>\n </div>\n </div>\n ) : null}\n\n {state.boardConfig !== null ? (\n widget(\"entity.github-repo.board\", {\n ...state.boardConfig,\n editorTrigger: () => onEditorToggle(true),\n isEditable: state.isEditingAllowed,\n pageURL,\n })\n ) : (\n <div\n className=\"d-flex flex-column align-items-center justify-content-center gap-4\"\n style={{ height: 384 }}\n >\n <h5 className=\"h5 d-inline-flex gap-2 m-0\">\n This community doesn't have GitHub boards.\n </h5>\n\n <button\n className=\"btn btn-primary d-inline-flex gap-2\"\n onClick={boardsCreateNew}\n >\n <i class=\"bi bi-kanban-fill\" />\n <span>Create one</span>\n </button>\n </div>\n )}\n </div>\n );\n};\n\nreturn GithubBoardConfigEditor(props);\n" }, "gigs-board.components.layout.Page": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\nreturn (\n <>\n {widget(\"components.layout.Banner\")}\n {props.header}\n {props.children}\n </>\n);\n" }, "gigs-board.pages.community.Sidebar": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\n/* INCLUDE: \"communities.jsx\" */\nconst communities = {\n \"zero-knowledge\": {\n overviewId: 397,\n eventsId: 401,\n icon: \"https://ipfs.near.social/ipfs/bafkreiajwq6ep3n7veddozji2djv5vviyisabhycbweslvpwhsoyuzcwi4\",\n cover:\n \"https://ipfs.near.social/ipfs/bafkreihgxg5kwts2juldaeasveyuddkm6tcabmrat2aaq5u6uyljtyt7lu\",\n title: \"Zero Knowledge\",\n desc: \"Building a zero knowledge ecosystem on NEAR.\",\n },\n protocol: {\n overviewId: 412,\n eventsId: 413,\n icon: \"https://ipfs.near.social/ipfs/bafkreidpitdafcnhkp4uyomacypdgqvxr35jtfnbxa5s6crby7qjk2nv5a\",\n cover:\n \"https://ipfs.near.social/ipfs/bafkreicg4svzfz5nvllomsahndgm7u62za4sib4mmbygxzhpcl4htqwr4a\",\n title: \"Protocol\",\n desc: \"Supporting the ongoing innovation of the NEAR Protocol.\",\n },\n tooling: {\n overviewId: 416,\n eventsId: 417,\n icon: \"https://ipfs.near.social/ipfs/bafkreie2eaj5czmpfe6pe53kojzcspgozebdsonffwvbxtpuipnwahybvi\",\n cover:\n \"https://ipfs.near.social/ipfs/bafkreiehzr7z2fhoqqmkt3z667wubccbch6sqtsnvd6msodyzpnf72cszy\",\n title: \"Tooling\",\n desc: \"Supporting the ongoing innovation of tooling.\",\n },\n \"contract-standards\": {\n overviewId: 414,\n eventsId: 415,\n icon: \"https://ipfs.near.social/ipfs/bafkreiepgdnu7soc6xgbyd4adicbf3eyxiiwqawn6tguaix6aklfpir634\",\n cover:\n \"https://ipfs.near.social/ipfs/bafkreiaowjqxds24fwcliyriintjd4ucciprii2rdxjmxgi7f5dmzuscey\",\n title: \"Contract Standards\",\n desc: \"Coordinating the contribution to the NEAR dapp standards.\",\n },\n};\n/* END_INCLUDE: \"communities.jsx\" */\n\n/* INCLUDE: \"mockcommunity.jsx\" */\nconst socialLinks = [\n {\n href: \"#/mob.near/widget/ProfilePage?accountId=self.social.near\",\n iconClass: \"bi bi-globe\",\n label: community.title,\n },\n\n {\n href: \"https://github.com/NearSocial\",\n iconClass: \"bi bi-github\",\n label: community.title,\n },\n {\n href: \"https://twitter.com/NearSocial_\",\n iconClass: \"bi bi-twitter\",\n label: community.title,\n },\n {\n href: \"https://t.me/NearSocial\",\n iconClass: \"bi bi-telegram\",\n label: community.title,\n },\n];\n\n// TODO ADD AMIN MEMBERS HERE\n\nconst TeamMembers = [\n {\n id: \"\",\n role: \"\",\n avatar: \"\",\n wallet: \"\",\n },\n\n {\n id: \"js_joker\",\n role: \"Admin\",\n avatar:\n \"https://paras.id/_next/image?url=https%3A%2F%2Fparas-cdn.imgix.net%2F6196b861da8a91415f23e551a5e88c0ac0671c0d%3Fw%3D400&w=1080&q=75\",\n wallet: \"@js_joker.near\",\n },\n];\n/* END_INCLUDE: \"mockcommunity.jsx\" */\n\nif (!props.label) {\n return (\n <div class=\"alert alert-danger\" role=\"alert\">\n Error: label is required\n </div>\n );\n}\n\nconst label = props.label;\n\nconst discussionRequiredPosts =\n Near.view(nearDevGovGigsContractAccountId, \"get_posts_by_label\", {\n label,\n }) ?? [];\n\nconst community = communities[props.label];\n\nconst onMention = (accountId) => (\n <span key={accountId} className=\"d-inline-flex\" style={{ fontWeight: 500 }}>\n <Widget\n src=\"neardevgov.near/widget/ProfileLine\"\n props={{\n accountId: accountId.toLowerCase(),\n hideAccountId: true,\n tooltip: true,\n }}\n />\n </span>\n);\n\n// START OF SIDEBAR\n// Social Links Master Styling\nconst SocialLink = ({ link, index }) => (\n <a\n className={`btn btn-outline-secondary border-0 d-flex align-items-center`}\n href={link.href}\n style={{ marginLeft: \"0px\" }}\n >\n <i className={link.iconClass}></i>\n <span className=\"ms-1\">{link.label || community.title}</span>\n </a>\n);\n\n// Social Media Icons\nconst SocialMediaIcons = (\n <div\n className=\"mb-1 d-flex gap-2 flex-wrap flex-column\"\n style={{ padding: \"0px\" }}\n >\n {socialLinks.map((link, index) => (\n <SocialLink key={index} link={link} index={index} />\n ))}\n </div>\n);\n\nconst CommunitySummary = (\n <div style={{ top: \"0\", left: \"0\" }}>\n <Markdown text={community.desc} onMention={onMention} />\n <h3 className=\"mt-2 mb-2\">{community.label}</h3>\n <div className=\"row mb-2 align-items-center d-flex justify-content-between\">\n <div className=\"col-auto\">\n <div className=\"d-flex align-items-center\">\n <a href={href(\"Feed\", { label })} key={label}>\n <span\n className=\"badge text-bg-grey ms-1\"\n style={{\n color: \"rgba(0, 0, 0, 0.7)\",\n fontSize: \"1em\",\n fontWeight: \"normal\",\n boxShadow: \"0px 1px 3px rgba(0, 0, 0, 0.2)\",\n padding: \"0.2em 0.5em\",\n }}\n >\n <div>{label}</div>\n </span>\n </a>\n </div>\n </div>\n </div>\n <br></br>\n <br></br>\n {socialLinks.map((link, index) => (\n <SocialLink key={index} link={link} index={index} />\n ))}\n </div>\n);\n\nconst Card = ({ content }) => (\n <div\n className=\"card\"\n style={{\n border: \"none\",\n }}\n >\n <div className=\"card-body\">\n <p className=\"card-text\">{content}</p>\n </div>\n </div>\n);\n\nconst CommunityOverview = (\n <Card title={`${community.title} Overview`} content={CommunitySummary}></Card>\n);\n\nconst TeamMember = ({ member }) => (\n <div className=\"d-flex align-items-start mb-1 justify-content-start\">\n <img\n src={member.avatar}\n alt={member.id}\n style={{\n width: \"50px\",\n height: \"50px\",\n borderRadius: \"50%\",\n marginRight: \"10px\",\n }}\n />\n <div style={{ paddingTop: \"7px\" }}>\n <h6 style={{ fontSize: \"110%\", fontWeight: \"bold\", marginBottom: \"0\" }}>\n {member.id}\n </h6>\n <p style={{ fontSize: \"100%\" }}>{member.wallet}</p>\n </div>\n </div>\n);\n\n// Team Members List\nconst TeamMembersList = TeamMembers.map((member) => (\n <TeamMember key={member.id} member={member} />\n));\n\n// More Info Button\nconst MoreInfoButton = (\n <div className=\"d-flex justify-content-start\">\n <button\n type=\"button\"\n class=\"btn\"\n style={{\n color: \"black\",\n fontSize: \"0.8rem\",\n fontWeight: \"bold\",\n }}\n href=\"#\"\n >\n See More\n </button>\n </div>\n);\n\n// Team Card\nconst TeamsCard = (\n <div style={{ width: \"100%\" }}>\n <Card\n title={\"Team Members\"}\n content={\n <div>\n <h5\n style={{\n fontSize: \"1.3rem\",\n fontWeight: \"800\",\n marginBottom: \"20px\",\n }}\n >\n Group Moderators\n </h5>\n {TeamMembersList}\n {MoreInfoButton}\n </div>\n }\n ></Card>\n </div>\n);\n\n// Define the Sidebar component\nconst Sidebar = () => (\n <div class=\"col-md-12 d-flex flex-column align-items-end\">\n {CommunityOverview}\n <hr style={{ width: \"100%\", borderTop: \"4px solid #00000033\" }} />\n {TeamsCard}\n </div>\n);\n\n// Define the layout for the page\nconst PageLayout = () => (\n <div class=\"container\">\n <div class=\"row\">\n <Sidebar />\n </div>\n </div>\n);\n\nreturn <PageLayout />;\n// END OF SIDEBAR\n\n// USAGE\n// copy and paste this into the return function of a page you want the sidebar on\n// make sure to add `col-mb-9` to the class of the div you want to\n// take up 2/3 of the screen to the left\n\n// then make sure to add `col-mb-3` to the class of the div you want to\n// take up 1/3 of the screen to the\n\n{\n /* <div class=\"col-4 container-fluid\">\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.community.Sidebar`}\n props={{\n metadata: metadata,\n accountId: accountId,\n widgetName: widgetName,\n label: props.label,\n }}\n />\n</div> */\n}\n" }, "gigs-board.components.layout.Controls": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\nreturn (\n <div class=\"d-flex flex-row-reverse\">\n <a\n class=\"btn btn-light\"\n style={{\n backgroundColor: \"#0C7283\",\n color: \"#f3f3f3\",\n }}\n href={href(\"Create\", { labels: props.labels })}\n >\n <i class=\"bi bi-plus-circle-fill\"></i>\n Submit Idea / Solution\n </a>\n </div>\n);\n" }, "gigs-board.components.layout.SearchByAuthor": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\nconst onSearchAuthor = props.onSearchAuthor;\nconst selectedAuthors = props.authorQuery?.author\n ? [{ name: props.authorQuery.author }]\n : [];\n\nconst authors = Near.view(nearDevGovGigsContractAccountId, \"get_all_authors\");\nif (!authors) {\n return <div>Loading ...</div>;\n}\nconst wrappedAuthors = authors.map((author) => ({ name: author }));\n\nconst onChangeAuthor = (selectedAuthors) => {\n onSearchAuthor(selectedAuthors[0]?.name);\n};\n\nreturn (\n <>\n <Typeahead\n clearButton\n id=\"basic-typeahead-single\"\n labelKey=\"name\"\n onChange={onChangeAuthor}\n options={wrappedAuthors}\n placeholder=\"Search by author\"\n selected={selectedAuthors}\n />\n </>\n);\n" }, "gigs-board.components.teams.LabelsPermissions": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\nconst access_info =\n Near.view(nearDevGovGigsContractAccountId, \"get_access_control_info\") ?? null;\n\nif (!access_info) {\n return <div>Loading...</div>;\n}\n\nconst rules_list = props.rules_list ?? access_info.rules_list;\n\nconst permissionExplainer = (permission) => {\n if (permission.startsWith(\"starts-with:\")) {\n let s = permission.substring(\"starts-with:\".length);\n if (s == \"\") {\n return \"Any label\";\n } else {\n return `Labels that start with \"${s}\"`;\n }\n } else {\n return permission;\n }\n};\n\nreturn (\n <div className=\"card border-secondary\" key=\"labelpermissions\">\n <div className=\"card-header\">\n <i class=\"bi-lock-fill\"> </i>\n <small class=\"text-muted\">Restricted Labels</small>\n </div>\n <ul class=\"list-group list-group-flush\">\n {Object.entries(rules_list).map(([pattern, metadata]) => (\n <li class=\"list-group-item\" key={pattern}>\n <span class=\"badge text-bg-primary\" key={`${pattern}-permission`}>\n {permissionExplainer(pattern)}\n </span>{\" \"}\n {metadata.description}\n </li>\n ))}\n </ul>\n </div>\n);\n" }, "gigs-board.components.community.CommunityHeader": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\nconst Header = styled.div`\n overflow: hidden;\n background: #f3f3f3;\n margin-top: -25px;\n margin-bottom: 25px;\n`;\n\nconst NavUnderline = styled.ul`\n a {\n color: #3252a6;\n text-decoration: none;\n }\n\n a.active {\n font-weight: bold;\n border-bottom: 2px solid #0c7283;\n }\n`;\n\nconst BreadcrumbLink = styled.a`\n {\n color: #3252a6;\n text-decoration: none;\n }\n`;\n\nconst BreadcrumbBold = styled.b`\n {\n color: #3252a6;\n }\n`;\n\nconst topicTabs = [\n {\n defaultActive: true,\n iconClass: \"bi bi-house-door\",\n path: \"community.Overview\",\n title: \"Overview\",\n },\n {\n iconClass: \"bi bi-chat-square-text\",\n path: \"community.Discussions\",\n title: \"Discussions\",\n },\n {\n iconClass: \"bi bi-coin\",\n path: \"community.Sponsorship\",\n title: \"Sponsorship\",\n },\n {\n iconClass: \"bi bi-calendar\",\n path: \"community.Events\",\n title: \"Events\",\n },\n {\n iconClass: \"bi bi-github\",\n path: \"community.github\",\n title: \"GitHub\",\n },\n {\n iconClass: \"bi bi-telegram\",\n path: \"community.Telegram\",\n title: \"Telegram\",\n },\n];\n\nconst CommunityHeader = ({ label, tab }) => {\n State.init({ shared: { isEditorEnabled: false } });\n Storage.set(\"state\", state.shared);\n\n const onEditorToggle = () =>\n State.update((lastState) => ({\n ...lastState,\n\n shared: {\n ...lastState.shared,\n isEditorEnabled: !lastState.shared.isEditorEnabled,\n },\n }));\n\n return (\n <Header className=\"d-flex flex-column gap-3 px-4 pt-3\">\n <ol className=\"breadcrumb\">\n <li className=\"breadcrumb-item\">\n <BreadcrumbLink href={href(\"Feed\")}>DevHub</BreadcrumbLink>\n </li>\n\n <li className=\"breadcrumb-item active\" aria-current=\"page\">\n <BreadcrumbBold>{props.title}</BreadcrumbBold>\n </li>\n </ol>\n\n <div className=\"d-flex justify-content-between\">\n <div className=\"d-flex align-items-center\">\n <img src={props.icon} width=\"95px\" height=\"95px\"></img>\n\n <div>\n <div className=\"h5 pt-3 ps-3\">{props.title}</div>\n <div className=\"ps-3 pb-2 text-secondary\">{props.desc}</div>\n </div>\n </div>\n\n {widget(\"components.atom.toggle\", {\n active: state.shared.isEditorEnabled,\n className: \"visually-hidden\",\n direction: \"rtl\",\n key: \"community-editor-toggle\",\n label: \"( WIP ) Editor mode\",\n onSwitch: onEditorToggle,\n })}\n </div>\n\n <NavUnderline className=\"nav\">\n {topicTabs.map(({ defaultActive, iconClass, path, title }) =>\n title ? (\n <li className=\"nav-item\" key={title}>\n <a\n aria-current={defaultActive && \"page\"}\n className={[\n \"d-inline-flex gap-2\",\n tab === title ? \"nav-link active\" : \"nav-link\",\n ].join(\" \")}\n href={href(path, { label })}\n >\n {iconClass && <i className={iconClass} />}\n <span>{title}</span>\n </a>\n </li>\n ) : null\n )}\n </NavUnderline>\n </Header>\n );\n};\n\nreturn CommunityHeader(props);\n" }, "gigs-board.components.posts.ProfileHeader": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\nconst postId = props.post.id ?? (props.id ? parseInt(props.id) : 0);\nconst post =\n props.post ??\n Near.view(nearDevGovGigsContractAccountId, \"get_post\", { post_id: postId });\nif (!post) {\n return <div>Loading ...</div>;\n}\n\nreturn (\n <>\n {!hideImage && (\n <Widget\n className=\"col-auto aspect-ratio-square\"\n key=\"image\"\n src=\"mob.near/widget/ProfileImage\"\n props={{\n style: {\n width: \"3em\",\n height: \"3em\",\n marginRight: \"0.1em\",\n borderRadius: \"50%\",\n \"@media (max-width: 768px)\": {\n // Small screens\n marginBottom: \"12em\",\n },\n \"@media (min-width: 768px)\": {\n // Medium screens\n marginBottom: \"6em\",\n },\n },\n profile,\n accountId: \"post.author_id\",\n className: \"d-inline-block rounded-circle\",\n imageClassName: \"rounded w-100 h-100 align-top\",\n }}\n />\n )}\n {!hideName && <span key=\"name\">{name}</span>}\n {!hideAccountId && (\n <span key=\"accountId\" className=\"text-muted ms-1\">\n @{accountId}\n </span>\n )}\n </>\n);\n" }, "gigs-board.pages.community.Discussions": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\n/* INCLUDE: \"shared/mocks\" */\nconst communities = {\n \"zero-knowledge\": {\n overviewId: 397,\n eventsId: 401,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreiajwq6ep3n7veddozji2djv5vviyisabhycbweslvpwhsoyuzcwi4\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreihgxg5kwts2juldaeasveyuddkm6tcabmrat2aaq5u6uyljtyt7lu\",\n\n title: \"Zero Knowledge\",\n desc: \"Building a zero knowledge ecosystem on NEAR.\",\n telegram: \"NearZeroKnowledge\",\n },\n\n protocol: {\n overviewId: 412,\n eventsId: 413,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreidpitdafcnhkp4uyomacypdgqvxr35jtfnbxa5s6crby7qjk2nv5a\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreicg4svzfz5nvllomsahndgm7u62za4sib4mmbygxzhpcl4htqwr4a\",\n\n title: \"Protocol\",\n desc: \"Supporting the ongoing innovation of the NEAR Protocol.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-protocol\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Protocol NEPs\",\n },\n },\n },\n },\n\n telegram: \"NEAR_Protocol_Community_Group\",\n },\n\n tooling: {\n overviewId: 416,\n eventsId: 417,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreie2eaj5czmpfe6pe53kojzcspgozebdsonffwvbxtpuipnwahybvi\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreiehzr7z2fhoqqmkt3z667wubccbch6sqtsnvd6msodyzpnf72cszy\",\n\n title: \"Tooling\",\n desc: \"Supporting the ongoing innovation of tooling.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-tools\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Tooling NEPs\",\n },\n },\n },\n },\n\n telegram: \"NEAR_Tools_Community_Group\",\n },\n\n \"contract-standards\": {\n overviewId: 414,\n eventsId: 415,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreiepgdnu7soc6xgbyd4adicbf3eyxiiwqawn6tguaix6aklfpir634\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreiaowjqxds24fwcliyriintjd4ucciprii2rdxjmxgi7f5dmzuscey\",\n\n title: \"Contract Standards\",\n desc: \"Coordinating the contribution to the NEAR dapp standards.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Contract Standards NEPs\",\n },\n },\n },\n },\n\n telegram: \"nearnft\",\n },\n};\n/* END_INCLUDE: \"shared/mocks\" */\n\nif (!props.label) {\n return (\n <div class=\"alert alert-danger\" role=\"alert\">\n Error: label is required\n </div>\n );\n}\n\nconst label = props.label;\n\nconst discussionRequiredPosts =\n Near.view(nearDevGovGigsContractAccountId, \"get_posts_by_label\", {\n label,\n }) ?? [];\n\nconst community = communities[props.label];\n\nconst SearchResults = (\n <div style={{ display: \"none\" }}>\n <div class=\"row\">\n <div class=\"col\">\n {widget(\"components.post.DiscussionFeed\", {\n query: \"your-query-string\",\n })}\n </div>\n </div>\n </div>\n);\n\nconst onMention = (accountId) => (\n <span key={accountId} className=\"d-inline-flex\" style={{ fontWeight: 500 }}>\n <Widget\n src=\"neardevgov.near/widget/ProfileLine\"\n props={{\n accountId: accountId.toLowerCase(),\n hideAccountId: true,\n tooltip: true,\n }}\n />\n </span>\n);\n\nconst LabelsDisplay = (\n <div className=\"d-flex flex-wrap gap-2 mb-2\">\n {tags.length > 0 && (\n <div>\n {tags.map((tag, i) => (\n <span\n key={i}\n className=\"me-1 mb-1 fw-light badge border border-secondary text-bg-light\"\n >\n #{tag}\n </span>\n ))}\n </div>\n )}\n <div className=\"collapse public-tags\">\n <Widget src=\"mob.near/widget/PublicTags\" props={{ accountId }} />\n </div>\n </div>\n);\n\nconst Discussions = (\n <div class=\"row\">\n <div class=\"col-md-8\">\n {widget(\"components.layout.Controls\", {\n labels: discussionsRequiredLabels,\n })}\n <div className=\"row mb-2\">\n <div className=\"col\">\n <small className=\"text-muted\">\n Required label:\n <a href={href(\"Feed\", { label })} key={label}>\n <span\n className=\"badge text-bg-grey me-1\"\n style={{\n color: \"black\",\n fontSize: \"1.3em\",\n boxShadow: \"0px 1px 3px rgba(0, 0, 0, 0.2)\",\n }}\n >\n {label}\n </span>\n </a>\n </small>\n </div>\n </div>\n </div>\n {widget(\"components.layout.Controls\", {\n labels: label,\n })}\n <div class=\"row\">\n <div class=\"col\">\n {discussionRequiredPosts.map((postId) =>\n widget(\"components.posts.DiscussionFeed\", { id: postId }, postId)\n )}\n </div>\n </div>\n </div>\n);\n\nreturn widget(\"components.community.Layout\", {\n label: props.label,\n tab: \"Discussions\",\n children: (\n <div class=\"row\">\n <div class=\"col-md-9\">\n <div\n className=\"row align-items-center d-flex justify-content-between\"\n style={{ marginTop: \"18px\" }}\n >\n <div className=\"col-auto\">\n <div className=\"d-flex align-items-center\">\n <small className=\"text-muted\" style={{ fontSize: \"1.15em\" }}>\n Required tag:\n </small>\n <a href={href(\"Feed\", { label })} key={label}>\n <span\n className=\"badge ms-1\"\n style={{\n color: \"rgba(0, 0, 0, 0.7)\",\n fontSize: \"1em\",\n fontWeight: \"normal\",\n padding: \"0.2em 0.5em\",\n border: \"1px solid rgba(0, 80, 80, 0.2)\",\n }}\n >\n {label}\n </span>\n </a>\n </div>\n </div>\n <div className=\"col-auto aspect-ratio-square\">\n {widget(\"components.layout.Controls\", {\n labels: discussionsRequiredLabels,\n })}\n </div>\n </div>\n <br></br>\n <div class=\"row\">\n <div class=\"col\">\n {discussionRequiredPosts.map((postId) =>\n widget(\n \"components.posts.DiscussionFeed\",\n { id: postId, collapsed: true },\n postId\n )\n )}\n </div>\n </div>\n </div>\n <div class=\"col-3 container-fluid\">\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.community.Sidebar`}\n props={{\n metadata: metadata,\n accountId: accountId,\n widgetName: widgetName,\n label: props.label,\n }}\n />\n </div>\n </div>\n ),\n});\n" }, "gigs-board.components.layout.Banner": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\nconst Banner = styled.div`\n {\n height: 62px;\n background: #181818;\n margin-top: -24px;\n padding: 16px 20px;\n\n img {\n height: 30px;\n }\n\n margin-bottom: 25px;\n }\n`;\n\nreturn (\n <>\n <Banner className=\"d-flex justify-content-between\">\n <a href={href(\"Feed\")}>\n <img src=\"https://ipfs.near.social/ipfs/bafkreibjsn3gswlcc5mvgkfv7ady2lzkd2htm55l472suarbd34qryh2uy\"></img>\n </a>\n <div>\n <a\n href=\"https://www.neardevgov.org/blog/near-developer-dao\"\n class=\"text-white me-2\"\n >\n Developer DAO\n </a>\n\n <div class=\"btn-group\" role=\"group\">\n <button\n type=\"button\"\n class=\"btn btn-outline-light rounded-circle\"\n style={{\n width: \"30px\",\n height: \"30px\",\n padding: \"6px 0px\",\n borderWidth: \"0.5px\",\n lineHeight: \"0px\",\n }}\n data-bs-toggle=\"dropdown\"\n aria-expanded=\"false\"\n >\n <i class=\"bi bi-question-lg\"></i>\n </button>\n <ul class=\"dropdown-menu dropdown-menu-end\">\n <li>\n <a\n target=\"_blank\"\n class=\"dropdown-item\"\n href=\"https://github.com/near/devgigsboard-widgets/issues/new?assignees=&labels=bug&template=bug_report.md&title=\"\n >\n Report a bug\n </a>\n </li>\n <li>\n <a\n target=\"_blank\"\n class=\"dropdown-item\"\n href=\"https://github.com/near/devgigsboard-widgets/issues/new?assignees=&labels=enhancement&template=feature-request.md&title=\"\n >\n Suggest an improvement\n </a>\n </li>\n </ul>\n </div>\n </div>\n </Banner>\n </>\n);\n" }, "gigs-board.components.layout.LikeButton.Faces": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\nconst accountId = context.accountId;\n\nconst likesByUsers = props.likesByUsers || {};\nconst limit = props.limit ?? 3;\n\nlet likes = Object.keys(likesByUsers).reverse();\n\nconst graphLikes = [];\nconst nonGraph = [];\n\nconst graph =\n (accountId &&\n Social.keys(`${accountId}/graph/follow/*`, \"final\")[accountId].graph\n .follow) ||\n {};\n\nlikes.forEach((accountId) => {\n if (accountId in graph) {\n graphLikes.push(accountId);\n } else {\n nonGraph.push(accountId);\n }\n});\n\nlet faces = [...graphLikes, ...nonGraph];\n\nif (faces.length < limit + 3) {\n limit = faces.length;\n}\n\nconst renderFaces = faces.splice(0, limit);\n\nconst Faces = styled.span`\n .face {\n display: inline-block;\n position: relative;\n margin: -0.1em;\n height: 1.5em;\n width: 1.5em;\n min-width: 1.5em;\n vertical-align: top;\n img {\n object-fit: cover;\n border-radius: 50%;\n width: 100%;\n height: 100%;\n }\n }\n`;\n\nconst Others = styled.span`\n &:hover {\n color: white !important;\n }\n`;\n\nconst numLikes = likes.length - limit;\n\nreturn (\n <>\n <Faces className=\"ms-1\">\n {renderFaces.map((accountId, i) => (\n <a\n key={i}\n href={`#/mob.near/widget/ProfilePage?accountId=${accountId}`}\n className=\"text-decoration-none d-inline-block\"\n >\n <Widget\n src=\"mob.near/widget/Profile.OverlayTrigger\"\n props={{\n accountId,\n children: (\n <Widget\n src=\"mob.near/widget/ProfileImage\"\n props={{\n metadata,\n accountId,\n widgetName,\n style: { zIndex: 10 - i },\n className: \"face\",\n tooltip: false,\n imageStyle: {},\n imageClassName: \"\",\n }}\n />\n ),\n }}\n />\n </a>\n ))}\n </Faces>\n {numLikes > 0 ? (\n <OverlayTrigger\n placement=\"auto\"\n overlay={\n <Tooltip>\n <div\n className=\"text-truncate text-start\"\n style={{ maxWidth: \"16em\" }}\n >\n {faces.slice(0, 10).map((accountId, i) => (\n <Fragment key={i}>\n <Widget\n src=\"mob.near/widget/ProfileLine\"\n props={{ accountId, link: false }}\n />\n <br />\n </Fragment>\n ))}\n {faces.length > 10 ? \"...\" : \"\"}\n </div>\n </Tooltip>\n }\n >\n <span className=\"ms-1\">\n and {numLikes} other{numLikes === 1 ? \"\" : \"s\"}\n </span>\n </OverlayTrigger>\n ) : (\n \"\"\n )}\n </>\n);\n" }, "gigs-board.pages.WrapperWidget": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\nconst WrapperWidget = ({ children, id, storageType }) => {\n // This function handles the state change for the children widgets\n const handleStateChange = (key, value) => {\n // Use the unique identifier to create a unique storage key\n const storageKey = `${id}_${key}`;\n\n if (storageType === \"local\") {\n // Update the local storage with the new state\n Storage.set(storageKey, JSON.stringify(value));\n } else if (storageType === \"sync\") {\n // Update the sync storage with the new state\n // Replace this with the appropriate API call for your sync storage\n Storage.set(storageKey, JSON.stringify(value));\n }\n\n // Update component state\n State.update({ [storageKey]: value });\n };\n\n // This function initializes the state of the children widgets\n const initState = (key, defaultValue) => {\n // Use the unique identifier to create a unique storage key\n const storageKey = `${id}_${key}`;\n\n let storedValue;\n if (storageType === \"local\") {\n storedValue = Storage.get(storageKey);\n }\n\n if (storedValue) {\n return JSON.parse(storedValue);\n }\n\n return defaultValue;\n };\n\n // Render the children widgets and pass the state management functions as props\n return children.map((child) =>\n Widget({ src: child, props: { handleStateChange, initState } })\n );\n};\n" }, "gigs-board.pages.Feed": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\nState.init({\n propsLabel: props.label,\n label: props.label,\n author: props.author,\n});\n\n// When rerendered with different props, State will be preserved, so we need to update the state when we detect that the props have changed.\nif (props.label !== state.propsLabel) {\n State.update({\n propsLabel: props.label,\n label: props.label,\n });\n}\n\nconst onSearchLabel = (label) => {\n State.update({ label });\n};\n\nconst onSearchAuthor = (author) => {\n State.update({ author });\n};\n\nreturn widget(\"components.layout.Page\", {\n header: widget(\"components.community.FeedHeader\"),\n children: widget(\"components.posts.Search\", {\n children: widget(\"components.layout.Controls\"),\n recency: props.recency,\n label: state.label,\n author: state.author,\n //\n labelQuery: { label: state.label },\n onSearchLabel,\n //\n authorQuery: { author: state.author },\n onSearchAuthor,\n }),\n});\n" }, "gigs-board.components.posts.CompactPost": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n/* INCLUDE: \"shared/lib/gui\" */\nconst Card = styled.div`\n &:hover {\n box-shadow: rgba(3, 102, 214, 0.3) 0px 0px 0px 3px;\n }\n`;\n\nconst CompactContainer = styled.div`\n width: fit-content !important;\n max-width: 100%;\n`;\n/* END_INCLUDE: \"shared/lib/gui\" */\n\nconst postId = props.post.id ?? (props.id ? parseInt(props.id) : 0);\nconst post =\n props.post ??\n Near.view(nearDevGovGigsContractAccountId, \"get_post\", { post_id: postId });\nif (!post) {\n return <div>Loading ...</div>;\n}\nconst snapshot = post.snapshot;\n\nconst shareButton = (\n <a\n class=\"card-link\"\n href={href(\"Post\", { id: postId })}\n role=\"button\"\n target=\"_blank\"\n title=\"Open in new tab\"\n >\n <div class=\"bi bi-share\"></div>\n </a>\n);\n\nconst header = (\n <div className=\"card-header\">\n <small class=\"text-muted\">\n <div class=\"row justify-content-between\">\n <div class=\"col-4\">\n <a\n href={`#/neardevgov.near/widget/ProfilePage?accountId=${post.author_id}`}\n className=\"link-dark text-truncate\"\n >\n <Widget\n src=\"mob.near/widget/ProfileImage\"\n props={{\n metadata,\n accountId: post.author_id,\n widgetName,\n style: { height: \"1.5em\", width: \"1.5em\", minWidth: \"1.5em\" },\n }}\n />\n <span className=\"text-muted\">@{post.author_id}</span>\n </a>\n </div>\n <div class=\"col-5\">\n <div class=\"d-flex justify-content-end\">{shareButton}</div>\n </div>\n </div>\n </small>\n </div>\n);\n\nconst emptyIcons = {\n Idea: \"bi-lightbulb\",\n Comment: \"bi-chat\",\n Submission: \"bi-rocket\",\n Attestation: \"bi-check-circle\",\n Sponsorship: \"bi-cash-coin\",\n};\n\nconst borders = {\n Idea: \"border-secondary\",\n Comment: \"border-secondary\",\n Submission: \"border-secondary\",\n Attestation: \"border-secondary\",\n Sponsorship: \"border-secondary\",\n};\n\nconst renamedPostType =\n snapshot.post_type == \"Submission\" ? \"Solution\" : snapshot.post_type;\n\nconst postLables = post.snapshot.labels ? (\n <div class=\"card-title\">\n {post.snapshot.labels.map((label) => (\n <a href={href(\"Feed\", { label })} key={label}>\n <span class=\"badge text-bg-primary me-1\">{label}</span>\n </a>\n ))}\n </div>\n) : null;\n\nconst postTitle =\n snapshot.post_type == \"Comment\" ? null : (\n <div class=\"card-text\">\n <div className=\"row justify-content-between\">\n <div class=\"col-9\">\n <i class={`bi ${emptyIcons[snapshot.post_type]}`}> </i>\n {renamedPostType}: {snapshot.name}\n </div>\n </div>\n </div>\n );\n\nconst limitedMarkdown = styled.div`\n max-height: 6em;\n`;\n\n// Should make sure the posts under the currently top viewed post are limited in size.\nconst descriptionArea =\n snapshot.post_type == \"Comment\" ? (\n <limitedMarkdown className=\"overflow-auto\">\n <Markdown class=\"card-text\" text={snapshot.description}></Markdown>\n </limitedMarkdown>\n ) : null;\n\nreturn (\n <Card className={`card my-2 ${borders[snapshot.post_type]}`}>\n {header}\n <div className=\"card-body\">\n {postTitle}\n {descriptionArea}\n {postLables}\n </div>\n </Card>\n);\n" } } } } }

Transaction Execution Plan

Convert Transaction To Receipt
Gas Burned:
3 Tgas
Tokens Burned:
0.00031 
Receipt:
Predecessor ID:
Receiver ID:
Gas Burned:
89 Tgas
Tokens Burned:
0.00894 
Called method: 'set' in contract: social.near
Arguments:
{ "data": { "jgdev.near": { "widget": { "gigs-board.pages.Teams": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\nconst access_info =\n Near.view(nearDevGovGigsContractAccountId, \"get_access_control_info\") ?? null;\nconst root_members =\n Near.view(nearDevGovGigsContractAccountId, \"get_root_members\") ?? null;\n\nif (!access_info || !root_members) {\n return <div>Loading...</div>;\n}\n\nconst pageContent = (\n <div>\n {widget(\"components.teams.LabelsPermissions\", {\n rules: access_info.rules_list,\n })}\n {Object.keys(root_members).map((member) =>\n widget(\n \"components.teams.TeamInfo\",\n { member, members_list: access_info.members_list },\n member\n )\n )}\n </div>\n);\n\nreturn widget(\"components.layout.Page\", {\n children: pageContent,\n});\n" }, "DevGov.Notification.Item.Left": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\nif (!props.type) {\n return \"Loading ...\";\n}\n\nconst type = props.type.split(\"/\")[1];\nreturn props.type ? (\n <>\n {type == \"like\"\n ? \"liked your\"\n : type == \"reply\"\n ? \"replied to your\"\n : type == \"edit\"\n ? \"edited your\"\n : type == \"mention\"\n ? \"mentioned you in their\"\n : \"???\"}{\" \"}\n <a className=\"fw-bold text-muted\" href={href(\"Post\", { id: props.post })}>\n Developer Governance post\n </a>\n </>\n) : (\n \"Loading ...\"\n);\n" }, "gigs-board.pages.community.Sponsorship": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\n/* INCLUDE: \"shared/mocks\" */\nconst communities = {\n \"zero-knowledge\": {\n overviewId: 397,\n eventsId: 401,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreiajwq6ep3n7veddozji2djv5vviyisabhycbweslvpwhsoyuzcwi4\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreihgxg5kwts2juldaeasveyuddkm6tcabmrat2aaq5u6uyljtyt7lu\",\n\n title: \"Zero Knowledge\",\n desc: \"Building a zero knowledge ecosystem on NEAR.\",\n telegram: \"NearZeroKnowledge\",\n },\n\n protocol: {\n overviewId: 412,\n eventsId: 413,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreidpitdafcnhkp4uyomacypdgqvxr35jtfnbxa5s6crby7qjk2nv5a\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreicg4svzfz5nvllomsahndgm7u62za4sib4mmbygxzhpcl4htqwr4a\",\n\n title: \"Protocol\",\n desc: \"Supporting the ongoing innovation of the NEAR Protocol.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-protocol\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Protocol NEPs\",\n },\n },\n },\n },\n\n telegram: \"NEAR_Protocol_Community_Group\",\n },\n\n tooling: {\n overviewId: 416,\n eventsId: 417,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreie2eaj5czmpfe6pe53kojzcspgozebdsonffwvbxtpuipnwahybvi\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreiehzr7z2fhoqqmkt3z667wubccbch6sqtsnvd6msodyzpnf72cszy\",\n\n title: \"Tooling\",\n desc: \"Supporting the ongoing innovation of tooling.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-tools\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Tooling NEPs\",\n },\n },\n },\n },\n\n telegram: \"NEAR_Tools_Community_Group\",\n },\n\n \"contract-standards\": {\n overviewId: 414,\n eventsId: 415,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreiepgdnu7soc6xgbyd4adicbf3eyxiiwqawn6tguaix6aklfpir634\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreiaowjqxds24fwcliyriintjd4ucciprii2rdxjmxgi7f5dmzuscey\",\n\n title: \"Contract Standards\",\n desc: \"Coordinating the contribution to the NEAR dapp standards.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Contract Standards NEPs\",\n },\n },\n },\n },\n\n telegram: \"nearnft\",\n },\n};\n/* END_INCLUDE: \"shared/mocks\" */\n\nif (!props.label) {\n return (\n <div class=\"alert alert-danger\" role=\"alert\">\n Error: label is required\n </div>\n );\n}\n\nconst postIdsWithLabels = (labels) => {\n const ids = labels\n .map(\n (label) =>\n Near.view(nearDevGovGigsContractAccountId, \"get_posts_by_label\", {\n label,\n }) ?? []\n )\n .map((ids) => new Set(ids))\n .reduce((previous, current) => {\n let res = new Set();\n for (let id of current) {\n if (previous.has(id)) {\n res.add(id);\n }\n }\n return res;\n });\n ids.delete(communities[props.label].overviewId);\n ids.delete(communities[props.label].eventsId);\n return [...ids].reverse();\n};\n\nconst sponsorshipRequiredLabels = [\"funding\", props.label];\nconst sponsorshipRequiredPosts = postIdsWithLabels(sponsorshipRequiredLabels);\n\nconst Sponsorship = (\n <div>\n <div class=\"row mb-2 justify-content-center\">\n <div class=\"col-md-auto\">\n <small class=\"text-muted\">\n Post Type: <b>Sponsorship</b>\n </small>\n </div>\n <div class=\"col-md-auto\">\n <small class=\"text-muted\">\n Required labels:\n {sponsorshipRequiredLabels.map((label) => (\n <a href={href(\"Feed\", { label })} key={label}>\n <span class=\"badge text-bg-primary me-1\">{label}</span>\n </a>\n ))}\n </small>\n </div>\n </div>\n <div class=\"row\">\n <div class=\"col\">\n <div class=\"card\">\n <div class=\"card-body border-secondary\">\n <h6 class=\"card-title\">\n Sponsored Projects ({sponsorshipRequiredPosts.length})\n </h6>\n <div class=\"row\">\n {sponsorshipRequiredPosts.map((postId) => (\n <div class=\"col-3\">\n {widget(\n \"components.posts.CompactPost\",\n { id: postId },\n postId\n )}\n </div>\n ))}\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n);\n\nreturn widget(\"components.community.Layout\", {\n label: props.label,\n tab: \"Sponsorship\",\n children: Sponsorship,\n});\n" }, "gigs-board.entity.github-repo.board": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\n/* INCLUDE: \"shared/lib/gui\" */\nconst Card = styled.div`\n &:hover {\n box-shadow: rgba(3, 102, 214, 0.3) 0px 0px 0px 3px;\n }\n`;\n\nconst CompactContainer = styled.div`\n width: fit-content !important;\n max-width: 100%;\n`;\n/* END_INCLUDE: \"shared/lib/gui\" */\n\nconst dataToColumns = (data, columns) =>\n Object.values(columns).reduce(\n (registry, column) => ({\n ...registry,\n\n [column.id]: [\n ...(registry[column.id] ?? []),\n\n ...data.filter((ticket) =>\n column?.labelSearchTerms.every((searchTerm) =>\n searchTerm.length > 0\n ? ticket.labels.some((label) =>\n label.name.toLowerCase().includes(searchTerm.toLowerCase())\n )\n : true\n )\n ),\n ],\n }),\n\n {}\n );\n\nconst withType = (type) => (data) => ({ ...data, type });\n\nconst GithubRepoBoard = ({\n columns,\n dataTypesIncluded,\n description,\n editorTrigger,\n isEditable,\n pageURL,\n repoURL,\n ticketState,\n title,\n}) => {\n const ticketStateForSure =\n ticketState === \"open\" || ticketState === \"closed\" || ticketState === \"all\"\n ? ticketState\n : \"all\";\n\n State.init({\n ticketsByColumn: {},\n });\n\n if (repoURL) {\n const pullRequests = dataTypesIncluded.PullRequest\n ? (\n fetch(\n `https://api.github.com/repos/${repoURL\n .split(\"/\")\n .slice(-2)\n .concat([\"pulls\"])\n .join(\"/\")}?state=${ticketStateForSure}`\n ).body ?? []\n ).map(withType(\"PullRequest\"))\n : [];\n\n const issues = dataTypesIncluded.Issue\n ? (\n fetch(\n `https://api.github.com/repos/${repoURL\n .split(\"/\")\n .slice(-2)\n .concat([\"issues\"])\n .join(\"/\")}state=${ticketStateForSure}`\n ).body ?? []\n ).map(withType(\"Issue\"))\n : [];\n\n State.update({\n ticketsByColumn: dataToColumns([...issues, ...pullRequests], columns),\n });\n }\n\n return (\n <div className=\"d-flex flex-column gap-4 pb-4\">\n <div className=\"d-flex flex-column align-items-center gap-2\">\n <h5 className=\"h5 d-inline-flex gap-2 m-0\">\n <i className=\"bi bi-kanban-fill\" />\n <span>{title}</span>\n </h5>\n\n <p className=\"m-0 py-1 text-secondary text-center\">{description}</p>\n </div>\n\n <div className=\"d-flex justify-content-end gap-3\">\n {pageURL ? (\n <a\n className=\"card-link d-inline-flex me-auto\"\n href={pageURL}\n rel=\"noreferrer\"\n role=\"button\"\n target=\"_blank\"\n title=\"Link to this board\"\n >\n <span className=\"hstack gap-2\">\n <i className=\"bi bi-share\" />\n <span>Open in new tab</span>\n </span>\n </a>\n ) : null}\n\n {pageURL ? (\n <button\n className=\"btn btn-sm btn-outline-secondary d-inline-flex gap-2\"\n onClick={() => clipboard.writeText(pageURL)}\n >\n <i className=\"bi bi-clipboard-fill\" />\n <span>Copy link</span>\n </button>\n ) : null}\n\n {isEditable ? (\n <button\n className=\"btn btn-sm btn-primary d-inline-flex gap-2\"\n onClick={editorTrigger}\n >\n <i className=\"bi bi-wrench-adjustable-circle-fill\" />\n <span>Configure</span>\n </button>\n ) : null}\n </div>\n\n <div className=\"d-flex gap-3\" style={{ overflowX: \"auto\" }}>\n {Object.keys(columns).length > 0 ? (\n Object.values(columns).map((column) => (\n <div className=\"col-3\" key={column.id}>\n <div className=\"card\">\n <div\n className={[\n \"card-body d-flex flex-column gap-3\",\n \"border border-2 border-secondary rounded-2\",\n ].join(\" \")}\n >\n <h6 className=\"card-title h6 d-flex align-items-center gap-2 m-0\">\n {column.title}\n\n <span className=\"badge rounded-pill bg-secondary\">\n {(state.ticketsByColumn[column.id] ?? []).length}\n </span>\n </h6>\n\n <p class=\"text-secondary m-0\">{column.description}</p>\n\n <div class=\"d-flex flex-column gap-3\">\n {(state.ticketsByColumn[column.id] ?? []).map((data) =>\n widget(\"entity.github-repo.ticket\", { data }, data.id)\n )}\n </div>\n </div>\n </div>\n </div>\n ))\n ) : (\n <div\n className={[\n \"d-flex align-items-center justify-content-center\",\n \"w-100 text-black-50 opacity-50\",\n ].join(\" \")}\n style={{ height: 384 }}\n >\n No columns were created so far.\n </div>\n )}\n </div>\n </div>\n );\n};\n\nreturn GithubRepoBoard(props);\n" }, "gigs-board.components.community.Layout": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\n/* INCLUDE: \"shared/mocks\" */\nconst communities = {\n \"zero-knowledge\": {\n overviewId: 397,\n eventsId: 401,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreiajwq6ep3n7veddozji2djv5vviyisabhycbweslvpwhsoyuzcwi4\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreihgxg5kwts2juldaeasveyuddkm6tcabmrat2aaq5u6uyljtyt7lu\",\n\n title: \"Zero Knowledge\",\n desc: \"Building a zero knowledge ecosystem on NEAR.\",\n telegram: \"NearZeroKnowledge\",\n },\n\n protocol: {\n overviewId: 412,\n eventsId: 413,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreidpitdafcnhkp4uyomacypdgqvxr35jtfnbxa5s6crby7qjk2nv5a\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreicg4svzfz5nvllomsahndgm7u62za4sib4mmbygxzhpcl4htqwr4a\",\n\n title: \"Protocol\",\n desc: \"Supporting the ongoing innovation of the NEAR Protocol.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-protocol\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Protocol NEPs\",\n },\n },\n },\n },\n\n telegram: \"NEAR_Protocol_Community_Group\",\n },\n\n tooling: {\n overviewId: 416,\n eventsId: 417,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreie2eaj5czmpfe6pe53kojzcspgozebdsonffwvbxtpuipnwahybvi\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreiehzr7z2fhoqqmkt3z667wubccbch6sqtsnvd6msodyzpnf72cszy\",\n\n title: \"Tooling\",\n desc: \"Supporting the ongoing innovation of tooling.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-tools\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Tooling NEPs\",\n },\n },\n },\n },\n\n telegram: \"NEAR_Tools_Community_Group\",\n },\n\n \"contract-standards\": {\n overviewId: 414,\n eventsId: 415,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreiepgdnu7soc6xgbyd4adicbf3eyxiiwqawn6tguaix6aklfpir634\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreiaowjqxds24fwcliyriintjd4ucciprii2rdxjmxgi7f5dmzuscey\",\n\n title: \"Contract Standards\",\n desc: \"Coordinating the contribution to the NEAR dapp standards.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Contract Standards NEPs\",\n },\n },\n },\n },\n\n telegram: \"nearnft\",\n },\n};\n/* END_INCLUDE: \"shared/mocks\" */\n\nconst Content = styled.div`\n {\n padding: 0 32px;\n }\n`;\n\nif (!props.label) {\n return (\n <div class=\"alert alert-danger\" role=\"alert\">\n Error: label is required\n </div>\n );\n}\n\nconst community = communities[props.label];\n\nreturn (\n <>\n {widget(\"components.layout.Banner\")}\n {widget(\"components.community.CommunityHeader\", {\n title: community.title,\n icon: community.icon,\n desc: community.desc,\n label: props.label,\n tab: props.tab,\n })}\n <Content>{props.children}</Content>\n </>\n);\n" }, "gigs-board.pages.community.Telegram": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\n/* INCLUDE: \"shared/mocks\" */\nconst communities = {\n \"zero-knowledge\": {\n overviewId: 397,\n eventsId: 401,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreiajwq6ep3n7veddozji2djv5vviyisabhycbweslvpwhsoyuzcwi4\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreihgxg5kwts2juldaeasveyuddkm6tcabmrat2aaq5u6uyljtyt7lu\",\n\n title: \"Zero Knowledge\",\n desc: \"Building a zero knowledge ecosystem on NEAR.\",\n telegram: \"NearZeroKnowledge\",\n },\n\n protocol: {\n overviewId: 412,\n eventsId: 413,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreidpitdafcnhkp4uyomacypdgqvxr35jtfnbxa5s6crby7qjk2nv5a\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreicg4svzfz5nvllomsahndgm7u62za4sib4mmbygxzhpcl4htqwr4a\",\n\n title: \"Protocol\",\n desc: \"Supporting the ongoing innovation of the NEAR Protocol.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-protocol\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Protocol NEPs\",\n },\n },\n },\n },\n\n telegram: \"NEAR_Protocol_Community_Group\",\n },\n\n tooling: {\n overviewId: 416,\n eventsId: 417,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreie2eaj5czmpfe6pe53kojzcspgozebdsonffwvbxtpuipnwahybvi\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreiehzr7z2fhoqqmkt3z667wubccbch6sqtsnvd6msodyzpnf72cszy\",\n\n title: \"Tooling\",\n desc: \"Supporting the ongoing innovation of tooling.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-tools\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Tooling NEPs\",\n },\n },\n },\n },\n\n telegram: \"NEAR_Tools_Community_Group\",\n },\n\n \"contract-standards\": {\n overviewId: 414,\n eventsId: 415,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreiepgdnu7soc6xgbyd4adicbf3eyxiiwqawn6tguaix6aklfpir634\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreiaowjqxds24fwcliyriintjd4ucciprii2rdxjmxgi7f5dmzuscey\",\n\n title: \"Contract Standards\",\n desc: \"Coordinating the contribution to the NEAR dapp standards.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Contract Standards NEPs\",\n },\n },\n },\n },\n\n telegram: \"nearnft\",\n },\n};\n/* END_INCLUDE: \"shared/mocks\" */\n\nif (!props.label) {\n return (\n <div class=\"alert alert-danger\" role=\"alert\">\n Error: label is required\n </div>\n );\n}\n\nconst community = communities[props.label];\n\nconst group = community.telegram;\n\nconst Telegram = (\n <div>\n <iframe\n iframeResizer\n src={\n \"https://j96g3uepe0.execute-api.us-east-1.amazonaws.com/groups-ui/\" +\n group\n }\n frameborder=\"0\"\n // Required by iframeResizer\n style={{\n width: \"1px\",\n minWidth: \"100%\",\n }}\n ></iframe>\n </div>\n);\n\nreturn widget(\"components.community.Layout\", {\n label: props.label,\n tab: \"Telegram\",\n children: Telegram,\n});\n" }, "DevGov.Notification.Item.Right": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\nreturn props.post === undefined ? (\n \"Loading ...\"\n) : (\n <>\n <a className=\"btn btn-outline-dark\" href={href(\"Post\", { id: props.post })}>\n View Developer Governance post\n </a>\n </>\n);\n" }, "gigs-board.pages.community.Overview": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\n/* INCLUDE: \"shared/mocks\" */\nconst communities = {\n \"zero-knowledge\": {\n overviewId: 397,\n eventsId: 401,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreiajwq6ep3n7veddozji2djv5vviyisabhycbweslvpwhsoyuzcwi4\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreihgxg5kwts2juldaeasveyuddkm6tcabmrat2aaq5u6uyljtyt7lu\",\n\n title: \"Zero Knowledge\",\n desc: \"Building a zero knowledge ecosystem on NEAR.\",\n telegram: \"NearZeroKnowledge\",\n },\n\n protocol: {\n overviewId: 412,\n eventsId: 413,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreidpitdafcnhkp4uyomacypdgqvxr35jtfnbxa5s6crby7qjk2nv5a\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreicg4svzfz5nvllomsahndgm7u62za4sib4mmbygxzhpcl4htqwr4a\",\n\n title: \"Protocol\",\n desc: \"Supporting the ongoing innovation of the NEAR Protocol.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-protocol\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Protocol NEPs\",\n },\n },\n },\n },\n\n telegram: \"NEAR_Protocol_Community_Group\",\n },\n\n tooling: {\n overviewId: 416,\n eventsId: 417,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreie2eaj5czmpfe6pe53kojzcspgozebdsonffwvbxtpuipnwahybvi\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreiehzr7z2fhoqqmkt3z667wubccbch6sqtsnvd6msodyzpnf72cszy\",\n\n title: \"Tooling\",\n desc: \"Supporting the ongoing innovation of tooling.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-tools\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Tooling NEPs\",\n },\n },\n },\n },\n\n telegram: \"NEAR_Tools_Community_Group\",\n },\n\n \"contract-standards\": {\n overviewId: 414,\n eventsId: 415,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreiepgdnu7soc6xgbyd4adicbf3eyxiiwqawn6tguaix6aklfpir634\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreiaowjqxds24fwcliyriintjd4ucciprii2rdxjmxgi7f5dmzuscey\",\n\n title: \"Contract Standards\",\n desc: \"Coordinating the contribution to the NEAR dapp standards.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Contract Standards NEPs\",\n },\n },\n },\n },\n\n telegram: \"nearnft\",\n },\n};\n/* END_INCLUDE: \"shared/mocks\" */\n\nif (!props.label) {\n return (\n <div class=\"alert alert-danger\" role=\"alert\">\n Error: label is required\n </div>\n );\n}\n\nconst community = communities[props.label];\n\nconst overviewPost = Near.view(nearDevGovGigsContractAccountId, \"get_post\", {\n post_id: community.overviewId,\n});\nif (!overviewPost) {\n return <div>Loading ...</div>;\n}\n\nconst onMention = (accountId) => (\n <span key={accountId} className=\"d-inline-flex\" style={{ fontWeight: 500 }}>\n <Widget\n src=\"neardevgov.near/widget/ProfileLine\"\n props={{\n accountId: accountId.toLowerCase(),\n hideAccountId: true,\n tooltip: true,\n }}\n />\n </span>\n);\n\nconst Overview = (\n <div>\n <Markdown\n class=\"card-text\"\n text={overviewPost.snapshot.description}\n onMention={onMention}\n ></Markdown>\n </div>\n);\n\nreturn (\n <div className=\"container\">\n <div className=\"row\">\n <div className=\"col-xs-12\">\n {widget(\"components.community.Layout\", {\n label: props.label,\n tab: \"Overview\",\n })}\n </div>\n </div>\n <div className=\"row\">\n <div className=\"col-xs-12 col-lg-12\">{Overview}</div>\n </div>\n </div>\n);\n" }, "gigs-board.components.posts.Post": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n/* INCLUDE: \"shared/lib/gui\" */\nconst Card = styled.div`\n &:hover {\n box-shadow: rgba(3, 102, 214, 0.3) 0px 0px 0px 3px;\n }\n`;\n\nconst CompactContainer = styled.div`\n width: fit-content !important;\n max-width: 100%;\n`;\n/* END_INCLUDE: \"shared/lib/gui\" */\n\nconst postId = props.post.id ?? (props.id ? parseInt(props.id) : 0);\nconst post =\n props.post ??\n Near.view(nearDevGovGigsContractAccountId, \"get_post\", { post_id: postId });\nif (!post) {\n return <div>Loading ...</div>;\n}\n\nconst snapshot = post.snapshot;\n// If this post is displayed under another post. Used to limit the size.\nconst isUnderPost = props.isUnderPost ? true : false;\nconst parentId = Near.view(nearDevGovGigsContractAccountId, \"get_parent_id\", {\n post_id: postId,\n});\n\nconst childPostIdsUnordered =\n Near.view(nearDevGovGigsContractAccountId, \"get_children_ids\", {\n post_id: postId,\n }) ?? [];\n\nconst childPostIds = props.isPreview ? [] : childPostIdsUnordered.reverse();\nconst expandable = props.isPreview ? false : props.expandable ?? false;\nconst defaultExpanded = expandable ? props.defaultExpanded : true;\n\nfunction readableDate(timestamp) {\n var a = new Date(timestamp);\n return a.toDateString() + \" \" + a.toLocaleTimeString();\n}\n\nconst timestamp = readableDate(\n snapshot.timestamp ? snapshot.timestamp / 1000000 : Date.now()\n);\n\nconst postSearchKeywords = props.searchKeywords ? (\n <div\n style={{ marginLeft: \"1rem\", fontFamily: \"monospace\" }}\n key=\"post-search-keywords\"\n >\n <span>Found keywords: </span>\n {props.searchKeywords.map((label) => {\n return <span class=\"badge text-bg-info me-1\">{label}</span>;\n })}\n </div>\n) : (\n <div key=\"post-search-keywords\"></div>\n);\n\nconst searchKeywords = props.searchKeywords ? (\n <div class=\"mb-1\" key=\"search-keywords\">\n <small class=\"text-muted\" style={{ marginLeft: \"1rem\" }}>\n {postSearchKeywords}\n </small>\n </div>\n) : (\n <div key=\"search-keywords\"></div>\n);\n\nconst linkToParent =\n isUnderPost || !parentId ? (\n <div key=\"link-to-parent\"></div>\n ) : (\n <div className=\"card-header\" key=\"link-to-parent\">\n <a href={href(\"Post\", { id: parentId })}>\n <i class=\"bi bi-arrow-90deg-up\"></i>Go to parent{\" \"}\n </a>\n </div>\n );\n\nconst allowedToEdit =\n !props.isPreview &&\n Near.view(nearDevGovGigsContractAccountId, \"is_allowed_to_edit\", {\n post_id: postId,\n editor: context.accountId,\n });\n\nconst btnEditorWidget = (postType, name) => {\n return (\n <li>\n <a\n class=\"dropdown-item\"\n data-bs-toggle=\"collapse\"\n href={`#collapse${postType}Editor${postId}`}\n role=\"button\"\n aria-expanded=\"false\"\n aria-controls={`collapse${postType}Editor${postId}`}\n >\n {name}\n </a>\n </li>\n );\n};\n\nconst editControl = allowedToEdit ? (\n <div class=\"btn-group\" role=\"group\">\n <a\n class=\"card-link px-2\"\n role=\"button\"\n title=\"Edit post\"\n data-bs-toggle=\"dropdown\"\n aria-expanded=\"false\"\n type=\"button\"\n >\n <div class=\"bi bi-pencil-square\"></div>\n </a>\n <ul class=\"dropdown-menu\">\n {btnEditorWidget(\"Idea\", \"Edit as an idea\")}\n {btnEditorWidget(\"Submission\", \"Edit as a solution\")}\n {btnEditorWidget(\"Attestation\", \"Edit as an attestation\")}\n {btnEditorWidget(\"Sponsorship\", \"Edit as a sponsorship\")}\n {btnEditorWidget(\"Comment\", \"Edit as a comment\")}\n </ul>\n </div>\n) : (\n <div></div>\n);\n\nconst shareButton = props.isPreview ? (\n <div></div>\n) : (\n <a\n class=\"card-link\"\n href={href(\"Post\", { id: postId })}\n role=\"button\"\n target=\"_blank\"\n title=\"Open in new tab\"\n style={{ color: \"rgb(0,128,128)\", border: \"1em\" }}\n >\n <div class=\"bi bi-share\"></div>\n </a>\n);\n\nconst StyledLink = styled.a`\n color: rgba(0, 0, 0, 0.8);\n font-size: inherit;\n font-style: italic;\n font-weight: bold;\n opacity: 0.75;\n text-decoration: none;\n &:hover {\n text-decoration: underline;\n }\n`;\n\nconst StyledDiv = styled.div`\n display: flex;\n flex-wrap: nowrap;\n justify-content: end;\n align-items: center;\n width: 100%;\n color: rgba(0, 0, 0, 0.8);\n // padding: \"15px\";\n margin-right: 16px;\n font-size: 1.2em;\n`;\n\nconst ResponsiveDiv = styled.div`\n display: flex;\n justify-content: end;\n align-items: center;\n width: 100%;\n @media (max-width: 768px) {\n flex-direction: column;\n align-items: flex-start;\n }\n`;\n\n// start of test edits\nconst accountId = (props.accountId = post.author_id);\nconst link = props.link ?? true;\nconst hideAccountId = props.hideAccountId;\nconst hideName = props.hideName;\nconst hideImage = props.hideImage;\n\nconst profile = props.profile ?? Social.getr(`${accountId}/profile`);\n\nconst name = profile.name ?? accountId;\nconst title = props.title ?? `${name} @${accountId}`;\nconst tooltip =\n props.tooltip && (props.tooltip === true ? title : props.tooltip);\n\nlet inner = (\n <>\n {!hideName && (\n <span key=\"name\">\n {name}\n <br></br>\n </span>\n )}\n {!hideAccountId && (\n <span key=\"accountId\" className=\"text-muted ms-1 d-flex\">\n @{accountId}\n </span>\n )}\n </>\n);\n\ninner = link ? (\n <a\n href={\n link !== true\n ? link\n : `#/mob.near/widget/ProfilePage?accountId=${accountId}`\n }\n className=\"link-dark text-truncate d-flex flex-column align-items-start\"\n >\n {inner}\n </a>\n) : (\n <span className=\"text-truncate d-flex flex-column align-items-start\">\n {inner}\n </span>\n);\n\nif (props.tooltip === true) {\n return (\n <Widget\n src=\"mob.near/widget/Profile.OverlayTrigger\"\n props={{ accountId, children: inner }}\n />\n );\n}\nif (tooltip) {\n inner = (\n <OverlayTrigger placement=\"auto\" overlay={<Tooltip>{tooltip}</Tooltip>}>\n {inner}\n </OverlayTrigger>\n );\n}\n// end of test edits\n\nconst header = (\n <ResponsiveDiv\n className=\"py-1 px-3\"\n style={{ fontSize: \"1em\", alignItems: \"start\" }}\n >\n <div className=\"d-flex align-items-start justify-content-between\">\n <div\n className=\"col-auto d-flex align-items-start\"\n style={{ padding: \"1rem\" }}\n >\n <div\n className=\"square rounded-circle\"\n style={{\n overflow: \"hidden\",\n width: \"3.33em\",\n height: \"3.33em\",\n backgroundColor: \"#008080\",\n }}\n >\n <Widget\n key=\"image\"\n src=\"mob.near/widget/ProfileImage\"\n props={{\n style: { width: \"100%\", height: \"100%\" },\n profile,\n accountId,\n }}\n />\n </div>\n\n <div\n style={{\n marginLeft: \"1em\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n }}\n >\n <span\n key=\"accountId\"\n className=\"text-muted \"\n style={{\n display: \"block\",\n fontSize: \"1rem\",\n fontWeight: \"500\",\n marginTop: \"0px\",\n }}\n >\n {inner}\n </span>\n </div>\n </div>\n </div>\n <StyledDiv>\n {editControl}\n <span className=\"px-2\">{timestamp}</span>\n <div className=\"bi bi-clock-history px-2\"></div>\n {shareButton}\n </StyledDiv>\n </ResponsiveDiv>\n);\n\nconst emptyIcons = {\n Idea: \"bi-lightbulb\",\n Comment: \"bi-chat\",\n Submission: \"bi-rocket\",\n Attestation: \"bi-check-circle\",\n Sponsorship: \"bi-cash-coin\",\n Github: \"bi-github\",\n Like: \"bi-heart\",\n Reply: \"bi-reply\",\n};\n\nconst fillIcons = {\n Idea: \"bi-lightbulb-fill\",\n Comment: \"bi-chat-fill\",\n Submission: \"bi-rocket-fill\",\n Attestation: \"bi-check-circle-fill\",\n Sponsorship: \"bi-cash-coin\",\n Github: \"bi-github\",\n Like: \"bi-heart-fill\",\n Reply: \"bi-reply-fill\",\n};\n\nconst borders = {\n Idea: \"border-secondary\",\n Comment: \"border-secondary\",\n Submission: \"border-secondary\",\n Attestation: \"border-secondary\",\n Sponsorship: \"border-secondary\",\n Github: \"border-secondary\",\n};\n\nconst containsLike = props.isPreview\n ? false\n : post.likes.find((l) => l.author_id == context.accountId);\nconst likeBtnClass = containsLike ? fillIcons.Like : emptyIcons.Like;\n// This must be outside onLike, because Near.view returns null at first, and when the view call finished, it returns true/false.\n// If checking this inside onLike, it will give `null` and we cannot tell the result is true or false.\nlet grantNotify = Near.view(\"social.near\", \"is_write_permission_granted\", {\n predecessor_id: nearDevGovGigsContractAccountId,\n key: context.accountId + \"/index/notify\",\n});\nif (grantNotify === null) {\n return <div>Loading...</div>;\n}\nconst onLike = () => {\n if (!context.accountId) {\n return;\n }\n let likeTxn = [\n {\n contractName: nearDevGovGigsContractAccountId,\n methodName: \"add_like\",\n args: {\n post_id: postId,\n },\n deposit: Big(10).pow(21).mul(2),\n gas: Big(10).pow(12).mul(100),\n },\n ];\n if (grantNotify === false) {\n likeTxn.unshift({\n contractName: \"social.near\",\n methodName: \"grant_write_permission\",\n args: {\n predecessor_id: nearDevGovGigsContractAccountId,\n keys: [context.accountId + \"/index/notify\"],\n },\n deposit: Big(10).pow(23),\n gas: Big(10).pow(12).mul(30),\n });\n }\n Near.call(likeTxn);\n};\nconst btnCreatorWidget = (postType, icon, name, desc) => {\n return (\n <li class=\"py-1\">\n <a\n class=\"dropdown-item text-decoration-none d-flex align-items-center lh-sm\"\n style={{ color: \"rgb(55,109,137)\" }}\n data-bs-toggle=\"collapse\"\n href={`#collapse${postType}Creator${postId}`}\n role=\"button\"\n aria-expanded=\"false\"\n aria-controls={`collapse${postType}Creator${postId}`}\n >\n <i class={`bi ${icon}`} style={{ fontSize: \"1rem\" }}>\n {\" \"}\n </i>\n <div class=\"ps-2 text-wrap\" style={{ width: \"18rem\" }}>\n <div>{name}</div>\n <small class=\"fw-light text-secondary\">{desc}</small>\n </div>\n </a>\n </li>\n );\n};\n\nconst buttonsFooter = props.isPreview ? null : (\n <div class=\"row\" key=\"buttons-footer\" style={{ marginLeft: \"0.2rem\" }}>\n <div class=\"col-8\">\n <div\n class=\"btn-group text-sm\"\n role=\"group\"\n aria-label=\"Basic outlined example\"\n >\n <button\n type=\"button\"\n class=\"btn btn-outline-secondary\"\n style={{ border: \"0px\", opacity: \"0.7\" }}\n onClick={onLike}\n >\n <i class={`bi ${likeBtnClass}`}> </i>\n {post.likes.length == 0\n ? \"Like\"\n : widget(\"components.layout.LikeButton.Faces\", {\n likesByUsers: Object.fromEntries(\n post.likes.map(({ author_id }) => [author_id, \"\"])\n ),\n })}\n </button>\n <div class=\"btn-group text-sm\" role=\"group\">\n <button\n type=\"button\"\n class=\"btn btn-outline-secondary\"\n style={{ border: \"0px\", opacity: \"0.84\" }}\n data-bs-toggle=\"dropdown\"\n aria-expanded=\"false\"\n >\n <i class={`bi ${emptyIcons.Reply}`}> </i> Reply\n </button>\n <ul class=\"dropdown-menu\">\n {btnCreatorWidget(\n \"Idea\",\n emptyIcons.Idea,\n \"Idea\",\n \"Get feedback from the community about a problem, opportunity, or need.\"\n )}\n {btnCreatorWidget(\n \"Submission\",\n emptyIcons.Submission,\n \"Solution\",\n \"Provide a specific proposal or implementation to an idea, optionally requesting funding.\"\n )}\n {btnCreatorWidget(\n \"Attestation\",\n emptyIcons.Attestation,\n \"Attestation\",\n \"Formally review or validate a solution as a recognized expert.\"\n )}\n {btnCreatorWidget(\n \"Sponsorship\",\n emptyIcons.Sponsorship,\n \"Sponsorship\",\n \"Offer to fund projects, events, or proposals that match your needs.\"\n )}\n <li>\n <hr class=\"dropdown-divider\" />\n </li>\n {btnCreatorWidget(\n \"Comment\",\n emptyIcons.Comment,\n \"Comment\",\n \"Ask a question, provide information, or share a resource that is relevant to the thread.\"\n )}\n </ul>\n </div>\n <button\n type=\"button\"\n class=\"btn btn-outline-secondary text-sm\"\n style={{ border: \"0px\", opacity: \"0.84\" }}\n data-bs-toggle=\"collapse\"\n href={`#collapseChildPosts${postId}`}\n aria-expanded={defaultExpanded}\n aria-controls={`collapseChildPosts${postId}`}\n >\n <i class=\"bi bi-arrows-expand\"> </i>{\" \"}\n {`Expand Replies (${childPostIds.length})`}\n </button>\n </div>\n </div>\n </div>\n);\n\nconst CreatorWidget = (postType) => {\n return (\n <div\n class=\"collapse\"\n id={`collapse${postType}Creator${postId}`}\n data-bs-parent={`#accordion${postId}`}\n >\n {widget(\"components.posts.PostEditor\", {\n postType,\n parentId: postId,\n mode: \"Create\",\n })}\n </div>\n );\n};\n\nconst EditorWidget = (postType) => {\n return (\n <div\n class=\"collapse\"\n id={`collapse${postType}Editor${postId}`}\n data-bs-parent={`#accordion${postId}`}\n >\n {widget(\"components.posts.PostEditor\", {\n postType,\n postId,\n mode: \"Edit\",\n author_id: post.author_id,\n name: post.snapshot.name,\n description: post.snapshot.description,\n labels: post.snapshot.labels,\n amount: post.snapshot.amount,\n token: post.snapshot.sponsorship_token,\n supervisor: post.snapshot.supervisor,\n githubLink: post.snapshot.github_link,\n })}\n </div>\n );\n};\n\nconst editorsFooter = props.isPreview ? null : (\n <div class=\"row\" id={`accordion${postId}`} key=\"editors-footer\">\n {CreatorWidget(\"Comment\")}\n {EditorWidget(\"Comment\")}\n {CreatorWidget(\"Idea\")}\n {EditorWidget(\"Idea\")}\n {CreatorWidget(\"Submission\")}\n {EditorWidget(\"Submission\")}\n {CreatorWidget(\"Attestation\")}\n {EditorWidget(\"Attestation\")}\n {CreatorWidget(\"Sponsorship\")}\n {EditorWidget(\"Sponsorship\")}\n {CreatorWidget(\"Github\")}\n {EditorWidget(\"Github\")}\n </div>\n);\n\nconst renamedPostType =\n snapshot.post_type == \"Submission\" ? \"Solution\" : snapshot.post_type;\n\nconst postLabels = post.snapshot.labels ? (\n <div\n class=\"card-title\"\n key=\"post-labels\"\n style={{ marginLeft: \"1rem\", marginBottom: \"0.8rem\" }}\n >\n {post.snapshot.labels.map((label) => {\n return (\n <>\n <a href={href(\"Feed\", { label })} key={label}>\n <span\n className=\"badge ms-1\"\n style={{\n color: \"rgba(0, 0, 0, 0.7)\",\n fontSize: \"1em\",\n fontWeight: \"normal\",\n padding: \"0.2em 0.5em\",\n border: \"1px solid rgba(0, 80, 80, 0.2)\",\n marginTop: \"1rem\",\n }}\n >\n {label}\n </span>\n </a>\n </>\n );\n })}\n </div>\n) : (\n <div key=\"post-labels\"></div>\n);\n\nconst postTitle =\n snapshot.post_type == \"Comment\" ? (\n <div key=\"post-title\"></div>\n ) : (\n <h5 class=\"card-title\" key=\"post-title\">\n <div\n className=\"row justify-content-between\"\n style={{ fontSize: \"1.3em\", fontWeight: \"600\", marginLeft: \"0.3rem\" }}\n >\n <div class=\"col-12\">\n <i class={`bi ${emptyIcons[snapshot.post_type]}`}> </i>\n {renamedPostType}: {snapshot.name}\n </div>\n </div>\n </h5>\n );\n\nconst postExtra =\n snapshot.post_type == \"Sponsorship\" ? (\n <div key=\"post-extra\">\n <h6\n class=\"card-subtitle text-muted\"\n style={{\n marginLeft: \"1rem\",\n marginBottom: \"1rem\",\n fontSize: \"1.25em\",\n fontWeight: \"600\",\n }}\n >\n Maximum amount: {snapshot.amount} {snapshot.sponsorship_token}\n </h6>\n <h6\n class=\"card-subtitle text-muted\"\n style={{\n marginLeft: \"1rem\",\n marginBottom: \"1.5rem\",\n fontSize: \"1.25em\",\n fontWeight: \"600\",\n }}\n >\n Supervisor:{\" \"}\n <Widget\n src={`neardevgov.near/widget/ProfileLine`}\n props={{ accountId: snapshot.supervisor }}\n />\n </h6>\n </div>\n ) : (\n <div></div>\n );\n\nconst postsList =\n props.isPreview || childPostIds.length == 0 ? (\n <div key=\"posts-list\"></div>\n ) : (\n <div class=\"row\" key=\"posts-list\">\n <div\n class={`collapse ${defaultExpanded ? \"show\" : \"\"}`}\n id={`collapseChildPosts${postId}`}\n >\n {childPostIds.map((childId) =>\n widget(\n \"components.posts.Post\",\n { id: childId, isUnderPost: true },\n `subpost${childId}of${postId}`\n )\n )}\n </div>\n </div>\n );\n\n// Determine if located in the post page.\n\nconst isInList = props.isInList;\nconst contentArray = snapshot.description.split(\"\\n\");\nconst needClamp = isInList && contentArray.length > 5;\n// Initialize 'clamp' to 'true' if the content is long enough, otherwise 'false'\ninitState({\n clamp: needClamp,\n});\nconst onMention = (accountId) => (\n <span key={accountId} className=\"d-inline-flex\" style={{ fontWeight: 500 }}>\n <Widget\n src=\"neardevgov.near/widget/ProfileLine\"\n props={{\n accountId: accountId.toLowerCase(),\n hideAccountId: true,\n tooltip: true,\n }}\n />\n </span>\n);\n\n// Determine whether the content is longer than 4 lines\nconst isContentLong = contentArray.length > 5;\n\nconst clampedContent = state.clamp\n ? contentArray.slice(0, 5).join(\"\\n\")\n : snapshot.description;\n\n// Your CSS classes for styling. Make sure the names match exactly with the ones you're using in your divs.\nconst limitedMarkdown = styled.div`\n max-height: 23em;\n`;\n\nconst clampMarkdown = styled.div`\n .clamp {\n display: -webkit-box;\n -webkit-line-clamp: 5;\n -webkit-box-orient: vertical;\n overflow: hidden;\n }\n`;\n\nconst descriptionArea = isUnderPost ? (\n <limitedMarkdown\n className=\"overflow-auto\"\n key=\"description-area\"\n style={{ marginLeft: \"1rem\", paddingRight: \"15px\", marginBottom: \"1rem\" }}\n >\n <Markdown\n className=\"card-text\"\n text={snapshot.description}\n onMention={onMention}\n />\n </limitedMarkdown>\n) : (\n <clampMarkdown>\n <div\n className={state.clamp ? \"clamp\" : \"\"}\n style={{\n fontSize: \"1rem\",\n paddingLeft: \"15px\",\n paddingRight: \"15px\",\n marginBottom: \"-10px\",\n }}\n >\n <Markdown\n className=\"card-text\"\n text={state.clamp ? clampedContent : snapshot.description}\n onMention={onMention}\n key=\"description-area\"\n ></Markdown>\n </div>\n {state.clamp && isContentLong ? (\n <div className=\"d-flex justify-content-center\">\n <StyledLink>\n <a\n style={{ fontSize: \"1rem\", fontWeight: 700 }}\n className=\"btn btn-link text-black\"\n onClick={() => State.update({ clamp: false })}\n >\n <br></br>\n See More...\n </a>\n </StyledLink>\n </div>\n ) : !state.clamp && isContentLong ? (\n <div className=\"d-flex justify-content-center\">\n <StyledLink>\n <a\n style={{ fontSize: \"1rem\", fontWeight: 700 }}\n className=\"btn btn-link text-black\"\n onClick={() => State.update({ clamp: true })}\n >\n ^ Close\n </a>\n </StyledLink>\n </div>\n ) : null}\n </clampMarkdown>\n);\n\nreturn (\n <Card className={`card my-2`}>\n {linkToParent}\n {header}\n <div className=\"card-body \">\n {searchKeywords}\n {postTitle}\n <div style={{ marginTop: \"1rem\", marginBottom: \"1rem\" }}></div>\n {postExtra}\n {descriptionArea}\n {postLabels}\n {buttonsFooter}\n {editorsFooter}\n {postsList}\n </div>\n </Card>\n);\n" }, "gigs-board.pages.Boards": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\nconst selectedBoardId = props.selectedBoardId ?? \"mnwtransition\";\n\nconst boards = props.boards ?? [\n {\n name: \"near.social\",\n id: \"nearsocial\",\n config: {\n requiredLabels: [\"near-social\"],\n columns: [\n { label: \"widget\", title: \"Widget\" },\n { label: \"integration\", title: \"Integration\" },\n { label: \"feature-request\", title: \"Feature Request\" },\n ],\n excludedLabels: [],\n },\n },\n {\n name: \"Gigs Board\",\n id: \"gigsboard\",\n config: {\n requiredLabels: [\"gigs-board\"],\n columns: [\n { label: \"nep\", title: \"NEP\" },\n { label: \"badges\", title: \"Badges\" },\n { label: \"feature-request\", title: \"Feature Request\" },\n ],\n excludedLabels: [],\n },\n },\n {\n name: \"Funding\",\n id: \"funding\",\n config: {\n requiredLabels: [\"funding\"],\n columns: [\n { label: \"funding-new-request\", title: \"New Request\" },\n {\n label: \"funding-information-collection\",\n title: \"Information Collection\",\n },\n { label: \"funding-processing\", title: \"Processing\" },\n { label: \"funding-funded\", title: \"Funded\" },\n ],\n excludedLabels: [],\n },\n },\n];\n\n// Bootstrap tabs documentation: https://getbootstrap.com/docs/5.2/components/navs-tabs\nconst pageContent = (\n <div>\n <ul class=\"nav nav-tabs my-3\">\n {boards.map((board) => (\n <li class=\"nav-item\" key={board.id}>\n <a\n href={href(\"Boards\", { selectedBoardId: board.id })}\n class={`nav-link ${board.id == selectedBoardId ? \"active\" : \"\"}`}\n >\n {board.name}\n </a>\n </li>\n ))}\n </ul>\n <div class=\"tab-content\">\n {boards.map((board) => (\n <div\n class={`tab-pane fade ${\n board.id == selectedBoardId ? \"show active\" : \"\"\n }`}\n id={`board${board.id}`}\n role=\"tabpanel\"\n aria-labelledby={`${board.id}-tab`}\n tabindex=\"0\"\n key={board.id}\n >\n {widget(\"components.boards.KanbanBoard\", {\n requiredLabels: board.config.requiredLabels,\n excludedLabels: board.config.excludedLabels,\n columns: board.config.columns,\n boardId: board.id,\n })}\n </div>\n ))}\n </div>\n </div>\n);\n\nreturn widget(\"components.layout.Page\", {\n children: pageContent,\n});\n" }, "gigs-board.pages.community.github": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\nconst CommunityGithubPage = ({ label }) =>\n widget(\"components.community.Layout\", {\n label,\n tab: \"GitHub\",\n children: (\n <div className=\"d-flex flex-column\">\n {widget(\"feature.integration.github.board-config-editor\", {\n label,\n pageURL: \"near.org\" + href(\"community.github\", { label }),\n })}\n </div>\n ),\n });\n\nreturn CommunityGithubPage(props);\n" }, "gigs-board.pages.Post": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\nreturn widget(\"components.layout.Page\", {\n children: widget(\"components.posts.Post\", {\n id: props.id,\n }),\n});\n" }, "gigs-board.components.community.FeedHeader": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\n/* INCLUDE: \"shared/mocks\" */\nconst communities = {\n \"zero-knowledge\": {\n overviewId: 397,\n eventsId: 401,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreiajwq6ep3n7veddozji2djv5vviyisabhycbweslvpwhsoyuzcwi4\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreihgxg5kwts2juldaeasveyuddkm6tcabmrat2aaq5u6uyljtyt7lu\",\n\n title: \"Zero Knowledge\",\n desc: \"Building a zero knowledge ecosystem on NEAR.\",\n telegram: \"NearZeroKnowledge\",\n },\n\n protocol: {\n overviewId: 412,\n eventsId: 413,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreidpitdafcnhkp4uyomacypdgqvxr35jtfnbxa5s6crby7qjk2nv5a\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreicg4svzfz5nvllomsahndgm7u62za4sib4mmbygxzhpcl4htqwr4a\",\n\n title: \"Protocol\",\n desc: \"Supporting the ongoing innovation of the NEAR Protocol.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-protocol\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Protocol NEPs\",\n },\n },\n },\n },\n\n telegram: \"NEAR_Protocol_Community_Group\",\n },\n\n tooling: {\n overviewId: 416,\n eventsId: 417,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreie2eaj5czmpfe6pe53kojzcspgozebdsonffwvbxtpuipnwahybvi\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreiehzr7z2fhoqqmkt3z667wubccbch6sqtsnvd6msodyzpnf72cszy\",\n\n title: \"Tooling\",\n desc: \"Supporting the ongoing innovation of tooling.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-tools\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Tooling NEPs\",\n },\n },\n },\n },\n\n telegram: \"NEAR_Tools_Community_Group\",\n },\n\n \"contract-standards\": {\n overviewId: 414,\n eventsId: 415,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreiepgdnu7soc6xgbyd4adicbf3eyxiiwqawn6tguaix6aklfpir634\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreiaowjqxds24fwcliyriintjd4ucciprii2rdxjmxgi7f5dmzuscey\",\n\n title: \"Contract Standards\",\n desc: \"Coordinating the contribution to the NEAR dapp standards.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Contract Standards NEPs\",\n },\n },\n },\n },\n\n telegram: \"nearnft\",\n },\n};\n/* END_INCLUDE: \"shared/mocks\" */\n\nconst Gradient = styled.div`\n {\n margin-top: -25px;\n margin-bottom: 25px;\n height: 250px;\n text-align: center;\n background: radial-gradient(\n circle,\n rgba(29, 55, 57, 1) 30%,\n rgba(24, 24, 24, 1) 80%\n );\n\n font-family: Arial, sans-serif;\n }\n\n .text-primary-gradient {\n color: #53fdca;\n -webkit-text-fill-color: transparent;\n background-image: linear-gradient(#8e76ba, #1ed2f0);\n -webkit-background-clip: text;\n background-clip: text;\n }\n\n .subtitle-above {\n font-size: 18px;\n letter-spacing: 1px;\n font-family: Courier, monospace;\n }\n\n .subtitle-below {\n font-size: 16px;\n }\n\n .slogan {\n font-weight: 600;\n font-size: 60px;\n }\n`;\n\nreturn (\n <>\n <Gradient className=\"d-flex flex-column justify-content-center\">\n <div class=\"subtitle-above text-white opacity-75 mb-2\">\n A decentralized community of\n </div>\n <h1 class=\"mb-3 text-white slogan\">\n <span class=\"text-primary-gradient\">NEAR </span>Developers\n </h1>\n <div class=\"subtitle-below text-white opacity-75\">\n Share your ideas, match solutions, and access support and funding.\n </div>\n </Gradient>\n <div class=\"h5 pb-3\">Featured Communities</div>\n <div class=\"row\">\n {Object.entries(communities).map(([label, community]) => {\n return (\n <div class=\"col\">\n {widget(\n \"components.community.FeaturedCommunity\",\n {\n label,\n ...community,\n },\n label\n )}\n </div>\n );\n })}\n </div>\n <div class=\"h5 pb-3 pt-5\">Activity</div>\n </>\n);\n" }, "gigs-board.components.posts.PostEditor": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\nconst postType = props.postType ?? \"Sponsorship\";\nconst parentId = props.parentId ?? null;\nconst postId = props.postId ?? null;\nconst mode = props.mode ?? \"Create\";\n\nconst referralLabels = props.referral ? [`referral:${props.referral}`] : [];\nconst labelStrings = (props.labels ?? []).concat(referralLabels);\nconst labels = labelStrings.map((s) => {\n return { name: s };\n});\n\nconst initState = props.initState;\nconst handleStateChange = props.handleStateChange;\n\ninitState({\n author_id: context.accountId,\n // Should be a list of objects with field \"name\".\n labels,\n // Should be a list of labels as strings.\n // Both of the label structures should be modified together.\n labelStrings,\n postType,\n name: props.name ?? \"\",\n description: props.description ?? \"\",\n amount: props.amount ?? \"0\",\n token: props.token ?? \"Near\",\n supervisor: props.supervisor ?? \"\",\n githubLink: props.githubLink ?? \"\",\n warning: \"\",\n});\nconst savedState = Storage.getItem(\"widgetState\");\nif (savedState) {\n handleStateChange(JSON.parse(savedState));\n}\n\nlet fields = {\n Comment: [\"description\"],\n Idea: [\"name\", \"description\"],\n Submission: [\"name\", \"description\"],\n Attestation: [\"name\", \"description\"],\n Sponsorship: [\n \"name\",\n \"description\",\n \"amount\",\n \"sponsorship_token\",\n \"supervisor\",\n ],\n Github: [\"githubLink\", \"name\", \"description\"],\n}[postType];\n\n// This must be outside onClick, because Near.view returns null at first, and when the view call finished, it returns true/false.\n// If checking this inside onClick, it will give `null` and we cannot tell the result is true or false.\nlet grantNotify = Near.view(\"social.near\", \"is_write_permission_granted\", {\n predecessor_id: nearDevGovGigsContractAccountId,\n key: context.accountId + \"/index/notify\",\n});\nif (grantNotify === null) {\n return;\n}\nconst onSubmit = () => {\n let labels = state.labelStrings;\n var body = {\n Comment: { description: state.description, comment_version: \"V2\" },\n Idea: {\n name: state.name,\n description: state.description,\n idea_version: \"V1\",\n },\n Submission: {\n name: state.name,\n description: state.description,\n submission_version: \"V1\",\n },\n Attestation: {\n name: state.name,\n description: state.description,\n attestation_version: \"V1\",\n },\n Sponsorship: {\n name: state.name,\n description: state.description,\n amount: state.amount,\n sponsorship_token: state.token,\n supervisor: state.supervisor,\n sponsorship_version: \"V1\",\n },\n Github: {\n name: state.name,\n description: state.description,\n github_version: \"V0\",\n github_link: state.githubLink,\n },\n }[postType];\n body[\"post_type\"] = postType;\n if (!context.accountId) {\n return;\n }\n let txn = [];\n if (mode == \"Create\") {\n txn.push({\n contractName: nearDevGovGigsContractAccountId,\n methodName: \"add_post\",\n args: {\n parent_id: parentId,\n labels,\n body,\n },\n deposit: Big(10).pow(21).mul(2),\n gas: Big(10).pow(12).mul(100),\n });\n } else if (mode == \"Edit\") {\n txn.push({\n contractName: nearDevGovGigsContractAccountId,\n methodName: \"edit_post\",\n args: {\n id: postId,\n labels,\n body,\n },\n deposit: Big(10).pow(21).mul(2),\n gas: Big(10).pow(12).mul(100),\n });\n }\n if (mode == \"Create\" || mode == \"Edit\") {\n if (grantNotify === false) {\n txn.unshift({\n contractName: \"social.near\",\n methodName: \"grant_write_permission\",\n args: {\n predecessor_id: nearDevGovGigsContractAccountId,\n keys: [context.accountId + \"/index/notify\"],\n },\n deposit: Big(10).pow(23),\n gas: Big(10).pow(12).mul(30),\n });\n }\n Near.call(txn);\n }\n};\n\nconst githubLinkDiv = fields.includes(\"githubLink\") ? (\n <div className=\"col-lg-12 mb-2\">\n Github Issue URL:\n <input\n type=\"text\"\n value={state.githubLink}\n onChange={(event) => State.update({ githubLink: event.target.value })}\n />\n </div>\n) : null;\n\nconst nameDiv = fields.includes(\"name\") ? (\n <div className=\"col-lg-12 mb-2\">\n Name:\n <input\n type=\"text\"\n value={state.name}\n onChange={(event) => State.update({ name: event.target.value })}\n />\n </div>\n) : null;\n\nconst descriptionDiv = fields.includes(\"description\") ? (\n <div className=\"col-lg-12 mb-2\">\n Description:\n <textarea\n rows=\"5\"\n value={state.description}\n onChange={(event) => State.update({ description: event.target.value })}\n />\n </div>\n) : null;\n\nconst amountDiv = fields.includes(\"amount\") ? (\n <div className=\"col-lg-12 mb-2\">\n Amount:\n <input\n type=\"text\"\n value={state.amount}\n onChange={(event) => State.update({ amount: event.target.value })}\n />\n </div>\n) : null;\n\nconst tokenDiv = fields.includes(\"sponsorship_token\") ? (\n <div className=\"col-lg-12 mb-2\">\n Token:\n <input\n type=\"text\"\n value={state.token}\n onChange={(event) => State.update({ token: event.target.value })}\n />\n </div>\n) : null;\n\nconst supervisorDiv = fields.includes(\"supervisor\") ? (\n <div className=\"col-lg-12 mb-2\">\n Supervisor:\n <input\n type=\"text\"\n value={state.supervisor}\n onChange={(event) => State.update({ supervisor: event.target.value })}\n />\n </div>\n) : null;\n\nconst labelDiv = fields.includes(\"labels\") ? (\n <div className=\"col-lg-12 mb-2\">\n Labels:\n <input\n type=\"text\"\n value={state.labelStrings.join(\",\")}\n onChange={(event) => {\n let labels = event.target.value.split(\",\");\n labels = labels.map((o) => {\n o = o.trim();\n checkLabel(o);\n return { name: o };\n });\n State.update({ labels, labelStrings: event.target.value.split(\",\") });\n }}\n />\n </div>\n) : null;\n\nconst postTypeDiv = fields.includes(\"post_type\") ? (\n <div className=\"col-lg-12 mb-2\">\n Post Type:\n <select\n value={state.postType}\n onChange={(event) => State.update({ postType: event.target.value })}\n >\n <option value=\"Proposal\">Proposal</option>\n <option value=\"Issue\">Issue</option>\n <option value=\"Grant\">Grant</option>\n </select>\n </div>\n) : null;\n\nconst grantNotifyDiv = fields.includes(\"grantNotify\") ? (\n <div className=\"col-lg-12 mb-2\">\n Grant Notify:\n <input\n type=\"checkbox\"\n checked={state.grantNotify}\n onChange={(event) => State.update({ grantNotify: event.target.checked })}\n />\n </div>\n) : null;\n\nconst normalizeLabel = (label) =>\n label\n .replaceAll(/[- \\.]/g, \"_\")\n .replaceAll(/[^\\w]+/g, \"\")\n .replaceAll(/_+/g, \"-\")\n .replace(/^-+/, \"\")\n .replace(/-+$/, \"\")\n .toLowerCase()\n .trim(\"-\");\n\nconst checkLabel = (label) => {\n Near.asyncView(nearDevGovGigsContractAccountId, \"is_allowed_to_use_labels\", {\n editor: context.accountId,\n labels: [label],\n }).then((allowed) => {\n if (allowed) {\n State.update({ warning: \"\" });\n } else {\n State.update({\n warning:\n 'The label \"' +\n label +\n '\" is protected and can only be added by moderators',\n });\n return;\n }\n });\n};\n\nconst setLabels = (labels) => {\n labels = labels.map((o) => {\n o.name = normalizeLabel(o.name);\n return o;\n });\n if (labels.length < state.labels.length) {\n let oldLabels = new Set(state.labels.map((label) => label.name));\n for (let label of labels) {\n oldLabels.delete(label.name);\n }\n let removed = oldLabels.values().next().value;\n Near.asyncView(\n nearDevGovGigsContractAccountId,\n \"is_allowed_to_use_labels\",\n { editor: context.accountId, labels: [removed] }\n ).then((allowed) => {\n if (allowed) {\n let labelStrings = labels.map(({ name }) => name);\n State.update({ labels, labelStrings });\n } else {\n State.update({\n warning:\n 'The label \"' +\n removed +\n '\" is protected and can only be updated by moderators',\n });\n return;\n }\n });\n } else {\n let labelStrings = labels.map((o) => {\n return o.name;\n });\n State.update({ labels, labelStrings });\n }\n};\nconst existingLabelStrings =\n Near.view(nearDevGovGigsContractAccountId, \"get_all_allowed_labels\", {\n editor: context.accountId,\n }) ?? [];\nconst existingLabelSet = new Set(existingLabelStrings);\nconst existingLabels = existingLabelStrings.map((s) => {\n return { name: s };\n});\n\nconst labelEditor = (\n <div className=\"col-lg-12 mb-2\">\n Labels:\n <Typeahead\n multiple\n labelKey=\"name\"\n onInputChange={checkLabel}\n onChange={setLabels}\n options={existingLabels}\n placeholder=\"near.social, widget, NEP, standard, protocol, tool\"\n selected={state.labels}\n positionFixed\n allowNew={(results, props) => {\n return (\n !existingLabelSet.has(props.text) &&\n props.selected.filter((selected) => selected.name === props.text)\n .length == 0 &&\n Near.view(\n nearDevGovGigsContractAccountId,\n \"is_allowed_to_use_labels\",\n { editor: context.accountId, labels: [props.text] }\n )\n );\n }}\n />\n </div>\n);\n\nconst disclaimer = (\n <p>\n <i>\n * Note, all projects that were granted sponsorships are required to pass\n KYC to receive the funding.\n </i>\n </p>\n);\n\nconst renamedPostType = postType == \"Submission\" ? \"Solution\" : postType;\n// Below there is a weird code with fields.includes(\"githubLink\") ternary operator.\n// This is to hack around rendering bug of near.social.\nreturn (\n <div className=\"card\">\n <div className=\"card-header\">\n {mode} {renamedPostType}\n </div>\n\n <div class=\"card-body\">\n {state.warning ? (\n <div\n class=\"alert alert-warning alert-dismissible fade show\"\n role=\"alert\"\n >\n {state.warning}\n <button\n type=\"button\"\n class=\"btn-close\"\n data-bs-dismiss=\"alert\"\n aria-label=\"Close\"\n onClick={() => State.update({ warning: \"\" })}\n ></button>\n </div>\n ) : (\n <></>\n )}\n {fields.includes(\"githubLink\") ? (\n <div className=\"row\">\n {githubLinkDiv}\n {labelEditor}\n {nameDiv}\n {descriptionDiv}\n </div>\n ) : (\n <div className=\"row\">\n {labelEditor}\n {nameDiv}\n {amountDiv}\n {tokenDiv}\n {supervisorDiv}\n {descriptionDiv}\n </div>\n )}\n\n <a className=\"btn btn-outline-primary mb-2\" onClick={onSubmit}>\n Submit\n </a>\n {disclaimer}\n </div>\n <div class=\"card-footer\">\n Preview:\n {widget(\"components.posts.Post\", {\n isPreview: true,\n id: 0, // irrelevant\n post: {\n author_id: state.author_id,\n likes: [],\n snapshot: {\n editor_id: state.editor_id,\n labels: state.labelStrings,\n post_type: postType,\n name: state.name,\n description: state.description,\n amount: state.amount,\n sponsorship_token: state.token,\n supervisor: state.supervisor,\n github_link: state.githubLink,\n },\n },\n })}\n </div>\n </div>\n);\n" }, "gigs-board.components.boards.KanbanBoard": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\nconst requiredLabels = props.requiredLabels ?? [\"near-social\"];\nconst excludedLabels = props.excludedLabels ?? [\"nft\"];\nconst columns = props.columns ?? [\n { label: \"widget\", title: \"Widget\" },\n { label: \"integration\", title: \"Integration\" },\n { label: \"feature-request\", title: \"Feature Request\" },\n];\n\nconst labelsToIdSet = (labels) => {\n const ids = labels.map(\n (label) =>\n Near.view(nearDevGovGigsContractAccountId, \"get_posts_by_label\", {\n label,\n }) ?? []\n );\n const idsFlat = ids.flat(1);\n return new Set(idsFlat);\n};\n\nconst requiredPostsSet = labelsToIdSet(requiredLabels);\nconst excludedPostsSet = labelsToIdSet(excludedLabels);\n\nconst postsPerLabel = columns.map((column) => {\n let allIds = (\n Near.view(nearDevGovGigsContractAccountId, \"get_posts_by_label\", {\n label: column.label,\n }) ?? []\n ).reverse();\n if (requiredLabels.length > 0) {\n return {\n ...column,\n posts: allIds.filter(\n (i) => requiredPostsSet.has(i) && !excludedPostsSet.has(i)\n ),\n };\n } else {\n // No extra filtering is required.\n return { ...column, posts: allIds };\n }\n});\n\nreturn (\n <div>\n <div class=\"row mb-2\">\n {props.boardId ? (\n <div class=\"col\">\n <small class=\"text-muted\">\n <a\n class=\"card-link\"\n href={href(\"Boards\", { selectedBoardId: props.boardId })}\n role=\"button\"\n target=\"_blank\"\n title=\"Link to this board\"\n >\n <div class=\"hstack gap-3\">\n <div class=\"bi bi-share\"></div>\n <div>Link to this board</div>\n </div>\n </a>\n </small>\n </div>\n ) : null}\n\n {requiredLabels.length > 0 ? (\n <div class=\"col\">\n <small class=\"text-muted\">\n Required labels:\n {requiredLabels.map((label) => (\n <a href={href(\"Feed\", { label })} key={label}>\n <span class=\"badge text-bg-primary me-1\">{label}</span>\n </a>\n ))}\n </small>\n </div>\n ) : null}\n {excludedLabels.length > 0 ? (\n <div class=\"col\">\n <small class=\"text-muted\">\n Excluded labels:\n {excludedLabels.map((label) => (\n <a href={href(\"Feed\", { label })} key={label}>\n <span class=\"badge text-bg-primary me-1\">{label}</span>\n </a>\n ))}\n </small>\n </div>\n ) : null}\n </div>\n <div class=\"row\">\n {postsPerLabel.map((column) => (\n <div class=\"col-3\" key={column.label}>\n <div class=\"card\">\n <div class=\"card-body border-secondary\">\n <h6 class=\"card-title\">\n {column.title}({column.posts.length})\n </h6>\n {column.posts.map((postId) =>\n widget(\"components.posts.CompactPost\", { id: postId }, postId)\n )}\n </div>\n </div>\n </div>\n ))}\n </div>\n </div>\n);\n" }, "gigs-board.components.community.FeaturedCommunity": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\nconst Hover = styled.div`\n &:hover {\n box-shadow: 0px 1px 3px rgba(16, 24, 40, 0.1),\n 0px 1px 2px rgba(16, 24, 40, 0.06);\n }\n`;\n\nreturn (\n <Hover className=\"card\">\n <a\n href={href(\"community.Overview\", {\n label: props.label,\n })}\n class=\"text-decoration-none text-reset\"\n >\n <img src={props.cover} class=\"card-img-top\"></img>\n <div class=\"h5 pt-3 ps-3\">{props.title}</div>\n <div class=\"ps-3 pb-2 text-secondary\">{props.desc}</div>\n </a>\n </Hover>\n);\n" }, "gigs-board.components.posts.DiscussionFeed": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\n//////////////////////////////////////////////////////////////////////\n///STOPWORDS//////////////////////////////////////////////////////////\nconst stopWords = [\n \"about\",\n \"above\",\n \"after\",\n \"again\",\n \"against\",\n \"all\",\n \"and\",\n \"any\",\n \"are\",\n \"because\",\n \"been\",\n \"before\",\n \"being\",\n \"below\",\n \"between\",\n \"both\",\n \"but\",\n \"can\",\n \"cannot\",\n \"could\",\n \"did\",\n \"does\",\n \"doing\",\n \"down\",\n \"during\",\n \"each\",\n \"etc\",\n \"few\",\n \"for\",\n \"from\",\n \"further\",\n \"had\",\n \"has\",\n \"have\",\n \"having\",\n \"her\",\n \"hers\",\n \"herself\",\n \"him\",\n \"himself\",\n \"his\",\n \"how\",\n \"into\",\n \"its\",\n \"itself\",\n \"just\",\n \"more\",\n \"most\",\n \"myself\",\n \"nor\",\n \"not\",\n \"now\",\n \"off\",\n \"once\",\n \"only\",\n \"other\",\n \"our\",\n \"ours\",\n \"ourselves\",\n \"out\",\n \"over\",\n \"own\",\n \"same\",\n \"she\",\n \"should\",\n \"some\",\n \"still\",\n \"such\",\n \"than\",\n \"that\",\n \"the\",\n \"their\",\n \"theirs\",\n \"them\",\n \"themselves\",\n \"then\",\n \"there\",\n \"these\",\n \"they\",\n \"this\",\n \"those\",\n \"through\",\n \"too\",\n \"under\",\n \"until\",\n \"very\",\n \"was\",\n \"were\",\n \"what\",\n \"when\",\n \"where\",\n \"which\",\n \"while\",\n \"who\",\n \"whom\",\n \"why\",\n \"will\",\n \"with\",\n \"you\",\n \"your\",\n \"yours\",\n \"yourself\",\n \"yourselves\",\n \"www\",\n \"http\",\n \"com\",\n];\n\nconst stopWordsDictionary = {};\nfor (let i = 0; i < stopWords.length; i++) {\n stopWordsDictionary[stopWords[i]] = true;\n}\n\nfunction isStopWord(word) {\n return stopWordsDictionary.hasOwnProperty(word.toLowerCase());\n}\n//////////////////////////////////////////////////////////////////////\n///SYNONYMS///////////////////////////////////////////////////////////\nconst synonyms = {\n ether: \"ethereum\",\n eth: \"ethereum\",\n either: \"ethereum\",\n app: \"application\",\n cryptocyrrency: \"crypto\",\n developerdao: \"devdao\",\n dev: \"develop\",\n doc: \"document\",\n lib: \"librari\",\n saw: \"see\",\n seen: \"see\",\n tweet: \"twitter\",\n paid: \"pai\",\n src: \"sourc\",\n};\n\nconst applySynonym = (word) => {\n if (synonyms.hasOwnProperty(word.toLowerCase())) {\n return synonyms[word];\n }\n return word;\n};\n//////////////////////////////////////////////////////////////////////\n///STEMMING///////////////////////////////////////////////////////////\nconst step2list = {\n ational: \"ate\",\n tional: \"tion\",\n enci: \"ence\",\n anci: \"ance\",\n izer: \"ize\",\n bli: \"ble\",\n alli: \"al\",\n entli: \"ent\",\n eli: \"e\",\n ousli: \"ous\",\n ization: \"ize\",\n ation: \"ate\",\n ator: \"ate\",\n alism: \"al\",\n iveness: \"ive\",\n fulness: \"ful\",\n ousness: \"ous\",\n aliti: \"al\",\n iviti: \"ive\",\n biliti: \"ble\",\n logi: \"log\",\n};\n\n/** @type {Record<string, string>} */\nconst step3list = {\n icate: \"ic\",\n ative: \"\",\n alize: \"al\",\n iciti: \"ic\",\n ical: \"ic\",\n ful: \"\",\n ness: \"\",\n};\n\nconst gt0 = /^([^aeiou][^aeiouy]*)?([aeiouy][aeiou]*)([^aeiou][^aeiouy]*)/;\nconst eq1 =\n /^([^aeiou][^aeiouy]*)?([aeiouy][aeiou]*)([^aeiou][^aeiouy]*)([aeiouy][aeiou]*)?$/;\nconst gt1 =\n /^([^aeiou][^aeiouy]*)?(([aeiouy][aeiou]*)([^aeiou][^aeiouy]*)){2,}/;\nconst vowelInStem = /^([^aeiou][^aeiouy]*)?[aeiouy]/;\nconst consonantLike = /^([^aeiou][^aeiouy]*)[aeiouy][^aeiouwxy]$/;\n\n// Exception expressions.\nconst sfxLl = /ll$/;\nconst sfxE = /^(.+?)e$/;\nconst sfxY = /^(.+?)y$/;\nconst sfxIon = /^(.+?(s|t))(ion)$/;\nconst sfxEdOrIng = /^(.+?)(ed|ing)$/;\nconst sfxAtOrBlOrIz = /(at|bl|iz)$/;\nconst sfxEED = /^(.+?)eed$/;\nconst sfxS = /^.+?[^s]s$/;\nconst sfxSsesOrIes = /^.+?(ss|i)es$/;\nconst sfxMultiConsonantLike = /([^aeiouylsz])\\1$/;\nconst step2 =\n /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/;\nconst step3 = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/;\nconst step4 =\n /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/;\n\n/**\n * Get the stem from a given value.\n *\n * @param {string} value\n * Value to stem.\n * @returns {string}\n * Stem for `value`\n */\n// eslint-disable-next-line complexity\nfunction stemmer(value) {\n let result = value.toLowerCase();\n\n // Exit early.\n if (result.length < 3) {\n return result;\n }\n\n /** @type {boolean} */\n let firstCharacterWasLowerCaseY = false;\n\n // Detect initial `y`, make sure it never matches.\n if (\n result.codePointAt(0) === 121 // Lowercase Y\n ) {\n firstCharacterWasLowerCaseY = true;\n result = \"Y\" + result.slice(1);\n }\n\n // Step 1a.\n if (sfxSsesOrIes.test(result)) {\n // Remove last two characters.\n result = result.slice(0, -2);\n } else if (sfxS.test(result)) {\n // Remove last character.\n result = result.slice(0, -1);\n }\n\n /** @type {RegExpMatchArray|null} */\n let match;\n\n // Step 1b.\n if ((match = sfxEED.exec(result))) {\n if (gt0.test(match[1])) {\n // Remove last character.\n result = result.slice(0, -1);\n }\n } else if ((match = sfxEdOrIng.exec(result)) && vowelInStem.test(match[1])) {\n result = match[1];\n\n if (sfxAtOrBlOrIz.test(result)) {\n // Append `e`.\n result += \"e\";\n } else if (sfxMultiConsonantLike.test(result)) {\n // Remove last character.\n result = result.slice(0, -1);\n } else if (consonantLike.test(result)) {\n // Append `e`.\n result += \"e\";\n }\n }\n\n // Step 1c.\n if ((match = sfxY.exec(result)) && vowelInStem.test(match[1])) {\n // Remove suffixing `y` and append `i`.\n result = match[1] + \"i\";\n }\n\n // Step 2.\n if ((match = step2.exec(result)) && gt0.test(match[1])) {\n result = match[1] + step2list[match[2]];\n }\n\n // Step 3.\n if ((match = step3.exec(result)) && gt0.test(match[1])) {\n result = match[1] + step3list[match[2]];\n }\n\n // Step 4.\n if ((match = step4.exec(result))) {\n if (gt1.test(match[1])) {\n result = match[1];\n }\n } else if ((match = sfxIon.exec(result)) && gt1.test(match[1])) {\n result = match[1];\n }\n\n // Step 5.\n if (\n (match = sfxE.exec(result)) &&\n (gt1.test(match[1]) ||\n (eq1.test(match[1]) && !consonantLike.test(match[1])))\n ) {\n result = match[1];\n }\n\n if (sfxLl.test(result) && gt1.test(result)) {\n result = result.slice(0, -1);\n }\n\n // Turn initial `Y` back to `y`.\n if (firstCharacterWasLowerCaseY) {\n result = \"y\" + result.slice(1);\n }\n\n return result;\n}\n\n//////////////////////////////////////////////////////////////////////\n///SPELLCHECK/////////////////////////////////////////////////////////\nfunction levenshteinDistance(s, t, threshold) {\n const BIG_NUMBER = 10000;\n if (s == null || t == null) {\n return BIG_NUMBER;\n }\n if (threshold < 0) {\n return BIG_NUMBER;\n }\n let n = s.length;\n let m = t.length;\n if (Math.abs(n - m) >= threshold) {\n return BIG_NUMBER;\n }\n\n // if one string is empty, the edit distance is necessarily the length of the other\n if (n == 0) {\n return m <= threshold ? m : BIG_NUMBER;\n } else if (m == 0) {\n return n <= threshold ? n : BIG_NUMBER;\n }\n\n if (n > m) {\n // swap the two strings to consume less memory\n let temp = s;\n s = t;\n t = temp;\n let tempSize = n;\n n = m;\n m = tempSize;\n }\n\n let p = Array.from({ length: n + 1 }, () => 0); // 'previous' cost array, horizontally\n let d = Array.from({ length: n + 1 }, () => 0); // cost array, horizontally\n let _d; // placeholder to assist in swapping p and d\n\n // fill in starting table values\n const boundary = Math.min(n, threshold) + 1;\n for (let i = 0; i < boundary; i++) {\n p[i] = i;\n }\n // these fills ensure that the value above the rightmost entry of our\n // stripe will be ignored in following loop iterations\n for (let i = boundary; i < p.length; i++) {\n p[i] = BIG_NUMBER;\n }\n for (let i = 0; i < d.length; i++) {\n d[i] = BIG_NUMBER;\n }\n\n // iterates through t\n for (let j = 1; j <= m; j++) {\n const t_j = t.charAt(j - 1); // jth character of t\n d[0] = j;\n\n // compute stripe indices, constrain to array size\n const min = Math.max(1, j - threshold);\n const max = j > BIG_NUMBER - threshold ? n : Math.min(n, j + threshold);\n\n // the stripe may lead off of the table if s and t are of different sizes\n if (min > max) {\n return BIG_NUMBER;\n }\n\n // ignore entry left of leftmost\n if (min > 1) {\n d[min - 1] = BIG_NUMBER;\n }\n\n // iterates through [min, max] in s\n for (let i = min; i <= max; i++) {\n if (s.charAt(i - 1) == t_j) {\n // diagonally left and up\n d[i] = p[i - 1];\n } else {\n // 1 + minimum of cell to the left, to the top, diagonally left and up\n d[i] = 1 + Math.min(Math.min(d[i - 1], p[i]), p[i - 1]);\n }\n }\n\n // copy current distance counts to 'previous row' distance counts\n _d = p;\n p = d;\n d = _d;\n }\n // we don't need to check for threshold here because we did it inside the loop\n return p[n] <= threshold ? p[n] : BIG_NUMBER;\n}\n\nconst spellcheckQueryProcessing = (query, dictionary) => {\n // Split text document into words\n const words = stemAndFilterQuery(query);\n const dictionaryArray = Object.keys(dictionary);\n // Iterate over each word in the text\n for (let i = 0; i < words.length; i++) {\n let word = words[i].toLowerCase().replace(/[^a-z0-9]/g, \"\");\n\n // If the word is not in the dictionary, find the closest match\n if (!dictionary.hasOwnProperty(word)) {\n let closestMatch = undefined;\n let closestDistance = word.length;\n let allowedDistance = Math.min(word.length - 1, 3);\n // Iterate over each word in the dictionary\n if (word.length > 1) {\n for (let j = 0; j < dictionaryArray.length; j++) {\n let dictWord = dictionaryArray[j];\n let distance = levenshteinDistance(word, dictWord, allowedDistance);\n\n // If the distance is less than the closest distance, update the closest match\n if (distance <= allowedDistance && distance < closestDistance) {\n closestMatch = dictWord;\n closestDistance = distance;\n }\n }\n }\n // Replace the misspelled word with the closest match\n words[i] = closestMatch;\n }\n }\n return words.filter((word) => !!word);\n};\n\n//////////////////////////////////////////////////////////////////////\n///INDEXER&SEARCH/////////////////////////////////////////////////////\nconst fillDictionaryWith = (dict, text, id) => {\n let word = \"\";\n for (let i = 0; i < text.length; i++) {\n const char = text.charAt(i);\n const nextChar = text.charAt(i + 1);\n if (/\\w/.test(char) || (char === \".\" && /\\w/.test(nextChar))) {\n word += char.toLowerCase();\n } else if (word.length > 0) {\n const processedWord = applySynonym(stemmer(word));\n if (processedWord.length > 1 && !isStopWord(processedWord)) {\n const oldValue = dict[processedWord] || [];\n dict[processedWord] = [...oldValue, id];\n }\n word = \"\";\n }\n }\n const processedWord = applySynonym(stemmer(word));\n if (processedWord.length > 1 && !isStopWord(processedWord)) {\n const oldValue = dict[stemmer(processedWord)] || [];\n dict[stemmer(processedWord)] = [...oldValue, id];\n }\n return dict;\n};\n\nconst buildIndex = (posts) => {\n let index = {};\n\n posts.forEach((post) => {\n const title = post.snapshot.name;\n const labels = post.snapshot.labels.join(\" \");\n const text = post.snapshot.description;\n const postType = post.snapshot.post_type;\n const authorId = post.author_id;\n const postText = `${authorId} ${postType} ${title} ${labels} ${text}`;\n index = fillDictionaryWith(index, postText, post.id);\n });\n return index;\n};\n\nconst stemAndFilterQuery = (query) => {\n return Object.keys(fillDictionaryWith({}, query));\n};\n\nconst sortSearchResult = (searchResult) => {\n // create a map to count the frequency of each element\n const freq = new Map();\n for (const num of searchResult) {\n freq.set(num, (freq.get(num) || 0) + 1);\n }\n\n // define a custom comparison function to sort the array\n function compare(a, b) {\n // compare the frequency of the two elements\n const freqDiff = freq.get(b) - freq.get(a);\n if (freqDiff !== 0) {\n return freqDiff; // if they have different frequency, sort by frequency\n } else {\n return 0; // if they have the same frequency, leave as it is. Will be sorted by search term, by date\n }\n }\n\n // sort the array using the custom comparison function\n searchResult.sort(compare);\n return searchResult.filter(\n (elem, index) => searchResult.indexOf(elem) === index\n );\n};\n\nconst search = (processedQueryArray, index) => {\n return sortSearchResult(\n processedQueryArray.flatMap((queryWord) => {\n const termSearchRes = index[queryWord].reverse();\n const termSortedSearchRes = sortSearchResult(termSearchRes);\n return termSortedSearchRes;\n })\n );\n};\n\n//////////////////////////////////////////////////////////////////////\n///UI&UX//////////////////////////////////////////////////////////////\n//Run search and spelling computation every time the search bar modified\n//but no more frequent than 1 time per 1.5 seconds\nconst amountOfResultsToShowFirst = 5;\n\nconst buildPostsIndex = () => {\n return Near.asyncView(\"devgovgigs.near\", \"get_posts\").then((posts) => {\n const index = buildIndex(posts);\n const data = posts.reduce((acc, post) => {\n acc[post.id] = post;\n return acc;\n }, {});\n return { index, data };\n });\n};\n\nconst getProcessedPostsCached = () => {\n return useCache(() => buildPostsIndex(), \"processedPostsCached\");\n};\n\nif (!state.interval) {\n let termStorage = \"\";\n Storage.privateSet(\"term\", \"\");\n setInterval(() => {\n const currentInput = Storage.privateGet(\"term\");\n if (currentInput !== termStorage) {\n termStorage = currentInput;\n computeResults(termStorage);\n }\n }, 1500);\n State.update({\n interval: true,\n });\n}\n\nconst computeResults = (term) => {\n const start = new Date().getTime();\n const processedPostsCached = useCache(\n () =>\n buildPostsIndex().then((processedPosts) => {\n // Run query first time posts retrieved\n const query = term;\n const processedQuery = spellcheckQueryProcessing(\n query,\n processedPosts.index\n );\n const searchResult = search(processedQuery, processedPosts.index);\n console.log(processedQuery);\n console.log(searchResult);\n State.update({\n searchResult,\n shownSearchResults: searchResult.slice(0, amountOfResultsToShowFirst),\n processedQuery,\n loading: false,\n });\n return processedPosts;\n }),\n \"processedPostsCached\"\n );\n if (processedPostsCached) {\n // Run query every other time after data retrieved and cached\n const query = term;\n const processedQuery = spellcheckQueryProcessing(\n query,\n processedPostsCached.index\n );\n const searchResult = search(processedQuery, processedPostsCached.index);\n console.log(processedQuery);\n console.log(searchResult);\n State.update({\n searchResult,\n shownSearchResults: searchResult.slice(0, 10),\n processedQuery,\n loading: false,\n });\n }\n const end = new Date().getTime();\n console.log(\"search time: \", end - start);\n};\n\nconst updateInput = (term) => {\n Storage.privateSet(\"term\", term);\n State.update({\n term,\n loading: true,\n });\n};\n\nconst getSearchResultsKeywordsFor = (postId) => {\n const index = getProcessedPostsCached().index;\n return state.processedQuery.filter((queryWord) => {\n return index[queryWord].includes(postId);\n });\n};\n\nconst showMoreSearchResults = () => {\n const shownSearchResults = state.shownSearchResults || [];\n const newShownSearchResults = state.searchResult.slice(\n 0,\n shownSearchResults.length + amountOfResultsToShowFirst\n );\n State.update({ shownSearchResults: newShownSearchResults });\n};\n\n// Add a new state value\nif (!state.searchVisible) {\n State.update({\n searchVisible: false,\n });\n}\n\n// Conditionally render the input box\n{\n state.searchVisible && (\n <input\n type=\"search\"\n style={{\n \"padding-left\": \"40px\",\n }}\n className=\"form-control\"\n value={state.term ?? \"\"}\n onChange={(e) => updateInput(e.target.value)}\n placeholder={props.placeholder ?? `Search Posts`}\n />\n );\n}\n\nreturn (\n <div>\n {state.term && state.term.length > 1 && state.searchResult\n ? widget(\"components.posts.List\", {\n searchResult: {\n postIds: state.searchResult,\n keywords: Object.fromEntries(\n state.searchResult.map((postId) => {\n return [postId, getSearchResultsKeywordsFor(postId)];\n })\n ),\n },\n recency: props.recency,\n label: props.label,\n author: props.author,\n })\n : widget(\"components.posts.List\", {\n recency: props.recency,\n label: props.label,\n author: props.author,\n })}\n </div>\n);\n" }, "gigs-board.components.layout.Navbar": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\nreturn (\n <div class=\"card border-secondary mb-2\">\n <div class=\"nav navbar navbar-expand-lg bg-body-tertiary\">\n <div class=\"container-fluid\">\n <ul class=\"navbar-nav me-auto mb-2 mb-lg-0\">\n <li class=\"nav-item \">\n <a class=\"nav-link active\" href={href(\"Feed\")}>\n <i class=\"bi-house-fill\"> </i>\n Home\n </a>\n </li>\n <li class=\"nav-item\">\n <a class=\"nav-link active\" href={href(\"Feed\", { recency: \"all\" })}>\n <i class=\"bi-envelope-fill\"> </i>\n Recent\n </a>\n </li>\n <li class=\"nav-item\">\n <a\n class=\"nav-link active\"\n href={href(\"Feed\", { label: \"recurrent\" })}\n >\n <i class=\"bi-repeat\"> </i>\n Recurrent\n </a>\n </li>\n <li class=\"nav-item\">\n <a class=\"nav-link active\" href={href(\"Feed\", { recency: \"hot\" })}>\n <i class=\"bi-fire\"> </i>\n Hottest\n </a>\n </li>\n <li class=\"nav-item\">\n <a class=\"nav-link active\" href={href(\"Boards\")}>\n <i class=\"bi-kanban\"> </i>\n Boards\n </a>\n </li>\n <li class=\"nav-item\">\n <a\n class=\"nav-link active\"\n href={href(\"Teams\")}\n title=\"View teams and permissions\"\n >\n <i class=\"bi-people-fill\"> </i>\n Teams\n </a>\n </li>\n\n {props.children\n ? props.children.map((child) => (\n <li class=\"nav-item active ms-2\">{child}</li>\n ))\n : null}\n </ul>\n </div>\n </div>\n </div>\n);\n" }, "gigs-board.components.posts.List": { "": "// This component implementation was forked from [IndexFeed], but it does not fully implement lazy loading.\n// While this component uses InfiniteScroll, it still loads the whole list of Post IDs in one view call.\n// The contract will need to be extended with pagination support, yet, even in the current state the page loads much faster.\n// [IndexFeed]: https://near.social/#/mob.near/widget/WidgetSource?src=mob.near/widget/IndexFeed\n\n/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\ninitState({\n period: \"week\",\n});\n\nfunction defaultRenderItem(postId, additionalProps) {\n if (!additionalProps) {\n additionalProps = {};\n }\n // It is important to have a non-zero-height element as otherwise InfiniteScroll loads too many items on initial load\n return (\n <div style={{ minHeight: \"150px\" }}>\n {widget(\n `components.posts.Post`,\n {\n id: postId,\n expandable: true,\n defaultExpanded: false,\n isInList: true,\n ...additionalProps,\n },\n postId\n )}\n </div>\n );\n}\n\nconst renderItem = props.renderItem ?? defaultRenderItem;\n\nconst cachedRenderItem = (item, i) => {\n if (props.searchResult && props.searchResult.keywords[item]) {\n return renderItem(item, {\n searchKeywords: props.searchResult.keywords[item],\n });\n }\n\n const key = JSON.stringify(item);\n\n if (!(key in state.cachedItems)) {\n state.cachedItems[key] = renderItem(item);\n State.update();\n }\n return state.cachedItems[key];\n};\n\nconst initialRenderLimit = props.initialRenderLimit ?? 3;\nconst addDisplayCount = props.nextLimit ?? initialRenderLimit;\n\nfunction getPostsByLabel() {\n let postIds = Near.view(\n nearDevGovGigsContractAccountId,\n \"get_posts_by_label\",\n {\n label: props.label,\n }\n );\n if (postIds) {\n postIds.reverse();\n }\n return postIds;\n}\n\nfunction getPostsByAuthor() {\n let postIds = Near.view(\n nearDevGovGigsContractAccountId,\n \"get_posts_by_author\",\n {\n author: props.author,\n }\n );\n if (postIds) {\n postIds.reverse();\n }\n return postIds;\n}\n\nfunction intersectPostsWithLabel(postIds) {\n if (props.label) {\n let postIdLabels = getPostsByLabel();\n if (postIdLabels === null) {\n // wait until postIdLabels are loaded\n return null;\n }\n postIdLabels = new Set(postIdLabels);\n return postIds.filter((id) => postIdLabels.has(id));\n }\n return postIds;\n}\n\nfunction intersectPostsWithAuthor(postIds) {\n if (props.author) {\n let postIdsByAuthor = getPostsByAuthor();\n if (postIdsByAuthor == null) {\n // wait until postIdsByAuthor are loaded\n return null;\n } else {\n postIdsByAuthor = new Set(postIdsByAuthor);\n return postIds.filter((id) => postIdsByAuthor.has(id));\n }\n }\n return postIds;\n}\n\nconst ONE_DAY = 60 * 60 * 24 * 1000;\nconst ONE_WEEK = 60 * 60 * 24 * 1000 * 7;\nconst ONE_MONTH = 60 * 60 * 24 * 1000 * 30;\n\nfunction getHotnessScore(post) {\n //post.id - shows the age of the post, should grow exponentially, since newer posts are more important\n //post.likes.length - linear value\n const age = Math.pow(post.id, 5);\n const comments = post.comments;\n const commentAge = comments.reduce((sum, age) => sum + Math.pow(age, 5), 0);\n const totalAge = age + commentAge;\n //use log functions to make likes score and exponentially big age score close to each other\n return Math.log10(post.likes.length) + Math.log(Math.log10(totalAge));\n}\n\nconst getPeriodText = (period) => {\n let text = \"Last 24 hours\";\n if (period === \"week\") {\n text = \"Last week\";\n }\n if (period === \"month\") {\n text = \"Last month\";\n }\n return text;\n};\n\nconst findHottestsPosts = (postIds, period) => {\n let allPosts;\n if (!state.allPosts) {\n allPosts = Near.view(\"devgovgigs.near\", \"get_posts\");\n if (!allPosts) {\n return [];\n }\n State.update({ allPosts });\n } else {\n allPosts = state.allPosts;\n }\n let postIdsSet = new Set(postIds);\n let posts = allPosts.filter((post) => postIdsSet.has(post.id));\n\n let periodTime = ONE_DAY;\n if (period === \"week\") {\n periodTime = ONE_WEEK;\n }\n if (period === \"month\") {\n periodTime = ONE_MONTH;\n }\n const periodLimitedPosts = posts.filter((post) => {\n const timestamp = post.snapshot.timestamp / 1000000;\n return Date.now() - timestamp < periodTime;\n });\n const modifiedPosts = periodLimitedPosts.map((post) => {\n const comments =\n Near.view(\"devgovgigs.near\", \"get_children_ids\", {\n post_id: post.id,\n }) || [];\n post = { ...post, comments };\n return {\n ...post,\n postScore: getHotnessScore(post),\n };\n });\n modifiedPosts.sort((a, b) => b.postScore - a.postScore);\n return modifiedPosts.map((post) => post.id);\n};\n\nlet postIds;\nif (props.searchResult) {\n postIds = props.searchResult.postIds;\n postIds = intersectPostsWithLabel(postIds);\n postIds = intersectPostsWithAuthor(postIds);\n} else if (props.label) {\n postIds = getPostsByLabel();\n postIds = intersectPostsWithAuthor(postIds);\n} else if (props.author) {\n postIds = getPostsByAuthor();\n} else if (props.recency == \"all\") {\n postIds = Near.view(nearDevGovGigsContractAccountId, \"get_all_post_ids\");\n if (postIds) {\n postIds.reverse();\n }\n} else {\n postIds = Near.view(nearDevGovGigsContractAccountId, \"get_children_ids\");\n if (postIds) {\n postIds.reverse();\n }\n}\n\nif (props.recency == \"hot\") {\n postIds = findHottestsPosts(postIds, state.period);\n}\n\nconst loader = (\n <div className=\"loader\" key={\"loader\"}>\n <span\n className=\"spinner-grow spinner-grow-sm me-1\"\n role=\"status\"\n aria-hidden=\"true\"\n />\n Loading ...\n </div>\n);\n\nif (postIds === null) {\n return loader;\n}\nconst initialItems = postIds;\n//const initialItems = postIds.map(postId => ({ id: postId, ...Near.view(nearDevGovGigsContractAccountId, \"get_post\", { post_id: postId }) }));\n\n// const computeFetchFrom = (items, limit) => {\n// if (!items || items.length < limit) {\n// return false;\n// }\n// const blockHeight = items[items.length - 1].blockHeight;\n// return index.options.order === \"desc\" ? blockHeight - 1 : blockHeight + 1;\n// };\n\n// const mergeItems = (newItems) => {\n// const items = [\n// ...new Set([...newItems, ...state.items].map((i) => JSON.stringify(i))),\n// ].map((i) => JSON.parse(i));\n// items.sort((a, b) => a.blockHeight - b.blockHeight);\n// if (index.options.order === \"desc\") {\n// items.reverse();\n// }\n// return items;\n// };\n\nconst jInitialItems = JSON.stringify(initialItems);\nif (state.jInitialItems !== jInitialItems) {\n // const jIndex = JSON.stringify(index);\n // if (jIndex !== state.jIndex) {\n State.update({\n jIndex,\n jInitialItems,\n items: initialItems,\n fetchFrom: false,\n //nextFetchFrom: computeFetchFrom(initialItems, index.options.limit),\n nextFetchFrom: false,\n displayCount: initialRenderLimit,\n cachedItems: {},\n });\n // } else {\n // State.update({\n // jInitialItems,\n // items: mergeItems(initialItems),\n // });\n // }\n}\n\nif (state.fetchFrom) {\n console.log(\"TODO: fetchFrom\");\n // const limit = addDisplayCount;\n // const newItems = Social.index(\n // index.action,\n // index.key,\n // Object.assign({}, index.options, {\n // from: state.fetchFrom,\n // subscribe: undefined,\n // limit,\n // })\n // );\n // if (newItems !== null) {\n // State.update({\n // items: mergeItems(newItems),\n // fetchFrom: false,\n // nextFetchFrom: computeFetchFrom(newItems, limit),\n // });\n // }\n}\n\nconst makeMoreItems = () => {\n State.update({\n displayCount: state.displayCount + addDisplayCount,\n });\n if (\n state.items.length - state.displayCount < addDisplayCount * 2 &&\n !state.fetchFrom &&\n state.nextFetchFrom &&\n state.nextFetchFrom !== state.fetchFrom\n ) {\n State.update({\n fetchFrom: state.nextFetchFrom,\n });\n }\n};\n\nconst fetchMore =\n props.manual &&\n (state.fetchFrom && state.items.length < state.displayCount\n ? loader\n : state.displayCount < state.items.length && (\n <div key={\"loader more\"}>\n <a href=\"javascript:void\" onClick={(e) => makeMoreItems()}>\n {props.loadMoreText ?? \"Load more...\"}\n </a>\n </div>\n ));\n\nconst items = state.items ? state.items.slice(0, state.displayCount) : [];\n\nconsole.log(items);\nconst renderedItems = items.map(cachedRenderItem);\n\nconst Head =\n props.recency == \"hot\" ? (\n <div class=\"row\">\n <div class=\"fs-5 col-6 align-self-center\">\n <i class=\"bi-fire\"></i>\n <span>Hottest Posts</span>\n </div>\n <div class=\"col-6 dropdown d-flex justify-content-end\">\n <a\n class=\"btn btn-secondary dropdown-toggle\"\n href=\"#\"\n role=\"button\"\n id=\"dropdownMenuLink\"\n data-bs-toggle=\"dropdown\"\n aria-expanded=\"false\"\n >\n {getPeriodText(state.period)}\n </a>\n\n <ul class=\"dropdown-menu\" aria-labelledby=\"dropdownMenuLink\">\n <li>\n <button\n class=\"dropdown-item\"\n onClick={() => {\n State.update({ period: \"day\" });\n }}\n >\n {getPeriodText(\"day\")}\n </button>\n </li>\n <li>\n <button\n class=\"dropdown-item\"\n onClick={() => {\n State.update({ period: \"week\" });\n }}\n >\n {getPeriodText(\"week\")}\n </button>\n </li>\n <li>\n <button\n class=\"dropdown-item\"\n onClick={() => {\n State.update({ period: \"month\" });\n }}\n >\n {getPeriodText(\"month\")}\n </button>\n </li>\n </ul>\n </div>\n </div>\n ) : (\n <></>\n );\n\nreturn (\n <>\n {Head}\n {state.items.length > 0 ? (\n <InfiniteScroll\n pageStart={0}\n loadMore={makeMoreItems}\n hasMore={state.displayCount < state.items.length}\n loader={loader}\n >\n {renderedItems}\n </InfiniteScroll>\n ) : (\n <p class=\"text-secondary\">\n No posts {props.searchResult ? \"matches search\" : \"\"}\n {props.recency == \"hot\"\n ? \" in \" + getPeriodText(state.period).toLowerCase()\n : \"\"}\n </p>\n )}\n </>\n);\n" }, "gigs-board.components.posts.Search": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\n//////////////////////////////////////////////////////////////////////\n///STOPWORDS//////////////////////////////////////////////////////////\nconst stopWords = [\n \"about\",\n \"above\",\n \"after\",\n \"again\",\n \"against\",\n \"all\",\n \"and\",\n \"any\",\n \"are\",\n \"because\",\n \"been\",\n \"before\",\n \"being\",\n \"below\",\n \"between\",\n \"both\",\n \"but\",\n \"can\",\n \"cannot\",\n \"could\",\n \"did\",\n \"does\",\n \"doing\",\n \"down\",\n \"during\",\n \"each\",\n \"etc\",\n \"few\",\n \"for\",\n \"from\",\n \"further\",\n \"had\",\n \"has\",\n \"have\",\n \"having\",\n \"her\",\n \"hers\",\n \"herself\",\n \"him\",\n \"himself\",\n \"his\",\n \"how\",\n \"into\",\n \"its\",\n \"itself\",\n \"just\",\n \"more\",\n \"most\",\n \"myself\",\n \"nor\",\n \"not\",\n \"now\",\n \"off\",\n \"once\",\n \"only\",\n \"other\",\n \"our\",\n \"ours\",\n \"ourselves\",\n \"out\",\n \"over\",\n \"own\",\n \"same\",\n \"she\",\n \"should\",\n \"some\",\n \"still\",\n \"such\",\n \"than\",\n \"that\",\n \"the\",\n \"their\",\n \"theirs\",\n \"them\",\n \"themselves\",\n \"then\",\n \"there\",\n \"these\",\n \"they\",\n \"this\",\n \"those\",\n \"through\",\n \"too\",\n \"under\",\n \"until\",\n \"very\",\n \"was\",\n \"were\",\n \"what\",\n \"when\",\n \"where\",\n \"which\",\n \"while\",\n \"who\",\n \"whom\",\n \"why\",\n \"will\",\n \"with\",\n \"you\",\n \"your\",\n \"yours\",\n \"yourself\",\n \"yourselves\",\n \"www\",\n \"http\",\n \"com\",\n];\n\nconst stopWordsDictionary = {};\nfor (let i = 0; i < stopWords.length; i++) {\n stopWordsDictionary[stopWords[i]] = true;\n}\n\nfunction isStopWord(word) {\n return stopWordsDictionary.hasOwnProperty(word.toLowerCase());\n}\n//////////////////////////////////////////////////////////////////////\n///SYNONYMS///////////////////////////////////////////////////////////\nconst synonyms = {\n ether: \"ethereum\",\n eth: \"ethereum\",\n either: \"ethereum\",\n app: \"application\",\n cryptocyrrency: \"crypto\",\n developerdao: \"devdao\",\n dev: \"develop\",\n doc: \"document\",\n lib: \"librari\",\n saw: \"see\",\n seen: \"see\",\n tweet: \"twitter\",\n paid: \"pai\",\n src: \"sourc\",\n};\n\nconst applySynonym = (word) => {\n if (synonyms.hasOwnProperty(word.toLowerCase())) {\n return synonyms[word];\n }\n return word;\n};\n//////////////////////////////////////////////////////////////////////\n///STEMMING///////////////////////////////////////////////////////////\nconst step2list = {\n ational: \"ate\",\n tional: \"tion\",\n enci: \"ence\",\n anci: \"ance\",\n izer: \"ize\",\n bli: \"ble\",\n alli: \"al\",\n entli: \"ent\",\n eli: \"e\",\n ousli: \"ous\",\n ization: \"ize\",\n ation: \"ate\",\n ator: \"ate\",\n alism: \"al\",\n iveness: \"ive\",\n fulness: \"ful\",\n ousness: \"ous\",\n aliti: \"al\",\n iviti: \"ive\",\n biliti: \"ble\",\n logi: \"log\",\n};\n\n/** @type {Record<string, string>} */\nconst step3list = {\n icate: \"ic\",\n ative: \"\",\n alize: \"al\",\n iciti: \"ic\",\n ical: \"ic\",\n ful: \"\",\n ness: \"\",\n};\n\nconst gt0 = /^([^aeiou][^aeiouy]*)?([aeiouy][aeiou]*)([^aeiou][^aeiouy]*)/;\nconst eq1 =\n /^([^aeiou][^aeiouy]*)?([aeiouy][aeiou]*)([^aeiou][^aeiouy]*)([aeiouy][aeiou]*)?$/;\nconst gt1 =\n /^([^aeiou][^aeiouy]*)?(([aeiouy][aeiou]*)([^aeiou][^aeiouy]*)){2,}/;\nconst vowelInStem = /^([^aeiou][^aeiouy]*)?[aeiouy]/;\nconst consonantLike = /^([^aeiou][^aeiouy]*)[aeiouy][^aeiouwxy]$/;\n\n// Exception expressions.\nconst sfxLl = /ll$/;\nconst sfxE = /^(.+?)e$/;\nconst sfxY = /^(.+?)y$/;\nconst sfxIon = /^(.+?(s|t))(ion)$/;\nconst sfxEdOrIng = /^(.+?)(ed|ing)$/;\nconst sfxAtOrBlOrIz = /(at|bl|iz)$/;\nconst sfxEED = /^(.+?)eed$/;\nconst sfxS = /^.+?[^s]s$/;\nconst sfxSsesOrIes = /^.+?(ss|i)es$/;\nconst sfxMultiConsonantLike = /([^aeiouylsz])\\1$/;\nconst step2 =\n /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/;\nconst step3 = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/;\nconst step4 =\n /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/;\n\n/**\n * Get the stem from a given value.\n *\n * @param {string} value\n * Value to stem.\n * @returns {string}\n * Stem for `value`\n */\n// eslint-disable-next-line complexity\nfunction stemmer(value) {\n let result = value.toLowerCase();\n\n // Exit early.\n if (result.length < 3) {\n return result;\n }\n\n /** @type {boolean} */\n let firstCharacterWasLowerCaseY = false;\n\n // Detect initial `y`, make sure it never matches.\n if (\n result.codePointAt(0) === 121 // Lowercase Y\n ) {\n firstCharacterWasLowerCaseY = true;\n result = \"Y\" + result.slice(1);\n }\n\n // Step 1a.\n if (sfxSsesOrIes.test(result)) {\n // Remove last two characters.\n result = result.slice(0, -2);\n } else if (sfxS.test(result)) {\n // Remove last character.\n result = result.slice(0, -1);\n }\n\n /** @type {RegExpMatchArray|null} */\n let match;\n\n // Step 1b.\n if ((match = sfxEED.exec(result))) {\n if (gt0.test(match[1])) {\n // Remove last character.\n result = result.slice(0, -1);\n }\n } else if ((match = sfxEdOrIng.exec(result)) && vowelInStem.test(match[1])) {\n result = match[1];\n\n if (sfxAtOrBlOrIz.test(result)) {\n // Append `e`.\n result += \"e\";\n } else if (sfxMultiConsonantLike.test(result)) {\n // Remove last character.\n result = result.slice(0, -1);\n } else if (consonantLike.test(result)) {\n // Append `e`.\n result += \"e\";\n }\n }\n\n // Step 1c.\n if ((match = sfxY.exec(result)) && vowelInStem.test(match[1])) {\n // Remove suffixing `y` and append `i`.\n result = match[1] + \"i\";\n }\n\n // Step 2.\n if ((match = step2.exec(result)) && gt0.test(match[1])) {\n result = match[1] + step2list[match[2]];\n }\n\n // Step 3.\n if ((match = step3.exec(result)) && gt0.test(match[1])) {\n result = match[1] + step3list[match[2]];\n }\n\n // Step 4.\n if ((match = step4.exec(result))) {\n if (gt1.test(match[1])) {\n result = match[1];\n }\n } else if ((match = sfxIon.exec(result)) && gt1.test(match[1])) {\n result = match[1];\n }\n\n // Step 5.\n if (\n (match = sfxE.exec(result)) &&\n (gt1.test(match[1]) ||\n (eq1.test(match[1]) && !consonantLike.test(match[1])))\n ) {\n result = match[1];\n }\n\n if (sfxLl.test(result) && gt1.test(result)) {\n result = result.slice(0, -1);\n }\n\n // Turn initial `Y` back to `y`.\n if (firstCharacterWasLowerCaseY) {\n result = \"y\" + result.slice(1);\n }\n\n return result;\n}\n\n//////////////////////////////////////////////////////////////////////\n///SPELLCHECK/////////////////////////////////////////////////////////\nfunction levenshteinDistance(s, t, threshold) {\n const BIG_NUMBER = 10000;\n if (s == null || t == null) {\n return BIG_NUMBER;\n }\n if (threshold < 0) {\n return BIG_NUMBER;\n }\n let n = s.length;\n let m = t.length;\n if (Math.abs(n - m) >= threshold) {\n return BIG_NUMBER;\n }\n\n // if one string is empty, the edit distance is necessarily the length of the other\n if (n == 0) {\n return m <= threshold ? m : BIG_NUMBER;\n } else if (m == 0) {\n return n <= threshold ? n : BIG_NUMBER;\n }\n\n if (n > m) {\n // swap the two strings to consume less memory\n let temp = s;\n s = t;\n t = temp;\n let tempSize = n;\n n = m;\n m = tempSize;\n }\n\n let p = Array.from({ length: n + 1 }, () => 0); // 'previous' cost array, horizontally\n let d = Array.from({ length: n + 1 }, () => 0); // cost array, horizontally\n let _d; // placeholder to assist in swapping p and d\n\n // fill in starting table values\n const boundary = Math.min(n, threshold) + 1;\n for (let i = 0; i < boundary; i++) {\n p[i] = i;\n }\n // these fills ensure that the value above the rightmost entry of our\n // stripe will be ignored in following loop iterations\n for (let i = boundary; i < p.length; i++) {\n p[i] = BIG_NUMBER;\n }\n for (let i = 0; i < d.length; i++) {\n d[i] = BIG_NUMBER;\n }\n\n // iterates through t\n for (let j = 1; j <= m; j++) {\n const t_j = t.charAt(j - 1); // jth character of t\n d[0] = j;\n\n // compute stripe indices, constrain to array size\n const min = Math.max(1, j - threshold);\n const max = j > BIG_NUMBER - threshold ? n : Math.min(n, j + threshold);\n\n // the stripe may lead off of the table if s and t are of different sizes\n if (min > max) {\n return BIG_NUMBER;\n }\n\n // ignore entry left of leftmost\n if (min > 1) {\n d[min - 1] = BIG_NUMBER;\n }\n\n // iterates through [min, max] in s\n for (let i = min; i <= max; i++) {\n if (s.charAt(i - 1) == t_j) {\n // diagonally left and up\n d[i] = p[i - 1];\n } else {\n // 1 + minimum of cell to the left, to the top, diagonally left and up\n d[i] = 1 + Math.min(Math.min(d[i - 1], p[i]), p[i - 1]);\n }\n }\n\n // copy current distance counts to 'previous row' distance counts\n _d = p;\n p = d;\n d = _d;\n }\n // we don't need to check for threshold here because we did it inside the loop\n return p[n] <= threshold ? p[n] : BIG_NUMBER;\n}\n\nconst spellcheckQueryProcessing = (query, dictionary) => {\n // Split text document into words\n const words = stemAndFilterQuery(query);\n const dictionaryArray = Object.keys(dictionary);\n // Iterate over each word in the text\n for (let i = 0; i < words.length; i++) {\n let word = words[i].toLowerCase().replace(/[^a-z0-9]/g, \"\");\n\n // If the word is not in the dictionary, find the closest match\n if (!dictionary.hasOwnProperty(word)) {\n let closestMatch = undefined;\n let closestDistance = word.length;\n let allowedDistance = Math.min(word.length - 1, 3);\n // Iterate over each word in the dictionary\n if (word.length > 1) {\n for (let j = 0; j < dictionaryArray.length; j++) {\n let dictWord = dictionaryArray[j];\n let distance = levenshteinDistance(word, dictWord, allowedDistance);\n\n // If the distance is less than the closest distance, update the closest match\n if (distance <= allowedDistance && distance < closestDistance) {\n closestMatch = dictWord;\n closestDistance = distance;\n }\n }\n }\n // Replace the misspelled word with the closest match\n words[i] = closestMatch;\n }\n }\n return words.filter((word) => !!word);\n};\n\n//////////////////////////////////////////////////////////////////////\n///INDEXER&SEARCH/////////////////////////////////////////////////////\nconst fillDictionaryWith = (dict, text, id) => {\n let word = \"\";\n for (let i = 0; i < text.length; i++) {\n const char = text.charAt(i);\n const nextChar = text.charAt(i + 1);\n if (/\\w/.test(char) || (char === \".\" && /\\w/.test(nextChar))) {\n word += char.toLowerCase();\n } else if (word.length > 0) {\n const processedWord = applySynonym(stemmer(word));\n if (processedWord.length > 1 && !isStopWord(processedWord)) {\n const oldValue = dict[processedWord] || [];\n dict[processedWord] = [...oldValue, id];\n }\n word = \"\";\n }\n }\n const processedWord = applySynonym(stemmer(word));\n if (processedWord.length > 1 && !isStopWord(processedWord)) {\n const oldValue = dict[stemmer(processedWord)] || [];\n dict[stemmer(processedWord)] = [...oldValue, id];\n }\n return dict;\n};\n\nconst buildIndex = (posts) => {\n let index = {};\n\n posts.forEach((post) => {\n const title = post.snapshot.name;\n const labels = post.snapshot.labels.join(\" \");\n const text = post.snapshot.description;\n const postType = post.snapshot.post_type;\n const authorId = post.author_id;\n const postText = `${authorId} ${postType} ${title} ${labels} ${text}`;\n index = fillDictionaryWith(index, postText, post.id);\n });\n return index;\n};\n\nconst stemAndFilterQuery = (query) => {\n return Object.keys(fillDictionaryWith({}, query));\n};\n\nconst sortSearchResult = (searchResult) => {\n // create a map to count the frequency of each element\n const freq = new Map();\n for (const num of searchResult) {\n freq.set(num, (freq.get(num) || 0) + 1);\n }\n\n // define a custom comparison function to sort the array\n function compare(a, b) {\n // compare the frequency of the two elements\n const freqDiff = freq.get(b) - freq.get(a);\n if (freqDiff !== 0) {\n return freqDiff; // if they have different frequency, sort by frequency\n } else {\n return 0; // if they have the same frequency, leave as it is. Will be sorted by search term, by date\n }\n }\n\n // sort the array using the custom comparison function\n searchResult.sort(compare);\n return searchResult.filter(\n (elem, index) => searchResult.indexOf(elem) === index\n );\n};\n\nconst search = (processedQueryArray, index) => {\n return sortSearchResult(\n processedQueryArray.flatMap((queryWord) => {\n const termSearchRes = index[queryWord].reverse();\n const termSortedSearchRes = sortSearchResult(termSearchRes);\n return termSortedSearchRes;\n })\n );\n};\n\n//////////////////////////////////////////////////////////////////////\n///UI&UX//////////////////////////////////////////////////////////////\n//Run search and spelling computation every time the search bar modified\n//but no more frequent than 1 time per 1.5 seconds\nconst amountOfResultsToShowFirst = 5;\n\nconst buildPostsIndex = () => {\n return Near.asyncView(\"devgovgigs.near\", \"get_posts\").then((posts) => {\n const index = buildIndex(posts);\n const data = posts.reduce((acc, post) => {\n acc[post.id] = post;\n return acc;\n }, {});\n return { index, data };\n });\n};\n\nconst getProcessedPostsCached = () => {\n return useCache(() => buildPostsIndex(), \"processedPostsCached\");\n};\n\nif (!state.interval) {\n let termStorage = \"\";\n Storage.privateSet(\"term\", \"\");\n setInterval(() => {\n const currentInput = Storage.privateGet(\"term\");\n if (currentInput !== termStorage) {\n termStorage = currentInput;\n computeResults(termStorage);\n }\n }, 1500);\n State.update({\n interval: true,\n });\n}\n\nconst computeResults = (term) => {\n const start = new Date().getTime();\n const processedPostsCached = useCache(\n () =>\n buildPostsIndex().then((processedPosts) => {\n // Run query first time posts retrieved\n const query = term;\n const processedQuery = spellcheckQueryProcessing(\n query,\n processedPosts.index\n );\n const searchResult = search(processedQuery, processedPosts.index);\n console.log(processedQuery);\n console.log(searchResult);\n State.update({\n searchResult,\n shownSearchResults: searchResult.slice(0, amountOfResultsToShowFirst),\n processedQuery,\n loading: false,\n });\n return processedPosts;\n }),\n \"processedPostsCached\"\n );\n if (processedPostsCached) {\n // Run query every other time after data retrieved and cached\n const query = term;\n const processedQuery = spellcheckQueryProcessing(\n query,\n processedPostsCached.index\n );\n const searchResult = search(processedQuery, processedPostsCached.index);\n console.log(processedQuery);\n console.log(searchResult);\n State.update({\n searchResult,\n shownSearchResults: searchResult.slice(0, 10),\n processedQuery,\n loading: false,\n });\n }\n const end = new Date().getTime();\n console.log(\"search time: \", end - start);\n};\n\nconst updateInput = (term) => {\n Storage.privateSet(\"term\", term);\n State.update({\n term,\n loading: true,\n });\n};\n\nconst getSearchResultsKeywordsFor = (postId) => {\n const index = getProcessedPostsCached().index;\n return state.processedQuery.filter((queryWord) => {\n return index[queryWord].includes(postId);\n });\n};\n\nconst showMoreSearchResults = () => {\n const shownSearchResults = state.shownSearchResults || [];\n const newShownSearchResults = state.searchResult.slice(\n 0,\n shownSearchResults.length + amountOfResultsToShowFirst\n );\n State.update({ shownSearchResults: newShownSearchResults });\n};\n\nreturn (\n <>\n <div className=\"d-flex flex-row gap-4\">\n <div className=\"d-flex flex-row position-relative w-25\">\n <div className=\"position-absolute d-flex ps-3 flex-column h-100 justify-center\">\n {state.loading ? (\n <span\n className=\"spinner-grow spinner-grow-sm m-auto\"\n role=\"status\"\n aria-hidden=\"true\"\n />\n ) : (\n <i class=\"bi bi-search m-auto\"></i>\n )}\n </div>\n <input\n type=\"search\"\n className=\"ps-5 form-control border border-0 bg-light\"\n value={state.term ?? \"\"}\n onChange={(e) => updateInput(e.target.value)}\n placeholder={props.placeholder ?? `Search Posts`}\n />\n </div>\n <div class=\"dropdown\">\n <button\n class=\"btn btn-light dropdown-toggle\"\n type=\"button\"\n data-bs-toggle=\"dropdown\"\n aria-expanded=\"false\"\n >\n Sort\n </button>\n <ul class=\"dropdown-menu px-2 shadow\">\n <li>\n <a\n style={{ borderRadius: \"5px\" }}\n class=\"dropdown-item link-underline link-underline-opacity-0\"\n href={href(\"Feed\")}\n >\n Latest\n </a>\n </li>\n <li>\n <a\n style={{ borderRadius: \"5px\" }}\n class=\"dropdown-item link-underline link-underline-opacity-0\"\n href={href(\"Feed\", { recency: \"hot\" })}\n >\n Hottest\n </a>\n </li>\n <li>\n <a\n style={{ borderRadius: \"5px\" }}\n class=\"dropdown-item link-underline link-underline-opacity-0\"\n href={href(\"Feed\", { recency: \"all\" })}\n >\n All replies\n </a>\n </li>\n </ul>\n </div>\n <div class=\"dropdown\">\n {widget(\"components.layout.SearchByAuthor\", {\n authorQuery: props.authorQuery,\n onSearchAuthor: props.onSearchAuthor,\n })}\n </div>\n <div>\n {widget(\"components.layout.SearchByLabel\", {\n labelQuery: props.labelQuery,\n onSearchLabel: props.onSearchLabel,\n })}\n </div>\n <div className=\"d-flex flex-row-reverse flex-grow-1\">\n {props.children}\n </div>\n </div>\n {state.processedQuery &&\n state.processedQuery.length > 0 &&\n state.term.toLowerCase().trim() !== state.processedQuery.join(\" \") && (\n <div class=\"mb-2\" style={{ \"font-family\": \"monospace\" }}>\n Looking for\n <strong>{state.processedQuery.join(\" \")}</strong>:\n </div>\n )}\n {state.term && state.term.length > 1 && state.searchResult\n ? widget(\"components.posts.List\", {\n searchResult: {\n postIds: state.searchResult,\n keywords: Object.fromEntries(\n state.searchResult.map((postId) => {\n return [postId, getSearchResultsKeywordsFor(postId)];\n })\n ),\n },\n recency: props.recency,\n label: props.label,\n author: props.author,\n })\n : widget(\"components.posts.List\", {\n recency: props.recency,\n label: props.label,\n author: props.author,\n })}\n </>\n);\n" }, "gigs-board.pages.community.Events": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\n/* INCLUDE: \"shared/mocks\" */\nconst communities = {\n \"zero-knowledge\": {\n overviewId: 397,\n eventsId: 401,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreiajwq6ep3n7veddozji2djv5vviyisabhycbweslvpwhsoyuzcwi4\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreihgxg5kwts2juldaeasveyuddkm6tcabmrat2aaq5u6uyljtyt7lu\",\n\n title: \"Zero Knowledge\",\n desc: \"Building a zero knowledge ecosystem on NEAR.\",\n telegram: \"NearZeroKnowledge\",\n },\n\n protocol: {\n overviewId: 412,\n eventsId: 413,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreidpitdafcnhkp4uyomacypdgqvxr35jtfnbxa5s6crby7qjk2nv5a\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreicg4svzfz5nvllomsahndgm7u62za4sib4mmbygxzhpcl4htqwr4a\",\n\n title: \"Protocol\",\n desc: \"Supporting the ongoing innovation of the NEAR Protocol.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-protocol\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Protocol NEPs\",\n },\n },\n },\n },\n\n telegram: \"NEAR_Protocol_Community_Group\",\n },\n\n tooling: {\n overviewId: 416,\n eventsId: 417,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreie2eaj5czmpfe6pe53kojzcspgozebdsonffwvbxtpuipnwahybvi\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreiehzr7z2fhoqqmkt3z667wubccbch6sqtsnvd6msodyzpnf72cszy\",\n\n title: \"Tooling\",\n desc: \"Supporting the ongoing innovation of tooling.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-tools\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Tooling NEPs\",\n },\n },\n },\n },\n\n telegram: \"NEAR_Tools_Community_Group\",\n },\n\n \"contract-standards\": {\n overviewId: 414,\n eventsId: 415,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreiepgdnu7soc6xgbyd4adicbf3eyxiiwqawn6tguaix6aklfpir634\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreiaowjqxds24fwcliyriintjd4ucciprii2rdxjmxgi7f5dmzuscey\",\n\n title: \"Contract Standards\",\n desc: \"Coordinating the contribution to the NEAR dapp standards.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Contract Standards NEPs\",\n },\n },\n },\n },\n\n telegram: \"nearnft\",\n },\n};\n/* END_INCLUDE: \"shared/mocks\" */\n\nif (!props.label) {\n return (\n <div class=\"alert alert-danger\" role=\"alert\">\n Error: label is required\n </div>\n );\n}\n\nconst community = communities[props.label];\n\nconst eventsPost = Near.view(nearDevGovGigsContractAccountId, \"get_post\", {\n post_id: community.eventsId,\n});\nif (!eventsPost) {\n return <div>Loading ...</div>;\n}\n\nconst onMention = (accountId) => (\n <span key={accountId} className=\"d-inline-flex\" style={{ fontWeight: 500 }}>\n <Widget\n src=\"neardevgov.near/widget/ProfileLine\"\n props={{\n accountId: accountId.toLowerCase(),\n hideAccountId: true,\n tooltip: true,\n }}\n />\n </span>\n);\n\nconst Events = (\n <div>\n <Markdown\n class=\"card-text\"\n text={eventsPost.snapshot.description}\n onMention={onMention}\n ></Markdown>\n </div>\n);\n\nreturn widget(\"components.community.Layout\", {\n label: props.label,\n tab: \"Events\",\n children: Events,\n});\n" }, "gigs-board.pages.Create": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\nconst parentId = props.parentId ?? null;\nconst postId = props.postId ?? null;\nconst mode = props.mode ?? \"Create\";\n\nconst referralLabels = props.referral ? [`referral:${props.referral}`] : [];\nconst labelStrings = (props.labels ? props.labels.split(\",\") : []).concat(\n referralLabels\n);\nconst labels = labelStrings.map((s) => {\n return { name: s };\n});\n\ninitState({\n seekingFunding: false,\n //\n author_id: context.accountId,\n // Should be a list of objects with field \"name\".\n labels,\n // Should be a list of labels as strings.\n // Both of the label structures should be modified together.\n labelStrings,\n postType: \"Idea\",\n name: props.name ?? \"\",\n description: props.description ?? \"\",\n amount: props.amount ?? \"\",\n token: props.token ?? \"NEAR\",\n supervisor: props.supervisor ?? \"neardevgov.near\",\n githubLink: props.githubLink ?? \"\",\n warning: \"\",\n});\n\n// This must be outside onClick, because Near.view returns null at first, and when the view call finished, it returns true/false.\n// If checking this inside onClick, it will give `null` and we cannot tell the result is true or false.\nlet grantNotify = Near.view(\"social.near\", \"is_write_permission_granted\", {\n predecessor_id: nearDevGovGigsContractAccountId,\n key: context.accountId + \"/index/notify\",\n});\nif (grantNotify === null) {\n return;\n}\n\nconst onSubmit = () => {\n let labels = state.labelStrings;\n\n let body = {\n name: state.name,\n description: generateDescription(\n state.description,\n state.amount,\n state.token,\n state.supervisor\n ),\n };\n\n if (state.postType === \"Solution\") {\n body = {\n ...body,\n post_type: \"Submission\",\n submission_version: \"V1\",\n };\n } else {\n // Idea\n body = {\n ...body,\n post_type: \"Idea\",\n idea_version: \"V1\",\n };\n }\n\n if (!context.accountId) return;\n\n let txn = [];\n if (mode == \"Create\") {\n txn.push({\n contractName: nearDevGovGigsContractAccountId,\n methodName: \"add_post\",\n args: {\n parent_id: parentId,\n labels,\n body: body,\n },\n deposit: Big(10).pow(21).mul(3),\n gas: Big(10).pow(12).mul(100),\n });\n } else if (mode == \"Edit\") {\n txn.push({\n contractName: nearDevGovGigsContractAccountId,\n methodName: \"edit_post\",\n args: {\n id: postId,\n labels,\n body: body,\n },\n deposit: Big(10).pow(21).mul(2),\n gas: Big(10).pow(12).mul(100),\n });\n }\n if (mode == \"Create\" || mode == \"Edit\") {\n if (grantNotify === false) {\n txn.unshift({\n contractName: \"social.near\",\n methodName: \"grant_write_permission\",\n args: {\n predecessor_id: nearDevGovGigsContractAccountId,\n keys: [context.accountId + \"/index/notify\"],\n },\n deposit: Big(10).pow(23),\n gas: Big(10).pow(12).mul(30),\n });\n }\n Near.call(txn);\n }\n};\n\nconst onIdeaClick = () => {\n State.update({ postType: \"Idea\", seekingFunding: false });\n};\n\nconst onSolutionClick = () => {\n State.update({ postType: \"Solution\" });\n};\n\nconst normalizeLabel = (label) =>\n label\n .replaceAll(/[- \\.]/g, \"_\")\n .replaceAll(/[^\\w]+/g, \"\")\n .replaceAll(/_+/g, \"-\")\n .replace(/^-+/, \"\")\n .replace(/-+$/, \"\")\n .toLowerCase()\n .trim(\"-\");\n\nconst checkLabel = (label) => {\n Near.asyncView(nearDevGovGigsContractAccountId, \"is_allowed_to_use_labels\", {\n editor: context.accountId,\n labels: [label],\n }).then((allowed) => {\n if (allowed) {\n State.update({ warning: \"\" });\n } else {\n State.update({\n warning:\n 'The label \"' +\n label +\n '\" is protected and can only be added by moderators',\n });\n return;\n }\n });\n};\n\nconst setLabels = (labels) => {\n labels = labels.map((o) => {\n o.name = normalizeLabel(o.name);\n return o;\n });\n if (labels.length < state.labels.length) {\n let oldLabels = new Set(state.labels.map((label) => label.name));\n for (let label of labels) {\n oldLabels.delete(label.name);\n }\n let removed = oldLabels.values().next().value;\n Near.asyncView(\n nearDevGovGigsContractAccountId,\n \"is_allowed_to_use_labels\",\n { editor: context.accountId, labels: [removed] }\n ).then((allowed) => {\n if (allowed) {\n let labelStrings = labels.map(({ name }) => name);\n State.update({ labels, labelStrings });\n } else {\n State.update({\n warning:\n 'The label \"' +\n removed +\n '\" is protected and can only be updated by moderators',\n });\n return;\n }\n });\n } else {\n let labelStrings = labels.map((o) => {\n return o.name;\n });\n State.update({ labels, labelStrings });\n }\n};\nconst existingLabelStrings =\n Near.view(nearDevGovGigsContractAccountId, \"get_all_allowed_labels\", {\n editor: context.accountId,\n }) ?? [];\nconst existingLabelSet = new Set(existingLabelStrings);\nconst existingLabels = existingLabelStrings.map((s) => {\n return { name: s };\n});\n\nconst labelEditor = (\n <div className=\"col-lg-12 mb-2\">\n <p className=\"fs-6 fw-bold mb-1\">Labels</p>\n <Typeahead\n multiple\n labelKey=\"name\"\n onInputChange={checkLabel}\n onChange={setLabels}\n options={existingLabels}\n placeholder=\"near.social, widget, NEP, standard, protocol, tool\"\n selected={state.labels}\n positionFixed\n allowNew={(results, props) => {\n return (\n !existingLabelSet.has(props.text) &&\n props.selected.filter((selected) => selected.name === props.text)\n .length == 0 &&\n Near.view(\n nearDevGovGigsContractAccountId,\n \"is_allowed_to_use_labels\",\n { editor: context.accountId, labels: [props.text] }\n )\n );\n }}\n />\n </div>\n);\n\nconst nameDiv = (\n <div className=\"col-lg-6 mb-2\">\n <p className=\"fs-6 fw-bold mb-1\">Title</p>\n <input\n type=\"text\"\n value={state.name}\n onChange={(event) => State.update({ name: event.target.value })}\n />\n </div>\n);\n\nconst descriptionDiv = (\n <div className=\"col-lg-12 mb-2\">\n <p className=\"fs-6 fw-bold mb-1\">Description</p>\n <textarea\n value={state.description}\n type=\"text\"\n rows={6}\n className=\"form-control\"\n onChange={(event) => State.update({ description: event.target.value })}\n />\n </div>\n);\n\nconst isFundraisingDiv = (\n // This is jank with just btns and not radios. But the radios were glitchy af\n <>\n <div class=\"mb-2\">\n <p class=\"fs-6 fw-bold mb-1\">\n Are you seeking funding for your solution?\n <span class=\"text-muted fw-normal\">(Optional)</span>\n </p>\n <div class=\"form-check form-check-inline\">\n <label class=\"form-check-label\">\n <button\n className=\"btn btn-light p-0\"\n style={{\n backgroundColor: state.seekingFunding ? \"#0C7283\" : \"inherit\",\n color: \"#f3f3f3\",\n border: \"solid #D9D9D9\",\n borderRadius: \"100%\",\n height: \"20px\",\n width: \"20px\",\n }}\n onClick={() => State.update({ seekingFunding: true })}\n />\n Yes\n </label>\n </div>\n <div class=\"form-check form-check-inline\">\n <label class=\"form-check-label\">\n <button\n className=\"btn btn-light p-0\"\n style={{\n backgroundColor: !state.seekingFunding ? \"#0C7283\" : \"inherit\",\n color: \"#f3f3f3\",\n border: \"solid #D9D9D9\",\n borderRadius: \"100%\",\n height: \"20px\",\n width: \"20px\",\n }}\n onClick={() => State.update({ seekingFunding: false })}\n />\n No\n </label>\n </div>\n </div>\n </>\n);\n\nconst fundraisingDiv = (\n <div class=\"d-flex flex-column mb-2\">\n <div className=\"col-lg-6 mb-2\">\n Currency\n <select\n onChange={(event) => State.update({ token: event.target.value })}\n class=\"form-select\"\n aria-label=\"Default select example\"\n >\n <option selected value=\"NEAR\">\n NEAR\n </option>\n <option value=\"USDC\">USDC</option>\n <option value=\"USD\">USD</option>\n </select>\n </div>\n <div className=\"col-lg-6 mb-2\">\n Requested amount <span class=\"text-muted fw-normal\">(Numbers Only)</span>\n <input\n type=\"number\"\n value={parseInt(state.amount) > 0 ? state.amount : \"\"}\n min={0}\n onChange={(event) =>\n State.update({\n amount: Number(\n event.target.value.toString().replace(/e/g, \"\")\n ).toString(),\n })\n }\n />\n </div>\n <div className=\"col-lg-6 mb-2\">\n <p class=\"mb-1\">\n Requested sponsor <span class=\"text-muted fw-normal\">(Optional)</span>\n </p>\n <p style={{ fontSize: \"13px\" }} class=\"m-0 text-muted fw-light\">\n If you are requesting funding from a specific sponsor, please enter\n their username.\n </p>\n <div class=\"input-group flex-nowrap\">\n <span class=\"input-group-text\" id=\"addon-wrapping\">\n @\n </span>\n <input\n type=\"text\"\n class=\"form-control\"\n placeholder=\"Enter username\"\n value={state.supervisor}\n onChange={(event) => State.update({ supervisor: event.target.value })}\n />\n </div>\n </div>\n </div>\n);\n\nfunction generateDescription(text, amount, token, supervisor) {\n const funding = `###### Requested amount: ${amount} ${token}\\n###### Requested sponsor: @${supervisor}\\n`;\n if (amount > 0 && token && supervisor) return funding + text;\n return text;\n}\n\nreturn (\n <div class=\"bg-light d-flex flex-column flex-grow-1\">\n {widget(\"components.layout.Banner\")}\n <div class=\"mx-5 mb-5\">\n <div aria-label=\"breadcrumb\">\n <ol class=\"breadcrumb\">\n <li class=\"breadcrumb-item\">\n <a\n style={{\n color: \"#3252A6\",\n }}\n className=\"fw-bold\"\n href={href(\"Feed\")}\n >\n DevHub\n </a>\n </li>\n <li class=\"breadcrumb-item active\" aria-current=\"page\">\n Create new\n </li>\n </ol>\n </div>\n <h4>Create a new post</h4>\n <p>{state.seekingFunding}</p>\n <div class=\"card border-light\">\n <div class=\"card-body\">\n <p class=\"card-title fw-bold fs-6\">What do you want to create?</p>\n <div class=\"d-flex flex-row gap-2\">\n <button\n onClick={onIdeaClick}\n type=\"button\"\n class={`btn btn-outline-secondary`}\n style={\n state.postType === \"Idea\"\n ? {\n backgroundColor: \"#0C7283\",\n color: \"#f3f3f3\",\n }\n : {}\n }\n >\n <i class=\"bi bi-lightbulb\"></i>\n Idea\n </button>\n <button\n onClick={onSolutionClick}\n type=\"button\"\n class={`btn btn-outline-secondary`}\n style={\n state.postType !== \"Idea\"\n ? {\n backgroundColor: \"#0C7283\",\n color: \"#f3f3f3\",\n }\n : {}\n }\n >\n <i class=\"bi bi-rocket\"></i>\n Solution\n </button>\n </div>\n <p class=\"text-muted w-75 my-1\">\n {state.postType === \"Idea\"\n ? \"Get feedback from the community about a problem, opportunity, or need.\"\n : \"Provide a specific proposal or implementation to an idea, optionally requesting funding. If your solution relates to an existing idea, please reply to the original post with a solution.\"}\n </p>\n {state.warning && (\n <div\n class=\"alert alert-warning alert-dismissible fade show\"\n role=\"alert\"\n >\n {state.warning}\n <button\n type=\"button\"\n class=\"btn-close\"\n data-bs-dismiss=\"alert\"\n aria-label=\"Close\"\n onClick={() => State.update({ warning: \"\" })}\n ></button>\n </div>\n )}\n <div className=\"row\">\n {nameDiv}\n {descriptionDiv}\n {labelEditor}\n {state.postType === \"Solution\" && isFundraisingDiv}\n {state.seekingFunding && fundraisingDiv}\n </div>\n <button\n style={{\n width: \"7rem\",\n backgroundColor: \"#0C7283\",\n color: \"#f3f3f3\",\n }}\n className=\"btn btn-light mb-2 p-3\"\n onClick={onSubmit}\n >\n Submit\n </button>\n </div>\n <div class=\"bg-light d-flex flex-row p-1 border-bottom\"></div>\n <div class=\"card-body\">\n <p class=\"text-muted m-0\">Preview</p>\n <div>\n {widget(\"components.posts.Post\", {\n isPreview: true,\n id: 0, // irrelevant\n post: {\n author_id: state.author_id,\n likes: [],\n snapshot: {\n editor_id: state.editor_id,\n labels: state.labelStrings,\n post_type: state.postType,\n name: state.name,\n description: generateDescription(\n state.description,\n state.amount,\n state.token,\n state.supervisor\n ),\n github_link: state.githubLink,\n },\n },\n })}\n </div>\n </div>\n </div>\n </div>\n </div>\n);\n" }, "gigs-board.components.teams.TeamInfo": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n/* INCLUDE: \"shared/lib/gui\" */\nconst Card = styled.div`\n &:hover {\n box-shadow: rgba(3, 102, 214, 0.3) 0px 0px 0px 3px;\n }\n`;\n\nconst CompactContainer = styled.div`\n width: fit-content !important;\n max-width: 100%;\n`;\n/* END_INCLUDE: \"shared/lib/gui\" */\n\nconst metadata = props.members_list[props.member];\nconst isTeam = props.member.startsWith(\"team:\");\nconst memberBadge = isTeam ? \"bi-people-fill\" : \"person-fill\";\nconst header = isTeam ? (\n <div class=\"d-flex\">\n <i class=\"bi bi-people-fill me-1\"></i>\n {props.member}\n </div>\n) : (\n <Widget\n src={`neardevgov.near/widget/ProfileLine`}\n props={{ accountId: props.member }}\n />\n);\n\nconst permissionDesc = {\n \"edit-post\": \"Can edit posts with these labels\",\n \"use-labels\": \"Can assign and unassign these labels\",\n};\n\nconst permissionExplainer = (permission) => {\n if (permission.startsWith(\"starts-with:\")) {\n let s = permission.substring(\"starts-with:\".length);\n if (s == \"\") {\n return \"Any label\";\n } else {\n return `Labels that start with \"${s}\"`;\n }\n } else {\n return permission;\n }\n};\n\nconst permissionsFilter = (permissionType) => {\n let res = [];\n for (const [pattern, permissions] of Object.entries(metadata.permissions)) {\n if (permissions.includes(permissionType)) {\n res.push(pattern);\n }\n }\n return res;\n};\n\nconst permissionsRenderer = (permissionType) => {\n let permissions = permissionsFilter(permissionType);\n if (permissions.length > 0) {\n return (\n <p class=\"card-text\" key={`${permissionType}-permissions`}>\n {permissionDesc[permissionType]}:\n {permissions.map((permission) => (\n <span class=\"badge text-bg-primary\" key={permission}>\n {permissionExplainer(permission)}\n </span>\n ))}\n </p>\n );\n } else {\n return <div></div>;\n }\n};\n\nreturn (\n <Card className=\"card my-2 border-secondary\">\n <div className=\"card-header\">\n <small class=\"text-muted\">{header}</small>\n </div>\n <div className=\"card-body\">\n <p class=\"card-text\" key=\"description\">\n <Markdown class=\"card-text\" text={metadata.description}></Markdown>\n </p>\n {permissionsRenderer(\"edit-post\")}\n {permissionsRenderer(\"use-labels\")}\n {metadata.children ? (\n <div class=\"vstack\">\n {metadata.children.map((child) =>\n widget(\n \"components.teams.TeamInfo\",\n { member: child, members_list: props.members_list },\n child\n )\n )}\n </div>\n ) : null}\n </div>\n </Card>\n);\n" }, "gigs-board.components.layout.SearchByLabel": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\nconst onSearchLabel = props.onSearchLabel;\nconst selectedLabels = props.labelQuery?.label\n ? [{ name: props.labelQuery.label }]\n : [];\n\nconst labels = Near.view(nearDevGovGigsContractAccountId, \"get_all_labels\");\nif (!labels) {\n return <div>Loading ...</div>;\n}\nconst wrappedLabels = labels.map((label) => ({ name: label }));\n\nconst onChange = (selectedLabels) => {\n onSearchLabel(selectedLabels[0]?.name);\n};\n\nreturn (\n <Typeahead\n clearButton\n id=\"basic-typeahead-single\"\n labelKey=\"name\"\n onChange={onChange}\n options={wrappedLabels}\n placeholder=\"Search by tag\"\n selected={selectedLabels}\n />\n);\n" }, "gigs-board.feature.integration.github.board-config-editor": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n/* INCLUDE: \"shared/lib/form\" */\n/**\n *! TODO: Extract into separate library module\n *! once `useForm` is converted into a form factory widget\n */\nconst traversalUpdate = ({\n input,\n target: treeOrBranch,\n path: [currentBranchKey, ...remainingBranch],\n params,\n via: nodeUpdate,\n}) => ({\n ...treeOrBranch,\n\n [currentBranchKey]:\n remainingBranch.length > 0\n ? traversalUpdate({\n input,\n\n target:\n typeof treeOrBranch[currentBranchKey] === \"object\"\n ? treeOrBranch[currentBranchKey]\n : {\n ...((treeOrBranch[currentBranchKey] ?? null) !== null\n ? { __archivedLeaf__: treeOrBranch[currentBranchKey] }\n : {}),\n },\n\n path: remainingBranch,\n via: nodeUpdate,\n })\n : nodeUpdate({\n input,\n lastKnownState: treeOrBranch[currentBranchKey],\n params,\n }),\n});\n\nconst fieldDefaultUpdate = ({\n input,\n lastKnownState,\n params: { arrayDelimiter },\n}) => {\n switch (typeof input) {\n case \"boolean\":\n return input;\n\n case \"object\":\n return Array.isArray(input) && typeof lastKnownState === \"string\"\n ? input.join(arrayDelimiter ?? \",\")\n : input;\n\n case \"string\":\n return Array.isArray(lastKnownState)\n ? input.split(arrayDelimiter ?? \",\").map((string) => string.trim())\n : input;\n\n default: {\n if ((input ?? null) === null) {\n switch (typeof lastKnownState) {\n case \"boolean\":\n return !lastKnownState;\n\n default:\n return lastKnownState;\n }\n } else return input;\n }\n }\n};\n\nconst useForm = ({ stateKey: formStateKey }) => ({\n formState: state[formStateKey],\n\n formUpdate:\n ({ path: fieldPath, via: fieldCustomUpdate, ...params }) =>\n (fieldInput) =>\n State.update((lastKnownState) =>\n traversalUpdate({\n input: fieldInput?.target?.value ?? fieldInput,\n target: lastKnownState,\n path: [formStateKey, ...fieldPath],\n params,\n\n via:\n typeof fieldCustomUpdate === \"function\"\n ? fieldCustomUpdate\n : fieldDefaultUpdate,\n })\n ),\n});\n/* END_INCLUDE: \"shared/lib/form\" */\n/* INCLUDE: \"shared/lib/gui\" */\nconst Card = styled.div`\n &:hover {\n box-shadow: rgba(3, 102, 214, 0.3) 0px 0px 0px 3px;\n }\n`;\n\nconst CompactContainer = styled.div`\n width: fit-content !important;\n max-width: 100%;\n`;\n/* END_INCLUDE: \"shared/lib/gui\" */\n/* INCLUDE: \"shared/lib/uuid\" */\nconst uuid = () =>\n [Date.now().toString(16)]\n .concat(\n Array.from(\n { length: 4 },\n () => Math.floor(Math.random() * 0xffffffff) & 0xffffffff\n ).map((value) => value.toString(16))\n )\n .join(\"-\");\n\nconst uuidIndexed = (data) => {\n const id = uuid();\n\n return Object.fromEntries([[id, { ...data, id }]]);\n};\n/* END_INCLUDE: \"shared/lib/uuid\" */\n/* INCLUDE: \"shared/mocks\" */\nconst communities = {\n \"zero-knowledge\": {\n overviewId: 397,\n eventsId: 401,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreiajwq6ep3n7veddozji2djv5vviyisabhycbweslvpwhsoyuzcwi4\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreihgxg5kwts2juldaeasveyuddkm6tcabmrat2aaq5u6uyljtyt7lu\",\n\n title: \"Zero Knowledge\",\n desc: \"Building a zero knowledge ecosystem on NEAR.\",\n telegram: \"NearZeroKnowledge\",\n },\n\n protocol: {\n overviewId: 412,\n eventsId: 413,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreidpitdafcnhkp4uyomacypdgqvxr35jtfnbxa5s6crby7qjk2nv5a\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreicg4svzfz5nvllomsahndgm7u62za4sib4mmbygxzhpcl4htqwr4a\",\n\n title: \"Protocol\",\n desc: \"Supporting the ongoing innovation of the NEAR Protocol.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-protocol\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Protocol NEPs\",\n },\n },\n },\n },\n\n telegram: \"NEAR_Protocol_Community_Group\",\n },\n\n tooling: {\n overviewId: 416,\n eventsId: 417,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreie2eaj5czmpfe6pe53kojzcspgozebdsonffwvbxtpuipnwahybvi\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreiehzr7z2fhoqqmkt3z667wubccbch6sqtsnvd6msodyzpnf72cszy\",\n\n title: \"Tooling\",\n desc: \"Supporting the ongoing innovation of tooling.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-tools\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Tooling NEPs\",\n },\n },\n },\n },\n\n telegram: \"NEAR_Tools_Community_Group\",\n },\n\n \"contract-standards\": {\n overviewId: 414,\n eventsId: 415,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreiepgdnu7soc6xgbyd4adicbf3eyxiiwqawn6tguaix6aklfpir634\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreiaowjqxds24fwcliyriintjd4ucciprii2rdxjmxgi7f5dmzuscey\",\n\n title: \"Contract Standards\",\n desc: \"Coordinating the contribution to the NEAR dapp standards.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Contract Standards NEPs\",\n },\n },\n },\n },\n\n telegram: \"nearnft\",\n },\n};\n/* END_INCLUDE: \"shared/mocks\" */\n\nconst dataTypesLocked = {\n Issue: true,\n PullRequest: true,\n};\n\nconst boardConfigDefaults = {\n id: uuid(),\n columns: {},\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"\",\n repoURL: \"\",\n ticketState: \"all\",\n title: \"\",\n};\n\nconst GithubBoardConfigEditor = ({ label, pageURL }) => {\n const communityGitHubKanbanBoards =\n communities[label].integrations?.github?.boards ?? {};\n\n State.init({\n boardConfig: null,\n\n editingMode: \"form\",\n isEditingAllowed: false, // According to user permission level\n isEditorEnabled: false,\n\n ...Storage.get(\n \"state\",\n `${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.components.community.CommunityHeader`\n ),\n });\n\n const onEditorToggle = (forcedState) =>\n State.update((lastKnownState) => ({\n ...lastKnownState,\n isEditorEnabled: forcedState ?? !lastKnownState.isEditorEnabled,\n }));\n\n const onEditingModeChange = ({ target: { value } }) =>\n State.update((lastKnownState) => ({\n ...lastKnownState,\n editingMode: value,\n }));\n\n if (\n state.boardConfig === null &&\n Object.keys(communityGitHubKanbanBoards).length > 0\n ) {\n State.update((lastKnownState) => ({\n ...lastKnownState,\n boardConfig: Object.values(communityGitHubKanbanBoards)[0],\n }));\n }\n\n const boardsCreateNew = () =>\n State.update((lastKnownState) => ({\n ...lastKnownState,\n boardConfig: boardConfigDefaults,\n isEditorEnabled: true,\n }));\n\n const { formState, formUpdate } = useForm({ stateKey: \"boardConfig\" });\n\n const columnsCreateNew = ({ lastKnownState }) =>\n Object.keys(lastKnownState).length < 6\n ? {\n ...lastKnownState,\n\n ...uuidIndexed({\n description: \"\",\n labelSearchTerms: [],\n title: \"New column\",\n }),\n }\n : lastKnownState;\n\n const columnsDeleteById =\n (id) =>\n ({ lastKnownState }) =>\n Object.fromEntries(\n Object.entries(lastKnownState).filter(([columnId]) => columnId !== id)\n );\n\n const form =\n formState !== null ? (\n <>\n <div className=\"d-flex gap-3 flex-column flex-lg-row\">\n <div className=\"input-group-text border-0 d-flex flex-column flex-1 flex-shrink-0\">\n <span id={`${formState.id}-title`}>Title</span>\n\n <input\n aria-describedby={`${formState.id}-title`}\n className=\"form-control\"\n onChange={formUpdate({ path: [\"title\"] })}\n placeholder=\"NEAR Protocol NEPs\"\n type=\"text\"\n value={formState.title}\n />\n </div>\n\n <div\n className={[\n \"input-group-text border-0\",\n \"d-flex flex-column justify-content-evenly flex-4 w-100\",\n ].join(\" \")}\n >\n <span id={`${formState.id}-repoURL`}>GitHub repository URL</span>\n\n <input\n aria-describedby={`${formState.id}-repoURL`}\n className=\"form-control\"\n onChange={formUpdate({ path: [\"repoURL\"] })}\n placeholder=\"https://github.com/example-org/example-repo\"\n type=\"text\"\n value={formState.repoURL}\n />\n </div>\n </div>\n\n <div className=\"d-flex gap-3 flex-column flex-lg-row\">\n <CompactContainer className=\"d-flex gap-3 flex-column justify-content-start p-3 ps-0\">\n <span\n className=\"d-inline-flex gap-2\"\n id={`${formState.id}-dataTypesIncluded`}\n >\n <i class=\"bi bi-database-fill\" />\n <span>Tracked data</span>\n </span>\n\n {Object.entries(formState.dataTypesIncluded).map(\n ([typeName, enabled]) =>\n widget(\n \"components.atom.toggle\",\n {\n active: enabled,\n className: \"w-100\",\n disabled: dataTypesLocked[typeName],\n key: typeName,\n label: typeName,\n\n onSwitch: formUpdate({\n path: [\"dataTypesIncluded\", typeName],\n }),\n },\n\n typeName\n )\n )}\n </CompactContainer>\n\n <CompactContainer className=\"d-flex gap-3 flex-column justify-content-start p-3 ps-0\">\n <span\n className=\"d-inline-flex gap-2\"\n id={`${formState.id}-dataTypesIncluded`}\n >\n <i class=\"bi bi-database-fill\" />\n <span>Ticket state</span>\n </span>\n\n {widget(\"components.atom.button-switch\", {\n currentValue: formState.ticketState,\n key: \"ticketState\",\n onChange: formUpdate({ path: [\"ticketState\"] }),\n\n options: [\n { label: \"All\", value: \"all\" },\n { label: \"Open\", value: \"open\" },\n { label: \"Closed\", value: \"closed\" },\n ],\n\n title: \"Editing mode selection\",\n })}\n </CompactContainer>\n\n <div className=\"input-group-text border-0 d-flex flex-column w-100\">\n <span id={`${formState.id}-description`}>Description</span>\n\n <textarea\n aria-describedby={`${formState.id}-description`}\n className=\"form-control h-75\"\n onChange={formUpdate({ path: [\"description\"] })}\n placeholder=\"Latest NEAR Enhancement Proposals by status.\"\n type=\"text\"\n value={formState.description}\n />\n </div>\n </div>\n\n <div className=\"d-flex align-items-center justify-content-between\">\n <span className=\"d-inline-flex gap-2 m-0\">\n <i className=\"bi bi-list-task\" />\n <span>Columns ( max. 6 )</span>\n </span>\n </div>\n\n <div className=\"d-flex flex-column align-items-center gap-3\">\n {Object.values(formState.columns).map(\n ({ id, description, labelSearchTerms, title }) => (\n <div\n class=\"d-flex flex-column gap-3 rounded-2 p-3 w-100 bg-secondary bg-opacity-25\"\n key={id}\n >\n <div class=\"d-flex gap-3\">\n <div\n className=\"d-flex flex-column flex-grow-1\"\n style={{ width: \"inherit\" }}\n >\n <span id={`${formState.id}-column-${id}-title`}>Title</span>\n\n <input\n aria-describedby={`${formState.id}-column-${id}-title`}\n className=\"form-control\"\n onChange={formUpdate({\n path: [\"columns\", id, \"title\"],\n })}\n placeholder=\"👀 Review\"\n type=\"text\"\n value={title}\n />\n </div>\n\n <button\n class=\"btn btn-outline-danger\"\n onClick={formUpdate({\n path: [\"columns\"],\n via: columnsDeleteById(id),\n })}\n title=\"Delete column\"\n >\n <i class=\"bi bi-file-earmark-minus-fill\" />\n </button>\n </div>\n\n <div\n className=\"d-flex flex-column\"\n style={{ width: \"inherit\" }}\n >\n <span id={`${formState.id}-column-${id}-description`}>\n Description\n </span>\n\n <input\n aria-describedby={`${formState.id}-column-${id}-description`}\n className=\"form-control\"\n onChange={formUpdate({\n path: [\"columns\", id, \"description\"],\n })}\n placeholder=\"NEPs that need a review by Subject Matter Experts.\"\n type=\"text\"\n value={description}\n />\n </div>\n\n <div\n className=\"d-flex flex-column\"\n style={{ width: \"inherit\" }}\n >\n <span\n className=\"text-wrap\"\n id={`${formState.id}-column-${title}-searchTerms`}\n >\n Search terms for all the labels MUST be presented in\n included tickets, comma-separated\n </span>\n\n <input\n aria-describedby={`${formState.id}-column-${title}-searchTerms`}\n aria-label=\"Search terms for included labels\"\n className=\"form-control\"\n onChange={formUpdate({\n path: [\"columns\", id, \"labelSearchTerms\"],\n })}\n placeholder=\"WG-, draft, review, proposal, ...\"\n type=\"text\"\n value={labelSearchTerms.join(\", \")}\n />\n </div>\n </div>\n )\n )}\n </div>\n </>\n ) : null;\n\n return (\n <div className=\"d-flex flex-column gap-4\">\n {state.isEditorEnabled && formState !== null ? (\n <div\n className={[\n \"d-flex flex-column gap-3\",\n \"border border-2 border-primary rounded-2 p-3 w-100\",\n ].join(\" \")}\n >\n <div className=\"d-flex align-items-center justify-content-between gap-3\">\n <h5 className=\"h5 d-inline-flex gap-2 m-0\">\n <i className=\"bi bi-wrench-adjustable-circle-fill\" />\n <span>Board configuration</span>\n </h5>\n\n {widget(\"components.atom.button-switch\", {\n currentValue: state.editingMode,\n key: \"editingMode\",\n onChange: onEditingModeChange,\n\n options: [\n { label: \"Form\", value: \"form\" },\n { label: \"JSON\", value: \"JSON\" },\n ],\n\n title: \"Editing mode selection\",\n })}\n </div>\n\n {state.editingMode === \"form\" ? (\n form\n ) : (\n <div className=\"d-flex flex-column flex-grow-1 border-0 bg-transparent w-100\">\n <textarea\n className=\"form-control\"\n disabled\n rows=\"12\"\n type=\"text\"\n value={JSON.stringify(formState, null, \"\\t\")}\n />\n </div>\n )}\n\n <div className=\"d-flex align-items-center justify-content-end gap-3\">\n <button\n className=\"btn btn-outline-secondary d-inline-flex gap-2 me-auto\"\n disabled={Object.keys(formState.columns).length >= 6}\n onClick={formUpdate({\n path: [\"columns\"],\n via: columnsCreateNew,\n })}\n >\n <i class=\"bi bi-plus-lg\" />\n <span>New column</span>\n </button>\n\n <button\n className=\"btn btn-outline-danger d-inline-flex gap-2 align-items-center\"\n onClick={() => onEditorToggle(false)}\n style={{ width: \"fit-content\" }}\n >\n <span>Cancel</span>\n </button>\n\n <button\n disabled={!formState.hasChanges}\n className=\"btn btn-primary d-inline-flex gap-2 align-items-center\"\n style={{ width: \"fit-content\" }}\n >\n <i className=\"bi bi-file-arrow-up-fill\" />\n <span>Save</span>\n </button>\n </div>\n </div>\n ) : null}\n\n {state.boardConfig !== null ? (\n widget(\"entity.github-repo.board\", {\n ...state.boardConfig,\n editorTrigger: () => onEditorToggle(true),\n isEditable: state.isEditingAllowed,\n pageURL,\n })\n ) : (\n <div\n className=\"d-flex flex-column align-items-center justify-content-center gap-4\"\n style={{ height: 384 }}\n >\n <h5 className=\"h5 d-inline-flex gap-2 m-0\">\n This community doesn't have GitHub boards.\n </h5>\n\n <button\n className=\"btn btn-primary d-inline-flex gap-2\"\n onClick={boardsCreateNew}\n >\n <i class=\"bi bi-kanban-fill\" />\n <span>Create one</span>\n </button>\n </div>\n )}\n </div>\n );\n};\n\nreturn GithubBoardConfigEditor(props);\n" }, "gigs-board.components.layout.Page": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\nreturn (\n <>\n {widget(\"components.layout.Banner\")}\n {props.header}\n {props.children}\n </>\n);\n" }, "gigs-board.pages.community.Sidebar": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\n/* INCLUDE: \"communities.jsx\" */\nconst communities = {\n \"zero-knowledge\": {\n overviewId: 397,\n eventsId: 401,\n icon: \"https://ipfs.near.social/ipfs/bafkreiajwq6ep3n7veddozji2djv5vviyisabhycbweslvpwhsoyuzcwi4\",\n cover:\n \"https://ipfs.near.social/ipfs/bafkreihgxg5kwts2juldaeasveyuddkm6tcabmrat2aaq5u6uyljtyt7lu\",\n title: \"Zero Knowledge\",\n desc: \"Building a zero knowledge ecosystem on NEAR.\",\n },\n protocol: {\n overviewId: 412,\n eventsId: 413,\n icon: \"https://ipfs.near.social/ipfs/bafkreidpitdafcnhkp4uyomacypdgqvxr35jtfnbxa5s6crby7qjk2nv5a\",\n cover:\n \"https://ipfs.near.social/ipfs/bafkreicg4svzfz5nvllomsahndgm7u62za4sib4mmbygxzhpcl4htqwr4a\",\n title: \"Protocol\",\n desc: \"Supporting the ongoing innovation of the NEAR Protocol.\",\n },\n tooling: {\n overviewId: 416,\n eventsId: 417,\n icon: \"https://ipfs.near.social/ipfs/bafkreie2eaj5czmpfe6pe53kojzcspgozebdsonffwvbxtpuipnwahybvi\",\n cover:\n \"https://ipfs.near.social/ipfs/bafkreiehzr7z2fhoqqmkt3z667wubccbch6sqtsnvd6msodyzpnf72cszy\",\n title: \"Tooling\",\n desc: \"Supporting the ongoing innovation of tooling.\",\n },\n \"contract-standards\": {\n overviewId: 414,\n eventsId: 415,\n icon: \"https://ipfs.near.social/ipfs/bafkreiepgdnu7soc6xgbyd4adicbf3eyxiiwqawn6tguaix6aklfpir634\",\n cover:\n \"https://ipfs.near.social/ipfs/bafkreiaowjqxds24fwcliyriintjd4ucciprii2rdxjmxgi7f5dmzuscey\",\n title: \"Contract Standards\",\n desc: \"Coordinating the contribution to the NEAR dapp standards.\",\n },\n};\n/* END_INCLUDE: \"communities.jsx\" */\n\n/* INCLUDE: \"mockcommunity.jsx\" */\nconst socialLinks = [\n {\n href: \"#/mob.near/widget/ProfilePage?accountId=self.social.near\",\n iconClass: \"bi bi-globe\",\n label: community.title,\n },\n\n {\n href: \"https://github.com/NearSocial\",\n iconClass: \"bi bi-github\",\n label: community.title,\n },\n {\n href: \"https://twitter.com/NearSocial_\",\n iconClass: \"bi bi-twitter\",\n label: community.title,\n },\n {\n href: \"https://t.me/NearSocial\",\n iconClass: \"bi bi-telegram\",\n label: community.title,\n },\n];\n\n// TODO ADD AMIN MEMBERS HERE\n\nconst TeamMembers = [\n {\n id: \"\",\n role: \"\",\n avatar: \"\",\n wallet: \"\",\n },\n\n {\n id: \"js_joker\",\n role: \"Admin\",\n avatar:\n \"https://paras.id/_next/image?url=https%3A%2F%2Fparas-cdn.imgix.net%2F6196b861da8a91415f23e551a5e88c0ac0671c0d%3Fw%3D400&w=1080&q=75\",\n wallet: \"@js_joker.near\",\n },\n];\n/* END_INCLUDE: \"mockcommunity.jsx\" */\n\nif (!props.label) {\n return (\n <div class=\"alert alert-danger\" role=\"alert\">\n Error: label is required\n </div>\n );\n}\n\nconst label = props.label;\n\nconst discussionRequiredPosts =\n Near.view(nearDevGovGigsContractAccountId, \"get_posts_by_label\", {\n label,\n }) ?? [];\n\nconst community = communities[props.label];\n\nconst onMention = (accountId) => (\n <span key={accountId} className=\"d-inline-flex\" style={{ fontWeight: 500 }}>\n <Widget\n src=\"neardevgov.near/widget/ProfileLine\"\n props={{\n accountId: accountId.toLowerCase(),\n hideAccountId: true,\n tooltip: true,\n }}\n />\n </span>\n);\n\n// START OF SIDEBAR\n// Social Links Master Styling\nconst SocialLink = ({ link, index }) => (\n <a\n className={`btn btn-outline-secondary border-0 d-flex align-items-center`}\n href={link.href}\n style={{ marginLeft: \"0px\" }}\n >\n <i className={link.iconClass}></i>\n <span className=\"ms-1\">{link.label || community.title}</span>\n </a>\n);\n\n// Social Media Icons\nconst SocialMediaIcons = (\n <div\n className=\"mb-1 d-flex gap-2 flex-wrap flex-column\"\n style={{ padding: \"0px\" }}\n >\n {socialLinks.map((link, index) => (\n <SocialLink key={index} link={link} index={index} />\n ))}\n </div>\n);\n\nconst CommunitySummary = (\n <div style={{ top: \"0\", left: \"0\" }}>\n <Markdown text={community.desc} onMention={onMention} />\n <h3 className=\"mt-2 mb-2\">{community.label}</h3>\n <div className=\"row mb-2 align-items-center d-flex justify-content-between\">\n <div className=\"col-auto\">\n <div className=\"d-flex align-items-center\">\n <a href={href(\"Feed\", { label })} key={label}>\n <span\n className=\"badge text-bg-grey ms-1\"\n style={{\n color: \"rgba(0, 0, 0, 0.7)\",\n fontSize: \"1em\",\n fontWeight: \"normal\",\n boxShadow: \"0px 1px 3px rgba(0, 0, 0, 0.2)\",\n padding: \"0.2em 0.5em\",\n }}\n >\n <div>{label}</div>\n </span>\n </a>\n </div>\n </div>\n </div>\n <br></br>\n <br></br>\n {socialLinks.map((link, index) => (\n <SocialLink key={index} link={link} index={index} />\n ))}\n </div>\n);\n\nconst Card = ({ content }) => (\n <div\n className=\"card\"\n style={{\n border: \"none\",\n }}\n >\n <div className=\"card-body\">\n <p className=\"card-text\">{content}</p>\n </div>\n </div>\n);\n\nconst CommunityOverview = (\n <Card title={`${community.title} Overview`} content={CommunitySummary}></Card>\n);\n\nconst TeamMember = ({ member }) => (\n <div className=\"d-flex align-items-start mb-1 justify-content-start\">\n <img\n src={member.avatar}\n alt={member.id}\n style={{\n width: \"50px\",\n height: \"50px\",\n borderRadius: \"50%\",\n marginRight: \"10px\",\n }}\n />\n <div style={{ paddingTop: \"7px\" }}>\n <h6 style={{ fontSize: \"110%\", fontWeight: \"bold\", marginBottom: \"0\" }}>\n {member.id}\n </h6>\n <p style={{ fontSize: \"100%\" }}>{member.wallet}</p>\n </div>\n </div>\n);\n\n// Team Members List\nconst TeamMembersList = TeamMembers.map((member) => (\n <TeamMember key={member.id} member={member} />\n));\n\n// More Info Button\nconst MoreInfoButton = (\n <div className=\"d-flex justify-content-start\">\n <button\n type=\"button\"\n class=\"btn\"\n style={{\n color: \"black\",\n fontSize: \"0.8rem\",\n fontWeight: \"bold\",\n }}\n href=\"#\"\n >\n See More\n </button>\n </div>\n);\n\n// Team Card\nconst TeamsCard = (\n <div style={{ width: \"100%\" }}>\n <Card\n title={\"Team Members\"}\n content={\n <div>\n <h5\n style={{\n fontSize: \"1.3rem\",\n fontWeight: \"800\",\n marginBottom: \"20px\",\n }}\n >\n Group Moderators\n </h5>\n {TeamMembersList}\n {MoreInfoButton}\n </div>\n }\n ></Card>\n </div>\n);\n\n// Define the Sidebar component\nconst Sidebar = () => (\n <div class=\"col-md-12 d-flex flex-column align-items-end\">\n {CommunityOverview}\n <hr style={{ width: \"100%\", borderTop: \"4px solid #00000033\" }} />\n {TeamsCard}\n </div>\n);\n\n// Define the layout for the page\nconst PageLayout = () => (\n <div class=\"container\">\n <div class=\"row\">\n <Sidebar />\n </div>\n </div>\n);\n\nreturn <PageLayout />;\n// END OF SIDEBAR\n\n// USAGE\n// copy and paste this into the return function of a page you want the sidebar on\n// make sure to add `col-mb-9` to the class of the div you want to\n// take up 2/3 of the screen to the left\n\n// then make sure to add `col-mb-3` to the class of the div you want to\n// take up 1/3 of the screen to the\n\n{\n /* <div class=\"col-4 container-fluid\">\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.community.Sidebar`}\n props={{\n metadata: metadata,\n accountId: accountId,\n widgetName: widgetName,\n label: props.label,\n }}\n />\n</div> */\n}\n" }, "gigs-board.components.layout.Controls": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\nreturn (\n <div class=\"d-flex flex-row-reverse\">\n <a\n class=\"btn btn-light\"\n style={{\n backgroundColor: \"#0C7283\",\n color: \"#f3f3f3\",\n }}\n href={href(\"Create\", { labels: props.labels })}\n >\n <i class=\"bi bi-plus-circle-fill\"></i>\n Submit Idea / Solution\n </a>\n </div>\n);\n" }, "gigs-board.components.layout.SearchByAuthor": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\nconst onSearchAuthor = props.onSearchAuthor;\nconst selectedAuthors = props.authorQuery?.author\n ? [{ name: props.authorQuery.author }]\n : [];\n\nconst authors = Near.view(nearDevGovGigsContractAccountId, \"get_all_authors\");\nif (!authors) {\n return <div>Loading ...</div>;\n}\nconst wrappedAuthors = authors.map((author) => ({ name: author }));\n\nconst onChangeAuthor = (selectedAuthors) => {\n onSearchAuthor(selectedAuthors[0]?.name);\n};\n\nreturn (\n <>\n <Typeahead\n clearButton\n id=\"basic-typeahead-single\"\n labelKey=\"name\"\n onChange={onChangeAuthor}\n options={wrappedAuthors}\n placeholder=\"Search by author\"\n selected={selectedAuthors}\n />\n </>\n);\n" }, "gigs-board.components.teams.LabelsPermissions": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\nconst access_info =\n Near.view(nearDevGovGigsContractAccountId, \"get_access_control_info\") ?? null;\n\nif (!access_info) {\n return <div>Loading...</div>;\n}\n\nconst rules_list = props.rules_list ?? access_info.rules_list;\n\nconst permissionExplainer = (permission) => {\n if (permission.startsWith(\"starts-with:\")) {\n let s = permission.substring(\"starts-with:\".length);\n if (s == \"\") {\n return \"Any label\";\n } else {\n return `Labels that start with \"${s}\"`;\n }\n } else {\n return permission;\n }\n};\n\nreturn (\n <div className=\"card border-secondary\" key=\"labelpermissions\">\n <div className=\"card-header\">\n <i class=\"bi-lock-fill\"> </i>\n <small class=\"text-muted\">Restricted Labels</small>\n </div>\n <ul class=\"list-group list-group-flush\">\n {Object.entries(rules_list).map(([pattern, metadata]) => (\n <li class=\"list-group-item\" key={pattern}>\n <span class=\"badge text-bg-primary\" key={`${pattern}-permission`}>\n {permissionExplainer(pattern)}\n </span>{\" \"}\n {metadata.description}\n </li>\n ))}\n </ul>\n </div>\n);\n" }, "gigs-board.components.community.CommunityHeader": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\nconst Header = styled.div`\n overflow: hidden;\n background: #f3f3f3;\n margin-top: -25px;\n margin-bottom: 25px;\n`;\n\nconst NavUnderline = styled.ul`\n a {\n color: #3252a6;\n text-decoration: none;\n }\n\n a.active {\n font-weight: bold;\n border-bottom: 2px solid #0c7283;\n }\n`;\n\nconst BreadcrumbLink = styled.a`\n {\n color: #3252a6;\n text-decoration: none;\n }\n`;\n\nconst BreadcrumbBold = styled.b`\n {\n color: #3252a6;\n }\n`;\n\nconst topicTabs = [\n {\n defaultActive: true,\n iconClass: \"bi bi-house-door\",\n path: \"community.Overview\",\n title: \"Overview\",\n },\n {\n iconClass: \"bi bi-chat-square-text\",\n path: \"community.Discussions\",\n title: \"Discussions\",\n },\n {\n iconClass: \"bi bi-coin\",\n path: \"community.Sponsorship\",\n title: \"Sponsorship\",\n },\n {\n iconClass: \"bi bi-calendar\",\n path: \"community.Events\",\n title: \"Events\",\n },\n {\n iconClass: \"bi bi-github\",\n path: \"community.github\",\n title: \"GitHub\",\n },\n {\n iconClass: \"bi bi-telegram\",\n path: \"community.Telegram\",\n title: \"Telegram\",\n },\n];\n\nconst CommunityHeader = ({ label, tab }) => {\n State.init({ shared: { isEditorEnabled: false } });\n Storage.set(\"state\", state.shared);\n\n const onEditorToggle = () =>\n State.update((lastState) => ({\n ...lastState,\n\n shared: {\n ...lastState.shared,\n isEditorEnabled: !lastState.shared.isEditorEnabled,\n },\n }));\n\n return (\n <Header className=\"d-flex flex-column gap-3 px-4 pt-3\">\n <ol className=\"breadcrumb\">\n <li className=\"breadcrumb-item\">\n <BreadcrumbLink href={href(\"Feed\")}>DevHub</BreadcrumbLink>\n </li>\n\n <li className=\"breadcrumb-item active\" aria-current=\"page\">\n <BreadcrumbBold>{props.title}</BreadcrumbBold>\n </li>\n </ol>\n\n <div className=\"d-flex justify-content-between\">\n <div className=\"d-flex align-items-center\">\n <img src={props.icon} width=\"95px\" height=\"95px\"></img>\n\n <div>\n <div className=\"h5 pt-3 ps-3\">{props.title}</div>\n <div className=\"ps-3 pb-2 text-secondary\">{props.desc}</div>\n </div>\n </div>\n\n {widget(\"components.atom.toggle\", {\n active: state.shared.isEditorEnabled,\n className: \"visually-hidden\",\n direction: \"rtl\",\n key: \"community-editor-toggle\",\n label: \"( WIP ) Editor mode\",\n onSwitch: onEditorToggle,\n })}\n </div>\n\n <NavUnderline className=\"nav\">\n {topicTabs.map(({ defaultActive, iconClass, path, title }) =>\n title ? (\n <li className=\"nav-item\" key={title}>\n <a\n aria-current={defaultActive && \"page\"}\n className={[\n \"d-inline-flex gap-2\",\n tab === title ? \"nav-link active\" : \"nav-link\",\n ].join(\" \")}\n href={href(path, { label })}\n >\n {iconClass && <i className={iconClass} />}\n <span>{title}</span>\n </a>\n </li>\n ) : null\n )}\n </NavUnderline>\n </Header>\n );\n};\n\nreturn CommunityHeader(props);\n" }, "gigs-board.components.posts.ProfileHeader": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\nconst postId = props.post.id ?? (props.id ? parseInt(props.id) : 0);\nconst post =\n props.post ??\n Near.view(nearDevGovGigsContractAccountId, \"get_post\", { post_id: postId });\nif (!post) {\n return <div>Loading ...</div>;\n}\n\nreturn (\n <>\n {!hideImage && (\n <Widget\n className=\"col-auto aspect-ratio-square\"\n key=\"image\"\n src=\"mob.near/widget/ProfileImage\"\n props={{\n style: {\n width: \"3em\",\n height: \"3em\",\n marginRight: \"0.1em\",\n borderRadius: \"50%\",\n \"@media (max-width: 768px)\": {\n // Small screens\n marginBottom: \"12em\",\n },\n \"@media (min-width: 768px)\": {\n // Medium screens\n marginBottom: \"6em\",\n },\n },\n profile,\n accountId: \"post.author_id\",\n className: \"d-inline-block rounded-circle\",\n imageClassName: \"rounded w-100 h-100 align-top\",\n }}\n />\n )}\n {!hideName && <span key=\"name\">{name}</span>}\n {!hideAccountId && (\n <span key=\"accountId\" className=\"text-muted ms-1\">\n @{accountId}\n </span>\n )}\n </>\n);\n" }, "gigs-board.pages.community.Discussions": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\n/* INCLUDE: \"shared/mocks\" */\nconst communities = {\n \"zero-knowledge\": {\n overviewId: 397,\n eventsId: 401,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreiajwq6ep3n7veddozji2djv5vviyisabhycbweslvpwhsoyuzcwi4\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreihgxg5kwts2juldaeasveyuddkm6tcabmrat2aaq5u6uyljtyt7lu\",\n\n title: \"Zero Knowledge\",\n desc: \"Building a zero knowledge ecosystem on NEAR.\",\n telegram: \"NearZeroKnowledge\",\n },\n\n protocol: {\n overviewId: 412,\n eventsId: 413,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreidpitdafcnhkp4uyomacypdgqvxr35jtfnbxa5s6crby7qjk2nv5a\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreicg4svzfz5nvllomsahndgm7u62za4sib4mmbygxzhpcl4htqwr4a\",\n\n title: \"Protocol\",\n desc: \"Supporting the ongoing innovation of the NEAR Protocol.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-protocol\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-protocol\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Protocol NEPs\",\n },\n },\n },\n },\n\n telegram: \"NEAR_Protocol_Community_Group\",\n },\n\n tooling: {\n overviewId: 416,\n eventsId: 417,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreie2eaj5czmpfe6pe53kojzcspgozebdsonffwvbxtpuipnwahybvi\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreiehzr7z2fhoqqmkt3z667wubccbch6sqtsnvd6msodyzpnf72cszy\",\n\n title: \"Tooling\",\n desc: \"Supporting the ongoing innovation of tooling.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-tools\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-tools\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Tooling NEPs\",\n },\n },\n },\n },\n\n telegram: \"NEAR_Tools_Community_Group\",\n },\n\n \"contract-standards\": {\n overviewId: 414,\n eventsId: 415,\n\n icon: \"https://ipfs.near.social/ipfs/bafkreiepgdnu7soc6xgbyd4adicbf3eyxiiwqawn6tguaix6aklfpir634\",\n\n cover:\n \"https://ipfs.near.social/ipfs/bafkreiaowjqxds24fwcliyriintjd4ucciprii2rdxjmxgi7f5dmzuscey\",\n\n title: \"Contract Standards\",\n desc: \"Coordinating the contribution to the NEAR dapp standards.\",\n\n integrations: {\n github: {\n boards: {\n \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\": {\n id: \"18855b9c9f2-216091d-6484800b-42593f54-6102b48a\",\n\n columns: {\n \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\": {\n id: \"18855f4a93e-76a9b704-14c3ebdb-1e6c0f05-22653630\",\n\n description:\n \"NEPs that need a moderator review or author revision.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-draft\"],\n title: \"📄 Draft\",\n },\n\n \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\": {\n description:\n \"NEPS that need a review by Subject Matter Experts.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-review\"],\n title: \"👀 Review\",\n id: \"18877dc932c-c309c28--4b95e909--220e9bbb--51ff54c9\",\n },\n\n \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\": {\n description:\n \"NEPS in the final review stage that need the work group voting indications.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-voting\"],\n title: \"✔ Voting\",\n id: \"18877dd71e5-47d177b8-5505178-640a5937--17968e87\",\n },\n\n \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\": {\n description:\n \"NEPS that were reviewed and approved by a work group.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-approved\"],\n title: \"✅ Approved NEPs\",\n id: \"18877e14753--5b0ca250-1edea464-523fd579--5ebde527\",\n },\n\n \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\": {\n description:\n \"NEPS that were reviewed and approved by a work group or NEP moderators.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"A-NEP-GrammarFix\"],\n title: \"🔧 Approved Fixes\",\n id: \"18877e2f94c-4cc0ff57--1fb016c6--39ce0459-23922e81\",\n },\n\n \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\": {\n description:\n \"NEPs that were retracted by the author or had no activity for over two months.\",\n\n labelSearchTerms: [\"WG-contract-standards\", \"S-retracted\"],\n title: \"❌ RETRACTED\",\n id: \"18877e40c46--76d23f4d-578f24a8--2cfcd190--74aa77be\",\n },\n },\n\n dataTypesIncluded: { Issue: false, PullRequest: true },\n description: \"Latest NEAR Enhancement Proposals by status\",\n repoURL: \"https://github.com/near/NEPs\",\n ticketState: \"all\",\n title: \"NEAR Contract Standards NEPs\",\n },\n },\n },\n },\n\n telegram: \"nearnft\",\n },\n};\n/* END_INCLUDE: \"shared/mocks\" */\n\nif (!props.label) {\n return (\n <div class=\"alert alert-danger\" role=\"alert\">\n Error: label is required\n </div>\n );\n}\n\nconst label = props.label;\n\nconst discussionRequiredPosts =\n Near.view(nearDevGovGigsContractAccountId, \"get_posts_by_label\", {\n label,\n }) ?? [];\n\nconst community = communities[props.label];\n\nconst SearchResults = (\n <div style={{ display: \"none\" }}>\n <div class=\"row\">\n <div class=\"col\">\n {widget(\"components.post.DiscussionFeed\", {\n query: \"your-query-string\",\n })}\n </div>\n </div>\n </div>\n);\n\nconst onMention = (accountId) => (\n <span key={accountId} className=\"d-inline-flex\" style={{ fontWeight: 500 }}>\n <Widget\n src=\"neardevgov.near/widget/ProfileLine\"\n props={{\n accountId: accountId.toLowerCase(),\n hideAccountId: true,\n tooltip: true,\n }}\n />\n </span>\n);\n\nconst LabelsDisplay = (\n <div className=\"d-flex flex-wrap gap-2 mb-2\">\n {tags.length > 0 && (\n <div>\n {tags.map((tag, i) => (\n <span\n key={i}\n className=\"me-1 mb-1 fw-light badge border border-secondary text-bg-light\"\n >\n #{tag}\n </span>\n ))}\n </div>\n )}\n <div className=\"collapse public-tags\">\n <Widget src=\"mob.near/widget/PublicTags\" props={{ accountId }} />\n </div>\n </div>\n);\n\nconst Discussions = (\n <div class=\"row\">\n <div class=\"col-md-8\">\n {widget(\"components.layout.Controls\", {\n labels: discussionsRequiredLabels,\n })}\n <div className=\"row mb-2\">\n <div className=\"col\">\n <small className=\"text-muted\">\n Required label:\n <a href={href(\"Feed\", { label })} key={label}>\n <span\n className=\"badge text-bg-grey me-1\"\n style={{\n color: \"black\",\n fontSize: \"1.3em\",\n boxShadow: \"0px 1px 3px rgba(0, 0, 0, 0.2)\",\n }}\n >\n {label}\n </span>\n </a>\n </small>\n </div>\n </div>\n </div>\n {widget(\"components.layout.Controls\", {\n labels: label,\n })}\n <div class=\"row\">\n <div class=\"col\">\n {discussionRequiredPosts.map((postId) =>\n widget(\"components.posts.DiscussionFeed\", { id: postId }, postId)\n )}\n </div>\n </div>\n </div>\n);\n\nreturn widget(\"components.community.Layout\", {\n label: props.label,\n tab: \"Discussions\",\n children: (\n <div class=\"row\">\n <div class=\"col-md-9\">\n <div\n className=\"row align-items-center d-flex justify-content-between\"\n style={{ marginTop: \"18px\" }}\n >\n <div className=\"col-auto\">\n <div className=\"d-flex align-items-center\">\n <small className=\"text-muted\" style={{ fontSize: \"1.15em\" }}>\n Required tag:\n </small>\n <a href={href(\"Feed\", { label })} key={label}>\n <span\n className=\"badge ms-1\"\n style={{\n color: \"rgba(0, 0, 0, 0.7)\",\n fontSize: \"1em\",\n fontWeight: \"normal\",\n padding: \"0.2em 0.5em\",\n border: \"1px solid rgba(0, 80, 80, 0.2)\",\n }}\n >\n {label}\n </span>\n </a>\n </div>\n </div>\n <div className=\"col-auto aspect-ratio-square\">\n {widget(\"components.layout.Controls\", {\n labels: discussionsRequiredLabels,\n })}\n </div>\n </div>\n <br></br>\n <div class=\"row\">\n <div class=\"col\">\n {discussionRequiredPosts.map((postId) =>\n widget(\n \"components.posts.DiscussionFeed\",\n { id: postId, collapsed: true },\n postId\n )\n )}\n </div>\n </div>\n </div>\n <div class=\"col-3 container-fluid\">\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.community.Sidebar`}\n props={{\n metadata: metadata,\n accountId: accountId,\n widgetName: widgetName,\n label: props.label,\n }}\n />\n </div>\n </div>\n ),\n});\n" }, "gigs-board.components.layout.Banner": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\nconst Banner = styled.div`\n {\n height: 62px;\n background: #181818;\n margin-top: -24px;\n padding: 16px 20px;\n\n img {\n height: 30px;\n }\n\n margin-bottom: 25px;\n }\n`;\n\nreturn (\n <>\n <Banner className=\"d-flex justify-content-between\">\n <a href={href(\"Feed\")}>\n <img src=\"https://ipfs.near.social/ipfs/bafkreibjsn3gswlcc5mvgkfv7ady2lzkd2htm55l472suarbd34qryh2uy\"></img>\n </a>\n <div>\n <a\n href=\"https://www.neardevgov.org/blog/near-developer-dao\"\n class=\"text-white me-2\"\n >\n Developer DAO\n </a>\n\n <div class=\"btn-group\" role=\"group\">\n <button\n type=\"button\"\n class=\"btn btn-outline-light rounded-circle\"\n style={{\n width: \"30px\",\n height: \"30px\",\n padding: \"6px 0px\",\n borderWidth: \"0.5px\",\n lineHeight: \"0px\",\n }}\n data-bs-toggle=\"dropdown\"\n aria-expanded=\"false\"\n >\n <i class=\"bi bi-question-lg\"></i>\n </button>\n <ul class=\"dropdown-menu dropdown-menu-end\">\n <li>\n <a\n target=\"_blank\"\n class=\"dropdown-item\"\n href=\"https://github.com/near/devgigsboard-widgets/issues/new?assignees=&labels=bug&template=bug_report.md&title=\"\n >\n Report a bug\n </a>\n </li>\n <li>\n <a\n target=\"_blank\"\n class=\"dropdown-item\"\n href=\"https://github.com/near/devgigsboard-widgets/issues/new?assignees=&labels=enhancement&template=feature-request.md&title=\"\n >\n Suggest an improvement\n </a>\n </li>\n </ul>\n </div>\n </div>\n </Banner>\n </>\n);\n" }, "gigs-board.components.layout.LikeButton.Faces": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\nconst accountId = context.accountId;\n\nconst likesByUsers = props.likesByUsers || {};\nconst limit = props.limit ?? 3;\n\nlet likes = Object.keys(likesByUsers).reverse();\n\nconst graphLikes = [];\nconst nonGraph = [];\n\nconst graph =\n (accountId &&\n Social.keys(`${accountId}/graph/follow/*`, \"final\")[accountId].graph\n .follow) ||\n {};\n\nlikes.forEach((accountId) => {\n if (accountId in graph) {\n graphLikes.push(accountId);\n } else {\n nonGraph.push(accountId);\n }\n});\n\nlet faces = [...graphLikes, ...nonGraph];\n\nif (faces.length < limit + 3) {\n limit = faces.length;\n}\n\nconst renderFaces = faces.splice(0, limit);\n\nconst Faces = styled.span`\n .face {\n display: inline-block;\n position: relative;\n margin: -0.1em;\n height: 1.5em;\n width: 1.5em;\n min-width: 1.5em;\n vertical-align: top;\n img {\n object-fit: cover;\n border-radius: 50%;\n width: 100%;\n height: 100%;\n }\n }\n`;\n\nconst Others = styled.span`\n &:hover {\n color: white !important;\n }\n`;\n\nconst numLikes = likes.length - limit;\n\nreturn (\n <>\n <Faces className=\"ms-1\">\n {renderFaces.map((accountId, i) => (\n <a\n key={i}\n href={`#/mob.near/widget/ProfilePage?accountId=${accountId}`}\n className=\"text-decoration-none d-inline-block\"\n >\n <Widget\n src=\"mob.near/widget/Profile.OverlayTrigger\"\n props={{\n accountId,\n children: (\n <Widget\n src=\"mob.near/widget/ProfileImage\"\n props={{\n metadata,\n accountId,\n widgetName,\n style: { zIndex: 10 - i },\n className: \"face\",\n tooltip: false,\n imageStyle: {},\n imageClassName: \"\",\n }}\n />\n ),\n }}\n />\n </a>\n ))}\n </Faces>\n {numLikes > 0 ? (\n <OverlayTrigger\n placement=\"auto\"\n overlay={\n <Tooltip>\n <div\n className=\"text-truncate text-start\"\n style={{ maxWidth: \"16em\" }}\n >\n {faces.slice(0, 10).map((accountId, i) => (\n <Fragment key={i}>\n <Widget\n src=\"mob.near/widget/ProfileLine\"\n props={{ accountId, link: false }}\n />\n <br />\n </Fragment>\n ))}\n {faces.length > 10 ? \"...\" : \"\"}\n </div>\n </Tooltip>\n }\n >\n <span className=\"ms-1\">\n and {numLikes} other{numLikes === 1 ? \"\" : \"s\"}\n </span>\n </OverlayTrigger>\n ) : (\n \"\"\n )}\n </>\n);\n" }, "gigs-board.pages.WrapperWidget": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\nconst WrapperWidget = ({ children, id, storageType }) => {\n // This function handles the state change for the children widgets\n const handleStateChange = (key, value) => {\n // Use the unique identifier to create a unique storage key\n const storageKey = `${id}_${key}`;\n\n if (storageType === \"local\") {\n // Update the local storage with the new state\n Storage.set(storageKey, JSON.stringify(value));\n } else if (storageType === \"sync\") {\n // Update the sync storage with the new state\n // Replace this with the appropriate API call for your sync storage\n Storage.set(storageKey, JSON.stringify(value));\n }\n\n // Update component state\n State.update({ [storageKey]: value });\n };\n\n // This function initializes the state of the children widgets\n const initState = (key, defaultValue) => {\n // Use the unique identifier to create a unique storage key\n const storageKey = `${id}_${key}`;\n\n let storedValue;\n if (storageType === \"local\") {\n storedValue = Storage.get(storageKey);\n }\n\n if (storedValue) {\n return JSON.parse(storedValue);\n }\n\n return defaultValue;\n };\n\n // Render the children widgets and pass the state management functions as props\n return children.map((child) =>\n Widget({ src: child, props: { handleStateChange, initState } })\n );\n};\n" }, "gigs-board.pages.Feed": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n\nState.init({\n propsLabel: props.label,\n label: props.label,\n author: props.author,\n});\n\n// When rerendered with different props, State will be preserved, so we need to update the state when we detect that the props have changed.\nif (props.label !== state.propsLabel) {\n State.update({\n propsLabel: props.label,\n label: props.label,\n });\n}\n\nconst onSearchLabel = (label) => {\n State.update({ label });\n};\n\nconst onSearchAuthor = (author) => {\n State.update({ author });\n};\n\nreturn widget(\"components.layout.Page\", {\n header: widget(\"components.community.FeedHeader\"),\n children: widget(\"components.posts.Search\", {\n children: widget(\"components.layout.Controls\"),\n recency: props.recency,\n label: state.label,\n author: state.author,\n //\n labelQuery: { label: state.label },\n onSearchLabel,\n //\n authorQuery: { author: state.author },\n onSearchAuthor,\n }),\n});\n" }, "gigs-board.components.posts.CompactPost": { "": "/* INCLUDE: \"common.jsx\" */\nconst nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId ||\n (context.widgetSrc ?? \"devgovgigs.near\").split(\"/\", 1)[0];\n\nconst nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId ||\n (context.widgetSrc ?? \"jgdev.near\").split(\"/\", 1)[0];\n\nfunction widget(widgetName, widgetProps, key) {\n widgetProps = {\n ...widgetProps,\n nearDevGovGigsContractAccountId: props.nearDevGovGigsContractAccountId,\n nearDevGovGigsWidgetsAccountId: props.nearDevGovGigsWidgetsAccountId,\n referral: props.referral,\n };\n\n return (\n <Widget\n src={`${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.${widgetName}`}\n props={widgetProps}\n key={key}\n />\n );\n}\n\nfunction href(widgetName, linkProps) {\n linkProps = { ...linkProps };\n\n if (props.nearDevGovGigsContractAccountId) {\n linkProps.nearDevGovGigsContractAccountId =\n props.nearDevGovGigsContractAccountId;\n }\n\n if (props.nearDevGovGigsWidgetsAccountId) {\n linkProps.nearDevGovGigsWidgetsAccountId =\n props.nearDevGovGigsWidgetsAccountId;\n }\n\n if (props.referral) {\n linkProps.referral = props.referral;\n }\n\n const linkPropsQuery = Object.entries(linkProps)\n .filter(([_key, nullable]) => (nullable ?? null) !== null)\n .map(([key, value]) => `${key}=${value}`)\n .join(\"&\");\n\n return `/#/${nearDevGovGigsWidgetsAccountId}/widget/gigs-board.pages.${widgetName}${\n linkPropsQuery ? \"?\" : \"\"\n }${linkPropsQuery}`;\n}\n/* END_INCLUDE: \"common.jsx\" */\n/* INCLUDE: \"shared/lib/gui\" */\nconst Card = styled.div`\n &:hover {\n box-shadow: rgba(3, 102, 214, 0.3) 0px 0px 0px 3px;\n }\n`;\n\nconst CompactContainer = styled.div`\n width: fit-content !important;\n max-width: 100%;\n`;\n/* END_INCLUDE: \"shared/lib/gui\" */\n\nconst postId = props.post.id ?? (props.id ? parseInt(props.id) : 0);\nconst post =\n props.post ??\n Near.view(nearDevGovGigsContractAccountId, \"get_post\", { post_id: postId });\nif (!post) {\n return <div>Loading ...</div>;\n}\nconst snapshot = post.snapshot;\n\nconst shareButton = (\n <a\n class=\"card-link\"\n href={href(\"Post\", { id: postId })}\n role=\"button\"\n target=\"_blank\"\n title=\"Open in new tab\"\n >\n <div class=\"bi bi-share\"></div>\n </a>\n);\n\nconst header = (\n <div className=\"card-header\">\n <small class=\"text-muted\">\n <div class=\"row justify-content-between\">\n <div class=\"col-4\">\n <a\n href={`#/neardevgov.near/widget/ProfilePage?accountId=${post.author_id}`}\n className=\"link-dark text-truncate\"\n >\n <Widget\n src=\"mob.near/widget/ProfileImage\"\n props={{\n metadata,\n accountId: post.author_id,\n widgetName,\n style: { height: \"1.5em\", width: \"1.5em\", minWidth: \"1.5em\" },\n }}\n />\n <span className=\"text-muted\">@{post.author_id}</span>\n </a>\n </div>\n <div class=\"col-5\">\n <div class=\"d-flex justify-content-end\">{shareButton}</div>\n </div>\n </div>\n </small>\n </div>\n);\n\nconst emptyIcons = {\n Idea: \"bi-lightbulb\",\n Comment: \"bi-chat\",\n Submission: \"bi-rocket\",\n Attestation: \"bi-check-circle\",\n Sponsorship: \"bi-cash-coin\",\n};\n\nconst borders = {\n Idea: \"border-secondary\",\n Comment: \"border-secondary\",\n Submission: \"border-secondary\",\n Attestation: \"border-secondary\",\n Sponsorship: \"border-secondary\",\n};\n\nconst renamedPostType =\n snapshot.post_type == \"Submission\" ? \"Solution\" : snapshot.post_type;\n\nconst postLables = post.snapshot.labels ? (\n <div class=\"card-title\">\n {post.snapshot.labels.map((label) => (\n <a href={href(\"Feed\", { label })} key={label}>\n <span class=\"badge text-bg-primary me-1\">{label}</span>\n </a>\n ))}\n </div>\n) : null;\n\nconst postTitle =\n snapshot.post_type == \"Comment\" ? null : (\n <div class=\"card-text\">\n <div className=\"row justify-content-between\">\n <div class=\"col-9\">\n <i class={`bi ${emptyIcons[snapshot.post_type]}`}> </i>\n {renamedPostType}: {snapshot.name}\n </div>\n </div>\n </div>\n );\n\nconst limitedMarkdown = styled.div`\n max-height: 6em;\n`;\n\n// Should make sure the posts under the currently top viewed post are limited in size.\nconst descriptionArea =\n snapshot.post_type == \"Comment\" ? (\n <limitedMarkdown className=\"overflow-auto\">\n <Markdown class=\"card-text\" text={snapshot.description}></Markdown>\n </limitedMarkdown>\n ) : null;\n\nreturn (\n <Card className={`card my-2 ${borders[snapshot.post_type]}`}>\n {header}\n <div className=\"card-body\">\n {postTitle}\n {descriptionArea}\n {postLables}\n </div>\n </Card>\n);\n" } } } } }
Empty result
No logs
Receipt:
Predecessor ID:
Receiver ID:
Gas Burned:
223 Ggas
Tokens Burned:
0 
Transferred 0.18054  to jgdev.near
Empty result
No logs