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 = () => (
-
-);
+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);