mirror of
https://github.com/clearml/clearml-web
synced 2025-06-26 18:27:02 +00:00
202 lines
9.1 KiB
TypeScript
Executable File
202 lines
9.1 KiB
TypeScript
Executable File
import {ChangeDetectionStrategy, Component, EventEmitter, Inject, OnDestroy, OnInit, ViewChild} from '@angular/core';
|
|
import {Store} from '@ngrx/store';
|
|
import * as actions from './select-model.actions';
|
|
import {clearTableFilter, setSelectedModels, showArchive} from './select-model.actions';
|
|
import {
|
|
selectGlobalFilter, selectModels, selectNoMoreModels, selectSelectedModels, selectSelectedModelsList, selectSelectModelTableFilters, selectShowArchive, selectTableSortFields, selectViewMode
|
|
} from './select-model.reducer';
|
|
import {combineLatest, Observable, Subscription} from 'rxjs';
|
|
import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog';
|
|
import {ConfirmDialogComponent} from '../shared/ui-components/overlay/confirm-dialog/confirm-dialog.component';
|
|
import {ColHeaderTypeEnum, ISmCol, TableSortOrderEnum} from '../shared/ui-components/data/table/table.consts';
|
|
import {SelectedModel, TableModel} from '../models/shared/models.model';
|
|
import {MODELS_TABLE_COLS, ModelsViewModesEnum} from '../models/models.consts';
|
|
import {FilterMetadata} from 'primeng/api/filtermetadata';
|
|
import {selectAllProjectsUsers, selectProjectSystemTags, selectSelectedProject, selectTablesFilterProjectsOptions} from '../core/reducers/projects.reducer';
|
|
import {selectMetadataColsForProject, selectMetadataColsOptions, selectModelsFrameworks, selectModelsTags, selectModelTableColumns} from '../models/reducers';
|
|
import {User} from '~/business-logic/model/users/user';
|
|
import * as modelsActions from '../models/actions/models-view.actions';
|
|
import {SortMeta} from 'primeng/api';
|
|
import {ModelsTableComponent} from '@common/models/shared/models-table/models-table.component';
|
|
import {debounceTime, distinctUntilChanged, map, tap} from 'rxjs/operators';
|
|
import {Project} from '~/business-logic/model/projects/models';
|
|
import {getTablesFilterProjectsOptions, resetTablesFilterProjectsOptions} from '@common/core/actions/projects.actions';
|
|
import {isEqual, unionBy} from 'lodash-es';
|
|
import {compareLimitations} from '@common/shared/entity-page/footer-items/compare-footer-item';
|
|
import {addMessage} from '@common/core/actions/layout.actions';
|
|
import {MESSAGES_SEVERITY} from '@common/constants';
|
|
|
|
@Component({
|
|
selector: 'sm-select-model',
|
|
templateUrl: './select-model.component.html',
|
|
styleUrls: ['./select-model.component.scss'],
|
|
changeDetection: ChangeDetectionStrategy.OnPush
|
|
})
|
|
export class SelectModelComponent implements OnInit, OnDestroy {
|
|
|
|
public models$: Observable<SelectedModel[]>;
|
|
public tableSortFields$: Observable<SortMeta[]>;
|
|
public tableSortOrder$: Observable<TableSortOrderEnum>;
|
|
public noMoreModels$: Observable<boolean>;
|
|
public tableFilters$: Observable<{ [s: string]: FilterMetadata }>;
|
|
public searchValue$: Observable<string>;
|
|
public selectedModels$: Observable<Array<TableModel>>;
|
|
public viewMode$: Observable<ModelsViewModesEnum>;
|
|
public users$: Observable<Array<User>>;
|
|
public tags$: Observable<string[]>;
|
|
public systemTags$: Observable<string[]>;
|
|
public tableCols = MODELS_TABLE_COLS;
|
|
public selectedProject$: Observable<Project>;
|
|
public projectsOptions$: Observable<Project[]>;
|
|
public frameworks$: Observable<string[]>;
|
|
private subs = new Subscription();
|
|
|
|
public selectedProject: Project;
|
|
private selectedModels: Array<SelectedModel>;
|
|
private columns$: Observable<ISmCol[]>;
|
|
private metadataTableCols$: Observable<ISmCol[]>;
|
|
public tableCols$: Observable<ISmCol[]>;
|
|
public metadataColsOptions$: Observable<Record<string, string[]>>;
|
|
public showArchive$: Observable<boolean>;
|
|
|
|
constructor(private store: Store,
|
|
public dialogRef: MatDialogRef<ConfirmDialogComponent>,
|
|
@Inject(MAT_DIALOG_DATA) public data: {
|
|
selectionMode: 'multiple' | 'single' | null;
|
|
selectedModels: string[];
|
|
header: string;
|
|
hideShowArchived: boolean;
|
|
}) {
|
|
// this.models$ = this.store.select(selectModelsList);
|
|
this.models$ = combineLatest([
|
|
this.store.select(selectModels),
|
|
this.store.select(selectSelectedModelsList),
|
|
]).pipe(
|
|
map(([models, selectedModels]) => unionBy(selectedModels, models, 'id')),
|
|
map(models => models?.map(model => ({...model, system_tags: model.system_tags?.map((t => t.replace('archive', ' archive')))})))
|
|
);
|
|
this.tableSortFields$ = this.store.select(selectTableSortFields);
|
|
this.tableFilters$ = this.store.select(selectSelectModelTableFilters);
|
|
this.selectedModels$ = this.store.select(selectSelectedModels).pipe(tap(models => this.selectedModels = models));
|
|
this.viewMode$ = this.store.select(selectViewMode);
|
|
this.searchValue$ = this.store.select(selectGlobalFilter);
|
|
this.noMoreModels$ = this.store.select(selectNoMoreModels);
|
|
this.showArchive$ = this.store.select(selectShowArchive);
|
|
this.users$ = this.store.select(selectAllProjectsUsers);
|
|
this.tags$ = this.store.select(selectModelsTags);
|
|
this.systemTags$ = this.store.select(selectProjectSystemTags);
|
|
this.subs.add(this.store.select(selectSelectedProject).pipe(debounceTime(100))
|
|
.subscribe(selectedProject => {
|
|
this.selectedProject = selectedProject;
|
|
if (selectedProject?.id !== '*') {
|
|
this.store.dispatch(actions.tableFilterChanged({col: {id: 'project.name'}, value: [selectedProject.id]}));
|
|
}
|
|
}));
|
|
this.frameworks$ = this.store.select(selectModelsFrameworks);
|
|
|
|
this.projectsOptions$ = this.store.select(selectTablesFilterProjectsOptions);
|
|
|
|
this.metadataColsOptions$ = this.store.select(selectMetadataColsOptions);
|
|
this.columns$ = this.store.select(selectModelTableColumns);
|
|
this.metadataTableCols$ = this.store.select(selectMetadataColsForProject);
|
|
this.tableCols$ = combineLatest([this.columns$, this.metadataTableCols$])
|
|
.pipe(
|
|
map(([tableCols, metricCols]) =>
|
|
(tableCols.length > 0 ? tableCols : this.tableCols)
|
|
.concat(metricCols.map(col => ({...col, metric: true})))
|
|
),
|
|
distinctUntilChanged((a, b) => isEqual(a, b)),
|
|
map(cols => cols.filter(col => (!col.hidden || col.id === 'project.name')).map(col => ({
|
|
...col,
|
|
hidden: false,
|
|
headerType: col.headerType === ColHeaderTypeEnum.checkBox ? ColHeaderTypeEnum.title : col.headerType,
|
|
...(col.id === 'project.name' && {
|
|
getter: 'project',
|
|
filterable: true,
|
|
searchableFilter: true,
|
|
sortable: false,
|
|
headerType: ColHeaderTypeEnum.sortFilter,
|
|
}),
|
|
})
|
|
)));
|
|
}
|
|
|
|
@ViewChild(ModelsTableComponent) table: ModelsTableComponent;
|
|
|
|
ngOnInit() {
|
|
this.store.dispatch(resetTablesFilterProjectsOptions());
|
|
this.store.dispatch(actions.getNextModels());
|
|
this.data.selectedModels && this.store.dispatch(actions.getSelectedModels({selectedIds: this.data.selectedModels}));
|
|
this.store.dispatch(modelsActions.getAllProjectsFrameworks());
|
|
this.store.dispatch(modelsActions.getTagsForAllProjects());
|
|
window.setTimeout(() => this.table.table.rowRightClick = new EventEmitter());
|
|
}
|
|
|
|
ngOnDestroy(): void {
|
|
this.store.dispatch(resetTablesFilterProjectsOptions());
|
|
this.store.dispatch(actions.resetSelectModelState({fullReset: false}));
|
|
this.subs.unsubscribe();
|
|
}
|
|
|
|
closeDialog(modelId: string) {
|
|
if (modelId) {
|
|
return this.dialogRef.close(modelId);
|
|
}
|
|
return this.dialogRef.close(null);
|
|
}
|
|
|
|
closeDialogMultiple() {
|
|
return this.dialogRef.close(this.selectedModels.map(model => model.id));
|
|
}
|
|
|
|
getNextModels() {
|
|
this.store.dispatch(actions.getNextModels());
|
|
}
|
|
|
|
sortedChanged(sort: { isShift: boolean; colId: ISmCol['id'] }) {
|
|
this.store.dispatch(actions.tableSortChanged({colId: sort.colId, isShift: sort.isShift}));
|
|
}
|
|
|
|
filterChanged(filter: { col: ISmCol; value: string }) {
|
|
this.store.dispatch(actions.tableFilterChanged({col: filter.col, value: filter.value}));
|
|
}
|
|
|
|
onSearchValueChanged(value: string) {
|
|
this.store.dispatch(actions.globalFilterChanged({filter: value}));
|
|
}
|
|
|
|
modelSelectionChanged(event: { model: SelectedModel }) {
|
|
if (this.data.selectionMode !== 'multiple') {
|
|
this.closeDialog(event.model?.id);
|
|
}
|
|
}
|
|
|
|
modelsSelectionChanged(models: SelectedModel[]) {
|
|
if (this.data.selectionMode !== 'multiple') {
|
|
return;
|
|
}
|
|
if (models.length === 0) {
|
|
this.store.dispatch(addMessage(MESSAGES_SEVERITY.WARN, 'Compare module should include at least one model'));
|
|
return;
|
|
}
|
|
if (models.length <= compareLimitations) {
|
|
this.store.dispatch(setSelectedModels({models}));
|
|
} else {
|
|
this.store.dispatch(addMessage(MESSAGES_SEVERITY.WARN, compareLimitations + ' or fewer models can be compared'));
|
|
}
|
|
}
|
|
|
|
filterSearchChanged({value}: { colId: string; value: { value: string; loadMore?: boolean } }) {
|
|
!value.loadMore && this.store.dispatch(resetTablesFilterProjectsOptions());
|
|
this.store.dispatch(getTablesFilterProjectsOptions({searchString: value.value || '', loadMore: value.loadMore}));
|
|
}
|
|
|
|
clearFilters() {
|
|
this.store.dispatch(clearTableFilter());
|
|
}
|
|
|
|
showArchives($event: boolean) {
|
|
this.store.dispatch(showArchive({showArchive: $event}));
|
|
}
|
|
}
|