chore: tidy

This commit is contained in:
cha0s 2021-01-26 18:13:50 -06:00
parent dd36832bcc
commit ec4e72c54a
9 changed files with 124 additions and 99 deletions

View File

@ -7,8 +7,8 @@ import {projectsSelector} from '@persea/core';
import ProjectItem from './project-item';
const Dashboard = React.memo(() => {
const {projects} = useSelector(projectsSelector);
const items = Object.entries(projects)
const {structure} = useSelector(projectsSelector);
const items = Object.entries(structure)
.map(([uuid, project]) => (
<ProjectItem
key={uuid}

View File

@ -44,7 +44,7 @@ const treeFromResourcePaths = (label, uuid, resourcePaths) => {
return tree;
};
const Project = ({project: {label, resourcePaths}, uuid}) => (
const Project = ({structure: {label, resourcePaths}, uuid}) => (
<div className="project">
<ProjectContext.Provider value={uuid}>
<div className="sidebar">
@ -69,7 +69,7 @@ export const propTypes = PropTypes.shape({
});
Project.propTypes = {
project: propTypes.isRequired,
structure: propTypes.isRequired,
uuid: PropTypes.string.isRequired,
};

View File

@ -5,14 +5,14 @@ import {join} from 'path';
import {Resource} from '@avocado/resource';
import {PropTypes, React} from '@latus/react';
import {useSelector} from '@latus/redux';
import {projectsSelector} from '@persea/core';
import {structureSelector} from '@persea/core';
import Project from '../index';
const ProjectRoute = ({match: {params: {uuid}}}) => {
const {projects} = useSelector(projectsSelector);
const structure = useSelector((state) => structureSelector(state, uuid));
Resource.root = join('/projects', uuid);
return <Project uuid={uuid} project={projects[uuid]} />;
return <Project uuid={uuid} structure={structure} />;
};
ProjectRoute.propTypes = {

View File

@ -6,13 +6,13 @@ import {
useLatus,
} from '@latus/react';
import {useSelector} from '@latus/redux';
import {projectsSelector, UriContext} from '@persea/core';
import {resourceSelector, UriContext} from '@persea/core';
const Resource = ({uri, uuid}) => {
const latus = useLatus();
const {resources} = useSelector(projectsSelector);
const resource = useSelector((state) => resourceSelector(state, `${uuid}${uri}`));
const Component = latus.get('%resource-renderers')(uri);
const buffer = Buffer.from(resources[`${uuid}${uri}`], 'base64');
const buffer = Buffer.from(resource, 'base64');
return (
<div className="resource">
<UriContext.Provider value={uri}>

View File

@ -1,12 +1,9 @@
import fs from 'fs';
import {join} from 'path';
import {promisify} from 'util';
import {decorateWithLatus, gatherWithLatus} from '@latus/core';
import express from 'express';
const readFile = promisify(fs.readFile).bind(fs);
const stat = promisify(fs.stat).bind(fs);
import projectsState from './state/projects';
const resources = express.static(join(process.cwd(), 'projects'));
@ -28,69 +25,17 @@ export default {
}
next();
},
'@latus/redux/defaultState': async (req) => {
const projectsResourcePaths = req
? await req.user.projectsResourcePaths()
: {};
const resources = await Object.entries(projectsResourcePaths)
.reduce(async (r, [uuid, resourcePaths]) => ({
...(await r),
...(
await (await Promise.all(resourcePaths
.map(async ([, path]) => {
try {
return [
(await stat(join(process.cwd(), 'projects', uuid, path))).isFile(),
path,
];
}
catch (error) {
return [false];
}
})))
.filter(([stat]) => stat)
.map(([, path]) => path)
.reduce(async (r, path) => ({
...(await r),
[join(uuid, path)]: (
await readFile(join(process.cwd(), 'projects', uuid, path))
).toString('base64'),
}), {})
),
}), {});
return {
projects: {
projects: Object.fromEntries(
await Promise.all(
Object.entries(projectsResourcePaths)
.map(async ([uuid, resourcePaths]) => {
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,
resourcePaths,
},
];
}),
),
),
resources,
},
user: {
id: req
? req.user.id
: 0,
},
};
},
'@latus/redux/defaultState': async (req) => ({
projects: await projectsState(
req
? await req.user.projectsResourcePaths()
: {},
),
user: {
id: req
? req.user.id
: 0,
},
}),
},
};

View File

@ -0,0 +1,72 @@
import fs from 'fs';
import {join} from 'path';
import {promisify} from 'util';
const readFile = promisify(fs.readFile).bind(fs);
const stat = promisify(fs.stat).bind(fs);
const projectResources = async (uuid, resourcePaths) => {
const statPaths = await Promise.all(
resourcePaths
.map(async ([, path]) => {
try {
return [
(await stat(join(process.cwd(), 'projects', uuid, path))).isFile(),
path,
];
}
catch (error) {
return [false];
}
}),
);
const filePaths = statPaths
.filter(([stat]) => stat)
.map(([, path]) => path);
return filePaths
.reduce(async (r, path) => ({
...(await r),
[join(uuid, path)]: (
await readFile(join(process.cwd(), 'projects', uuid, path))
).toString('base64'),
}), {});
};
const projectsResources = (projectsResourcePaths) => (
Object.entries(projectsResourcePaths)
.reduce(async (r, [uuid, resourcePaths]) => ({
...(await r),
...(await projectResources(uuid, resourcePaths)),
}), {})
);
const projectsStructure = async (projectsResourcePaths) => (
Object.fromEntries(
await Promise.all(
Object.entries(projectsResourcePaths)
.map(async ([uuid, resourcePaths]) => {
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,
resourcePaths,
},
];
}),
),
)
);
export default async (projectsResourcePaths) => ({
structure: await projectsStructure(projectsResourcePaths),
resources: await projectsResources(projectsResourcePaths),
});

View File

@ -5,15 +5,20 @@ import {
export const projectsSelector = (state) => state.projects;
export const projectSelector = createSelector(
export const resourceSelector = createSelector(
[projectsSelector, (_, path) => path],
({resources}, path) => path && resources[path],
);
export const structureSelector = createSelector(
[projectsSelector, (_, uuid) => uuid],
(projects, uuid) => uuid && projects[uuid],
({structure}, uuid) => uuid && structure[uuid],
);
const slice = createSlice({
name: 'persea/projects',
initialState: {
projects: {},
structure: {},
resources: {},
},
/* eslint-disable no-param-reassign */

View File

@ -1,28 +1,12 @@
import {JSONB} from '@avocado/resource';
import {createNextState} from '@latus/redux';
import {applyPatch} from 'fast-json-patch';
import JsonResourceComponent from './json';
import {patchJsonResource} from './state';
import reducer from './state/reducer';
export {default as useJsonPatcher} from './hooks/use-json-patcher';
export * from './state';
export default {
hooks: {
'@latus/redux/reducers': () => (state, {payload, type}) => {
if (type !== patchJsonResource.toString()) {
return state;
}
const {patch, project, uri} = payload;
return createNextState(state, (draft) => {
const buffer = Buffer.from(draft.projects.resources[`${project}${uri}`], 'base64');
const json = JSONB.parse(buffer);
applyPatch(json, patch);
// eslint-disable-next-line no-param-reassign
draft.projects.resources[`${project}${uri}`] = JSONB.bufferify(json).toString('base64');
});
},
'@latus/redux/reducers': () => reducer,
'@persea/core/resource-renderers': () => [
JsonResourceComponent,
],

View File

@ -0,0 +1,19 @@
import {JSONB} from '@avocado/resource';
import {createNextState} from '@latus/redux';
import {applyPatch} from 'fast-json-patch';
import {patchJsonResource} from './json';
export default (state, {payload, type}) => {
if (type !== patchJsonResource.toString()) {
return state;
}
const {patch, project, uri} = payload;
return createNextState(state, (draft) => {
const buffer = Buffer.from(draft.projects.resources[`${project}${uri}`], 'base64');
const json = JSONB.parse(buffer);
applyPatch(json, patch);
// eslint-disable-next-line no-param-reassign
draft.projects.resources[`${project}${uri}`] = JSONB.bufferify(json).toString('base64');
});
};