diff --git a/.vscode/settings.json b/.vscode/settings.json
index bbf7d45..5a0ffc9 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -2,6 +2,8 @@
"css.validate": false,
"scss.validate": false,
"cSpell.words": [
- "Formik"
+ "Formik",
+ "autorun",
+ "wouter"
]
}
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index dec5ee3..a5e3eb0 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -15492,11 +15492,6 @@
"pretty-format": "^3.8.0"
}
},
- "preact-router": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/preact-router/-/preact-router-3.2.1.tgz",
- "integrity": "sha512-KEN2VN1DxUlTwzW5IFkF13YIA2OdQ2OvgJTkQREF+AA2NrHRLaGbB68EjS4IeZOa1shvQ1FvEm3bSLta4sXBhg=="
- },
"prelude-ls": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
@@ -21144,6 +21139,11 @@
"microevent.ts": "~0.1.1"
}
},
+ "wouter-preact": {
+ "version": "2.7.4",
+ "resolved": "https://registry.npmjs.org/wouter-preact/-/wouter-preact-2.7.4.tgz",
+ "integrity": "sha512-lYYO3JozPcHB9VP3FrjliADVD04p0TDFRP28wVFWfIGN8l8RxCTWXQxvm9uQ0vFU7CBUA2nOFeCveBPXdZiGLQ=="
+ },
"wrap-ansi": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
diff --git a/package.json b/package.json
index ef1718a..e12e2bf 100644
--- a/package.json
+++ b/package.json
@@ -41,10 +41,10 @@
"preact-jsx-chai": "^3.0.0",
"preact-markup": "^2.1.1",
"preact-render-to-string": "^5.1.18",
- "preact-router": "^3.2.1",
"ramda": "^0.27.1",
"subscriptions-transport-ws": "^0.9.18",
- "tailwindcss": "npm:@tailwindcss/postcss7-compat@^2.0.3"
+ "tailwindcss": "npm:@tailwindcss/postcss7-compat@^2.0.3",
+ "wouter-preact": "^2.7.4"
},
"devDependencies": {
"@graphql-codegen/cli": "^1.21.3",
diff --git a/src/components/app.tsx b/src/components/app.tsx
index cc37bd0..3124882 100644
--- a/src/components/app.tsx
+++ b/src/components/app.tsx
@@ -4,7 +4,7 @@ import { ProjectPanel } from './projects/project-panel';
import styles from './app.scss';
import { OverlayContainer } from './commons/overlay/overlay';
import { useObserver } from 'mobx-react';
-import Router, { Route } from 'preact-router';
+import { Router, Route } from 'wouter-preact';
import { createApolloClient } from '../units/apollo-client';
import { ProjectDetails } from './pipeline-tasks/project-details';
import { PipelineEditor } from './pipelines/pipeline-editor';
@@ -25,13 +25,16 @@ const App: FunctionalComponent = () => {
const Content = () => {
return ;
};
+
const Board = () => {
return useObserver(() => {
return (
-
+
+ {params => }
+
}
diff --git a/src/components/commit-actions/commit-actions.tsx b/src/components/commit-actions/commit-actions.tsx
index e74a922..8326295 100644
--- a/src/components/commit-actions/commit-actions.tsx
+++ b/src/components/commit-actions/commit-actions.tsx
@@ -21,7 +21,7 @@ import {
} from '@fortawesome/free-solid-svg-icons';
import { useLocalObservable } from 'mobx-react';
import { PipelineTask, PipelineUnits } from '../../generated/graphql';
-import { route } from 'preact-router';
+import { useLocation } from 'wouter-preact';
const CREATE_PIPELINE_TASK = gql`
mutation CreatePipelineTask($task: CreatePipelineTaskInput!) {
@@ -42,18 +42,12 @@ interface Props {
branch?: string;
}
-class Store {
- constructor() {
- makeAutoObservable(this);
- }
- isTasksWorking = [false, false, false, false];
-}
-
export const CommitActions = ({ pipeline, commit }: Props) => {
const [createTask] = useMutation<
{ task: PipelineTask },
{ task: CreatePipelineTaskInput }
>(CREATE_PIPELINE_TASK);
+ const setLocation = useLocation()[1];
const doWork = async (units: PipelineUnits[]) => {
const { data } = await createTask({
@@ -61,9 +55,7 @@ export const CommitActions = ({ pipeline, commit }: Props) => {
task: { pipelineId: pipeline.id, commit, units }
}
});
- route(
- `/projects/${pipeline.projectId}/pipelines/${pipeline.id}/tasks/${data?.task.id}`
- );
+ setLocation(`/tasks/${data?.task.id}`);
};
const commitActionsStore = useLocalObservable(() => new CommitActionsStore());
diff --git a/src/components/commit-logs/commit-log-list.tsx b/src/components/commit-logs/commit-log-list.tsx
index 1c0c5d5..145258b 100644
--- a/src/components/commit-logs/commit-log-list.tsx
+++ b/src/components/commit-logs/commit-log-list.tsx
@@ -4,8 +4,8 @@ import { gql, useQuery, useSubscription } from '@apollo/client';
import styles from './commit-log-list.scss';
import { CommitActions } from '../commit-actions/commit-actions';
import { FIND_PIPELINE } from '../pipelines/pipeline-list.constants';
-import { route } from 'preact-router';
import { PipelineTaskStatus } from '../pipeline-tasks/pipeline-task-status';
+import { useLocation } from 'wouter-preact';
const LIST_LOGS = gql`
subscription listLogsForPipeline($id: String!) {
@@ -41,6 +41,7 @@ export const CommitLogList = ({ pipelineId }: Props) => {
id: pipelineId!
}
});
+ const setLocation = useLocation()[1];
const queryResult = useQuery<{ pipeline: Pipeline }>(FIND_PIPELINE, {
variables: { id: pipelineId }
});
@@ -56,14 +57,7 @@ export const CommitLogList = ({ pipelineId }: Props) => {
{log.tasks.map(task => (
- -
- route(
- `/projects/${pipeline?.projectId}/pipelines/${pipeline?.id}/tasks/${task.id}`
- )
- }
- >
+
- setLocation(`/tasks/${task.id}`)}>
{task.startedAt}
))}
diff --git a/src/components/pipeline-tasks/project-details.tsx b/src/components/pipeline-tasks/project-details.tsx
index dd8b129..28899d8 100644
--- a/src/components/pipeline-tasks/project-details.tsx
+++ b/src/components/pipeline-tasks/project-details.tsx
@@ -6,12 +6,9 @@ import styles from './project-details.scss';
import { createOverlay } from '../../components/commons/overlay/overlay';
import { ProjectEditor } from '../../components/projects/project-editor';
import { CommitLogList } from '../../components/commit-logs/commit-log-list';
-import { makeAutoObservable } from 'mobx';
-import { Observer, useLocalObservable } from 'mobx-react';
-import Router, { RoutableProps, Route } from 'preact-router';
+import { Router, Route } from 'wouter-preact';
import { gql, useQuery } from '@apollo/client';
import { PipelineList } from '../../components/pipelines/pipeline-list';
-import { PipelineTaskList } from '../../components/pipeline-tasks/pipeline-task-list';
import { PipelineTaskDetails } from '../../components/pipeline-tasks/pipeline-task-details';
const FIND_PROJECT = gql`
@@ -27,21 +24,11 @@ const FIND_PROJECT = gql`
}
`;
-interface Props extends RoutableProps {
- id: string;
+interface Props {
+ projectId: string;
}
-class Store {
- setBranch(branch?: string) {
- this.branch = branch;
- }
- constructor() {
- makeAutoObservable(this);
- }
- branch?: string;
-}
-
-export const ProjectDetails = ({ id, path }: Props) => {
+export const ProjectDetails = ({ projectId: id }: Props) => {
const { data } = useQuery<{ project: Project }, { id: string }>(
FIND_PROJECT,
{
@@ -53,54 +40,43 @@ export const ProjectDetails = ({ id, path }: Props) => {
const project: Project | undefined = data?.project;
- const store = useLocalObservable(() => new Store());
const editProject = () => {
createOverlay({
content:
});
};
- const onSelectBranch = (branch?: string) => {
- store.setBranch(branch);
- };
-
return (
-
-
-
- {project?.name}
- {project?.webUrl ? (
-
-
-
- ) : null}
-
- {project?.comment}
-
-
-
-
- {project ? (
-
-
-
- {(): any => (
-
-
-
-
- )}
-
-
- ) : null}
-
+
+
+
+
+ {project?.name}
+ {project?.webUrl ? (
+
+
+
+ ) : null}
+
+ {project?.comment}
+
+
+
+
+ {project ? (
+
+
+
+ {({ taskId }) => }
+
+
+ {({ pipelineId }) => }
+
+
+ ) : null}
+
+
);
};
diff --git a/src/components/pipelines/pipeline-editor.tsx b/src/components/pipelines/pipeline-editor.tsx
index 01a6f89..5ce9add 100644
--- a/src/components/pipelines/pipeline-editor.tsx
+++ b/src/components/pipelines/pipeline-editor.tsx
@@ -1,6 +1,5 @@
import { Field, Form, Formik } from 'formik';
import { h } from 'preact';
-import { RoutableProps } from 'preact-router';
import styles from './pipeline-editor.scss';
import { useOverlay } from '../../components/commons/overlay/overlay';
import { gql, useLazyQuery, useMutation } from '@apollo/client';
@@ -75,7 +74,7 @@ const MODIFY_PIPELINE = gql`
}
`;
-interface Props extends RoutableProps {
+interface Props {
projectId: string;
id?: string;
}
diff --git a/src/components/pipelines/pipeline-list.tsx b/src/components/pipelines/pipeline-list.tsx
index f155c83..98b6b31 100644
--- a/src/components/pipelines/pipeline-list.tsx
+++ b/src/components/pipelines/pipeline-list.tsx
@@ -1,7 +1,7 @@
import { gql, useQuery, useMutation } from '@apollo/client';
-import { makeAutoObservable, reaction } from 'mobx';
+import { makeAutoObservable } from 'mobx';
import { useLocalObservable } from 'mobx-react-lite';
-import { useMemo } from 'preact/hooks';
+import { useMemo, useState } from 'preact/hooks';
import { h } from 'preact';
import { Pipeline } from '../../generated/graphql';
import styles from './pipeline-list.scss';
@@ -18,7 +18,7 @@ import { createOverlay } from '../commons/overlay/overlay';
import { PipelineEditor } from './pipeline-editor';
import { LIST_PIPELINES } from './pipeline-list.constants';
import { Observer, observer } from 'mobx-react';
-import { route } from 'preact-router';
+import { useLocation, useRoute } from 'wouter-preact';
const DELETE_PIPELINE = gql`
mutation DeletePipeline($id: String!) {
@@ -32,29 +32,25 @@ interface Props {
class Store {
pipelines?: Pipeline[];
- currPipelineId?: string;
editMode = false;
constructor() {
makeAutoObservable(this);
}
refetching = false;
- setPipelines(pipelines: any[] | undefined) {
+ setPipelines(pipelines: Pipeline[] | undefined) {
this.pipelines = pipelines;
}
setRefetching(val: boolean) {
this.refetching = val;
}
- setCurrPipelineId(id: string) {
- this.currPipelineId = id;
- }
toggleEditMode() {
this.editMode = !this.editMode;
}
}
export const PipelineList = ({ projectId }: Props) => {
- const { data, refetch, loading } = useQuery<{ pipelines: Pipeline[] }>(
+ const { data, refetch } = useQuery<{ pipelines: Pipeline[] }>(
LIST_PIPELINES,
{
variables: {
@@ -67,15 +63,26 @@ export const PipelineList = ({ projectId }: Props) => {
const store = useLocalObservable(() => new Store());
- useMemo(() => store.setPipelines(pipelines), [store, pipelines]);
-
- reaction(
- () => store.currPipelineId,
- () => {
- route(`/projects/${projectId}/pipelines/${store.currPipelineId}`);
- }
+ const [currentPipeline, setCurrentPipeline] = useState(
+ undefined
);
+ useMemo(() => store.setPipelines(pipelines), [store, pipelines]);
+ const params = useRoute('/pipelines/:pipelineId')[1];
+
+ useMemo(() => {
+ let pipeline = pipelines?.find(
+ pipeline => pipeline.id === params?.pipelineId
+ );
+ if (!pipeline) {
+ pipeline = pipelines?.[0];
+ }
+ if (pipeline === currentPipeline) {
+ return;
+ }
+ setCurrentPipeline(pipeline);
+ }, [params, pipelines]);
+
const Header = observer(() => {
const addPipeline = () => {
createOverlay({
@@ -110,7 +117,13 @@ export const PipelineList = ({ projectId }: Props) => {
});
const items = pipelines?.map(pipeline => (
- {(): any => }
+ {(): any => (
+
+ )}
));
@@ -123,7 +136,16 @@ export const PipelineList = ({ projectId }: Props) => {
};
const Item = observer(
- ({ pipeline, store }: { pipeline: Pipeline; store: Store }) => {
+ ({
+ pipeline,
+ store,
+ currentPipeline
+ }: {
+ pipeline: Pipeline;
+ store: Store;
+ currentPipeline?: Pipeline;
+ }) => {
+ const setLocation = useLocation()[1];
const [remove] = useMutation(DELETE_PIPELINE, {
variables: { id: pipeline.id },
update(cache) {
@@ -152,7 +174,7 @@ const Item = observer(
}
});
- const isActive = store.currPipelineId === pipeline.id;
+ const isActive = currentPipeline?.id === pipeline.id;
const openModifyPanel = () => {
createOverlay({
content: (
@@ -184,7 +206,7 @@ const Item = observer(
},
styles.item
)}
- onClick={() => store.setCurrPipelineId(pipeline.id)}
+ onClick={() => setLocation(`/pipelines/${pipeline.id}`)}
>
{pipeline.name}
diff --git a/src/components/projects/project-panel.tsx b/src/components/projects/project-panel.tsx
index abba436..9c07b27 100644
--- a/src/components/projects/project-panel.tsx
+++ b/src/components/projects/project-panel.tsx
@@ -1,18 +1,8 @@
import { gql, useQuery } from '@apollo/client';
-import {
- action,
- autorun,
- computed,
- makeObservable,
- observable,
- reaction
-} from 'mobx';
-import { useLocalObservable, useObserver } from 'mobx-react';
import { h } from 'preact';
-import { route } from 'preact-router';
-import { forwardRef } from 'preact/compat';
+import { forwardRef, useState } from 'preact/compat';
import { useImperativeHandle, useMemo, useRef } from 'preact/hooks';
-import { appStore } from '../../app.store';
+import { useLocation, useRoute } from 'wouter-preact';
import { Project } from '../../generated/graphql';
import { createOverlay } from '../commons/overlay/overlay';
import { ProjectEditor } from './project-editor';
@@ -33,45 +23,6 @@ const FIND_PROJECTS = gql`
interface ListRef {
refetch: () => void;
}
-
-class Store {
- @observable currentProjectId?: string;
- @observable projects?: Project[];
- constructor() {
- makeObservable(this);
- }
- @computed
- get currentProject() {
- return this.projects?.find(it => it.id === this.currentProjectId);
- }
-
- @computed
- get list() {
- return this.projects?.map(item => (
- - this.setCurrentProjectId(item.id)}
- >
-
{item.name}
- {item.comment}
-
- ));
- }
-
- @action
- setCurrentProjectId = (id: string) => {
- this.currentProjectId = id;
- route(`/projects/${id}`);
- };
-
- @action
- setProjects = (projects?: Project[]) => {
- this.projects = projects;
- };
-}
export function ProjectPanel() {
const listRef = useRef();
const addProject = () => {
@@ -104,14 +55,36 @@ const List = forwardRef((_, ref) => {
projects: Project[];
}>(FIND_PROJECTS);
const projects = data?.projects;
-
- const store = useLocalObservable(() => new Store());
+ const setLocation = useLocation()[1];
+ const params = useRoute('/projects/:projectId/:rest*')[1];
+ const [currentProject, setCurrentProject] = useState(
+ undefined
+ );
useMemo(() => {
- store.setProjects(projects);
- }, [projects, store]);
+ let project = projects?.find(project => params?.projectId === project.id);
+ if (!project) {
+ project = projects?.[0];
+ }
+ if (project === currentProject) {
+ return;
+ }
+ setCurrentProject(project);
+ }, [params, projects]);
+ const items = projects?.map(item => (
+ - setLocation(`/projects/${item.id}`)}
+ >
+
{item.name}
+ {item.comment}
+
+ ));
useImperativeHandle(ref, () => ({
refetch
}));
- return useObserver(() => {store.list}
);
+ return {items}
;
});
diff --git a/tsconfig.json b/tsconfig.json
index 7a35e6f..a458346 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -3,7 +3,7 @@
/* Basic Options */
"target": "ES6" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'. */,
"module": "ESNext" /* Specify module code generation: 'none', commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */,
- // "lib": [], /* Specify library files to be included in the compilation: */
+ "lib": ["ESNext"], /* Specify library files to be included in the compilation: */
"allowJs": true /* Allow javascript files to be compiled. */,
// "checkJs": true, /* Report errors in .js files. */
"jsx": "react" /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */,