Skip to content

Commit

Permalink
Merge pull request #1 from itexpert120/homepage
Browse files Browse the repository at this point in the history
New Homepage
  • Loading branch information
elliotBraem authored Nov 8, 2023
2 parents 143d73f + fec8dfa commit df5015d
Show file tree
Hide file tree
Showing 26 changed files with 2,671 additions and 924 deletions.
3 changes: 2 additions & 1 deletion .eslintignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
workspaces/
build/
build/
apps/
204 changes: 204 additions & 0 deletions apps/homepage/widget/MetadataEditor.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
const initialMetadata = props.initialMetadata ?? {};
const onChange = props.onChange;
const options = props.options;

State.init({
initialMetadata,
metadata: initialMetadata,
reportedMetadata: initialMetadata,
linktree: initialMetadata.linktree ?? {},
image: initialMetadata.image,
backgroundImage: initialMetadata.backgroundImage,
screenshots: initialMetadata.screenshots ?? {},
});

const metadata = {
name: options.name ? state.metadata.name : undefined,
description: options.name ? state.metadata.description : undefined,
linktree:
options.linktree && Object.keys(state.linktree).length > 0
? state.linktree
: undefined,
image:
options.image && state.image && Object.keys(state.image).length > 0
? state.image
: undefined,
backgroundImage:
options.backgroundImage &&
state.backgroundImage &&
Object.keys(state.backgroundImage).length > 0
? state.backgroundImage
: undefined,
tags: options.tags ? state.metadata.tags : undefined,
screenshots: options.screenshots ? state.metadata.screenshots : undefined,
};

if (
onChange &&
JSON.stringify(state.reportedMetadata) !== JSON.stringify(metadata)
) {
State.update({
reportedMetadata: metadata,
});
onChange(metadata);
}

const Container = styled.div`
color: #fff;
`;

const CustomTagEditor = styled.div`
.form-control {
background: #23242b;
border: 1px solid rgba(255, 255, 255, 0.2);
}
`;

const CustomImageUpload = styled.div`
.nav-link {
background: transparent;
color: #fff;
border: none;
}
.nav.nav-tabs {
border: none;
}
.nav-link.active {
color: #fff;
background: transparent;
border: 1px solid rgba(255, 255, 255, 0.2);
border-bottom: none;
}
.p-2 {
border: none;
border: 1px solid rgba(255, 255, 255, 0.2) !important;
/* border-top: 0; */
background: #23242b !important;
color: #fff !important;
}
.form-control {
background: #23242b;
border: 1px solid rgba(255, 255, 255, 0.2);
}
`;

return (
<Container>
{options.name && (
<div className="mb-3">
<label className="mb-2">{options.name.label ?? "Name"}</label>
<input
type="text"
value={state.metadata.name}
style={{
background: "#23242b",
color: "#fff",
border: "1px solid rgba(255, 255, 255, 0.20)",
}}
/>
</div>
)}
{options.image && (
<div className="mb-3" style={{ color: "#000" }}>
<label className="mb-2 text-white">
{options.image.label ?? "Image"}
</label>
<CustomImageUpload>
<Widget
src="mob.near/widget/ImageEditorTabs"
props={{
image: state.image,
onChange: (image) => State.update({ image }),
}}
/>
</CustomImageUpload>
</div>
)}
{options.backgroundImage && (
<div className="mb-3">
<label className="mb-2">
{options.backgroundImage.label ?? "Background image"}
</label>
<Widget
src="mob.near/widget/ImageEditorTabs"
props={{
image: state.backgroundImage,
onChange: (backgroundImage) => State.update({ backgroundImage }),
}}
/>
</div>
)}
{options.description && (
<div className="mb-3">
<label className="mb-2">
{options.description.label ?? "Description"}
</label>
<span className="text-secondary"> (supports markdown)</span>
<textarea
className="form-control"
rows={5}
value={state.metadata.description}
onChange={(e) => {
state.metadata.description = e.target.value;
State.update();
}}
style={{
background: "#23242b",
color: "#fff",
border: "1px solid rgba(255, 255, 255, 0.20)",
}}
/>
</div>
)}
{options.tags && (
<CustomTagEditor className="mb-3">
<label className="mb-2">{options.tags.label ?? "Tags"}</label>
<Widget
src="mob.near/widget/TagsEditor"
props={{
initialTagsObject: metadata.tags,
tagsPattern: options.tags.pattern,
placeholder:
options.tags.placeholder ??
"rust, engineer, artist, humanguild, nft, learner, founder",
setTagsObject: (tags) => {
state.metadata.tags = tags;
State.update();
},
}}
/>
</CustomTagEditor>
)}
{options.linktree &&
(options.linktree.links ?? []).map((link) => (
<div className="mb-3">
<label class="mb-2">{link.label}</label>
<div className="input-group">
<span
className="input-group-text"
style={{
background: "#23242b",
color: "#fff",
border: "1px solid rgba(255, 255, 255, 0.20)",
}}
>
{link.prefix}
</span>
<input
type="text"
value={state.linktree[link.name]}
style={{
background: "#23242b",
color: "#fff",
border: "1px solid rgba(255, 255, 255, 0.20)",
}}
/>
</div>
</div>
))}
</Container>
);
181 changes: 181 additions & 0 deletions apps/homepage/widget/WidgetMetadata.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
const accountId = props.accountId;
const widgetName = props.widgetName;
const widgetPath = `${accountId}/widget/${widgetName}`;
const blockHeight = props.blockHeight;
const metadata = props.metadata ?? Social.getr(`${widgetPath}/metadata`);
const renderTag = props.renderTag;

const name = metadata.name ?? widgetName;
const description = metadata.description;
const image = metadata.image;
const tags = Object.keys(metadata.tags ?? {});
const expanded = !!props.expanded;

const linktree = Object.entries(metadata.linktree ?? {});
const linktreeElements = {
website: {
prefix: "https://",
icon: "bi-globe2",
},
};

const CustomProfileLink = styled.div`
* {
color: #fff !important;
}
`;

const linktreeObjects = linktree.map((o, i) => {
const key = o[0];
let value = o[1];
if (!value) {
return null;
}
const e = linktreeElements[key];
if (e.prefix) {
value = value && value.replace(e.prefix, "");
}
const icon = e.icon ? (
<i className={`bi ${e.icon ?? ""} text-secondary me-1`}></i>
) : (
""
);
return e.prefix ? (
<div key={i} className="text-truncate">
<a href={`${e.prefix}${value}`}>
{icon}
{value}
</a>
</div>
) : (
<div key={i} className="text-truncate">
{key}: {icon}
{value}
</div>
);
});

const descriptionKey = `${widgetPath}-description`.replaceAll(/[._\/-]/g, "--");

return (
<div
className="card text-white"
style={{ borderRadius: "1rem", background: "#23242b" }}
>
<div className="row py-3 g-1">
<div className="m-auto text-center" style={{ maxWidth: "12em" }}>
<div
className="d-inline-block"
style={{ width: "10em", height: "10em" }}
>
<Widget
src="mob.near/widget/Image"
props={{
image,
className: "w-100 h-100",
style: {
objectFit: "cover",
borderRadius: "0.5rem",
background: "#000",
},
thumbnail: false,
fallbackUrl:
"https://ipfs.near.social/ipfs/bafkreifzm3fvsuzjbnyik6iikfi6iy3jpqxyx2cdc7pwfwxkexy24326wu",
alt: widgetName,
}}
/>
</div>
</div>
<div className="col px-2">
<div className="position-relative">
<h5 className="card-title">{name}</h5>
<div className="text-truncate mb-1">
<a className="stretched-link" href={`#/${widgetPath}`}>
<i className="bi bi-box-arrow-up-right text-secondary me-1" />
{widgetPath}
</a>
</div>
</div>
<div className="card-text" style={{ color: "#fff" }}>
{tags.length > 0 && (
<div>
{tags.map((tag, i) => {
const tagBadge = (
<span key={i} className="me-1 mb-1 badge bg-secondary">
#{tag}
</span>
);
return renderTag ? renderTag(tag, tagBadge) : tagBadge;
})}
</div>
)}
{!expanded && (description || linktreeObjects.length > 0) && (
<button
className="btn btn-sm btn-outline-secondary border-0"
data-bs-toggle="collapse"
data-bs-target={`#${descriptionKey}`}
aria-expanded="false"
aria-controls={descriptionKey}
>
<i className="bi bi-arrows-angle-expand me-1"></i>Show details
</button>
)}
<a
href={`#/mob.near/widget/WidgetSource?src=${widgetPath}`}
className="btn btn-sm btn-outline-secondary border-0"
target="_blank"
>
<i className="bi bi-file-earmark-code me-1"></i>Source
</a>
<a
href={`#/bozon.near/widget/WidgetHistory?widgetPath=${widgetPath}`}
className="btn btn-sm btn-outline-secondary border-0"
target="_blank"
>
<i className="bi bi-clock-history me-1"></i>History
</a>
<a
href={`#/edit/${widgetPath}`}
className="btn btn-sm btn-outline-secondary border-0"
>
<i className="bi bi-pencil-square me-1"></i>
{accountId === context.accountId ? "Edit" : "Fork"}
</a>
</div>
</div>
</div>
<div
className={`card-text p-2 pt-0 ${expanded ? "" : "collapse"}`}
id={descriptionKey}
>
<Markdown text={description} />
{linktreeObjects}
</div>
<div
className="card-footer"
style={{
borderBottomLeftRadius: "1rem",
borderBottomRightRadius: "1rem",
}}
>
<div className="d-flex justify-content-start">
<CustomProfileLink className="flex-grow-1 me-1 text-truncate">
<span className="text-secondary me-1">By</span>
<Widget
src="mob.near/widget/ProfileLine"
props={{ accountId, link: props.profileLink }}
/>
</CustomProfileLink>
<div>
<small className="ps-1 text-nowrap text-muted ms-auto">
<i className="bi bi-clock me-1"></i>
<Widget
src="mob.near/widget/TimeAgo"
props={{ keyPath: widgetPath, now: props.metadata, blockHeight }}
/>
</small>
</div>
</div>
</div>
</div>
);
Loading

0 comments on commit df5015d

Please sign in to comment.