diff --git a/apps/astraplusplus/widget/Actions/UseInDao.jsx b/apps/astraplusplus/widget/Actions/UseInDao.jsx new file mode 100644 index 0000000..9a16a1d --- /dev/null +++ b/apps/astraplusplus/widget/Actions/UseInDao.jsx @@ -0,0 +1,173 @@ +const publicApiKey = "/*__@replace:pikespeakApiKey__*/"; +const templateId = props.templateId; +const accountId = context.accountId ?? ""; + +const [selectedDao, setSelectedDao] = useState(null); +const [toastMessage, setToastMessage] = useState(""); +const [modalOpen, setModalOpen] = useState(false); + +const forgeUrl = (apiUrl, params) => + apiUrl + + Object.keys(params) + .sort() + .reduce((paramString, p) => paramString + `${p}=${params[p]}&`, "?"); + +const daos = useCache( + () => + asyncFetch(forgeUrl(`https://api.pikespeak.ai/daos/members`, {}), { + mode: "cors", + headers: { + "x-api-key": publicApiKey + } + }).then((res) => { + return res.body[accountId]["daos"].map((dao) => ({ + contract_id: dao + })); + }), + "use-in-my-daos-" + accountId, + { subscribe: false } +); + +const Select = styled.select` + border: none; + background: transparent; + font-size: inherit; + color: inherit; + font-family: inherit; + font-weight: 500; + width: 100%; + border-radius: inherit; + padding: ${({ size }) => + size === "sm" ? "0 15px" : size === "lg" ? "0 23px" : "0 18px"}; + height: ${({ size }) => + size === "sm" ? "32px" : size === "lg" ? "40px" : "36px"}; + + option { + font-size: inherit; + color: inherit; + font-family: inherit; + font-weight: 500; + } +`; + +function onSave() { + const publicKey = ""; + const signature = ""; + if (selectedDao && templateId) { + const buff = Buffer.from(`${accountId}|${publicKey}|${signature}`); + asyncFetch( + `https://api.app.astrodao.com/api/v1/proposals/templates/${templateId}/clone/${selectedDao}`, + { + method: "POST", + headers: { + Authorization: `Bearer ${buff.toString("base64")}` + }, + body: JSON.stringify({ + templateId: templateId, + targetDao: selectedDao + }) + } + ) + .then((res) => { + console.log("res:", res); + setToastMessage("Templated saved to your DAO."); + setModalOpen(false); + }) + .catch((err) => { + console.log("err:", err); + setToastMessage("Error occured, Please try again later."); + setModalOpen(false); + }); + } +} + +useEffect(() => { + let timeoutId; + + if (toastMessage) { + timeoutId = setTimeout(() => { + setToastMessage(""); + }, 2000); + } + + return () => { + clearTimeout(timeoutId); + }; +}, [toastMessage]); + +return ( + <> + + + +

Actions Library

+ + {daos.length > 0 ? ( +
+ + +
+ +
+
+ ) : ( + "Sorry, you are not a member of any DAO council." + )} + + ), + toggle: ( + setModalOpen(true) + }} + /> + ) + }} + /> + +); diff --git a/apps/astraplusplus/widget/Actions/ViewAction.jsx b/apps/astraplusplus/widget/Actions/ViewAction.jsx new file mode 100644 index 0000000..22b54e4 --- /dev/null +++ b/apps/astraplusplus/widget/Actions/ViewAction.jsx @@ -0,0 +1,252 @@ +const { router, id } = props; +const actionLink = `#//*__@appAccount__*//widget/home?page=actions`; + +const res = fetch( + `https://api.app.astrodao.com/api/v1/proposals/templates?filter[0]=id||$eq||${id}&limit=1000&offset=0&join=daos||id` +); +const url = `https://near.org//*__@appAccount__*//widget/home?page=dao&tab=action&id=${id}`; + +const twitterURL = new URL("https://twitter.com/intent/tweet"); +twitterURL.searchParams.append("text", "Sharing a DAO template from Astra++"); +twitterURL.searchParams.append("url", url); + +const telegramURL = new URL("https://t.me/share/url"); +telegramURL.searchParams.append("url", url); +telegramURL.searchParams.append("text", "Sharing a DAO template from Astra++"); +const [isExpanded, setIsExpanded] = useState(false); +const [copied, setCopied] = useState(false); + +const socialMedia = [ + { + name: "Share", + link: url.toString(), + icon: "bi bi-share", + copyLink: true + }, + { + name: "Twitter", + link: twitterURL.toString(), + icon: "bi bi-twitter" + }, + + { + name: "Telegram", + link: telegramURL.toString(), + icon: "bi bi-telegram" + } +]; + +const Wrapper = styled.div` + .social_button { + height: 2.5em; + width: 2.5em; + border-radius: 0.5rem; + color: #4498e0; + border: 1px solid #4498e0; + transition: all 200ms ease; + text-decoration: none; + display: flex; + justify-content: center; + align-items: center; + font-size: 16px; + } + + .text-sm { + font-size: 13px; + } + + .flex-3 { + flex: 3; + } + + .flex-2 { + flex: 2; + } + + .flex-1 { + flex: 1; + } + + .gap-6 { + gap: 3.5rem; + } + + label { + color: #828688; + margin-bottom: 0.5rem; + } +`; + +useEffect(() => { + let timeoutId; + + if (copied) { + timeoutId = setTimeout(() => { + setCopied(false); + }, 2000); + } + + return () => { + clearTimeout(timeoutId); + }; +}, [copied]); + +const copyToClipboard = (link) => { + clipboard.writeText(link); + setCopied(true); +}; + +const data = res?.body?.data?.[0]; + +return ( + + + { + router.navigate({ + page: "actions" + }); + }} + > + + Back to Actions Library + + {res === null || !Array.isArray(res.body.data) ? ( + + ) : ( +
+
+
+

{data?.name}

+
{data?.createdBy}
+
+
+ {socialMedia.map((item, index) => + item.copyLink ? ( +
copyToClipboard(item.link)} + > + +
+ ) : ( + + + + ) + )} + +
+
+
+
+ +
+ {Array.isArray(data?.daos) && + data.daos.map(({ id }) => ( + + {id} + + ))} +
+
+
+
+
+
+
+ +
{data.name}
+
+
+
+ +
+ {data.config.smartContractAddress} +
+
+
+ +
{data.config.methodName}
+
+
+
+
+ +
{data.description}
+
+
+ +
+ {Big(data.config.actionsGas) + .div(Big(10).pow(12)) + .toFixed()} +
+
+
+
+
+
JSON
+ + View More{" "} + {isExpanded ? ( + + ) : ( + + )} + + ), + variant: "info", + size: "md", + onClick: (e) => { + setIsExpanded(!isExpanded); + } + }} + /> +
+ {isExpanded && ( +
+ {data.config.json} +
+ )} +
+
+
+
+
+ )} +
+); diff --git a/apps/astraplusplus/widget/Actions/index.jsx b/apps/astraplusplus/widget/Actions/index.jsx index f9c6f27..787aa82 100644 --- a/apps/astraplusplus/widget/Actions/index.jsx +++ b/apps/astraplusplus/widget/Actions/index.jsx @@ -1 +1,261 @@ -return
Page Under Development
; +const { router } = props; + +const sortList = [ + { + label: "Newest", + value: "createdAt,DESC" + }, + { + label: "Oldest", + value: "createdAt,ASC" + } +]; + +const [searchTerm, setSearch] = useState(null); +const [isFiltersOpen, setFiltersOpen] = useState(false); +const [currentPage, setCurrentPage] = useState(0); +const [selectedSort, setSelectedSort] = useState(sortList[0].value); + +const resPerPage = 20; + +const forgeUrl = (params) => { + let url = "https://api.app.astrodao.com/api/v1/proposals/templates?"; + Object.entries(params).forEach(([key, value]) => { + let paramValue = value; + if (key === "s") { + paramValue = encodeURIComponent(JSON.stringify(value)); + } else if (key === "sort") { + paramValue = encodeURIComponent(value); + } + if (paramValue !== undefined && paramValue !== null && paramValue !== "") { + url += `${key}=${paramValue}&`; + } + }); + return url; +}; + +const res = fetch( + forgeUrl({ + offset: currentPage * resPerPage, + limit: resPerPage, + join: "daos||id", + sort: selectedSort, + s: { $and: [{ name: { $contL: searchTerm || "" } }] } + }) +); + +const Wrapper = styled.div` + table { + overflow-x: auto; + font-size: 14px; + width: 100%; + box-sizing: border-box; + } + + @media screen and (max-width: 1000px) { + table { + display: block; + } + } + + th, + td { + padding: 10px; + text-align: left; + } + + tr { + border-bottom: 1px solid lightgray; + } + + thead { + border-bottom: 2px solid #4498e0; + font-size: 16px; + } + + .icons-color i { + color: #4498e0; + } + + .text-sm { + font-size: 12px; + } + + .font-weight-bold { + font-weight: bold; + } + + .text-primary { + color: #4498e0 !important; + } + + .selected { + background-color: #4498e0 !important; + color: white !important; + } + + .pointer-cursor { + cursor: pointer; + } + + .data-row { + border-bottom: 1px solid lightgray; + display: table-row; + color: inherit; + text-decoration: none; + } + + .data-row:hover { + background-color: #f5f5f5; + } +`; + +const actionLink = ({ id }) => { + return `#//*__@appAccount__*//widget/home?page=action&id=${id}`; +}; + +return ( + +

Actions Library

+

+ Add new functionality and power up your workflow with these templates. +

+
+ + ) + }} + /> + + Sort:{" "} + {sortList.find((item) => item.value === selectedSort).label}{" "} + + + ), + variant: "info outline ", + size: "md" + }} + /> + ), + content: ( + {}, + applyView: (sort) => { + setSelectedSort(sort); + }, + selectedView: selectedSort + }} + /> + ) + }} + /> +
+ {res === null || !Array.isArray(res.body.data) ? ( + + ) : ( +
+ + + + + + + + + + {res.body.data.map((item) => { + const address = item.config.smartContractAddress; + return ( + { + e.stopPropagation(); + router.navigate({ + page: "action", + id: address + }); + }} + > + + + + + ); + })} + +
NameSmart Contracts
+
+
{item.name}
+

{item.description}

+
+
+ + +
{ + e.preventDefault(); + e.stopPropagation(); + }} + > + +
+
+
+ { + setCurrentPage(page); + }, + revaluateOnRender: true + }} + /> +
+
+ )} +
+); diff --git a/apps/astraplusplus/widget/home.jsx b/apps/astraplusplus/widget/home.jsx index c51e6e7..9411b64 100644 --- a/apps/astraplusplus/widget/home.jsx +++ b/apps/astraplusplus/widget/home.jsx @@ -1,292 +1,300 @@ const CoADaoId = props.dev - ? "/*__@replace:CoADaoIdTesting__*/" - : "/*__@replace:CoADaoId__*/"; + ? "/*__@replace:CoADaoIdTesting__*/" + : "/*__@replace:CoADaoId__*/"; const VotingBodyDaoId = props.dev - ? "/*__@replace:VotingBodyDaoIdTesting__*/" - : "/*__@replace:VotingBodyDaoId__*/"; + ? "/*__@replace:VotingBodyDaoIdTesting__*/" + : "/*__@replace:VotingBodyDaoId__*/"; const TCDaoId = props.dev - ? "/*__@replace:TCDaoIdTesting__*/" - : "/*__@replace:TCDaoId__*/"; + ? "/*__@replace:TCDaoIdTesting__*/" + : "/*__@replace:TCDaoId__*/"; const HoMDaoId = props.dev - ? "/*__@replace:HoMDaoIdTesting__*/" - : "/*__@replace:HoMDaoId__*/"; + ? "/*__@replace:HoMDaoIdTesting__*/" + : "/*__@replace:HoMDaoId__*/"; let { page, tab, daoId, house } = props; if (!page) { - page = "home"; + page = "home"; } const currentLink = "#//*__@appAccount__*//widget/home"; State.init({ - activePage: page, - activeTab: tab, - activeDaoId: daoId + activePage: page, + activeTab: tab, + activeDaoId: daoId }); if ( - page !== state.activePage || - tab !== state.activeTab || - daoId !== state.activeDaoId + page !== state.activePage || + tab !== state.activeTab || + daoId !== state.activeDaoId ) { - State.update({ - activePage: page, - activeTab: tab, - activeDaoId: daoId - }); + State.update({ + activePage: page, + activeTab: tab, + activeDaoId: daoId + }); } page = state.activePage; const router = { - params: { page, tab, daoId, house }, - navigate: (newParams) => { - router.params = { - ...newParams - }; - State.update({ - activePage: router.params.page, - activeTab: router.params.tab, - activeDaoId: router.params.daoId - }); - } + params: { page, tab, daoId, house }, + navigate: (newParams) => { + router.params = { + ...newParams + }; + State.update({ + activePage: router.params.page, + activeTab: router.params.tab, + activeDaoId: router.params.daoId + }); + } }; const pages = [ - [ - { - title: "Home", - icon: , - active: page.split("-")[0] === "home", - href: currentLink + "?page=home", - onClick: () => router.navigate({ page: "home" }), - widgetName: "Feed.index", - defaultProps: {} - }, - { - title: "Social feed", - active: page === "home", - href: currentLink + "?page=home", - onClick: () => router.navigate({ page: "home" }), - widgetName: "Feed.index", - defaultProps: {} - }, - { - title: "My proposals", - active: page === "my-proposals", - href: currentLink + "?page=my-proposals", - onClick: () => router.navigate({ page: "my-proposals" }), - widgetName: "MyProposals.index", - defaultProps: {} - } - ], - [ - { - title: "Government", - icon: , - active: page.split("-")[0] === "congress", - href: currentLink + "?page=congress", - onClick: () => router.navigate({ page: "congress" }), - widgetName: "Congress.index" - }, - { - title: "HoM", - active: page === "congress" && router.params.house === "hom", - href: currentLink + `?page=congress&house=hom`, - onClick: () => router.navigate({ page: "congress", house: "hom" }), - widgetName: "DAO.index" - }, - { - title: "CoA", - active: page === "congress" && router.params.house === "coa", - href: currentLink + `?page=congress&house=coa`, - onClick: () => router.navigate({ page: "congress", house: "coa" }), - widgetName: "DAO.index" - }, - { - title: "TC", - active: page === "congress" && router.params.house === "tc", - href: currentLink + `?page=congress&house=tc`, - onClick: () => router.navigate({ page: "congress", house: "tc" }), - widgetName: "DAO.index" - }, - { - title: "Voting Body", - active: page === "congress" && router.params.house === "vb", - href: currentLink + `?page=congress&house=vb`, - onClick: () => router.navigate({ page: "congress", house: "vb" }), - widgetName: "DAO.index" - } - ], - [ - { - title: "DAOs", - icon: , - active: page === "daos", - href: currentLink + "?page=daos", - onClick: () => router.navigate({ page: "daos" }), - widgetName: "DAOs.index", - defaultProps: {} - }, - { - title: "My DAOs", - active: page === "my-daos", - href: currentLink + "?page=my-daos", - widgetName: "DAOs.index", - onClick: () => router.navigate({ page: "my-daos" }), - defaultProps: { - filter: "myDAOs" - } - }, - { - title: "Following", - active: page === "daos-following", - href: currentLink + "?page=daos-following", - widgetName: "DAOs.index", - onClick: () => router.navigate({ page: "daos-following" }), - defaultProps: { - filter: "followedDAOs" - } - }, - { - title: "All", - active: page === "daos", - href: currentLink + "?page=daos", - widgetName: "DAOs.index", - onClick: () => router.navigate({ page: "daos" }), - defaultProps: {} - } - ], + [ + { + title: "Home", + icon: , + active: page.split("-")[0] === "home", + href: currentLink + "?page=home", + onClick: () => router.navigate({ page: "home" }), + widgetName: "Feed.index", + defaultProps: {} + }, { - title: "Community Voice", - icon: , - active: page === "communityVoice", - href: currentLink + "?page=communityVoice", - onClick: () => router.navigate({ page: "communityVoice" }), - widgetName: "CommunityVoice", - defaultProps: {} + title: "Social feed", + active: page === "home", + href: currentLink + "?page=home", + onClick: () => router.navigate({ page: "home" }), + widgetName: "Feed.index", + defaultProps: {} }, { - title: "Actions library", - icon: , - active: page === "actions", - href: currentLink + "?page=actions", - onClick: () => router.navigate({ page: "actions" }), - widgetName: "Actions.index" + title: "My proposals", + active: page === "my-proposals", + href: currentLink + "?page=my-proposals", + onClick: () => router.navigate({ page: "my-proposals" }), + widgetName: "MyProposals.index", + defaultProps: {} + } + ], + [ + { + title: "Government", + icon: , + active: page.split("-")[0] === "congress", + href: currentLink + "?page=congress", + onClick: () => router.navigate({ page: "congress" }), + widgetName: "Congress.index" }, { - title: "Create DAO", - active: page === "create-dao", - href: currentLink + "?page=create-dao", - onClick: () => router.navigate({ page: "create-dao" }), - widgetName: "CreateDAO.index", - hidden: true + title: "HoM", + active: page === "congress" && router.params.house === "hom", + href: currentLink + `?page=congress&house=hom`, + onClick: () => router.navigate({ page: "congress", house: "hom" }), + widgetName: "DAO.index" }, { - title: "DAO", - active: page === "dao", - href: currentLink + "?page=dao", - onClick: (daoId, tab) => router.navigate({ page: "dao", daoId, tab }), - widgetName: "DAO.index", - hidden: true + title: "CoA", + active: page === "congress" && router.params.house === "coa", + href: currentLink + `?page=congress&house=coa`, + onClick: () => router.navigate({ page: "congress", house: "coa" }), + widgetName: "DAO.index" }, { - title: "Voting History", - active: page === "votinghistory", - href: currentLink + "?page=votinghistory", - onClick: (daoId, tab) => router.navigate({ page: "votinghistory" }), - widgetName: "VotingHistory.index", - hidden: true + title: "TC", + active: page === "congress" && router.params.house === "tc", + href: currentLink + `?page=congress&house=tc`, + onClick: () => router.navigate({ page: "congress", house: "tc" }), + widgetName: "DAO.index" + }, + { + title: "Voting Body", + active: page === "congress" && router.params.house === "vb", + href: currentLink + `?page=congress&house=vb`, + onClick: () => router.navigate({ page: "congress", house: "vb" }), + widgetName: "DAO.index" } + ], + [ + { + title: "DAOs", + icon: , + active: page === "daos", + href: currentLink + "?page=daos", + onClick: () => router.navigate({ page: "daos" }), + widgetName: "DAOs.index", + defaultProps: {} + }, + { + title: "My DAOs", + active: page === "my-daos", + href: currentLink + "?page=my-daos", + widgetName: "DAOs.index", + onClick: () => router.navigate({ page: "my-daos" }), + defaultProps: { + filter: "myDAOs" + } + }, + { + title: "Following", + active: page === "daos-following", + href: currentLink + "?page=daos-following", + widgetName: "DAOs.index", + onClick: () => router.navigate({ page: "daos-following" }), + defaultProps: { + filter: "followedDAOs" + } + }, + { + title: "All", + active: page === "daos", + href: currentLink + "?page=daos", + widgetName: "DAOs.index", + onClick: () => router.navigate({ page: "daos" }), + defaultProps: {} + } + ], + { + title: "Community Voice", + icon: , + active: page === "communityVoice", + href: currentLink + "?page=communityVoice", + onClick: () => router.navigate({ page: "communityVoice" }), + widgetName: "CommunityVoice", + defaultProps: {} + }, + { + title: "Actions library", + icon: , + active: page === "actions", + href: currentLink + "?page=actions", + onClick: () => router.navigate({ page: "actions" }), + widgetName: "Actions.index" + }, + { + title: "Create DAO", + active: page === "create-dao", + href: currentLink + "?page=create-dao", + onClick: () => router.navigate({ page: "create-dao" }), + widgetName: "CreateDAO.index", + hidden: true + }, + { + title: "DAO", + active: page === "dao", + href: currentLink + "?page=dao", + onClick: (daoId, tab) => router.navigate({ page: "dao", daoId, tab }), + widgetName: "DAO.index", + hidden: true + }, + { + title: "Voting History", + active: page === "votinghistory", + href: currentLink + "?page=votinghistory", + onClick: (daoId, tab) => router.navigate({ page: "votinghistory" }), + widgetName: "VotingHistory.index", + hidden: true + }, + { + title: "Action", + active: page === "action", + href: currentLink + "?page=action", + onClick: (id) => router.navigate({ page: "action", id: id }), + widgetName: "Actions.ViewAction", + hidden: true + } ]; let activePage = null; pages.find((page) => { - if (Array.isArray(page)) { - return page.find((subPage) => { - if (subPage.active) { - activePage = subPage; - return true; - } - return false; - }); - } - if (page.active) { - activePage = page; + if (Array.isArray(page)) { + return page.find((subPage) => { + if (subPage.active) { + activePage = subPage; return true; - } - return false; + } + return false; + }); + } + if (page.active) { + activePage = page; + return true; + } + return false; }); const pageContent = activePage ? ( - + ) : ( - "404" + "404" ); const Root = styled.div` - font-family: - "Open Sans", - "Manrope", - system-ui, - -apple-system, - "Segoe UI", - Roboto, - "Helvetica Neue", - "Noto Sans", - "Liberation Sans", - Arial, - sans-serif, - "Apple Color Emoji", - "Segoe UI Emoji", - "Segoe UI Symbol", - "Noto Color Emoji"; - font-size: 16px; - line-height: 1.5; + font-family: + "Open Sans", + "Manrope", + system-ui, + -apple-system, + "Segoe UI", + Roboto, + "Helvetica Neue", + "Noto Sans", + "Liberation Sans", + Arial, + sans-serif, + "Apple Color Emoji", + "Segoe UI Emoji", + "Segoe UI Symbol", + "Noto Color Emoji"; + font-size: 16px; + line-height: 1.5; + color: #000; + + a { color: #000; + text-decoration: none; + } - a { - color: #000; - text-decoration: none; - } + a:hover { + color: #4498e0; + } - a:hover { - color: #4498e0; - } - - .ndc-card { - border-radius: 16px; - box-shadow: - rgba(0, 0, 0, 0.1) 0 1px 3px, - rgba(0, 0, 0, 0.05) 0 1px 20px; - background-color: #fff; - } + .ndc-card { + border-radius: 16px; + box-shadow: + rgba(0, 0, 0, 0.1) 0 1px 3px, + rgba(0, 0, 0, 0.05) 0 1px 20px; + background-color: #fff; + } `; return ( - - + + - - {activePage.widgetName === "Congress.index" ? ( -
{pageContent}
- ) : ( -
- {pageContent} -
- )} -
+ + {activePage.widgetName === "Congress.index" ? ( +
{pageContent}
+ ) : ( +
+ {pageContent} +
+ )} +
);