Skip to content

Commit

Permalink
Develop to main (#10)
Browse files Browse the repository at this point in the history
* wip index

* add ItemFeed

* add passProps to Router

* aliases

* Created a module for Image upload (#8)

* Add components (#7)

* Add components

* modify components.Index

* modify components.Index

* fmt

---------

Co-authored-by: Elliot Braem <[email protected]>

* version

---------

Co-authored-by: Jiku Godwill Nsanwi <[email protected]>
Co-authored-by: Zeeshan Ahmad <[email protected]>
  • Loading branch information
3 people authored Jul 17, 2024
1 parent b484b1d commit ce6604b
Show file tree
Hide file tree
Showing 49 changed files with 3,380 additions and 289 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/release-testnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ on:
push:
branches: [develop]
jobs:
deploy-mainnet:
deploy-testnet:
uses: NEARBuilders/bos-workspace/.github/workflows/deploy.yml@main
with:
bw-legacy: false
Expand Down
3 changes: 2 additions & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
node_modules/
node_modules/
build/
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "devs.near",
"version": "0.0.0",
"version": "0.0.1",
"description": "",
"author": "nearbuilders",
"license": "MIT",
Expand Down
71 changes: 71 additions & 0 deletions widget/Index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
const { Layout } = VM.require("${config_account}/widget/Layout") || {
Layout: () => <>layout not found</>,
};

const { Router } = VM.require("${config_account}/widget/Router") || {
Router: () => <>router not found</>,
};

const data = Social.index("post", "main", { order: "desc", limit: 1 });

const { accountId, blockHeight } = data && data.length && data[0];

// const item = {
// path: `${accountId}/post/main`,
// blockHeight: blockHeight,
// type: "social",
// };

// const item = {
// path: `mob.near/post/main`,
// blockHeight: "81101335",
// type: "social",
// };

const item = {
path: "efiz.near/thing/core",
};

const CSS = styled.div`
width: 100%,
height: 100vh;
`;

const Header = () => <div style={{ border: "solid" }}>header</div>;

const Footer = () => <>built by everyone :)</>;

const Sidebar = () => <>sidebar</>;

const Content = () => (
<Layout blocks={{ Header, Footer }}>
<div style={{ height: "60vh" }}>
"mob.near/post/main@81101335" // this is a very personal thing...
<p>{JSON.stringify(data)}</p>
<Router
config={{
param: "page",
routes: {
home: {
path: "every.near/widget/every.thing.view",
init: item,
},
home: {
path: "${config_account}/widget/Library",
init: item,
},
},
}}
page={"home"}
/>
</div>
</Layout>
);

return (
<CSS>
<Layout variant="sidebar" blocks={{ Sidebar, Header, Footer }}>
<Content />
</Layout>
</CSS>
);
104 changes: 104 additions & 0 deletions widget/IpfsImageUpload.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
const IPFSImageUpload = ({
key,
name,
className,
img,
setImg,
msg,
setMsg,
onError,
accepts,
multiple,
clickable,
maxFiles,
maxFileSize,
minFileSize,
dragActiveClassName,
}) => {
const attributes = {
key,
name,
className,
img,
setImg,
msg,
setMsg,
onError,
accepts,
multiple,
clickable,
maxFiles,
maxFileSize,
minFileSize,
dragActiveClassName,
};
const ipfsUrl = (cid) => `https://ipfs.near.social/ipfs/${cid}`;
const uploadFile = (files) => {
setMsg("Uploading...");

const file = files[0];

const uploadPromise = asyncFetch("https://ipfs.near.social/add", {
method: "POST",
headers: {
"Content-Type": file.type,
},
body: file,
})
.then((response) => {
if (!response.ok) {
setMsg("Upload failed!");
return Promise.reject(new Error("Upload failed"));
}
return response.body;
})
.then((data) => {
console.log(data);
setImg(data);
})
.catch((error) => {
console.error("Upload error:", error);
setMsg("Upload failed!");
})
.finally(() => {
setMsg("Replace Image");
});

uploadPromise
.then(() => {
console.log("Upload successful!");
})
.catch((error) => {
console.error("Upload failed:", error);
});
};
return (
<div className="d-inline-block" key={attributes.key}>
{img?.cid && (
<div
className="d-inline-block me-2 overflow-hidden align-middle"
style={{ width: "2.5em", height: "2.5em" }}
>
<img
className="rounded w-100 h-100"
style={{ objectFit: "cover" }}
src={ipfsUrl(img?.cid)}
alt="upload preview"
/>
</div>
)}
<Files
multiple={false}
accepts={["image/*"]}
minFileSize={1}
clickable
onChange={uploadFile}
{...attributes}
>
{msg}
</Files>
</div>
);
};

return { IPFSImageUpload };
32 changes: 32 additions & 0 deletions widget/PR/ItemFeed.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
const items = props.items;
const renderItem = props.renderItem;
const perPage = props.perPage || 10;

const jItems = JSON.stringify(items);
if (state.jItems !== jItems) {
State.update({
items: 0,
jItems,
});
}

const makeMoreItems = () => {
State.update({
items: state.items + perPage,
});
};

const Layout = props.Layout;

const renderedItems = items.slice(0, state.items).map(renderItem);

return (
<InfiniteScroll
pageStart={0}
loadMore={makeMoreItems}
hasMore={state.items < items.length}
loader={<div className="loader">Loading ...</div>}
>
{Layout ? <Layout>{renderedItems}</Layout> : <>{renderedItems}</>}
</InfiniteScroll>
);
18 changes: 2 additions & 16 deletions widget/Router.jsx
Original file line number Diff line number Diff line change
@@ -1,51 +1,38 @@
const { href } = VM.require("${config_account}/widget/lib.url") || {
href: () => "/",
};

const Content = styled.div`
width: 100%;
height: 100%;
`;

function findDefaultRoute(routesObject) {
const routeKey =
routesObject &&
Object.keys(routesObject).find((key) => {
const route = routesObject[key];
return route.default === true;
});

if (routeKey) {
return routesObject[routeKey];
} else {
return null;
}
}

function Router({ config, ...passProps }) {
const { routes, PageNotFound, debug, param } = config;

if (!param) param = "page";

const defaultRoute =
findDefaultRoute(routes) ??
(routes && Object.keys(routes).length && routes[Object.keys(routes)[0]]);
const defaultRoute = findDefaultRoute(routes);
const activeRoute =
(routes && routes.hasOwnProperty(passProps[param]) && routes[passProps[param]]) || defaultRoute;

if (!PageNotFound) PageNotFound = () => <p>404 Not Found</p>;

if (!activeRoute) {
// Handle 404 or default case for unknown routes
return <PageNotFound />;
}

// An improvement may be to "lazy load", e.g. load all widgets at once and only "display" the active one
// potentionally add a "lazy: true" prop to the route object

// for each route, if lazy, load the widget and store it in a map
// set display for the active route

// we may want to convert this to a widget for that purpose, to manage state?
if (debug) {
return (
Expand All @@ -59,12 +46,11 @@ function Router({ config, ...passProps }) {
<Content key={param + JSON.stringify(activeRoute)}>
<Widget
src={activeRoute.path}
props={activeRoute.init}
props={{ ...activeRoute.init, ...passProps }}
loading={<div style={{ height: "100%", width: "100%" }} />}
/>
</Content>
);
}
}

return { Router };
12 changes: 0 additions & 12 deletions widget/components.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ const Header = styled.div`

const Search = styled.div`
width: 246px;
@media (max-width: 500px) {
width: 100%;
}
Expand Down Expand Up @@ -106,16 +105,13 @@ const Text = styled.p`
text-overflow: ${(p) => (p.ellipsis ? "ellipsis" : "")};
white-space: ${(p) => (p.ellipsis ? "nowrap" : "")};
overflow-wrap: anywhere;
b {
font-weight: 600;
color: #11181c;
}
&[href] {
display: inline-flex;
gap: 0.25rem;
&:hover,
&:focus {
text-decoration: underline;
Expand All @@ -127,11 +123,9 @@ const Items = styled.div`
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 24px;
@media (max-width: 1200px) {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
@media (max-width: 800px) {
grid-template-columns: minmax(0, 1fr);
}
Expand All @@ -154,14 +148,12 @@ const Button = styled.button`
cursor: pointer;
color: #11181c !important;
margin: 0;
&:hover,
&:focus {
background: #ecedee;
text-decoration: none;
outline: none;
}
span {
color: #687076 !important;
}
Expand All @@ -174,13 +166,11 @@ const Tabs = styled.div`
margin-bottom: -24px;
overflow: auto;
scroll-behavior: smooth;
@media (max-width: 1200px) {
background: #f8f9fa;
border-top: 1px solid #eceef0;
margin-left: -12px;
margin-right: -12px;
> * {
flex: 1;
}
Expand All @@ -202,11 +192,9 @@ const TabsButton = styled.a`
outline: none;
text-align: center;
text-decoration: none !important;
&:hover {
color: #11181c;
}
&::after {
content: "";
display: ${(p) => (p.selected ? "block" : "none")};
Expand Down
19 changes: 19 additions & 0 deletions widget/components/Index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const { Avatar } = VM.require("${config_account}/widget/components.ui.avatar");
const { AvatarGroup } = VM.require("${config_account}/widget/components.ui.avatar-group");
const { Badge } = VM.require("${config_account}/widget/components.ui.badge");
const { Button } = VM.require("${config_account}/widget/components.ui.button");
const { Chip } = VM.require("${config_account}/widget/components.ui.chip");
const { Container } = VM.require("${config_account}/widget/components.ui.container");
const { Logo } = VM.require("${config_account}/widget/components.ui.logo");
const { Tag } = VM.require("${config_account}/widget/components.ui.tag");

return {
Avatar,
AvatarGroup,
Badge,
Button,
Chip,
Container,
Logo,
Tag,
};
Loading

0 comments on commit ce6604b

Please sign in to comment.