Unverified Commit 5e16ca73 authored by Maxime Golfier's avatar Maxime Golfier Committed by GitHub
Browse files

feat(app): add agreements by generating answers for each agreements (#1233)

* feat: add CC

* fix: linter

* fix: com

* fix: some issues

* fix: agreements.ts

* fix: doc

* fix: yarn.lock

* fix(app): agreements without parent_id
parent aba35894
......@@ -3,32 +3,34 @@
We would love for you to contribute to the backoffice of [Code du travail numérique][link-cdtn] and
help make it even better than it is today!
- [Contribute](#contribute)
- [Prerequisites](#prerequisites)
- [Get Started](#get-started)
- [Standalone](#standalone)
- [Test](#test)
- [Scripts](#scripts)
- [Recommended IDE Settings](#recommended-ide-settings)
- [VS Code](#vs-code)
- [Known Issues](#known-issues)
- [Docker Compose](#docker-compose)
- [Jest Watch](#jest-watch)
- [Common Tasks](#common-tasks)
- [Database backup in production](#database-backup-in-production)
- [Database restore in production](#database-restore-in-production)
- [Database snapshot update in development](#database-snapshot-update-in-development)
- [Database snapshot restore in development](#database-snapshot-restore-in-development)
- [Naming Guidelines](#naming-guidelines)
- [API-related methods](#api-related-methods)
- [React methods](#react-methods)
- [Redux states](#redux-states)
- [React variables](#react-variables)
- [Commit Message Guidelines](#commit-message-guidelines)
- [Revert](#revert)
- [Type](#type)
- [Scope](#scope)
- [Subject](#subject)
- [Contributing](#contributing)
- [Contribute](#contribute)
- [Prerequisites](#prerequisites)
- [Get Started](#get-started)
- [To run on arm architecture](#to-run-on-arm-architecture)
- [Standalone](#standalone)
- [Test](#test)
- [Scripts](#scripts)
- [Recommended IDE Settings](#recommended-ide-settings)
- [VS Code](#vs-code)
- [Known Issues](#known-issues)
- [Docker Compose](#docker-compose)
- [Jest Watch](#jest-watch)
- [Common Tasks](#common-tasks)
- [Database backup in production](#database-backup-in-production)
- [Database restore in production](#database-restore-in-production)
- [Database snapshot update in development](#database-snapshot-update-in-development)
- [Database snapshot restore in development](#database-snapshot-restore-in-development)
- [Naming Guidelines](#naming-guidelines)
- [API-related methods](#api-related-methods)
- [React methods](#react-methods)
- [Redux states](#redux-states)
- [React variables](#react-variables)
- [Commit Message Guidelines](#commit-message-guidelines)
- [Revert](#revert)
- [Type](#type)
- [Scope](#scope)
- [Subject](#subject)
## Contribute
......@@ -62,6 +64,24 @@ The website should now be available at: <http://localhost:3100>.
- Email: `nemo@sea.com`
Mot de passe: `Azerty123`
#### To run on arm architecture
You have to change `docker-compose.yml` by replacing `postgrest` service by the following one:
```yml
postgrest:
container_name: cdtn_backoffice_postgrest
image: hughjfchen/hughjfchen:postgrest-aarch64-6.0.2
restart: always
environment:
PGRST_DB_ANON_ROLE: ${PGRST_DB_ANON_ROLE}
PGRST_DB_SCHEMA: ${PGRST_DB_SCHEMA}
PGRST_DB_URI: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}
PGRST_JWT_SECRET: ${PGRST_JWT_SECRET}
depends_on:
- db
```
### Standalone
Standalone dev also runs [**ctdn-api**](https://github.com/SocialGouv/cdtn-api) locally:
......@@ -248,8 +268,8 @@ interface {
### React variables
- All the variables referencing a component must start with **$**
(i.e.: `<Button ref={node => this.$button = node}>`).
- All the variables referencing a component must start with **$** (i.e.:
`<Button ref={node => this.$button = node}>`).
---
......@@ -317,6 +337,8 @@ The subject contains a succinct description of the change:
[link-cdtb-commits]: https://github.com/SocialGouv/code-du-travail-backoffice/commits/master
[link-cdtn]: https://code.travail.gouv.fr
[link-docker-no-sudo]: https://docs.docker.com/install/linux/linux-postinstall/#manage-docker-as-a-non-root-user
[link-issue-1]: https://github.com/docker/docker-credential-helpers/issues/103#issuecomment-421822269
[link-docker-no-sudo]:
https://docs.docker.com/install/linux/linux-postinstall/#manage-docker-as-a-non-root-user
[link-issue-1]:
https://github.com/docker/docker-credential-helpers/issues/103#issuecomment-421822269
[link-issue-2]: https://github.com/facebook/jest/issues/3254#issuecomment-297214395
......@@ -19,6 +19,7 @@ services:
postgrest:
container_name: cdtn_backoffice_postgrest
image: postgrest/postgrest:v6.0.2
# image: hughjfchen/hughjfchen:postgrest-aarch64-6.0.2 # for aarch64
restart: always
environment:
PGRST_DB_ANON_ROLE: ${PGRST_DB_ANON_ROLE}
......
module.exports = {
extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
parser: "@typescript-eslint/parser",
plugins: ["@typescript-eslint", "jest", "only-warn"],
root: true,
env: {
"jest/globals": true,
browser: true,
node: true,
},
};
/// <reference types="next" />
/// <reference types="next/types/global" />
......@@ -20,6 +20,7 @@
"@fortawesome/react-fontawesome": "0.1.14",
"@koa/router": "10.0.0",
"@zeit/next-css": "1.0.1",
"axios": "^0.24.0",
"colors": "1.4.0",
"diff": "5.0.0",
"emotion": "11.0.0",
......@@ -76,15 +77,23 @@
"@testing-library/jest-dom": "5.11.8",
"@testing-library/react": "12.1.2",
"@types/hast": "2.3.1",
"@types/node": "^16.11.12",
"@types/ramda": "0.27.34",
"@types/react": "^17.0.37",
"@types/react-test-renderer": "17.0.0",
"@typescript-eslint/eslint-plugin": "^5.6.0",
"@typescript-eslint/parser": "^5.6.0",
"dotenv": "10.0.0",
"eslint": "^8.4.1",
"eslint-plugin-jest": "^25.3.0",
"eslint-plugin-only-warn": "^1.0.3",
"identity-obj-proxy": "3.0.0",
"mutationobserver-shim": "0.3.7",
"nodemon": "2.0.7",
"prettier": "2.2.1",
"react-test-renderer": "17.0.1",
"rimraf": "3.0.2",
"typescript": "^4.5.3",
"waait": "1.0.5",
"zxcvbn": "4.4.2"
}
......
import withAdminEdit from "../../../src/templates/withAdminEdit";
import { FIELDS } from "./new";
const componentDidMount = async (api, id) => {
const { data: agreements } = await api.eq("id", id).get("/agreements");
const { data: allAgreements } = await api.get("/agreements");
const fields = [
...FIELDS,
{
label: "Nom",
name: "name",
type: "input",
},
{
label: "IDCC",
name: "idcc",
type: "input",
},
{
label: "Convention parente",
name: "parent_id",
......
import withAdminNew from "../../../src/templates/withAdminNew";
export const FIELDS = [
{
label: "Nom",
name: "name",
type: "input",
},
{
label: "IDCC",
name: "idcc",
type: "input",
},
];
const componentDidMount = async api => {
const { data: agreements } = await api.get("/agreements");
const fields = [
...FIELDS,
{
label: "Convention parente",
name: "parent_id",
options: agreements.map(({ id, idcc, name }) => ({
label: `${idcc} - ${name}`,
value: id,
})),
type: "select",
},
];
return { fields };
};
const AdminAgreementsNewPage = withAdminNew(
{
apiPath: "/agreements",
i18nIsFeminine: true,
i18nSubject: "convention",
indexPath: "/agreements",
},
componentDidMount,
);
export default AdminAgreementsNewPage;
import { useRouter } from "next/router";
import React from "react";
import { addAgreement } from "../../../src/api";
import AdminForm from "../../../src/components/AdminForm";
import AdminMain from "../../../src/layouts/AdminMain";
import customPostgrester from "../../../src/libs/customPostgrester";
import toast from "../../../src/libs/toast";
export default function AdminNew(props: any): JSX.Element {
const [isLoading, setIsLoading] = React.useState(true);
const [fields, setFields] = React.useState([]);
const { back } = useRouter();
React.useEffect(() => {
async function init() {
const { data: agreements } = await customPostgrester().get("/agreements");
const fields = [
{
label: "Nom",
name: "name",
type: "input",
},
{
label: "IDCC",
name: "idcc",
type: "input",
},
{
label: "Convention parente",
name: "parent_id",
options: agreements.map(({ id, idcc, name }) => ({
label: `${idcc} - ${name}`,
value: id,
})),
type: "select",
},
];
setFields(fields);
setIsLoading(false);
}
init();
}, []);
const onSubmit = async data => {
try {
await addAgreement(data.name, data.idcc, data.parent_id);
back();
} catch (e) {
toast.error(e.message);
}
};
return (
<>
{isLoading ? (
<AdminMain isLoading />
) : (
<AdminForm
apiPath="/agreements"
fields={fields}
i18nIsFeminine={true}
i18nSubject="convention"
indexPath="/agreements"
onSubmit={onSubmit}
/>
)}
</>
);
}
import { apiFetch, getHeaderId } from "../utils";
export const addAgreement = async (
name: string,
idcc: string,
parent_id?: string,
): Promise<any> => {
const { headers } = await apiFetch(
"POST",
"/agreements",
parent_id ? { name, idcc, parent_id } : { name, idcc },
);
const agreementId = getHeaderId(headers.location);
const { data: questions } = await apiFetch("GET", "/questions");
return Promise.all(
questions.map(question =>
apiFetch("POST", "/answers", {
agreement_id: agreementId,
question_id: question.id,
state: "draft",
user_id: null,
parent_id: null,
prevalue: "",
generic_reference: null,
value: "",
}),
),
);
};
export * from "./agreements";
......@@ -100,6 +100,12 @@ class AdminForm extends React.Component {
*/
async submit(event) {
event.preventDefault();
const { onSubmit } = this.props;
if (onSubmit) {
onSubmit(this.state);
return;
}
if (this.state.isSubmitting) return;
this.setState({ error: null, isSubmitting: true });
const { apiPath } = this.props;
......@@ -414,6 +420,7 @@ AdminForm.propTypes = {
id: PropTypes.string,
indexPath: PropTypes.string.isRequired,
name: PropTypes.any,
onSubmit: PropTypes.func,
};
export default AdminForm;
import jsCookie from "js-cookie";
import axios from "axios";
export type ApiFetchType = "GET" | "POST" | "PUT" | "DELETE";
export function apiFetch(
method: ApiFetchType,
path: string,
data?: Record<string, any>,
): Promise<any> {
return new Promise((resolve, reject) => {
axios({
method,
url: process.env.API_URI + path,
data,
headers: {
Authorization: `Bearer ${jsCookie.get("jwt")}`,
},
}).then(
result => {
resolve(result);
},
error => {
reject(error);
},
);
});
}
export * from "./process";
export * from "./api";
export function getHeaderId(location: string): string {
try {
return location.split("?id=eq.")[1];
} catch {
return null;
}
}
{
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"strict": false,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve"
},
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx"
],
"exclude": [
"node_modules"
]
}
This diff is collapsed.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment