Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ BROWSER=false
PORT=8081
SKIP_PREFLIGHT_CHECK=true
REACT_APP_DHIS2_BASE_URL=http://localhost:8080
VITE_DHIS2_BASE_URL=http://localhost:8080
VITE_DHIS2_AUTH=
VITE_PORT=8081

CYPRESS_DHIS2_AUTH='admin:district'
CYPRESS_EXTERNAL_API="https://dev.eyeseetea.com/play"
Expand Down
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,10 @@ cypress/fixtures/

# IntelliJ
.idea/*

# Yarn 4
.yarn/cache
.yarn/install-state.gz
.yarn/unplugged
.yarn/build-state.yml
.pnp.*
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v16.14.0
v22.22.0
1 change: 1 addition & 0 deletions .yarnrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
nodeLinker: node-modules
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,22 @@ $ yarn install
Start the development server:

```
$ PORT=8081 REACT_APP_DHIS2_BASE_URL="http://localhost:8080" yarn start
$ PORT=8081 VITE_DHIS2_BASE_URL="http://localhost:8080" VITE_DHIS2_AUTH="" yarn start
```

Now in your browser, go to `http://localhost:8081`.

Notes:

- Requests to DHIS2 will be transparently proxied (see `src/setupProxy.js`) from `http://localhost:8081/dhis2/path` to `http://localhost:8080/path` to avoid CORS and cross-domain problems.
- Requests to DHIS2 will be transparently proxied from `http://localhost:8081/dhis2/path` to `http://localhost:8080/path` (see `vite.config.ts`) to avoid CORS and cross-domain problems.

- The optional environment variable `REACT_APP_DHIS2_AUTH=USERNAME:PASSWORD` forces some credentials to be used by the proxy. This variable is usually not set, so the app has the same user logged in at `REACT_APP_DHIS2_BASE_URL`.
- The optional environment variable `VITE_DHIS2_AUTH=USERNAME:PASSWORD` forces some credentials to be used by the proxy. This variable is usually not set, so the app has the same user logged in at `VITE_DHIS2_BASE_URL`.

- The optional environment variable `REACT_APP_PROXY_LOG_LEVEL` can be helpful to debug the proxyfied requests (accepts: "warn" | "debug" | "info" | "error" | "silent")
- The optional environment variable `VITE_PROXY_LOG_LEVEL` can be helpful to debug the proxied requests (accepts: "warn" | "debug" | "info" | "error" | "silent")

- Create a file `.env.local` (copy it from `.env`) to customize environment variables so you can simply run `yarn start`.

- [why-did-you-render](https://github.com/welldone-software/why-did-you-render) is installed, but it does not work when using standard react scripts (`yarn start`). Instead, use `yarn craco-start` to debug re-renders with WDYR. Note that hot reloading does not work out-of-the-box with [craco](https://github.com/gsoft-inc/craco).
- [why-did-you-render](https://github.com/welldone-software/why-did-you-render) is loaded in development to help debug re-renders.

## Tests

Expand Down
30 changes: 0 additions & 30 deletions craco.config.js

This file was deleted.

30 changes: 30 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8" />
<link rel="shortcut icon" href="/favicon.ico?v=1" />

<link
type="text/css"
rel="stylesheet"
href="/includes/material-design-icons/material-icons.css"
/>
<link type="text/css" rel="stylesheet" href="/includes/roboto-font.css" />
<link
href="//maxcdn.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.min.css"
rel="stylesheet"
/>

<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<meta name="theme-color" content="#000000" />
<title>Bulk Load | DHIS2</title>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<script type="module" src="/src/index.tsx"></script>
</body>
</html>

68 changes: 47 additions & 21 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,31 +9,32 @@
"type": "git",
"url": "git+https://github.com/eyeseetea/bulk-load.git"
},
"packageManager": "yarn@4.12.0",
"dependencies": {
"@dhis2/app-runtime": "3.2.7",
"@dhis2/app-runtime": "3.12.0",
"@dhis2/d2-i18n": "1.1.3",
"@dhis2/d2-ui-core": "7.3.3",
"@dhis2/ui-core": "6.24.0",
"@dhis2/ui-widgets": "6.24.0",
"@eyeseetea/d2-api": "1.20.0",
"@eyeseetea/d2-ui-components": "2.12.0",
"@eyeseetea/feedback-component": "0.1.3-beta.3",
"@eyeseetea/feedback-component": "0.3.0",
"@eyeseetea/xlsx-populate": "4.3.2-beta.1",
"@material-ui/core": "4.12.3",
"@material-ui/icons": "4.11.2",
"@material-ui/styles": "4.11.4",
"@material-ui/core": "4.12.4",
"@material-ui/icons": "4.11.3",
"@material-ui/styles": "4.11.5",
"async-promise-pool": "1.0.6",
"axios": "0.24.0",
"axios": "1.13.5",
"core-js": "3.20.3",
"d2": "31.10.2",
"date-fns": "2.28.0",
"file-saver": "2.0.5",
"jquery": "3.6.0",
"jszip": "3.10.1",
"lodash": "4.17.21",
"lodash": "4.17.23",
"lodash.product": "18.10.0",
"md5": "2.3.0",
"moment": "2.29.1",
"moment": "2.29.4",
"prop-types": "15.8.1",
"purify-ts": "1.1.0",
"purify-ts-extra-codec": "0.6.0",
Expand All @@ -43,31 +44,31 @@
"react-dropzone": "11.5.1",
"react-json-view": "1.21.3",
"react-markdown": "^8.0.7",
"react-router-dom": "6.2.1",
"react-scripts": "4.0.3",
"react-router-dom": "6.30.3",
"rehype-raw": "^6.1.1",
"rehype-sanitize": "^5.0.1",
"styled-jsx": "4.0.1"
"styled-jsx": "5.0.0"
},
"scripts": {
"start": "react-scripts start",
"craco-start": "craco start",
"start": "vite --strictPort",
"prebuild": "yarn localize && yarn test",
"build-folder": "rm -rf build/ && d2-manifest package.json manifest.webapp && react-scripts build && yarn run manifest && cp -r i18n icon.png build",
"build": "REACT_APP_DHIS2_BASE_URL='' REACT_APP_DHIS2_AUTH='' yarn build-folder && rm -f $npm_package_name.zip && cd build && zip --quiet -r ../$npm_package_name.zip *",
"test": "jest --passWithNoTests",
"build-folder": "rm -rf build/ && d2-manifest package.json manifest.webapp && tsc && vite build --outDir=build && yarn run manifest && cp -r i18n icon.png build",
"build": "VITE_DHIS2_BASE_URL='' VITE_DHIS2_AUTH='' yarn build-folder && rm -f $npm_package_name.zip && cd build && zip --quiet -r ../$npm_package_name.zip *",
"test": "yarn test-unit",
"test-unit": "vitest run --reporter=basic",
"test-unit-watch": "vitest watch",
"lint": "eslint src cypress --ext .js,.jsx,.ts,.tsx",
"eject": "react-scripts eject",
"prettify": "prettier \"./**/*.{js,jsx,json,css,ts,tsx}\" --write",
"extract-pot": "yarn d2-i18n-extract -p src/ -o i18n/",
"localize": "yarn update-po && d2-i18n-generate -n bulk-load -p ./i18n/ -o ./src/locales/",
"update-po": "yarn extract-pot && for pofile in i18n/*.po; do msgmerge --backup=off -U $pofile i18n/en.pot; done",
"update-po": "yarn extract-pot && find i18n/ -name '*.po' -exec msgmerge --backup=off -U {} i18n/en.pot \\;",
"manifest": "d2-manifest package.json build/manifest.webapp",
"cy:verify": "cypress verify",
"check-uncommited": "test -z \"$(git status -uno --porcelain)\"",
"cy:e2e:open": "NODE_ENV=test CYPRESS_E2E=true cypress open",
"cy:e2e:run": "NODE_ENV=test CYPRESS_E2E=true cypress run --browser chrome",
"prepare": "husky install"
"prepare": "corepack enable 2>/dev/null || true && husky install",
"postinstall": "yarn localize"
},
"devDependencies": {
"@babel/core": "7.16.7",
Expand All @@ -89,12 +90,12 @@
"@types/webpack-env": "1.16.3",
"@typescript-eslint/eslint-plugin": "5.9.1",
"@typescript-eslint/parser": "5.9.1",
"@vitejs/plugin-react": "^3.1.0",
"@welldone-software/why-did-you-render": "6.2.3",
"babel-core": "6.26.3",
"babel-eslint": "10.1.0",
"babel-preset-react-app": "10.0.1",
"cmd-ts": "^0.10.0",
"craco": "0.0.3",
"cypress": "9.2.1",
"cypress-xpath": "1.6.2",
"d2-manifest": "1.0.0",
Expand All @@ -112,13 +113,38 @@
"eslint-plugin-unused-imports": "2.0.0",
"http-proxy-middleware": "2.0.1",
"husky": "7.0.4",
"jest": "27.4.7",
"jsdom": "^21.1.2",
"node-stdlib-browser": "^1.2.0",
"postcss-rtl": "1.7.3",
"prettier": "2.5.1",
"ts-node": "10.4.0",
"typescript": "4.5.4",
"vite": "^4.2.0",
"vite-plugin-checker": "^0.6.2",
"vite-plugin-node-stdlib-browser": "^0.2.1",
"vitest": "^0.32.2",
"wait-on": "6.0.0"
},
"resolutions": {
"axios": "1.13.5",
"@babel/runtime": "7.26.10",
"i18next": "19.8.5",
"brace-expansion": "1.1.12",
"form-data": "4.0.4",
"glob-parent": "5.1.2",
"lodash": "4.17.23",
"lodash-es": "4.17.23",
"moment": "2.29.4",
"minimatch": "3.1.3",
"nanoid": "3.3.8",
"node-fetch": "2.6.7",
"path-to-regexp": "1.9.0",
"qs": "6.14.2",
"diff": "5.2.2",
"debug": "4.3.4",
"ua-parser-js": "0.7.24",
"jszip": "3.7.0"
},
"manifest.webapp": {
"name": "Bulk Load",
"description": "DHIS2 Bulk Load App",
Expand Down
47 changes: 0 additions & 47 deletions public/index.html

This file was deleted.

4 changes: 2 additions & 2 deletions src/CompositionRoot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ import { HistoryCleanupUseCase } from "./domain/usecases/HistoryCleanupUseCase";
import { GetHistoryEntriesUseCase } from "./domain/usecases/GetHistoryEntriesUseCase";
import { GetHistoryEntryDetailsUseCase } from "./domain/usecases/GetHistoryEntryDetailsUseCase";
import { DownloadDocumentUseCase } from "./domain/usecases/DownloadDocumentUseCase";
import { D2Api, D2ApiDefault } from "./types/d2-api";
import { D2Api } from "./types/d2-api";
import { GetFilteredThemesUseCase } from "./domain/usecases/GetFilteredThemesUseCase";
import { NRCModuleMetadataD2Repository } from "./data/templates/nrc/NRCModuleMetadataD2Repository";
import { FileD2Repository } from "./data/FileD2Repository";
Expand All @@ -65,7 +65,7 @@ export interface CompositionRootOptions {
}

export function getCompositionRoot({ appConfig, dhisInstance, mockApi, importSource = "zip" }: CompositionRootOptions) {
const api = mockApi ?? new D2ApiDefault({ baseUrl: dhisInstance.url });
const api = mockApi ?? new D2Api({ baseUrl: dhisInstance.url });
const instance: InstanceRepository = new InstanceDhisRepository(dhisInstance, mockApi);
const config: ConfigRepository = new ConfigWebRepository(appConfig);
const storage: StorageRepository =
Expand Down
4 changes: 2 additions & 2 deletions src/data/D2UsersRepository.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { DhisInstance } from "../domain/entities/DhisInstance";
import { User } from "../domain/entities/User";
import { SearchResults, UsersRepository } from "../domain/repositories/UsersRepository";
import { D2ApiDefault, D2OrganisationUnit, D2Api } from "../types/d2-api";
import { D2OrganisationUnit, D2Api } from "../types/d2-api";

export class D2UsersRepository implements UsersRepository {
private api: D2Api;

constructor(localInstance: DhisInstance, mockApi?: D2Api) {
this.api = mockApi ?? new D2ApiDefault({ baseUrl: localInstance.url });
this.api = mockApi ?? new D2Api({ baseUrl: localInstance.url });
}

async getCurrentUser(): Promise<User> {
Expand Down
4 changes: 2 additions & 2 deletions src/data/DocumentD2Repository.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { D2Api } from "../types/d2-api";
import { DhisInstance } from "../domain/entities/DhisInstance";
import { D2ApiDefault, DataStore } from "../types/d2-api";
import { DataStore } from "../types/d2-api";
import { dataStoreNamespace } from "./StorageDataStoreRepository";
import { Id } from "../domain/entities/ReferenceObject";
import { DocumentDeleteOptions, DocumentRepository } from "../domain/repositories/DocumentRepository";
Expand All @@ -13,7 +13,7 @@ export class DocumentD2Repository implements DocumentRepository {
private readonly dataStoreKey = "documents";

constructor(localInstance: DhisInstance) {
this.api = new D2ApiDefault({ baseUrl: localInstance.url });
this.api = new D2Api({ baseUrl: localInstance.url });
this.dataStore = this.api.dataStore(dataStoreNamespace);
}

Expand Down
4 changes: 2 additions & 2 deletions src/data/FileD2Repository.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { DhisInstance } from "../domain/entities/DhisInstance";
import { FileResource } from "../domain/entities/FileResource";
import { FileRepository } from "../domain/repositories/FileRepository";
import { D2Api, D2ApiDefault } from "../types/d2-api";
import { D2Api } from "../types/d2-api";
import { promiseMap } from "../utils/promises";
import { Maybe } from "../types/utils";

Expand All @@ -18,7 +18,7 @@ export class FileD2Repository implements FileRepository {
private api: D2Api;

constructor(localInstance: DhisInstance) {
this.api = new D2ApiDefault({ baseUrl: localInstance.url });
this.api = new D2Api({ baseUrl: localInstance.url });
}

async uploadAll(files: FileResource[]): Promise<FileResource[]> {
Expand Down
4 changes: 2 additions & 2 deletions src/data/HistoryDataStoreRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { HistoryRepository } from "../domain/repositories/HistoryRepository";
import { HistoryEntry, HistoryEntrySummary, HistoryEntryDetails } from "../domain/entities/HistoryEntry";
import { Id } from "../domain/entities/ReferenceObject";
import { DhisInstance } from "../domain/entities/DhisInstance";
import { D2Api, D2ApiDefault, DataStore } from "../types/d2-api";
import { D2Api, DataStore } from "../types/d2-api";
import { dataStoreNamespace } from "./StorageDataStoreRepository";

export class HistoryDataStoreRepository implements HistoryRepository {
Expand All @@ -11,7 +11,7 @@ export class HistoryDataStoreRepository implements HistoryRepository {
private readonly HISTORY_KEY = "history";

constructor({ url }: DhisInstance, mockApi?: D2Api) {
this.api = mockApi ?? new D2ApiDefault({ baseUrl: url });
this.api = mockApi ?? new D2Api({ baseUrl: url });
this.dataStore = this.api.dataStore(dataStoreNamespace);
}

Expand Down
Loading
Loading