diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index 4ba43f17..761a4e1f 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -245,6 +245,7 @@ import { NewTrackDialogComponent } from './components/new-track-dialog/new-track
import { ReleaseTrackPageComponent } from './views/dashboard-page/release-management/release-track-page/release-track-page.component';
import { StatusChipComponent } from './components/status-chip/status-chip.component';
import { WorkbenchChipComponent } from './components/workbench-chip/workbench-chip.component';
+import { BulkPromoteDialogComponent } from './components/bulk-update-dialog/bulk-update-dialog.component';
export function initConfig(appConfigService: AppConfigService) {
return () => appConfigService.loadAppConfig();
@@ -267,6 +268,7 @@ export function initConfig(appConfigService: AppConfigService) {
SaveDialogComponent,
WorkflowStatusDialogComponent,
AddDialogComponent,
+ BulkPromoteDialogComponent,
DeleteDialogComponent,
HistoryTimelineComponent,
MembershipSectionComponent,
diff --git a/src/app/components/bulk-update-dialog/bulk-update-dialog.component.html b/src/app/components/bulk-update-dialog/bulk-update-dialog.component.html
new file mode 100644
index 00000000..2cab0cfb
--- /dev/null
+++ b/src/app/components/bulk-update-dialog/bulk-update-dialog.component.html
@@ -0,0 +1,76 @@
+
+
{{ config.title }}
+
+
+
+ No available objects.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/app/components/bulk-update-dialog/bulk-update-dialog.component.scss b/src/app/components/bulk-update-dialog/bulk-update-dialog.component.scss
new file mode 100644
index 00000000..31713d01
--- /dev/null
+++ b/src/app/components/bulk-update-dialog/bulk-update-dialog.component.scss
@@ -0,0 +1,38 @@
+@use '../../../style/globals';
+@use '../../../style/colors';
+
+.add-dialog {
+ .mat-mdc-list-item:hover h3 {
+ color: colors.color(primary);
+ }
+ .mat-mdc-list-item h3 {
+ @extend .subheading;
+ font-weight: 700 !important;
+ }
+ .mat-mdc-list-item + .mat-list-item {
+ .dark & {
+ border-top: 1px solid colors.border-color(dark);
+ }
+ .light & {
+ border-top: 1px solid colors.border-color(light);
+ }
+ }
+
+ min-width: 40vw;
+ max-width: 80vw;
+ max-height: 75vh;
+ padding: 24px;
+
+ .left-button {
+ margin-right: 12px;
+ }
+
+ .right-button {
+ margin-left: 12px;
+ }
+
+ .mat-mdc-checkbox {
+ margin-bottom: 16px;
+ display: block;
+ }
+}
diff --git a/src/app/components/bulk-update-dialog/bulk-update-dialog.component.ts b/src/app/components/bulk-update-dialog/bulk-update-dialog.component.ts
new file mode 100644
index 00000000..a80a4b11
--- /dev/null
+++ b/src/app/components/bulk-update-dialog/bulk-update-dialog.component.ts
@@ -0,0 +1,58 @@
+import { Component, Inject, ViewEncapsulation } from '@angular/core';
+import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { StixObject } from 'src/app/classes/stix/stix-object';
+import { SelectionModel } from '@angular/cdk/collections';
+import { StixListConfig } from '../stix/stix-list/stix-list.component';
+
+@Component({
+ selector: 'app-bulk-update-dialog',
+ templateUrl: './bulk-update-dialog.component.html',
+ styleUrls: ['./bulk-update-dialog.component.scss'],
+ encapsulation: ViewEncapsulation.None,
+ standalone: false,
+})
+export class BulkPromoteDialogComponent {
+ constructor(
+ public dialogRef: MatDialogRef,
+ @Inject(MAT_DIALOG_DATA) public config: BulkPromoteDialogConfig
+ ) {}
+
+ public get stixObjects(): StixObject[] {
+ if (Array.isArray(this.config.stixListConfig?.stixObjects)) {
+ return this.config.stixListConfig.stixObjects;
+ }
+ return this.config.selectableObjects || [];
+ }
+
+ public get hasSelectableContent(): boolean {
+ return (
+ this.config.type === 'user' ||
+ this.config.type === 'analytic' ||
+ !!this.config.stixListConfig ||
+ (this.config.selectableObjects?.length ?? 0) > 0
+ );
+ }
+
+ public clearSelections() {
+ this.config.select.clear();
+ this.dialogRef.close(true);
+ }
+
+ public selectAll(): void {
+ const ids = this.stixObjects.map(obj => obj.stixID);
+ this.config.select.select(...ids);
+ }
+}
+
+export interface BulkPromoteDialogConfig {
+ selectableObjects?: StixObject[]; // Stix Object array of selectable objects not in list
+ type: string; // type to display stix list
+ select: SelectionModel; // selection model to retrieve list of selected object
+ selectAll?: boolean;
+ selectionType?: 'many' | 'one' | 'disabled'; // defaults to 'many' if a selection model is given
+ canPromote?: boolean;
+ canDemote?: boolean;
+ title?: string; // dialog text
+ clearSelection?: boolean; //boolean to add clear selection button
+ stixListConfig?: StixListConfig; // optional full stix-list config
+}
diff --git a/src/app/views/dashboard-page/release-management/release-track-page/release-track-page.component.html b/src/app/views/dashboard-page/release-management/release-track-page/release-track-page.component.html
index a5c56555..56eeaebb 100644
--- a/src/app/views/dashboard-page/release-management/release-track-page/release-track-page.component.html
+++ b/src/app/views/dashboard-page/release-management/release-track-page/release-track-page.component.html
@@ -343,6 +343,22 @@ Resolution Details
add
Add
+
+