Skip to content

Commit 45c9fec

Browse files
authored
feat: make frontend config and theme file locations configurable (#1830)
## Description Add backend configuration options to customize the file locations of `frontend.config.json` and `frontend.theme.json` via new environment variables `FRONTEND_CONFIG_FILE` and `FRONTEND_THEME_FILE`. The default location has been changed from /src/config to project root for consistency with other customizable configuration files (up for discussion). ## Motivation The backend will serve a configuration and theme to a connected frontend via the `/api/v3/admin/config` and `/api/v3/admin/theme` endpoints. The data sources for these endpoints are currently hardcoded to `/src/config/frontend.config.json` and `/src/config/frontend.config.json`. This is inconsistent with other configuration files which are located at the project root and can be configured in `.env`. This PR introduces environment variables `FRONTEND_CONFIG_FILE` and `FRONTEND_THEME_FILE` for customizing the location of the json files. The default location of both files has been moved to the project root directory. ## Changes: * added `FRONTEND_CONFIG_FILE` and `FRONTEND_THEME_FILE` environment variables * admin.service gets config and theme from ConfigService instead of static location * moved `frontend.config.json` and `frontend.theme.json` from `/src/config` to project root directory * null returns from admin controller/service now indicate missing frontend configuration or theme * admin.servoce.spec unit tests use mock objects instead of static json ## Tests included - [x] Included for each change/fix? - [x] Passing? <!-- Merge will not be approved unless tests pass --> ## Documentation - [x] swagger documentation updated (required for API changes) - [x] official documentation updated ### official documentation info <!-- If you have updated the official documentation, please provide PR # and URL of the updated pages -->
2 parents 29e8ce5 + bbf9fc8 commit 45c9fec

File tree

6 files changed

+132
-21
lines changed

6 files changed

+132
-21
lines changed

.env.example

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ ES_USERNAME="elastic"
8282
ES_PASSWORD="duo-password"
8383
ES_REFRESH=<"wait_for"|"false">
8484

85+
FRONTEND_CONFIG_FILE="./src/config/frontend.config.json"
86+
FRONTEND_THEME_FILE="./src/config/frontend.theme.json"
8587
LOGGERS_CONFIG_FILE="loggers.json"
8688
DATASET_TYPES_FILE="datasetTypes.json"
8789
PROPOSAL_TYPES_FILE="proposalTypes.json"

README.md

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -40,24 +40,26 @@ Thank you for your interest in contributing to our project!
4040
3. `npm install`
4141
4. Add _.env_ file to project root folder. See [Environment variables](#environment-variables).
4242
5. _Optional_ Add [functionalAccounts.json](#local-user-accounts) file to project root folder to create local users.
43-
6. _Optional_ Add [loggers.json](#loggers-configuration) file to the root folder and configure multiple loggers.
44-
7. _Optional_ Add [proposalTypes.json](#proposal-types-configuration) file to the root folder and configure the proposal types.
45-
8. _Optional_ Add [datasetTypes.json](#dataset-types-configuration) file to the root folder and configure the dataset types.
46-
9. `npm run start:dev`
47-
10. Go to http://localhost:3000/explorer to get an overview of available endpoints and database schemas.
48-
11. To be able to run the e2e tests with the same setup as in the Github actions you will need to run `npm run prepare:local` and after that run `npm run start:dev`. This will start all needed containers and copy some configuration to the right place.
43+
6. _Optional_ Edit or replace [frontend.config.json](#frontend-configuration-and-theme) and [frontend.theme.json](#frontend-configuration-and-theme) files in the `/src/config` directory to change frontend configuration served from the backend.
44+
7. _Optional_ Add [loggers.json](#loggers-configuration) file to the root folder and configure multiple loggers.
45+
8. _Optional_ Add [proposalTypes.json](#proposal-types-configuration) file to the root folder and configure the proposal types.
46+
9. _Optional_ Add [datasetTypes.json](#dataset-types-configuration) file to the root folder and configure the dataset types.
47+
10. `npm run start:dev`
48+
11. Go to http://localhost:3000/explorer to get an overview of available endpoints and database schemas.
49+
12. To be able to run the e2e tests with the same setup as in the Github actions you will need to run `npm run prepare:local` and after that run `npm run start:dev`. This will start all needed containers and copy some configuration to the right place.
4950

5051
## Develop in a container using the docker-compose.dev file
5152

5253
1. `git clone https://github.com/SciCatProject/scicat-backend-next.git`
5354
2. `docker-compose -f docker-compose.dev.yaml up -d`
5455
3. _Optional_ Mount [functionalAccounts.json](#local-user-accounts) file to a volume in the container to create local users.
55-
4. _Optional_ Mount [loggers.json](#loggers-configuration) file to a volume in the container to configure multiple loggers.
56-
5. _Optional_ Mount [proposalTypes.json](#proposal-types-configuration) file to a volume in the container to configure the proposal types.
57-
6. _Optional_ Mount [datasetTypes.json](#dataset-types-configuration) file to a volume in the container to configure the dataset types.
58-
7. _Optional_ Change the container env variables.
59-
8. Attach to the container.
60-
9. `npm run start:dev`
56+
4. _Optional_ Mount [frontend.config.json](#frontend-configuration-and-theme) and [frontend.theme.json](#frontend-configuration-and-theme) files to a volume in the container in the `/src/config` directory to change frontend configuration served from the backend.
57+
5. _Optional_ Mount [loggers.json](#loggers-configuration) file to a volume in the container to configure multiple loggers.
58+
6. _Optional_ Mount [proposalTypes.json](#proposal-types-configuration) file to a volume in the container to configure the proposal types.
59+
7. _Optional_ Mount [datasetTypes.json](#dataset-types-configuration) file to a volume in the container to configure the dataset types.
60+
8. _Optional_ Change the container env variables.
61+
9. Attach to the container.
62+
10. `npm run start:dev`
6163
10. Go to http://localhost:3000/explorer to get an overview of available endpoints and database schemas.
6264

6365
## Test the app
@@ -95,6 +97,12 @@ automatically create the specified accounts on startup. If this file is not prov
9597
Follow the structure of [functionalAccounts.json.minimal.example](/functionalAccounts.json.minimal.example) to create
9698
your own _functionalAccounts.json_ file.
9799

100+
## Frontend configuration and theme
101+
102+
The SciCat backend provides functionality to serve a configuration and theme to a connected frontend. The default files are _frontend.config.json_ and _frontend.theme.json_ located in the `/src/config` directory, locally or in the container. The file names and locations can be configured via the environment variables `FRONTEND_CONFIG_FILE` and `FRONTEND_THEME_FILE`.
103+
104+
Follow the structure of the provided [frontend.config.json](/frontend.config.json) and [frontend.theme.json](/frontend.theme.json) to create your own files.
105+
98106
### Loggers configuration
99107

100108
Providing a file called _loggers.json_ at the root of the project, locally or in the container, and create an external logger class in the `src/loggers/loggingProviders/`directory will automatically create specified one or multiple loggers instances.
@@ -199,6 +207,8 @@ Valid environment variables for the .env file. See [.env.example](/.env.example)
199207
| `ES_MAX_RESULT` | number | | Maximum records that can be indexed into Elasticsearch. | 10000 |
200208
| `ES_FIELDS_LIMIT` | number | | The total number of fields in an index. | 1000 |
201209
| `ES_REFRESH` | string | | If set to `wait_for`, Elasticsearch will wait till data is inserted into the specified index before returning a response. | false |
210+
| `FRONTEND_CONFIG_FILE` | string | | The file name for frontend configuration, located in the `/src/config` directory by default. | "./src/config/frontend.config.json" |
211+
| `FRONTEND_THEME_FILE` | string | | The file name for frontend theme, located in the `/src/config` directory by default. | "./src/config/frontend.theme.json" |
202212
| `LOGGERS_CONFIG_FILE` | string | | The file name for loggers configuration, located in the project root directory. | "loggers.json" |
203213
| `PROPOSAL_TYPES_FILE` | string | | The file name for proposal types configuration, located in the project root directory. | "proposalTypes.json" |
204214
| `SWAGGER_PATH` | string | Yes | swaggerPath is the path where the swagger UI will be available. | "explorer"|

docs/frontend-config-guide/dynamic-dataset-detail-component.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
## Overview
44

55
This guide provides details on configuring the **Dynamic Dataset Detail Component** on the frontend. This component can be customized to display dataset information in various templates and layouts based on your needs.
6-
The configuration needs to be provided or mounted in `/src/config/frontend.config.json`
6+
The configuration needs to be provided or mounted in the location specified by the environment variable `FRONTEND_CONFIG_FILE` (default `src/config/frontend.config.json`).
77

88
## Configuration guide
99

src/admin/admin.service.spec.ts

Lines changed: 93 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,104 @@
11
import { Test, TestingModule } from "@nestjs/testing";
22
import { ConfigService } from "@nestjs/config";
33
import { AdminService } from "./admin.service";
4-
import config from "../config/frontend.config.json";
5-
import theme from "../config/frontend.theme.json";
4+
5+
const mockConfig: Record<string, unknown> = {
6+
accessTokenPrefix: "Bearer ",
7+
addDatasetEnabled: false,
8+
archiveWorkflowEnabled: false,
9+
datasetReduceEnabled: true,
10+
datasetJsonScientificMetadata: true,
11+
editDatasetSampleEnabled: true,
12+
editMetadataEnabled: true,
13+
editPublishedData: false,
14+
addSampleEnabled: false,
15+
externalAuthEndpoint: "/api/v3/auth/msad",
16+
facility: "SciCat Vanilla",
17+
siteIcon: "site-header-logo.png",
18+
loginFacilityLabel: "SciCat Vanilla",
19+
loginLdapLabel: "Ldap",
20+
loginLocalLabel: "Local",
21+
loginFacilityEnabled: true,
22+
loginLdapEnabled: true,
23+
loginLocalEnabled: true,
24+
localLoginLabel: "Local",
25+
fileColorEnabled: true,
26+
fileDownloadEnabled: true,
27+
gettingStarted: null,
28+
ingestManual: null,
29+
jobsEnabled: true,
30+
jsonMetadataEnabled: true,
31+
jupyterHubUrl: "",
32+
landingPage: "doi.ess.eu/detail/",
33+
lbBaseURL: "http://localhost:3000",
34+
logbookEnabled: true,
35+
loginFormEnabled: true,
36+
metadataPreviewEnabled: true,
37+
metadataStructure: "",
38+
multipleDownloadAction: "http:/127.0.0.1:3012/zip",
39+
multipleDownloadEnabled: true,
40+
oAuth2Endpoints: [
41+
{
42+
authURL: "api/v3/auth/oidc",
43+
displayText: "ESS One Identity",
44+
},
45+
],
46+
policiesEnabled: true,
47+
retrieveDestinations: [],
48+
riotBaseUrl: "http://scichat.esss.lu.se",
49+
scienceSearchEnabled: true,
50+
scienceSearchUnitsEnabled: true,
51+
searchPublicDataEnabled: true,
52+
searchSamples: true,
53+
sftpHost: "login.esss.dk",
54+
sourceFolder: "/data/ess",
55+
maxDirectDownloadSize: 5000000000,
56+
maxFileSizeWarning:
57+
"Some files are above <maxDirectDownloadSize> and cannot be downloaded directly. These file can be downloaded via sftp host: <sftpHost> in directory: <sourceFolder>",
58+
shareEnabled: true,
59+
shoppingCartEnabled: true,
60+
shoppingCartOnHeader: true,
61+
tableSciDataEnabled: true,
62+
datasetDetailsShowMissingProposalId: false,
63+
notificationInterceptorEnabled: true,
64+
metadataEditingUnitListDisabled: true,
65+
datafilesActionsEnabled: true,
66+
datafilesActions: [],
67+
labelMaps: {
68+
filters: {},
69+
},
70+
defaultDatasetsListSettings: {
71+
columns: [],
72+
filters: [],
73+
conditions: [],
74+
},
75+
labelsLocalization: {
76+
datasetDefault: {},
77+
datasetCustom: {},
78+
proposalDefault: {},
79+
},
80+
dateFormat: "yyyy-MM-dd HH:mm",
81+
datasetDetailComponent: {
82+
enableCustomizedComponent: false,
83+
customization: [],
84+
},
85+
};
86+
87+
const mockTheme: Record<string, unknown> = {
88+
name: "light",
89+
properties: {
90+
"--theme-primary-default": "#27aae1",
91+
},
92+
};
693

794
describe("AdminService", () => {
895
let service: AdminService;
996
const mockConfigService = {
1097
get: jest.fn((propertyPath: string) => {
1198
const config = {
1299
maxFileUploadSizeInMb: "12mb",
100+
frontendConfig: mockConfig,
101+
frontendTheme: mockTheme,
13102
} as Record<string, unknown>;
14103

15104
return config[propertyPath];
@@ -39,7 +128,7 @@ describe("AdminService", () => {
39128
const result = await service.getConfig();
40129

41130
expect(result).toEqual({
42-
...config,
131+
...mockConfig,
43132
maxFileUploadSizeInMb: "12mb",
44133
});
45134
});
@@ -48,7 +137,7 @@ describe("AdminService", () => {
48137
describe("getTheme", () => {
49138
it("should return theme config", async () => {
50139
const result = await service.getTheme();
51-
expect(result).toEqual(theme);
140+
expect(result).toEqual(mockTheme);
52141
});
53142
});
54143
});

src/admin/admin.service.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
import { Injectable } from "@nestjs/common";
2-
import config from "../config/frontend.config.json";
3-
import theme from "../config/frontend.theme.json";
42
import { ConfigService } from "@nestjs/config";
53

64
@Injectable()
@@ -14,15 +12,21 @@ export class AdminService {
1412
}
1513

1614
async getTheme(): Promise<Record<string, unknown> | null> {
15+
const theme =
16+
this.configService.get<Record<string, unknown>>("frontendTheme") || null;
1717
return theme;
1818
}
1919

2020
// NOTE: Adjusts backend config values for frontend use (e.g., file upload limits).
2121
// Add future backend-dependent adjustments here as needed.
22-
private applyBackendConfigAdjustments(): Record<string, unknown> {
22+
private applyBackendConfigAdjustments(): Record<string, unknown> | null {
23+
const config =
24+
this.configService.get<Record<string, unknown>>("frontendConfig") || null;
25+
if (!config) {
26+
return null;
27+
}
2328
const postEncodedMaxFileUploadSize =
2429
this.configService.get<string>("maxFileUploadSizeInMb") || "16mb";
25-
2630
return {
2731
...config,
2832
maxFileUploadSizeInMb: postEncodedMaxFileUploadSize,

src/config/configuration.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ const configuration = () => {
5151
proposalTypes: {},
5252
};
5353
const jsonConfigFileList: { [key: string]: string } = {
54+
frontendConfig:
55+
process.env.FRONTEND_CONFIG_FILE || "./src/config/frontend.config.json",
56+
frontendTheme:
57+
process.env.FRONTEND_THEME_FILE || "./src/config/frontend.theme.json",
5458
loggers: process.env.LOGGERS_CONFIG_FILE || "loggers.json",
5559
datasetTypes: process.env.DATASET_TYPES_FILE || "datasetTypes.json",
5660
proposalTypes: process.env.PROPOSAL_TYPES_FILE || "proposalTypes.json",
@@ -301,6 +305,8 @@ const configuration = () => {
301305
},
302306
datasetTypes: jsonConfigMap.datasetTypes,
303307
proposalTypes: jsonConfigMap.proposalTypes,
308+
frontendConfig: jsonConfigMap.frontendConfig,
309+
frontendTheme: jsonConfigMap.frontendTheme,
304310
};
305311
return merge(config, localconfiguration);
306312
};

0 commit comments

Comments
 (0)