From 20c64664ce683b2d0d17c842af426abc40512e14 Mon Sep 17 00:00:00 2001 From: cha0s Date: Sat, 23 Jan 2021 18:16:43 -0600 Subject: [PATCH] feat: projects --- app/package.json | 1 + app/src/react/components/dashboard/index.jsx | 27 ++++++++++++++----- .../dashboard/project-item/index.jsx | 21 +++++++++++++++ .../dashboard/project-item/index.scss | 0 app/src/react/components/persea/index.jsx | 2 ++ app/src/react/components/project/index.jsx | 20 ++++++++++++++ app/src/react/components/project/index.scss | 0 .../react/components/project/route/index.jsx | 22 +++++++++++++++ .../react/components/project/route/index.scss | 0 packages/core/src/index.js | 1 + packages/core/src/server/index.js | 27 +++++++++++++++++-- packages/core/src/state/projects.js | 9 +++++-- 12 files changed, 120 insertions(+), 10 deletions(-) create mode 100644 app/src/react/components/dashboard/project-item/index.jsx create mode 100644 app/src/react/components/dashboard/project-item/index.scss create mode 100644 app/src/react/components/project/index.jsx create mode 100644 app/src/react/components/project/index.scss create mode 100644 app/src/react/components/project/route/index.jsx create mode 100644 app/src/react/components/project/route/index.scss diff --git a/app/package.json b/app/package.json index fd6f098..eea4483 100644 --- a/app/package.json +++ b/app/package.json @@ -14,6 +14,7 @@ "watch": "NODE_PATH=./node_modules webpack --hot --watch --mode development" }, "dependencies": { + "@avocado/resource": "^2.0.0", "@latus/core": "^2.0.0", "@latus/db": "^2.0.0", "@latus/governor": "^2.0.0", diff --git a/app/src/react/components/dashboard/index.jsx b/app/src/react/components/dashboard/index.jsx index 693eaa5..ffc53a2 100644 --- a/app/src/react/components/dashboard/index.jsx +++ b/app/src/react/components/dashboard/index.jsx @@ -1,13 +1,28 @@ import './index.scss'; import {React} from '@latus/react'; +import {useSelector} from '@latus/redux'; +import {projectsSelector} from '@persea/core'; -const Dashboard = () => ( -
-

Dashboard

-

Sup ;p

-
-); +import ProjectItem from './project-item'; + +const Dashboard = () => { + const {projects} = useSelector(projectsSelector); + const items = Object.entries(projects) + .map(([uuid, project]) => ( + + )); + return ( +
+

Dashboard

+ {items} +
+ ); +}; Dashboard.propTypes = {}; diff --git a/app/src/react/components/dashboard/project-item/index.jsx b/app/src/react/components/dashboard/project-item/index.jsx new file mode 100644 index 0000000..ce50741 --- /dev/null +++ b/app/src/react/components/dashboard/project-item/index.jsx @@ -0,0 +1,21 @@ +import './index.scss'; + +import {Link} from 'react-router-dom'; +import {PropTypes, React} from '@latus/react'; + +import {propTypes as projectPropTypes} from 'components/project'; + +const ProjectItem = ({project: {label, resourcePaths}, uuid}) => ( + +

{label}

+
{uuid}
+
{resourcePaths.length}
+ +); + +ProjectItem.propTypes = { + project: projectPropTypes.isRequired, + uuid: PropTypes.string.isRequired, +}; + +export default ProjectItem; diff --git a/app/src/react/components/dashboard/project-item/index.scss b/app/src/react/components/dashboard/project-item/index.scss new file mode 100644 index 0000000..e69de29 diff --git a/app/src/react/components/persea/index.jsx b/app/src/react/components/persea/index.jsx index 01f927b..454a52e 100644 --- a/app/src/react/components/persea/index.jsx +++ b/app/src/react/components/persea/index.jsx @@ -13,6 +13,7 @@ import { } from 'react-router-dom'; import Dashboard from 'components/dashboard'; +import ProjectRoute from 'components/project/route'; const Persea = ({history}) => { const isLoggedIn = useSelector(userIdSelector); @@ -23,6 +24,7 @@ const Persea = ({history}) => { {isLoggedIn ? : Login} + diff --git a/app/src/react/components/project/index.jsx b/app/src/react/components/project/index.jsx new file mode 100644 index 0000000..90000ec --- /dev/null +++ b/app/src/react/components/project/index.jsx @@ -0,0 +1,20 @@ +import './index.scss'; + +import {PropTypes, React} from '@latus/react'; + +const Project = ({project: {label}}) => ( +
+

{label}

+
+); + +export const propTypes = PropTypes.shape({ + label: PropTypes.string.isRequired, + resourcePaths: PropTypes.arrayOf(PropTypes.string).isRequired, +}); + +Project.propTypes = { + project: propTypes.isRequired, +}; + +export default Project; diff --git a/app/src/react/components/project/index.scss b/app/src/react/components/project/index.scss new file mode 100644 index 0000000..e69de29 diff --git a/app/src/react/components/project/route/index.jsx b/app/src/react/components/project/route/index.jsx new file mode 100644 index 0000000..909dfe2 --- /dev/null +++ b/app/src/react/components/project/route/index.jsx @@ -0,0 +1,22 @@ +import './index.scss'; + +import {PropTypes, React} from '@latus/react'; +import {useSelector} from '@latus/redux'; +import {projectsSelector} from '@persea/core'; + +import Project from '../index'; + +const ProjectRoute = ({match: {params: {uuid}}}) => { + const {projects} = useSelector(projectsSelector); + return ; +}; + +ProjectRoute.propTypes = { + match: PropTypes.shape({ + params: PropTypes.shape({ + uuid: PropTypes.string, + }), + }).isRequired, +}; + +export default ProjectRoute; diff --git a/app/src/react/components/project/route/index.scss b/app/src/react/components/project/route/index.scss new file mode 100644 index 0000000..e69de29 diff --git a/packages/core/src/index.js b/packages/core/src/index.js index 23c80e7..ea84635 100644 --- a/packages/core/src/index.js +++ b/packages/core/src/index.js @@ -1,6 +1,7 @@ import {projects, user} from './state'; export * from './state'; +export * from './tree'; export default { hooks: { diff --git a/packages/core/src/server/index.js b/packages/core/src/server/index.js index e20e073..c4005ac 100644 --- a/packages/core/src/server/index.js +++ b/packages/core/src/server/index.js @@ -4,7 +4,7 @@ import {promisify} from 'util'; import {decorateWithLatus, gatherWithLatus} from '@latus/core'; -import {treeToPaths} from '../tree'; +import {treeToPaths, treeToResourcePaths} from '../tree'; const readFile = promisify(fs.readFile).bind(fs); const stat = promisify(fs.stat).bind(fs); @@ -49,7 +49,30 @@ export default { }), {}); return { projects: { - projects, + projects: Object.fromEntries( + await Promise.all( + Object.entries(projects) + .map(async ([uuid, tree]) => { + let label; + try { + const buffer = await readFile(join(process.cwd(), 'projects', `${uuid}.json`)); + const config = JSON.parse(buffer.toString()); + label = config.name; + } + catch (error) { + label = uuid; + } + return [ + uuid, + { + label, + tree, + resourcePaths: treeToResourcePaths(tree), + }, + ]; + }), + ), + ), resources, }, user: { diff --git a/packages/core/src/state/projects.js b/packages/core/src/state/projects.js index 9a94cac..7cee41f 100644 --- a/packages/core/src/state/projects.js +++ b/packages/core/src/state/projects.js @@ -6,6 +6,7 @@ import { import { addPathToTree, removePathFromTree, + treeToResourcePaths, } from '../tree'; export const projectsSelector = (state) => state.projects; @@ -25,8 +26,12 @@ const slice = createSlice({ extraReducers: { }, reducers: { - createProject: ({projects}, {payload: {tree, uuid}}) => { - projects[uuid] = tree; + createProject: ({projects}, {payload: {label, tree, uuid}}) => { + projects[uuid] = { + label, + tree, + resourcePaths: treeToResourcePaths(tree), + }; }, createResource: ({projects, resources}, {payload: {data, project, uri}}) => { projects[project] = addPathToTree(projects[project], uri);