From 599a2985fcb8b67151f6714f6050ee0adad7191c Mon Sep 17 00:00:00 2001 From: Elliot Braem <16282460+elliotBraem@users.noreply.github.com> Date: Mon, 30 Oct 2023 13:43:11 -0400 Subject: [PATCH] Community Addon Framework, Wiki and Telegram Plugins (#343) * feat: adds workflow to deploy to testnet * fix: prettier * fix: build script * feature: devhub.testnet workflow * feat: creates dev script * feat: replaces release workflow * feature: init root * feature: pass props for widgets accountId and contract accountId * feature: demo for new root * feature: adds the configurators wip * feature: branding configurator * feature: about and information configurator * feature: adds new addon flow * fix: communities metadata * fix: pass widgets to addon configurator * fix: formatting and centering * feature: refactored configurator * feature: working information, about, and access control editors * fix: branding for upload, but broken preview * feature: blog start * feature: tab links * refactor: working communities with new root * feature: implements feed * fix: format * feature: addons and configs with swapping config * feat: puts in replacements for the refactor * fix: name casing * fix: format * Implement server side search (#298) * Implement server side search * case insensitive search on content * add search test * Update deploy-dev-testnet.yml * feature: adds addons and their configurators (#326) * fix: bos-loader pulls from cargo * fix: links and replacements * chore: dummy data * feature: rename page * wip: plugins * feature: able to configure addons from community config * feat: dummy data * fix: key in tab selection * feat: telegram configurator * feature: init github * refactor: moves configurators inside of configuration * refactor: posts and blog * fix: replace mob * fix: broken link * fix: move app and clean-up * refactor: structure * fix: scripts * fix: bos-loader pulls from cargo * fix: links and replacements * feat: adds workflow to deploy to testnet (#305) * feat: adds workflow to deploy to testnet * fix: prettier * fix: build script * feature: devhub.testnet workflow * feat: creates dev script * feat: replaces release workflow * feat: adds weekly promotion of develop to main * fix: adds replacements for mainnet (#318) * Fix community posting (#308) * chore: Format * Fix community post button --------- Co-authored-by: Bo Yao * fix: main branch deploy action (#319) * fix: adds replacements for mainnet * fix: changes devhub.testnet to devhubtest.testnet * Improve search ux (#317) * big improvement on search ux * add search icon * feat: adds workflow to deploy to testnet * feat: creates dev script * refactor: structure clean up and fixes (#330) * fix: adds replacements for mainnet (#318) * Fix community posting (#308) * chore: Format * Fix community post button --------- Co-authored-by: Bo Yao * fix: main branch deploy action (#319) * fix: adds replacements for mainnet * fix: changes devhub.testnet to devhubtest.testnet * Improve search ux (#317) * big improvement on search ux * add search icon * fix: bos-loader pulls from cargo * fix: links and replacements * fix: formatting * fix: bos-loader pulls from cargo * feat: adds workflow to deploy to testnet (#305) * feat: adds workflow to deploy to testnet * fix: prettier * fix: build script * feature: devhub.testnet workflow * feat: creates dev script * feat: replaces release workflow * feat: adds weekly promotion of develop to main * fix: adds replacements for mainnet (#318) * Fix community posting (#308) * chore: Format * Fix community post button --------- Co-authored-by: Bo Yao * fix: main branch deploy action (#319) * fix: adds replacements for mainnet * fix: changes devhub.testnet to devhubtest.testnet * Improve search ux (#317) * big improvement on search ux * add search icon * feat: adds workflow to deploy to testnet * feat: creates dev script * refactor: rename to devhub * chore: removes hello * refactor: renames from DevHub to devhub references in code * fix: marks legacy and makes new feed test * feature: catches up to main * fix: formatting * feature: wrapped kanban and github wip * test: adds tests for community * fix: formatting * fix: bash explicit * fix: adds check for jq --------- Co-authored-by: Carina.Akaia.near Co-authored-by: Bo Yao * refactor: structure clean up and fixes (#330) * fix: adds replacements for mainnet (#318) * Fix community posting (#308) * chore: Format * Fix community post button --------- Co-authored-by: Bo Yao * fix: main branch deploy action (#319) * fix: adds replacements for mainnet * fix: changes devhub.testnet to devhubtest.testnet * Improve search ux (#317) * big improvement on search ux * add search icon * fix: bos-loader pulls from cargo * fix: links and replacements * fix: formatting * fix: bos-loader pulls from cargo * feat: adds workflow to deploy to testnet (#305) * feat: adds workflow to deploy to testnet * fix: prettier * fix: build script * feature: devhub.testnet workflow * feat: creates dev script * feat: replaces release workflow * feat: adds weekly promotion of develop to main * fix: adds replacements for mainnet (#318) * Fix community posting (#308) * chore: Format * Fix community post button --------- Co-authored-by: Bo Yao * fix: main branch deploy action (#319) * fix: adds replacements for mainnet * fix: changes devhub.testnet to devhubtest.testnet * Improve search ux (#317) * big improvement on search ux * add search icon * feat: adds workflow to deploy to testnet * feat: creates dev script * refactor: rename to devhub * chore: removes hello * refactor: renames from DevHub to devhub references in code * fix: marks legacy and makes new feed test * feature: catches up to main * fix: formatting * feature: wrapped kanban and github wip * test: adds tests for community * fix: formatting * fix: bash explicit * fix: adds check for jq --------- Co-authored-by: Carina.Akaia.near Co-authored-by: Bo Yao * refactor: moves over search post feature * refactor: converts legacy * refactor: replaces a with Link and separates out community card and spawner * refactor: simplfies configurator wip * fix: community configurator * feat: blog configuration * feat: improved configurator for wiki * feat: blog editor * fix: tag component * Website Redesign (#336) * Rebase to develop branch * fix: organize componnets according to atomic design * feat: Add hrefs to navlinks * fix: remove duplicate banner * fix: remove duplicate Navbar dropdown * fix: remove comments from app layout * feat: add visual indicator to navbar on selected link feat: adds deploy script fix: access control configurator fix: ids for addons fix: formatting fix: communities test * refactor: new devhub root and refactor of current app chore: removes homepage work chore: removes homepage from app.js fix: removes from contributing fix: cleans pull request fix: removes change to deploy-dev workflow step * feat: configures tests for different wallet connection scenarios fix: remove deploy fix: removes deploy script * fix: formatting * feat: adds community addon framework, wiki and telegram plugins * fix: formatting * test: bootstraps addon test wip * fix: formatting * test: modifies test criteria * feat: max length of 30 for a tab * fix: addon text and title * feat: adjustments to addons in configure community * feat: improves wiki plugin * fix: formatting * fix: tests * fix: tab type, padding, and preview buttons * fix: formatting --------- Co-authored-by: Thomas Co-authored-by: Bo Yao Co-authored-by: Carina.Akaia.near Co-authored-by: Zeeshan Ahmad --- playwright-tests/tests/addons.spec.js | 124 +++++++ playwright-tests/tests/search.spec.js | 1 + src/core/adapter/devhub-contract.jsx | 48 +-- src/devhub/components/molecule/Input.jsx | 99 ++++++ src/devhub/components/templates/AppLayout.jsx | 1 - .../entity/addon/telegram/Configurator.jsx | 117 +++++++ src/devhub/entity/addon/telegram/Viewer.jsx | 51 +++ src/devhub/entity/addon/wiki/Configurator.jsx | 163 +++++++++ src/devhub/entity/addon/wiki/Viewer.jsx | 52 +++ src/devhub/entity/community/Provider.jsx | 5 +- .../configuration/AddonsConfigurator.jsx | 323 ++++++++++++++++++ src/devhub/page/addon.jsx | 147 ++++++++ src/devhub/page/community/configuration.jsx | 40 ++- src/devhub/page/community/index.jsx | 21 +- 14 files changed, 1161 insertions(+), 31 deletions(-) create mode 100644 playwright-tests/tests/addons.spec.js create mode 100644 src/devhub/components/molecule/Input.jsx create mode 100644 src/devhub/entity/addon/telegram/Configurator.jsx create mode 100644 src/devhub/entity/addon/telegram/Viewer.jsx create mode 100644 src/devhub/entity/addon/wiki/Configurator.jsx create mode 100644 src/devhub/entity/addon/wiki/Viewer.jsx create mode 100644 src/devhub/entity/community/configuration/AddonsConfigurator.jsx create mode 100644 src/devhub/page/addon.jsx diff --git a/playwright-tests/tests/addons.spec.js b/playwright-tests/tests/addons.spec.js new file mode 100644 index 000000000..f740f1dc5 --- /dev/null +++ b/playwright-tests/tests/addons.spec.js @@ -0,0 +1,124 @@ +const { test, expect } = require("@playwright/test"); + +test.describe("Wallet is connected", () => { + test.use({ + storageState: "playwright-tests/storage-states/wallet-connected.json", + }); + + test.describe("AddonsConfigurator", () => { + const baseUrl = + "/devgovgigs.near/widget/app?page=community.configuration&handle=devhub-test"; + // const dropdownSelector = + // 'input[data-component="near/widget/DIG.InputSelect"]'; + // const addButtonSelector = "button.btn-success:has(i.bi.bi-plus)"; + // const toggleButtonSelector = 'button[role="switch"]'; + // const moveUpButtonSelector = "button.btn-secondary:has(i.bi.bi-arrow-up)"; + // const removeButtonSelector = + // "button.btn-outline-danger:has(i.bi.bi-trash-fill)"; + + test("Addons configuration section comes up on load", async ({ page }) => { + await page.goto(baseUrl); + + const addonsConfiguratorSelector = 'span:has-text("Add-Ons")'; + + await page.waitForSelector(addonsConfiguratorSelector, { + state: "visible", + }); + }); + }); +}); + +// NOTE: +// The below tests need some more work. +// We are using the DIG component, which is essentially a Radix Select field. +// Radix select renders as an input and requires to be focused, then value inputted, before the option can be selected. +// I was having trouble making this work. + +// test('Can add an addon to the list', async ({ page }) => { +// await page.goto(baseUrl); + +// await page.click(dropdownSelector); +// await page.fill(dropdownSelector, 'Wiki'); +// await page.click(`li:has-text('Wiki')`); + +// await page.waitForSelector(addButtonSelector, { +// state: "visible", +// }); + +// await page.click(addButtonSelector); + +// const addedAddon = await page.$('input[type="text"].form-control[disabled][value="Wiki"]'); // You will need to fill this in +// expect(addedAddon).toBeTruthy(); +// }); + +// test('Can reorder addons in the list', async ({ page }) => { +// await page.goto(baseUrl); + +// await page.click(dropdownSelector); +// await page.inputValue(dropdownSelector, 'Wiki'); +// await page.click(`li:has-text('Wiki')`); + +// await page.waitForSelector(addButtonSelector, { +// state: "visible", +// }); + +// await page.click(addButtonSelector); + +// await page.inputValue(dropdownSelector, 'telegram'); +// await page.click(addButtonSelector); + +// await page.waitForSelector(moveUpButtonSelector, { +// state: "visible", +// }); + +// await page.click(moveUpButtonSelector); + +// const firstAddon = await page.$('input[type="text"].form-control[disabled][value="Telegram"]'); +// const secondAddon = await page.$('input[type="text"].form-control[disabled][value="Wiki"]'); +// expect(firstAddon).toBeTruthy(); +// expect(secondAddon).toBeTruthy(); +// }); + +// test('Can remove an addon from the list', async ({ page }) => { +// await page.goto(baseUrl); + +// await page.inputValue(dropdownSelector, 'Wiki'); + +// await page.waitForSelector(addButtonSelector, { +// state: "visible", +// }); + +// await page.click(addButtonSelector); + +// await page.waitForSelector(removeButtonSelector, { +// state: "visible", +// }); + +// await page.click(removeButtonSelector); + +// const removedAddon = await page.$('input[type="text"].form-control[disabled][value="Wiki"]'); // You will need to fill this in +// expect(removedAddon).toBeNull(); +// }); + +// test('Can toggle to disable an addon', async ({ page }) => { +// await page.goto(baseUrl); + +// await page.inputValue(dropdownSelector, 'Wiki'); +// await page.waitForSelector(addButtonSelector, { +// state: "visible", +// }); + +// await page.click(addButtonSelector); + +// await page.waitForSelector(toggleButtonSelector, { +// state: "visible", +// }); + +// await page.click(toggleButtonSelector); + +// const toggleState = await page.getAttribute(toggleButtonSelector, 'aria-checked'); +// expect(toggleState).toBe('false'); +// }); +// }); + +// }); diff --git a/playwright-tests/tests/search.spec.js b/playwright-tests/tests/search.spec.js index 8e6cc5bf2..be967b90c 100644 --- a/playwright-tests/tests/search.spec.js +++ b/playwright-tests/tests/search.spec.js @@ -9,6 +9,7 @@ test("should show post history for posts in the feed", async ({ page }) => { state: "visible", }); await searchInput.fill("zero knowledge"); + await searchInput.press("Enter"); await page.waitForSelector('span:has-text("zero knowledge")', { state: "visible", diff --git a/src/core/adapter/devhub-contract.jsx b/src/core/adapter/devhub-contract.jsx index eb74d0f13..fbbac46d9 100644 --- a/src/core/adapter/devhub-contract.jsx +++ b/src/core/adapter/devhub-contract.jsx @@ -113,30 +113,30 @@ function getAvailableAddons() { configurator_widget: "${REPL_DEVHUB}/widget/devhub.entity.addon.telegram.Configurator", }, - { - id: "github", - title: "Github", - description: "Connect your github", - view_widget: "${REPL_DEVHUB}/widget/devhub.entity.addon.github.Viewer", - configurator_widget: - "${REPL_DEVHUB}/widget/devhub.entity.addon.github.Configurator", - }, - { - id: "kanban", - title: "Kanban", - description: "Connect your github kanban board", - view_widget: "${REPL_DEVHUB}/widget/devhub.entity.addon.kanban.Viewer", - configurator_widget: - "${REPL_DEVHUB}/widget/devhub.entity.addon.kanban.Configurator", - }, - { - id: "blog", - title: "Blog", - description: "Create a blog for your community", - view_widget: "${REPL_DEVHUB}/widget/devhub.entity.addon.blog.Viewer", - configurator_widget: - "${REPL_DEVHUB}/widget/devhub.entity.addon.blog.Configurator", - }, + // { + // id: "github", + // title: "Github", + // description: "Connect your github", + // view_widget: "${REPL_DEVHUB}/widget/devhub.entity.addon.github.Viewer", + // configurator_widget: + // "${REPL_DEVHUB}/widget/devhub.entity.addon.github.Configurator", + // }, + // { + // id: "kanban", + // title: "Kanban", + // description: "Connect your github kanban board", + // view_widget: "${REPL_DEVHUB}/widget/devhub.entity.addon.kanban.Viewer", + // configurator_widget: + // "${REPL_DEVHUB}/widget/devhub.entity.addon.kanban.Configurator", + // }, + // { + // id: "blog", + // title: "Blog", + // description: "Create a blog for your community", + // view_widget: "${REPL_DEVHUB}/widget/devhub.entity.addon.blog.Viewer", + // configurator_widget: + // "${REPL_DEVHUB}/widget/devhub.entity.addon.blog.Configurator", + // }, ]; // return Near.view("${REPL_DEVHUB_CONTRACT}", "get_available_addons") ?? null; } diff --git a/src/devhub/components/molecule/Input.jsx b/src/devhub/components/molecule/Input.jsx new file mode 100644 index 000000000..69b27c7e2 --- /dev/null +++ b/src/devhub/components/molecule/Input.jsx @@ -0,0 +1,99 @@ +const TextInput = ({ + className, + format, + inputProps: { className: inputClassName, ...inputProps }, + key, + label, + multiline, + onChange, + placeholder, + type, + value, + skipPaddingGap, + style, + ...otherProps +}) => { + const typeAttribute = + type === "text" || type === "password" || type === "number" ? type : "text"; + + const renderedLabels = [ + (label?.length ?? 0) > 0 ? ( + + {label} + + {inputProps.required ? * : null} + + ) : null, + + format === "markdown" ? ( + + ) : null, + + format === "comma-separated" ? ( + + {format} + + ) : null, + + (inputProps.max ?? null) !== null ? ( + {`${ + value?.length ?? 0 + } / ${inputProps.max}`} + ) : null, + ].filter((label) => label !== null); + + return ( +
+ {renderedLabels.length > 0 ? ( + + {renderedLabels.map((label) => label)} + + ) : null} + + {!multiline ? ( +
+ {inputProps.prefix && ( + {inputProps.prefix} + )} + +
+ ) : ( +