diff --git a/src/config/frontend.config.json b/src/config/frontend.config.json index 5dc093125..437e0a8cd 100644 --- a/src/config/frontend.config.json +++ b/src/config/frontend.config.json @@ -27,86 +27,6 @@ "jupyterHubUrl": "", "landingPage": "doi.ess.eu/detail/", "lbBaseURL": "http://127.0.0.1:3000", - "localColumns": [ - { - "name": "select", - "order": 0, - "type": "standard", - "enabled": true - }, - { - "name": "pid", - "order": 1, - "type": "standard", - "enabled": true - }, - { - "name": "datasetName", - "order": 2, - "type": "standard", - "enabled": true - }, - { - "name": "runNumber", - "order": 3, - "type": "standard", - "enabled": true - }, - { - "name": "sourceFolder", - "order": 4, - "type": "standard", - "enabled": true - }, - { - "name": "size", - "order": 5, - "type": "standard", - "enabled": true - }, - { - "name": "creationTime", - "order": 6, - "type": "standard", - "enabled": true - }, - { - "name": "type", - "order": 7, - "type": "standard", - "enabled": true - }, - { - "name": "image", - "order": 8, - "type": "standard", - "enabled": true - }, - { - "name": "metadata", - "order": 9, - "type": "standard", - "enabled": false - }, - { - "name": "proposalId", - "order": 10, - "type": "standard", - "enabled": true - }, - { - "name": "ownerGroup", - "order": 11, - "type": "standard", - "enabled": false - }, - { - "name": "dataStatus", - "order": 12, - "type": "standard", - "enabled": false - } - ], "logbookEnabled": true, "loginFormEnabled": true, "maxDirectDownloadSize": 5000000000, @@ -181,18 +101,106 @@ "authorization": ["#datasetAccess", "#datasetPublic"] } ], - "defaultSearchInterfaceSettings": { - "columns": [], + "labelMaps": { + "filters": { + "LocationFilter": "asdasd", + "PidFilter": "asdasdsad identifiler", + "GroupFilter": "fff", + "TypeFilter": "Typfggge", + "KeywordFilter": "ggg", + "DateRangeFilter": "Start Date - End Date", + "TextFilter": "Text" + } + }, + "defaultDatasetsListSettings": { + "columns": [ + { + "name": "select", + "order": 0, + "type": "standard", + "enabled": true + }, + { + "name": "pid", + "order": 1, + "type": "standard", + "enabled": true + }, + { + "name": "datasetName", + "order": 2, + "type": "standard", + "enabled": true + }, + { + "name": "runNumber", + "order": 3, + "type": "standard", + "enabled": true + }, + { + "name": "sourceFolder", + "order": 4, + "type": "standard", + "enabled": true + }, + { + "name": "size", + "order": 5, + "type": "standard", + "enabled": true + }, + { + "name": "creationTime", + "order": 6, + "type": "standard", + "enabled": true + }, + { + "name": "type", + "order": 7, + "type": "standard", + "enabled": true + }, + { + "name": "image", + "order": 8, + "type": "standard", + "enabled": true + }, + { + "name": "metadata", + "order": 9, + "type": "standard", + "enabled": false + }, + { + "name": "proposalId", + "order": 10, + "type": "standard", + "enabled": true + }, + { + "name": "ownerGroup", + "order": 11, + "type": "standard", + "enabled": false + }, + { + "name": "dataStatus", + "order": 12, + "type": "standard", + "enabled": false + } + ], "filters": [ - { "type": "LocationFilterComponent", "visible": true }, - { "type": "PidFilterComponent", "visible": true }, - { "type": "PidFilterContainsComponent", "visible": false }, - { "type": "PidFilterStartsWithComponent", "visible": false }, - { "type": "GroupFilterComponent", "visible": true }, - { "type": "TypeFilterComponent", "visible": true }, - { "type": "KeywordFilterComponent", "visible": true }, - { "type": "DateRangeFilterComponent", "visible": true }, - { "type": "TextFilterComponent", "visible": true } + { "LocationFilter": true }, + { "PidFilter": true }, + { "GroupFilter": true }, + { "TypeFilter": true }, + { "KeywordFilter": true }, + { "DateRangeFilter": true }, + { "TextFilter": true } ], "conditions": [] } diff --git a/src/users/schemas/user-settings.schema.ts b/src/users/schemas/user-settings.schema.ts index 59f4aea5a..ad9d9b564 100644 --- a/src/users/schemas/user-settings.schema.ts +++ b/src/users/schemas/user-settings.schema.ts @@ -5,24 +5,24 @@ import { Document } from "mongoose"; export type UserSettingsDocument = UserSettings & Document; -// Define possible filter component types as a union of string literals -export type FilterComponentType = - | "LocationFilterComponent" - | "PidFilterComponent" - | "PidFilterContainsComponent" - | "PidFilterStartsWithComponent" - | "GroupFilterComponent" - | "TypeFilterComponent" - | "KeywordFilterComponent" - | "DateRangeFilterComponent" - | "TextFilterComponent"; - -// Define the Filter interface -export interface FilterConfig { - type: FilterComponentType; - visible: boolean; +// NOTE: PidFilterContains and PidFilterStartsWith filters are not implemented +export enum FilterComponentType { + LocationFilter = "LocationFilter", + PidFilter = "PidFilter", + PidFilterContains = "PidFilterContains", + PidFilterStartsWith = "PidFilterStartsWith", + GroupFilter = "GroupFilter", + TypeFilter = "TypeFilter", + KeywordFilter = "KeywordFilter", + DateRangeFilter = "DateRangeFilter", + TextFilter = "TextFilter", } +// NOTE: The key is one of FilterComponentType, and the value is a string +export type FilterConfig = Partial<{ + [K in FilterComponentType]: boolean; +}>; + // Define the Condition interface export interface ScientificCondition { field: string; diff --git a/src/users/users.controller.ts b/src/users/users.controller.ts index d894ef955..687ae6544 100644 --- a/src/users/users.controller.ts +++ b/src/users/users.controller.ts @@ -42,7 +42,6 @@ import { CreateCustomJwt } from "./dto/create-custom-jwt.dto"; import { AuthenticatedPoliciesGuard } from "../casl/guards/auth-check.guard"; import { ReturnedUserDto } from "./dto/returned-user.dto"; import { ReturnedAuthLoginDto } from "src/auth/dto/returnedLogin.dto"; -import { PoliciesGuard } from "src/casl/guards/policies.guard"; @ApiBearerAuth() @ApiTags("users") diff --git a/src/users/users.service.ts b/src/users/users.service.ts index 7369730d7..09c5fab21 100644 --- a/src/users/users.service.ts +++ b/src/users/users.service.ts @@ -18,6 +18,7 @@ import { JwtService, JwtSignOptions } from "@nestjs/jwt"; import { JWTUser } from "../auth/interfaces/jwt-user.interface"; import * as fs from "fs"; import { + FilterComponentType, UserSettings, UserSettingsDocument, } from "./schemas/user-settings.schema"; @@ -273,16 +274,39 @@ export class UsersService implements OnModuleInit { } async findByIdUserSettings(userId: string): Promise { - return this.userSettingsModel.findOne({ userId }).exec(); + const result = await this.userSettingsModel.findOne({ userId }).exec(); + + if (!result) { + return null; + } + + // NOTE: The extra functions ensure filters in user setting record match the FilterComponentType format. + // If not, reset the user settings to maintain consistency. + const validFilters = result.filters.some((filter) => { + const [key, value] = Object.entries(filter)[0]; + return this.isValidFilterComponentType(key, value); + }); + + if (!validFilters) { + return this.findOneAndUpdateUserSettings(userId, { filters: [] }); + } + + return result; } async findOneAndUpdateUserSettings( userId: string, updateUserSettingsDto: UpdateUserSettingsDto | PartialUpdateUserSettingsDto, ): Promise { - return this.userSettingsModel - .findOneAndUpdate({ userId }, updateUserSettingsDto, { new: true }) + const result = await this.userSettingsModel + .findOneAndUpdate({ userId }, updateUserSettingsDto, { + new: true, + upsert: true, + setDefaultsOnInsert: true, + }) .exec(); + + return result; } async findOneAndDeleteUserSettings(userId: string): Promise { @@ -339,4 +363,14 @@ export class UsersService implements OnModuleInit { const jwtString = this.jwtService.sign(user, signAndVerifyOptions); return { jwt: jwtString }; } + + private isValidFilterComponentType( + key: string, + value: unknown, + ): key is FilterComponentType { + return ( + Object.keys(FilterComponentType).includes(key) && + typeof value === "boolean" + ); + } }