From df36ab6358462e7ccfcf02c20128613fb8b097f0 Mon Sep 17 00:00:00 2001 From: 0xExp-po <153439271+0xExp-po@users.noreply.github.com> Date: Sat, 14 Sep 2024 16:35:11 +0200 Subject: [PATCH] Update workflow (#45) * chore: update config data type * feat: add modal in project list * chore: add projectcard modal open nanostores * chore: remove set project section in dashboard * chore: change modal when no config file * chore: change description of get commit section * chore: change path from commit to project * chore: update style of projectinfomodal without config data * chore: add tooltip to commit badge * chore: update logo in project info modal * chore: change maintainer address to github name * chore: change register button position * chore: add jump to latest commit button * chore: remove dropdown * chore: display logo instead thumbnail in project card * fix: hide register button during loading * fix: detail button in mobile * chore: open history and jump to latest commit --- dapp/public/icons/arrow.svg | 3 + dapp/src/components/CommitRecord.jsx | 24 +++- dapp/src/components/GetCommit.astro | 4 +- dapp/src/components/ProjectCard.jsx | 8 +- dapp/src/components/ProjectInfo.astro | 110 ++++++++++++----- dapp/src/components/ProjectList.jsx | 95 +++++++++------ dapp/src/components/RegisterProject.astro | 2 +- dapp/src/components/SetProject.astro | 4 +- dapp/src/components/utils/Modal.jsx | 28 +++++ .../src/components/utils/ProjectInfoModal.jsx | 112 ++++++++++++++++++ dapp/src/pages/index.astro | 2 - .../src/pages/{commit.astro => project.astro} | 0 dapp/src/types/projectConfig.ts | 2 + dapp/src/utils/store.js | 3 +- 14 files changed, 322 insertions(+), 75 deletions(-) create mode 100644 dapp/public/icons/arrow.svg create mode 100644 dapp/src/components/utils/Modal.jsx create mode 100644 dapp/src/components/utils/ProjectInfoModal.jsx rename dapp/src/pages/{commit.astro => project.astro} (100%) diff --git a/dapp/public/icons/arrow.svg b/dapp/public/icons/arrow.svg new file mode 100644 index 0000000..04f032b --- /dev/null +++ b/dapp/public/icons/arrow.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dapp/src/components/CommitRecord.jsx b/dapp/src/components/CommitRecord.jsx index 1fa352a..b3a9313 100644 --- a/dapp/src/components/CommitRecord.jsx +++ b/dapp/src/components/CommitRecord.jsx @@ -32,13 +32,29 @@ const CommitRecord = ({ message, date, authorName, authorGithubLink, sha, commit {(isLatestCommit || isMaintainer) && (
{isLatestCommit && ( -
- verified commit +
+
+ verified commit +
+
+
+ This commit was verified on-chain by a maintainer +
+
+
)} {isMaintainer && ( -
- verified maintainer +
+
+ verified maintainer +
+
+
+ This maintainer is allowed to register new commit hash on-chain +
+
+
)}
diff --git a/dapp/src/components/GetCommit.astro b/dapp/src/components/GetCommit.astro index cbfc7a8..82c848f 100644 --- a/dapp/src/components/GetCommit.astro +++ b/dapp/src/components/GetCommit.astro @@ -4,7 +4,7 @@ import Loading from "./utils/Loading.astro"; ---
- +
{ @@ -48,7 +50,7 @@ const ProjectCard = ({ config }) => { setProjectLatestSha(latestSha); } else setProjectLatestSha(""); - window.location.href = '/commit'; + projectCardModalOpen.set(true); } else { alert(`There is not such project: ${config.projectName}`); } @@ -61,9 +63,9 @@ const ProjectCard = ({ config }) => {
{config.projectName}
diff --git a/dapp/src/components/ProjectInfo.astro b/dapp/src/components/ProjectInfo.astro index 8927ca7..60d2e8d 100644 --- a/dapp/src/components/ProjectInfo.astro +++ b/dapp/src/components/ProjectInfo.astro @@ -52,6 +52,12 @@ import ModalInput from "./utils/ModalInput.astro"; View Project Info
+
+ + + + Jump to Latest Verified Commit +
@@ -111,7 +117,7 @@ import ModalInput from "./utils/ModalInput.astro";
- +

@@ -166,31 +172,60 @@ import ModalInput from "./utils/ModalInput.astro"; const ul = maintainersList.querySelector("ul"); if (ul) { ul.innerHTML = ''; - projectInfo.maintainers.forEach((maintainer: string) => { - const li = document.createElement("li"); - li.className = "relative"; - - const content = document.createElement("p"); - content.className = "truncate"; - content.textContent = maintainer; - - li.appendChild(content); - - const popup = document.createElement("p"); - popup.className = "absolute left-0 bottom-full mb-1 bg-black text-white text-xs text-center p-1 rounded hidden before:content-[''] before:absolute before:left-1/2 before:top-full before:-translate-x-1/2 before:border-4 before:border-transparent before:border-t-black max-w-[240px] sm:max-w-[320px] md:max-w-none break-words"; - popup.textContent = maintainer; - li.appendChild(popup); - - li.addEventListener("mouseenter", () => { - popup.classList.remove("hidden"); + const configData = loadConfigData(); + if (configData && configData.authorGithubNames && configData.maintainersAddresses) { + configData.authorGithubNames.forEach((authorName: string, index: number) => { + const li = document.createElement("li"); + li.className = "relative"; + + const content = document.createElement("p"); + content.className = "truncate"; + content.textContent = authorName; + + li.appendChild(content); + + const popup = document.createElement("p"); + popup.className = "absolute left-0 bottom-full mb-1 bg-black text-white text-xs text-center p-1 rounded hidden before:content-[''] before:absolute before:left-5 before:top-full before:-translate-x-1/2 before:border-4 before:border-transparent before:border-t-black max-w-[240px] sm:max-w-[320px] md:max-w-none break-words"; + popup.textContent = configData.maintainersAddresses[index] || ''; + li.appendChild(popup); + + li.addEventListener("mouseenter", () => { + popup.classList.remove("hidden"); + }); + + li.addEventListener("mouseleave", () => { + popup.classList.add("hidden"); + }); + + ul.appendChild(li); }); - - li.addEventListener("mouseleave", () => { - popup.classList.add("hidden"); + } else { + projectInfo.maintainers.forEach((maintainer: string) => { + const li = document.createElement("li"); + li.className = "relative"; + + const content = document.createElement("p"); + content.className = "truncate"; + content.textContent = maintainer; + + li.appendChild(content); + + const popup = document.createElement("p"); + popup.className = "absolute left-0 bottom-full mb-1 bg-black text-white text-xs text-center p-1 rounded hidden before:content-[''] before:absolute before:left-1/2 before:top-full before:-translate-x-1/2 before:border-4 before:border-transparent before:border-t-black max-w-[240px] sm:max-w-[320px] md:max-w-none break-words"; + popup.textContent = maintainer; + li.appendChild(popup); + + li.addEventListener("mouseenter", () => { + popup.classList.remove("hidden"); + }); + + li.addEventListener("mouseleave", () => { + popup.classList.add("hidden"); + }); + + ul.appendChild(li); }); - - ul.appendChild(li); - }); + } } } const githubLink = document.getElementById("github-link") as HTMLAnchorElement; @@ -282,12 +317,13 @@ import ModalInput from "./utils/ModalInput.astro"; } const viewCommitHistory = document.getElementById("view-commit-history"); + const jumpToLatestCommit = document.getElementById("jump-to-latest-commit"); const viewCommitText = document.getElementById("view-commit-text"); const commitHistoryContainer = document.getElementById("commit-history-container"); const commitIconUp = document.getElementById("commit-icon-up"); const commitIconDown = document.getElementById("commit-icon-down"); - if (viewCommitHistory && viewCommitText && commitHistoryContainer && commitIconUp && commitIconDown) { + if (viewCommitHistory && commitHistoryContainer) { viewCommitHistory.addEventListener("click", () => { if (commitHistoryContainer.style.maxHeight === "0px" || !commitHistoryContainer.style.maxHeight) { commitHistoryContainer.style.maxHeight = `${commitHistoryContainer.scrollHeight}px`; @@ -295,7 +331,24 @@ import ModalInput from "./utils/ModalInput.astro"; commitHistoryContainer.style.maxHeight = "0px"; } }); - + } + + if (jumpToLatestCommit && commitHistoryContainer) { + jumpToLatestCommit.addEventListener("click", () => { + if (commitHistoryContainer.style.maxHeight === "0px" || !commitHistoryContainer.style.maxHeight) { + commitHistoryContainer.style.maxHeight = `${commitHistoryContainer.scrollHeight}px`; + } else { + setTimeout(() => { + const latestCommit = document.getElementById('latest-commit-record'); + if (latestCommit) { + latestCommit.scrollIntoView({ behavior: 'smooth', block: 'center' }); + } + }, 10); + } + }) + } + + if (viewCommitText && commitHistoryContainer && commitIconUp && commitIconDown) { commitHistoryContainer.addEventListener("transitionend", () => { if (commitHistoryContainer.style.maxHeight === "0px") { viewCommitText.textContent = "View Commit History"; @@ -310,7 +363,7 @@ import ModalInput from "./utils/ModalInput.astro"; if (latestCommit) { latestCommit.scrollIntoView({ behavior: 'smooth', block: 'center' }); } - }, 1000); + }, 10); } }); } @@ -357,7 +410,8 @@ import ModalInput from "./utils/ModalInput.astro"; projectLogo.style.display = 'none'; } } - if (projectThumbnail) projectThumbnail.src = configData.thumbnailImageLink || '/fallback-image.jpg'; + // if (projectThumbnail) projectThumbnail.src = configData.thumbnailImageLink || '/fallback-image.jpg'; + if (projectThumbnail) projectThumbnail.src = convertGitHubLink(configData.logoImageLink) || '/fallback-image.jpg'; if (projectDescription) projectDescription.textContent = configData.description || ''; if (companyName) companyName.innerHTML = `Developed by ${configData.companyName || ''}`; diff --git a/dapp/src/components/ProjectList.jsx b/dapp/src/components/ProjectList.jsx index 0efb111..a35266f 100644 --- a/dapp/src/components/ProjectList.jsx +++ b/dapp/src/components/ProjectList.jsx @@ -1,21 +1,29 @@ import React, { useState, useEffect } from 'react'; +import { useStore } from '@nanostores/react'; import ProjectCard from './ProjectCard.jsx'; -import { getDemoConfigData } from '../constants/demoConfigData.js'; import Dropdown from './utils/DropDown.jsx'; -import { refreshLocalStorage, setProjectId } from '../service/StateService'; +import ProjectInfoModal from './utils/ProjectInfoModal.jsx'; +import { getDemoConfigData } from '../constants/demoConfigData'; +import { refreshLocalStorage, setProjectId, loadConfigData } from '../service/StateService'; +import { projectCardModalOpen } from '../utils/store.js'; +import { convertGitHubLink } from '../utils/editLinkFunctions'; const ProjectList = () => { - const [projects, setProjects] = useState([]); - const [filteredProjects, setFilteredProjects] = useState([]); + const isProjectInfoModalOpen = useStore(projectCardModalOpen); + const [projects, setProjects] = useState(undefined); + const [filteredProjects, setFilteredProjects] = useState(undefined); const [searchTerm, setSearchTerm] = useState(''); const [category, setCategory] = useState('all'); - const options = [ - { label: 'All', value: 'all' }, - { label: 'Web', value: 'web' }, - { label: 'Mobile', value: 'mobile' }, - { label: 'Desktop', value: 'desktop' }, - ]; + const [isModalOpen, setModalOpen] = useState(false); + const [projectInfo, setProjectInfo] = useState(null); + + // const options = [ + // { label: 'All', value: 'all' }, + // { label: 'Web', value: 'web' }, + // { label: 'Mobile', value: 'mobile' }, + // { label: 'Desktop', value: 'desktop' }, + // ]; useEffect(() => { const fetchProjects = async () => { @@ -29,13 +37,30 @@ const ProjectList = () => { }, []); useEffect(() => { - const filtered = projects.filter(project => - project?.projectName.toLowerCase().includes(searchTerm.toLowerCase()) && - (category === 'all') - ); - setFilteredProjects(filtered); + if (projects) { + const filtered = projects.filter(project => + project?.projectName.toLowerCase().includes(searchTerm.toLowerCase()) && + (category === 'all') + ); + setFilteredProjects(filtered); + } }, [searchTerm, category, projects]); + useEffect(() => { + setModalOpen(isProjectInfoModalOpen); + if (isProjectInfoModalOpen) { + const configData = loadConfigData(); + if (configData?.logoImageLink) { + setProjectInfo({ + ...configData, + logoImageLink: convertGitHubLink(configData.logoImageLink) + }); + } else { + setProjectInfo(configData); + } + } + }, [isProjectInfoModalOpen]); + const handleSearch = () => { console.log('Search function activated'); }; @@ -49,12 +74,12 @@ const ProjectList = () => { return (
- setCategory(e.target.value)} /> -
+ {/* setCategory(e.target.value)} /> */} +
setSearchTerm(e.target.value)} /> @@ -65,27 +90,31 @@ const ProjectList = () => {
- {filteredProjects.length === 0 && ( +
+ + {filteredProjects !== undefined && ( + filteredProjects.length > 0 ? ( +
+ {filteredProjects.map((project, index) => ( + + ))} +
+ ) : ( +
+ {/*

No projects found

*/} - )} -
- - {filteredProjects.length > 0 ? ( -
- {filteredProjects.map((project, index) => ( - - ))} -
- ) : ( -
-

No projects found

-
+
+ ) )} + + {isModalOpen && + projectCardModalOpen.set(false)}/> + }
); }; diff --git a/dapp/src/components/RegisterProject.astro b/dapp/src/components/RegisterProject.astro index 0f1006f..5fd5f4b 100644 --- a/dapp/src/components/RegisterProject.astro +++ b/dapp/src/components/RegisterProject.astro @@ -107,7 +107,7 @@ import ModalInput from "./utils/ModalInput.astro"; if (!register_status) { alert("Project could not be registered! Please retry."); } else { - navigate("/commit"); + navigate("/project"); } }); } diff --git a/dapp/src/components/SetProject.astro b/dapp/src/components/SetProject.astro index 36d33bb..da53bb4 100644 --- a/dapp/src/components/SetProject.astro +++ b/dapp/src/components/SetProject.astro @@ -93,6 +93,8 @@ const TANSU_CONTRACT_ID = import.meta.env.PUBLIC_TANSU_CONTRACT_ID; telegram: "", discord: "", instagram: "", + facebook: "", + reddit: "", }, authorGithubNames: tomlData.PRINCIPALS?.map((p: { github: any; }) => p.github) || [], maintainersAddresses: tomlData.ACCOUNTS || [], @@ -106,7 +108,7 @@ const TANSU_CONTRACT_ID = import.meta.env.PUBLIC_TANSU_CONTRACT_ID; if (typeof latestSha === 'string' && latestSha.match(/^[a-f0-9]{40}$/)) { setProjectLatestSha(latestSha); } else setProjectLatestSha(""); - navigate("/commit"); + navigate("/project"); } else { navigate("/register"); } diff --git a/dapp/src/components/utils/Modal.jsx b/dapp/src/components/utils/Modal.jsx new file mode 100644 index 0000000..896649a --- /dev/null +++ b/dapp/src/components/utils/Modal.jsx @@ -0,0 +1,28 @@ +import React from 'react'; + +const Modal = ({ id, title, children, onClose }) => { + return ( +
+
+
+

+ {title && {title}} +

+ +
+
+ {children} +
+
+
+ ); +}; + +export default Modal; diff --git a/dapp/src/components/utils/ProjectInfoModal.jsx b/dapp/src/components/utils/ProjectInfoModal.jsx new file mode 100644 index 0000000..b6d04cd --- /dev/null +++ b/dapp/src/components/utils/ProjectInfoModal.jsx @@ -0,0 +1,112 @@ +import React, { useState, useEffect } from 'react'; +import Modal from './Modal'; +import { loadProjectName } from '../../service/StateService'; + +const ProjectInfoModal = ({ id, projectInfo, onClose }) => { + const [projectName, setProjectName] = useState(""); + + useEffect(() => { + const getProjectName = () => { + const projectName = loadProjectName(); + if (projectName) { + setProjectName(projectName); + } + }; + + getProjectName(); + }, []); + + const handleDetailClick = () => { + window.location.href = '/project'; + }; + + return ( + +
+ {projectInfo && Object.keys(projectInfo).length > 0 ? ( + <> +
+ {/* {projectInfo.logoImageLink && + + } */} +

{projectInfo.projectName || "No project name"}

+
+
+ {/* Project Thumbnail */} + Project Thumbnail +
+

{projectInfo?.description || "No description"}

+
+
+ +
+
+

Official Links

+ +
+ +
+

Social

+ +
+
+
+ {projectInfo?.companyName ? ( +

Developed by {projectInfo.companyName}

+ ) : ( +

No company name

+ )} + +
+ + ) : ( +
+

{projectName || "No project name"}

+
+

This project is missing a tansu.toml configuration file.

+
+
+ +
+
+ )} +
+
+ ); +}; + +export default ProjectInfoModal; \ No newline at end of file diff --git a/dapp/src/pages/index.astro b/dapp/src/pages/index.astro index 7c58536..3d7776e 100644 --- a/dapp/src/pages/index.astro +++ b/dapp/src/pages/index.astro @@ -1,7 +1,6 @@ --- import Layout from "../layouts/Layout.astro"; -import SetProject from "../components/SetProject.astro"; import Container from "../components/layout/Container.astro"; import ProjectList from "../components/ProjectList.jsx"; --- @@ -12,7 +11,6 @@ import ProjectList from "../components/ProjectList.jsx";
-
diff --git a/dapp/src/pages/commit.astro b/dapp/src/pages/project.astro similarity index 100% rename from dapp/src/pages/commit.astro rename to dapp/src/pages/project.astro diff --git a/dapp/src/types/projectConfig.ts b/dapp/src/types/projectConfig.ts index c41692d..d853adf 100644 --- a/dapp/src/types/projectConfig.ts +++ b/dapp/src/types/projectConfig.ts @@ -13,6 +13,8 @@ export interface ConfigData { telegram: string; discord: string; instagram: string; + facebook: string; + reddit: string; }; authorGithubNames: string[]; maintainersAddresses: string[]; diff --git a/dapp/src/utils/store.js b/dapp/src/utils/store.js index 864826b..9d9b5d5 100644 --- a/dapp/src/utils/store.js +++ b/dapp/src/utils/store.js @@ -1,4 +1,5 @@ import { atom } from 'nanostores' export const projectInfoLoaded = atom(false); -export const latestCommit = atom(""); \ No newline at end of file +export const latestCommit = atom(""); +export const projectCardModalOpen = atom(false); \ No newline at end of file