├── backend ├── app │ ├── __init__.py │ ├── logging.conf │ ├── main.py │ ├── schemas.py │ └── endpoints.py ├── tests │ ├── __init__.py │ ├── data │ │ ├── foo.bar │ │ ├── test.txt │ │ ├── test.pdf │ │ └── cli │ │ │ ├── expected │ │ │ ├── nested │ │ │ │ └── test.txt │ │ │ └── test.html │ │ │ ├── input │ │ │ ├── nested │ │ │ │ └── test.txt │ │ │ └── test.html │ │ │ ├── recognizer_config.json │ │ │ └── anonymizer_config.json │ ├── cli │ │ ├── __init__.py │ │ └── test_cli.py │ ├── endpoints │ │ ├── __init__.py │ │ ├── test_tags.py │ │ ├── test_supported_recognizers.py │ │ ├── test_score.py │ │ ├── test_anonymize_file.py │ │ ├── test_find_piis.py │ │ └── test_anonymize.py │ └── conftest.py ├── pyproject.toml ├── .flake8 ├── requirements-dev.txt ├── .dockerignore ├── cli │ ├── recognizer_config.json │ ├── anonymizer_config.json │ └── redact.py ├── requirements.txt ├── README.md └── Dockerfile ├── frontend ├── .dockerignore ├── src │ ├── components │ │ ├── scores │ │ │ ├── ScoresDialog.sass │ │ │ ├── ScoresDialogBody.test.jsx │ │ │ ├── ScoresTable.test.jsx │ │ │ ├── ScoresDialog.test.jsx │ │ │ ├── ScoresDialog.jsx │ │ │ ├── ScoresDialogBody.jsx │ │ │ └── ScoresTable.jsx │ │ ├── HelpDialog.sass │ │ ├── ActiveRecognizerSettings.sass │ │ ├── preview │ │ │ ├── PdfPreview.sass │ │ │ ├── TextPreview.sass │ │ │ ├── PreviewControl.sass │ │ │ ├── TextPreview.test.jsx │ │ │ ├── TextPreview.jsx │ │ │ ├── PreviewControl.test.jsx │ │ │ ├── PdfPreview.jsx │ │ │ └── PreviewControl.jsx │ │ ├── annotation │ │ │ ├── annotator │ │ │ │ ├── Span.js │ │ │ │ ├── Mark.jsx │ │ │ │ ├── utils.js │ │ │ │ └── TokenAnnotator.jsx │ │ │ ├── AnnotationControl.sass │ │ │ ├── Dropzone.test.jsx │ │ │ ├── Dropzone.sass │ │ │ ├── AnnotationControl.test.jsx │ │ │ ├── AnnotationForm.test.jsx │ │ │ ├── Dropzone.jsx │ │ │ ├── AnnotationControl.jsx │ │ │ ├── AnnotationForm.sass │ │ │ └── AnnotationForm.jsx │ │ ├── App.sass │ │ ├── NavBar.sass │ │ ├── AboutDialog.sass │ │ ├── Disclaimer.jsx │ │ ├── Main.sass │ │ ├── anonymizationConfig │ │ │ ├── RandomizedResponseMechanism.jsx │ │ │ ├── AnonymizationConfigMenu.test.jsx │ │ │ ├── Item.jsx │ │ │ ├── AnonymizationConfigMenu.sass │ │ │ ├── GeneralizationMechanism.jsx │ │ │ ├── TagMechanismConfig.jsx │ │ │ ├── DefaultMechanismConfig.jsx │ │ │ ├── LaplaceNoiseMechanism.jsx │ │ │ ├── anonymizationConfig.jsx │ │ │ ├── PseudonymizationMechanism.jsx │ │ │ ├── randomizedResponseCountryDemoValues.js │ │ │ ├── SuppressionMechanism.jsx │ │ │ └── AnonymizationConfigMenu.jsx │ │ ├── LocalizationWrapper.jsx │ │ ├── LocalizationWrapper.test.jsx │ │ ├── MainMenu.test.jsx │ │ ├── App.test.jsx │ │ ├── MainMenu.sass │ │ ├── Help.jsx │ │ ├── About.jsx │ │ ├── NavBar.test.jsx │ │ ├── NavBar.jsx │ │ ├── HelpDialog.jsx │ │ ├── ErrorBoundary.jsx │ │ ├── Settings.jsx │ │ ├── AboutDialog.jsx │ │ ├── ActiveRecognizerSettings.jsx │ │ ├── SettingsDialog.jsx │ │ ├── MainMenu.jsx │ │ ├── App.jsx │ │ ├── Main.test.jsx │ │ └── Main.jsx │ ├── js │ │ ├── toaster.js │ │ ├── polyglotContext.js │ │ ├── anonymization.js │ │ ├── annotation.js │ │ ├── constants.js │ │ ├── token.js │ │ ├── useLocalStorage.js │ │ ├── useCompile.js │ │ └── useAnonymization.js │ ├── setupTests.js │ ├── index.jsx │ ├── index.css │ ├── translations │ │ ├── utils.js │ │ ├── en.js │ │ └── de.js │ └── api │ │ └── routes.js ├── public │ ├── robots.txt │ ├── favicon.ico │ └── index.html ├── Dockerfile.dev ├── Dockerfile ├── .gitignore ├── nginx.conf ├── package.json └── README.md ├── docs ├── logo.png ├── scores.png ├── approach.png ├── annotation.png ├── end-to-end.gif └── anonymization.gif ├── .gitignore ├── docker-compose.yml ├── .run ├── Dev Servers.run.xml ├── Lint, format and test project.run.xml ├── Frontend Dev Server.run.xml ├── Frontend Tests.run.xml ├── Backend Tests.run.xml ├── Pre-commit Hooks.run.xml └── Backend Dev Server.run.xml ├── docker-compose.dev.yml ├── .github └── workflows │ ├── pre_commit.yml │ ├── test_frontend.yml │ └── test_backend.yml ├── .pre-commit-config.yaml ├── LICENSE └── README.md /backend/app/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /backend/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /backend/tests/data/foo.bar: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /backend/tests/cli/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /backend/tests/endpoints/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /backend/tests/data/test.txt: -------------------------------------------------------------------------------- 1 | Deutschland. -------------------------------------------------------------------------------- /frontend/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /backend/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.black] 2 | line-length = 127 3 | -------------------------------------------------------------------------------- /backend/.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | ignore = E203, W503 3 | max-line-length = 127 4 | -------------------------------------------------------------------------------- /frontend/src/components/scores/ScoresDialog.sass: -------------------------------------------------------------------------------- 1 | .dialog 2 | width: auto 3 | -------------------------------------------------------------------------------- /docs/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openredact/openredact-app/HEAD/docs/logo.png -------------------------------------------------------------------------------- /frontend/src/components/HelpDialog.sass: -------------------------------------------------------------------------------- 1 | .more-vertical-space 2 | padding-top: 20px 3 | -------------------------------------------------------------------------------- /docs/scores.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openredact/openredact-app/HEAD/docs/scores.png -------------------------------------------------------------------------------- /docs/approach.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openredact/openredact-app/HEAD/docs/approach.png -------------------------------------------------------------------------------- /docs/annotation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openredact/openredact-app/HEAD/docs/annotation.png -------------------------------------------------------------------------------- /docs/end-to-end.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openredact/openredact-app/HEAD/docs/end-to-end.gif -------------------------------------------------------------------------------- /docs/anonymization.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openredact/openredact-app/HEAD/docs/anonymization.gif -------------------------------------------------------------------------------- /frontend/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /backend/requirements-dev.txt: -------------------------------------------------------------------------------- 1 | pre-commit==2.16.0 2 | black==19.10b0 3 | pytest==5.4.1 4 | pytest-cov==2.8.1 5 | -------------------------------------------------------------------------------- /backend/tests/data/test.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openredact/openredact-app/HEAD/backend/tests/data/test.pdf -------------------------------------------------------------------------------- /frontend/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openredact/openredact-app/HEAD/frontend/public/favicon.ico -------------------------------------------------------------------------------- /backend/tests/data/cli/expected/nested/test.txt: -------------------------------------------------------------------------------- 1 | Meine E-Mail Adresse lautet Email 1. 2 | Sie ist in XXXXXXXXXXX registriert. 3 | -------------------------------------------------------------------------------- /frontend/src/components/ActiveRecognizerSettings.sass: -------------------------------------------------------------------------------- 1 | .recognizer-list 2 | margin-right: 20px 3 | list-style-type: none 4 | -------------------------------------------------------------------------------- /backend/tests/data/cli/input/nested/test.txt: -------------------------------------------------------------------------------- 1 | Meine E-Mail Adresse lautet test@mail.de. 2 | Sie ist in Deutschland registriert. 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # PyCharm 2 | .idea/ 3 | 4 | # Mac 5 | .DS_Store 6 | 7 | # Virtualenv 8 | venv/ 9 | 10 | # Tests 11 | __pycache__ 12 | -------------------------------------------------------------------------------- /backend/.dockerignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .pytest_cache 3 | 4 | # Mac 5 | .DS_Store 6 | 7 | # Virtualenv 8 | venv/ 9 | 10 | # Tests 11 | __pycache__ 12 | -------------------------------------------------------------------------------- /backend/cli/recognizer_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "language": "de", 3 | "recognizer_paths": [], 4 | "use_statistical_ner": true, 5 | "load_integrated_recognizers": true 6 | } 7 | -------------------------------------------------------------------------------- /frontend/src/components/preview/PdfPreview.sass: -------------------------------------------------------------------------------- 1 | .react-pdf__Page__canvas 2 | margin: 0 auto 3 | 4 | .pdf-outline 5 | border-radius: 0 6 | margin: 10px 7 | padding: 0 8 | -------------------------------------------------------------------------------- /backend/tests/data/cli/recognizer_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "language": "de", 3 | "recognizer_paths": [], 4 | "use_statistical_ner": false, 5 | "load_integrated_recognizers": true 6 | } 7 | -------------------------------------------------------------------------------- /backend/tests/endpoints/test_tags.py: -------------------------------------------------------------------------------- 1 | def test_get_tags(client): 2 | response = client.get("/api/tags") 3 | assert response.status_code == 200 4 | assert "PER" in response.json() 5 | -------------------------------------------------------------------------------- /frontend/src/components/annotation/annotator/Span.js: -------------------------------------------------------------------------------- 1 | class Span { 2 | constructor(start, end) { 3 | this.start = start; 4 | this.end = end; 5 | } 6 | } 7 | 8 | export default Span; 9 | -------------------------------------------------------------------------------- /frontend/src/components/App.sass: -------------------------------------------------------------------------------- 1 | @import "~@blueprintjs/core/lib/scss/variables" 2 | 3 | $config-width: 16vw 4 | 5 | .grid-container 6 | display: grid 7 | grid-template-columns: 0.16fr 0.84fr 8 | -------------------------------------------------------------------------------- /frontend/src/js/toaster.js: -------------------------------------------------------------------------------- 1 | import { Position, Toaster } from "@blueprintjs/core"; 2 | 3 | const AppToaster = Toaster.create({ 4 | position: Position.TOP_RIGHT, 5 | }); 6 | 7 | export default AppToaster; 8 | -------------------------------------------------------------------------------- /backend/cli/anonymizer_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "defaultMechanism": { 3 | "mechanism": "suppression", 4 | "config": { 5 | "suppressionChar": "X" 6 | } 7 | }, 8 | "mechanismsByTag": {} 9 | } 10 | -------------------------------------------------------------------------------- /frontend/src/components/preview/TextPreview.sass: -------------------------------------------------------------------------------- 1 | .preview-text 2 | cursor: default 3 | padding: 15px 4 | font-family: "Courier New", sans-serif 5 | 6 | .document-outline 7 | border-radius: 0 8 | margin: 10px 9 | -------------------------------------------------------------------------------- /backend/tests/endpoints/test_supported_recognizers.py: -------------------------------------------------------------------------------- 1 | def test_get_supported_recognizers(client): 2 | response = client.get("/api/recognizers") 3 | assert response.status_code == 200 4 | assert "email_recognizer" in response.json() 5 | -------------------------------------------------------------------------------- /frontend/src/js/polyglotContext.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const PolyglotContext = React.createContext((key, options = {}) => 4 | options === {} ? key : key + JSON.stringify(options) 5 | ); 6 | 7 | export default PolyglotContext; 8 | -------------------------------------------------------------------------------- /frontend/src/components/annotation/AnnotationControl.sass: -------------------------------------------------------------------------------- 1 | @import "~@blueprintjs/core/lib/scss/variables" 2 | @import "../Main" 3 | 4 | .annotation-card 5 | margin: $border-width 0.5*$border-width $border-width $border-width 6 | position: relative 7 | box-shadow: none 8 | -------------------------------------------------------------------------------- /frontend/Dockerfile.dev: -------------------------------------------------------------------------------- 1 | # build and run the frontend 2 | FROM node:10 3 | 4 | WORKDIR /app 5 | 6 | COPY package*.json /app/ 7 | 8 | RUN npm install 9 | 10 | ENV REACT_APP_API_BASE_URL=http://127.0.0.1:8000/api 11 | 12 | COPY public /app/public 13 | COPY src /app/src 14 | -------------------------------------------------------------------------------- /frontend/src/components/NavBar.sass: -------------------------------------------------------------------------------- 1 | .logo 2 | width: 40px 3 | height: 40px 4 | margin-right: 10px 5 | 6 | .heading 7 | font-size: 20px 8 | 9 | .branding 10 | a 11 | color: inherit 12 | text-decoration: inherit 13 | 14 | &:hover 15 | color: inherit 16 | -------------------------------------------------------------------------------- /backend/requirements.txt: -------------------------------------------------------------------------------- 1 | fastapi==0.65.2 2 | uvicorn==0.11.7 3 | python-multipart==0.0.5 4 | click==7.1.1 5 | git+https://github.com/openredact/expose-text.git#egg=expose-text 6 | git+https://github.com/openredact/nerwhal.git#egg=nerwhal 7 | git+https://github.com/openredact/anonymizer.git#egg=or-anonymizer 8 | -------------------------------------------------------------------------------- /backend/tests/endpoints/test_score.py: -------------------------------------------------------------------------------- 1 | def test_score_computation(client): 2 | response = client.post( 3 | "/api/score", json={"computedAnnotations": [], "goldAnnotations": [{"start": 0, "end": 1, "tag": "PER"}]} 4 | ) 5 | assert response.status_code == 200 6 | assert response.json()["total"]["f1"] == 0.0 7 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.3" 2 | services: 3 | backend: 4 | build: 5 | context: ./backend 6 | image: openredact/backend:${TAG:-latest} 7 | expose: 8 | - 8000 9 | frontend: 10 | build: ./frontend 11 | image: openredact/frontend:${TAG:-latest} 12 | ports: 13 | - "80:80" 14 | -------------------------------------------------------------------------------- /frontend/src/js/anonymization.js: -------------------------------------------------------------------------------- 1 | class Anonymization { 2 | constructor({ start, end, startChar, endChar, text }) { 3 | this.start = start; 4 | this.end = end; 5 | this.startChar = startChar; 6 | this.endChar = endChar; 7 | this.text = text; 8 | } 9 | } 10 | 11 | export default Anonymization; 12 | -------------------------------------------------------------------------------- /frontend/src/js/annotation.js: -------------------------------------------------------------------------------- 1 | import { v4 as uuidv4 } from "uuid"; 2 | 3 | class Annotation { 4 | constructor(start, end, tag, text) { 5 | this.start = start; 6 | this.end = end; 7 | this.text = text; 8 | this.tag = tag; 9 | this.id = uuidv4(); 10 | } 11 | } 12 | 13 | export default Annotation; 14 | -------------------------------------------------------------------------------- /frontend/src/js/constants.js: -------------------------------------------------------------------------------- 1 | const constants = {}; 2 | 3 | constants.title = "OpenRedact"; 4 | constants.tooltipHoverOpenDelay = 500; 5 | constants.maxTagColors = 12; 6 | constants.compileTimeout = 300; 7 | 8 | // Set fixed value or 0 for auto width 9 | constants.previewPdfWidth = 0; 10 | 11 | export default constants; 12 | -------------------------------------------------------------------------------- /backend/tests/data/cli/expected/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Test 6 | 7 | 8 | 9 |
Meine E-Mail Adresse lautet Email 1.
10 |
Sie ist in XXXXXXXXXXX registriert.
11 | 12 | 13 | -------------------------------------------------------------------------------- /backend/tests/data/cli/input/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Test 6 | 7 | 8 | 9 |
Meine E-Mail Adresse lautet test@mail.de.
10 |
Sie ist in Deutschland registriert.
11 | 12 | 13 | -------------------------------------------------------------------------------- /frontend/src/js/token.js: -------------------------------------------------------------------------------- 1 | class Token { 2 | constructor(startChar, endChar, text, hasWhitespace, linebreakCount) { 3 | this.startChar = startChar; 4 | this.endChar = endChar; 5 | this.text = text; 6 | this.hasWhitespace = hasWhitespace; 7 | this.linebreakCount = linebreakCount; 8 | } 9 | } 10 | 11 | export default Token; 12 | -------------------------------------------------------------------------------- /frontend/src/setupTests.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/no-extraneous-dependencies */ 2 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 3 | // allows you to do things like: 4 | // expect(element).toHaveTextContent(/react/i) 5 | // learn more: https://github.com/testing-library/jest-dom 6 | import "@testing-library/jest-dom/extend-expect"; 7 | -------------------------------------------------------------------------------- /backend/tests/conftest.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | 3 | import pytest 4 | from fastapi.testclient import TestClient 5 | 6 | from app.main import app 7 | 8 | 9 | @pytest.fixture(scope="session") 10 | def client(): 11 | return TestClient(app) 12 | 13 | 14 | @pytest.fixture 15 | def test_data(): 16 | return Path(__file__).parent / "data" 17 | -------------------------------------------------------------------------------- /.run/Dev Servers.run.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /frontend/src/components/AboutDialog.sass: -------------------------------------------------------------------------------- 1 | @import "~@blueprintjs/core/lib/scss/variables" 2 | 3 | .logo-background 4 | background: $dark-gray3 5 | 6 | .logo 7 | width: 40px 8 | height: 40px 9 | display: block 10 | margin: 20px auto 11 | 12 | .copyright 13 | margin-top: 40px 14 | margin-bottom: 0 15 | 16 | .more-vertical-space 17 | padding-top: 20px 18 | -------------------------------------------------------------------------------- /frontend/src/components/annotation/Dropzone.test.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { render } from "@testing-library/react"; 3 | import Dropzone from "./Dropzone"; 4 | 5 | it("renders", () => { 6 | const { getByText } = render( {}} />); 7 | const dropzone = getByText(/\.txt/i); 8 | expect(dropzone).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /frontend/src/components/annotation/Dropzone.sass: -------------------------------------------------------------------------------- 1 | @import "~@blueprintjs/core/lib/scss/variables" 2 | 3 | .dropzone 4 | display: flex 5 | flex-direction: column 6 | align-items: center 7 | padding: 20px 8 | border-width: 2px 9 | border-radius: 2px 10 | border-color: $gray3 11 | border-style: dashed 12 | background-color: $white 13 | color: $pt-text-color-muted 14 | outline: none 15 | -------------------------------------------------------------------------------- /frontend/src/components/preview/PreviewControl.sass: -------------------------------------------------------------------------------- 1 | @import "../Main" 2 | 3 | .preview-card 4 | margin: $border-width $border-width $border-width 0.5*$border-width 5 | position: relative 6 | box-shadow: none 7 | padding: 0 8 | 9 | .cancel-warning 10 | top: 5px 11 | right: 5px 12 | position: absolute 13 | cursor: pointer 14 | 15 | .preview-html 16 | & > div 17 | margin: 0 auto 18 | -------------------------------------------------------------------------------- /backend/tests/data/cli/anonymizer_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "defaultMechanism": { 3 | "mechanism": "suppression", 4 | "config": { 5 | "suppressionChar": "X" 6 | } 7 | }, 8 | "mechanismsByTag": { 9 | "EMAIL": { 10 | "mechanism": "pseudonymization", 11 | "config": { 12 | "format_string": "Email {}", 13 | "stateful": true 14 | } 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /frontend/Dockerfile: -------------------------------------------------------------------------------- 1 | # build and compile the frontend 2 | FROM node:10 as build-stage 3 | 4 | WORKDIR /app 5 | 6 | COPY package*.json /app/ 7 | 8 | RUN npm install 9 | 10 | COPY ./ /app/ 11 | 12 | ENV REACT_APP_API_BASE_URL=/api 13 | 14 | RUN npm run build 15 | 16 | # serve built frontend using nginx 17 | FROM nginx:1.15 18 | 19 | COPY --from=build-stage /app/build/ /assets 20 | COPY nginx.conf /etc/nginx/nginx.conf -------------------------------------------------------------------------------- /frontend/src/components/preview/TextPreview.test.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { render } from "@testing-library/react"; 3 | import TextPreview from "./TextPreview"; 4 | 5 | it("renders preview text", () => { 6 | const text = "This is a sample text."; 7 | const { getByText } = render(); 8 | const element = getByText(text); 9 | expect(element).toBeInTheDocument(); 10 | }); 11 | -------------------------------------------------------------------------------- /frontend/src/components/scores/ScoresDialogBody.test.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { render } from "@testing-library/react"; 3 | import ScoresDialogBody from "./ScoresDialogBody"; 4 | 5 | it("renders", () => { 6 | const { getByText } = render( 7 | 8 | ); 9 | const text = getByText(/annotation\.scores/); 10 | expect(text).toBeInTheDocument(); 11 | }); 12 | -------------------------------------------------------------------------------- /.run/Lint, format and test project.run.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /frontend/src/index.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | import { FocusStyleManager } from "@blueprintjs/core"; 4 | import "./index.css"; 5 | import LocalizationWrapper from "./components/LocalizationWrapper"; 6 | 7 | FocusStyleManager.onlyShowFocusOnTabs(); 8 | 9 | ReactDOM.render( 10 | 11 | 12 | , 13 | document.getElementById("root") 14 | ); 15 | -------------------------------------------------------------------------------- /frontend/src/components/Disclaimer.jsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from "react"; 2 | import { Callout } from "@blueprintjs/core"; 3 | import PolyglotContext from "../js/polyglotContext"; 4 | 5 | const Disclaimer = () => { 6 | const t = useContext(PolyglotContext); 7 | 8 | return ( 9 | 10 | {t("disclaimer.text")} 11 | 12 | ); 13 | }; 14 | 15 | export default Disclaimer; 16 | -------------------------------------------------------------------------------- /frontend/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | 25 | public/pdf.worker.min.js 26 | -------------------------------------------------------------------------------- /frontend/src/components/Main.sass: -------------------------------------------------------------------------------- 1 | @import "~@blueprintjs/core/lib/scss/variables" 2 | 3 | $border-width: 5px 4 | $main-menu-height: 40px 5 | $main-view-height: calc(100vh - #{$pt-navbar-height} - #{$main-menu-height}) 6 | 7 | .main 8 | display: grid 9 | grid: $main-menu-height $main-view-height / 100% 10 | 11 | .main-view 12 | display: grid 13 | grid: auto / 50% 50% 14 | overflow-y: scroll 15 | position: relative 16 | background-color: $light-gray3 17 | -------------------------------------------------------------------------------- /frontend/src/components/annotation/AnnotationControl.test.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { render } from "@testing-library/react"; 3 | import AnnotationControl from "./AnnotationControl"; 4 | 5 | it("renders", () => { 6 | render( 7 | {}} 11 | onFileDrop={() => {}} 12 | isLoading={false} 13 | tags={[]} 14 | /> 15 | ); 16 | }); 17 | -------------------------------------------------------------------------------- /frontend/src/index.css: -------------------------------------------------------------------------------- 1 | @import "~normalize.css"; 2 | @import "~@blueprintjs/core/lib/css/blueprint.css"; 3 | @import "~@blueprintjs/icons/lib/css/blueprint-icons.css"; 4 | 5 | body { 6 | margin: 0; 7 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", 8 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", 9 | sans-serif; 10 | -webkit-font-smoothing: antialiased; 11 | -moz-osx-font-smoothing: grayscale; 12 | } 13 | -------------------------------------------------------------------------------- /.run/Frontend Dev Server.run.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |