From a15a670b90522f9bc919dd0449c42960fe2893cb Mon Sep 17 00:00:00 2001 From: Elliot Braem <16282460+elliotBraem@users.noreply.github.com> Date: Mon, 22 Jan 2024 23:13:38 -0500 Subject: [PATCH 001/132] init --- apps/bos-blocks/bos.config.json | 3 + apps/bos-blocks/widget/Compose.jsx | 99 +++++++ apps/bos-blocks/widget/Feed.jsx | 89 ++++++ apps/bos-blocks/widget/Library.jsx | 270 ++++++++++++++++++ .../widget/PR/FilteredIndexFeed.jsx | 11 + apps/bos-blocks/widget/PR/IndexFeed.jsx | 192 +++++++++++++ apps/bos-blocks/widget/PR/MergedIndexFeed.jsx | 259 +++++++++++++++++ apps/bos-blocks/widget/Router.jsx | 72 +++++ apps/builddao/widget/app.jsx | 82 ++++++ apps/builddao/widget/config.jsx | 32 +++ apps/builddao/widget/page/feed.jsx | 49 ++++ apps/builddao/widget/page/home.jsx | 1 + src/App.js | 31 +- src/pages/Viewer.js | 74 +++++ 14 files changed, 1256 insertions(+), 8 deletions(-) create mode 100644 apps/bos-blocks/bos.config.json create mode 100644 apps/bos-blocks/widget/Compose.jsx create mode 100644 apps/bos-blocks/widget/Feed.jsx create mode 100644 apps/bos-blocks/widget/Library.jsx create mode 100644 apps/bos-blocks/widget/PR/FilteredIndexFeed.jsx create mode 100644 apps/bos-blocks/widget/PR/IndexFeed.jsx create mode 100644 apps/bos-blocks/widget/PR/MergedIndexFeed.jsx create mode 100644 apps/bos-blocks/widget/Router.jsx create mode 100644 apps/builddao/widget/app.jsx create mode 100644 apps/builddao/widget/config.jsx create mode 100644 apps/builddao/widget/page/feed.jsx create mode 100644 apps/builddao/widget/page/home.jsx create mode 100644 src/pages/Viewer.js diff --git a/apps/bos-blocks/bos.config.json b/apps/bos-blocks/bos.config.json new file mode 100644 index 00000000..25f7b186 --- /dev/null +++ b/apps/bos-blocks/bos.config.json @@ -0,0 +1,3 @@ +{ + "appAccount": "devs.near" +} \ No newline at end of file diff --git a/apps/bos-blocks/widget/Compose.jsx b/apps/bos-blocks/widget/Compose.jsx new file mode 100644 index 00000000..203c52cf --- /dev/null +++ b/apps/bos-blocks/widget/Compose.jsx @@ -0,0 +1,99 @@ +if (!context.accountId) { + return ""; +} + +const index = props.index || { + post: JSON.stringify({ + key: "main", + value: { + type: "md", + }, + }), +}; + +const composeData = () => { + if (props.appendHashtags) { + state.content.text = props.appendHashtags(state.content.text); + } + const data = { + post: { + main: JSON.stringify(state.content), + }, + index, + }; + + const item = { + type: "social", + path: `${context.accountId}/post/main`, + }; + + const notifications = state.extractMentionNotifications( + state.content.text, + item + ); + + if (notifications.length) { + data.index.notify = JSON.stringify( + notifications.length > 1 ? notifications : notifications[0] + ); + } + + const hashtags = state.extractHashtags(state.content.text); + + if (hashtags.length) { + data.index.hashtag = JSON.stringify( + hashtags.map((hashtag) => ({ + key: hashtag, + value: item, + })) + ); + } + + return data; +}; + +State.init({ + onChange: ({ content }) => { + State.update({ content }); + }, +}); + +return ( + <> +
+ { + State.update({ extractMentionNotifications, extractHashtags }); + }, + composeButton: (onCompose) => ( + { + onCompose(); + }} + > + Post + + ), + }} + /> +
+ {state.content && ( + + )} + +); diff --git a/apps/bos-blocks/widget/Feed.jsx b/apps/bos-blocks/widget/Feed.jsx new file mode 100644 index 00000000..f252659e --- /dev/null +++ b/apps/bos-blocks/widget/Feed.jsx @@ -0,0 +1,89 @@ +const Feed = ({ index, typeWhitelist, Item, Layout, showCompose }) => { + Item = Item || ((props) =>
{JSON.stringify(props)}
); + Layout = Layout || (({ children }) => children); + + const renderItem = (a, i) => { + if (typeWhitelist && !typeWhitelist.includes(a.value.type)) { + return false; + } + return ( +
+ +
+ ); + }; + + const composeIndex = () => { + const arr = Array.isArray(index) ? index : [index]; + + const grouped = arr.reduce((acc, i) => { + if (i.action !== "repost") { + if (!acc[i.action]) { + acc[i.action] = []; + } + acc[i.action].push({ key: i.key, value: { type: "md" } }); + } + return acc; + }, {}); + + Object.keys(grouped).forEach((action) => { + if (grouped[action].length === 1) { + grouped[action] = grouped[action][0]; + } + grouped[action] = JSON.stringify(grouped[action]); + }); + + return grouped; + }; + + const appendHashtags = (v) => { + const arr = Array.isArray(index) ? index : [index]; + const hashtags = arr + .filter((i) => i.action === "hashtag") + .map((i) => i.key); + + hashtags.forEach((hashtag) => { + if (v.toLowerCase().includes(`#${hashtag.toLowerCase()}`)) return; + else v += ` #${hashtag}`; + }); + + return v; + }; + + return ( + <> + {showCompose && ( + + )} + {Array.isArray(index) ? ( + {children}, + }} + /> + ) : ( + {children}, + }} + /> + )} + + ); +}; + +return { Feed }; diff --git a/apps/bos-blocks/widget/Library.jsx b/apps/bos-blocks/widget/Library.jsx new file mode 100644 index 00000000..c164e5b9 --- /dev/null +++ b/apps/bos-blocks/widget/Library.jsx @@ -0,0 +1,270 @@ +/** + * This is just a direct copy of mob.near/widget/N.Library + */ +const accountId = context.accountId || "root.near"; +const authorId = "mob.near"; + +const itemDescription = + 'The identifier item. It will be used as a unique identifier of the entity that receives the action. It\'s also used as a key of the action in the index.\nThe item should be an object with the following keys: `type`, `path` and optional `blockHeight`.\n- `type`: If the data is stored in the social DB, then the type is likely `"social"`, other types can be defined in the standards.\n- `path`: The path to the item. For a `"social"` type, it\'s absolute path within SocialDB, e.g. `alice.near/post/main`.\n- `blockHeight`: An optional paremeter to indicate the block when the data was stored. Since SocialDB data can be overwritten to save storage, the exact data should be referenced by the block height (e.g. for a given post). But if the latest data should be used, then `blockHeight` should be ommited.\n\nExamples of `item`:\n- `{type: "social", path: "mob.near/widget/N.Library"}`\n- `{type: "social", path: "mob.near/post/main", blockHeight: 81101335}`\n'; + +const components = [ + { + title: "Feed", + // category: "Profile", + widgetName: "Feed", + description: + "", + // demoProps: { accountId }, + // requiredProps: { + // accountId: "The account ID of the profile", + // }, + // optionalProps: { + // profile: "Object that holds profile information to display", + // fast: "Render profile picture faster using external cache, default true if the `props.profile` is not provided", + // hideDescription: "Don't show description, default false", + // }, + }, + { + title: "Context Menu", + // category: "Profile", + widgetName: "ContextMenu", + description: + "", + // demoProps: { accountId, tooltip: true }, + // requiredProps: { + // accountId: "The account ID of the profile", + // }, + // optionalProps: { + // profile: "Object that holds profile information to display", + // fast: "Render profile picture faster using external cache, default true if the `props.profile` is not provided", + // tooltip: + // "Display overlay tooltip when you hover over the profile, default false", + // }, + }, + { + title: "Router", + // category: "Profile", + widgetName: "Router", + description: + "", + // demoProps: { accountId, tooltip: true }, + // requiredProps: { + // accountId: "The account ID of the profile", + // }, + // optionalProps: { + // link: "Whether to make profile clickable with a link to the profile page, default true.", + // hideAccountId: "Don't show account ID, default false", + // hideName: "Don't show profile name, default false", + // hideImage: "Don't show profile picture, default false", + // hideCheckmark: "Don't show premium checkmark, default false", + // profile: "Object that holds profile information to display", + // fast: "Render profile picture faster using external cache, default true if the `props.profile` is not provided", + // title: + // 'Optional title when you hover over the profile. Default `"${name} ${accountId}"`', + // tooltip: + // "Display overlay tooltip or title when you hover over the profile, default false. Will display a custom title if tooltip is given. If tooltip is true, the full tooltip is displayed. Default false", + // }, + }, +]; + +const renderProps = (props, optional) => { + return Object.entries(props || {}).map(([key, desc]) => { + return ( + + + + {key} + + + + + + + ); + }); +}; + +const renderComponent = (c, i) => { + const widgetSrc = `${authorId}/widget/${c.widgetName}`; + const embedCode = ` ` ${s}`) + .join("\n")}}}\n/>\n`; + const id = c.title.toLowerCase().replaceAll(" ", "-"); + return ( +
+
+ +

{c.title}

+
+

{c.description}

+ +
+ +
+ +
+
+ +
+ +
+ + + + + + + + + + {renderProps(c.requiredProps)} + {renderProps(c.optionalProps, true)} + +
KeyDescription
+ +
+ +
+ +
+
+
+ ); +}; + +const renderMenuItem = (c, i) => { + const prev = i ? components[i - 1] : null; + const res = []; + if (!prev || prev.category !== c.category) { + res.push( +
+ {c.category} +
+ ); + } + const id = c.title.toLowerCase().replaceAll(" ", "-"); + res.push( +
+ {c.title} +
+ ); + return res; +}; + +const Wrapper = styled.div` +@media(min-width: 992px) { + .b-s { + border-left: 1px solid #eee; + } + .b-e { + border-right: 1px solid #eee; + } +} +.category:not(:first-child) { + margin-top: 1em; +} +.component { + padding: 0.5em 12px; + padding-bottom: 0; + margin-bottom: 3em; + margin: 0 -12px 3em; + position: relative; + + &:hover { + background: rgba(0, 0, 0, 0.03); + } + + .anchor { + position: absolute; + top: -70px; + } + + table { + background: white; + } + + label { + font-size: 20px; + } + + .code { + display: inline-flex; + line-height: normal; + border-radius: 0.3em; + padding: 0 4px; + border: 1px solid #ddd; + background: rgba(0, 0, 0, 0.03); + font-family: var(--bs-font-monospace); + } + .path { + + } + .preview { + background-color: white; + padding: 12px; + border: 1px solid #eee; + border-radius: 12px; + pre { + margin-bottom: 0; + } + } + .props { + .prop-key { + font-weight: 600; + &.optional { + font-weight: normal; + } + } + .prop-desc { + p { + margin-bottom: 0; + } + } + } + .embed-code { + position: relative; + + .embed-copy { + position: absolute; + top: 18px; + right: 10px; + } + } +} +`; + +return ( + +

Social Components Library

+
+ This library contains common social components used by near.social +
+
+
{components.map(renderMenuItem)}
+
{components.map(renderComponent)}
+
+
+); \ No newline at end of file diff --git a/apps/bos-blocks/widget/PR/FilteredIndexFeed.jsx b/apps/bos-blocks/widget/PR/FilteredIndexFeed.jsx new file mode 100644 index 00000000..4decaa9f --- /dev/null +++ b/apps/bos-blocks/widget/PR/FilteredIndexFeed.jsx @@ -0,0 +1,11 @@ +const filter = context.accountId && { + ignore: Social.getr(`${context.accountId}/graph/hide`), +}; + +return ( + +); \ No newline at end of file diff --git a/apps/bos-blocks/widget/PR/IndexFeed.jsx b/apps/bos-blocks/widget/PR/IndexFeed.jsx new file mode 100644 index 00000000..651bc880 --- /dev/null +++ b/apps/bos-blocks/widget/PR/IndexFeed.jsx @@ -0,0 +1,192 @@ +const index = JSON.parse(JSON.stringify(props.index)); +if (!index) { + return "props.index is not defined"; +} + +const filter = props.filter; + +const renderItem = + props.renderItem ?? + ((item, i) => ( +
+ #{item.blockHeight}: {JSON.stringify(item)} +
+ )); +const cachedRenderItem = (item, i) => { + const key = JSON.stringify(item); + + if (!(key in state.cachedItems)) { + state.cachedItems[key] = renderItem(item, i); + State.update(); + } + return state.cachedItems[key]; +}; + +index.options = index.options || {}; +const initialRenderLimit = + props.initialRenderLimit ?? index.options.limit ?? 10; +const addDisplayCount = props.nextLimit ?? initialRenderLimit; + +index.options.limit = Math.min( + Math.max(initialRenderLimit + addDisplayCount * 2, index.options.limit ?? 0), + 100 +); +const reverse = !!props.reverse; + +const initialItems = Social.index(index.action, index.key, index.options); +if (initialItems === null) { + return ""; +} + +const computeFetchFrom = (items, limit) => { + if (!items || items.length < limit) { + return false; + } + const blockHeight = items[items.length - 1].blockHeight; + return index.options.order === "desc" ? blockHeight - 1 : blockHeight + 1; +}; + +const mergeItems = (newItems) => { + const items = [ + ...new Set([...newItems, ...state.items].map((i) => JSON.stringify(i))), + ].map((i) => JSON.parse(i)); + items.sort((a, b) => a.blockHeight - b.blockHeight); + if (index.options.order === "desc") { + items.reverse(); + } + return items; +}; + +const jInitialItems = JSON.stringify(initialItems); +if (state.jInitialItems !== jInitialItems) { + const jIndex = JSON.stringify(index); + const nextFetchFrom = computeFetchFrom(initialItems, index.options.limit); + if (jIndex !== state.jIndex || nextFetchFrom !== state.initialNextFetchFrom) { + State.update({ + jIndex, + jInitialItems, + items: initialItems, + fetchFrom: false, + initialNextFetchFrom: nextFetchFrom, + nextFetchFrom, + displayCount: initialRenderLimit, + cachedItems: {}, + }); + } else { + State.update({ + jInitialItems, + items: mergeItems(initialItems), + }); + } +} + +if (state.fetchFrom) { + const limit = addDisplayCount; + const newItems = Social.index( + index.action, + index.key, + Object.assign({}, index.options, { + from: state.fetchFrom, + subscribe: undefined, + limit, + }) + ); + if (newItems !== null) { + State.update({ + items: mergeItems(newItems), + fetchFrom: false, + nextFetchFrom: computeFetchFrom(newItems, limit), + }); + } +} + +const filteredItems = state.items; +if (filter) { + if (filter.ignore) { + filteredItems = filteredItems.filter( + (item) => !(item.accountId in filter.ignore) + ); + } +} + +const maybeFetchMore = () => { + if ( + filteredItems.length - state.displayCount < addDisplayCount * 2 && + !state.fetchFrom && + state.nextFetchFrom && + state.nextFetchFrom !== state.fetchFrom + ) { + State.update({ + fetchFrom: state.nextFetchFrom, + }); + } +}; + +maybeFetchMore(); + +const makeMoreItems = () => { + State.update({ + displayCount: state.displayCount + addDisplayCount, + }); + maybeFetchMore(); +}; + +const loader = ( +
+
+); + +const fetchMore = + props.manual && + !props.hideFetchMore && + (state.fetchFrom && filteredItems.length < state.displayCount + ? loader + : state.displayCount < filteredItems.length && ( + + )); + +const items = filteredItems ? filteredItems.slice(0, state.displayCount) : []; +if (reverse) { + items.reverse(); +} + +const renderedItems = items.map(cachedRenderItem); +const Layout = props.Layout; + +return props.manual ? ( + <> + {reverse && fetchMore} + {renderedItems} + {!reverse && fetchMore} + +) : ( + +
+ } + > + {props.headerElement} + {Layout ? {renderedItems} : <>{renderedItems}} + {props.footerElement} + +); \ No newline at end of file diff --git a/apps/bos-blocks/widget/PR/MergedIndexFeed.jsx b/apps/bos-blocks/widget/PR/MergedIndexFeed.jsx new file mode 100644 index 00000000..9a62accb --- /dev/null +++ b/apps/bos-blocks/widget/PR/MergedIndexFeed.jsx @@ -0,0 +1,259 @@ +if (!props.index) { + return "props.index is not defined"; +} +const indices = JSON.parse( + JSON.stringify(Array.isArray(props.index) ? props.index : [props.index]) +); + +const filter = props.filter; + +const renderItem = + props.renderItem ?? + ((item) => ( +
+ #{item.blockHeight}: {JSON.stringify(item)} +
+ )); +const cachedRenderItem = (item, i) => { + const key = JSON.stringify(item); + + if (!(key in state.cachedItems)) { + state.cachedItems[key] = renderItem(item, i); + State.update(); + } + return state.cachedItems[key]; +}; + +const initialRenderLimit = props.initialRenderLimit ?? 10; +const addDisplayCount = props.nextLimit ?? initialRenderLimit; +const reverse = !!props.reverse; + +const computeFetchFrom = (items, limit, desc) => { + if (!items || items.length < limit) { + return false; + } + const blockHeight = items[items.length - 1].blockHeight; + return desc ? blockHeight - 1 : blockHeight + 1; +}; + +const mergeItems = (iIndex, oldItems, newItems, desc) => { + const index = indices[iIndex]; + const items = [ + ...new Set( + [ + ...newItems.map((item) => ({ + ...item, + action: index.action, + key: index.key, + index: iIndex, + })), + ...oldItems, + ].map((i) => JSON.stringify(i)) + ), + ].map((i) => JSON.parse(i)); + items.sort((a, b) => a.blockHeight - b.blockHeight); + if (desc) { + items.reverse(); + } + return items; +}; + +const jIndices = JSON.stringify(indices); +if (jIndices !== state.jIndices) { + State.update({ + jIndices, + feeds: indices.map(() => ({})), + items: [], + displayCount: initialRenderLimit, + cachedItems: {}, + }); +} + +let stateChanged = false; +for (let iIndex = 0; iIndex < indices.length; ++iIndex) { + const index = indices[iIndex]; + const feed = state.feeds[iIndex]; + let feedChanged = false; + index.options = index.options || {}; + index.options.limit = Math.min( + Math.max(initialRenderLimit + addDisplayCount * 2, index.options.limit), + 100 + ); + const desc = index.options.order === "desc"; + + const initialItems = Social.index( + index.action, + index.key, + index.options, + index.cacheOptions + ); + if (initialItems === null) { + continue; + } + + const jInitialItems = JSON.stringify(initialItems); + const nextFetchFrom = computeFetchFrom( + initialItems, + index.options.limit, + desc + ); + if (feed.jInitialItems !== jInitialItems) { + feed.jInitialItems = jInitialItems; + feedChanged = true; + if (nextFetchFrom !== feed.initialNextFetchFrom) { + feed.fetchFrom = false; + feed.items = mergeItems(iIndex, [], initialItems, desc); + feed.initialNextFetchFrom = nextFetchFrom; + feed.nextFetchFrom = nextFetchFrom; + } else { + feed.items = mergeItems(iIndex, feed.items, initialItems, desc); + } + } + + feed.usedCount = 0; + + if (feedChanged) { + state.feeds[iIndex] = feed; + stateChanged = true; + } +} + +// Construct merged feed and compute usage per feed. + +const filteredItems = []; +while (filteredItems.length < state.displayCount) { + let bestItem = null; + for (let iIndex = 0; iIndex < indices.length; ++iIndex) { + const index = indices[iIndex]; + const feed = state.feeds[iIndex]; + const desc = index.options.order === "desc"; + if (!feed.items) { + continue; + } + const item = feed.items[feed.usedCount]; + if (!item) { + continue; + } + if ( + bestItem === null || + (desc + ? item.blockHeight > bestItem.blockHeight + : item.blockHeight < bestItem.blockHeight) + ) { + bestItem = item; + } + } + if (!bestItem) { + break; + } + state.feeds[bestItem.index].usedCount++; + if (filter) { + if (filter.ignore) { + if (bestItem.accountId in filter.ignore) { + continue; + } + } + } + filteredItems.push(bestItem); +} + +// Fetch new items for feeds that don't have enough items. +for (let iIndex = 0; iIndex < indices.length; ++iIndex) { + const index = indices[iIndex]; + const feed = state.feeds[iIndex]; + const desc = index.options.order === "desc"; + let feedChanged = false; + + if ( + (feed.items.length || 0) - feed.usedCount < addDisplayCount * 2 && + !feed.fetchFrom && + feed.nextFetchFrom && + feed.nextFetchFrom !== feed.fetchFrom + ) { + feed.fetchFrom = feed.nextFetchFrom; + feedChanged = true; + } + + if (feed.fetchFrom) { + const limit = addDisplayCount; + const newItems = Social.index( + index.action, + index.key, + Object.assign({}, index.options, { + from: feed.fetchFrom, + subscribe: undefined, + limit, + }) + ); + if (newItems !== null) { + feed.items = mergeItems(iIndex, feed.items, newItems, desc); + feed.fetchFrom = false; + feed.nextFetchFrom = computeFetchFrom(newItems, limit, desc); + feedChanged = true; + } + } + + if (feedChanged) { + state.feeds[iIndex] = feed; + stateChanged = true; + } +} + +if (stateChanged) { + State.update(); +} + +const makeMoreItems = () => { + State.update({ + displayCount: state.displayCount + addDisplayCount, + }); +}; + +const loader = ( +
+
+); + +const fetchMore = + props.manual && + (state.feeds.some((f) => !!f.fetchFrom) && + filteredItems.length < state.displayCount + ? loader + : state.displayCount < filteredItems.length && ( + + )); + +const items = filteredItems ? filteredItems.slice(0, state.displayCount) : []; +if (reverse) { + items.reverse(); +} + +const renderedItems = items.map(cachedRenderItem); +const Layout = props.Layout; + +return props.manual ? ( + <> + {reverse && fetchMore} + {renderedItems} + {!reverse && fetchMore} + +) : ( + + {Layout ? {renderedItems} : <>{renderedItems}} + +); \ No newline at end of file diff --git a/apps/bos-blocks/widget/Router.jsx b/apps/bos-blocks/widget/Router.jsx new file mode 100644 index 00000000..c6bea38c --- /dev/null +++ b/apps/bos-blocks/widget/Router.jsx @@ -0,0 +1,72 @@ +// We eventually want to merge this with what we have in buildhub.near/widget/app + +const routes = props.routes; +if (!routes) { + routes = []; +} +const Navigator = props.Navigator; + +State.init({ + CurrentWidget: null, +}); + +function init() { + if (!state.CurrentWidget) { + // TODO: check from local storage or props + const initialSrc = Object.values(props.routes)[0].src; + State.update({ CurrentWidget: initialSrc }); + // () => + } +} + +init(); + +// Function to handle navigation +function handleNavigate(newRoute, passProps) { + const currentSrc = props.routes[newRoute]?.src; + State.update({ CurrentWidget: currentSrc, passProps }); +} + +// const activePage = pages.find((p) => p.active); + +// const navigate = (v, params) => { +// State.update({ page: v, project: params?.project }); +// const url = Url.construct("#//*__@appAccount__*//widget/home", params); +// Storage.set("url", url); +// }; + +function RouterLink({ to, children, passProps }) { + return ( + handleNavigate(to, passProps)} + key={"link-to-" + to} + style={{ cursor: "pointer" }} + > + {children} + + ); +} + +// Render the current widget or a default message if the route is not found +return ( +
+ {/* Navigation buttons -- this should be passed to a Navigator widget */} +
+ +
+ {/** This could already render all of the children, but just put them as display none (lazy loading) */} + {state.CurrentWidget ? ( + + ) : ( +
{JSON.stringify(state.CurrentWidget)}
+ )} +
+); \ No newline at end of file diff --git a/apps/builddao/widget/app.jsx b/apps/builddao/widget/app.jsx new file mode 100644 index 00000000..5c2f5b60 --- /dev/null +++ b/apps/builddao/widget/app.jsx @@ -0,0 +1,82 @@ +const { page, layout, loading, ...passProps } = props; + +const { routes, theme } = VM.require("buildhub.near/widget/config") ?? { + routes: {}, + theme: "background-color: red;" +}; + +const { AppLayout } = VM.require("every.near/widget/layout") || { + AppLayout: () => <>Layout loading..., +}; + +if (!page) page = Object.keys(routes)[0] || "home"; + +const Root = styled.div` + a { + color: inherit; + } + + ${theme} + + // can come from config +`; + +const [activeRoute, setActiveRoute] = useState(page); + +useEffect(() => { + setActiveRoute(page); +}, [page]); + +function Router({ active, routes }) { // this may be converted to a module at devs.near/widget/Router + const routeParts = active.split("."); + + let currentRoute = routes; + let src = ""; + let defaultProps = {}; + + for (let part of routeParts) { + if (currentRoute[part]) { + currentRoute = currentRoute[part]; + src = currentRoute.path; + + if (currentRoute.init) { + defaultProps = { ...defaultProps, ...currentRoute.init }; + } + } else { + // Handle 404 or default case for unknown routes + return

404 Not Found

; + } + } + + return ( +
+ +
+ ); +} + +const Container = styled.div` + display: flex; + height: 100vh; +`; + +const Content = styled.div` + width: 100%; + height: 100%; + overflow: scroll; +`; + +return ( + + + + + + + + + +); diff --git a/apps/builddao/widget/config.jsx b/apps/builddao/widget/config.jsx new file mode 100644 index 00000000..2d71b26e --- /dev/null +++ b/apps/builddao/widget/config.jsx @@ -0,0 +1,32 @@ +return { + "type": "app", + "routes": { + "home": { + "path": "buildhub.near/widget/page.home", + "blockHeight": "final", + "init": { + "name": "Home", + "icon": "bi bi-house" + } + }, + "feed": { + "path": "buildhub.near/widget/page.feed", + "blockHeight": "final", + "init": { + "icon": "bi bi-globe" + } + }, + "inspect": { + "path": "mob.near/widget/WidgetSource", + "blockHeight": "final", + "hide": true + }, + "notifications": { + "path": "mob.near/widget/NotificationFeed", + "blockHeight": "final", + "hide": true + } + }, + "theme": "background-color: white;" +} +; \ No newline at end of file diff --git a/apps/builddao/widget/page/feed.jsx b/apps/builddao/widget/page/feed.jsx new file mode 100644 index 00000000..53cc3566 --- /dev/null +++ b/apps/builddao/widget/page/feed.jsx @@ -0,0 +1,49 @@ +const { Feed } = VM.require("devs.near/widget/Feed") || { + // this is being pulled from local apps/bos-blocks/widget/Feed + Feed: () =>

Feed loading...

, +}; + +// would a provider pattern be helpful here? +// const { items } = props; + +const [activeItem, setActiveItem] = useState(null); + +function Sidebar() { + return ( // minimal styling, classnames from Theme +
setActiveItem}> +

sidebar

+
+ ); +} + +// can we take influence from the pattern in buildhub.near/widget/app? + +return ( + <> + +

{JSON.stringify(p)}

} + /> + +); diff --git a/apps/builddao/widget/page/home.jsx b/apps/builddao/widget/page/home.jsx new file mode 100644 index 00000000..c61d8eb7 --- /dev/null +++ b/apps/builddao/widget/page/home.jsx @@ -0,0 +1 @@ +return

home

; diff --git a/src/App.js b/src/App.js index 2f8395ff..b0f84a8a 100644 --- a/src/App.js +++ b/src/App.js @@ -41,6 +41,7 @@ import ProposePage from "./pages/ProposePage"; import ViewPage from "./pages/ViewPage"; import ResourcesPage from "./pages/ResourcesPage"; import LibraryPage from "./pages/LibraryPage"; +import Viewer from "./pages/Viewer"; export const refreshAllowanceObj = {}; const documentationHref = "https://docs.near.org/bos"; @@ -80,17 +81,24 @@ function App() { bundle: false, }), setupNightly(), - setupKeypom({ + setupKeypom({ networkId: NetworkId, - signInContractId: NetworkId == "testnet" ? "v1.social08.testnet" : "social.near", + signInContractId: + NetworkId == "testnet" ? "v1.social08.testnet" : "social.near", trialAccountSpecs: { - url: NetworkId == "testnet" ? "https://test.nearbuilders.org/#trial-url/ACCOUNT_ID/SECRET_KEY" : "https://nearbuilders.org/#trial-url/ACCOUNT_ID/SECRET_KEY", - modalOptions: KEYPOM_OPTIONS(NetworkId) + url: + NetworkId == "testnet" + ? "https://test.nearbuilders.org/#trial-url/ACCOUNT_ID/SECRET_KEY" + : "https://nearbuilders.org/#trial-url/ACCOUNT_ID/SECRET_KEY", + modalOptions: KEYPOM_OPTIONS(NetworkId), }, instantSignInSpecs: { - url: NetworkId == 'testnet' ? 'https://test.nearbuilders.org/#instant-url/ACCOUNT_ID/SECRET_KEY/MODULE_ID' : 'https://nearbuilders.org/#instant-url/ACCOUNT_ID/SECRET_KEY/MODULE_ID', + url: + NetworkId == "testnet" + ? "https://test.nearbuilders.org/#instant-url/ACCOUNT_ID/SECRET_KEY/MODULE_ID" + : "https://nearbuilders.org/#instant-url/ACCOUNT_ID/SECRET_KEY/MODULE_ID", }, - }), + }), ], }), customElements: { @@ -102,7 +110,7 @@ function App() { if (props.to) { props.to = typeof props.to === "string" && - isValidAttribute("a", "href", props.to) + isValidAttribute("a", "href", props.to) ? props.to : "about:blank"; } @@ -195,8 +203,15 @@ function App() { + + {/* I've added the below as the isolated route for rendering the app */} + + + + + {/* Legacy: */} @@ -231,4 +246,4 @@ function App() { ); } -export default App; \ No newline at end of file +export default App; diff --git a/src/pages/Viewer.js b/src/pages/Viewer.js new file mode 100644 index 00000000..5310c7bd --- /dev/null +++ b/src/pages/Viewer.js @@ -0,0 +1,74 @@ +import { Widget } from "near-social-vm"; +import React, { useEffect, useMemo, useState } from "react"; +import { useLocation, useParams } from "react-router-dom"; + +const SESSION_STORAGE_REDIRECT_MAP_KEY = "nearSocialVMredirectMap"; + +function Viewer({ code }) { + const { path } = useParams(); // get path from url, could be socialdb path or relative to "core" + const location = useLocation(); // get query params from url + const searchParams = new URLSearchParams(location.search); + + // create props from params + const passProps = useMemo(() => { + return Array.from(searchParams.entries()).reduce((props, [key, value]) => { + props[key] = value; + return props; + }, {}); + }, [location]); + + const src = useMemo(() => { + const defaultSrc = "buildhub.near/widget/app"; // default widget to load + const pathSrc = path || defaultSrc; // if no path, load default widget + return pathSrc; + // const lastSlashIndex = pathSrc.lastIndexOf("/", pathSrc.indexOf(".near")); + // return lastSlashIndex !== -1 + // ? pathSrc.substring(lastSlashIndex + 1) + // : defaultSrc; + }, [path]); + + const [redirectMap, setRedirectMap] = useState(null); + + useEffect(() => { + const fetchRedirectMap = async () => { + try { + const localStorageFlags = JSON.parse( + localStorage.getItem("flags") || "{}" + ); + let redirectMapData; + + if (localStorageFlags.bosLoaderUrl) { + const response = await fetch(localStorageFlags.bosLoaderUrl); + const data = await response.json(); + redirectMapData = data.components; + } else { + redirectMapData = JSON.parse( + sessionStorage.getItem(SESSION_STORAGE_REDIRECT_MAP_KEY) || "{}" + ); + } + setRedirectMap(redirectMapData); + } catch (error) { + console.error("Error fetching redirect map:", error); + } + }; + fetchRedirectMap(); + }, []); + + console.log( + `gateway rendering: ${src} with props: ${JSON.stringify(passProps)}` + ); + + return ( + + ); +} + +export default Viewer; From a9d9f6c86adfc0a17a491898022f0ae5ea24ad9e Mon Sep 17 00:00:00 2001 From: Zeeshan Ahmad Date: Tue, 23 Jan 2024 11:25:44 +0500 Subject: [PATCH 002/132] Use variables to color components --- apps/builddao/widget/GeneralFeed.jsx | 30 +++++++++++++++++ apps/builddao/widget/components.jsx | 2 ++ .../components/AsideWithMainContent.jsx | 2 +- apps/builddao/widget/components/Button.jsx | 22 +++++++------ .../builddao/widget/components/ButtonLink.jsx | 22 +++++++------ apps/builddao/widget/components/Checkbox.jsx | 4 +-- .../builddao/widget/components/InputField.jsx | 10 +++--- .../builddao/widget/components/Pagination.jsx | 6 ++-- apps/builddao/widget/components/Post.jsx | 32 +++++++++---------- .../widget/components/ProgressState.jsx | 21 ++++++------ apps/builddao/widget/components/Step.jsx | 2 +- apps/builddao/widget/components/TextBox.jsx | 11 +++---- .../builddao/widget/components/TextEditor.jsx | 4 +-- .../widget/components/UploadField.jsx | 16 ++++++---- apps/builddao/widget/components/login-now.jsx | 2 +- 15 files changed, 112 insertions(+), 74 deletions(-) create mode 100644 apps/builddao/widget/GeneralFeed.jsx diff --git a/apps/builddao/widget/GeneralFeed.jsx b/apps/builddao/widget/GeneralFeed.jsx new file mode 100644 index 00000000..4bca9028 --- /dev/null +++ b/apps/builddao/widget/GeneralFeed.jsx @@ -0,0 +1,30 @@ +const Theme = styled.div` + --stroke-color: rgba(255, 255, 255, 0.2); + --bg-1: #0b0c14; + --bg-2: ##23242b; + --bg-1-hover: #17181c; + --bg-1-hover-transparent: rgba(23, 24, 28, 0); + --label-color: #fff; + --font-color: #fff; + --font-muted-color: #cdd0d5; + --black: #000; + --system-red: #fd2a5c; + --yellow: #ffaf51; + + --post-bg: #23242b; + --post-bg-transparent: rgba(23, 24, 28, 0); + + --button-primary-bg: #ffaf51; + --button-outline-bg: transparent; + --button-default-bg: #23242b; + + --button-primary-color: #000; + --button-outline-color: #fff; + --button-default-color: #cdd0d5; + + --button-primary-hover-bg: #e49b48; + --button-outline-hover-bg: rgba(255, 255, 255, 0.2); + --button-default-hover-bg: #17181c; +`; + +return ; diff --git a/apps/builddao/widget/components.jsx b/apps/builddao/widget/components.jsx index 38499bad..191845e0 100644 --- a/apps/builddao/widget/components.jsx +++ b/apps/builddao/widget/components.jsx @@ -1,4 +1,5 @@ const { Button } = VM.require("buildhub.near/widget/components.Button"); +const { ButtonLink } = VM.require("buildhub.near/widget/components.ButtonLink"); const { ProgressState } = VM.require( "buildhub.near/widget/components.ProgressState" ); @@ -45,6 +46,7 @@ function User(props) { return { Button, + ButtonLink, Pagination, Post, ProgressState, diff --git a/apps/builddao/widget/components/AsideWithMainContent.jsx b/apps/builddao/widget/components/AsideWithMainContent.jsx index c1abfd8a..66a75678 100644 --- a/apps/builddao/widget/components/AsideWithMainContent.jsx +++ b/apps/builddao/widget/components/AsideWithMainContent.jsx @@ -13,7 +13,7 @@ const Container = styled.div` const AsideContainer = styled.div` border-radius: 16px; - border: 1px solid var(--Stroke-color, rgba(255, 255, 255, 0.2)); + border: 1px solid var(--stroke-color, rgba(255, 255, 255, 0.2)); background: var(--bg-1, #0b0c14); width: 100%; diff --git a/apps/builddao/widget/components/Button.jsx b/apps/builddao/widget/components/Button.jsx index 885bfd4d..830c76ff 100644 --- a/apps/builddao/widget/components/Button.jsx +++ b/apps/builddao/widget/components/Button.jsx @@ -24,38 +24,40 @@ const StyledButton = styled.button` background: ${(props) => { switch (props.variant) { case "primary": - return "#FFAF51"; + return "var(--button-primary-bg, #FFAF51)"; case "outline": - return "transparent"; + return "var(--button-outline-bg, transparent)"; default: - return "#23242B"; + return "var(--button-default-bg, #23242B)"; } }}; color: ${(props) => { switch (props.variant) { case "primary": - return "#000"; + return "var(--button-primary-color, #000)"; case "outline": - return "#fff"; + return "var(--button-outline-color, #fff)"; default: - return "#CDD0D5"; + return "var(--button-default-color, #CDD0D5)"; } }}; border: ${(props) => - props.variant === "outline" ? "1px solid rgba(255, 255, 255, 0.20)" : ""}; + props.variant === "outline" + ? "1px solid var(--stroke-color, rgba(255, 255, 255, 0.20))" + : ""}; /* Hover states */ &:hover { background: ${(props) => { switch (props.variant) { case "primary": - return "#e49b48"; + return "var(--button-primary-hover-bg, #e49b48)"; case "outline": - return "rgba(255, 255, 255, 0.20)"; + return "var(--button-outline-hover-bg, rgba(255, 255, 255, 0.20))"; default: - return "#17181c"; + return "var(--button-default-hover-bg, #17181c)"; } }}; } diff --git a/apps/builddao/widget/components/ButtonLink.jsx b/apps/builddao/widget/components/ButtonLink.jsx index 153e7381..11283685 100644 --- a/apps/builddao/widget/components/ButtonLink.jsx +++ b/apps/builddao/widget/components/ButtonLink.jsx @@ -24,38 +24,40 @@ const StyledLink = styled.a` background: ${(props) => { switch (props.variant) { case "primary": - return "#FFAF51"; + return "var(--button-primary-bg, #FFAF51)"; case "outline": - return "transparent"; + return "var(--button-outline-bg, transparent)"; default: - return "#23242B"; + return "var(--button-default-bg, #23242B)"; } }}; color: ${(props) => { switch (props.variant) { case "primary": - return "#000"; + return "var(--button-primary-color, #000)"; case "outline": - return "#fff"; + return "var(--button-outline-color, #fff)"; default: - return "#CDD0D5"; + return "var(--button-default-color, #CDD0D5)"; } }}; border: ${(props) => - props.variant === "outline" ? "1px solid rgba(255, 255, 255, 0.20)" : ""}; + props.variant === "outline" + ? "1px solid var(--stroke-color, rgba(255, 255, 255, 0.20))" + : ""}; /* Hover states */ &:hover { background: ${(props) => { switch (props.variant) { case "primary": - return "#e49b48"; + return "var(--button-primary-hover-bg, #e49b48)"; case "outline": - return "rgba(255, 255, 255, 0.20)"; + return "var(--button-outline-hover-bg, rgba(255, 255, 255, 0.20))"; default: - return "#17181c"; + return "var(--button-default-hover-bg, #17181c)"; } }}; } diff --git a/apps/builddao/widget/components/Checkbox.jsx b/apps/builddao/widget/components/Checkbox.jsx index 27387079..97aec9e4 100644 --- a/apps/builddao/widget/components/Checkbox.jsx +++ b/apps/builddao/widget/components/Checkbox.jsx @@ -8,7 +8,7 @@ const CheckboxLabel = styled.label` align-items: center; gap: 8px; - color: #fff; + color: var(--label-color, #fff); font-size: 16px; font-style: normal; font-weight: 400; @@ -31,4 +31,4 @@ function Checkbox({ value, onChange, label }) { ); } -return { Checkbox }; \ No newline at end of file +return { Checkbox }; diff --git a/apps/builddao/widget/components/InputField.jsx b/apps/builddao/widget/components/InputField.jsx index ab6fcff0..deacecd2 100644 --- a/apps/builddao/widget/components/InputField.jsx +++ b/apps/builddao/widget/components/InputField.jsx @@ -6,7 +6,7 @@ const InputContainer = styled.div` `; const Label = styled.label` - color: var(--White-100, #fff); + color: var(--label-color, #fff); /* Body/16px */ font-size: 16px; @@ -24,12 +24,12 @@ const Input = styled.input` gap: 10px; border-radius: 8px; - border: 1px solid var(--Stroke-color, rgba(255, 255, 255, 0.2)); - background: var(--Bg-1, #0b0c14); + border: 1px solid var(--stroke-color, rgba(255, 255, 255, 0.2)); + background: var(--bg-1, #0b0c14); flex: 1 0 0; - color: var(--White-50, #cdd0d5); + color: var(--font-muted-color, #cdd0d5); /* Body/16px */ font-size: 16px; @@ -62,4 +62,4 @@ function InputField({ ); } -return { InputField }; \ No newline at end of file +return { InputField }; diff --git a/apps/builddao/widget/components/Pagination.jsx b/apps/builddao/widget/components/Pagination.jsx index 4196eb2a..5e39fb73 100644 --- a/apps/builddao/widget/components/Pagination.jsx +++ b/apps/builddao/widget/components/Pagination.jsx @@ -21,7 +21,7 @@ const Pagination = styled.div` align-items: center; gap: 10px; border-radius: 8px; - color: var(--White-100, #fff); + color: var(--font-color, #fff); transition: all 300ms; cursor: pointer; @@ -33,11 +33,11 @@ const Pagination = styled.div` &.selected, &:hover { - background-color: #23242b; + background-color: var(--bg-1, #23242b); } &.arrow { - border: 1px solid rgba(255, 255, 255, 0.2); + border: 1px solid var(--stroke-color, rgba(255, 255, 255, 0.2)); } &.disabled { diff --git a/apps/builddao/widget/components/Post.jsx b/apps/builddao/widget/components/Post.jsx index 3c569b24..4106a19b 100644 --- a/apps/builddao/widget/components/Post.jsx +++ b/apps/builddao/widget/components/Post.jsx @@ -6,19 +6,19 @@ const StyledPost = styled.div` margin-bottom: 1rem; .post { border-radius: 16px; - border: 1px solid var(--Stroke-color, rgba(255, 255, 255, 0.2)); - color: #b6b6b8; + border: 1px solid var(--stroke-color, rgba(255, 255, 255, 0.2)); + color: var(--font-muted-color, #b6b6b8); padding: 24px !important; - background-color: #23242b; + background-color: var(--bg-1, #23242b); transition: all 300ms; &:hover { - background-color: #1c1f33 !important; + background-color: var(--bg-1-hover, #17181c) !important; .expand-post { background-image: linear-gradient( to bottom, - rgba(28, 31, 51, 0), - rgba(28, 31, 51, 1) 25% + var(--bg-1-hover-transparent, rgba(23, 24, 28, 0)), + var(--bg-1-hover, #17181c) 25% ) !important; } } @@ -26,7 +26,7 @@ const StyledPost = styled.div` .post-header { span, .text-muted { - color: #fff !important; + color: var(--font-color, #fff) !important; } } @@ -38,34 +38,34 @@ const StyledPost = styled.div` .expand-post { background-image: linear-gradient( to bottom, - rgba(35, 36, 43, 0), - rgba(35, 36, 43, 1) 25% + var(--post-bg, rgba(35, 36, 43, 0)), + var(--post-bg-transparent, rgba(35, 36, 43, 1)) 25% ) !important; } } .dropdown-menu { - background-color: #0b0c14 !important; - color: #fff !important; + background-color: var(--bg-1, #0b0c14) !important; + color: var(--font-color, #fff) !important; li.dropdown-item { - color: #fff !important; + color: var(--font-color, #fff) !important; &:hover { a { - color: #0b0c14 !important; + color: var(--bg-1, #0b0c14) !important; } } } .link-dark, .dropdown-item { - color: #fff !important; + color: var(--font-color, #fff) !important; &:hover { - color: #0b0c14 !important; + color: var(--bg-1, #0b0c14) !important; span { - color: #0b0c14 !important; + color: var(--bg-1, #0b0c14) !important; } } } diff --git a/apps/builddao/widget/components/ProgressState.jsx b/apps/builddao/widget/components/ProgressState.jsx index e96fe0ba..41be6d01 100644 --- a/apps/builddao/widget/components/ProgressState.jsx +++ b/apps/builddao/widget/components/ProgressState.jsx @@ -1,4 +1,3 @@ - const Progress = styled.div` display: flex; width: 40px; @@ -12,13 +11,13 @@ const Progress = styled.div` border: ${(props) => { switch (props.status) { case "focused": - return "1px solid var(--Yellow, #FFAF51)"; + return "1px solid var(--yellow, #FFAF51)"; case "error": - return "1px solid var(--System-Red, #FD2A5C)"; + return "1px solid var(--system-red, #FD2A5C)"; case "completed": - return "1px solid var(--Stroke-color, rgba(255, 255, 255, 0.20))"; + return "1px solid var(--stroke-color, rgba(255, 255, 255, 0.20))"; default: - return "1px solid var(--Stroke-color, rgba(255, 255, 255, 0.20))"; + return "1px solid var(--stroke-color, rgba(255, 255, 255, 0.20))"; } }}; @@ -29,7 +28,7 @@ const Progress = styled.div` case "error": return "#2f101f"; case "completed": - return "#FFAF51"; + return "var(--yellow, #FFAF51)"; default: return "#23242B"; } @@ -38,13 +37,13 @@ const Progress = styled.div` color: ${(props) => { switch (props.status) { case "focused": - return "#fff"; + return "var(--font-color, #fff)"; case "error": - return "#FD2A5C"; + return "var(--system-red, #FD2A5C)"; case "completed": - return "#000"; + return "var(--black, #000)"; default: - return "#fff"; + return "var(--font-color, #fff)"; } }}; `; @@ -66,4 +65,4 @@ function ProgressState({ children, status }) { ); } -return { ProgressState }; \ No newline at end of file +return { ProgressState }; diff --git a/apps/builddao/widget/components/Step.jsx b/apps/builddao/widget/components/Step.jsx index c4f4bcd1..0f9fceab 100644 --- a/apps/builddao/widget/components/Step.jsx +++ b/apps/builddao/widget/components/Step.jsx @@ -11,7 +11,7 @@ const StepContainer = styled.div` left: 0; right: 0; height: 1px; - background: #000; /* Change color as needed */ + background: var(--black, #000); /* Change color as needed */ background-image: repeating-linear-gradient( 90deg, #3c3d43, diff --git a/apps/builddao/widget/components/TextBox.jsx b/apps/builddao/widget/components/TextBox.jsx index 66113c3c..55b6e3d4 100644 --- a/apps/builddao/widget/components/TextBox.jsx +++ b/apps/builddao/widget/components/TextBox.jsx @@ -1,5 +1,5 @@ const Label = styled.label` - color: var(--White-100, #fff); + color: var(--label-color, #fff); /* Body/16px */ font-size: 16px; @@ -8,7 +8,6 @@ const Label = styled.label` line-height: 170%; /* 27.2px */ `; - const TextArea = styled.textarea` display: flex; min-height: 100px; @@ -18,10 +17,10 @@ const TextArea = styled.textarea` align-self: stretch; border-radius: 8px; - border: 1px solid var(--Stroke-color, rgba(255, 255, 255, 0.2)); - background: var(--Bg-1, #0b0c14); + border: 1px solid var(--stroke-color, rgba(255, 255, 255, 0.2)); + background: var(--bg-1, #0b0c14); - color: var(--White-50, #fff); + color: var(--font-color, #fff); /* Body/16px */ font-size: 16px; @@ -42,4 +41,4 @@ function TextBox({ label, value, onChange, placeholder, maxWidth }) { ); } -return { TextBox }; \ No newline at end of file +return { TextBox }; diff --git a/apps/builddao/widget/components/TextEditor.jsx b/apps/builddao/widget/components/TextEditor.jsx index 160ea28f..bdb999c5 100644 --- a/apps/builddao/widget/components/TextEditor.jsx +++ b/apps/builddao/widget/components/TextEditor.jsx @@ -137,7 +137,7 @@ function TextEditor({ value, onChange, maxWidth }) { src="mob.near/widget/MarkdownEditorIframe" props={{ initialText: value, - embedCss: MarkdownEditor, + embedCss: props.EditorCSS || MarkdownEditor, onChange, }} /> @@ -145,4 +145,4 @@ function TextEditor({ value, onChange, maxWidth }) { ); } -return { TextEditor }; \ No newline at end of file +return { TextEditor }; diff --git a/apps/builddao/widget/components/UploadField.jsx b/apps/builddao/widget/components/UploadField.jsx index 1d663954..b0f873b2 100644 --- a/apps/builddao/widget/components/UploadField.jsx +++ b/apps/builddao/widget/components/UploadField.jsx @@ -14,11 +14,12 @@ const UploadContainer = styled.div` gap: 24px; border-radius: 16px; - border: 1px dashed var(--Stroke-color, rgba(255, 255, 255, 0.2)); - background: ${(props) => (props.background ? "#23242B" : "#0b0c14")}; + border: 1px dashed var(--stroke-color, rgba(255, 255, 255, 0.2)); + background: ${(props) => + props.background ? "var(--bg-2, #23242B)" : "var(--bg-1, #0b0c14)"}; p { - color: var(--White-100, #fff); + color: var(--font-color, #fff); text-align: center; /* Body/Medium-16px */ @@ -30,7 +31,7 @@ const UploadContainer = styled.div` } p.secondary { - color: var(--White-50, #cdd0d5); + color: var(--font-muted-color, #cdd0d5); text-align: center; font-size: 12px; font-style: normal; @@ -39,7 +40,7 @@ const UploadContainer = styled.div` } i { - color: white; + color: var(--font-color, #fff); font-size: 2rem; } `; @@ -54,7 +55,10 @@ function UploadField({ background }) { JPEG, PNG, PDF, and MP4 formats, up to 50 MB.

- diff --git a/apps/builddao/widget/components/login-now.jsx b/apps/builddao/widget/components/login-now.jsx index cd5c619e..b82ba89a 100644 --- a/apps/builddao/widget/components/login-now.jsx +++ b/apps/builddao/widget/components/login-now.jsx @@ -1,6 +1,6 @@ const Container = styled.div` background-color: #23242b; - color: #ffffff; + color: #fff; width: 100%; height: 16rem; From a89c6a71f3fc5cc2ef5507193a336653a1cdcf89 Mon Sep 17 00:00:00 2001 From: Zeeshan Ahmad Date: Tue, 23 Jan 2024 11:28:59 +0500 Subject: [PATCH 003/132] Add Feed tabs to general feed --- apps/builddao/widget/GeneralFeed.jsx | 141 +++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) diff --git a/apps/builddao/widget/GeneralFeed.jsx b/apps/builddao/widget/GeneralFeed.jsx index 4bca9028..d9c89f85 100644 --- a/apps/builddao/widget/GeneralFeed.jsx +++ b/apps/builddao/widget/GeneralFeed.jsx @@ -27,4 +27,145 @@ const Theme = styled.div` --button-default-hover-bg: #17181c; `; +function formatDate(date) { + const options = { year: "numeric", month: "short", day: "numeric" }; + return date.toLocaleDateString("en-US", options); +} + +const daoName = "Build DAO"; +const feedLink = "https://nearbuilders.org/feed"; + +const feeds = { + resolutions: { + label: "Resolutions", + icon: "bi-calendar3", + name: "resolution", + hashtag: "nearyearresolutions2024", + template: `### 🎉 NEAR YEAR RESOLUTIONS: 2024 + (posted via [${daoName} Gateway](${feedLink})) + + **🌟 REFLECTIONS ON THE PAST YEAR:** + - [Reflection 1 from the past year] + - [Reflection 2 from the past year] + + **🎯 NEW YEAR'S RESOLUTIONS:** + - [Resolution 1] + - [Resolution 2] + + **📊 MEASURING SUCCESS:** + - [Metric 1 for Success] + - [Metric 2 for Success] + `, + }, + updates: { + label: "Updates", + icon: "bi-bell", + name: "update", + hashtag: "update", + template: `### BUILDER UPDATE: ${formatDate(new Date())} + (posted via [${daoName} Gateway](${feedLink}?tab=update)) + + **✅ DONE** + - [what'd you do] + - [link proof] + + **⏩ NEXT** + - [what's next?] + - [what are you thinking about?] + + **🛑 BLOCKERS** + - [what's blocking you?] + - [how can someone help?] + `, + }, + documentation: { + label: "Documentation", + icon: "bi-book", + name: "documentation", + hashtag: "documentation", + template: `## TITLE + (posted via [${daoName} Gateway](${feedLink}?tab=documentation)) + + **WHAT IS _____?** + - [context] + - [why is it important?] + + **EXAMPLE** + - [how can this be demonstrated?] + - [what is the expected outcome?] + + **USAGE** + - [where is it used?] + - [how to use it] + `, + }, + question: { + label: "Question", + icon: "bi-question-lg", + name: "question", + hashtag: "question", + template: `## what is your question? + (posted via [${daoName} Gateway](${feedLink}?tab=question)) + + [what are you thinking about?] + [why are you asking?] + `, + }, + answer: { + label: "Answer", + icon: "bi-journal-code", + name: "answer", + hashtag: "answer", + template: `## Share an answer + (posted via [${daoName} Gateway](${feedLink}?tab=answer)) + + [please restate the question you are answering] + + [your answer] + + [link to relevant docs, examples, or resources] + `, + }, + opportunity: { + label: "Opportunity", + icon: "bi-briefcase", + name: "opportunity", + hashtag: "opportunity", + template: `## TITLE + (posted via [${daoName} Gateway](${feedLink}?tab=opportunity)) + + [what is the opportunity?] + + [explain the motivation or reason] + + `, + }, + idea: { + label: "Idea", + icon: "bi-lightbulb", + name: "idea", + hashtag: "idea", + template: ``, + }, + task: { + label: "Task", + icon: "bi-check-lg", + name: "task", + template: `## TASK TITLE + (posted via [${daoName} Gateway](${feedLink}?tab=task)) + + **What needs to be done?** + - [Describe the task or action steps] + + **Context or additional information:** + - [Provide any context or details] + `, + }, + bookmarks: { + label: "Bookmarks", + icon: "bi-bookmark", + name: "bookmark", + }, +}; + return ; From 5eb25c80a02c1c85862519a588dd0ae8ed12a44c Mon Sep 17 00:00:00 2001 From: Zeeshan Ahmad Date: Tue, 23 Jan 2024 11:49:08 +0500 Subject: [PATCH 004/132] Make General Feed functional --- apps/builddao/widget/Feed.jsx | 1 - apps/builddao/widget/GeneralFeed.jsx | 87 ++++++++++++++++++- .../components/AsideWithMainContent.jsx | 2 +- 3 files changed, 87 insertions(+), 3 deletions(-) diff --git a/apps/builddao/widget/Feed.jsx b/apps/builddao/widget/Feed.jsx index 0fb4ac77..6113ad5d 100644 --- a/apps/builddao/widget/Feed.jsx +++ b/apps/builddao/widget/Feed.jsx @@ -156,7 +156,6 @@ const feeds = { }; const [activeFeed, setActiveFeed] = useState(tab || "resolutions"); -const [template, setTemplate] = useState("What did you have in mind?"); return ( <>); +const { Post, Button } = VM.require("buildhub.near/widget/components") || { + Post: () => <>, + Button: () => <>, +}; + const Theme = styled.div` --stroke-color: rgba(255, 255, 255, 0.2); --bg-1: #0b0c14; @@ -168,4 +174,83 @@ const feeds = { }, }; -return ; +const tab = props.tab || "resolutions"; + +const [activeFeed, setActiveFeed] = useState(tab); +const daoTag = "build"; + +return ( + + { + const data = feeds[route]; + return ( + + ); + }), + mainContent: ( + <> + {context.accountId ? ( + activeFeed !== "bookmarks" ? ( + + ) : ( + + ) + ) : ( + + )} + {activeFeed !== "bookmarks" && ( + ( + + )} + /> + )} + + ), + }} + /> + +); diff --git a/apps/builddao/widget/components/AsideWithMainContent.jsx b/apps/builddao/widget/components/AsideWithMainContent.jsx index 66a75678..c56a243c 100644 --- a/apps/builddao/widget/components/AsideWithMainContent.jsx +++ b/apps/builddao/widget/components/AsideWithMainContent.jsx @@ -23,7 +23,7 @@ const AsideContainer = styled.div` align-items: flex-start; gap: 16px; margin-bottom: 1rem; - height: calc(min(100vh - 64px, 100%)); + height: max-content; @media screen and (max-width: 768px) { border: 0px; From a0127751c50751fb90ad47752792f378782ade89 Mon Sep 17 00:00:00 2001 From: Zeeshan Ahmad Date: Tue, 23 Jan 2024 11:59:34 +0500 Subject: [PATCH 005/132] Pass required dao tag from general feed to compose --- apps/builddao/widget/Compose.jsx | 2 +- apps/builddao/widget/GeneralFeed.jsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/builddao/widget/Compose.jsx b/apps/builddao/widget/Compose.jsx index 4c388232..9542195f 100644 --- a/apps/builddao/widget/Compose.jsx +++ b/apps/builddao/widget/Compose.jsx @@ -92,7 +92,7 @@ const postToCustomFeed = ({ feed, text, labels }) => { labels = labels.map((label) => label.toLowerCase()); labels.push(feed.name.toLowerCase()); - const requiredHashtags = ["build"]; + const requiredHashtags = props.requiredHashtags || ["build"]; if (feed.hashtag) requiredHashtags.push(feed.hashtag.toLowerCase()); requiredHashtags.push(feed.name.toLowerCase()); diff --git a/apps/builddao/widget/GeneralFeed.jsx b/apps/builddao/widget/GeneralFeed.jsx index 94058b07..036473a2 100644 --- a/apps/builddao/widget/GeneralFeed.jsx +++ b/apps/builddao/widget/GeneralFeed.jsx @@ -40,6 +40,7 @@ function formatDate(date) { const daoName = "Build DAO"; const feedLink = "https://nearbuilders.org/feed"; +const daoTag = "testDao"; const feeds = { resolutions: { @@ -175,9 +176,7 @@ const feeds = { }; const tab = props.tab || "resolutions"; - const [activeFeed, setActiveFeed] = useState(tab); -const daoTag = "build"; return ( @@ -212,6 +211,7 @@ return ( props={{ feed: feeds[activeFeed], template: feeds[activeFeed].template, + requiredHashtags: [daoTag], }} /> ) : ( From 4a78c4341b1d59d2a261d61425e031c2e18f032b Mon Sep 17 00:00:00 2001 From: Zeeshan Ahmad Date: Tue, 23 Jan 2024 12:00:38 +0500 Subject: [PATCH 006/132] Change feed name back --- apps/builddao/widget/GeneralFeed.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/builddao/widget/GeneralFeed.jsx b/apps/builddao/widget/GeneralFeed.jsx index 036473a2..c77c8ac2 100644 --- a/apps/builddao/widget/GeneralFeed.jsx +++ b/apps/builddao/widget/GeneralFeed.jsx @@ -40,7 +40,7 @@ function formatDate(date) { const daoName = "Build DAO"; const feedLink = "https://nearbuilders.org/feed"; -const daoTag = "testDao"; +const daoTag = "build"; const feeds = { resolutions: { From db358f858d48e76471b2cf80ed8be499aa8313b0 Mon Sep 17 00:00:00 2001 From: Zeeshan Ahmad Date: Tue, 23 Jan 2024 12:30:32 +0500 Subject: [PATCH 007/132] More style improvements and link navigation --- apps/builddao/widget/Compose.jsx | 34 ++----------------- apps/builddao/widget/GeneralFeed.jsx | 28 ++++++++++----- apps/builddao/widget/components/Post.jsx | 20 +++++------ .../widget/components/post/Content.jsx | 2 +- 4 files changed, 33 insertions(+), 51 deletions(-) diff --git a/apps/builddao/widget/Compose.jsx b/apps/builddao/widget/Compose.jsx index 9542195f..2ed3c09d 100644 --- a/apps/builddao/widget/Compose.jsx +++ b/apps/builddao/widget/Compose.jsx @@ -171,7 +171,7 @@ const PostCreator = styled.div` gap: 1.5rem; padding: 1rem; - background: #23242b; + background: var(--compose-bg, #23242b); border-radius: 12px; margin-bottom: 1rem; @@ -373,36 +373,6 @@ const MarkdownPreview = styled.div` } `; -const LabelSelect = styled.div` - label { - color: #fff; - } - - .rbt-input-multi { - background: #23242b !important; - color: #fff !important; - } - - .rbt-token { - background: #202020 !important; - color: #fff !important; - } - - .rbt-menu { - background: #23242b !important; - color: #fff !important; - - .dropdown-item { - color: #fff !important; - transition: all 300ms; - - &:hover { - background: #202020; - } - } - } -`; - const avatarComponent = useMemo(() => { return (
@@ -428,7 +398,7 @@ return ( src="mob.near/widget/MarkdownEditorIframe" props={{ initialText: postContent, - embedCss: MarkdownEditor, + embedCss: props.customCSS || MarkdownEditor, onChange: (v) => { setPostContent(v); Storage.privateSet(draftKey, v || ""); diff --git a/apps/builddao/widget/GeneralFeed.jsx b/apps/builddao/widget/GeneralFeed.jsx index c77c8ac2..4d81e340 100644 --- a/apps/builddao/widget/GeneralFeed.jsx +++ b/apps/builddao/widget/GeneralFeed.jsx @@ -1,15 +1,15 @@ const { Feed } = VM.require("devs.near/widget/Module.Feed") || (() => <>); -const { Post, Button } = VM.require("buildhub.near/widget/components") || { +const { Post, ButtonLink } = VM.require("buildhub.near/widget/components") || { Post: () => <>, - Button: () => <>, + ButtonLink: () => <>, }; const Theme = styled.div` --stroke-color: rgba(255, 255, 255, 0.2); --bg-1: #0b0c14; - --bg-2: ##23242b; --bg-1-hover: #17181c; --bg-1-hover-transparent: rgba(23, 24, 28, 0); + --bg-2: ##23242b; --label-color: #fff; --font-color: #fff; --font-muted-color: #cdd0d5; @@ -17,7 +17,10 @@ const Theme = styled.div` --system-red: #fd2a5c; --yellow: #ffaf51; - --post-bg: #23242b; + --compose-bg: #23242b; + + --post-bg: #0b0c14; + --post-bg-hover: #17181c; --post-bg-transparent: rgba(23, 24, 28, 0); --button-primary-bg: #ffaf51; @@ -175,7 +178,14 @@ const feeds = { }, }; -const tab = props.tab || "resolutions"; +if (!feeds) { + return ""; +} + +const tab = props.tab || Object.keys(feeds)[0]; +if (Object.keys(feeds).includes(props.hashtag)) { + tab = props.hashtag; +} const [activeFeed, setActiveFeed] = useState(tab); return ( @@ -186,20 +196,22 @@ return ( sideContent: Object.keys(feeds || {}).map((route) => { const data = feeds[route]; return ( - + ); }), mainContent: ( diff --git a/apps/builddao/widget/components/Post.jsx b/apps/builddao/widget/components/Post.jsx index 4106a19b..bf8b7fd9 100644 --- a/apps/builddao/widget/components/Post.jsx +++ b/apps/builddao/widget/components/Post.jsx @@ -9,16 +9,16 @@ const StyledPost = styled.div` border: 1px solid var(--stroke-color, rgba(255, 255, 255, 0.2)); color: var(--font-muted-color, #b6b6b8); padding: 24px !important; - background-color: var(--bg-1, #23242b); + background-color: var(--post-bg, #23242b); transition: all 300ms; &:hover { - background-color: var(--bg-1-hover, #17181c) !important; + background-color: var(--post-bg-hover, #17181c) !important; .expand-post { background-image: linear-gradient( to bottom, - var(--bg-1-hover-transparent, rgba(23, 24, 28, 0)), - var(--bg-1-hover, #17181c) 25% + var(--post-bg-hover-transparent, rgba(23, 24, 28, 0)), + var(--post-bg-hover, #17181c) 25% ) !important; } } @@ -38,21 +38,21 @@ const StyledPost = styled.div` .expand-post { background-image: linear-gradient( to bottom, - var(--post-bg, rgba(35, 36, 43, 0)), - var(--post-bg-transparent, rgba(35, 36, 43, 1)) 25% + var(--post-bg-transparent, rgba(35, 36, 43, 0)), + var(--post-bg, rgba(35, 36, 43, 1)) 25% ) !important; } } .dropdown-menu { - background-color: var(--bg-1, #0b0c14) !important; + background-color: var(--post-bg, #0b0c14) !important; color: var(--font-color, #fff) !important; li.dropdown-item { color: var(--font-color, #fff) !important; &:hover { a { - color: var(--bg-1, #0b0c14) !important; + color: var(--post-bg, #0b0c14) !important; } } } @@ -62,10 +62,10 @@ const StyledPost = styled.div` color: var(--font-color, #fff) !important; &:hover { - color: var(--bg-1, #0b0c14) !important; + color: var(--post-bg, #0b0c14) !important; span { - color: var(--bg-1, #0b0c14) !important; + color: var(--post-bg, #0b0c14) !important; } } } diff --git a/apps/builddao/widget/components/post/Content.jsx b/apps/builddao/widget/components/post/Content.jsx index 83039a20..cc7f49a0 100644 --- a/apps/builddao/widget/components/post/Content.jsx +++ b/apps/builddao/widget/components/post/Content.jsx @@ -59,7 +59,7 @@ const [onHashtag] = useState(() => (hashtag) => ( className="d-inline-flex" style={{ color: "var(--bs-link-color)" }} > - #{hashtag} + #{hashtag} )); From 1e3747e5fc054cbf1cb5e66122298885c10f8179 Mon Sep 17 00:00:00 2001 From: Zeeshan Ahmad Date: Tue, 23 Jan 2024 20:12:54 +0500 Subject: [PATCH 008/132] Add required tag --- apps/builddao/widget/GeneralFeed.jsx | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/apps/builddao/widget/GeneralFeed.jsx b/apps/builddao/widget/GeneralFeed.jsx index 4d81e340..c5b1ea51 100644 --- a/apps/builddao/widget/GeneralFeed.jsx +++ b/apps/builddao/widget/GeneralFeed.jsx @@ -240,7 +240,19 @@ return ( index={[ { action: "hashtag", - key: feeds[activeFeed].hashtag, + key: feeds[activeFeed].hashtag, // resolution + options: { + limit: 10, + order: "desc", + }, + cacheOptions: { + ignoreCache: true, + }, + required: true, + }, + { + action: "hashtag", + key: daoTag, // build options: { limit: 10, order: "desc", From b1e8a318954037edc88cfcadb67b5931667f802c Mon Sep 17 00:00:00 2001 From: Zeeshan Ahmad Date: Tue, 23 Jan 2024 20:23:03 +0500 Subject: [PATCH 009/132] add css variables to config --- apps/builddao/widget/config.jsx | 85 ++++++++++++++++++++++----------- 1 file changed, 58 insertions(+), 27 deletions(-) diff --git a/apps/builddao/widget/config.jsx b/apps/builddao/widget/config.jsx index 2d71b26e..7d0abafb 100644 --- a/apps/builddao/widget/config.jsx +++ b/apps/builddao/widget/config.jsx @@ -1,32 +1,63 @@ +const theme = ` + --stroke-color: rgba(255, 255, 255, 0.2); + --bg-1: #0b0c14; + --bg-1-hover: #17181c; + --bg-1-hover-transparent: rgba(23, 24, 28, 0); + --bg-2: ##23242b; + --label-color: #fff; + --font-color: #fff; + --font-muted-color: #cdd0d5; + --black: #000; + --system-red: #fd2a5c; + --yellow: #ffaf51; + + --compose-bg: #23242b; + + --post-bg: #0b0c14; + --post-bg-hover: #17181c; + --post-bg-transparent: rgba(23, 24, 28, 0); + + --button-primary-bg: #ffaf51; + --button-outline-bg: transparent; + --button-default-bg: #23242b; + + --button-primary-color: #000; + --button-outline-color: #fff; + --button-default-color: #cdd0d5; + + --button-primary-hover-bg: #e49b48; + --button-outline-hover-bg: rgba(255, 255, 255, 0.2); + --button-default-hover-bg: #17181c; +`; + return { - "type": "app", - "routes": { - "home": { - "path": "buildhub.near/widget/page.home", - "blockHeight": "final", - "init": { - "name": "Home", - "icon": "bi bi-house" - } + type: "app", + routes: { + home: { + path: "buildhub.near/widget/page.home", + blockHeight: "final", + init: { + name: "Home", + icon: "bi bi-house", + }, }, - "feed": { - "path": "buildhub.near/widget/page.feed", - "blockHeight": "final", - "init": { - "icon": "bi bi-globe" - } + feed: { + path: "buildhub.near/widget/page.feed", + blockHeight: "final", + init: { + icon: "bi bi-globe", + }, }, - "inspect": { - "path": "mob.near/widget/WidgetSource", - "blockHeight": "final", - "hide": true + inspect: { + path: "mob.near/widget/WidgetSource", + blockHeight: "final", + hide: true, + }, + notifications: { + path: "mob.near/widget/NotificationFeed", + blockHeight: "final", + hide: true, }, - "notifications": { - "path": "mob.near/widget/NotificationFeed", - "blockHeight": "final", - "hide": true - } }, - "theme": "background-color: white;" -} -; \ No newline at end of file + theme: theme, +}; From 5b65548397b524a30a62f0b973fb52bcefce2202 Mon Sep 17 00:00:00 2001 From: Zeeshan Ahmad Date: Tue, 23 Jan 2024 20:34:59 +0500 Subject: [PATCH 010/132] Abstract theme and aside content of feed to config --- apps/builddao/widget/GeneralFeed.jsx | 180 +----------------- .../builddao/widget/components/ButtonLink.jsx | 2 +- apps/builddao/widget/config.jsx | 146 ++++++++++++++ 3 files changed, 153 insertions(+), 175 deletions(-) diff --git a/apps/builddao/widget/GeneralFeed.jsx b/apps/builddao/widget/GeneralFeed.jsx index c5b1ea51..942755e8 100644 --- a/apps/builddao/widget/GeneralFeed.jsx +++ b/apps/builddao/widget/GeneralFeed.jsx @@ -4,179 +4,11 @@ const { Post, ButtonLink } = VM.require("buildhub.near/widget/components") || { ButtonLink: () => <>, }; -const Theme = styled.div` - --stroke-color: rgba(255, 255, 255, 0.2); - --bg-1: #0b0c14; - --bg-1-hover: #17181c; - --bg-1-hover-transparent: rgba(23, 24, 28, 0); - --bg-2: ##23242b; - --label-color: #fff; - --font-color: #fff; - --font-muted-color: #cdd0d5; - --black: #000; - --system-red: #fd2a5c; - --yellow: #ffaf51; +const daoName = props.daoName || "Build DAO"; +const feedLink = props.feedLink || "https://nearbuilders.org/feed"; +const daoTag = props.daoTag || "build"; - --compose-bg: #23242b; - - --post-bg: #0b0c14; - --post-bg-hover: #17181c; - --post-bg-transparent: rgba(23, 24, 28, 0); - - --button-primary-bg: #ffaf51; - --button-outline-bg: transparent; - --button-default-bg: #23242b; - - --button-primary-color: #000; - --button-outline-color: #fff; - --button-default-color: #cdd0d5; - - --button-primary-hover-bg: #e49b48; - --button-outline-hover-bg: rgba(255, 255, 255, 0.2); - --button-default-hover-bg: #17181c; -`; - -function formatDate(date) { - const options = { year: "numeric", month: "short", day: "numeric" }; - return date.toLocaleDateString("en-US", options); -} - -const daoName = "Build DAO"; -const feedLink = "https://nearbuilders.org/feed"; -const daoTag = "build"; - -const feeds = { - resolutions: { - label: "Resolutions", - icon: "bi-calendar3", - name: "resolution", - hashtag: "nearyearresolutions2024", - template: `### 🎉 NEAR YEAR RESOLUTIONS: 2024 - (posted via [${daoName} Gateway](${feedLink})) - - **🌟 REFLECTIONS ON THE PAST YEAR:** - - [Reflection 1 from the past year] - - [Reflection 2 from the past year] - - **🎯 NEW YEAR'S RESOLUTIONS:** - - [Resolution 1] - - [Resolution 2] - - **📊 MEASURING SUCCESS:** - - [Metric 1 for Success] - - [Metric 2 for Success] - `, - }, - updates: { - label: "Updates", - icon: "bi-bell", - name: "update", - hashtag: "update", - template: `### BUILDER UPDATE: ${formatDate(new Date())} - (posted via [${daoName} Gateway](${feedLink}?tab=update)) - - **✅ DONE** - - [what'd you do] - - [link proof] - - **⏩ NEXT** - - [what's next?] - - [what are you thinking about?] - - **🛑 BLOCKERS** - - [what's blocking you?] - - [how can someone help?] - `, - }, - documentation: { - label: "Documentation", - icon: "bi-book", - name: "documentation", - hashtag: "documentation", - template: `## TITLE - (posted via [${daoName} Gateway](${feedLink}?tab=documentation)) - - **WHAT IS _____?** - - [context] - - [why is it important?] - - **EXAMPLE** - - [how can this be demonstrated?] - - [what is the expected outcome?] - - **USAGE** - - [where is it used?] - - [how to use it] - `, - }, - question: { - label: "Question", - icon: "bi-question-lg", - name: "question", - hashtag: "question", - template: `## what is your question? - (posted via [${daoName} Gateway](${feedLink}?tab=question)) - - [what are you thinking about?] - [why are you asking?] - `, - }, - answer: { - label: "Answer", - icon: "bi-journal-code", - name: "answer", - hashtag: "answer", - template: `## Share an answer - (posted via [${daoName} Gateway](${feedLink}?tab=answer)) - - [please restate the question you are answering] - - [your answer] - - [link to relevant docs, examples, or resources] - `, - }, - opportunity: { - label: "Opportunity", - icon: "bi-briefcase", - name: "opportunity", - hashtag: "opportunity", - template: `## TITLE - (posted via [${daoName} Gateway](${feedLink}?tab=opportunity)) - - [what is the opportunity?] - - [explain the motivation or reason] - - `, - }, - idea: { - label: "Idea", - icon: "bi-lightbulb", - name: "idea", - hashtag: "idea", - template: ``, - }, - task: { - label: "Task", - icon: "bi-check-lg", - name: "task", - template: `## TASK TITLE - (posted via [${daoName} Gateway](${feedLink}?tab=task)) - - **What needs to be done?** - - [Describe the task or action steps] - - **Context or additional information:** - - [Provide any context or details] - `, - }, - bookmarks: { - label: "Bookmarks", - icon: "bi-bookmark", - name: "bookmark", - }, -}; +const feeds = props.feeds || {}; if (!feeds) { return ""; @@ -189,7 +21,7 @@ if (Object.keys(feeds).includes(props.hashtag)) { const [activeFeed, setActiveFeed] = useState(tab); return ( - + <> - + ); diff --git a/apps/builddao/widget/components/ButtonLink.jsx b/apps/builddao/widget/components/ButtonLink.jsx index 11283685..f9a3978c 100644 --- a/apps/builddao/widget/components/ButtonLink.jsx +++ b/apps/builddao/widget/components/ButtonLink.jsx @@ -41,7 +41,7 @@ const StyledLink = styled.a` default: return "var(--button-default-color, #CDD0D5)"; } - }}; + }} !important; border: ${(props) => props.variant === "outline" diff --git a/apps/builddao/widget/config.jsx b/apps/builddao/widget/config.jsx index 7d0abafb..6b57fa9b 100644 --- a/apps/builddao/widget/config.jsx +++ b/apps/builddao/widget/config.jsx @@ -1,3 +1,8 @@ +function formatDate(date) { + const options = { year: "numeric", month: "short", day: "numeric" }; + return date.toLocaleDateString("en-US", options); +} + const theme = ` --stroke-color: rgba(255, 255, 255, 0.2); --bg-1: #0b0c14; @@ -30,6 +35,139 @@ const theme = ` --button-default-hover-bg: #17181c; `; +const feeds = { + resolutions: { + label: "Resolutions", + icon: "bi-calendar3", + name: "resolution", + hashtag: "nearyearresolutions2024", + template: `### 🎉 NEAR YEAR RESOLUTIONS: 2024 + (posted via [${daoName} Gateway](${feedLink})) + + **🌟 REFLECTIONS ON THE PAST YEAR:** + - [Reflection 1 from the past year] + - [Reflection 2 from the past year] + + **🎯 NEW YEAR'S RESOLUTIONS:** + - [Resolution 1] + - [Resolution 2] + + **📊 MEASURING SUCCESS:** + - [Metric 1 for Success] + - [Metric 2 for Success] + `, + }, + updates: { + label: "Updates", + icon: "bi-bell", + name: "update", + hashtag: "update", + template: `### BUILDER UPDATE: ${formatDate(new Date())} + (posted via [${daoName} Gateway](${feedLink}?tab=update)) + + **✅ DONE** + - [what'd you do] + - [link proof] + + **⏩ NEXT** + - [what's next?] + - [what are you thinking about?] + + **🛑 BLOCKERS** + - [what's blocking you?] + - [how can someone help?] + `, + }, + documentation: { + label: "Documentation", + icon: "bi-book", + name: "documentation", + hashtag: "documentation", + template: `## TITLE + (posted via [${daoName} Gateway](${feedLink}?tab=documentation)) + + **WHAT IS _____?** + - [context] + - [why is it important?] + + **EXAMPLE** + - [how can this be demonstrated?] + - [what is the expected outcome?] + + **USAGE** + - [where is it used?] + - [how to use it] + `, + }, + question: { + label: "Question", + icon: "bi-question-lg", + name: "question", + hashtag: "question", + template: `## what is your question? + (posted via [${daoName} Gateway](${feedLink}?tab=question)) + + [what are you thinking about?] + [why are you asking?] + `, + }, + answer: { + label: "Answer", + icon: "bi-journal-code", + name: "answer", + hashtag: "answer", + template: `## Share an answer + (posted via [${daoName} Gateway](${feedLink}?tab=answer)) + + [please restate the question you are answering] + + [your answer] + + [link to relevant docs, examples, or resources] + `, + }, + opportunity: { + label: "Opportunity", + icon: "bi-briefcase", + name: "opportunity", + hashtag: "opportunity", + template: `## TITLE + (posted via [${daoName} Gateway](${feedLink}?tab=opportunity)) + + [what is the opportunity?] + + [explain the motivation or reason] + + `, + }, + idea: { + label: "Idea", + icon: "bi-lightbulb", + name: "idea", + hashtag: "idea", + template: ``, + }, + task: { + label: "Task", + icon: "bi-check-lg", + name: "task", + template: `## TASK TITLE + (posted via [${daoName} Gateway](${feedLink}?tab=task)) + + **What needs to be done?** + - [Describe the task or action steps] + + **Context or additional information:** + - [Provide any context or details] + `, + }, + bookmarks: { + label: "Bookmarks", + icon: "bi-bookmark", + name: "bookmark", + }, +}; + return { type: "app", routes: { @@ -48,6 +186,14 @@ return { icon: "bi bi-globe", }, }, + generalFeed: { + path: "buildhub.near/widget/GeneralFeed", + blockHeight: "final", + init: { + icon: "bi bi-globe", + feeds: feeds, + }, + }, inspect: { path: "mob.near/widget/WidgetSource", blockHeight: "final", From 63e16b02036356406b05662475e21b899e4fe566 Mon Sep 17 00:00:00 2001 From: Zeeshan Ahmad Date: Wed, 24 Jan 2024 07:59:48 +0500 Subject: [PATCH 011/132] Create Modal for Drafts --- apps/builddao/widget/Compose.jsx | 186 +++++++++++------- apps/builddao/widget/components/Modal.jsx | 14 +- .../widget/components/modals/DraftModal.jsx | 82 ++++++++ 3 files changed, 199 insertions(+), 83 deletions(-) create mode 100644 apps/builddao/widget/components/modals/DraftModal.jsx diff --git a/apps/builddao/widget/Compose.jsx b/apps/builddao/widget/Compose.jsx index d5a42980..8caa364c 100644 --- a/apps/builddao/widget/Compose.jsx +++ b/apps/builddao/widget/Compose.jsx @@ -3,6 +3,10 @@ const { Avatar, Button } = VM.require("buildhub.near/widget/components") || { Button: () => <>, }; +const { DraftModal } = + VM.require("buildhub.near/widget/components.modals.DraftModal") || + (() => <>); + const draftKey = props.feed.name || "draft"; const draft = Storage.privateGet(draftKey); @@ -486,6 +490,20 @@ const LabelSelect = styled.div` } `; +const [postUUID, setPostUUID] = useState(generateUID()); +const memoizedPostUUID = useMemo(() => postUUID, [postUUID]); + +useEffect(() => { + if (postContent === "") { + setPostUUID(generateUID()); + } +}, [postContent]); + +const setPostToTest = () => { + textareaInputHandler("Test"); + setPostUUID(generateUID()); +}; + const avatarComponent = useMemo(() => { return (
@@ -497,89 +515,105 @@ const avatarComponent = useMemo(() => { ); }, [context.accountId]); +const [showDraftsModal, setShowDraftsModal] = useState(false); + return ( - - {avatarComponent} -
- {view === "editor" ? ( - - { - textareaInputHandler(content); - }, - embedCss: MarkdownEditor, - }} - /> - {autocompleteEnabled && showAccountAutocomplete && ( +
+ + setShowDraftsModal(!showDraftsModal)} + children={
Test
} + /> + + {avatarComponent} +
+ {view === "editor" ? ( + setShowAccountAutocomplete(false), + initialText: postContent, + data: { handler: handler, content: postContent }, + onChange: (content) => { + textareaInputHandler(content); + }, + embedCss: MarkdownEditor, }} /> - )} - - ) : ( - - - {state.image.cid && ( + {autocompleteEnabled && showAccountAutocomplete && ( + setShowAccountAutocomplete(false), + }} + /> + )} + + ) : ( + - )} - - )} -
+ {state.image.cid && ( + + )} + + )} +
-
- {view === "editor" && ( - - )} - - -
- + + +
+
+
); diff --git a/apps/builddao/widget/components/Modal.jsx b/apps/builddao/widget/components/Modal.jsx index db7409fe..c029e3b7 100644 --- a/apps/builddao/widget/components/Modal.jsx +++ b/apps/builddao/widget/components/Modal.jsx @@ -22,7 +22,7 @@ const Content = styled.div` max-width: 1000px; padding: 24px; outline: none !important; - background: #23242B; + background: #23242b; border-radius: 16px; color: white; `; @@ -36,14 +36,14 @@ const NoButton = styled.button` `; const CloseContainer = styled.div` - display: flex; - justify-content: flex-end; - width: 100%; - padding-bottom: 24px; + display: flex; + justify-content: flex-end; + width: 100%; + padding-bottom: 24px; `; const Icon = styled.i` - font-size: 24px; + font-size: 24px; `; function Modal({ children, open, onOpenChange, toggle, toggleContainerProps }) { @@ -72,4 +72,4 @@ function Modal({ children, open, onOpenChange, toggle, toggleContainerProps }) { ); } -return { Modal }; \ No newline at end of file +return { Modal }; diff --git a/apps/builddao/widget/components/modals/DraftModal.jsx b/apps/builddao/widget/components/modals/DraftModal.jsx new file mode 100644 index 00000000..0f0c9aab --- /dev/null +++ b/apps/builddao/widget/components/modals/DraftModal.jsx @@ -0,0 +1,82 @@ +const { Button } = VM.require("buildhub.near/widget/components.Button"); + +const toggle = props.toggle ?? ; + +const Overlay = styled.div` + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + display: grid; + place-items: center; + overflow-y: auto; + z-index: 1000; + width: 100vw; + height: 100vh; + background: rgba(11, 12, 20, 0.5); +`; + +const Content = styled.div` + min-width: 500px; + max-width: 1000px; + padding: 24px; + outline: none !important; + background: #23242b; + border-radius: 16px; + color: white; +`; + +const NoButton = styled.button` + background: transparent; + border: none; + padding: 0; + margin: 0; + box-shadow: none; +`; + +const CloseContainer = styled.div` + display: flex; + justify-content: flex-end; + width: 100%; + padding-bottom: 24px; +`; + +const Icon = styled.i` + font-size: 24px; +`; + +function DraftModal({ + children, + open, + onOpenChange, + toggle, + toggleContainerProps, +}) { + return ( + + + {toggle} + + + + + +
+ +

+ Drafts +

+
+ +
+ {children} +
+
+
+
+
+ ); +} + +return { DraftModal }; From e6921e33fc6cab17decb34614126e0d76822da4e Mon Sep 17 00:00:00 2001 From: Zeeshan Ahmad Date: Wed, 24 Jan 2024 08:10:21 +0500 Subject: [PATCH 012/132] Save drafts --- apps/builddao/widget/Compose.jsx | 39 ++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/apps/builddao/widget/Compose.jsx b/apps/builddao/widget/Compose.jsx index 8caa364c..5070c88f 100644 --- a/apps/builddao/widget/Compose.jsx +++ b/apps/builddao/widget/Compose.jsx @@ -504,6 +504,32 @@ const setPostToTest = () => { setPostUUID(generateUID()); }; +const onSaveDraft = () => { + const savedDrafts = Storage.privateGet("savedDrafts") || ""; + const drafts = JSON.parse(savedDrafts) || []; + drafts.push(postContent); + Storage.privateSet("savedDrafts", JSON.stringify(drafts)); +}; + +const renderDrafts = () => { + const savedDrafts = Storage.privateGet("savedDrafts") || ""; + const drafts = JSON.parse(savedDrafts) || []; + + return ( +
+ {drafts.map((draft, i) => ( +
+ {draft} +
+ ))} + {drafts.length === 0 &&

No drafts saved

} +
+ ); +}; + const avatarComponent = useMemo(() => { return (
@@ -529,10 +555,19 @@ return ( setShowDraftsModal(!showDraftsModal)} - children={
Test
} + children={ +
+ +
+ } /> - {avatarComponent} +
+ {avatarComponent} + +
{view === "editor" ? ( Date: Wed, 24 Jan 2024 10:16:49 +0500 Subject: [PATCH 013/132] Handle deletion of drafts --- apps/builddao/widget/Compose.jsx | 140 +++++++++++++++--- apps/builddao/widget/components/Checkbox.jsx | 14 +- .../widget/components/modals/DraftModal.jsx | 9 +- 3 files changed, 132 insertions(+), 31 deletions(-) diff --git a/apps/builddao/widget/Compose.jsx b/apps/builddao/widget/Compose.jsx index 5070c88f..92a597da 100644 --- a/apps/builddao/widget/Compose.jsx +++ b/apps/builddao/widget/Compose.jsx @@ -490,6 +490,7 @@ const LabelSelect = styled.div` } `; +// To handle ifram refresh in order to trigger initialText change const [postUUID, setPostUUID] = useState(generateUID()); const memoizedPostUUID = useMemo(() => postUUID, [postUUID]); @@ -499,11 +500,32 @@ useEffect(() => { } }, [postContent]); -const setPostToTest = () => { - textareaInputHandler("Test"); - setPostUUID(generateUID()); +const avatarComponent = useMemo(() => { + return ( +
+ +
+

{context.accountId}

+
+
+ ); +}, [context.accountId]); + +// for drafts +const [showDraftsModal, setShowDraftsModal] = useState(false); +const [draftEditMode, setDraftEditMode] = useState(false); +const [checkedDrafts, setCheckDrafts] = useState([]); + +// handle deletion of drafts +const handleDraftDelete = () => { + const savedDrafts = Storage.privateGet("savedDrafts") || ""; + const drafts = JSON.parse(savedDrafts); + const newDrafts = drafts.filter((draft, i) => !checkedDrafts.includes(i)); + Storage.privateSet("savedDrafts", JSON.stringify(newDrafts)); + setCheckDrafts([]); }; +// handle draft save const onSaveDraft = () => { const savedDrafts = Storage.privateGet("savedDrafts") || ""; const drafts = JSON.parse(savedDrafts) || []; @@ -511,37 +533,89 @@ const onSaveDraft = () => { Storage.privateSet("savedDrafts", JSON.stringify(drafts)); }; -const renderDrafts = () => { +const DraftLabel = styled.span` + display: inline-flex; + padding: 12px; + align-items: center; + gap: 8px; + + color: #fff; + font-size: 16px; + font-style: normal; + font-weight: 400; + line-height: 170%; /* 27.2px */ +`; + +const DraftItem = ({ draft, checked, isEdit }) => { + return ( +
+ + {isEdit && ( + + )} + {draft} + +
+ ); +}; + +const RenderDrafts = () => { const savedDrafts = Storage.privateGet("savedDrafts") || ""; - const drafts = JSON.parse(savedDrafts) || []; + const drafts = JSON.parse(savedDrafts); + + const handleDraftSelect = (draft) => { + textareaInputHandler(draft); + setPostUUID(generateUID()); + setShowDraftsModal(false); + setView("editor"); + }; return (
{drafts.map((draft, i) => ( -
- {draft} +
handleDraftSelect(draft)}> +
))} - {drafts.length === 0 &&

No drafts saved

} + {drafts.length === 0 &&

No drafts saved

}
); }; -const avatarComponent = useMemo(() => { +const EditDrafts = () => { + const savedDrafts = Storage.privateGet("savedDrafts") || ""; + const drafts = JSON.parse(savedDrafts); + + const handleDraftSelect = (draftIndex) => { + if (checkedDrafts.includes(draftIndex)) { + setCheckDrafts(checkedDrafts.filter((draft) => draft !== draftIndex)); + } else { + setCheckDrafts([...checkedDrafts, draftIndex]); + } + }; + return ( -
- -
-

{context.accountId}

-
+
+ {drafts.map((draft, i) => ( +
handleDraftSelect(i)}> + +
+ ))} + {drafts.length === 0 &&

No drafts saved

}
); -}, [context.accountId]); - -const [showDraftsModal, setShowDraftsModal] = useState(false); +}; return (
@@ -555,11 +629,29 @@ return ( setShowDraftsModal(!showDraftsModal)} - children={ -
- -
+ editButton={ + draftEditMode ? ( +
+ + +
+ ) : ( + + ) } + children={
{draftEditMode ? : }
} />
diff --git a/apps/builddao/widget/components/Checkbox.jsx b/apps/builddao/widget/components/Checkbox.jsx index 27387079..1f3bed49 100644 --- a/apps/builddao/widget/components/Checkbox.jsx +++ b/apps/builddao/widget/components/Checkbox.jsx @@ -7,6 +7,8 @@ const CheckboxLabel = styled.label` padding: 12px; align-items: center; gap: 8px; + cursor: pointer; + max-width: 100%; color: #fff; font-size: 16px; @@ -15,20 +17,20 @@ const CheckboxLabel = styled.label` line-height: 170%; /* 27.2px */ `; -function Checkbox({ value, onChange, label }) { +function Checkbox({ className, value, onChange, label }) { return ( -
+
{value ? ( - + ) : ( - + )} - {label} + {label}
); } -return { Checkbox }; \ No newline at end of file +return { Checkbox }; diff --git a/apps/builddao/widget/components/modals/DraftModal.jsx b/apps/builddao/widget/components/modals/DraftModal.jsx index 0f0c9aab..825338a6 100644 --- a/apps/builddao/widget/components/modals/DraftModal.jsx +++ b/apps/builddao/widget/components/modals/DraftModal.jsx @@ -25,6 +25,12 @@ const Content = styled.div` background: #23242b; border-radius: 16px; color: white; + + @media screen and (max-width: 768px) { + max-width: 90%; + min-width: 50%; + width: 100%; + } `; const NoButton = styled.button` @@ -52,6 +58,7 @@ function DraftModal({ onOpenChange, toggle, toggleContainerProps, + editButton, }) { return ( @@ -68,7 +75,7 @@ function DraftModal({ Drafts

- + {editButton}
{children} From b116d139460e95b76c838e1d8291331cb1d663f1 Mon Sep 17 00:00:00 2001 From: Elliot Braem <16282460+elliotBraem@users.noreply.github.com> Date: Wed, 24 Jan 2024 10:54:03 -0500 Subject: [PATCH 014/132] Revert "Add Post Drafts" --- apps/builddao/widget/Compose.jsx | 414 +++--------------- apps/builddao/widget/components.jsx | 6 +- .../widget/components/AccountAutocomplete.jsx | 147 ------- apps/builddao/widget/components/Checkbox.jsx | 14 +- .../components/MarkdownEditorIframe.jsx | 64 --- apps/builddao/widget/components/Modal.jsx | 14 +- .../widget/components/modals/DraftModal.jsx | 89 ---- 7 files changed, 86 insertions(+), 662 deletions(-) delete mode 100644 apps/builddao/widget/components/AccountAutocomplete.jsx delete mode 100644 apps/builddao/widget/components/MarkdownEditorIframe.jsx delete mode 100644 apps/builddao/widget/components/modals/DraftModal.jsx diff --git a/apps/builddao/widget/Compose.jsx b/apps/builddao/widget/Compose.jsx index 92a597da..4c388232 100644 --- a/apps/builddao/widget/Compose.jsx +++ b/apps/builddao/widget/Compose.jsx @@ -1,33 +1,19 @@ -const { Avatar, Button } = VM.require("buildhub.near/widget/components") || { - Avatar: () => <>, - Button: () => <>, -}; +const { Avatar, Button } = VM.require("buildhub.near/widget/components"); -const { DraftModal } = - VM.require("buildhub.near/widget/components.modals.DraftModal") || - (() => <>); +Avatar = Avatar || (() => <>); +Button = Button || (() => <>); const draftKey = props.feed.name || "draft"; const draft = Storage.privateGet(draftKey); -const autocompleteEnabled = true; - if (draft === null) { return ""; } -State.init({ - image: {}, -}); - const [view, setView] = useState("editor"); const [postContent, setPostContent] = useState(""); const [hideAdvanced, setHideAdvanced] = useState(true); const [labels, setLabels] = useState([]); -const [showAccountAutocomplete, setShowAccountAutocomplete] = useState(false); -const [mentionsArray, setMentionsArray] = useState([]); -const [mentionInput, setMentionInput] = useState(null); -const [handler, setHandler] = useState("update"); setPostContent(draft || props.template); @@ -37,6 +23,16 @@ function generateUID() { return randomNumber.toString(16).padStart(8, "0"); } +function tagsFromLabels(labels) { + return labels.reduce( + (newLabels, label) => ({ + ...newLabels, + [label]: "", + }), + {} + ); +} + const extractMentions = (text) => { const mentionRegex = /@((?:(?:[a-z\d]+[-_])*[a-z\d]+\.)*(?:[a-z\d]+[-_])*[a-z\d]+)/gi; @@ -106,12 +102,6 @@ const postToCustomFeed = ({ feed, text, labels }) => { text = checkAndAppendHashtag(text, hashtag); }); - const content = { - type: "md", - image: state.image.cid ? { ipfs_cid: state.image.cid } : undefined, - text: text, - }; - const data = { // [feed.name]: { // [postId]: { @@ -127,7 +117,12 @@ const postToCustomFeed = ({ feed, text, labels }) => { // }, // }, post: { - main: JSON.stringify(content), + main: JSON.stringify({ + type: "md", + text, + // tags: tagsFromLabels(labels), + // postType: feed.name, + }), }, index: { post: JSON.stringify({ key: "main", value: { type: "md" } }), @@ -170,43 +165,6 @@ const postToCustomFeed = ({ feed, text, labels }) => { }); }; -function textareaInputHandler(value) { - const words = value.split(/\s+/); - const allMentiones = words - .filter((word) => word.startsWith("@")) - .map((mention) => mention.slice(1)); - const newMentiones = allMentiones.filter( - (item) => !mentionsArray.includes(item) - ); - setMentionInput(newMentiones?.[0] ?? ""); - setMentionsArray(allMentiones); - setShowAccountAutocomplete(newMentiones?.length > 0); - setPostContent(value); - setHandler("update"); - Storage.privateSet(draftKey, value || ""); -} - -function autoCompleteAccountId(id) { - let currentIndex = 0; - const updatedDescription = postContent.replace( - /(?:^|\s)(@[^\s]*)/g, - (match) => { - if (currentIndex === mentionsArray.indexOf(mentionInput)) { - currentIndex++; - return ` @${id}`; - } else { - currentIndex++; - return match; - } - } - ); - setPostContent(updatedDescription); - setShowAccountAutocomplete(false); - setMentionInput(null); - setHandler("autocompleteSelected"); - Storage.privateSet(draftKey, updatedDescription || ""); -} - const PostCreator = styled.div` display: flex; flex-direction: column; @@ -217,51 +175,6 @@ const PostCreator = styled.div` border-radius: 12px; margin-bottom: 1rem; - - .upload-image-button { - display: flex; - align-items: center; - justify-content: center; - background: #f1f3f5; - color: #11181c; - border-radius: 40px; - height: 40px; - min-width: 40px; - font-size: 0; - border: none; - cursor: pointer; - transition: background 200ms, opacity 200ms; - - &::before { - font-size: 16px; - } - - &:hover, - &:focus { - background: #d7dbde; - outline: none; - } - - &:disabled { - opacity: 0.5; - pointer-events: none; - } - - span { - margin-left: 12px; - } - } - - .d-inline-block { - display: flex !important; - gap: 12px; - margin: 0 !important; - - .overflow-hidden { - width: 40px !important; - height: 40px !important; - } - } `; const TextareaWrapper = styled.div` @@ -490,16 +403,6 @@ const LabelSelect = styled.div` } `; -// To handle ifram refresh in order to trigger initialText change -const [postUUID, setPostUUID] = useState(generateUID()); -const memoizedPostUUID = useMemo(() => postUUID, [postUUID]); - -useEffect(() => { - if (postContent === "") { - setPostUUID(generateUID()); - } -}, [postContent]); - const avatarComponent = useMemo(() => { return (
@@ -511,236 +414,63 @@ const avatarComponent = useMemo(() => { ); }, [context.accountId]); -// for drafts -const [showDraftsModal, setShowDraftsModal] = useState(false); -const [draftEditMode, setDraftEditMode] = useState(false); -const [checkedDrafts, setCheckDrafts] = useState([]); - -// handle deletion of drafts -const handleDraftDelete = () => { - const savedDrafts = Storage.privateGet("savedDrafts") || ""; - const drafts = JSON.parse(savedDrafts); - const newDrafts = drafts.filter((draft, i) => !checkedDrafts.includes(i)); - Storage.privateSet("savedDrafts", JSON.stringify(newDrafts)); - setCheckDrafts([]); -}; - -// handle draft save -const onSaveDraft = () => { - const savedDrafts = Storage.privateGet("savedDrafts") || ""; - const drafts = JSON.parse(savedDrafts) || []; - drafts.push(postContent); - Storage.privateSet("savedDrafts", JSON.stringify(drafts)); -}; - -const DraftLabel = styled.span` - display: inline-flex; - padding: 12px; - align-items: center; - gap: 8px; - - color: #fff; - font-size: 16px; - font-style: normal; - font-weight: 400; - line-height: 170%; /* 27.2px */ -`; - -const DraftItem = ({ draft, checked, isEdit }) => { - return ( -
- - {isEdit && ( - - )} - {draft} - -
- ); -}; - -const RenderDrafts = () => { - const savedDrafts = Storage.privateGet("savedDrafts") || ""; - const drafts = JSON.parse(savedDrafts); - - const handleDraftSelect = (draft) => { - textareaInputHandler(draft); - setPostUUID(generateUID()); - setShowDraftsModal(false); - setView("editor"); - }; - - return ( -
- {drafts.map((draft, i) => ( -
handleDraftSelect(draft)}> - -
- ))} - {drafts.length === 0 &&

No drafts saved

} -
- ); -}; - -const EditDrafts = () => { - const savedDrafts = Storage.privateGet("savedDrafts") || ""; - const drafts = JSON.parse(savedDrafts); - - const handleDraftSelect = (draftIndex) => { - if (checkedDrafts.includes(draftIndex)) { - setCheckDrafts(checkedDrafts.filter((draft) => draft !== draftIndex)); - } else { - setCheckDrafts([...checkedDrafts, draftIndex]); - } - }; - - return ( -
- {drafts.map((draft, i) => ( -
handleDraftSelect(i)}> - + {avatarComponent} +
+ {view === "editor" ? ( + + { + setPostContent(v); + Storage.privateSet(draftKey, v || ""); + }, + }} + /> + + ) : ( + + -
- ))} - {drafts.length === 0 &&

No drafts saved

} + + )}
- ); -}; -return ( -
- - setShowDraftsModal(!showDraftsModal)} - editButton={ - draftEditMode ? ( -
- - -
- ) : ( - - ) - } - children={
{draftEditMode ? : }
} - /> - -
- {avatarComponent} - -
-
+
+
- -
- {view === "editor" && ( - + <> + Edit + )} - - -
- -
+ + +
+ ); diff --git a/apps/builddao/widget/components.jsx b/apps/builddao/widget/components.jsx index b73c4264..38499bad 100644 --- a/apps/builddao/widget/components.jsx +++ b/apps/builddao/widget/components.jsx @@ -33,11 +33,7 @@ function Pagination({ function Post(props) { return ( - } - props={{ ...props }} - /> + ); } diff --git a/apps/builddao/widget/components/AccountAutocomplete.jsx b/apps/builddao/widget/components/AccountAutocomplete.jsx deleted file mode 100644 index 5823f397..00000000 --- a/apps/builddao/widget/components/AccountAutocomplete.jsx +++ /dev/null @@ -1,147 +0,0 @@ -if (!context.accountId || !props.term) return <>; - -let results = []; -const filterAccounts = props.filterAccounts ?? []; // hide certain accounts from the list -const profilesData = Social.get("*/profile/name", "final") || {}; -const followingData = Social.get( - `${context.accountId}/graph/follow/**`, - "final" -); -if (!profilesData) return <>; -const profiles = Object.entries(profilesData); -const term = (props.term || "").replace(/\W/g, "").toLowerCase(); -const limit = 5; - -for (let i = 0; i < profiles.length; i++) { - let score = 0; - const accountId = profiles[i][0]; - const accountIdSearch = profiles[i][0].replace(/\W/g, "").toLowerCase(); - const nameSearch = (profiles[i][1]?.profile?.name || "") - .replace(/\W/g, "") - .toLowerCase(); - const accountIdSearchIndex = accountIdSearch.indexOf(term); - const nameSearchIndex = nameSearch.indexOf(term); - - if (accountIdSearchIndex > -1 || nameSearchIndex > -1) { - score += 10; - - if (accountIdSearchIndex === 0) { - score += 10; - } - if (nameSearchIndex === 0) { - score += 10; - } - if (followingData[accountId] === "") { - score += 30; - } - - results.push({ - accountId, - score - }); - } -} - -results.sort((a, b) => b.score - a.score); -results = results.slice(0, limit); -if (filterAccounts?.length > 0) { - results = results.filter((item) => !filterAccounts?.includes(item.accountId)); -} - -function onResultClick(id) { - props.onSelect && props.onSelect(id); -} - -const Wrapper = styled.div` - position: relative; - - &::before { - content: ""; - display: block; - position: absolute; - right: 0; - width: 6px; - height: 100%; - z-index: 10; - } -`; - -const Scroller = styled.div` - position: relative; - display: flex; - padding: 6px; - gap: 6px; - overflow: auto; - scroll-behavior: smooth; - align-items: center; - scrollbar-width: none; - -ms-overflow-style: none; - &::-webkit-scrollbar { - display: none; - } - - > * { - max-width: 175px; - flex-grow: 0; - flex-shrink: 0; - - button { - border: 1px solid #eceef0; - background: #fff !important; - border-radius: 6px; - padding: 3px 6px; - transition: all 200ms; - - &:focus, - &:hover { - border-color: #687076; - } - } - } -`; - -const CloseButton = styled.button` - background: none; - border: none; - display: block; - padding: 12px; - color white; - transition: all 200ms; - - &:hover { - transform:scale(1.2); - } -`; - -const ProfileCardWrapper = styled.div` - opacity: 0.8; -`; - -if (results.length === 0) return <>; - -return ( - - - - - - - {results.map((result) => { - return ( - - - - ); - })} - - -); diff --git a/apps/builddao/widget/components/Checkbox.jsx b/apps/builddao/widget/components/Checkbox.jsx index 1f3bed49..27387079 100644 --- a/apps/builddao/widget/components/Checkbox.jsx +++ b/apps/builddao/widget/components/Checkbox.jsx @@ -7,8 +7,6 @@ const CheckboxLabel = styled.label` padding: 12px; align-items: center; gap: 8px; - cursor: pointer; - max-width: 100%; color: #fff; font-size: 16px; @@ -17,20 +15,20 @@ const CheckboxLabel = styled.label` line-height: 170%; /* 27.2px */ `; -function Checkbox({ className, value, onChange, label }) { +function Checkbox({ value, onChange, label }) { return ( -
+
{value ? ( - + ) : ( - + )} - {label} + {label}
); } -return { Checkbox }; +return { Checkbox }; \ No newline at end of file diff --git a/apps/builddao/widget/components/MarkdownEditorIframe.jsx b/apps/builddao/widget/components/MarkdownEditorIframe.jsx deleted file mode 100644 index ffb2e26b..00000000 --- a/apps/builddao/widget/components/MarkdownEditorIframe.jsx +++ /dev/null @@ -1,64 +0,0 @@ -const data = props.data ?? "# Hello World\n\n"; -const embedCss = props.embedCss || ""; - -const code = ` - - - - - - - -
- - -`; -return ( -