diff --git a/nuxeo-admin-console-web/angular-app/src/app/app-routing.module.ts b/nuxeo-admin-console-web/angular-app/src/app/app-routing.module.ts index ddd91ae5..c0e6e4c3 100644 --- a/nuxeo-admin-console-web/angular-app/src/app/app-routing.module.ts +++ b/nuxeo-admin-console-web/angular-app/src/app/app-routing.module.ts @@ -54,6 +54,13 @@ export const appRoutes: Route[] = [ "./features/sub-features/generic-multi-feature-layout/generic-multi-feature-layout.module" ).then((m) => m.GenericMultiFeatureLayoutModule), }, + { + path: "fulltext-reindex", + loadChildren: () => + import( + "./features/sub-features/generic-multi-feature-layout/generic-multi-feature-layout.module" + ).then((m) => m.GenericMultiFeatureLayoutModule), + }, { path: "**", redirectTo: "" }, ]; diff --git a/nuxeo-admin-console-web/angular-app/src/app/features/fulltext-reindex/fulltext-reindex.constants.ts b/nuxeo-admin-console-web/angular-app/src/app/features/fulltext-reindex/fulltext-reindex.constants.ts new file mode 100644 index 00000000..d7098a4d --- /dev/null +++ b/nuxeo-admin-console-web/angular-app/src/app/features/fulltext-reindex/fulltext-reindex.constants.ts @@ -0,0 +1,19 @@ +export const FULLTEXT_REINDEX_LABELS = { + FOLDER_REINDEX_TITLE: "Reindex the fulltext of a document and all of its children", + DOCUMENT_REINDEX_TITLE: "Reindex the fulltext of a single document", + NXQL_QUERY_REINDEX_TITLE: "Reindex the fulltext of the documents returned by a NXQL query", + REINDEX_BUTTON_LABEL: "Reindex", + DOCUMENT_QUERY: + "ecm:path='{query}' AND ecm:mixinType = 'Downloadable' AND ecm:isProxy = 0 AND ecm:mixinType != 'HiddenInNavigation' AND ecm:isVersion = 0 AND ecm:isTrashed = 0", + FOLDER_QUERY: + "(ecm:uuid='{query}' OR ecm:ancestorId='{query}') AND ecm:mixinType = 'Downloadable' AND ecm:isProxy = 0 AND ecm:mixinType != 'HiddenInNavigation' AND ecm:isVersion = 0 AND ecm:isTrashed = 0", + NXQL_QUERY: + "(ecm:uuid='{query}' OR ecm:ancestorId='{query}') AND ecm:mixinType = 'Downloadable' AND ecm:isProxy = 0 AND ecm:mixinType != 'HiddenInNavigation' AND ecm:isVersion = 0 AND ecm:isTrashed = 0", + NXQL_QUERY_DEFAULT_VALUE: + "SELECT * FROM Document WHERE ecm:mixinType != 'HiddenInNavigation' AND ecm:isProxy = 0 AND ecm:isVersion = 0 AND ecm:isTrashed = 0 AND ecm:mixinType = 'Downloadable' AND dc:title = 'A document to reindex'", + FORCE: "force", + FORCE_TITLE: "Empty fulltext index of binaries for excluded documents", + TRUE: "True", + FALSE: "False", + FORCE_HELPER_TEXT: "Use this option if you changed your fulltext configuration to exclude additional documents. This will remove the content of the files they hold from the fulltext index." +} diff --git a/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/document-tab/document-tab.component.html b/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/document-tab/document-tab.component.html index 4b9f1e60..feb4527b 100644 --- a/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/document-tab/document-tab.component.html +++ b/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/document-tab/document-tab.component.html @@ -1,33 +1,50 @@
-

{{ GENERIC_LABELS.REQUIRED_FIELD_INDICATOR }}

+ [ngClass]="{'vertical-flex': isFeatureVideoRenditions() || isFeatureFullTextReindex()}"> +

{{ GENERIC_LABELS.REQUIRED_FIELD_INDICATOR }}

{{ GENERIC_LABELS.DOCUMENT_ID_OR_PATH }}*

- {{getErrorMessage()}} + {{ getErrorMessage() }} + + -

{{VIDEO_RENDITIONS_LABELS.CONVERSION_NAMES}}

+

{{ VIDEO_RENDITIONS_LABELS.CONVERSION_NAMES }}

-

{{VIDEO_RENDITIONS_LABELS.CONVERSION_NAMES_HELPER_TEXT}}

-

{{VIDEO_RENDITIONS_LABELS.RECOMPUTE_VIDEO_INFO}}

+

{{ VIDEO_RENDITIONS_LABELS.CONVERSION_NAMES_HELPER_TEXT }}

+

{{ VIDEO_RENDITIONS_LABELS.RECOMPUTE_VIDEO_INFO }}

- {{VIDEO_RENDITIONS_LABELS.RECOMPUTE_MISSING_ONLY}} - {{VIDEO_RENDITIONS_LABELS.RECOMPUTE_ALL}} + {{ VIDEO_RENDITIONS_LABELS.RECOMPUTE_MISSING_ONLY }} + {{ VIDEO_RENDITIONS_LABELS.RECOMPUTE_ALL }}
+ +
+ + + {{ FULLTEXT_REINDEX_LABELS.FORCE_TITLE }} +
+

{{ FULLTEXT_REINDEX_LABELS.FORCE_HELPER_TEXT }}

+
\ No newline at end of file diff --git a/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/document-tab/document-tab.component.scss b/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/document-tab/document-tab.component.scss index c1ec92d0..8521aa43 100644 --- a/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/document-tab/document-tab.component.scss +++ b/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/document-tab/document-tab.component.scss @@ -40,9 +40,30 @@ left: 0; bottom: 0; } + &.fulltext-reindex { + left: 0; + bottom: 0; + } } .conversion-helper-text { font-size: 14px; margin-top: -15px; + color: #666666; + } + .force-checkbox-container { + display: flex; + align-items: center; + margin: 0 0 10px; + } + + .force-conversion-helper-text { + max-width: 600px; + white-space: normal; + word-wrap: break-word; + font-size: 13px; + margin-top: -15px; + color: #666666; } + + } diff --git a/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/document-tab/document-tab.component.spec.ts b/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/document-tab/document-tab.component.spec.ts index c5007086..775b718e 100644 --- a/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/document-tab/document-tab.component.spec.ts +++ b/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/document-tab/document-tab.component.spec.ts @@ -30,6 +30,7 @@ import { ErrorModalComponent } from "../error-modal/error-modal.component"; import { featureMap, FEATURES } from "../../generic-multi-feature-layout.mapping"; import { PICTURE_RENDITIONS_LABELS } from "../../../../pictures/pictures-renditions.constants"; import { THUMBNAIL_GENERATION_LABELS } from "../../../../thumbnail-generation/thumbnail-generation.constants"; +import { FULLTEXT_REINDEX_LABELS } from "../../../../fulltext-reindex/fulltext-reindex.constants"; describe("DocumentTabComponent", () => { let component: DocumentTabComponent; @@ -303,8 +304,14 @@ describe("DocumentTabComponent", () => { const result = featureMap()[FEATURES.THUMBNAIL_GENERATION](GENERIC_LABELS.DOCUMENT); expect(result.labels.pageTitle).toBe(THUMBNAIL_GENERATION_LABELS.DOCUMENT_THUMBNAIL_GENERATION_TITLE); expect(result.labels.submitBtnLabel).toBe(THUMBNAIL_GENERATION_LABELS.THUMBNAIL_GENERATION_BUTTON_LABEL); - expect(result.data.bodyParam.query).toBe(THUMBNAIL_GENERATION_LABELS.DOCUMENT_QUERY); }); }); + describe('FEATURES.FULLTEXT_REINDEX', () => { + it('should return correct labels and data for DOCUMENT tabType', () => { + const result = featureMap()[FEATURES.FULLTEXT_REINDEX](GENERIC_LABELS.DOCUMENT); + expect(result.labels.pageTitle).toBe(FULLTEXT_REINDEX_LABELS.DOCUMENT_REINDEX_TITLE); + expect(result.labels.submitBtnLabel).toBe(FULLTEXT_REINDEX_LABELS.REINDEX_BUTTON_LABEL); + }); + }); }); \ No newline at end of file diff --git a/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/document-tab/document-tab.component.ts b/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/document-tab/document-tab.component.ts index 2b8fdc1e..3faca0b5 100644 --- a/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/document-tab/document-tab.component.ts +++ b/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/document-tab/document-tab.component.ts @@ -1,4 +1,5 @@ import { VIDEO_RENDITIONS_LABELS } from "./../../../../video-renditions-generation/video-renditions-generation.constants"; +import { FULLTEXT_REINDEX_LABELS } from "src/app/features/fulltext-reindex/fulltext-reindex.constants"; import { REST_END_POINTS } from "./../../../../../shared/constants/rest-end-ponts.constants"; import { GenericMultiFeatureUtilitiesService } from "./../../services/generic-multi-feature-utilities.service"; import { NuxeoJSClientService } from "./../../../../../shared/services/nuxeo-js-client.service"; @@ -73,6 +74,7 @@ export class DocumentTabComponent implements OnInit, OnDestroy { activeFeature: FeaturesKey = {} as FeaturesKey; requestQuery = ""; VIDEO_RENDITIONS_LABELS = VIDEO_RENDITIONS_LABELS; + FULLTEXT_REINDEX_LABELS = FULLTEXT_REINDEX_LABELS; FEATURES = FEATURES; constructor( public dialogService: MatDialog, @@ -83,6 +85,7 @@ export class DocumentTabComponent implements OnInit, OnDestroy { ) { this.inputForm = this.fb.group({ inputIdentifier: ["", Validators.required], + force: [false], }); this.nuxeo = this.nuxeoJSClientService.getNuxeoInstance(); this.documentActionLaunched$ = this.store.pipe( @@ -117,6 +120,12 @@ export class DocumentTabComponent implements OnInit, OnDestroy { new FormControl("true") ); } + if (this.isFeatureFullTextReindex()) { + this.inputForm.addControl( + FULLTEXT_REINDEX_LABELS.FORCE, + new FormControl("false") + ); + } } this.documentActionLaunchedSubscription = @@ -209,6 +218,10 @@ export class DocumentTabComponent implements OnInit, OnDestroy { if (this.isFeatureVideoRenditions()) { this.inputForm?.get("conversionNames")?.reset(); } + if (this.isFeatureFullTextReindex()) { + this.inputForm?.get("force")?.reset(); + } + document.getElementById("inputIdentifier")?.focus(); } @@ -319,6 +332,13 @@ export class DocumentTabComponent implements OnInit, OnDestroy { ); } + isFeatureFullTextReindex(): boolean { + return ( + this.activeFeature === + (FEATURES.FULLTEXT_REINDEX as FeaturesKey) + ); + } + ngOnDestroy(): void { this.store.dispatch(FeatureActions.resetDocumentActionState()); this.documentActionLaunchedSubscription?.unsubscribe(); @@ -329,4 +349,4 @@ export class DocumentTabComponent implements OnInit, OnDestroy { this.launchedDialogOpenedSubscription?.unsubscribe(); this.errorDialogOpenedSubscription?.unsubscribe(); } -} +} \ No newline at end of file diff --git a/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/folder-tab/folder-tab.component.html b/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/folder-tab/folder-tab.component.html index a932150a..3404603c 100644 --- a/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/folder-tab/folder-tab.component.html +++ b/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/folder-tab/folder-tab.component.html @@ -1,5 +1,5 @@
+[ngClass]="{'vertical-flex': isFeatureVideoRenditions() || isFeatureFullTextReindex()}">

{{ GENERIC_LABELS.REQUIRED_FIELD_INDICATOR }}

{{ isIdAndPathRequired(activeFeature) ? GENERIC_LABELS.DOCUMENT_ID_OR_PATH : GENERIC_LABELS.DOCUMENT_ID }}*

@@ -29,9 +29,24 @@ + +
+ + + {{ FULLTEXT_REINDEX_LABELS.FORCE_TITLE }} +
+

{{ FULLTEXT_REINDEX_LABELS.FORCE_HELPER_TEXT }}

+
diff --git a/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/folder-tab/folder-tab.component.scss b/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/folder-tab/folder-tab.component.scss index 3164db4f..193a25a3 100644 --- a/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/folder-tab/folder-tab.component.scss +++ b/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/folder-tab/folder-tab.component.scss @@ -64,4 +64,24 @@ .conversion-helper-text { font-size: 14px; margin-top: -15px; + color: #666666; +} + +.conversion-helper-text { + font-size: 14px; + margin-top: -15px; +} +.force-checkbox-container { + display: flex; + align-items: center; + margin: 0 0 10px; +} + +.force-conversion-helper-text { + max-width: 600px; /* Adjust as needed */ + white-space: normal; + word-wrap: break-word; + font-size: 13px; + margin-top: -15px; + color: #666666; } \ No newline at end of file diff --git a/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/folder-tab/folder-tab.component.spec.ts b/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/folder-tab/folder-tab.component.spec.ts index c6c7c3fc..06d655e6 100644 --- a/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/folder-tab/folder-tab.component.spec.ts +++ b/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/folder-tab/folder-tab.component.spec.ts @@ -32,6 +32,7 @@ import { ErrorModalComponent } from "../error-modal/error-modal.component"; import { featureMap, FEATURES } from "../../generic-multi-feature-layout.mapping"; import { PICTURE_RENDITIONS_LABELS } from "../../../../pictures/pictures-renditions.constants"; import { THUMBNAIL_GENERATION_LABELS } from "../../../../thumbnail-generation/thumbnail-generation.constants"; +import { FULLTEXT_REINDEX_LABELS } from "../../../../fulltext-reindex/fulltext-reindex.constants"; describe("FolderTabComponent", () => { let component: FolderTabComponent; @@ -295,7 +296,14 @@ describe("FolderTabComponent", () => { const result = featureMap()[FEATURES.THUMBNAIL_GENERATION](GENERIC_LABELS.FOLDER); expect(result.labels.pageTitle).toBe(THUMBNAIL_GENERATION_LABELS.FOLDER_THUMBNAIL_GENERATION_TITLE); expect(result.labels.submitBtnLabel).toBe(THUMBNAIL_GENERATION_LABELS.THUMBNAIL_GENERATION_BUTTON_LABEL); - expect(result.data.bodyParam.query).toBe(THUMBNAIL_GENERATION_LABELS.FOLDER_QUERY); + }); + }); + + describe('FEATURES.FULLTEXT_REINDEX', () => { + it('should return correct labels and data for FOLDER tabType', () => { + const result = featureMap()[FEATURES.FULLTEXT_REINDEX](GENERIC_LABELS.FOLDER); + expect(result.labels.pageTitle).toBe(FULLTEXT_REINDEX_LABELS.FOLDER_REINDEX_TITLE); + expect(result.labels.submitBtnLabel).toBe(FULLTEXT_REINDEX_LABELS.REINDEX_BUTTON_LABEL); }); }); }); \ No newline at end of file diff --git a/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/folder-tab/folder-tab.component.ts b/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/folder-tab/folder-tab.component.ts index e56033b3..cb44206a 100644 --- a/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/folder-tab/folder-tab.component.ts +++ b/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/folder-tab/folder-tab.component.ts @@ -1,4 +1,5 @@ import { VIDEO_RENDITIONS_LABELS } from "./../../../../video-renditions-generation/video-renditions-generation.constants"; +import { FULLTEXT_REINDEX_LABELS } from "src/app/features/fulltext-reindex/fulltext-reindex.constants"; import { REST_END_POINTS } from "./../../../../../shared/constants/rest-end-ponts.constants"; import { MatDialog } from "@angular/material/dialog"; import { MatDialogRef } from "@angular/material/dialog"; @@ -76,6 +77,7 @@ export class FolderTabComponent implements OnInit, OnDestroy { > = {} as MatDialogRef; GENERIC_LABELS = GENERIC_LABELS; VIDEO_RENDITIONS_LABELS = VIDEO_RENDITIONS_LABELS; + FULLTEXT_REINDEX_LABELS = FULLTEXT_REINDEX_LABELS nuxeo: Nuxeo; isSubmitBtnDisabled = false; templateConfigData: FeatureData = {} as FeatureData; @@ -92,6 +94,7 @@ export class FolderTabComponent implements OnInit, OnDestroy { ) { this.inputForm = this.fb.group({ inputIdentifier: ["", Validators.required], + force: [false], }); this.nuxeo = this.nuxeoJSClientService.getNuxeoInstance(); this.folderActionLaunched$ = this.store.pipe( @@ -123,7 +126,12 @@ export class FolderTabComponent implements OnInit, OnDestroy { this.templateLabels.pageTitle ); } - + if(this.isFeatureFullTextReindex()) { + this.inputForm.addControl( + FULLTEXT_REINDEX_LABELS.FORCE, + new FormControl("false") + ); + } if (this.isFeatureVideoRenditions()) { this.inputForm.addControl( VIDEO_RENDITIONS_LABELS.CONVERSION_NAME_KEY, @@ -135,6 +143,8 @@ export class FolderTabComponent implements OnInit, OnDestroy { ); } + + this.folderActionLaunchedSubscription = this.folderActionLaunched$.subscribe((data) => { if (data?.commandId) { @@ -456,6 +466,13 @@ export class FolderTabComponent implements OnInit, OnDestroy { ); } + isFeatureFullTextReindex(): boolean { + return ( + this.activeFeature === + (FEATURES.FULLTEXT_REINDEX as FeaturesKey) + ); + } + ngOnDestroy(): void { this.store.dispatch(FeatureActions.resetFolderActionState()); this.folderActionLaunchedSubscription?.unsubscribe(); diff --git a/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/nxql-tab/nxql-tab.component.html b/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/nxql-tab/nxql-tab.component.html index 2ee40e49..46e08579 100644 --- a/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/nxql-tab/nxql-tab.component.html +++ b/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/nxql-tab/nxql-tab.component.html @@ -26,9 +26,24 @@ + +
+ + + {{ FULLTEXT_REINDEX_LABELS.FORCE_TITLE }} +
+

{{ FULLTEXT_REINDEX_LABELS.FORCE_HELPER_TEXT }}

+
diff --git a/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/nxql-tab/nxql-tab.component.scss b/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/nxql-tab/nxql-tab.component.scss index 7734931e..91211a4b 100644 --- a/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/nxql-tab/nxql-tab.component.scss +++ b/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/nxql-tab/nxql-tab.component.scss @@ -82,3 +82,24 @@ } } } + +.conversion-helper-text { + font-size: 14px; + margin-top: -15px; + color: #666666; +} + +.force-checkbox-container { + display: flex; + align-items: center; + margin: 0 0 10px; +} + +.force-conversion-helper-text { + max-width: 600px; /* Adjust as needed */ + white-space: normal; + word-wrap: break-word; + font-size: 13px; + margin-top: -15px; + color: #666666; +} diff --git a/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/nxql-tab/nxql-tab.component.spec.ts b/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/nxql-tab/nxql-tab.component.spec.ts index 5b8a172e..028b3c0d 100644 --- a/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/nxql-tab/nxql-tab.component.spec.ts +++ b/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/nxql-tab/nxql-tab.component.spec.ts @@ -32,6 +32,7 @@ import { featureMap, FEATURES } from "../../generic-multi-feature-layout.mapping import { PICTURE_RENDITIONS_LABELS } from "../../../../pictures/pictures-renditions.constants"; import { THUMBNAIL_GENERATION_LABELS } from "../../../../thumbnail-generation/thumbnail-generation.constants"; import { VIDEO_RENDITIONS_LABELS } from "../../../../video-renditions-generation/video-renditions-generation.constants"; +import { FULLTEXT_REINDEX_LABELS } from "../../../../fulltext-reindex/fulltext-reindex.constants"; describe("NXQLTabComponent", () => { @@ -347,7 +348,6 @@ describe("NXQLTabComponent", () => { const result = featureMap()[FEATURES.THUMBNAIL_GENERATION](GENERIC_LABELS.NXQL); expect(result.labels.pageTitle).toBe(THUMBNAIL_GENERATION_LABELS.NXQL_THUMBNAIL_GENERATION_TITLE); expect(result.labels.submitBtnLabel).toBe(THUMBNAIL_GENERATION_LABELS.THUMBNAIL_GENERATION_BUTTON_LABEL); - expect(result.data.bodyParam.query).toBe(THUMBNAIL_GENERATION_LABELS.NXQL_QUERY); }); }); @@ -368,4 +368,12 @@ describe("NXQLTabComponent", () => { expect(component.inputForm.contains(VIDEO_RENDITIONS_LABELS.CONVERSION_NAME_KEY)).toBe(false); expect(component.inputForm.contains(VIDEO_RENDITIONS_LABELS.RECOMPUTE_ALL_VIDEO_INFO_KEY)).toBe(false); }); + + describe('FEATURES.FULLTEXT_REINDEX', () => { + it('should return correct labels and data for NXQL tabType', () => { + const result = featureMap()[FEATURES.FULLTEXT_REINDEX](GENERIC_LABELS.NXQL); + expect(result.labels.pageTitle).toBe(FULLTEXT_REINDEX_LABELS.NXQL_QUERY_REINDEX_TITLE); + expect(result.labels.submitBtnLabel).toBe(FULLTEXT_REINDEX_LABELS.REINDEX_BUTTON_LABEL); + }); + }); }); diff --git a/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/nxql-tab/nxql-tab.component.ts b/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/nxql-tab/nxql-tab.component.ts index 54663552..e56ad99d 100644 --- a/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/nxql-tab/nxql-tab.component.ts +++ b/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/components/nxql-tab/nxql-tab.component.ts @@ -1,4 +1,5 @@ import { VIDEO_RENDITIONS_LABELS } from "./../../../../video-renditions-generation/video-renditions-generation.constants"; +import { FULLTEXT_REINDEX_LABELS } from "src/app/features/fulltext-reindex/fulltext-reindex.constants"; import { REST_END_POINTS } from "./../../../../../shared/constants/rest-end-ponts.constants"; import { MatDialog, MatDialogRef } from "@angular/material/dialog"; import { Component, OnDestroy, OnInit } from "@angular/core"; @@ -77,6 +78,7 @@ export class NXQLTabComponent implements OnInit, OnDestroy { > = {} as MatDialogRef; GENERIC_LABELS = GENERIC_LABELS; VIDEO_RENDITIONS_LABELS = VIDEO_RENDITIONS_LABELS; + FULLTEXT_REINDEX_LABELS = FULLTEXT_REINDEX_LABELS; nuxeo: Nuxeo; isSubmitBtnDisabled = false; templateConfigData: FeatureData = {} as FeatureData; @@ -97,6 +99,7 @@ export class NXQLTabComponent implements OnInit, OnDestroy { ) { this.inputForm = this.fb.group({ inputIdentifier: ["", Validators.required], + force: [false], }); this.nxqlActionLaunched$ = this.store.pipe( @@ -134,7 +137,6 @@ export class NXQLTabComponent implements OnInit, OnDestroy { this.spinnerVisible = status; } ); - if (this.isFeatureVideoRenditions()) { this.inputForm.addControl( VIDEO_RENDITIONS_LABELS.CONVERSION_NAME_KEY, @@ -145,6 +147,12 @@ export class NXQLTabComponent implements OnInit, OnDestroy { new FormControl("true") ); } + if(this.isFeatureFullTextReindex()) { + this.inputForm.addControl( + FULLTEXT_REINDEX_LABELS.FORCE, + new FormControl("false") + ); + } this.nxqlActionLaunchedSubscription = this.nxqlActionLaunched$.subscribe( (data) => { if (data?.commandId) { @@ -172,6 +180,13 @@ export class NXQLTabComponent implements OnInit, OnDestroy { ); } + isFeatureFullTextReindex(): boolean { + return ( + this.activeFeature === + (FEATURES.FULLTEXT_REINDEX as FeaturesKey) + ); + } + showActionErrorModal(error: ErrorDetails): void { this.genericMultiFeatureUtilitiesService.spinnerStatus.next(false); this.errorDialogRef = this.dialogService.open(ErrorModalComponent, { diff --git a/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/generic-multi-feature-layout.mapping.ts b/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/generic-multi-feature-layout.mapping.ts index 5832a9e8..d7468ccb 100644 --- a/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/generic-multi-feature-layout.mapping.ts +++ b/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/generic-multi-feature-layout.mapping.ts @@ -4,12 +4,14 @@ import { GENERIC_LABELS } from "./generic-multi-feature-layout.constants"; import { THUMBNAIL_GENERATION_LABELS } from "../../thumbnail-generation/thumbnail-generation.constants"; import { labelsList } from "./generic-multi-feature-layout.interface"; import { PICTURE_RENDITIONS_LABELS } from "../../pictures/pictures-renditions.constants"; +import { FULLTEXT_REINDEX_LABELS } from "../../fulltext-reindex/fulltext-reindex.constants"; export const FEATURES = { ELASTIC_SEARCH_REINDEX: "elasticsearch-reindex", THUMBNAIL_GENERATION: "thumbnail-generation", PICTURE_RENDITIONS: "picture-renditions", - VIDEO_RENDITIONS_GENERATION: "video-renditions-generation" + VIDEO_RENDITIONS_GENERATION: "video-renditions-generation", + FULLTEXT_REINDEX: "fulltext-reindex" } as const; export type FeaturesKey = keyof typeof FEATURES; @@ -76,11 +78,7 @@ export const featureMap = () => ({ }, [FEATURES.THUMBNAIL_GENERATION]: (tabType: string) => { let labels: labelsList; - let data = { - bodyParam: { - query: "" - } - }; + let data = {}; switch (tabType) { case GENERIC_LABELS.DOCUMENT: labels = { @@ -91,6 +89,9 @@ export const featureMap = () => ({ }; data = { bodyParam: { query: `${THUMBNAIL_GENERATION_LABELS.DOCUMENT_QUERY}` }, + requestHeaders: { + "Content-Type": "application/x-www-form-urlencoded", + }, }; break; @@ -103,6 +104,9 @@ export const featureMap = () => ({ bodyParam: { query: `${THUMBNAIL_GENERATION_LABELS.FOLDER_QUERY}`, }, + requestHeaders: { + "Content-Type": "application/x-www-form-urlencoded", + }, }; break; @@ -117,6 +121,9 @@ export const featureMap = () => ({ }; data = { bodyParam: { query: `${THUMBNAIL_GENERATION_LABELS.NXQL_QUERY}` }, + requestHeaders: { + "Content-Type": "application/x-www-form-urlencoded", + }, }; break; @@ -142,6 +149,9 @@ export const featureMap = () => ({ bodyParam: { query: `${PICTURE_RENDITIONS_LABELS.DOCUMENT_QUERY}`, }, + requestHeaders: { + "Content-Type": "application/x-www-form-urlencoded", + }, }; break; @@ -154,6 +164,9 @@ export const featureMap = () => ({ bodyParam: { query: `${PICTURE_RENDITIONS_LABELS.FOLDER_QUERY}`, }, + requestHeaders: { + "Content-Type": "application/x-www-form-urlencoded", + }, }; break; @@ -168,6 +181,9 @@ export const featureMap = () => ({ bodyParam: { query: `${PICTURE_RENDITIONS_LABELS.NXQL_QUERY}`, }, + requestHeaders: { + "Content-Type": "application/x-www-form-urlencoded", + }, }; break; @@ -245,4 +261,66 @@ export const featureMap = () => ({ data, }; }, + [FEATURES.FULLTEXT_REINDEX]: (tabType: string) => { + let labels: labelsList; + let data = {}; + switch (tabType) { + case GENERIC_LABELS.DOCUMENT: + labels = { + pageTitle: FULLTEXT_REINDEX_LABELS.DOCUMENT_REINDEX_TITLE, + submitBtnLabel: FULLTEXT_REINDEX_LABELS.REINDEX_BUTTON_LABEL, + }; + data = { + bodyParam: { + query: `${FULLTEXT_REINDEX_LABELS.DOCUMENT_QUERY}`, + [FULLTEXT_REINDEX_LABELS.FORCE]: `{force}`, + }, + requestHeaders: { + "Content-Type": "application/x-www-form-urlencoded", + }, + }; + break; + + case GENERIC_LABELS.FOLDER: + labels = { + pageTitle: FULLTEXT_REINDEX_LABELS.FOLDER_REINDEX_TITLE, + submitBtnLabel: FULLTEXT_REINDEX_LABELS.REINDEX_BUTTON_LABEL, + }; + data = { + bodyParam: { + query: `${FULLTEXT_REINDEX_LABELS.FOLDER_QUERY}`, + [FULLTEXT_REINDEX_LABELS.FORCE]: `{force}`, + }, + requestHeaders: { + "Content-Type": "application/x-www-form-urlencoded", + }, + }; + break; + + case GENERIC_LABELS.NXQL: + labels = { + pageTitle: FULLTEXT_REINDEX_LABELS.NXQL_QUERY_REINDEX_TITLE, + submitBtnLabel: FULLTEXT_REINDEX_LABELS.REINDEX_BUTTON_LABEL, + nxqlQueryPlaceholder: + FULLTEXT_REINDEX_LABELS.NXQL_QUERY_DEFAULT_VALUE, + }; + data = { + bodyParam: { + query: `${FULLTEXT_REINDEX_LABELS.NXQL_QUERY}`, + [FULLTEXT_REINDEX_LABELS.FORCE]: `{force}`, + }, + requestHeaders: { + "Content-Type": "application/x-www-form-urlencoded", + }, + }; + break; + + default: + throw new Error(`Unsupported type: ${tabType}`); + } + return { + labels, + data, + }; + }, }); diff --git a/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/generic-multi-feature-layout.module.ts b/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/generic-multi-feature-layout.module.ts index ac9bca0f..32f72784 100644 --- a/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/generic-multi-feature-layout.module.ts +++ b/nuxeo-admin-console-web/angular-app/src/app/features/sub-features/generic-multi-feature-layout/generic-multi-feature-layout.module.ts @@ -14,6 +14,7 @@ import { GenericMultiFeatureLayoutComponent } from "./generic-multi-feature-layo import { RouterModule } from "@angular/router"; import { ReactiveFormsModule } from "@angular/forms"; import { MatDialogModule } from "@angular/material/dialog"; +import { MatCheckboxModule } from '@angular/material/checkbox'; @NgModule({ declarations: [ @@ -33,7 +34,8 @@ import { MatDialogModule } from "@angular/material/dialog"; RouterModule, genericMultiFeatureLayoutRoutingModule, MatDialogModule, - MatSelectModule + MatSelectModule, + MatCheckboxModule ], exports: [GenericMultiFeatureLayoutComponent], }) diff --git a/nuxeo-admin-console-web/angular-app/src/app/layouts/menu-bar/menu-bar.constants.ts b/nuxeo-admin-console-web/angular-app/src/app/layouts/menu-bar/menu-bar.constants.ts index 94195865..7a25b3ae 100644 --- a/nuxeo-admin-console-web/angular-app/src/app/layouts/menu-bar/menu-bar.constants.ts +++ b/nuxeo-admin-console-web/angular-app/src/app/layouts/menu-bar/menu-bar.constants.ts @@ -39,6 +39,12 @@ export const ADMIN_MENU: Menu[] = [ }, { id: 6, + name: "Fulltext Reindex", + path: "fulltext-reindex", + isSelected: false, + }, + { + id: 7, name: "Bulk Action Monitoring", path: "bulk-action-monitoring", isSelected: false, diff --git a/nuxeo-admin-console-web/angular-app/src/app/shared/constants/rest-end-ponts.constants.ts b/nuxeo-admin-console-web/angular-app/src/app/shared/constants/rest-end-ponts.constants.ts index a389a692..31d10980 100644 --- a/nuxeo-admin-console-web/angular-app/src/app/shared/constants/rest-end-ponts.constants.ts +++ b/nuxeo-admin-console-web/angular-app/src/app/shared/constants/rest-end-ponts.constants.ts @@ -9,6 +9,7 @@ export const REST_END_POINTS = { THUMBNAIL_GENERATION: "THUMBNAIL_GENERATION", PICTURE_RENDITIONS: "PICTURE_RENDITIONS", VIDEO_RENDITIONS_GENERATION: "VIDEO_RENDITIONS_GENERATION", + FULLTEXT_REINDEX: "FULLTEXT_REINDEX", } as const; type RestEndpointKey = keyof typeof REST_END_POINTS; @@ -62,4 +63,8 @@ export const REST_END_POINT_CONFIG: Record< endpoint: "/management/videos/recompute", method: "POST", }, + FULLTEXT_REINDEX: { + endpoint: "/management/fulltext/extract", + method: "POST" + } };