Unverified Commit 19a8b374 authored by Ivan Gabriele's avatar Ivan Gabriele Committed by GitHub
Browse files

feat(app): migrate data-filler (#939)

parent dcbd266e
......@@ -12,7 +12,6 @@ API_SCHEME=http
# ------------------------------------------------
# Web
DATA_FILLER_PATH=/admin/data-filler
APP_DOMAIN=localhost
APP_PORT=3100
APP_PORT_PUBLIC=3100
......@@ -22,19 +21,12 @@ APP_SCHEME=http
# Development & test variables
DEV_DB_PORT=5433
DEV_KINTO_PORT=8889
DEV_POSTGREST_PORT=3001
##################################################
# Kinto
KINTO_BUCKET=datasets
##################################################
# PostgreSQL
POSTGRES_DB=test_db
POSTGRES_KINTO_DB=test_kinto_db
POSTGRES_PASSWORD=test_db_password
POSTGRES_USER=test_db_user
......
......@@ -8,7 +8,6 @@ cache:
- nodes_modules
- packages/api/nodes_modules
- packages/app/nodes_modules
- packages/data-filler/nodes_modules
jobs:
include:
......
......@@ -18,5 +18,6 @@
"directory": "./packages/data-filler",
"changeProcessCWD": true
}
]
],
"eslint.enable": true
}
......@@ -82,7 +82,6 @@ The following is the list of supported scopes:
- **db**
- **admin**
- **contrib**
- **data-filler**
There are currently a few exceptions to the "use package name" rule:
......
......@@ -23,7 +23,7 @@ numérique][link-cdtn].
git clone https://github.com/SocialGouv/code-du-travail-backoffice.git
cd code-du-travail-backoffice
yarn
# Build, migrate and seed the database (PostgreSQL), as well as the apis (PostgREST & Kinto):
# Build, migrate and seed the database (PostgreSQL), as well as the api (PostgREST):
yarn setup
# Start the containers and run packages code in dev mode (with watch & hot reload):
yarn dev
......@@ -62,10 +62,6 @@ Le site devrait être accessible à l'adresse http://localhost:3100.
{
"directory": "./packages/app",
"changeProcessCWD": true
},
{
"directory": "./packages/data-filler",
"changeProcessCWD": true
}
]
}
......
-------------------------------------- UP --------------------------------------
CREATE TABLE api.references (
id uuid PRIMARY KEY DEFAULT uuid_generate_v4(),
position smallint NOT NULL,
url text NOT NULL,
created_at timestamptz NOT NULL DEFAULT NOW(),
updated_at timestamptz NOT NULL DEFAULT NOW()
);
CREATE TRIGGER update_updated_at
BEFORE UPDATE ON api.references
FOR EACH ROW
EXECUTE PROCEDURE set_updated_at();
GRANT SELECT, INSERT, UPDATE, DELETE ON api.references TO administrator;
------------------------------------- DOWN -------------------------------------
DROP TABLE api.references;
-------------------------------------- UP --------------------------------------
CREATE TABLE api.themes (
id uuid PRIMARY KEY DEFAULT uuid_generate_v4(),
position smallint NOT NULL,
title text NOT NULL,
subtitle text,
introduction text,
variations text,
created_at timestamptz NOT NULL DEFAULT NOW(),
updated_at timestamptz NOT NULL DEFAULT NOW(),
parent_id uuid REFERENCES api.themes(id) ON DELETE SET NULL ON UPDATE NO ACTION
);
CREATE TRIGGER update_updated_at
BEFORE UPDATE ON api.themes
FOR EACH ROW
EXECUTE PROCEDURE set_updated_at();
GRANT SELECT, INSERT, UPDATE, DELETE ON api.themes TO administrator;
CREATE TABLE api.themes_references (
id serial PRIMARY KEY,
value text NOT NULL,
created_at timestamptz NOT NULL DEFAULT NOW(),
updated_at timestamptz NOT NULL DEFAULT NOW(),
theme_id uuid NOT NULL REFERENCES api.themes(id) ON DELETE CASCADE ON UPDATE NO ACTION,
reference_id uuid NOT NULL REFERENCES api.references(id) ON DELETE CASCADE ON UPDATE NO ACTION
);
CREATE TRIGGER update_updated_at
BEFORE UPDATE ON api.themes_references
FOR EACH ROW
EXECUTE PROCEDURE set_updated_at();
GRANT SELECT, INSERT, UPDATE, DELETE ON api.themes_references TO administrator;
GRANT USAGE, SELECT ON SEQUENCE api.themes_references_id_seq TO administrator;
------------------------------------- DOWN -------------------------------------
DROP TABLE api.themes_references;
DROP TABLE api.themes;
-------------------------------------- UP --------------------------------------
CREATE TABLE api.requests (
id uuid PRIMARY KEY DEFAULT uuid_generate_v4(),
question text NOT NULL,
variations text,
generic_answer text,
created_at timestamptz NOT NULL DEFAULT NOW(),
updated_at timestamptz NOT NULL DEFAULT NOW(),
theme_id uuid REFERENCES api.themes(id) ON DELETE SET NULL ON UPDATE NO ACTION
);
CREATE TRIGGER update_updated_at
BEFORE UPDATE ON api.requests
FOR EACH ROW
EXECUTE PROCEDURE set_updated_at();
GRANT SELECT, INSERT, UPDATE, DELETE ON api.requests TO administrator;
CREATE TABLE api.requests_references (
id serial PRIMARY KEY,
value text NOT NULL,
created_at timestamptz NOT NULL DEFAULT NOW(),
updated_at timestamptz NOT NULL DEFAULT NOW(),
request_id uuid NOT NULL REFERENCES api.requests(id) ON DELETE CASCADE ON UPDATE NO ACTION,
reference_id uuid NOT NULL REFERENCES api.references(id) ON DELETE CASCADE ON UPDATE NO ACTION
);
CREATE TRIGGER update_updated_at
BEFORE UPDATE ON api.requests_references
FOR EACH ROW
EXECUTE PROCEDURE set_updated_at();
GRANT SELECT, INSERT, UPDATE, DELETE ON api.requests_references TO administrator;
GRANT USAGE, SELECT ON SEQUENCE api.requests_references_id_seq TO administrator;
------------------------------------- DOWN -------------------------------------
DROP TABLE api.requests_references;
DROP TABLE api.requests;
-------------------------------------- UP --------------------------------------
CREATE TABLE api.definitions (
id uuid PRIMARY KEY DEFAULT uuid_generate_v4(),
name text NOT NULL,
value text NOT NULL,
abbreviations text,
variations text,
created_at timestamptz NOT NULL DEFAULT NOW(),
updated_at timestamptz NOT NULL DEFAULT NOW(),
theme_id uuid REFERENCES api.themes(id) ON DELETE SET NULL ON UPDATE NO ACTION
);
CREATE TRIGGER update_updated_at
BEFORE UPDATE ON api.definitions
FOR EACH ROW
EXECUTE PROCEDURE set_updated_at();
GRANT SELECT, INSERT, UPDATE, DELETE ON api.definitions TO administrator;
CREATE TABLE api.definitions_references (
id serial PRIMARY KEY,
value text NOT NULL,
created_at timestamptz NOT NULL DEFAULT NOW(),
updated_at timestamptz NOT NULL DEFAULT NOW(),
definition_id uuid NOT NULL REFERENCES api.definitions(id) ON DELETE CASCADE ON UPDATE NO ACTION,
reference_id uuid NOT NULL REFERENCES api.references(id) ON DELETE CASCADE ON UPDATE NO ACTION
);
CREATE TRIGGER update_updated_at
BEFORE UPDATE ON api.definitions_references
FOR EACH ROW
EXECUTE PROCEDURE set_updated_at();
GRANT SELECT, INSERT, UPDATE, DELETE ON api.definitions_references TO administrator;
GRANT USAGE, SELECT ON SEQUENCE api.definitions_references_id_seq TO administrator;
------------------------------------- DOWN -------------------------------------
DROP TABLE api.definitions_references;
DROP TABLE api.definitions;
const getMigrationQuery = require("../../../scripts/db/getMigrationQuery");
exports.up = async knex => {
await knex.raw(getMigrationQuery("20200204158587_create_references_table").up());
};
exports.down = async knex => {
await knex.raw(getMigrationQuery("20200204158587_create_references_table").down());
};
const getMigrationQuery = require("../../../scripts/db/getMigrationQuery");
exports.up = async knex => {
await knex.raw(getMigrationQuery("20200204161601_create_themes_table").up());
};
exports.down = async knex => {
await knex.raw(getMigrationQuery("20200204161601_create_themes_table").down());
};
const getMigrationQuery = require("../../../scripts/db/getMigrationQuery");
exports.up = async knex => {
await knex.raw(getMigrationQuery("20200204164038_create_requests_table").up());
};
exports.down = async knex => {
await knex.raw(getMigrationQuery("20200204164038_create_requests_table").down());
};
const getMigrationQuery = require("../../../scripts/db/getMigrationQuery");
exports.up = async knex => {
await knex.raw(getMigrationQuery("20200217142934_create_definitions_table").up());
};
exports.down = async knex => {
await knex.raw(getMigrationQuery("20200217142934_create_definitions_table").down());
};
const DumDum = require("dumdum");
const LABOR_LAW_REFERENCES = require("../../../packages/contrib/src/data/labor-law-references.json");
const LABOR_LAW_REFERENCES = require("../../../packages/app/src/data/labor-law-references.json");
const dumdum = DumDum.create({ locale: "fr" });
......
No preview for this file type
......@@ -5,10 +5,6 @@ services:
ports:
- ${DEV_DB_PORT}:5432
kinto:
ports:
- ${DEV_KINTO_PORT}:8888
postgrest:
ports:
- ${DEV_POSTGREST_PORT}:3000
......
......@@ -8,7 +8,6 @@ services:
# The JWT secret is used whithin the api.login() function:
PGRST_JWT_SECRET: ${PGRST_JWT_SECRET}
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_KINTO_DB: ${POSTGRES_KINTO_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
......@@ -16,20 +15,6 @@ services:
- ./backups:/backups
- ./scripts/docker/db:/scripts
# TODO Secure Kinto in prod.
kinto:
image: kinto/kinto-server:13.6.3
restart: always
environment:
KINTO_STORAGE_BACKEND: kinto.core.storage.postgresql
KINTO_STORAGE_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_KINTO_DB}
KINTO_PERMISSION_BACKEND: kinto.core.permission.postgresql
KINTO_PERMISSION_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_KINTO_DB}
KINTO_BUCKET_CREATE_PRINCIPALS: system.Everyone
KINTO_BUCKET_READ_PRINCIPALS: system.Everyone
depends_on:
- db
# https://postgrest.org/en/stable/install.html#containerized-postgrest-and-db-with-docker-compose
postgrest:
image: postgrest/postgrest:v6.0.2
......@@ -66,17 +51,13 @@ services:
API_PORT_PUBLIC: ${API_PORT_PUBLIC}
API_SCHEME: ${API_SCHEME}
API_URI_DOCKER: http://api:${API_PORT}
DATA_FILLER_PATH: ${DATA_FILLER_PATH}
DB_URI: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}
NODE_ENV: ${NODE_ENV}
KINTO_BUCKET: ${KINTO_BUCKET}
KINTO_URI: http://kinto:8888
APP_PORT: ${APP_PORT}
ports:
- ${APP_PORT}:${APP_PORT}
depends_on:
- api
- kinto
master:
# Keep the container up:
......
......@@ -10,7 +10,6 @@ Feature: Login
And I should see the subtitle "Global"
And I should see the subtitle "Par région"
And I should see the subtitle "Par convention collective"
And I should see the subtitle "Par région (détaillée)"
Scenario: Successfully login as a contributor
Given I am a registered "contributor"
......
# Web Container (including app & data-filler packages)
# Web Image
#
# TODO Move this image back to its own package?
FROM node:12.16.0-alpine
......@@ -6,21 +8,15 @@ ARG API_DOMAIN
ARG API_PORT_PUBLIC
ARG API_SCHEME
ARG API_URI_DOCKER
ARG DATA_FILLER_PATH
ARG DB_URI
ARG NODE_ENV
ARG KINTO_BUCKET
ARG KINTO_URI
ARG APP_PORT
ENV API_DOMAIN=$API_DOMAIN
ENV API_PORT_PUBLIC=$API_PORT_PUBLIC
ENV API_SCHEME=$API_SCHEME
ENV DATA_FILLER_PATH=$DATA_FILLER_PATH
ENV DB_URI=$DB_URI
ENV NODE_ENV=$NODE_ENV
ENV KINTO_BUCKET=$KINTO_BUCKET
ENV KINTO_URI=$KINTO_URI
ENV APP_PORT=$APP_PORT
WORKDIR /app
......
......@@ -7,15 +7,14 @@
"scripts": {
"build": "lerna run --scope \"@socialgouv/code-du-travail-backoffice__app\" build",
"db:backup": "node -r dotenv/config ./scripts/db/backup.js",
"db:init": "docker-compose exec -T db ./scripts/create_kinto_database.sh",
"db:migrate": "knex migrate:latest",
"db:migrate:make": "node ./scripts/db/generateMigration.js",
"db:restore": "node -r dotenv/config ./scripts/db/restore.js",
"db:seed": "knex seed:run && node ./packages/data-filler/fixture.js",
"db:seed": "knex seed:run",
"db:snapshot": "node -r dotenv/config ./scripts/db/backup.js --dev",
"db:snapshot:restore": "node -r dotenv/config ./scripts/db/restore.js --dev",
"dev": "yarn dev:docker && yarn dev:packages",
"dev:docker": "docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d kinto postgrest",
"dev:docker": "docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d postgrest",
"dev:packages": "lerna run --parallel --scope \"@socialgouv/code-du-travail-backoffice__api\" --scope \"@socialgouv/code-du-travail-backoffice__app\" dev",
"postinstall": "lerna link",
"setup": "yarn setup:env && node -r dotenv/config ./scripts/dev/setup.js",
......@@ -26,7 +25,7 @@
"test:e2e": "cucumber-js",
"test:lint": "lerna run test:lint",
"test:unit": "jest",
"test:update": "lerna run test:update",
"test:update": "lerna run --scope \"@socialgouv/code-du-travail-backoffice__app\" test:update",
"test:watch": "lerna run test:watch --parallel"
},
"dependencies": {
......
const withCss = require("@zeit/next-css");
const withTranspileModules = require("next-transpile-modules")([
"@socialgouv/code-du-travail-backoffice__data-filler"
]);
const {
API_DOMAIN,
API_PORT_PUBLIC,
API_SCHEME,
API_URI_DOCKER,
DATA_FILLER_PATH,
DEV_KINTO_PORT,
KINTO_BUCKET
} = process.env;
const { API_DOMAIN, API_PORT_PUBLIC, API_SCHEME, API_URI_DOCKER } = process.env;
const API_URI = `${API_SCHEME}://${API_DOMAIN}:${API_PORT_PUBLIC}`;
const KINTO_URI =
process.env.KINTO_URI !== undefined
? process.env.KINTO_URI
: `http://localhost:${DEV_KINTO_PORT}`;
module.exports = withCss(
// We use next-transpile-modules in order to transpile the data-filler package source so that it
// can be imported within this package during webpack build process:
// https://josephluck.co.uk/blog/next-typescript-monorepo
withTranspileModules({
// https://nextjs.org/docs#build-time-configuration
env: {
API_URI,
API_URI_DOCKER,
DATA_FILLER_PATH,
KINTO_BUCKET,
KINTO_URI
}
})
);
module.exports = withCss({
// https://nextjs.org/docs#build-time-configuration
env: {
API_URI,
API_URI_DOCKER
}
});
......@@ -35,7 +35,6 @@
"next-cookies": "2.0.3",
"next-redux-saga": "4.1.2",
"next-redux-wrapper": "4.0.1",
"next-transpile-modules": "3.0.2",
"numeral": "2.0.6",
"password-generator": "2.2.3",
"pg": "7.18.1",
......@@ -49,7 +48,6 @@
"react-paginate": "6.3.2",
"react-redux": "7.1.3",
"react-select": "3.0.8",
"react-svg-map": "2.0.2",
"react-table": "6.11.5",
"react-tag-autocomplete": "5.12.1",
"react-toastify": "5.5.0",
......
import getClient from "@socialgouv/code-du-travail-backoffice__data-filler/src/kinto/client";
import KintoContext from "@socialgouv/code-du-travail-backoffice__data-filler/src/kinto/KintoContext";
import withReduxSaga from "next-redux-saga";
import withRedux from "next-redux-wrapper";
import App from "next/app";
......@@ -37,7 +35,6 @@ class MainApp extends App {
}
render() {
const kintoClient = getClient();
const me = cache.get("me");
const { Component, pageProps, store } = this.props;
const { statusCode } = pageProps;
......@@ -47,9 +44,7 @@ class MainApp extends App {
return (
<Provider store={store}>
{hasError || me.isAuthenticated ? (
<KintoContext.Provider value={{ client: kintoClient }}>
<Component {...pageProps} />
</KintoContext.Provider>
<Component {...pageProps} />
) : (
<Login onLoggedIn={this.login.bind(this)} />
)}
......
......@@ -38,23 +38,16 @@ export default class AdminAgreementsEditPage extends AdminAgreementsNewPage {
render() {
if (this.state.isLoadingOverwrite) return <AdminMainLayout isLoading />;
const { name } = this.state.data;
return (
<AdminForm
apiPath="/agreements"
ariaLabels={{
cancelButton: `Bouton redirigeant vers la liste des conventions`,
createOrEditButton: `Bouton mettant à jour la convention "${name}"
dans la base de données à partir des données du
formulaire`
}}
defaultData={this.state.data}
fields={this.state.fields}
i18nIsFeminine
i18nSubject="convention"
id={this.props.id}
indexPath="/agreements"
name="agreement"
title={`Modifier la convention « ${name} »`}
/>
);
}
......
......@@ -18,24 +18,7 @@ const COLUMNS = [
];
const AdminAgreementIndexPage = () => (
<AdminIndex
apiPath="/agreements"
ariaLabels={{
cancelDeletionButton: `Bouton annulant la suppression de cette convention
de la base de données`,
deleteButton: `Bouton confirmant la suppression de cette convention de la
base de données`,
editButton: `Bouton redirigeant vers le formulaire d'édition des données
de cette convention`,
newButton: `Bouton redirigeant vers le formulaire de création d'une nouvel
nouvelle convetion`,
removeButton: `Bouton supprimant cette convention de la base de données
après confirmation`
}}
columns={COLUMNS}
slug="agreement"
title="Conventions"
/>
<AdminIndex apiPath="/agreements" columns={COLUMNS} i18nIsFeminine i18nSubject="convention" />
);
export default AdminAgreementIndexPage;
......@@ -61,16 +61,11 @@ export default class AdminAgreementsNewPage extends React.Component {
return (
<AdminForm
apiPath="/agreements"
ariaLabels={{
cancelButton: `Bouton redirigeant vers la liste des conventions`,
createOrEditButton: `Bouton créant une nouvelle convention dans la
base de données à partir des données du
formulaire`
}}
fields={this.state.fields}
i18nIsFeminine
i18nSubject="convention"
indexPath="/agreements"
name="agreement"
title="Nouvelle convention"
/>
);
}
......
import styled from "@emotion/styled";
import debounce from "lodash.debounce";
import React from "react";
import Medixtor from "react-medixtor";
import { connect } from "react-redux";
import { Flex } from "rebass";
......@@ -16,6 +15,7 @@ import Hr from "../../../src/elements/Hr";
import Icon from "../../../src/elements/Icon";
import Idcc from "../../../src/elements/Idcc";