Skip to content

Commit

Permalink
Added basic layout for plugin viewer.
Browse files Browse the repository at this point in the history
  • Loading branch information
SamTV12345 committed Sep 19, 2023
1 parent 0bc397f commit 7c46ea9
Show file tree
Hide file tree
Showing 7 changed files with 231 additions and 64 deletions.
7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,23 @@
"@fortawesome/free-solid-svg-icons": "^6.4.2",
"@fortawesome/react-fontawesome": "^0.2.0",
"@radix-ui/react-dialog": "^1.0.4",
"javascript-time-ago": "^2.5.9",
"marked": "^9.0.3",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-ga": "^3.3.1",
"react-router": "^6.14.0",
"react-router-dom": "^6.14.0",
"react-router-hash-link": "^2.4.3"
"react-router-hash-link": "^2.4.3",
"sanitize-html": "^2.11.0",
"timeago": "^1.6.7"
},
"devDependencies": {
"@saber2pr/types-github-api": "^0.0.9",
"@types/react": "^18.0.37",
"@types/react-dom": "^18.0.11",
"@types/react-lazy-load-image-component": "^1.5.3",
"@types/sanitize-html": "^2.9.0",
"@typescript-eslint/eslint-plugin": "^5.59.0",
"@typescript-eslint/parser": "^5.59.0",
"@vitejs/plugin-react-swc": "^3.0.0",
Expand Down
112 changes: 107 additions & 5 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

49 changes: 49 additions & 0 deletions src/components/Plugin.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import {PluginMetaData,Plugin} from "../store/Plugin.ts";
import {FC} from "react";
import TimeAgo from 'javascript-time-ago'
import en from 'javascript-time-ago/locale/en'
import sanitizeHtml from 'sanitize-html'
import * as marked from 'marked'
type PluginProps = {
metadata: PluginMetaData,
plugins: Plugin
}
TimeAgo.addDefaultLocale(en)
const timeago = new TimeAgo('en-US')


const formatTime = (isoDate: string) => {
return timeago.format(new Date(isoDate))
}

const renderMarkdown = (text: string) => {
const unsafeHtml = marked.parse(text)
const sanitizedHtml = sanitizeHtml(unsafeHtml)
return {__html: sanitizedHtml}
}

export const PluginCom: FC<PluginProps> = ({plugins})=>{
return <div className="dark:text-white border-[1px] p-2 rounded">
<div className="flex">
<div className="text-3xl text-primary flex gap-3">
<span>{plugins.name}</span>
<small className="align-text-bottom text-gray-400 mt-[3px]">{plugins.version}</small>
</div>
<div className="flex-grow"></div>
{plugins.time&&<div className="mr-5 mt-[0.3rem]">{formatTime(plugins.time)}</div>}
<div className="w-10 flex items-center mr-2">
<div className="w-10 border-[1px] border-white">
<div style={{width: plugins.popularity_score*100+"%"}} title={(plugins.popularity_score*100).toFixed(2)+"% popular among other plugins"} className="bg-primary w-10 h-5 self-center"></div>
</div>
</div>
</div>
<div>{plugins.description}</div>
<div className="flex gap-10">
{plugins.image&&<img alt={"Image of "+plugins.name} className="w-60" src={plugins.image}/>}
{plugins.readme&&<div className="w-full line-clamp-5" dangerouslySetInnerHTML={renderMarkdown(plugins.readme)}></div>}
</div>
<div>

</div>
</div>
}
47 changes: 27 additions & 20 deletions src/pages/PluginViewer.tsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,40 @@
import {Plugins} from "../store/Plugin.ts";
import {PluginResponse} from "../store/Plugin.ts";
import {useUIStore} from "../store/store.ts";
import {useEffect, useMemo} from "react";

import {useEffect} from "react";
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
import {faSearch} from "@fortawesome/free-solid-svg-icons";
import {PluginCom} from "../components/Plugin.tsx";
export const PluginViewer = ()=>{
const setPlugin = useUIStore(state => state.setPlugins)
const plugins = useUIStore(state => state.plugins)
const numberOfTotalDownloads = useMemo(()=>{
return Object.keys(plugins).reduce((acc, key)=>{
return acc + plugins[key].data.downloads
},0)
}, [plugins]
)
const retrievePlugins = async ()=>{
fetch('https://static.etherpad.org/plugins.full.json')
.then(response => response.json())
.then((data:Plugins) =>setPlugin(data))
}
const pluginSearchTerm = useUIStore(state => state.pluginSearchTerm)
const setPluginSearchTerm = useUIStore(state => state.setPluginSearchTerm)


useEffect(() => {
if (Object.keys(plugins).length > 0) return
retrievePlugins()
fetch('/api/plugins')
.then(response => response.json())
.then((data:PluginResponse) =>setPlugin(data))
}, []);

return <div className="ml-5 mr-5">
<h1 className="text-2xl dark:text-white">PluginViewer</h1>
return <div className="ml-5 mr-5 flex items-center flex-col">
<div>
<h1 className="text-2xl font-bold dark:text-white text-left w-full">PluginViewer</h1>
<span className="text-gray-400">
This page lists all available plugins for etherpad hosted on npm. <span className="text-primary">{numberOfTotalDownloads} downloads</span> of <span className="text-primary">231</span> plugins in the last month.
This page lists all available plugins for etherpad hosted on npm. <span className="text-primary">{plugins?.metadata.total_downloads} downloads</span> of <span className="text-primary">{plugins?.metadata.total_count}</span> plugins in the last month.
For more information about Etherpad visit https://etherpad.org.
</span>

<div className="mt-5 mb-5 relative flex self-center w-full md:w-3/4">
<input className="w-full rounded border-[1px] pt-2 pb-2 pl-8 pr-1" placeholder="Search for plugins to install" value={pluginSearchTerm} onChange={v=>setPluginSearchTerm(v.target.value)}/>
<FontAwesomeIcon icon={faSearch} className="absolute left-2 mt-[0.85rem]"/>
</div>
<div className="grid grid-cols-1 gap-3 w-full md:w-3/4 ">
{
plugins?.plugins.map((plugin)=> {
return <PluginCom plugins={plugin} metadata={plugins?.metadata}/>
})
}
</div>
</div>
</div>
}
Loading

0 comments on commit 7c46ea9

Please sign in to comment.