mirror of
https://github.com/clearml/clearml-web
synced 2025-06-26 18:27:02 +00:00
@@ -3,7 +3,7 @@
|
||||
## Building the UI from source
|
||||
### Prerequisite
|
||||
* a linux machine
|
||||
* Node 12 with latest npm
|
||||
* Node 16 with latest npm
|
||||
* clone the project to your local machine
|
||||
|
||||
### build
|
||||
|
||||
30356
package-lock.json
generated
30356
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
118
package.json
118
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ClearML-webapp",
|
||||
"version": "1.2.0",
|
||||
"version": "1.3.0",
|
||||
"license": "",
|
||||
"scripts": {
|
||||
"ng": "ng",
|
||||
@@ -20,82 +20,84 @@
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@angular/animations": "^12.2.13",
|
||||
"@angular/cdk": "^12.2.13",
|
||||
"@angular/common": "^12.2.13",
|
||||
"@angular/compiler": "^12.2.13",
|
||||
"@angular/core": "^12.2.13",
|
||||
"@angular/forms": "^12.2.13",
|
||||
"@angular/material": "^12.2.13",
|
||||
"@angular/platform-browser": "^12.2.13",
|
||||
"@angular/platform-browser-dynamic": "^12.2.13",
|
||||
"@angular/platform-server": "^12.2.13",
|
||||
"@angular/router": "^12.2.13",
|
||||
"@angular/service-worker": "^12.2.13",
|
||||
"@aws-sdk/client-s3": "^3.41.0",
|
||||
"@aws-sdk/s3-request-presigner": "^3.41.0",
|
||||
"@ngrx/effects": "^12.5.1",
|
||||
"@ngrx/entity": "^12.5.1",
|
||||
"@ngrx/router-store": "^12.5.1",
|
||||
"@ngrx/store": "^12.5.1",
|
||||
"@angular/animations": "^13.1.1",
|
||||
"@angular/cdk": "^13.1.1",
|
||||
"@angular/common": "^13.1.1",
|
||||
"@angular/compiler": "^13.1.1",
|
||||
"@angular/core": "^13.1.1",
|
||||
"@angular/forms": "^13.1.1",
|
||||
"@angular/material": "^13.1.1",
|
||||
"@angular/platform-browser": "^13.1.1",
|
||||
"@angular/platform-browser-dynamic": "^13.1.1",
|
||||
"@angular/platform-server": "^13.1.1",
|
||||
"@angular/router": "^13.1.1",
|
||||
"@angular/service-worker": "^13.1.1",
|
||||
"@aws-sdk/client-s3": "^3.45.0",
|
||||
"@aws-sdk/s3-request-presigner": "^3.45.0",
|
||||
"@ngneat/dag": "^1.1.0",
|
||||
"@ngrx/effects": "^13.0.2",
|
||||
"@ngrx/entity": "^13.0.2",
|
||||
"@ngrx/router-store": "^13.0.2",
|
||||
"@ngrx/store": "^13.0.2",
|
||||
"ace-builds": "^1.4.13",
|
||||
"angular-google-tag-manager": "^1.4.3",
|
||||
"angular-resizable-element": "^4.0.0",
|
||||
"angular-split": "^5.0.0",
|
||||
"angular-google-tag-manager": "^1.5.0",
|
||||
"angular-resizable-element": "^5.0.0",
|
||||
"angular-split": "^13.1.0",
|
||||
"ansi-to-html": "^0.7.2",
|
||||
"bootstrap": "^4.6.1",
|
||||
"britecharts": "^2.18.0",
|
||||
"curved-arrows": "^0.1.0",
|
||||
"d3-selection": "^1.4.2",
|
||||
"diff": "^5.0.0",
|
||||
"filesize": "^8.0.6",
|
||||
"has-ansi": "^5.0.1",
|
||||
"hocon-parser": "^1.0.1",
|
||||
"jwt-decode": "^3.1.2",
|
||||
"lodash": "^4.17.21",
|
||||
"lucene": "^2.1.1",
|
||||
"ngx-clipboard": "^14.0.2",
|
||||
"ngx-color-picker": "^11.0.0",
|
||||
"ngx-filesize": "^2.0.16",
|
||||
"ngx-markdown-editor": "^3.3.3",
|
||||
"ngx-clipboard": "^15.0.1",
|
||||
"ngx-color-picker": "^12.0.0",
|
||||
"ngx-markdown-editor": "^4.0.0",
|
||||
"ngx-window-token": "^6.0.0",
|
||||
"object-hash": "^2.2.0",
|
||||
"primeicons": "^5.0.0",
|
||||
"primeng": "^12.2.2",
|
||||
"primeng": "^13.0.4",
|
||||
"process": "^0.11.10",
|
||||
"rxjs": "^6.6.7",
|
||||
"rxjs": "^7.5.1",
|
||||
"string-to-color": "^2.2.2",
|
||||
"tslib": "^2.3.1",
|
||||
"url": "^0.11.0",
|
||||
"uuid": "^8.3.2",
|
||||
"zone.js": "~0.11.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "~12.2.1",
|
||||
"@angular-devkit/core": "^12.2.1",
|
||||
"@angular-devkit/schematics": "^12.2.1",
|
||||
"@angular-devkit/schematics-cli": "^0.1102.6",
|
||||
"@angular-eslint/builder": "^12.0.0",
|
||||
"@angular-eslint/eslint-plugin": "^12.0.0",
|
||||
"@angular-eslint/eslint-plugin-template": "^12.0.0",
|
||||
"@angular-eslint/schematics": "12.3.1",
|
||||
"@angular-eslint/template-parser": "^12.0.0",
|
||||
"@angular/cli": "^12.2.1",
|
||||
"@angular/compiler-cli": "^12.2.1",
|
||||
"@angular/language-service": "^12.2.1",
|
||||
"@fortawesome/fontawesome-free": "^5.15.3",
|
||||
"@ngrx/schematics": "^12.4.0",
|
||||
"@ngrx/store-devtools": "^12.4.0",
|
||||
"@schematics/schematics": "^0.1102.6",
|
||||
"@types/d3-selection": "^2.0.0",
|
||||
"@types/lodash": "^4.14.168",
|
||||
"@types/node": "^14.14.41",
|
||||
"@types/plotly.js": "^1.54.14",
|
||||
"@types/uuid": "^8.3.0",
|
||||
"@typescript-eslint/eslint-plugin": "4.28.2",
|
||||
"@typescript-eslint/parser": "4.28.2",
|
||||
"codelyzer": "^6.0.1",
|
||||
"eslint": "^7.26.0",
|
||||
"eslint-plugin-import": "2.22.1",
|
||||
"eslint-plugin-jsdoc": "32.3.0",
|
||||
"@angular-devkit/build-angular": "^13.1.2",
|
||||
"@angular-devkit/core": "^13.1.2",
|
||||
"@angular-devkit/schematics": "^13.1.2",
|
||||
"@angular-devkit/schematics-cli": "^13.1.2",
|
||||
"@angular-eslint/builder": "^13.0.1",
|
||||
"@angular-eslint/eslint-plugin": "^13.0.1",
|
||||
"@angular-eslint/eslint-plugin-template": "^13.0.1",
|
||||
"@angular-eslint/schematics": "13.0.1",
|
||||
"@angular-eslint/template-parser": "^13.0.1",
|
||||
"@angular/cli": "^13.1.2",
|
||||
"@angular/compiler-cli": "^13.1.1",
|
||||
"@angular/language-service": "^13.1.1",
|
||||
"@fortawesome/fontawesome-free": "^5.15.4",
|
||||
"@ngrx/schematics": "^13.0.2",
|
||||
"@ngrx/store-devtools": "^13.0.2",
|
||||
"@types/d3-selection": "^1.4.3",
|
||||
"@types/lodash": "^4.14.178",
|
||||
"@types/node": "^16.11.19",
|
||||
"@types/plotly.js": "^1.54.20",
|
||||
"@types/uuid": "^8.3.4",
|
||||
"@typescript-eslint/eslint-plugin": "5.9.0",
|
||||
"@typescript-eslint/parser": "5.9.0",
|
||||
"codelyzer": "^6.0.2",
|
||||
"eslint": "^8.6.0",
|
||||
"eslint-plugin-import": "2.25.4",
|
||||
"eslint-plugin-jsdoc": "37.5.1",
|
||||
"eslint-plugin-prefer-arrow": "1.2.3",
|
||||
"ts-node": "~9.1.1",
|
||||
"typescript": "^4.3.5",
|
||||
"webpack-bundle-analyzer": "^4.4.0"
|
||||
"typescript": "^4.5.4"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ import {selectSelectedProject} from '@common/core/reducers/projects.reducer';
|
||||
import {MatDialog} from '@angular/material/dialog';
|
||||
import {getTutorialBucketCredentials} from '@common/core/actions/common-auth.actions';
|
||||
import {termsOfUseAccepted} from '@common/core/actions/users.actions';
|
||||
import {distinctUntilChanged, filter, map, tap} from 'rxjs/operators';
|
||||
import {distinctUntilChanged, filter, map, tap, withLatestFrom} from 'rxjs/operators';
|
||||
import * as routerActions from './webapp-common/core/actions/router.actions';
|
||||
import {combineLatest, Observable, Subscription} from 'rxjs';
|
||||
import {selectBreadcrumbsStrings} from '@common/layout/layout.reducer';
|
||||
@@ -23,17 +23,19 @@ import {formatStaticCrumb} from '@common/layout/breadcrumbs/breadcrumbs-common.u
|
||||
import {ServerUpdatesService} from '@common/shared/services/server-updates.service';
|
||||
import {selectAvailableUpdates} from './core/reducers/view.reducer';
|
||||
import {UPDATE_SERVER_PATH} from './app.constants';
|
||||
import {firstLogin, plotlyReady, setScaleFactor, visibilityChanged} from '@common/core/actions/layout.actions';
|
||||
import {aceReady, firstLogin, plotlyReady, setScaleFactor, visibilityChanged} from '@common/core/actions/layout.actions';
|
||||
import {UiUpdatesService} from '@common/shared/services/ui-updates.service';
|
||||
import {UsageStatsService} from './core/services/usage-stats.service';
|
||||
import {dismissSurvey} from './core/actions/layout.actions';
|
||||
import {getScaleFactor} from '@common/shared/utils/shared-utils';
|
||||
import {getScaleFactor, loadExternalLibrary} from '@common/shared/utils/shared-utils';
|
||||
import {User} from './business-logic/model/users/user';
|
||||
import {ConfigurationService} from '@common/shared/services/configuration.service';
|
||||
import {GoogleTagManagerService} from 'angular-google-tag-manager';
|
||||
import {selectIsSharedAndNotOwner} from './features/experiments/reducers';
|
||||
import {TipsService} from '@common/shared/services/tips.service';
|
||||
import {USER_PREFERENCES_KEY} from '@common/user-preferences';
|
||||
import {selectIsPipelines} from '@common/experiments-compare/reducers';
|
||||
import {Environment} from '../environments/base';
|
||||
|
||||
@Component({
|
||||
selector: 'sm-root',
|
||||
@@ -65,6 +67,7 @@ export class AppComponent implements OnInit, OnDestroy {
|
||||
public hideUpdate: boolean;
|
||||
public showSurvey: boolean;
|
||||
private plotlyURL: string;
|
||||
private environment: Environment;
|
||||
|
||||
@HostListener('document:visibilitychange') onVisibilityChange() {
|
||||
this.store.dispatch(visibilityChanged({visible: !document.hidden}));
|
||||
@@ -99,7 +102,7 @@ export class AppComponent implements OnInit, OnDestroy {
|
||||
this.selectedProjectFromUrl$ = this.store.select(selectRouterParams)
|
||||
.pipe(
|
||||
filter((params: Params) => !!params),
|
||||
map(params => get('projectId', params) || null)
|
||||
map(params => params?.projectId || null)
|
||||
);
|
||||
|
||||
if (ConfigurationService.globalEnvironment.GTM_ID) {
|
||||
@@ -112,6 +115,7 @@ export class AppComponent implements OnInit, OnDestroy {
|
||||
this.hideUpdate = env.hideUpdateNotice;
|
||||
this.showSurvey = env.showSurvey;
|
||||
this.plotlyURL = env.plotlyURL;
|
||||
this.environment = env;
|
||||
});
|
||||
this.router.events
|
||||
.pipe(filter(event => event instanceof NavigationEnd))
|
||||
@@ -131,7 +135,7 @@ export class AppComponent implements OnInit, OnDestroy {
|
||||
filter(user => !!user?.id),
|
||||
distinctUntilChanged((prev, next) => prev?.id === next?.id)
|
||||
)
|
||||
.subscribe(() => {
|
||||
.subscribe(() => {
|
||||
this.store.dispatch(getAllSystemProjects());
|
||||
this.store.dispatch(getTutorialBucketCredentials());
|
||||
this.store.dispatch(termsOfUseAccepted());
|
||||
@@ -144,7 +148,7 @@ export class AppComponent implements OnInit, OnDestroy {
|
||||
loginTime = Date.now();
|
||||
localStorage.setItem(USER_PREFERENCES_KEY.firstLogin, `${loginTime}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
this.selectedProjectFromUrl$.subscribe((projectId: string) => {
|
||||
this.store.dispatch(setSelectedProjectId({projectId}));
|
||||
@@ -164,19 +168,22 @@ export class AppComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
});
|
||||
|
||||
this.breadcrumbsSubscription = this.store.select(selectBreadcrumbsStrings)
|
||||
.pipe(filter(names => !!names))
|
||||
.subscribe(
|
||||
(names) => {
|
||||
this.breadcrumbsStrings = prepareNames(names);
|
||||
this.updateTitle();
|
||||
}
|
||||
);
|
||||
this.breadcrumbsSubscription = this.store.select(selectBreadcrumbsStrings).pipe(
|
||||
filter(names => !!names),
|
||||
withLatestFrom(this.store.select(selectIsPipelines))
|
||||
).subscribe(
|
||||
([names, isPipeLines]) => {
|
||||
this.breadcrumbsStrings = prepareNames(names, isPipeLines);
|
||||
this.updateTitle();
|
||||
}
|
||||
);
|
||||
|
||||
if (window.localStorage.getItem('disableHidpi') !== 'true') {
|
||||
this.setScale();
|
||||
}
|
||||
|
||||
this.loadPlotly();
|
||||
loadExternalLibrary(this.store, this.environment.plotlyURL, plotlyReady);
|
||||
loadExternalLibrary(this.store, '/assets/ace-builds/ace.js', aceReady);
|
||||
}
|
||||
|
||||
private setScale() {
|
||||
@@ -241,35 +248,4 @@ export class AppComponent implements OnInit, OnDestroy {
|
||||
get guestUser(): boolean {
|
||||
return !this.currentUser || this.currentUser?.role === 'guest';
|
||||
}
|
||||
|
||||
public loadPlotly(): void {
|
||||
const init = () => {
|
||||
const script: HTMLScriptElement = document.createElement('script');
|
||||
script.type = 'text/javascript';
|
||||
script.src = this.plotlyURL;
|
||||
script.onerror = () => console.error(`Error loading plotly.js library from ${this.plotlyURL}`);
|
||||
script.crossOrigin = 'use-credentials';
|
||||
|
||||
const head: HTMLHeadElement = document.getElementsByTagName('head')[0];
|
||||
head.appendChild(script);
|
||||
|
||||
let counter = 600;
|
||||
|
||||
const fn = () => {
|
||||
const plotly = (window as any).Plotly;
|
||||
if (plotly) {
|
||||
this.store.dispatch(plotlyReady());
|
||||
} else if (counter > 0) {
|
||||
counter --;
|
||||
setTimeout(fn, 100);
|
||||
} else {
|
||||
throw new Error(`Error loading plotly.js library from ${this.plotlyURL}. Timeout.`);
|
||||
}
|
||||
};
|
||||
|
||||
fn();
|
||||
};
|
||||
|
||||
setTimeout(init);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,6 +49,32 @@ export const routes: Routes = [
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
path: 'pipelines',
|
||||
// canActivate: [RolePermissionsGuard],
|
||||
data: {search: true},
|
||||
loadChildren: () => import('@common/pipelines/pipelines.module').then(m => m.PipelinesModule),
|
||||
},
|
||||
{
|
||||
path: 'pipelines',
|
||||
// canActivate: [RolePermissionsGuard],
|
||||
data: {search: true},
|
||||
children: [
|
||||
{
|
||||
path: ':projectId',
|
||||
children: [
|
||||
{path: 'pipelines', loadChildren: () => import('./features/projects/projects.module').then(m => m.ProjectsModule)},
|
||||
{
|
||||
path: 'experiments', loadChildren: () => import('@common/pipelines-controller/pipelines-controller.module').then(m => m.PipelinesControllerModule)
|
||||
},
|
||||
{
|
||||
path: 'compare-experiments',
|
||||
loadChildren: () => import('./webapp-common/experiments-compare/experiments-compare.module').then(m => m.ExperimentsCompareModule)
|
||||
},
|
||||
]
|
||||
},
|
||||
]
|
||||
},
|
||||
{path: 'workers-and-queues', loadChildren: () => import('./features/workers-and-queues/workers-and-queues.module').then(m => m.WorkersAndQueuesModule)},
|
||||
{path: '404', loadChildren: () => import('./features/not-found/not-found.module').then(m => m.NotFoundModule)},
|
||||
{path: '**', loadChildren: () => import('./features/not-found/not-found.module').then(m => m.NotFoundModule)},
|
||||
|
||||
109
src/app/business-logic/api-services/pipelines.service.ts
Normal file
109
src/app/business-logic/api-services/pipelines.service.ts
Normal file
@@ -0,0 +1,109 @@
|
||||
/**
|
||||
* pipelines
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* OpenAPI spec version: 999.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by the swagger code generator program.
|
||||
* https://github.com/swagger-api/swagger-codegen.git
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/member-ordering */
|
||||
|
||||
import {HTTP} from '../../app.constants';
|
||||
import {SmApiRequestsService} from "./api-requests.service";
|
||||
|
||||
import { Inject, Injectable, Optional } from '@angular/core';
|
||||
import { HttpClient, HttpHeaders, HttpParams,
|
||||
HttpResponse, HttpEvent } from '@angular/common/http';
|
||||
import { CustomHttpUrlEncodingCodec } from '../encoder';
|
||||
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
import { PipelinesStartPipelineRequest } from '../model/pipelines/pipelinesStartPipelineRequest';
|
||||
import { PipelinesStartPipelineResponse } from '../model/pipelines/pipelinesStartPipelineResponse';
|
||||
|
||||
import { BASE_PATH, COLLECTION_FORMATS } from '../variables';
|
||||
import { Configuration } from '../configuration';
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class ApiPipelinesService {
|
||||
|
||||
protected basePath = HTTP.API_BASE_URL;
|
||||
public defaultHeaders = new HttpHeaders();
|
||||
public configuration = new Configuration();
|
||||
|
||||
constructor(protected apiRequest: SmApiRequestsService, @Optional()@Inject(BASE_PATH) basePath: string, @Optional() configuration: Configuration) {
|
||||
if (basePath) {
|
||||
this.basePath = basePath;
|
||||
}
|
||||
if (configuration) {
|
||||
this.configuration = configuration;
|
||||
this.basePath = basePath || configuration.basePath || this.basePath;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param consumes string[] mime-types
|
||||
* @return true: consumes contains 'multipart/form-data', false: otherwise
|
||||
*/
|
||||
private canConsumeForm(consumes: string[]): boolean {
|
||||
const form = 'multipart/form-data';
|
||||
for (const consume of consumes) {
|
||||
if (form === consume) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Start a pipeline
|
||||
* @param request request body
|
||||
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
|
||||
* @param reportProgress flag to report request and response progress.
|
||||
*/
|
||||
public pipelinesStartPipeline(request: PipelinesStartPipelineRequest, options?: any, observe: any = 'body', reportProgress: boolean = false ): Observable<any> {
|
||||
if (request === null || request === undefined) {
|
||||
throw new Error('Required parameter request was null or undefined when calling pipelinesStartPipeline.');
|
||||
}
|
||||
|
||||
let headers = this.defaultHeaders;
|
||||
if (options && options.async_enable) {
|
||||
headers = headers.set(this.configuration.asyncHeader, '1');
|
||||
}
|
||||
|
||||
// to determine the Accept header
|
||||
const httpHeaderAccepts: string[] = [
|
||||
'application/json'
|
||||
];
|
||||
const httpHeaderAcceptSelected: string | undefined = this.configuration.selectHeaderAccept(httpHeaderAccepts);
|
||||
if (httpHeaderAcceptSelected != undefined) {
|
||||
headers = headers.set("Accept", httpHeaderAcceptSelected);
|
||||
}
|
||||
|
||||
// to determine the Content-Type header
|
||||
const consumes: string[] = [
|
||||
];
|
||||
const httpContentTypeSelected:string | undefined = this.configuration.selectHeaderContentType(consumes);
|
||||
if (httpContentTypeSelected != undefined) {
|
||||
headers = headers.set("Content-Type", httpContentTypeSelected);
|
||||
}
|
||||
|
||||
return this.apiRequest.post<PipelinesStartPipelineResponse>(`${this.basePath}/pipelines.start_pipeline`,
|
||||
request,
|
||||
{
|
||||
withCredentials: this.configuration.withCredentials,
|
||||
headers: headers,
|
||||
observe: observe,
|
||||
reportProgress: reportProgress
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -59,6 +59,10 @@ import { ProjectsValidateDeleteResponse } from '../model/projects/projectsValida
|
||||
|
||||
import { BASE_PATH, COLLECTION_FORMATS } from '../variables';
|
||||
import { Configuration } from '../configuration';
|
||||
import {ProjectsGetModelMetadataKeysResponse} from '~/business-logic/model/projects/projectsGetModelMetadataKeysResponse';
|
||||
import {ProjectsGetModelMetadataKeysRequest} from '~/business-logic/model/projects/projectsGetModelMetadataKeysRequest';
|
||||
import {ProjectsGetProjectTagsResponse} from '~/business-logic/model/projects/projectsGetProjectTagsResponse';
|
||||
import {ProjectsGetProjectTagsRequest} from '~/business-logic/model/projects/projectsGetProjectTagsRequest';
|
||||
|
||||
|
||||
@Injectable()
|
||||
@@ -408,6 +412,53 @@ export class ApiProjectsService {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Get a list of all metadata keys used in models within the given project.
|
||||
* @param request request body
|
||||
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
|
||||
* @param reportProgress flag to report request and response progress.
|
||||
*/
|
||||
public projectsGetModelMetadataKeys(request: ProjectsGetModelMetadataKeysRequest, options?: any, observe: any = 'body', reportProgress: boolean = false ): Observable<any> {
|
||||
if (request === null || request === undefined) {
|
||||
throw new Error('Required parameter request was null or undefined when calling projectsGetModelMetadataKeys.');
|
||||
}
|
||||
|
||||
let headers = this.defaultHeaders;
|
||||
if (options && options.async_enable) {
|
||||
headers = headers.set(this.configuration.asyncHeader, '1');
|
||||
}
|
||||
|
||||
// to determine the Accept header
|
||||
const httpHeaderAccepts: string[] = [
|
||||
'application/json'
|
||||
];
|
||||
const httpHeaderAcceptSelected: string | undefined = this.configuration.selectHeaderAccept(httpHeaderAccepts);
|
||||
if (httpHeaderAcceptSelected != undefined) {
|
||||
headers = headers.set("Accept", httpHeaderAcceptSelected);
|
||||
}
|
||||
|
||||
// to determine the Content-Type header
|
||||
const consumes: string[] = [
|
||||
];
|
||||
const httpContentTypeSelected:string | undefined = this.configuration.selectHeaderContentType(consumes);
|
||||
if (httpContentTypeSelected != undefined) {
|
||||
headers = headers.set("Content-Type", httpContentTypeSelected);
|
||||
}
|
||||
|
||||
return this.apiRequest.post<ProjectsGetModelMetadataKeysResponse>(`${this.basePath}/projects.get_model_metadata_keys`,
|
||||
request,
|
||||
{
|
||||
withCredentials: this.configuration.withCredentials,
|
||||
headers: headers,
|
||||
observe: observe,
|
||||
reportProgress: reportProgress
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Get user and system tags used for the models under the specified projects
|
||||
@@ -453,6 +504,51 @@ export class ApiProjectsService {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Get user and system tags used for the specified projects and their children
|
||||
* @param request request body
|
||||
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
|
||||
* @param reportProgress flag to report request and response progress.
|
||||
*/
|
||||
public projectsGetProjectTags(request: ProjectsGetProjectTagsRequest, options?: any, observe: any = 'body', reportProgress: boolean = false ): Observable<any> {
|
||||
if (request === null || request === undefined) {
|
||||
throw new Error('Required parameter request was null or undefined when calling projectsGetProjectTags.');
|
||||
}
|
||||
|
||||
let headers = this.defaultHeaders;
|
||||
if (options && options.async_enable) {
|
||||
headers = headers.set(this.configuration.asyncHeader, '1');
|
||||
}
|
||||
|
||||
// to determine the Accept header
|
||||
const httpHeaderAccepts: string[] = [
|
||||
'application/json'
|
||||
];
|
||||
const httpHeaderAcceptSelected: string | undefined = this.configuration.selectHeaderAccept(httpHeaderAccepts);
|
||||
if (httpHeaderAcceptSelected != undefined) {
|
||||
headers = headers.set("Accept", httpHeaderAcceptSelected);
|
||||
}
|
||||
|
||||
// to determine the Content-Type header
|
||||
const consumes: string[] = [
|
||||
];
|
||||
const httpContentTypeSelected:string | undefined = this.configuration.selectHeaderContentType(consumes);
|
||||
if (httpContentTypeSelected != undefined) {
|
||||
headers = headers.set("Content-Type", httpContentTypeSelected);
|
||||
}
|
||||
|
||||
return this.apiRequest.post<ProjectsGetProjectTagsResponse>(`${this.basePath}/projects.get_project_tags`,
|
||||
request,
|
||||
{
|
||||
withCredentials: this.configuration.withCredentials,
|
||||
headers: headers,
|
||||
observe: observe,
|
||||
reportProgress: reportProgress
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Get unique parent tasks for the tasks in the specified projects
|
||||
|
||||
@@ -15,6 +15,7 @@ import {ApiWorkersService} from './api-services/workers.service';
|
||||
import {ApiServerService} from './api-services/server.service';
|
||||
import {ApiOrganizationService} from './api-services/organization.service';
|
||||
import {ApiLoginService} from './api-services/login.service';
|
||||
import {ApiPipelinesService} from '~/business-logic/api-services/pipelines.service';
|
||||
|
||||
@NgModule({
|
||||
imports : [CommonModule, HttpClientModule],
|
||||
@@ -34,7 +35,8 @@ import {ApiLoginService} from './api-services/login.service';
|
||||
ApiUsersService,
|
||||
ApiServerService,
|
||||
ApiOrganizationService,
|
||||
ApiLoginService
|
||||
ApiLoginService,
|
||||
ApiPipelinesService
|
||||
]
|
||||
})
|
||||
export class BusinessLogicModule {
|
||||
|
||||
@@ -25,4 +25,5 @@ export interface CredentialKey {
|
||||
*
|
||||
*/
|
||||
last_used_from?: string;
|
||||
label?: string; // (nir) until BE will implement
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import {MetadataItem} from '../queues/metadataItem';
|
||||
|
||||
/**
|
||||
* models
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* OpenAPI spec version: 2.14
|
||||
* OpenAPI spec version: 2.12
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by the swagger code generator program.
|
||||
@@ -34,7 +36,7 @@ export interface ModelsEditRequest {
|
||||
*/
|
||||
tags?: Array<string>;
|
||||
/**
|
||||
* System tags list. This field is reserved for system use, please don\'t use it.
|
||||
* System tags list. This field is reserved for system use, please don't use it.
|
||||
*/
|
||||
system_tags?: Array<string>;
|
||||
/**
|
||||
@@ -44,7 +46,7 @@ export interface ModelsEditRequest {
|
||||
/**
|
||||
* Json[d] object representing the model design. Should be identical to the network design of the task which created the model
|
||||
*/
|
||||
design?: object;
|
||||
design?: any;
|
||||
/**
|
||||
* Json object
|
||||
*/
|
||||
@@ -69,4 +71,5 @@ export interface ModelsEditRequest {
|
||||
* Iteration (used to update task statistics)
|
||||
*/
|
||||
iteration?: number;
|
||||
metadata?: object;
|
||||
}
|
||||
|
||||
2
src/app/business-logic/model/pipelines/models.ts
Normal file
2
src/app/business-logic/model/pipelines/models.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from '././pipelinesStartPipelineRequest';
|
||||
export * from '././pipelinesStartPipelineResponse';
|
||||
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* pipelines
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* OpenAPI spec version: 999.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by the swagger code generator program.
|
||||
* https://github.com/swagger-api/swagger-codegen.git
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
export interface PipelinesStartPipelineRequest {
|
||||
/**
|
||||
* ID of the task on which the pipeline will be based
|
||||
*/
|
||||
task: string;
|
||||
/**
|
||||
* Queue ID in which the created pipeline task will be enqueued
|
||||
*/
|
||||
queue?: string;
|
||||
/**
|
||||
* Task arguments, key/value to be placed in the hyperparameters Args section
|
||||
*/
|
||||
args?: object;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* pipelines
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* OpenAPI spec version: 999.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by the swagger code generator program.
|
||||
* https://github.com/swagger-api/swagger-codegen.git
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
export interface PipelinesStartPipelineResponse {
|
||||
/**
|
||||
* ID of the new pipeline task
|
||||
*/
|
||||
pipeline?: string;
|
||||
/**
|
||||
* True if the task was successfuly enqueued
|
||||
*/
|
||||
enqueued?: boolean;
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import {ProjectsGetAllResponseSingleSubProjects} from '~/business-logic/model/projects/projectsGetAllResponseSingleSubProjects';
|
||||
import {Stats} from '~/business-logic/model/projects/stats';
|
||||
|
||||
/**
|
||||
* projects
|
||||
@@ -51,6 +52,7 @@ export interface Project {
|
||||
* The default output destination URL for new tasks under this project
|
||||
*/
|
||||
default_output_destination?: string;
|
||||
stats?: Stats;
|
||||
/**
|
||||
* Last project update time. Reflects the last time the project metadata was changed or a task in this project has changed status
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* projects
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* OpenAPI spec version: 999.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by the swagger code generator program.
|
||||
* https://github.com/swagger-api/swagger-codegen.git
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
export interface ProjectsGetModelMetadataKeysRequest {
|
||||
/**
|
||||
* Project ID
|
||||
*/
|
||||
project: string;
|
||||
/**
|
||||
* If set to \'true\' and the project field is set then the result includes metadate keys from the subproject models
|
||||
*/
|
||||
include_subprojects?: boolean;
|
||||
/**
|
||||
* Page number
|
||||
*/
|
||||
page?: number;
|
||||
/**
|
||||
* Page size
|
||||
*/
|
||||
page_size?: number;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* projects
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* OpenAPI spec version: 999.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by the swagger code generator program.
|
||||
* https://github.com/swagger-api/swagger-codegen.git
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
export interface ProjectsGetModelMetadataKeysResponse {
|
||||
/**
|
||||
* A list of model keys
|
||||
*/
|
||||
keys?: Array<string>;
|
||||
/**
|
||||
* Remaining results
|
||||
*/
|
||||
remaining?: number;
|
||||
/**
|
||||
* Total number of results
|
||||
*/
|
||||
total?: number;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* projects
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* OpenAPI spec version: 999.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by the swagger code generator program.
|
||||
* https://github.com/swagger-api/swagger-codegen.git
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import { ProjectsGetProjectTagsRequestFilter } from '././projectsGetProjectTagsRequestFilter';
|
||||
|
||||
|
||||
export interface ProjectsGetProjectTagsRequest {
|
||||
/**
|
||||
* If set to \'true\' then the list of the system tags is also returned. The default value is \'false\'
|
||||
*/
|
||||
include_system?: boolean;
|
||||
/**
|
||||
* The list of projects under which the tags are searched. If not passed or empty then all the projects are searched
|
||||
*/
|
||||
projects?: Array<string>;
|
||||
filter?: ProjectsGetProjectTagsRequestFilter;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* projects
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* OpenAPI spec version: 999.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by the swagger code generator program.
|
||||
* https://github.com/swagger-api/swagger-codegen.git
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Filter on entities to collect tags from
|
||||
*/
|
||||
export interface ProjectsGetProjectTagsRequestFilter {
|
||||
/**
|
||||
* The list of tag values to filter by. Use \'null\' value to specify empty tags. Use \'__Snot\' value to specify that the following value should be excluded
|
||||
*/
|
||||
tags?: Array<string>;
|
||||
/**
|
||||
* The list of system tag values to filter by. Use \'null\' value to specify empty system tags. Use \'__Snot\' value to specify that the following value should be excluded
|
||||
*/
|
||||
system_tags?: Array<string>;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* projects
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* OpenAPI spec version: 999.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by the swagger code generator program.
|
||||
* https://github.com/swagger-api/swagger-codegen.git
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
export interface ProjectsGetProjectTagsResponse {
|
||||
/**
|
||||
* The list of unique tag values
|
||||
*/
|
||||
tags?: Array<string>;
|
||||
/**
|
||||
* The list of unique system tag values. Returned only if \'include_system\' is set to \'true\' in the request
|
||||
*/
|
||||
system_tags?: Array<string>;
|
||||
}
|
||||
@@ -17,9 +17,19 @@ export interface StatsStatusCount {
|
||||
/**
|
||||
* Total run time of all tasks in project (in seconds)
|
||||
*/
|
||||
completed_tasks?: number;
|
||||
running_tasks?: number;
|
||||
total_tasks?: number;
|
||||
total_runtime?: number;
|
||||
/**
|
||||
* Number of tasks
|
||||
*/
|
||||
total_tasks?: number;
|
||||
/**
|
||||
* Number of tasks completed in the last 24 hours
|
||||
*/
|
||||
completed_tasks_24h?: number;
|
||||
/**
|
||||
* The most recent started time of a task
|
||||
*/
|
||||
last_task_run?: number;
|
||||
status_count?: StatsStatusCountStatusCount;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* projects
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* OpenAPI spec version: 2.14
|
||||
* OpenAPI spec version: 999.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by the swagger code generator program.
|
||||
@@ -20,6 +20,10 @@ export interface StatsStatusCountStatusCount {
|
||||
* Number of \'created\' tasks in project
|
||||
*/
|
||||
created?: number;
|
||||
/**
|
||||
* Number of \'completed\' tasks in project
|
||||
*/
|
||||
completed?: number;
|
||||
/**
|
||||
* Number of \'queued\' tasks in project
|
||||
*/
|
||||
|
||||
@@ -82,17 +82,13 @@ export const localStorageReducer = (reducer: ActionReducer<any>): ActionReducer<
|
||||
const savedState = JSON.parse(localStorage.getItem(key));
|
||||
nextState = merge(nextState, savedState);
|
||||
}
|
||||
|
||||
if (state === nextState) {
|
||||
return nextState;
|
||||
}
|
||||
|
||||
if (actionsPrefix && !actionsPrefix.some(ap => action.type.startsWith(ap))) {
|
||||
return nextState;
|
||||
}
|
||||
|
||||
localStorage.setItem(key, JSON.stringify(pick(syncedKeys, nextState)));
|
||||
|
||||
return nextState;
|
||||
};
|
||||
|
||||
|
||||
@@ -21,18 +21,16 @@ const _statsReducer = createReducer(initialState,
|
||||
on(setUsageStats, (state: UsageStatState, newState) => ({...state, ...newState}))
|
||||
);
|
||||
|
||||
export function usageStatsReducer(state = initialState, action: Action): UsageStatState {
|
||||
return _statsReducer(state, action);
|
||||
}
|
||||
export const usageStatsReducer = (state = initialState, action: Action) => _statsReducer(state, action);
|
||||
|
||||
export const selectSendStats = state => state[userStatsFeatureKey];
|
||||
export const selectSendStats = state => state.userStatsFeatureKey;
|
||||
|
||||
export const selectAllowed = createSelector(selectSendStats, (state: UsageStatState) => state.allowed);
|
||||
export const selectCurrentVersion = createSelector(selectSendStats, (state: UsageStatState) => state.currVersion);
|
||||
export const selectAllowedVersion = createSelector(selectSendStats, (state: UsageStatState) => state.allowedVersion);
|
||||
export const selectAllowed = createSelector(selectSendStats, (state) => state?.allowed);
|
||||
export const selectCurrentVersion = createSelector(selectSendStats, (state) => state?.currVersion);
|
||||
export const selectAllowedVersion = createSelector(selectSendStats, (state) => state?.allowedVersion);
|
||||
export const selectPromptUser = createSelector(
|
||||
selectCurrentVersion,
|
||||
selectAllowedVersion,
|
||||
selectAllowed,
|
||||
(currentVer: string, allowedVer: string, allowed: boolean) => !allowed && currentVer !== allowedVer
|
||||
(currentVer, allowedVer, allowed) => !allowed && currentVer !== allowedVer
|
||||
);
|
||||
|
||||
@@ -3,7 +3,7 @@ import {createReducer, createSelector, on} from '@ngrx/store';
|
||||
import {initUsers, users, usersReducerFunctions, UsersState} from '@common/core/reducers/users-reducer';
|
||||
import {setCurrentUser} from '../actions/users.action';
|
||||
|
||||
export const selectHasDataFeature = createSelector(users, () => false);
|
||||
export const selectHasDataFeature = createSelector(users, state => false);
|
||||
export const selectHasUserManagement = createSelector(users, () => false);
|
||||
|
||||
export const usersReducer = createReducer<UsersState>(initUsers,
|
||||
@@ -16,7 +16,7 @@ export const usersReducer = createReducer<UsersState>(initUsers,
|
||||
}))
|
||||
);
|
||||
|
||||
export const selectFeatures = createSelector(users, () => []);
|
||||
export const selectFeatures = createSelector(users, (state) => []);
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
export const selectTermsOfUse = createSelector(users, () => ({accept_required: null}));
|
||||
export const selectInvitesPending = createSelector(users, () => []);
|
||||
export const selectTermsOfUse = createSelector(users, state => ({accept_required: null}));
|
||||
export const selectInvitesPending = createSelector(users, state => []);
|
||||
|
||||
@@ -20,7 +20,7 @@ const initViewState: ViewState = {
|
||||
export const views = state => state.views as ViewState;
|
||||
export const selectAvailableUpdates = createSelector(views, state => state.availableUpdates);
|
||||
export const selectShowSurvey = createSelector(views, state => state.showSurvey);
|
||||
export const selectUserSettingsNotificationPath = createSelector(views, () => '');
|
||||
export const selectUserSettingsNotificationPath = createSelector(views, (state) => '');
|
||||
|
||||
export function viewReducer(viewState: ViewState = initViewState, action) {
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ export class UsageStatsService {
|
||||
|
||||
if (!ConfigurationService.globalEnvironment.demo) {
|
||||
this.store.select(selectPromptUser)
|
||||
.pipe(filter(prompt => prompt))
|
||||
.pipe(filter(prompt => !!prompt))
|
||||
.subscribe(() => {
|
||||
const dialogRef = this.dialog.open(ConfirmDialogComponent,
|
||||
{
|
||||
|
||||
@@ -8,6 +8,7 @@ export enum sourceTypesEnum {
|
||||
}
|
||||
|
||||
export interface IExecutionForm {
|
||||
artifacts?: any[];
|
||||
source: {
|
||||
repository: string;
|
||||
tag?: string;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import {TaskStatusEnum} from '../../../business-logic/model/tasks/taskStatusEnum';
|
||||
import {ExperimentTableColFieldsEnum} from './experiments.model';
|
||||
import {TaskTypeEnum} from '~/business-logic/model/tasks/taskTypeEnum';
|
||||
import {Model} from '~/business-logic/model/models/model';
|
||||
|
||||
export type experimentSectionsEnum =
|
||||
'MODEL_INPUT'
|
||||
@@ -32,13 +34,15 @@ export const EXPERIMENTS_TABLE_COL_FIELDS = {
|
||||
PROJECT : 'project.name' as ExperimentTableColFieldsEnum,
|
||||
METRIC : 'project.name' as ExperimentTableColFieldsEnum,
|
||||
HYPER_PARAM : 'project.name' as ExperimentTableColFieldsEnum,
|
||||
PARENT : 'parent.name' as ExperimentTableColFieldsEnum
|
||||
PARENT : 'parent.name' as ExperimentTableColFieldsEnum,
|
||||
VERSION : 'hyperparams.properties.version' as ExperimentTableColFieldsEnum
|
||||
};
|
||||
|
||||
export enum ExperimentTagsEnum {
|
||||
Development = 'development',
|
||||
Hidden = 'archived',
|
||||
Shared = 'shared'
|
||||
Shared = 'shared',
|
||||
Pipeline = 'pipeline'
|
||||
}
|
||||
|
||||
export const EXPERIMENTS_TAGS = {
|
||||
@@ -56,3 +60,5 @@ export const EXPERIMENTS_STATUS_LABELS = {
|
||||
|
||||
};
|
||||
export const DevWarningEnabled = false;
|
||||
|
||||
export const excludeTypes = [];
|
||||
|
||||
@@ -6,7 +6,6 @@ import { CommonModule } from '@angular/common';
|
||||
import { LoginRoutingModule } from './login-routing.module';
|
||||
|
||||
import { MatAutocompleteModule } from '@angular/material/autocomplete';
|
||||
import {NgxFilesizeModule} from 'ngx-filesize';
|
||||
import {MatProgressSpinnerModule} from '@angular/material/progress-spinner';
|
||||
import {MatCheckboxModule} from '@angular/material/checkbox';
|
||||
import {SignupComponent} from './signup/signup.component';
|
||||
@@ -14,8 +13,8 @@ import {MatFormFieldModule} from '@angular/material/form-field';
|
||||
import {MatSelectModule} from '@angular/material/select';
|
||||
import {MatInputModule} from '@angular/material/input';
|
||||
import {MatRadioModule} from '@angular/material/radio';
|
||||
import {LoginComponent} from '../../webapp-common/login/login/login.component';
|
||||
import {SharedPipesModule} from '../../webapp-common/shared/pipes/shared-pipes.module';
|
||||
import {LoginComponent} from '@common/login/login/login.component';
|
||||
import {SharedPipesModule} from '@common/shared/pipes/shared-pipes.module';
|
||||
|
||||
@NgModule({
|
||||
declarations: [LoginComponent, SignupComponent],
|
||||
@@ -26,7 +25,6 @@ import {SharedPipesModule} from '../../webapp-common/shared/pipes/shared-pipes.m
|
||||
FormsModule,
|
||||
MatAutocompleteModule,
|
||||
HttpClientModule,
|
||||
NgxFilesizeModule,
|
||||
MatProgressSpinnerModule,
|
||||
MatCheckboxModule,
|
||||
MatFormFieldModule,
|
||||
|
||||
@@ -8,10 +8,19 @@
|
||||
[class.hide-item]="sharedView"
|
||||
activeFeature="models" [archivedMode]="isArchived"></sm-project-context-navbar>
|
||||
<div class="d-flex justify-content-end align-items-center right-buttons">
|
||||
<sm-clear-filters-button
|
||||
[tableFilters]="tableFilters"
|
||||
(clearTableFilters)="clearTableFilters.emit(tableFilters)"
|
||||
></sm-clear-filters-button>
|
||||
<sm-model-custom-cols-menu
|
||||
[hidden]="minimizedView || sharedView"
|
||||
[disabled]="minimizedView || sharedView"
|
||||
[isLoading]="isLoadingMetadataKeys"
|
||||
[metadataKeys]="metadataKeys"
|
||||
[tableCols]="tableCols"
|
||||
(removeColFromList)="removeColFromList.emit($event)"
|
||||
(selectedTableColsChanged)="selectedTableColsChanged.emit($event)"
|
||||
(selectMetadataKeysActiveChanged)="selectMetadataKeysActiveChanged.emit($event)"
|
||||
(addOrRemoveMetadataKeyFromColumns)="addOrRemoveMetadataKeyFromColumns.emit($event)"
|
||||
></sm-model-custom-cols-menu>
|
||||
<sm-refresh-button
|
||||
[autoRefreshState]="autoRefreshState"
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import {Component, EventEmitter, Input, Output} from '@angular/core';
|
||||
import {FilterMetadata} from "primeng/api/filtermetadata";
|
||||
import {FilterMetadata} from 'primeng/api/filtermetadata';
|
||||
import {ISmCol} from '@common/shared/ui-components/data/table/table.consts';
|
||||
|
||||
@Component({
|
||||
selector : 'sm-model-header',
|
||||
selector: 'sm-model-header',
|
||||
templateUrl: './model-header.component.html',
|
||||
styleUrls : ['./model-header.component.scss']
|
||||
styleUrls: ['./model-header.component.scss']
|
||||
})
|
||||
export class ModelHeaderComponent {
|
||||
private _tableCols: any;
|
||||
@@ -17,21 +18,26 @@ export class ModelHeaderComponent {
|
||||
get tableCols() {
|
||||
return this._tableCols;
|
||||
}
|
||||
|
||||
@Input() isArchived: boolean;
|
||||
@Input() hideArchiveToggle: boolean;
|
||||
@Input() hideCreateNewButton: boolean;
|
||||
@Input() disableCreateNewButton: boolean;
|
||||
@Input() autoRefreshState: boolean;
|
||||
@Input() metadataKeys: string[];
|
||||
@Input() isLoadingMetadataKeys: any;
|
||||
@Input() sharedView: boolean;
|
||||
@Input() tableFilters: { [s: string]: FilterMetadata };
|
||||
|
||||
@Output() isArchivedChanged = new EventEmitter<boolean>();
|
||||
@Output() isArchivedChanged = new EventEmitter<boolean>();
|
||||
@Output() addModelClicked = new EventEmitter();
|
||||
@Output() refreshListClicked = new EventEmitter();
|
||||
@Output() setAutoRefresh = new EventEmitter();
|
||||
@Output() refreshListClicked = new EventEmitter();
|
||||
@Output() setAutoRefresh = new EventEmitter();
|
||||
@Output() selectedTableColsChanged = new EventEmitter();
|
||||
@Output() clearTableFilters = new EventEmitter<{ [s: string]: FilterMetadata }>();
|
||||
|
||||
@Output() clearTableFilters = new EventEmitter<{ [s: string]: FilterMetadata }>();
|
||||
@Output() selectMetadataKeysActiveChanged = new EventEmitter();
|
||||
@Output() addOrRemoveMetadataKeyFromColumns = new EventEmitter<{ key: string; show: boolean }>();
|
||||
@Output() removeColFromList = new EventEmitter<ISmCol['id']>();
|
||||
|
||||
|
||||
archivedChanged(value: boolean) {
|
||||
|
||||
@@ -37,4 +37,4 @@ export const projectsReducer = (state: IProjectsState = projectsInitState, actio
|
||||
|
||||
export const projects = state => state.projects as IProjectsState;
|
||||
|
||||
export const selectShowHidden = createSelector(projects, () => false);
|
||||
export const selectShowHidden = createSelector(projects, (state) => false);
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
<sm-dialog-template>
|
||||
<sm-admin-dialog-template [newCredential]="data.credentials"></sm-admin-dialog-template>
|
||||
<sm-admin-dialog-template
|
||||
[newCredential]="(newCredential$ | async) || {}"
|
||||
(onCreateCredentials)="onCreateCredentials($event)"
|
||||
></sm-admin-dialog-template>
|
||||
</sm-dialog-template>
|
||||
|
||||
@@ -1,16 +1,27 @@
|
||||
import {Component, Inject, OnInit} from '@angular/core';
|
||||
import {Component, Inject} from '@angular/core';
|
||||
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
import {Store} from '@ngrx/store';
|
||||
import {createCredential} from '@common/core/actions/common-auth.actions';
|
||||
import {OrganizationGetUserCompaniesResponseCompanies} from '~/business-logic/model/organization/organizationGetUserCompaniesResponseCompanies';
|
||||
import {Observable} from 'rxjs';
|
||||
import {CredentialKeyExt, selectNewCredential} from '@common/core/reducers/common-auth-reducer';
|
||||
|
||||
@Component({
|
||||
selector: 'sm-create-credential-dialog',
|
||||
templateUrl: './create-credential-dialog.component.html',
|
||||
styleUrls: ['./create-credential-dialog.component.scss']
|
||||
})
|
||||
export class CreateCredentialDialogComponent implements OnInit {
|
||||
export class CreateCredentialDialogComponent {
|
||||
public newCredential$: Observable<CredentialKeyExt>;
|
||||
|
||||
constructor(@Inject(MAT_DIALOG_DATA) public data: {credentials: any; workspace?: string}) {}
|
||||
|
||||
ngOnInit() {
|
||||
constructor(
|
||||
@Inject(MAT_DIALOG_DATA) public data: {credentials: any; workspace?: OrganizationGetUserCompaniesResponseCompanies},
|
||||
private store: Store
|
||||
) {
|
||||
this.newCredential$ = this.store.select(selectNewCredential);
|
||||
}
|
||||
|
||||
onCreateCredentials({label}) {
|
||||
this.store.dispatch(createCredential({workspace: this.data.workspace, label}));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,10 +3,11 @@ import {Observable, Subscription} from 'rxjs';
|
||||
import {CredentialKeyExt, selectCredentials, selectNewCredential} from '@common/core/reducers/common-auth-reducer';
|
||||
import {selectCurrentUser} from '@common/core/reducers/users-reducer';
|
||||
import {filter, take} from 'rxjs/operators';
|
||||
import {credentialRevoked, getAllCredentials} from '@common/core/actions/common-auth.actions';
|
||||
import {credentialRevoked, getAllCredentials, resetCredential} from '@common/core/actions/common-auth.actions';
|
||||
import {Store} from '@ngrx/store';
|
||||
import { createCredential } from '@common/core/actions/common-auth.actions';
|
||||
import {GetCurrentUserResponseUserObject} from '~/business-logic/model/users/getCurrentUserResponseUserObject';
|
||||
import {MatDialog} from '@angular/material/dialog';
|
||||
import {CreateCredentialDialogComponent} from '~/features/settings/containers/admin/create-credential-dialog/create-credential-dialog.component';
|
||||
|
||||
@Component({
|
||||
selector: 'sm-user-credentials',
|
||||
@@ -19,7 +20,7 @@ export class UserCredentialsComponent implements OnInit, OnDestroy {
|
||||
private newCredentialSub: Subscription;
|
||||
creatingCredentials = false;
|
||||
private user: GetCurrentUserResponseUserObject;
|
||||
constructor(private store: Store) { }
|
||||
constructor(private store: Store, private dialog: MatDialog) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.store.select(selectCurrentUser)
|
||||
@@ -38,7 +39,15 @@ export class UserCredentialsComponent implements OnInit, OnDestroy {
|
||||
|
||||
createCredential() {
|
||||
this.creatingCredentials = true;
|
||||
this.store.dispatch(createCredential({workspace: this.user.company, openCredentialsPopup: true}));
|
||||
this.dialog.open(CreateCredentialDialogComponent, {
|
||||
data: {workspace : this.user.company},
|
||||
width: '816px'
|
||||
}
|
||||
).afterClosed().subscribe(() => {
|
||||
this.creatingCredentials = false;
|
||||
this.store.dispatch(resetCredential());
|
||||
});
|
||||
// this.store.dispatch(createCredential({workspace: this.user.company, openCredentialsPopup: true}));
|
||||
}
|
||||
|
||||
onCredentialRevoked(accessKey) {
|
||||
|
||||
@@ -4,7 +4,7 @@ import { SettingsRoutingModule } from './settings-routing.module';
|
||||
import { SettingsComponent } from '../settings/settings.component';
|
||||
import {SMMaterialModule} from '../../webapp-common/shared/material/material.module';
|
||||
import {SMSharedModule} from '@common/shared/shared.module';
|
||||
import {ReactiveFormsModule} from '@angular/forms';
|
||||
import {FormsModule, ReactiveFormsModule} from '@angular/forms';
|
||||
import {SharedModule} from '~/shared/shared.module';
|
||||
import {MatExpansionModule} from '@angular/material/expansion';
|
||||
import {WebappConfigurationComponent} from '@common/settings/webapp-configuration/webapp-configuration.component';
|
||||
@@ -47,7 +47,10 @@ import {CreateCredentialDialogComponent} from '~/features/settings/containers/ad
|
||||
SettingsRoutingModule,
|
||||
SMMaterialModule,
|
||||
SMSharedModule,
|
||||
ReactiveFormsModule, SharedModule, MatExpansionModule,
|
||||
ReactiveFormsModule,
|
||||
SharedModule,
|
||||
MatExpansionModule,
|
||||
FormsModule,
|
||||
],
|
||||
exports: [
|
||||
UserCredentialsComponent,
|
||||
|
||||
@@ -21,12 +21,14 @@ export const selectBreadcrumbsStringsBase = createSelector(
|
||||
(project, experiment, model, projects) =>
|
||||
({project, experiment, model, projects}) as IBreadcrumbs);
|
||||
|
||||
|
||||
export const prepareNames = (data: IBreadcrumbs) => {
|
||||
const project = prepareLinkData(data.project, true);
|
||||
export function prepareNames(data: IBreadcrumbs, noSubProjects?: boolean) {
|
||||
const project = prepareLinkData(data.project, true);
|
||||
if (data.project) {
|
||||
const subProjects = [];
|
||||
const subProjectsNames = data.project?.name?.split('/');
|
||||
let subProjectsNames = [data.project?.name];
|
||||
if (!noSubProjects) {
|
||||
subProjectsNames = data.project?.name?.split('/');
|
||||
}
|
||||
let currentName = '';
|
||||
subProjectsNames.forEach(name => {
|
||||
currentName += currentName ? ('/' + name) : name;
|
||||
@@ -37,11 +39,11 @@ export const prepareNames = (data: IBreadcrumbs) => {
|
||||
].find(proj => currentName === proj.name);
|
||||
subProjects.push(foundProject);
|
||||
});
|
||||
const subProjectsLinks = subProjects.map(subProject => ({
|
||||
name: subProject?.name.substring(subProject?.name.lastIndexOf('/') + 1),
|
||||
url: `projects/${subProject?.id}/projects`
|
||||
const subProjectsLinks = subProjects.map(proj => ({
|
||||
name: proj?.name.substring(proj?.name.lastIndexOf('/') + 1),
|
||||
url: (noSubProjects || (proj?.name === data.project?.name && data.project?.sub_projects?.length===0)) ? '' : `projects/${proj?.id}/projects`
|
||||
})) as { name: string; url: string }[];
|
||||
project.name = project.name.substring(project.name.lastIndexOf('/') + 1);
|
||||
project.name = project?.name.substring(project.name.lastIndexOf('/') + 1);
|
||||
project.subCrumbs = subProjectsLinks;
|
||||
}
|
||||
const task = prepareLinkData(data.task);
|
||||
|
||||
@@ -12,27 +12,39 @@
|
||||
|
||||
<ng-container *ngIf="currentUser">
|
||||
<a class="item d-block" #rlaHome="routerLinkActive" routerLink="/dashboard" routerLinkActive (click)="resetSearch()"
|
||||
smTooltip="DASHBOARD" showDelay="0" matTooltipPosition="right">
|
||||
smTooltip="DASHBOARD" [matTooltipShowDelay]="0" matTooltipPosition="right">
|
||||
<div class="item-icon">
|
||||
<i [class]="'al-icon al-ico-home al-color ' + (rlaHome.isActive ? 'neon-yellow': 'blue-300')" ></i>
|
||||
</div>
|
||||
<div class="caption">dashboard</div>
|
||||
</a>
|
||||
|
||||
<a class="item d-block" smTooltip="PROJECTS" showDelay="0" matTooltipPosition="right" routerLink="/projects"
|
||||
<a class="item d-block" smTooltip="PROJECTS" [matTooltipShowDelay]="0" matTooltipPosition="right" routerLink="/projects"
|
||||
[routerLinkActive] #rlaProjects="routerLinkActive">
|
||||
<div class="item-icon">
|
||||
<i [class]="'al-icon al-ico-projects al-color ' + (rlaProjects.isActive ? 'neon-yellow': 'blue-300')" ></i>
|
||||
</div>
|
||||
<div class="caption">projects</div>
|
||||
</a>
|
||||
<a class="item d-block"
|
||||
routerLink="/pipelines"
|
||||
routerLinkActive
|
||||
#rlaDatasets="routerLinkActive"
|
||||
smTooltip="PIPELINES"
|
||||
[matTooltipShowDelay]="0"
|
||||
matTooltipPosition="right">
|
||||
<div class="item-icon">
|
||||
<i [class]="'al-icon al-ico-pipelines al-color ' + (rlaDatasets.isActive ? 'neon-yellow': 'blue-300')"></i>
|
||||
</div>
|
||||
<div class="caption">pipelines</div>
|
||||
</a>
|
||||
<a class="item d-block"
|
||||
*smCheckPermission="true"
|
||||
routerLink="/workers-and-queues"
|
||||
routerLinkActive
|
||||
#rlaQueues="routerLinkActive"
|
||||
smTooltip="WORKERS & QUEUES"
|
||||
showDelay="0"
|
||||
[matTooltipShowDelay]="0"
|
||||
matTooltipPosition="right">
|
||||
<div class="item-icon">
|
||||
<i [class]="'al-icon al-ico-queues al-color ' + (rlaQueues.isActive ? 'neon-yellow': 'blue-300')" ></i>
|
||||
@@ -43,7 +55,9 @@
|
||||
</ng-container>
|
||||
<div *ngIf="currentUser" class="account">
|
||||
<a *ngIf="environment.whiteLabelLink" class="item d-block" target="_blank"
|
||||
[smTooltip]="environment.whiteLabelLink.tooltip" showDelay="0" matTooltipPosition="right"
|
||||
[smTooltip]="environment.whiteLabelLink.tooltip"
|
||||
[matTooltipShowDelay]="0"
|
||||
matTooltipPosition="right"
|
||||
[href]="environment.whiteLabelLink.link">
|
||||
<div class="item-icon"
|
||||
[style.background-image]="'url(' + environment.whiteLabelLink.logo + ')'"
|
||||
@@ -53,7 +67,9 @@
|
||||
<div class="caption">Ignite</div>
|
||||
</a>
|
||||
<a class="item d-block" href="https://github.com/allegroai/clearml" target="_blank"
|
||||
smTooltip="GitHub Repository" showDelay="0" matTooltipPosition="right">
|
||||
smTooltip="GitHub Repository"
|
||||
[matTooltipShowDelay]="0"
|
||||
matTooltipPosition="right">
|
||||
<div class="item-icon">
|
||||
<i class="fab fa-github fa-24 al-color blue-300"></i>
|
||||
</div>
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
import {TaskStatusEnum} from '../../business-logic/model/tasks/taskStatusEnum';
|
||||
import {TaskTypeEnum} from '../../business-logic/model/tasks/taskTypeEnum';
|
||||
import {TaskStatusEnum} from '~/business-logic/model/tasks/taskStatusEnum';
|
||||
import {TaskTypeEnum} from '~/business-logic/model/tasks/taskTypeEnum';
|
||||
|
||||
export enum EntityTypeEnum {
|
||||
experiment = 'experiment',
|
||||
model = 'model',
|
||||
project = 'project',
|
||||
controller = 'pipeline run'
|
||||
}
|
||||
|
||||
export enum CircleTypeEnum {
|
||||
completed = 'completed',
|
||||
running = 'running',
|
||||
pending = 'pending',
|
||||
failed = 'failed',
|
||||
empty = 'empty',
|
||||
'model-labels' = 'model-labels'
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
@font-face {
|
||||
font-family: '#{$icomoon-font-family}';
|
||||
src: url('./#{$icomoon-font-family}.ttf?mmpkhb') format('truetype');
|
||||
src: url('./#{$icomoon-font-family}.ttf?dn2wcr') format('truetype');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: block;
|
||||
@@ -1086,41 +1086,96 @@
|
||||
content: $al-ico-no-code;
|
||||
}
|
||||
}
|
||||
.al-ico-automation {
|
||||
&:before {
|
||||
content: $al-ico-automation;
|
||||
}
|
||||
}
|
||||
.al-ico-calendar-checked {
|
||||
&:before {
|
||||
content: $al-ico-calendar-checked;
|
||||
}
|
||||
}
|
||||
.al-ico-no-source {
|
||||
&:before {
|
||||
content: $al-ico-no-source;
|
||||
}
|
||||
}
|
||||
.al-ico-arrow-up {
|
||||
&:before {
|
||||
content: $al-ico-arrow-up;
|
||||
}
|
||||
}
|
||||
.al-ico-arrow-down {
|
||||
&:before {
|
||||
content: $al-ico-arrow-down;
|
||||
}
|
||||
}
|
||||
.al-ico-error-circle {
|
||||
&:before {
|
||||
content: $al-ico-error-circle;
|
||||
}
|
||||
}
|
||||
.al-ico-pipelines {
|
||||
&:before {
|
||||
content: $al-ico-pipelines;
|
||||
}
|
||||
}
|
||||
.al-ico-console {
|
||||
&:before {
|
||||
content: $al-ico-console;
|
||||
}
|
||||
}
|
||||
.al-ico-link-arrow {
|
||||
&:before {
|
||||
content: $al-ico-link-arrow;
|
||||
}
|
||||
}
|
||||
.al-ico-broken-file {
|
||||
&:before {
|
||||
content: $al-ico-broken-file;
|
||||
}
|
||||
}
|
||||
.al-ico-run {
|
||||
&:before {
|
||||
content: $al-ico-run;
|
||||
}
|
||||
}
|
||||
.al-ico-status-draft {
|
||||
&:before {
|
||||
content: $al-ico-status-draft;
|
||||
}
|
||||
}
|
||||
.al-ico-status-published {
|
||||
&:before {
|
||||
content: $al-ico-status-published;
|
||||
}
|
||||
}
|
||||
.al-ico-status-aborted-sec {
|
||||
&:before {
|
||||
content: $al-ico-status-aborted-sec;
|
||||
}
|
||||
}
|
||||
.al-ico-status-pending {
|
||||
&:before {
|
||||
content: $al-ico-status-pending;
|
||||
}
|
||||
}
|
||||
.al-ico-status-skiped {
|
||||
&:before {
|
||||
content: $al-ico-status-skiped;
|
||||
}
|
||||
}
|
||||
.al-ico-status-cached {
|
||||
&:before {
|
||||
content: $al-ico-status-cached;
|
||||
}
|
||||
}
|
||||
.al-ico-status-executed {
|
||||
&:before {
|
||||
content: $al-ico-status-executed;
|
||||
}
|
||||
}
|
||||
.al-ico-status-running {
|
||||
&:before {
|
||||
content: $al-ico-status-running;
|
||||
}
|
||||
}
|
||||
.al-ico-status-completed {
|
||||
&:before {
|
||||
content: $al-ico-status-completed;
|
||||
}
|
||||
}
|
||||
.al-ico-status-published {
|
||||
&:before {
|
||||
content: $al-ico-status-published;
|
||||
}
|
||||
}
|
||||
.al-ico-status-failed {
|
||||
&:before {
|
||||
content: $al-ico-status-failed;
|
||||
@@ -1131,9 +1186,14 @@
|
||||
content: $al-ico-status-aborted;
|
||||
}
|
||||
}
|
||||
.al-ico-status-aborted-sec {
|
||||
.al-ico-status-completed {
|
||||
&:before {
|
||||
content: $al-ico-status-aborted-sec;
|
||||
content: $al-ico-status-completed;
|
||||
}
|
||||
}
|
||||
.al-ico-status-queued {
|
||||
&:before {
|
||||
content: $al-ico-enqueue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
@@ -209,14 +209,25 @@ $al-ico-youtube: "\e9a8";
|
||||
$al-ico-lock: "\e9a9";
|
||||
$al-ico-lock-open: "\e9aa";
|
||||
$al-ico-no-code: "\e9ab";
|
||||
$al-ico-automation: "\e9ac";
|
||||
$al-ico-calendar-checked: "\e9ad";
|
||||
$al-ico-no-source: "\e9ae";
|
||||
$al-ico-arrow-up: "\e9b1";
|
||||
$al-ico-arrow-down: "\e9b2";
|
||||
$al-ico-error-circle: "\e9b4";
|
||||
$al-ico-pipelines: "\e9b5";
|
||||
$al-ico-console: "\e9bc";
|
||||
$al-ico-link-arrow: "\e9bf";
|
||||
$al-ico-broken-file: "\e9c0";
|
||||
$al-ico-run: "\e9c1";
|
||||
$al-ico-status-draft: "\e902";
|
||||
$al-ico-status-pending: "\e903";
|
||||
$al-ico-status-running: "\e904";
|
||||
$al-ico-status-completed: "\e905";
|
||||
$al-ico-status-published: "\e906";
|
||||
$al-ico-status-aborted-sec: "\e918";
|
||||
$al-ico-status-pending: "\e903";
|
||||
$al-ico-status-skiped: "\e9bd";
|
||||
$al-ico-status-cached: "\e9be";
|
||||
$al-ico-status-executed: "\e9ac";
|
||||
$al-ico-status-running: "\e904";
|
||||
$al-ico-status-failed: "\e907";
|
||||
$al-ico-status-aborted: "\e917";
|
||||
$al-ico-status-aborted-sec: "\e918";
|
||||
$al-ico-status-completed: "\e905";
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 816 B |
6
src/app/webapp-common/assets/icons/image-no-source.svg
Normal file
6
src/app/webapp-common/assets/icons/image-no-source.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="400" height="400" viewBox="0 0 400 400">
|
||||
<path d="M206 141.49h-18a4 4 0 0 0-4 4v32a4 4 0 0 0 4 4h24a4 4 0 0 0 4-4v-26Zm0 5.63 4.37 4.37H206Zm6 30.37h-24v-32h14v6a4 4 0 0 0 4 4h6Zm-6.34-12.83-2.83 2.83 2.83 2.83a2 2 0 0 1-2.83 2.83l-2.83-2.83-2.83 2.83a2 2 0 0 1-2.83-2.83l2.83-2.83-2.83-2.83a2 2 0 1 1 2.78-2.88v.05l2.83 2.83 2.83-2.83a2 2 0 0 1 2.88 2.78s0 0-.05 0" fill="#5a658e"/>
|
||||
<text transform="translate(32 208)" font-size="16" fill="#5a658e" font-family="'Heebo', sans-serif" font-weight="500">This source is not specified in this Framegroup</text>
|
||||
<text transform="translate(127 240)" font-size="12" fill="#5a658e" font-family="'Heebo', sans-serif">Changes cannot be applied</text>
|
||||
<text transform="translate(36 258)" font-size="12" fill="#5a658e" font-family="'Heebo', sans-serif">Choose an available source or go back to the version browser</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 913 B |
5
src/app/webapp-common/assets/icons/no-code-dk.svg
Normal file
5
src/app/webapp-common/assets/icons/no-code-dk.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 242.15">
|
||||
<title>no-code dark</title>
|
||||
<path fill="#39405f"
|
||||
d="M20.82,242.15H279.18A20.84,20.84,0,0,0,300,221.33V20.82A20.84,20.84,0,0,0,279.18,0H20.82A20.84,20.84,0,0,0,0,20.82V221.33A20.84,20.84,0,0,0,20.82,242.15Zm258.36-10.72H20.82a10.2,10.2,0,0,1-10.11-10.1V68.88H289.29V221.63a9.93,9.93,0,0,1-10.06,9.8h-.05ZM20.82,11H279.18a10.2,10.2,0,0,1,10.11,10.1V58.18H10.71V20.82a9.93,9.93,0,0,1,10-9.82Zm9.79,27.24a5.67,5.67,0,0,1-1.53-3.68,5.65,5.65,0,0,1,1.53-3.67,6,6,0,0,1,7.66,0,5.65,5.65,0,0,1,1.53,3.67,5.22,5.22,0,0,1-5.21,5.21,6.42,6.42,0,0,1-4-1.5Zm28.77,0a5.67,5.67,0,0,1-1.53-3.68,5.65,5.65,0,0,1,1.53-3.67,6,6,0,0,1,7.66,0,5.65,5.65,0,0,1,1.53,3.67,5.22,5.22,0,0,1-5.2,5.21,7.28,7.28,0,0,1-4-1.5Zm29.08,0a5.67,5.67,0,0,1-1.53-3.68,5.65,5.65,0,0,1,1.53-3.67c1.85-1.84,5.52-1.84,7.66,0a5.65,5.65,0,0,1,1.53,3.67,5.22,5.22,0,0,1-5.2,5.21,6.59,6.59,0,0,1-4-1.5ZM208.87,146.8l-8.33,8.34-18.75,18.75-8.33-8.34,18.73-18.75L173.45,128l8.34-8.33,18.75,18.75Zm-90.68-27.08L99.45,138.47l-8.33,8.33,8.33,8.34,18.74,18.75,8.33-8.34L107.79,146.8,126.54,128Zm16.5,69,11.5,2.51,19.05-86.32-11.52-2.54Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
94
src/app/webapp-common/assets/icons/pipeline-empty-state.svg
Normal file
94
src/app/webapp-common/assets/icons/pipeline-empty-state.svg
Normal file
@@ -0,0 +1,94 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="487" height="434" viewBox="0 0 487 434">
|
||||
<g style="opacity:.996">
|
||||
<path data-name="connector" d="M-72.842-2.432h31.272c12.026 0 16.185 7.754 16.185 15.728V43.33" transform="translate(444.116 27.577)" style="fill:none;stroke:#5a658e;stroke-width:2px"/>
|
||||
<path d="m936.044 346.708 3.429 3.429 3.429-3.429" transform="translate(-520.743 -279.229)" style="fill:none;stroke:#5a658e;stroke-width:2px"/>
|
||||
<g data-name="connector">
|
||||
<path data-name="connector" d="M-72.842-2.432h31.272c12.026 0 16.185 7.754 16.185 15.728V43.33" transform="translate(328.76 181.343)" style="fill:none;stroke:#5a658e;stroke-width:2px"/>
|
||||
<path data-name="connector-head" d="m936.044 346.708 3.429 3.429 3.429-3.429" transform="translate(-636.099 -125.463)" style="fill:none;stroke:#5a658e;stroke-width:2px"/>
|
||||
</g>
|
||||
<g data-name="connector">
|
||||
<path data-name="connector" d="M-25.386-2.432h-31.271c-12.026 0-16.184 7.754-16.184 15.728V43.33" transform="translate(259.337 27.577)" style="fill:none;stroke:#5a658e;stroke-width:2px"/>
|
||||
<path data-name="connector-head" d="m942.9 346.708-3.429 3.429-3.429-3.429" transform="translate(-752.978 -279.229)" style="fill:none;stroke:#5a658e;stroke-width:2px"/>
|
||||
</g>
|
||||
<g data-name="connector">
|
||||
<path data-name="connector" d="M-25.386-2.432h-31.271c-12.026 0-16.184 7.754-16.184 15.728V43.33" transform="translate(141.266 181.343)" style="fill:none;stroke:#5a658e;stroke-width:2px"/>
|
||||
<path data-name="connector-head" d="m942.9 346.708-3.429 3.429-3.429-3.429" transform="translate(-871.049 -125.463)" style="fill:none;stroke:#5a658e;stroke-width:2px"/>
|
||||
</g>
|
||||
<g data-name="connector">
|
||||
<path data-name="connector" transform="translate(185.899 127.427)" style="fill:none;stroke:#5a658e;stroke-width:2px" d="M0 0v21.527"/>
|
||||
<path data-name="connector-head" d="m936.044 346.708 3.429 3.429 3.429-3.429" transform="translate(-753.574 -200.856)" style="fill:none;stroke:#5a658e;stroke-width:2px"/>
|
||||
</g>
|
||||
<g data-name="connector">
|
||||
<path data-name="connector" transform="translate(303.596 279.194)" style="fill:none;stroke:#5a658e;stroke-width:2px" d="M0 0v24.386"/>
|
||||
<path data-name="connector-head" d="m936.044 346.708 3.429 3.429 3.429-3.429" transform="translate(-635.877 -46.23)" style="fill:none;stroke:#5a658e;stroke-width:2px"/>
|
||||
</g>
|
||||
<g data-name="connector">
|
||||
<path data-name="connector" transform="translate(303.596 356.194)" style="fill:none;stroke:#5a658e;stroke-width:2px" d="M0 0v24.386"/>
|
||||
<path data-name="connector-head" d="m936.044 346.708 3.429 3.429 3.429-3.429" transform="translate(-635.877 30.77)" style="fill:none;stroke:#5a658e;stroke-width:2px"/>
|
||||
</g>
|
||||
<g transform="translate(231.301 -3)">
|
||||
<path data-name="step" d="M4 0h129a4 4 0 0 1 4 4v29H0V4a4 4 0 0 1 4-4z" transform="translate(2.699 3)" style="fill:rgba(0,154,255,.2)"/>
|
||||
<path d="M0 0h137v13a4 4 0 0 1-4 4H4a4 4 0 0 1-4-4V0z" transform="translate(2.699 36)" style="fill:#009aff"/>
|
||||
<rect width="26" height="4" rx="2" transform="translate(105.699 43)" style="fill:#153856"/>
|
||||
<path d="M7.72 12.3a4.576 4.576 0 1 1 4.58-4.58 4.581 4.581 0 0 1-4.58 4.58m0 1.144A5.72 5.72 0 1 0 2 7.72a5.72 5.72 0 0 0 5.72 5.72m2.344-7.96-3.48 3.48-1.2-1.2-.809.809 2 2 4.289-4.289z" transform="translate(9.843 36.144)" style="fill:#153856"/>
|
||||
<rect width="55" height="4" rx="2" transform="translate(34.699 17)" style="fill:#009aff"/>
|
||||
<circle cx="8" cy="8" r="8" transform="translate(10.699 11)" style="fill:#0099fe"/>
|
||||
</g>
|
||||
<g data-name="step" transform="translate(347.301 71)">
|
||||
<path data-name="step" d="M4 0h129a4 4 0 0 1 4 4v29H0V4a4 4 0 0 1 4-4z" transform="translate(2.699 3)" style="fill:rgba(0,154,255,.2)"/>
|
||||
<path data-name="step-status" d="M0 0h137v13a4 4 0 0 1-4 4H4a4 4 0 0 1-4-4V0z" transform="translate(2.699 36)" style="fill:#009aff"/>
|
||||
<rect data-name="time" width="26" height="4" rx="2" transform="translate(105.699 43)" style="fill:#153856"/>
|
||||
<path data-name="ico-status-completed" d="M7.72 12.3a4.576 4.576 0 1 1 4.58-4.58 4.581 4.581 0 0 1-4.58 4.58m0 1.144A5.72 5.72 0 1 0 2 7.72a5.72 5.72 0 0 0 5.72 5.72m2.344-7.96-3.48 3.48-1.2-1.2-.809.809 2 2 4.289-4.289z" transform="translate(9.843 36.144)" style="fill:#153856"/>
|
||||
<rect data-name="title" width="55" height="4" rx="2" transform="translate(34.699 17)" style="fill:#009aff"/>
|
||||
<circle data-name="ico-object-type" cx="8" cy="8" r="8" transform="translate(10.699 11)" style="fill:#0099fe"/>
|
||||
</g>
|
||||
<g data-name="step" transform="translate(115.301 71)">
|
||||
<path data-name="step" d="M4 0h129a4 4 0 0 1 4 4v29H0V4a4 4 0 0 1 4-4z" transform="translate(2.699 3)" style="fill:rgba(0,154,255,.2)"/>
|
||||
<path data-name="step-status" d="M0 0h137v13a4 4 0 0 1-4 4H4a4 4 0 0 1-4-4V0z" transform="translate(2.699 36)" style="fill:#009aff"/>
|
||||
<rect data-name="time" width="26" height="4" rx="2" transform="translate(105.699 43)" style="fill:#153856"/>
|
||||
<path data-name="ico-status-completed" d="M7.72 12.3a4.576 4.576 0 1 1 4.58-4.58 4.581 4.581 0 0 1-4.58 4.58m0 1.144A5.72 5.72 0 1 0 2 7.72a5.72 5.72 0 0 0 5.72 5.72m2.344-7.96-3.48 3.48-1.2-1.2-.809.809 2 2 4.289-4.289z" transform="translate(9.843 36.144)" style="fill:#153856"/>
|
||||
<rect data-name="title" width="55" height="4" rx="2" transform="translate(34.699 17)" style="fill:#009aff"/>
|
||||
<circle data-name="ico-object-type" cx="8" cy="8" r="8" transform="translate(10.699 11)" style="fill:#0099fe"/>
|
||||
</g>
|
||||
<g data-name="step" transform="translate(115.301 150)">
|
||||
<path data-name="step" d="M4 0h129a4 4 0 0 1 4 4v29H0V4a4 4 0 0 1 4-4z" transform="translate(2.699 3)" style="fill:rgba(0,154,255,.2)"/>
|
||||
<path data-name="step-status" d="M0 0h137v13a4 4 0 0 1-4 4H4a4 4 0 0 1-4-4V0z" transform="translate(2.699 36)" style="fill:#009aff"/>
|
||||
<rect data-name="time" width="26" height="4" rx="2" transform="translate(105.699 43)" style="fill:#153856"/>
|
||||
<path data-name="ico-status-completed" d="M7.72 12.3a4.576 4.576 0 1 1 4.58-4.58 4.581 4.581 0 0 1-4.58 4.58m0 1.144A5.72 5.72 0 1 0 2 7.72a5.72 5.72 0 0 0 5.72 5.72m2.344-7.96-3.48 3.48-1.2-1.2-.809.809 2 2 4.289-4.289z" transform="translate(9.843 36.144)" style="fill:#153856"/>
|
||||
<rect data-name="title" width="55" height="4" rx="2" transform="translate(34.699 17)" style="fill:#009aff"/>
|
||||
<circle data-name="ico-object-type" cx="8" cy="8" r="8" transform="translate(10.699 11)" style="fill:#0099fe"/>
|
||||
</g>
|
||||
<g data-name="step" transform="translate(231.301 225)">
|
||||
<path data-name="step" d="M4 0h129a4 4 0 0 1 4 4v29H0V4a4 4 0 0 1 4-4z" transform="translate(2.699 3)" style="fill:rgba(0,154,255,.2)"/>
|
||||
<path data-name="step-status" d="M0 0h137v13a4 4 0 0 1-4 4H4a4 4 0 0 1-4-4V0z" transform="translate(2.699 36)" style="fill:#009aff"/>
|
||||
<rect data-name="time" width="26" height="4" rx="2" transform="translate(105.699 43)" style="fill:#153856"/>
|
||||
<path data-name="ico-status-completed" d="M7.72 12.3a4.576 4.576 0 1 1 4.58-4.58 4.581 4.581 0 0 1-4.58 4.58m0 1.144A5.72 5.72 0 1 0 2 7.72a5.72 5.72 0 0 0 5.72 5.72m2.344-7.96-3.48 3.48-1.2-1.2-.809.809 2 2 4.289-4.289z" transform="translate(9.843 36.144)" style="fill:#153856"/>
|
||||
<rect data-name="title" width="55" height="4" rx="2" transform="translate(34.699 17)" style="fill:#009aff"/>
|
||||
<circle data-name="ico-object-type" cx="8" cy="8" r="8" transform="translate(10.699 11)" style="fill:#0099fe"/>
|
||||
</g>
|
||||
<g data-name="step" transform="translate(231.301 303)">
|
||||
<path data-name="step" d="M4 0h129a4 4 0 0 1 4 4v29H0V4a4 4 0 0 1 4-4z" transform="translate(2.699 3)" style="fill:rgba(0,154,255,.2)"/>
|
||||
<path data-name="step-status" d="M0 0h137v13a4 4 0 0 1-4 4H4a4 4 0 0 1-4-4V0z" transform="translate(2.699 36)" style="fill:#009aff"/>
|
||||
<rect data-name="time" width="26" height="4" rx="2" transform="translate(105.699 43)" style="fill:#153856"/>
|
||||
<path data-name="ico-status-completed" d="M7.72 12.3a4.576 4.576 0 1 1 4.58-4.58 4.581 4.581 0 0 1-4.58 4.58m0 1.144A5.72 5.72 0 1 0 2 7.72a5.72 5.72 0 0 0 5.72 5.72m2.344-7.96-3.48 3.48-1.2-1.2-.809.809 2 2 4.289-4.289z" transform="translate(9.843 36.144)" style="fill:#153856"/>
|
||||
<rect data-name="title" width="55" height="4" rx="2" transform="translate(34.699 17)" style="fill:#009aff"/>
|
||||
<circle data-name="ico-object-type" cx="8" cy="8" r="8" transform="translate(10.699 11)" style="fill:#0099fe"/>
|
||||
</g>
|
||||
<g data-name="step" transform="translate(231.301 381)">
|
||||
<path data-name="step" d="M4 0h129a4 4 0 0 1 4 4v29H0V4a4 4 0 0 1 4-4z" transform="translate(2.699 3)" style="fill:rgba(20,170,140,.2)"/>
|
||||
<path data-name="step-status" d="M0 0h137v13a4 4 0 0 1-4 4H4a4 4 0 0 1-4-4V0z" transform="translate(2.699 36)" style="fill:#14a98b"/>
|
||||
<rect data-name="time" width="26" height="4" rx="2" transform="translate(105.699 43)" style="fill:#193a3e"/>
|
||||
<path d="M7.72 12.3a4.576 4.576 0 1 1 4.58-4.58 4.582 4.582 0 0 1-4.58 4.58m0 1.144A5.72 5.72 0 1 0 2 7.72a5.72 5.72 0 0 0 5.72 5.72m-.153-8.384 2.26 2.26a.572.572 0 0 1 0 .809l-2.26 2.26a.572.572 0 0 1-.976-.4V5.461a.572.572 0 0 1 .976-.4" transform="translate(9.843 36.144)" style="fill:#193b3f"/>
|
||||
<rect data-name="title" width="55" height="4" rx="2" transform="translate(34.699 17)" style="fill:#14a98b"/>
|
||||
<circle data-name="ico-object-type" cx="8" cy="8" r="8" transform="translate(10.699 11)" style="fill:#14a88a"/>
|
||||
</g>
|
||||
<g data-name="step" transform="translate(-2.699 225)">
|
||||
<path data-name="step" d="M4 0h129a4 4 0 0 1 4 4v29H0V4a4 4 0 0 1 4-4z" transform="translate(2.699 3)" style="fill:rgba(158,84,204,.2)"/>
|
||||
<path data-name="step-status" d="M0 0h137v13a4 4 0 0 1-4 4H4a4 4 0 0 1-4-4V0z" transform="translate(2.699 36)" style="fill:#9e54cc"/>
|
||||
<rect data-name="time" width="26" height="4" rx="2" transform="translate(105.699 43)" style="fill:#34294c"/>
|
||||
<path d="M7.72 12.3a4.576 4.576 0 1 1 4.58-4.58 4.582 4.582 0 0 1-4.58 4.58m0 1.144A5.72 5.72 0 1 0 2 7.72a5.72 5.72 0 0 0 5.72 5.72m2.86-8.009H4.86v1.145h5.72zm0 1.716H4.86v1.146h5.72zm0 1.716H4.86v1.144h5.72z" transform="translate(9.843 36.144)" style="fill:#352a4c"/>
|
||||
<rect data-name="title" width="55" height="4" rx="2" transform="translate(34.699 17)" style="fill:#9b51c9"/>
|
||||
<circle data-name="ico-object-type" cx="8" cy="8" r="8" transform="translate(10.699 11)" style="fill:#9c52ca"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 11 KiB |
File diff suppressed because one or more lines are too long
65
src/app/webapp-common/assets/plotly-2.9.0.min.js
vendored
Normal file
65
src/app/webapp-common/assets/plotly-2.9.0.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -5,8 +5,8 @@
|
||||
[placeholder]="searchPlaceholder$ | async"
|
||||
[hideIcons]="true"
|
||||
[minimumChars]="minChars"
|
||||
(valueChanged)="onSearchValueChanged($event)"
|
||||
(focusout)="onSearchFocusOut()"
|
||||
(valueChanged)="onSearchValueChanged($event)"
|
||||
>
|
||||
<i
|
||||
class="regexp al-ico-regex pointer"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {Component, OnInit, ViewChild} from '@angular/core';
|
||||
import {ActivatedRoute, Router, NavigationEnd} from '@angular/router';
|
||||
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit, ViewChild} from '@angular/core';
|
||||
import {ActivatedRoute, NavigationEnd, Router} from '@angular/router';
|
||||
import {Store} from '@ngrx/store';
|
||||
import {SetIsSearching, setSearchQuery} from '../../common-search.actions';
|
||||
import {ICommonSearchState, selectIsSearching, selectPlaceholder, selectSearchQuery} from '../../common-search.reducer';
|
||||
@@ -10,7 +10,8 @@ import {SearchComponent} from '../../../shared/ui-components/inputs/search/searc
|
||||
@Component({
|
||||
selector : 'sm-common-search',
|
||||
templateUrl: './common-search.component.html',
|
||||
styleUrls : ['./common-search.component.scss']
|
||||
styleUrls : ['./common-search.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class CommonSearchComponent implements OnInit {
|
||||
public searchQuery$: Observable<ICommonSearchState['searchQuery']>;
|
||||
@@ -26,7 +27,7 @@ export class CommonSearchComponent implements OnInit {
|
||||
private queryString: string;
|
||||
minChars = 3;
|
||||
|
||||
constructor(private store: Store<any>, private router: Router, private route: ActivatedRoute) {}
|
||||
constructor(private store: Store<any>, private router: Router, private route: ActivatedRoute, private cdr: ChangeDetectorRef) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.searchQuery$ = this.store.select(selectSearchQuery).pipe(tap(searchQuery => this.regExp = searchQuery?.regExp));
|
||||
@@ -39,9 +40,10 @@ export class CommonSearchComponent implements OnInit {
|
||||
setTimeout(this.setSearchActive.bind(this));
|
||||
}
|
||||
|
||||
onSearchValueChanged(query) {
|
||||
onSearchValueChanged(query: string) {
|
||||
this.queryString = query;
|
||||
this.store.dispatch(setSearchQuery({query, regExp: this.regExp}));
|
||||
this.cdr.detectChanges();
|
||||
this.store.dispatch(setSearchQuery({query: this.regExp? this.queryString: this.queryString.trim(), regExp: this.regExp}));
|
||||
}
|
||||
|
||||
openSearch() {
|
||||
@@ -66,6 +68,7 @@ export class CommonSearchComponent implements OnInit {
|
||||
}
|
||||
}
|
||||
this.searchActive = showSearch;
|
||||
this.cdr.detectChanges();
|
||||
}
|
||||
|
||||
clearSearch() {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@use '~@angular/material' as mat;
|
||||
@use '@angular/material' as mat;
|
||||
@import "angular-notifier/styles.scss";
|
||||
@import "angular-notifier/styles/themes/theme-material.scss";
|
||||
@import "shared/ui-components/styles/notifications";
|
||||
@@ -39,6 +39,7 @@ $sm-theme: mat.define-light-theme($sm-theme-primary, $sm-theme-accent, $sm-theme
|
||||
|
||||
@include mat.form-field-color($light-theme);
|
||||
@include mat.progress-spinner-theme($light-theme);
|
||||
@include mat.progress-bar-theme($light-theme);
|
||||
|
||||
.dark-theme {
|
||||
@include mat.core-theme($dark-theme);
|
||||
@@ -51,7 +52,6 @@ $sm-theme: mat.define-light-theme($sm-theme-primary, $sm-theme-accent, $sm-theme
|
||||
@include mat.datepicker-color($light-theme);
|
||||
@include mat.pseudo-checkbox-color($light-theme);
|
||||
@include mat.divider-color($light-theme);
|
||||
@include mat.progress-bar-theme($light-theme);
|
||||
|
||||
.mat-checkbox-frame,
|
||||
.mat-radio-outer-circle {
|
||||
@@ -71,6 +71,7 @@ $sm-theme: mat.define-light-theme($sm-theme-primary, $sm-theme-accent, $sm-theme
|
||||
.light-theme .mat-radio-button.mat-radio-disabled .mat-radio-inner-circle {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
.link {
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
@@ -92,7 +93,6 @@ $sm-theme: mat.define-light-theme($sm-theme-primary, $sm-theme-accent, $sm-theme
|
||||
@include mat.datepicker-color($light-theme);
|
||||
@include mat.pseudo-checkbox-color($light-theme);
|
||||
@include mat.divider-color($light-theme);
|
||||
@include mat.progress-bar-theme($light-theme);
|
||||
|
||||
.mat-checkbox-frame,
|
||||
.mat-radio-outer-circle {
|
||||
@@ -159,17 +159,31 @@ h4.al-header {
|
||||
h5.al-header {
|
||||
font-weight: normal;
|
||||
}
|
||||
span.highlight-text{
|
||||
|
||||
span.highlight-text {
|
||||
background: $neon-yellow-betterinchrome;
|
||||
&.current-match{
|
||||
border: 1px solid darken($neon-yellow-betterinchrome, 5%);
|
||||
border-radius: 4px;
|
||||
padding: 0 2px;
|
||||
|
||||
&.current-match {
|
||||
background: #f5d655;
|
||||
border: 1px solid darken(#f5d655, 15%);
|
||||
}
|
||||
}
|
||||
|
||||
hr {
|
||||
border-top: 1px solid rgba(0, 0, 0, .1);
|
||||
}
|
||||
|
||||
.pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.cursor-default {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.pointer-events-none {
|
||||
pointer-events: none;
|
||||
}
|
||||
@@ -272,14 +286,17 @@ button {
|
||||
.color-neon-yellow {
|
||||
color: $neon-yellow;
|
||||
}
|
||||
|
||||
.background-neon-green {
|
||||
background-color: $neon-green !important;
|
||||
background: $neon-green !important;
|
||||
}
|
||||
|
||||
.background-neon-yellow {
|
||||
background-color: $neon-yellow !important;
|
||||
background: $neon-yellow !important;
|
||||
}
|
||||
|
||||
.color-neon-green {
|
||||
color: $neon-green;
|
||||
}
|
||||
@@ -287,6 +304,7 @@ button {
|
||||
.border-radius {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.grabbing {
|
||||
cursor: grab;
|
||||
|
||||
@@ -758,6 +776,6 @@ button.btn.button-outline-dark {
|
||||
}
|
||||
|
||||
.ace_placeholder {
|
||||
font-family: SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;
|
||||
font-family: SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace;
|
||||
color: $blue-grey !important;
|
||||
}
|
||||
|
||||
@@ -24,11 +24,11 @@ export const ICONS = {
|
||||
DATASET: 'fa-puzzle-piece',
|
||||
TASK: 'fa-briefcase',
|
||||
MODEL: 'fa-cube',
|
||||
SHOW: 'fa-eye',
|
||||
SHOW: 'al-ico-show',
|
||||
ARCHIVE: 'al-ico-archive',
|
||||
RESTORE: 'al-ico-restore',
|
||||
COMPARE: 'al-ico-compare',
|
||||
HIDE: 'fa-eye-slash',
|
||||
HIDE: 'al-ico-hide',
|
||||
COMPLETED: 'fa-circle',
|
||||
ABORTED: 'fa-circle',
|
||||
UNKNOWN: 'fa-question-circle',
|
||||
@@ -54,7 +54,7 @@ export const ICONS = {
|
||||
LOG: 'fa-file-text-o',
|
||||
METRICS: 'fa-chart-area',
|
||||
TOKEN: 'fa-key',
|
||||
EDIT: 'fa-pencil-square-o',
|
||||
EDIT: 'al-ico-edit',
|
||||
EDITABLE: 'fa-pencil',
|
||||
RESET: 'al-ico-reset',
|
||||
CLONE: 'al-ico-clone',
|
||||
@@ -65,6 +65,7 @@ export const ICONS = {
|
||||
SHARE: 'al-ico-shared-item',
|
||||
ARROW_DOWN: 'al-ico-ico-chevron-down',
|
||||
ARROW_UP: 'al-ico-ico-chevron-up',
|
||||
RUN: 'al-ico-run',
|
||||
};
|
||||
|
||||
export type IconNames = keyof typeof ICONS;
|
||||
|
||||
@@ -10,7 +10,7 @@ export const updateS3Credential = createAction(
|
||||
);
|
||||
export const createCredential = createAction(
|
||||
AUTH_PREFIX + 'CREATE_CREDENTIAL (API)',
|
||||
props<{workspace: GetCurrentUserResponseUserObjectCompany; openCredentialsPopup?: boolean}>()
|
||||
props<{workspace: GetCurrentUserResponseUserObjectCompany; openCredentialsPopup?: boolean; label?: string}>()
|
||||
);
|
||||
export const addCredential = createAction(
|
||||
AUTH_PREFIX + 'ADD_CREDENTIAL',
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {MessageSeverityEnum, VIEW_PREFIX} from '../../../app.constants';
|
||||
import {MessageSeverityEnum, VIEW_PREFIX} from '~/app.constants';
|
||||
import {createAction, props} from '@ngrx/store';
|
||||
import {omit} from 'lodash/fp';
|
||||
import {HttpErrorResponse} from '@angular/common/http';
|
||||
@@ -37,12 +37,12 @@ export const setBackdrop = createAction(
|
||||
|
||||
export const activeLoader = createAction(
|
||||
VIEW_PREFIX + '[activate loader]',
|
||||
(endpoint: string) => ({endpoint})
|
||||
(endpoint: string) => ({endpoint, noPreferences: true})
|
||||
);
|
||||
|
||||
export const deactivateLoader = createAction(
|
||||
VIEW_PREFIX + '[deactivate loader]',
|
||||
(endpoint: string) => ({endpoint})
|
||||
(endpoint: string) => ({endpoint, noPreferences: true})
|
||||
);
|
||||
|
||||
|
||||
|
||||
@@ -1,22 +1,23 @@
|
||||
import {createAction, props} from '@ngrx/store';
|
||||
import {Project} from '../../../business-logic/model/projects/project';
|
||||
import {ProjectsUpdateRequest} from '../../../business-logic/model/projects/projectsUpdateRequest';
|
||||
import {ModelsPublishManyResponse} from '../../../business-logic/model/models/modelsPublishManyResponse';
|
||||
import {ModelsArchiveManyResponse} from '../../../business-logic/model/models/modelsArchiveManyResponse';
|
||||
import {ModelsDeleteManyResponse} from '../../../business-logic/model/models/modelsDeleteManyResponse';
|
||||
import {Project} from '~/business-logic/model/projects/project';
|
||||
import {ProjectsUpdateRequest} from '~/business-logic/model/projects/projectsUpdateRequest';
|
||||
import {ModelsPublishManyResponse} from '~/business-logic/model/models/modelsPublishManyResponse';
|
||||
import {ModelsArchiveManyResponse} from '~/business-logic/model/models/modelsArchiveManyResponse';
|
||||
import {ModelsDeleteManyResponse} from '~/business-logic/model/models/modelsDeleteManyResponse';
|
||||
import {archivedSelectedModels} from '@common/models/actions/models-menu.actions';
|
||||
import {TasksResetManyResponse} from '../../../business-logic/model/tasks/tasksResetManyResponse';
|
||||
import {TasksEnqueueManyResponse} from '../../../business-logic/model/tasks/tasksEnqueueManyResponse';
|
||||
import {TasksArchiveManyResponse} from '../../../business-logic/model/tasks/tasksArchiveManyResponse';
|
||||
import {TasksPublishManyResponse} from '../../../business-logic/model/tasks/tasksPublishManyResponse';
|
||||
import {TasksStopManyResponse} from '../../../business-logic/model/tasks/tasksStopManyResponse';
|
||||
import {EntityTypeEnum} from '../../../shared/constants/non-common-consts';
|
||||
import {TasksResetManyResponse} from '~/business-logic/model/tasks/tasksResetManyResponse';
|
||||
import {TasksEnqueueManyResponse} from '~/business-logic/model/tasks/tasksEnqueueManyResponse';
|
||||
import {TasksArchiveManyResponse} from '~/business-logic/model/tasks/tasksArchiveManyResponse';
|
||||
import {TasksPublishManyResponse} from '~/business-logic/model/tasks/tasksPublishManyResponse';
|
||||
import {TasksStopManyResponse} from '~/business-logic/model/tasks/tasksStopManyResponse';
|
||||
import {EntityTypeEnum} from '~/shared/constants/non-common-consts';
|
||||
import {MetricColumn} from '@common/shared/utils/tableParamEncode';
|
||||
import {ProjectStatsGraphData} from '@common/core/reducers/projects.reducer';
|
||||
|
||||
export const PROJECTS_PREFIX = '[ROOT_PROJECTS] ';
|
||||
export const SET_PROJECTS = PROJECTS_PREFIX + 'SET_PROJECTS';
|
||||
export const RESET_PROJECTS = PROJECTS_PREFIX + 'RESET_PROJECTS';
|
||||
export const REFETCH_PROJECTS = PROJECTS_PREFIX + 'REFETCH_PROJECTS';
|
||||
export const SET_LAST_UPDATE = PROJECTS_PREFIX + 'SET_LAST_UPDATE';
|
||||
export const RESET_SELECTED_PROJECT = PROJECTS_PREFIX + 'RESET_SELECTED_PROJECT';
|
||||
export const RESET_PROJECT_SELECTION = PROJECTS_PREFIX + 'RESET_PROJECT_SELECTION';
|
||||
@@ -31,6 +32,8 @@ export const getAllSystemProjects = createAction(
|
||||
PROJECTS_PREFIX + 'GET_PROJECTS'
|
||||
);
|
||||
|
||||
|
||||
|
||||
export const updateProject = createAction(
|
||||
UPDATE_PROJECT,
|
||||
props<{ id: string; changes: Partial<ProjectsUpdateRequest> }>()
|
||||
@@ -42,20 +45,25 @@ export const setAllProjects = createAction(
|
||||
);
|
||||
|
||||
export const resetProjects = createAction(RESET_PROJECTS);
|
||||
export const refetchProjects = createAction(REFETCH_PROJECTS);
|
||||
|
||||
export const setLastUpdate = createAction(
|
||||
SET_LAST_UPDATE,
|
||||
props<{ lastUpdate: string }>());
|
||||
|
||||
export const updateProjectCompleted = createAction(
|
||||
PROJECTS_PREFIX + 'UPDATE_PROJECT_COMPLETED'
|
||||
PROJECTS_PREFIX + 'UPDATE_PROJECT_COMPLETED',
|
||||
props<{id: string; changes: Partial<Project>}>()
|
||||
);
|
||||
|
||||
export const setSelectedProjectId = createAction(
|
||||
PROJECTS_PREFIX + 'SET_SELECTED_PROJECT_ID',
|
||||
props<{ projectId: string; example?: boolean }>()
|
||||
);
|
||||
|
||||
export const deletedProjectFromRoot = createAction(
|
||||
PROJECTS_PREFIX + 'DELETE_PROJECT_FROM_ROOT',
|
||||
props<{ project: Project }>()
|
||||
);
|
||||
export const setSelectedProject = createAction(
|
||||
PROJECTS_PREFIX + 'SET_SELECTED_PROJECT',
|
||||
props<{ project: Project }>()
|
||||
@@ -87,6 +95,10 @@ export const getCompanyTags = createAction(
|
||||
PROJECTS_PREFIX + '[get company tags]'
|
||||
);
|
||||
|
||||
export const getProjectsTags = createAction(
|
||||
PROJECTS_PREFIX + '[get projects tags]'
|
||||
);
|
||||
|
||||
export const setTagsFilterByProject = createAction(
|
||||
PROJECTS_PREFIX + '[set tags filter by project]',
|
||||
props<{ tagsFilterByProject: boolean }>()
|
||||
@@ -102,6 +114,16 @@ export const setCompanyTags = createAction(
|
||||
props<{ tags: string[]; systemTags: string[] }>()
|
||||
);
|
||||
|
||||
export const setAllProjectTags = createAction(
|
||||
PROJECTS_PREFIX + '[set all projects tags]',
|
||||
props<{ tags: string[]; systemTags: string[] }>()
|
||||
);
|
||||
|
||||
export const addAllProjectTags = createAction(
|
||||
PROJECTS_PREFIX + '[add all projects tags]',
|
||||
props<{ tags: string[]; systemTags: string[] }>()
|
||||
);
|
||||
|
||||
export const openTagColorsMenu = createAction(
|
||||
PROJECTS_PREFIX + '[open tag colors]'
|
||||
);
|
||||
|
||||
@@ -4,7 +4,7 @@ import {ApiAuthService} from '~/business-logic/api-services/auth.service';
|
||||
import * as authActions from '../actions/common-auth.actions';
|
||||
import {requestFailed} from '../actions/http.actions';
|
||||
import {activeLoader, deactivateLoader, setServerError} from '../actions/layout.actions';
|
||||
import {catchError, filter, finalize, map, mergeMap, switchMap, take, tap, throttleTime, withLatestFrom} from 'rxjs/operators';
|
||||
import {catchError, filter, finalize, map, mergeMap, switchMap, throttleTime, withLatestFrom} from 'rxjs/operators';
|
||||
import {AuthGetCredentialsResponse} from '~/business-logic/model/auth/authGetCredentialsResponse';
|
||||
import {select, Store} from '@ngrx/store';
|
||||
import {selectCurrentUser} from '../reducers/users-reducer';
|
||||
@@ -15,8 +15,6 @@ import {EMPTY, of} from 'rxjs';
|
||||
import {SignResponse} from '@common/settings/admin/base-admin.service';
|
||||
import {S3AccessResolverComponent} from '@common/layout/s3-access-resolver/s3-access-resolver.component';
|
||||
import {MatDialog} from '@angular/material/dialog';
|
||||
import {CreateCredentialDialogComponent} from '~/features/settings/containers/admin/create-credential-dialog/create-credential-dialog.component';
|
||||
import {resetCredential} from '../actions/common-auth.actions';
|
||||
|
||||
@Injectable()
|
||||
export class CommonAuthEffects {
|
||||
@@ -29,8 +27,7 @@ export class CommonAuthEffects {
|
||||
private store: Store<any>,
|
||||
private adminService: AdminService,
|
||||
private matDialog: MatDialog
|
||||
) {
|
||||
}
|
||||
) {}
|
||||
|
||||
activeLoader = createEffect(() => this.actions.pipe(
|
||||
ofType(authActions.getAllCredentials, authActions.createCredential),
|
||||
@@ -64,8 +61,7 @@ export class CommonAuthEffects {
|
||||
|
||||
createCredential = createEffect(() => this.actions.pipe(
|
||||
ofType(authActions.createCredential),
|
||||
mergeMap(action => this.credentialsApi.authCreateCredentials({}).pipe(
|
||||
tap( ({credentials}) => action.openCredentialsPopup && this.openCredentialsPopup(credentials, action)),
|
||||
mergeMap(action => this.credentialsApi.authCreateCredentials({label: action.label}).pipe(
|
||||
mergeMap(({credentials}) => [
|
||||
authActions.addCredential({newCredential: credentials, workspaceId: action.workspace?.id}),
|
||||
deactivateLoader(action.type)
|
||||
@@ -141,11 +137,4 @@ export class CommonAuthEffects {
|
||||
);
|
||||
})
|
||||
));
|
||||
|
||||
openCredentialsPopup(credentials, action): void {
|
||||
this.matDialog.open(CreateCredentialDialogComponent,
|
||||
{data: {credentials, ...(action.workspace && {workspace: action.workspace.name})}}
|
||||
).afterClosed().pipe(take(1)).subscribe(() => this.store.dispatch(resetCredential()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,13 +5,13 @@ import {ApiProjectsService} from '~/business-logic/api-services/projects.service
|
||||
import * as actions from '../actions/projects.actions';
|
||||
import {
|
||||
fetchGraphData, getAllSystemProjects,
|
||||
getCompanyTags,
|
||||
getCompanyTags, getProjectsTags,
|
||||
getTags,
|
||||
openMoreInfoPopup,
|
||||
openTagColorsMenu,
|
||||
openTagColorsMenu, refetchProjects,
|
||||
resetProjects, resetProjectSelection,
|
||||
setCompanyTags,
|
||||
setGraphData, setLastUpdate,
|
||||
setGraphData, setLastUpdate, setAllProjectTags,
|
||||
setTags
|
||||
} from '../actions/projects.actions';
|
||||
|
||||
@@ -104,8 +104,8 @@ export class ProjectsEffects {
|
||||
switchMap((action) =>
|
||||
this.projectsApi.projectsUpdate({project: action.id, ...action.changes})
|
||||
.pipe(
|
||||
mergeMap(() => [
|
||||
actions.updateProjectCompleted()
|
||||
mergeMap(res => [
|
||||
actions.updateProjectCompleted({id: action.id, changes: res?.fields || action.changes})
|
||||
]),
|
||||
catchError(err => [
|
||||
requestFailed(err),
|
||||
@@ -123,6 +123,7 @@ export class ProjectsEffects {
|
||||
})
|
||||
), {dispatch: false});
|
||||
|
||||
//getAll but not projects'
|
||||
getAllTags = createEffect(() => this.actions$.pipe(
|
||||
ofType(getCompanyTags),
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
@@ -134,6 +135,17 @@ export class ProjectsEffects {
|
||||
)
|
||||
));
|
||||
|
||||
getProjectsTags = createEffect(() => this.actions$.pipe(
|
||||
ofType(getProjectsTags),
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
switchMap(() => this.projectsApi.projectsGetProjectTags({filter: {system_tags: ['pipeline']}})
|
||||
.pipe(
|
||||
map((res: OrganizationGetTagsResponse) => setAllProjectTags({tags: res.tags, systemTags: res.system_tags})),
|
||||
catchError(error => [requestFailed(error)])
|
||||
)
|
||||
)
|
||||
));
|
||||
|
||||
getTagsEffect = createEffect(() => this.actions$.pipe(
|
||||
ofType(getTags),
|
||||
withLatestFrom(this.store.select(selectRouterParams).pipe(
|
||||
@@ -212,7 +224,7 @@ export class ProjectsEffects {
|
||||
));
|
||||
|
||||
resetRootProjects = createEffect(() => this.actions$.pipe(
|
||||
ofType(setActiveWorkspace),
|
||||
ofType(setActiveWorkspace, refetchProjects),
|
||||
mergeMap(() => [
|
||||
resetProjects(),
|
||||
getAllSystemProjects()
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import {Injectable} from '@angular/core';
|
||||
import {ActivatedRoute, Params, Router} from '@angular/router';
|
||||
import {ActivatedRoute, NavigationExtras, Params, Router} from '@angular/router';
|
||||
import {Actions, createEffect, ofType} from '@ngrx/effects';
|
||||
import {uniq} from 'lodash/fp';
|
||||
import {map, tap} from 'rxjs/operators';
|
||||
import {NAVIGATION_ACTIONS} from '~/app.constants';
|
||||
import {encodeFilters, encodeOrder} from '../../shared/utils/tableParamEncode';
|
||||
import {NavigateTo, NavigationEnd, SetRouterSegments, setURLParams} from '../actions/router.actions';
|
||||
import {from} from 'rxjs';
|
||||
|
||||
|
||||
@Injectable()
|
||||
@@ -34,22 +35,21 @@ export class RouterEffects {
|
||||
|
||||
setTableParams = createEffect(() => this.actions$.pipe(
|
||||
ofType(setURLParams),
|
||||
map((action) => {
|
||||
tap((action) => {
|
||||
const firstUpdate = !this.route.snapshot.queryParams.order;
|
||||
this.router.navigate(
|
||||
[],
|
||||
{
|
||||
relativeTo: this.route,
|
||||
replaceUrl: firstUpdate,
|
||||
queryParamsHandling: action.update ? 'merge' : '',
|
||||
queryParams: {
|
||||
...(action.columns && {columns: uniq(action.columns)}),
|
||||
...(action.orders && {order: encodeOrder(action.orders)}),
|
||||
...(action.filters && {filter: encodeFilters(action.filters)}),
|
||||
...(action.isArchived && {archive: true}),
|
||||
...(action.isDeep && {deep: true})
|
||||
}
|
||||
});
|
||||
const extra = {
|
||||
// relativeTo: this.route,
|
||||
...(firstUpdate && {replaceUrl: true}),
|
||||
...(action.update && {queryParamsHandling: 'merge'}),
|
||||
queryParams: {
|
||||
...(action.columns && {columns: uniq(action.columns)}),
|
||||
...(action.orders && {order: encodeOrder(action.orders)}),
|
||||
...(action.filters && {filter: encodeFilters(action.filters)}),
|
||||
...(action.isArchived !== undefined && {archive: action.isArchived ? 'true' : null}),
|
||||
...(action.isDeep && {deep: true})
|
||||
}
|
||||
} as NavigationExtras;
|
||||
this.router.navigate([], extra);
|
||||
})
|
||||
), {dispatch: false});
|
||||
|
||||
|
||||
@@ -3,6 +3,10 @@ import {merge, pick} from 'lodash/fp';
|
||||
import {setPreferences} from '../actions/users.actions';
|
||||
import {UserPreferences} from '@common/user-preferences';
|
||||
|
||||
interface extAction extends Action {
|
||||
noPreferences?: boolean;
|
||||
}
|
||||
|
||||
const firstRun = {};
|
||||
|
||||
export function createUserPrefReducer(
|
||||
@@ -11,7 +15,7 @@ export function createUserPrefReducer(
|
||||
actionsPrefix: string[],
|
||||
userPreferences: UserPreferences,
|
||||
reducer: ActionReducer<any>
|
||||
): ActionReducer<any, Action> {
|
||||
): ActionReducer<any, extAction> {
|
||||
|
||||
if (firstRun[key] === undefined) {
|
||||
firstRun[key] = true;
|
||||
@@ -32,7 +36,7 @@ export function createUserPrefReducer(
|
||||
}
|
||||
|
||||
// filter unchanged state.
|
||||
if (state === nextState) {
|
||||
if (action.noPreferences || state === nextState) {
|
||||
return nextState;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
updateAllCredentials,
|
||||
updateS3Credential
|
||||
} from '../actions/common-auth.actions';
|
||||
import {CredentialKey} from '../../../business-logic/model/auth/credentialKey';
|
||||
import {CredentialKey} from '~/business-logic/model/auth/credentialKey';
|
||||
import {inBucket} from '@common/settings/admin/base-admin.service';
|
||||
import {filter, map, timeoutWith} from 'rxjs/operators';
|
||||
|
||||
@@ -66,8 +66,10 @@ export const selectSignedUrl = url => createSelector(selectAuth, state => state.
|
||||
export const getSignedUrlOrOrigin$ = (url: string, store: Store) => store.pipe(
|
||||
select(selectSignedUrl(url)),
|
||||
filter(signed => !!signed?.signed),
|
||||
map(signed => signed?.signed || url),
|
||||
timeoutWith(600, store.select(selectSignedUrl(url)).pipe(map(signed => signed?.signed || url))),
|
||||
map(signed => signed?.signed),
|
||||
timeoutWith(900, store.select(selectSignedUrl(url))
|
||||
.pipe(map(signed => signed?.signed || url))
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import {createSelector} from '@ngrx/store';
|
||||
import * as projectsActions from '../actions/projects.actions';
|
||||
import {
|
||||
addAllProjectTags,
|
||||
setAllProjects,
|
||||
setCompanyTags,
|
||||
setGraphData,
|
||||
setLastUpdate,
|
||||
setMetricVariant,
|
||||
setMetricVariant, setAllProjectTags,
|
||||
setTagColors,
|
||||
setTags,
|
||||
setTagsFilterByProject,
|
||||
@@ -35,6 +36,7 @@ export interface RootProjects {
|
||||
archive: boolean;
|
||||
deep: boolean;
|
||||
projectTags: string[];
|
||||
allProjectsTags: string[];
|
||||
companyTags: string[];
|
||||
systemTags: string[];
|
||||
tagsColors: { [tag: string]: TagColor };
|
||||
@@ -50,6 +52,7 @@ const initRootProjects: RootProjects = {
|
||||
archive: false,
|
||||
deep: false,
|
||||
projectTags: [],
|
||||
allProjectsTags: [],
|
||||
companyTags: [],
|
||||
systemTags: [],
|
||||
tagsColors: {},
|
||||
@@ -69,6 +72,7 @@ export const selectIsDeepMode = createSelector(projects, state => state.deep);
|
||||
export const selectTagsFilterByProject = createSelector(projects, state => state.tagsFilterByProject);
|
||||
export const selectProjectTags = createSelector(projects, state => state.projectTags);
|
||||
export const selectCompanyTags = createSelector(projects, state => state.companyTags);
|
||||
export const selectAllProjectsTagsTags = createSelector(projects, state => state.allProjectsTags);
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
export const selectProjectSystemTags = createSelector(projects, state => getSystemTags({system_tags: state.systemTags} as ITableExperiment));
|
||||
export const selectTagsColors = createSelector(projects, state => state.tagsColors);
|
||||
@@ -117,10 +121,18 @@ export const projectsReducer = (state: RootProjects = initRootProjects, action)
|
||||
}
|
||||
case projectsActions.setSelectedProject.type:
|
||||
return {...state, selectedProject: action.project};
|
||||
case projectsActions.deletedProjectFromRoot.type:
|
||||
const projectIdsToDelete = [action.project.id].concat(action.project.sub_projects.map(project=> project.id))
|
||||
return {...state, projects: state.projects.filter(project=> !projectIdsToDelete.includes(project.id))};
|
||||
case projectsActions.resetSelectedProject.type:
|
||||
return {...state, selectedProject: initRootProjects.selectedProject};
|
||||
case projectsActions.updateProject.type: {
|
||||
return {...state, selectedProject: {...state.selectedProject, ...(action as ReturnType<typeof projectsActions.updateProject>).changes}};
|
||||
case projectsActions.updateProjectCompleted.type: {
|
||||
const payload = action as ReturnType<typeof projectsActions.updateProjectCompleted>;
|
||||
return {
|
||||
...state,
|
||||
selectedProject: {...state.selectedProject, ...payload.changes},
|
||||
projects: state.projects.map(project => project.id === payload.id ? project : {...project, ...payload.changes})
|
||||
};
|
||||
}
|
||||
case projectsActions.setArchive.type:
|
||||
return {...state, archive: action.archive};
|
||||
@@ -132,6 +144,10 @@ export const projectsReducer = (state: RootProjects = initRootProjects, action)
|
||||
return {...state, tagsFilterByProject: action.tagsFilterByProject};
|
||||
case setCompanyTags.type:
|
||||
return {...state, companyTags: action.tags, systemTags: action.systemTags};
|
||||
case setAllProjectTags.type:
|
||||
return {...state, allProjectsTags: action.tags};
|
||||
case addAllProjectTags.type:
|
||||
return {...state, allProjectsTags: Array.from(new Set(state.allProjectsTags.concat(action.tags))).sort()};
|
||||
case setTagColors.type:
|
||||
return {...state, tagsColors: {...state.tagsColors, [action.tag]: action.colors}};
|
||||
case setMetricVariant.type: {
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import {Injectable} from '@angular/core';
|
||||
import {act, Actions, Effect, ofType} from '@ngrx/effects';
|
||||
import {Actions, createEffect, ofType} from '@ngrx/effects';
|
||||
import {activeLoader, deactivateLoader} from '../core/actions/layout.actions';
|
||||
import {
|
||||
SearchActivate, SearchClear, searchExperiments, searchModels, searchProjects, searchSetTerm, searchStart, SetExperimentsResults, SetModelsResults, SetProjectsResults
|
||||
} from './dashboard-search.actions';
|
||||
import {EXPERIMENT_SEARCH_ONLY_FIELDS, SEARCH_ACTIONS, SEARCH_PAGE_SIZE} from './dashboard-search.consts';
|
||||
import {ApiProjectsService} from '../../business-logic/api-services/projects.service';
|
||||
import {ApiProjectsService} from '~/business-logic/api-services/projects.service';
|
||||
import {requestFailed} from '../core/actions/http.actions';
|
||||
import {Store} from '@ngrx/store';
|
||||
import {selectActiveSearch} from './dashboard-search.reducer';
|
||||
import {ProjectsGetAllExRequest} from '../../business-logic/model/projects/projectsGetAllExRequest';
|
||||
import {ApiTasksService} from '../../business-logic/api-services/tasks.service';
|
||||
import {ApiModelsService} from '../../business-logic/api-services/models.service';
|
||||
import {ProjectsGetAllExRequest} from '~/business-logic/model/projects/projectsGetAllExRequest';
|
||||
import {ApiTasksService} from '~/business-logic/api-services/tasks.service';
|
||||
import {ApiModelsService} from '~/business-logic/api-services/models.service';
|
||||
import {catchError, mergeMap, map, switchMap, withLatestFrom} from 'rxjs/operators';
|
||||
import {escapeRegex} from '../shared/utils/shared-utils';
|
||||
|
||||
@@ -27,14 +27,12 @@ export class DashboardSearchEffects {
|
||||
}
|
||||
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
@Effect()
|
||||
activeLoader = this.actions.pipe(
|
||||
activeLoader = createEffect(() => this.actions.pipe(
|
||||
ofType(SEARCH_ACTIONS.SEARCH_PROJECTS, SEARCH_ACTIONS.SEARCH_MODELS, SEARCH_ACTIONS.SEARCH_EXPERIMENTS),
|
||||
map(action => activeLoader(action.type))
|
||||
);
|
||||
));
|
||||
// add actions for each search
|
||||
@Effect()
|
||||
startSearch = this.actions.pipe(
|
||||
startSearch = createEffect(() => this.actions.pipe(
|
||||
ofType(searchStart.type),
|
||||
withLatestFrom(this.store.select(selectActiveSearch)),
|
||||
mergeMap(([action, active]: [ReturnType<typeof searchStart>, boolean]) => {
|
||||
@@ -49,10 +47,9 @@ export class DashboardSearchEffects {
|
||||
actionsToFire.push(searchModels(action));
|
||||
return actionsToFire;
|
||||
})
|
||||
);
|
||||
));
|
||||
|
||||
@Effect()
|
||||
searchProjects = this.actions.pipe(
|
||||
searchProjects = createEffect(() => this.actions.pipe(
|
||||
ofType(searchProjects.type),
|
||||
switchMap((action: ReturnType<typeof searchProjects>) => this.projectsApi.projectsGetAllEx({
|
||||
_any_: {
|
||||
@@ -67,10 +64,9 @@ export class DashboardSearchEffects {
|
||||
}).pipe(
|
||||
mergeMap(res => [new SetProjectsResults(res.projects), deactivateLoader(action.type)]),
|
||||
catchError(error => [deactivateLoader(action.type), requestFailed(error)])))
|
||||
);
|
||||
));
|
||||
|
||||
@Effect()
|
||||
searchModels = this.actions.pipe(
|
||||
searchModels = createEffect(() => this.actions.pipe(
|
||||
ofType(searchModels.type),
|
||||
switchMap((action: ReturnType<typeof searchModels>) => this.modelsApi.modelsGetAllEx({
|
||||
_any_: {
|
||||
@@ -84,10 +80,9 @@ export class DashboardSearchEffects {
|
||||
}).pipe(
|
||||
mergeMap(res => [new SetModelsResults(res.models), deactivateLoader(action.type)]),
|
||||
catchError(error => [deactivateLoader(action.type), requestFailed(error)])))
|
||||
);
|
||||
));
|
||||
|
||||
@Effect()
|
||||
searchExperiments = this.actions.pipe(
|
||||
searchExperiments = createEffect(() => this.actions.pipe(
|
||||
ofType(searchExperiments.type),
|
||||
switchMap((action: ReturnType<typeof searchExperiments>) => this.experimentsApi.tasksGetAllEx({
|
||||
_any_: {
|
||||
@@ -98,9 +93,9 @@ export class DashboardSearchEffects {
|
||||
size: SEARCH_PAGE_SIZE,
|
||||
only_fields: EXPERIMENT_SEARCH_ONLY_FIELDS,
|
||||
type: ['__$not', 'annotation_manual', '__$not', 'annotation', '__$not', 'dataset_import'],
|
||||
system_tags: ['-archived']
|
||||
system_tags: ['-archived', '-pipeline']
|
||||
}).pipe(
|
||||
mergeMap(res => [new SetExperimentsResults(res.tasks), deactivateLoader(action.type)]),
|
||||
catchError(error => [deactivateLoader(action.type), requestFailed(error)])))
|
||||
);
|
||||
));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {Injectable} from '@angular/core';
|
||||
import {ApiProjectsService} from '../../business-logic/api-services/projects.service';
|
||||
import {ApiProjectsService} from '~/business-logic/api-services/projects.service';
|
||||
import {Actions, createEffect, ofType} from '@ngrx/effects';
|
||||
import {requestFailed} from '../core/actions/http.actions';
|
||||
import {activeLoader, deactivateLoader} from '../core/actions/layout.actions';
|
||||
@@ -10,23 +10,21 @@ import {
|
||||
setRecentProjects,
|
||||
} from './common-dashboard.actions';
|
||||
import {CARDS_IN_ROW} from './common-dashboard.const';
|
||||
import {ApiTasksService} from '../../business-logic/api-services/tasks.service';
|
||||
import {ProjectsGetAllExRequest} from '../../business-logic/model/projects/projectsGetAllExRequest';
|
||||
import {ApiTasksService} from '~/business-logic/api-services/tasks.service';
|
||||
import {ProjectsGetAllExRequest} from '~/business-logic/model/projects/projectsGetAllExRequest';
|
||||
import {catchError, mergeMap, map, switchMap, withLatestFrom} from 'rxjs/operators';
|
||||
import {ApiLoginService} from '../../business-logic/api-services/login.service';
|
||||
import {MatDialog} from '@angular/material/dialog';
|
||||
import {ConfirmDialogComponent} from '../shared/ui-components/overlay/confirm-dialog/confirm-dialog.component';
|
||||
import {ApiLoginService} from '~/business-logic/api-services/login.service';
|
||||
import {Store} from '@ngrx/store';
|
||||
import {ErrorService} from '../shared/services/error.service';
|
||||
import {selectCurrentUser, selectShowOnlyUserWork} from '../core/reducers/users-reducer';
|
||||
|
||||
@Injectable()
|
||||
export class CommonDashboardEffects {
|
||||
constructor(private actions: Actions, private projectsApi: ApiProjectsService,
|
||||
private tasksApi: ApiTasksService, private loginApi: ApiLoginService,
|
||||
private errorService: ErrorService, private store: Store<any>,
|
||||
private dialog: MatDialog) {
|
||||
}
|
||||
constructor(
|
||||
private actions: Actions, private projectsApi: ApiProjectsService,
|
||||
private tasksApi: ApiTasksService, private loginApi: ApiLoginService,
|
||||
private errorService: ErrorService, private store: Store<any>,
|
||||
) {}
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
activeLoader = createEffect(() => this.actions.pipe(
|
||||
ofType(getRecentProjects, getRecentExperiments),
|
||||
@@ -62,7 +60,7 @@ export class CommonDashboardEffects {
|
||||
status: ['published', 'closed', 'failed', 'stopped', 'in_progress', 'completed'],
|
||||
type: ['__$not', 'annotation_manual', '__$not', 'annotation', '__$not', 'dataset_import'],
|
||||
only_fields: ['type', 'status', 'created', 'name', 'id', 'last_update', 'started', 'project.name'],
|
||||
system_tags: ['-archived'],
|
||||
system_tags: ['-archived', '-pipeline'],
|
||||
user: showOnlyUserWork ? [user.id] : null,
|
||||
})
|
||||
.pipe(
|
||||
|
||||
@@ -15,24 +15,26 @@ import {CommonExperimentSharedModule} from '../experiments/shared/common-experim
|
||||
import {CommonProjectsModule} from '../projects/common-projects.module';
|
||||
import {SharedModule} from '../../shared/shared.module';
|
||||
import { WelcomeMessageComponent } from './dumb/welcome-message/welcome-message.component';
|
||||
import {FormsModule} from '@angular/forms';
|
||||
|
||||
@NgModule({
|
||||
declarations: [DashboardProjectsComponent, DashboardExperimentsComponent, RecentExperimentTableComponent, WelcomeMessageComponent],
|
||||
exports : [DashboardProjectsComponent, DashboardExperimentsComponent],
|
||||
imports: [
|
||||
CommonModule,
|
||||
SMSharedModule,
|
||||
ExperimentsCommonModule,
|
||||
ExperimentSharedModule,
|
||||
CommonSearchModule,
|
||||
ProjectsSharedModule,
|
||||
CommonExperimentSharedModule,
|
||||
EffectsModule.forFeature([CommonDashboardEffects]),
|
||||
CommonLayoutModule,
|
||||
ExperimentSharedModule,
|
||||
CommonProjectsModule,
|
||||
SharedModule
|
||||
]
|
||||
imports: [
|
||||
CommonModule,
|
||||
SMSharedModule,
|
||||
ExperimentsCommonModule,
|
||||
ExperimentSharedModule,
|
||||
CommonSearchModule,
|
||||
ProjectsSharedModule,
|
||||
CommonExperimentSharedModule,
|
||||
EffectsModule.forFeature([CommonDashboardEffects]),
|
||||
CommonLayoutModule,
|
||||
ExperimentSharedModule,
|
||||
CommonProjectsModule,
|
||||
SharedModule,
|
||||
FormsModule
|
||||
]
|
||||
})
|
||||
export class CommonDashboardModule {
|
||||
}
|
||||
|
||||
@@ -44,7 +44,6 @@ export class DashboardProjectsComponent implements OnInit, AfterViewInit, OnDest
|
||||
}
|
||||
|
||||
ngAfterViewInit() {
|
||||
this.width.emit(this.header.nativeElement.getBoundingClientRect().width);
|
||||
window.setTimeout(() => this.width.emit(this.header.nativeElement.getBoundingClientRect().width));
|
||||
this.sub = fromEvent(window, 'resize')
|
||||
.pipe(throttleTime(50))
|
||||
|
||||
@@ -45,22 +45,27 @@
|
||||
</div>
|
||||
<div *ngIf="step.subNote" class="sub-note"><i class="mr-1 fas fa-info-circle info"></i>{{step.subNote}}</div>
|
||||
</div>
|
||||
<div class="step-container">
|
||||
<div class="step-header sub-note">Complete the clearml configuration information as prompted.</div>
|
||||
<div *ngIf="!accessKey ; else config" class="code empty-config">
|
||||
<div>
|
||||
<button class="mb-2 btn btn-neon" [disabled]="creatingCredentials" (click)="createCredentials()">CREATE NEW
|
||||
CREDENTIALS
|
||||
</button>
|
||||
</div>
|
||||
<div class="step-container cred-step" [class.first-step]="!credentialsCreated" [class.has-label]="credentialsLabel">
|
||||
<div class="step-header">Complete the clearml configuration information as prompted.</div>
|
||||
<div *ngIf="!credentialsCreated" class="d-flex align-items-end">
|
||||
<mat-form-field appearance="outline"
|
||||
class="label-input"
|
||||
floatLabel="always">
|
||||
<mat-label>Label (optional)</mat-label>
|
||||
<input matInput [(ngModel)]="credentialsLabel" [disabled]="credentialsCreated" placeholder="Credentials label" name="credentials">
|
||||
</mat-form-field>
|
||||
<button class="mb-2 btn btn-neon create-cred-button" (click)="createCredentials()">CREATE NEW
|
||||
CREDENTIALS
|
||||
</button>
|
||||
</div>
|
||||
<ng-template #config>
|
||||
<div class="cred-visible" [class.invisible]="!accessKey">
|
||||
<div class="code">
|
||||
<div #content class="content"><span class="variable">api</span> {{ '{' }}<ng-container *ngIf="community && workspace.name">
|
||||
<span class="comment">{{'# ' + workspace.name}}</span></ng-container>
|
||||
<span class="">{{'# ' + workspace.name}}</span></ng-container>
|
||||
<span class="variable">web_server</span><span class="operation">:</span> <span class="string">{{WEB_SERVER_URL}}</span>
|
||||
<span class="variable">api_server</span><span class="operation">:</span> <span class="string">{{API_BASE_URL}}</span>
|
||||
<ng-container *ngIf="fileBaseUrl"> <span class="variable">files_server</span><span class="operation">:</span> <span class="string">{{fileBaseUrl}}</span>
|
||||
<ng-container *ngIf="fileBaseUrl"> <span class="variable">files_server</span><span class="operation">:</span> <span class="string">{{fileBaseUrl}}</span><ng-container *ngIf="credentialsLabel">
|
||||
<span>{{'# ' + credentialsLabel}}</span></ng-container>
|
||||
</ng-container> <span class="variable">credentials</span> {{ '{' }}
|
||||
<span class="string">"access_key"</span> <span class="operation">=</span> <span class="string">"{{accessKey}}"</span>
|
||||
<span class="string">"secret_key"</span> <span class="operation">=</span> <span class="string">"{{secretKey}}"</span>
|
||||
@@ -72,8 +77,8 @@
|
||||
[copyIcon]="'far fa-lg fa-copy'"
|
||||
[clipboardText]="content.textContent"></sm-copy-clipboard>
|
||||
</div>
|
||||
</ng-template>
|
||||
<div class="sub-note"><i class="mr-1 fas fa-info-circle info"></i>Manage your app credentials in the <a target="_blank" href="settings/workspace-configuration">workspace settings page</a></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="step-container" *ngIf="!queue">
|
||||
<div class="step">3. Integrate</div>
|
||||
|
||||
@@ -58,8 +58,8 @@
|
||||
}
|
||||
|
||||
.steps-content {
|
||||
padding: 10px 32px;
|
||||
.step-container{
|
||||
padding: 0 32px 10px 32px;
|
||||
.step-container:not(:first-child){
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
}
|
||||
.step-header {
|
||||
color: $blue-500;
|
||||
margin-bottom: 1px;
|
||||
margin-bottom: 4px;
|
||||
width: 530px;
|
||||
}
|
||||
|
||||
@@ -104,12 +104,12 @@
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 16px;
|
||||
padding: 14px 16px;
|
||||
overflow: auto;
|
||||
margin-right: 16px;
|
||||
white-space: pre;
|
||||
font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
font-size: 12px;
|
||||
font-size: 11px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
@@ -138,11 +138,38 @@
|
||||
}
|
||||
}
|
||||
|
||||
.empty-config {
|
||||
height: 190px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
.cred-step {
|
||||
height: 238px;
|
||||
transition: height 1s ease;
|
||||
|
||||
&.has-label {
|
||||
height: 272px;
|
||||
}
|
||||
|
||||
&.first-step {
|
||||
height: 90px;
|
||||
}
|
||||
}
|
||||
|
||||
.cred-visible {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
transition: opacity 1s ease;
|
||||
|
||||
&.invisible {
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.label-input {
|
||||
flex: 1;
|
||||
padding-right: 12px;
|
||||
}
|
||||
|
||||
.create-cred-button {
|
||||
margin-top: 18px;
|
||||
height: 36px;
|
||||
padding: 0px 28px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog';
|
||||
import {setSelectedWorkspaceTab} from '@common/core/actions/users.actions';
|
||||
import {Subscription} from 'rxjs';
|
||||
import {selectActiveWorkspace} from '@common/core/reducers/users-reducer';
|
||||
import {filter, tap} from 'rxjs/operators';
|
||||
import {filter} from 'rxjs/operators';
|
||||
import {Store} from '@ngrx/store';
|
||||
import {createCredential, resetCredential} from '@common/core/actions/common-auth.actions';
|
||||
import {selectNewCredential} from '@common/core/reducers/common-auth-reducer';
|
||||
@@ -25,7 +25,7 @@ export class WelcomeMessageComponent implements OnInit, OnDestroy {
|
||||
public step: number = 1;
|
||||
accessKey: string;
|
||||
secretKey: string;
|
||||
creatingCredentials = false;
|
||||
credentialsCreated = false;
|
||||
|
||||
private workspacesSub: Subscription;
|
||||
public workspace: GetCurrentUserResponseUserObjectCompany;
|
||||
@@ -62,6 +62,7 @@ export class WelcomeMessageComponent implements OnInit, OnDestroy {
|
||||
doNotShowAgain: boolean;
|
||||
public gettingStartedContext: GettingStartedContext;
|
||||
docsLink: string;
|
||||
credentialsLabel: string;
|
||||
|
||||
constructor(
|
||||
private store: Store<any>,
|
||||
@@ -99,7 +100,6 @@ export class WelcomeMessageComponent implements OnInit, OnDestroy {
|
||||
|
||||
this.newCredentialSub = this.store.select(selectNewCredential)
|
||||
.pipe(
|
||||
tap(() => this.creatingCredentials = false),
|
||||
filter(credential => credential && Object.keys(credential).length > 0)
|
||||
).subscribe(credential => {
|
||||
this.accessKey = credential.access_key;
|
||||
@@ -118,9 +118,9 @@ export class WelcomeMessageComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
createCredentials() {
|
||||
this.creatingCredentials = true;
|
||||
this.credentialsCreated = true;
|
||||
this.store.dispatch(setSelectedWorkspaceTab({workspace: {id: this.workspace.id}}));
|
||||
this.store.dispatch(createCredential({workspace: this.workspace}));
|
||||
this.store.dispatch(createCredential({workspace: this.workspace, label: this.credentialsLabel}));
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="no-images no-output" [class.dark]="isDarkTheme" *ngIf="shouldShowNoImagesForExperiment(experimentId)">
|
||||
<svg class="mb-3 w-100" xmlns="http://www.w3.org/2000/svg" width="300" height="150" viewBox="0 0 300 150">
|
||||
<svg class="mb-3 w-100" xmlns="http://www.w3.org/2000/svg" width="400" height="200" viewBox="0 0 300 150">
|
||||
<path opacity="0.1"
|
||||
d="M72.67,79.36a5.39,5.39,0,0,1-1.45,4.32,1.17,1.17,0,0,1-.6.34,1.13,1.13,0,0,1-1.31-.88,1.11,1.11,0,0,1,.28-1,3.19,3.19,0,0,0,.89-2.36c-.22-1.09-1.66-1.73-1.68-1.74A1.12,1.12,0,0,1,69.65,76C69.76,76,72.22,77.07,72.67,79.36ZM46.19,78.1a1.38,1.38,0,0,0-1.06,1.61L47.3,90.38a1.38,1.38,0,0,0,1.61,1.06l4-.82L50.19,77.29Zm30.87.39c-.91-4.54-5.23-7.07-5.41-7.18a1.13,1.13,0,1,0-1.16,1.94s3.63,2.13,4.34,5.68-1.8,7-1.82,7a1.12,1.12,0,0,0,.25,1.56,1.11,1.11,0,0,0,.86.2,1.12,1.12,0,0,0,.68-.43C75,87.09,78,83,77.06,78.49Zm-3.57-12a1.12,1.12,0,0,0-1,2,12.48,12.48,0,0,1,2.91,2.24,13.87,13.87,0,0,1,3.88,7.28,14.19,14.19,0,0,1-.78,8.27,13,13,0,0,1-1.83,3.22,1.11,1.11,0,0,0,1.06,1.82h0a1,1,0,0,0,.63-.36,16.47,16.47,0,0,0,3.13-13.38A16.18,16.18,0,0,0,73.49,66.53Zm-9.28,1a1.35,1.35,0,0,0-1.6-1.06h0a1.45,1.45,0,0,0-.71.4L52.2,76.93l2.7,13.24,12.82,5.52a1.36,1.36,0,0,0,1.79-.7,1.33,1.33,0,0,0,.09-.81ZM261.4,76.66l-3.77,21.62-8.28-8.4-.47,2.7a4.13,4.13,0,0,1-4.76,3.35l-25.67-4.48a4.14,4.14,0,0,1-3.35-4.76l2.36-13.51c0-.12,0-.24.08-.35a6.17,6.17,0,1,1,10-3.71,5.62,5.62,0,0,1-.5,1.55l4.49.79a6.37,6.37,0,0,1,.06-1.63,6.15,6.15,0,1,1,11.63,3.65l4.63.81a4,4,0,0,1,3.4,4.53c0,.08,0,.15-.05.23l-.48,2.7ZM225.28,68.1a3.7,3.7,0,0,0-3.52-3.87h-.19a3.79,3.79,0,1,0,3.71,3.87Zm16.29,3A3.7,3.7,0,0,0,238,67.24h-.19a3.79,3.79,0,1,0,3.72,3.86Zm53.2-20.19L281,129.18a17.25,17.25,0,0,1-20,14l-78.27-13.81a17,17,0,0,1-11.13-7.08,17.86,17.86,0,0,1-1-1.69H130.44a17.86,17.86,0,0,1-1,1.69,17,17,0,0,1-11.13,7.08L40.09,143.16a17.25,17.25,0,0,1-20-14L6.26,50.86a17.26,17.26,0,0,1,14-20h0L94.63,17.77A17.24,17.24,0,0,1,110.76,6.58h79.47a17.24,17.24,0,0,1,16.13,11.19l74.38,13.11a17.25,17.25,0,0,1,14,20ZM120.22,119.58h-9.47a17.21,17.21,0,0,1-17.19-17.19V25.1L21.81,37.75a9.55,9.55,0,0,0-7.74,11.06l13.76,78.06a9.57,9.57,0,0,0,11.06,7.71L117,120.81A9.68,9.68,0,0,0,120.22,119.58Zm69.82-7a9.54,9.54,0,0,0,9.52-9.52V24.13a9.53,9.53,0,0,0-9.5-9.55h-79a9.51,9.51,0,0,0-9.51,9.51v79a9.53,9.53,0,0,0,9.51,9.52Zm95.52-70.94a9.49,9.49,0,0,0-6.17-3.93L207.56,25.1v77.33a17.23,17.23,0,0,1-17.21,17.15h-9.49a9.66,9.66,0,0,0,3.28,1.23l78.15,13.77a9.58,9.58,0,0,0,11.07-7.75l13.78-78.06a9.44,9.44,0,0,0-1.58-7.09Zm-109,.43c1.09.64,1,2.34,1,2.34l-.14,37.87a3.33,3.33,0,0,1-3.36,3.3h0l-48.13-.16a3.37,3.37,0,0,1-3.37-3.35l.2-37.39a3.3,3.3,0,0,1,2.11-3l.18-.08h49.68s1.76-.15,1.83.53ZM160.49,53.34a3.8,3.8,0,0,0,7.59,0,3.7,3.7,0,0,0-3.67-3.76h-.12A3.79,3.79,0,0,0,160.49,53.34ZM171.6,74.93l-8.55-9.46-.19-.19a2.49,2.49,0,0,0-3.52.16v0l-4.2,4.63-9.19-10.63a3.05,3.05,0,0,0-1.59-1,2.75,2.75,0,0,0-2.66.95h0l-13.13,15v4.13l43,.14Z"/>
|
||||
</svg>
|
||||
|
||||
@@ -52,7 +52,6 @@ sm-debug-images-view {
|
||||
transform: translateY(-50%) translateX(-50%);
|
||||
display: block;
|
||||
color: $cloudy-blue-two;
|
||||
font-size: 1.75rem;
|
||||
font-weight: 500;
|
||||
line-height: 1.2;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {Action, createAction, props} from '@ngrx/store';
|
||||
import {ISmAction} from '../../core/models/actions';
|
||||
import {IExperimentSettings} from '../../experiments/reducers/common-experiment-output.reducer';
|
||||
import {ScalarKeyEnum} from '../../../business-logic/model/events/scalarKeyEnum';
|
||||
import {ExperimentSettings} from '../../experiments/reducers/common-experiment-output.reducer';
|
||||
import {ScalarKeyEnum} from '~/business-logic/model/events/scalarKeyEnum';
|
||||
|
||||
|
||||
export const EXPERIMENTS_COMPARE_METRICS_CHARTS_ = 'EXPERIMENTS_COMPARE_METRICS_CHARTS_';
|
||||
@@ -68,7 +68,7 @@ export class SetExperimentPlots implements Action {
|
||||
export class SetExperimentSettings implements Action {
|
||||
readonly type = UPDATE_EXPERIMENT_SETTINGS;
|
||||
|
||||
constructor(public payload: { id: Array<string>; changes: Partial<IExperimentSettings>}) {
|
||||
constructor(public payload: { id: Array<string>; changes: Partial<ExperimentSettings>}) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -298,16 +298,25 @@ export abstract class ExperimentCompareBase extends ExperimentCompareDetailsBase
|
||||
}
|
||||
}
|
||||
|
||||
public find(text: string) {
|
||||
if (text) {
|
||||
this.findAllOccurrences(text);
|
||||
this.foundIndex = -1;
|
||||
this.findNext();
|
||||
} else if (this.searchText !== text) {
|
||||
this.foundPaths = [];
|
||||
this.selectedPath = null;
|
||||
public find(value: string) {
|
||||
const searchBackward = value === null;
|
||||
if (this.searchText !== value && !searchBackward) {
|
||||
this.resetSearch();
|
||||
if (value.length > 0) {
|
||||
this.findAllOccurrences(value);
|
||||
}
|
||||
this.searchText = value;
|
||||
}
|
||||
this.searchText = text;
|
||||
|
||||
if (value?.length > 0 || value === null) {
|
||||
searchBackward ? this.findPrev() : this.findNext();
|
||||
}
|
||||
}
|
||||
|
||||
public resetSearch() {
|
||||
this.foundPaths = [];
|
||||
this.selectedPath = null;
|
||||
this.foundIndex = -1;
|
||||
}
|
||||
|
||||
findAllOccurrences(text) {
|
||||
|
||||
@@ -69,31 +69,23 @@
|
||||
|
||||
|
||||
<sm-portal outletId="searchDiff">
|
||||
<div class="btn-group mr-2" role="group">
|
||||
<sm-search [value]="searchText"
|
||||
[minimumChars]="1"
|
||||
[debounceTime]="300"
|
||||
(keydown.enter)="findNext()"
|
||||
(valueChanged)="find($event)"
|
||||
></sm-search>
|
||||
|
||||
<button class="btn btn-secondary prev" smTooltip="Previous occurrence" [disabled]="foundPaths.length === 0 " (click)="findPrev()">
|
||||
<i class="fas fa-chevron-up"></i>
|
||||
</button>
|
||||
|
||||
<button class="btn btn-secondary next" smTooltip="Next occurrence" [disabled]="foundPaths.length === 0 " (click)="findNext()">
|
||||
<i class="fas fa-chevron-down"></i>
|
||||
</button>
|
||||
</div>
|
||||
<span [class.hidden]="searchText.length === 0 "> Match {{foundPaths.length === 0 ? '0' : foundIndex + 1}} / {{foundPaths.length}}</span>
|
||||
<sm-search class="light-theme"
|
||||
[value]="searchText"
|
||||
[minimumChars]="1"
|
||||
[debounceTime]="300"
|
||||
[enableNavigation]="true"
|
||||
[searchCounterIndex]="foundIndex"
|
||||
[searchResultsCount]="foundPaths.length"
|
||||
(valueChanged)="find($event)"
|
||||
></sm-search>
|
||||
</sm-portal>
|
||||
|
||||
<sm-portal outletId="nextDiff">
|
||||
<button class="btn btn-secondary btn-arrow mr-3" smTooltip="Previous diff" (click)="goToNextDiff('up')">
|
||||
<i class="fas fa-arrow-up"></i>
|
||||
<i class="al-icon al-ico-arrow-up sm"></i>
|
||||
</button>
|
||||
|
||||
<button class="btn btn-secondary btn-arrow" smTooltip="Next diff" (click)="goToNextDiff('down')">
|
||||
<i class="fas fa-arrow-down"></i>
|
||||
<i class="al-icon al-ico-arrow-down sm"></i>
|
||||
</button>
|
||||
</sm-portal>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
(keydown.escape)="clearMetricSearch(); searchMetric.value= ''"
|
||||
placeholder="Search metric"
|
||||
[smTooltip]="selectedMetric?.name"
|
||||
[showDelay]="500"
|
||||
[matTooltipShowDelay]="500"
|
||||
[value]="(!metrics || listOpen) ? '' : selectedMetric?.name"
|
||||
(input)="updateMetricsList($event)"
|
||||
>
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import {Component, HostListener, OnDestroy, OnInit, ElementRef, ViewChild} from '@angular/core';
|
||||
import {combineLatest, Observable, Subscription} from 'rxjs';
|
||||
import {select, Store} from '@ngrx/store';
|
||||
import {IExperimentInfoState} from '../../../../features/experiments/reducers/experiment-info.reducer';
|
||||
import {IExperimentInfoState} from '~/features/experiments/reducers/experiment-info.reducer';
|
||||
import {distinctUntilChanged, filter, map} from 'rxjs/operators';
|
||||
import {selectRouterParams} from '../../../core/reducers/router-reducer';
|
||||
import {selectRouterParams} from '@common/core/reducers/router-reducer';
|
||||
import {get, has} from 'lodash/fp';
|
||||
import {SetExperimentSettings, SetSelectedExperiments} from '../../actions/experiments-compare-charts.actions';
|
||||
import {selectRefreshing, selectScalarsGraphHyperParams, selectScalarsGraphMetrics, selectScalarsGraphShowIdenticalHyperParams, selectScalarsGraphTasks, selectMetricValueType, selectSelectedSettigsHyperParams, selectSelectedSettigsMetric} from '../../reducers';
|
||||
import {selectRefreshing, selectScalarsGraphHyperParams, selectScalarsGraphMetrics, selectScalarsGraphShowIdenticalHyperParams, selectScalarsGraphTasks, selectMetricValueType, selectSelectedSettingsHyperParams, selectSelectedSettingsMetric} from '../../reducers';
|
||||
import {getExperimentsHyperParams, setShowIdenticalHyperParams, setvalueType} from '../../actions/experiments-compare-scalars-graph.actions';
|
||||
import {GroupedHyperParams, MetricOption, MetricValueType, SelectedMetric, VariantOption} from '../../reducers/experiments-compare-charts.reducer';
|
||||
import {MatRadioChange} from '@angular/material/radio';
|
||||
import {selectPlotlyReady} from '../../../core/reducers/view.reducer';
|
||||
import {ExtFrame} from '../../../shared/experiment-graphs/single-graph/plotly-graph-base';
|
||||
import {selectPlotlyReady} from '@common/core/reducers/view.reducer';
|
||||
import {ExtFrame} from '@common/shared/experiment-graphs/single-graph/plotly-graph-base';
|
||||
|
||||
|
||||
export const _filter = (opt: VariantOption[], value: string): VariantOption[] => {
|
||||
@@ -69,8 +69,8 @@ export class ExperimentCompareHyperParamsGraphComponent implements OnInit, OnDes
|
||||
constructor(private store: Store<IExperimentInfoState>) {
|
||||
this.metrics$ = this.store.pipe(select(selectScalarsGraphMetrics));
|
||||
this.hyperParams$ = this.store.pipe(select(selectScalarsGraphHyperParams));
|
||||
this.selectedHyperParams$ = this.store.pipe(select(selectSelectedSettigsHyperParams));
|
||||
this.selectedMetric$ = this.store.pipe(select(selectSelectedSettigsMetric));
|
||||
this.selectedHyperParams$ = this.store.pipe(select(selectSelectedSettingsHyperParams));
|
||||
this.selectedMetric$ = this.store.pipe(select(selectSelectedSettingsMetric));
|
||||
this.selectShowIdenticalHyperParams$ = this.store.pipe(select(selectScalarsGraphShowIdenticalHyperParams));
|
||||
this.selectRefreshing$ = this.store.select(selectRefreshing);
|
||||
this.experiments$ = this.store.pipe(select(selectScalarsGraphTasks));
|
||||
@@ -94,7 +94,7 @@ export class ExperimentCompareHyperParamsGraphComponent implements OnInit, OnDes
|
||||
|
||||
this.hyperParamsSubscription = combineLatest([this.selectedHyperParams$, this.hyperParams$, this.selectShowIdenticalHyperParams$])
|
||||
.pipe(
|
||||
filter(([selectedParams, allParams, filterActive]) => !!allParams),
|
||||
filter(([, allParams]) => !!allParams),
|
||||
)
|
||||
.subscribe(([selectedParams, allParams, showIdentical]) => {
|
||||
this.showIdenticalParamsActive = showIdentical;
|
||||
@@ -161,7 +161,7 @@ export class ExperimentCompareHyperParamsGraphComponent implements OnInit, OnDes
|
||||
this.listOpen = false;
|
||||
}
|
||||
|
||||
selectedParamsChanged({param, value}) {
|
||||
selectedParamsChanged({param}) {
|
||||
const newSelectedParamsList = this.selectedHyperParams.includes(param) ? this.selectedHyperParams.filter(i => i !== param) : [...this.selectedHyperParams, param];
|
||||
this.updateServer(this.selectedMetric, newSelectedParamsList);
|
||||
}
|
||||
|
||||
@@ -1,41 +1,40 @@
|
||||
<div class="d-flex h-100">
|
||||
<div class="list-container">
|
||||
<sm-graph-settings-bar
|
||||
[verticalLayout]="true"
|
||||
[smoothWeight]="smoothWeight$ | async"
|
||||
[xAxisType]="xAxisType$ | async"
|
||||
[groupBy]="groupBy"
|
||||
[groupByOptions]="groupByOptions"
|
||||
(changeWeight)="changeSmoothness($event)"
|
||||
(toggleSettings)="toggleSettingsBar()"
|
||||
(changeXAxisType)="changeXAxisType($event)"
|
||||
(changeGroupBy)="changeGroupBy($event)"
|
||||
></sm-graph-settings-bar>
|
||||
<sm-selectable-grouped-filter-list
|
||||
[list]="graphList"
|
||||
[selected]="selectedGraph"
|
||||
[checkedList]="listOfHidden | async"
|
||||
[searchTerm]="searchTerm$ | async"
|
||||
(itemSelect)="metricSelected($event)"
|
||||
(hiddenChanged)="hiddenListChanged($event)"
|
||||
(searchTermChanged)="searchTermChanged($event)"
|
||||
>
|
||||
</sm-selectable-grouped-filter-list>
|
||||
</div>
|
||||
<div class="graphs-container h-100">
|
||||
<mat-drawer-container autosize>
|
||||
<mat-drawer opened="true" mode="side">
|
||||
<div class="list-container">
|
||||
<sm-graph-settings-bar
|
||||
class="drawer-settings-bar"
|
||||
[verticalLayout]="true"
|
||||
[smoothWeight]="smoothWeight$ | async"
|
||||
[xAxisType]="xAxisType$ | async"
|
||||
[groupBy]="groupBy"
|
||||
[groupByOptions]="groupByOptions"
|
||||
(changeWeight)="changeSmoothness($event)"
|
||||
(toggleSettings)="toggleSettingsBar()"
|
||||
(changeXAxisType)="changeXAxisType($event)"
|
||||
(changeGroupBy)="changeGroupBy($event)"
|
||||
></sm-graph-settings-bar>
|
||||
<sm-selectable-grouped-filter-list
|
||||
[list]="graphList"
|
||||
[selected]="selectedGraph"
|
||||
[checkedList]="listOfHidden | async"
|
||||
[searchTerm]="searchTerm$ | async"
|
||||
(itemSelect)="metricSelected($event)"
|
||||
(hiddenChanged)="hiddenListChanged($event)"
|
||||
(searchTermChanged)="searchTermChanged($event)"
|
||||
>
|
||||
</sm-selectable-grouped-filter-list>
|
||||
</div>
|
||||
</mat-drawer>
|
||||
<mat-drawer-content>
|
||||
<sm-experiment-graphs
|
||||
[metrics]="graphs"
|
||||
[hiddenList]="listOfHidden | async"
|
||||
[isGroupGraphs]="false"
|
||||
[isCompare]="true"
|
||||
[showSettings]="showSettingsBar$ | async"
|
||||
[smoothWeight]="(smoothWeight$ | async)"
|
||||
[xAxisType]="xAxisType$ | async"
|
||||
(resetGraphs)="resetMetrics()"
|
||||
(changeWeight)="changeSmoothness($event)"
|
||||
(changeXAxisType)="changeXAxisType($event)"
|
||||
(toggleSettings)="toggleSettingsBar()"
|
||||
>
|
||||
</sm-experiment-graphs>
|
||||
</div>
|
||||
</div>
|
||||
</mat-drawer-content>
|
||||
</mat-drawer-container>
|
||||
|
||||
@@ -1,22 +1,50 @@
|
||||
.toggle-all {
|
||||
font-size: 10px;
|
||||
padding-right: 2px;
|
||||
cursor: pointer;
|
||||
}
|
||||
@import "variables";
|
||||
|
||||
.list-container {
|
||||
$list-width: 300px;
|
||||
|
||||
:host {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 340px;
|
||||
//padding: 20px 24px 0 24px;
|
||||
border-right: 1px solid #efefef;
|
||||
}
|
||||
.graphs-container {
|
||||
flex: 1;
|
||||
padding: 0 !important;
|
||||
}
|
||||
height: 100%;
|
||||
|
||||
sm-graph-settings-bar {
|
||||
padding: 24px;
|
||||
border-bottom: 1px solid #efefef;
|
||||
mat-drawer {
|
||||
background-color: $white;
|
||||
}
|
||||
|
||||
mat-drawer-container {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.drawer-settings-bar {
|
||||
height: unset;
|
||||
padding: 24px;
|
||||
border-bottom: 1px solid $blue-100;
|
||||
}
|
||||
|
||||
.toggle-all {
|
||||
font-size: 10px;
|
||||
padding-right: 2px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.list-container {
|
||||
display: flex;
|
||||
position: relative;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
width: $list-width;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
border-right: 1px solid #efefef;
|
||||
}
|
||||
|
||||
.graphs-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
sm-experiment-graphs {
|
||||
height: calc(100% - 64px);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,31 +68,23 @@
|
||||
|
||||
|
||||
<sm-portal outletId="searchDiff">
|
||||
<div class="btn-group mr-2" role="group">
|
||||
<sm-search [value]="searchText"
|
||||
[minimumChars]="1"
|
||||
[debounceTime]="300"
|
||||
(keydown.enter)="findNext()"
|
||||
(valueChanged)="find($event)"
|
||||
></sm-search>
|
||||
|
||||
<button class="btn btn-secondary prev" smTooltip="Previous occurrence" [disabled]="foundPaths.length === 0 " (click)="findPrev()">
|
||||
<i class="fas fa-chevron-up"></i>
|
||||
</button>
|
||||
|
||||
<button class="btn btn-secondary next" smTooltip="Next occurrence" [disabled]="foundPaths.length === 0 " (click)="findNext()">
|
||||
<i class="fas fa-chevron-down"></i>
|
||||
</button>
|
||||
</div>
|
||||
<span [class.hidden]="searchText.length === 0 "> Match {{foundPaths.length === 0 ? '0' : foundIndex + 1}} / {{foundPaths.length}}</span>
|
||||
<sm-search class="light-theme"
|
||||
[value]="searchText"
|
||||
[minimumChars]="1"
|
||||
[debounceTime]="300"
|
||||
[enableNavigation]="true"
|
||||
[searchCounterIndex]="foundIndex"
|
||||
[searchResultsCount]="foundPaths.length"
|
||||
(valueChanged)="find($event)"
|
||||
></sm-search>
|
||||
</sm-portal>
|
||||
|
||||
<sm-portal outletId="nextDiff">
|
||||
<button class="btn btn-secondary btn-arrow mr-3" smTooltip="Previous diff" (click)="goToNextDiff('up')">
|
||||
<i class="fas fa-arrow-up"></i>
|
||||
<i class="al-icon al-ico-arrow-up sm"></i>
|
||||
</button>
|
||||
|
||||
<button class="btn btn-secondary btn-arrow" smTooltip="Next diff" (click)="goToNextDiff('down')">
|
||||
<i class="fas fa-arrow-down"></i>
|
||||
<i class="al-icon al-ico-arrow-down sm"></i>
|
||||
</button>
|
||||
</sm-portal>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<div class="d-flex h-100">
|
||||
<div class="list-container">
|
||||
<sm-selectable-filter-list
|
||||
checkAllIcon="fa-eye"
|
||||
checkAllIcon="al-ico-show"
|
||||
placeholder="Find plots"
|
||||
[list]="graphList"
|
||||
[selected]="selectedGraph"
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
[parents]="parent$ | async"
|
||||
[noMoreExperiments]="noMoreExperiments$ | async"
|
||||
[systemTags]="systemTags$ | async"
|
||||
[entityType]="entityTypes.experiment"
|
||||
(tagsMenuOpened)="refreshTagsList()"
|
||||
(typesMenuOpened)="refreshTypesList()"
|
||||
(experimentsSelectionChanged)="experimentsSelectionChanged($event)"
|
||||
|
||||
@@ -15,13 +15,13 @@ import {
|
||||
selectSelectedExperimentsForCompareAdd
|
||||
} from '../../reducers';
|
||||
import {BehaviorSubject, combineLatest, Observable, Subscription} from 'rxjs';
|
||||
import {Task} from '../../../../business-logic/model/tasks/task';
|
||||
import {Task} from '~/business-logic/model/tasks/task';
|
||||
import {Params} from '@angular/router';
|
||||
import {selectRouterParams} from '../../../core/reducers/router-reducer';
|
||||
import {selectRouterParams} from '@common/core/reducers/router-reducer';
|
||||
import {distinctUntilChanged, distinctUntilKeyChanged, filter, map} from 'rxjs/operators';
|
||||
import {compareLimitations} from '../../../shared/entity-page/footer-items/compare-footer-item';
|
||||
import {compareLimitations} from '@common/shared/entity-page/footer-items/compare-footer-item';
|
||||
import {MatDialogRef} from '@angular/material/dialog';
|
||||
import {ITableExperiment} from '../../../experiments/shared/common-experiment-model.model';
|
||||
import {ITableExperiment} from '@common/experiments/shared/common-experiment-model.model';
|
||||
import {
|
||||
selectActiveParentsFilter,
|
||||
selectExperimentsList,
|
||||
@@ -34,21 +34,24 @@ import {
|
||||
selectExperimentsUsers,
|
||||
selectHyperParamsOptions,
|
||||
selectNoMoreExperiments,
|
||||
selectTableFilters
|
||||
} from '../../../experiments/reducers';
|
||||
selectTableFilters, selectTableSortFields
|
||||
} from '@common/experiments/reducers';
|
||||
import {get, isEqual, unionBy} from 'lodash/fp';
|
||||
import {ColHeaderTypeEnum, ISmCol, TableSortOrderEnum} from '../../../shared/ui-components/data/table/table.consts';
|
||||
import {filterArchivedExperiments} from '../../../experiments/shared/common-experiments.utils';
|
||||
import {InitSearch} from '../../../common-search/common-search.actions';
|
||||
import {ColHeaderTypeEnum, ISmCol, TableSortOrderEnum} from '@common/shared/ui-components/data/table/table.consts';
|
||||
import {filterArchivedExperiments} from '@common/experiments/shared/common-experiments.utils';
|
||||
import {InitSearch} from '@common/common-search/common-search.actions';
|
||||
import * as experimentsActions from '../../../experiments/actions/common-experiments-view.actions';
|
||||
import {resetExperiments, resetGlobalFilter} from '../../../experiments/actions/common-experiments-view.actions';
|
||||
import {User} from '../../../../business-logic/model/users/user';
|
||||
import {selectProjectSystemTags, selectRootProjects} from '../../../core/reducers/projects.reducer';
|
||||
import {resetExperiments, resetGlobalFilter} from '@common/experiments/actions/common-experiments-view.actions';
|
||||
import {User} from '~/business-logic/model/users/user';
|
||||
import {selectProjectSystemTags, selectRootProjects} from '@common/core/reducers/projects.reducer';
|
||||
import {SortMeta} from 'primeng/api';
|
||||
import {Project} from '../../../../business-logic/model/projects/project';
|
||||
import {addMessage} from '../../../core/actions/layout.actions';
|
||||
import {MESSAGES_SEVERITY} from '../../../../app.constants';
|
||||
import {ProjectsGetTaskParentsResponseParents} from '../../../../business-logic/model/projects/projectsGetTaskParentsResponseParents';
|
||||
import {Project} from '~/business-logic/model/projects/project';
|
||||
import {addMessage} from '@common/core/actions/layout.actions';
|
||||
import {MESSAGES_SEVERITY} from '~/app.constants';
|
||||
import {ProjectsGetTaskParentsResponseParents} from '~/business-logic/model/projects/projectsGetTaskParentsResponseParents';
|
||||
import {FilterMetadata} from 'primeng/api/filtermetadata';
|
||||
import {INITIAL_EXPERIMENT_TABLE_COLS} from '@common/experiments/experiment.consts';
|
||||
import {EntityTypeEnum} from '~/shared/constants/non-common-consts';
|
||||
|
||||
export const allowAddExperiment$ = (selectRouterParams$: Observable<Params>) => selectRouterParams$.pipe(
|
||||
distinctUntilKeyChanged('ids'),
|
||||
@@ -64,6 +67,8 @@ export const allowAddExperiment$ = (selectRouterParams$: Observable<Params>) =>
|
||||
styleUrls: ['./select-experiments-for-compare.component.scss']
|
||||
})
|
||||
export class SelectExperimentsForCompareComponent implements OnInit, OnDestroy {
|
||||
public tableCols = INITIAL_EXPERIMENT_TABLE_COLS;
|
||||
public entityTypes = EntityTypeEnum;
|
||||
public experimentsResults$: Observable<Task[]>;
|
||||
public selectedExperimentsIds: string[] = [];
|
||||
private paramsSubscription: Subscription;
|
||||
@@ -78,7 +83,7 @@ export class SelectExperimentsForCompareComponent implements OnInit, OnDestroy {
|
||||
public experiments$: Observable<any>;
|
||||
private projectId: string;
|
||||
public users$: Observable<User[]>;
|
||||
public tableFilters$: Observable<{ [p: string]: { value: any; matchMode: string } }>;
|
||||
public tableFilters$: Observable<{ [columnId: string]: FilterMetadata }>;
|
||||
public tags$: Observable<string[]>;
|
||||
public systemTags$: Observable<string[]>;
|
||||
public types$: Observable<string[]>;
|
||||
@@ -119,14 +124,13 @@ export class SelectExperimentsForCompareComponent implements OnInit, OnDestroy {
|
||||
this.types$ = this.store.select(selectExperimentsTypes);
|
||||
this.systemTags$ = this.store.select(selectProjectSystemTags);
|
||||
this.noMoreExperiments$ = this.store.select(selectNoMoreExperiments);
|
||||
this.tableSortFields$ = this.store.select(selectCompareAddTableSortFields);
|
||||
this.tableSortFields$ = this.store.select(selectTableSortFields);
|
||||
this.hyperParamsOptions$ = this.store.select(selectHyperParamsOptions);
|
||||
this.activeParentsFilter$ = this.store.select(selectActiveParentsFilter);
|
||||
this.tableCols$ = combineLatest([this.columns$, this.metricTableCols$, this.resizedCols$])
|
||||
.pipe(
|
||||
filter(([tableCols,,]) => !!tableCols),
|
||||
map(([tableCols, metricCols, resizedCols]) =>
|
||||
tableCols
|
||||
(tableCols.length > 0 ? tableCols: this.tableCols)
|
||||
.concat(metricCols.map(col => ({...col, metric: true})))
|
||||
.map(col => ({
|
||||
...col,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {ChangeDetectionStrategy, Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
|
||||
import {EXPERIMENTS_STATUS_LABELS} from '../../../../features/experiments/shared/experiments.const';
|
||||
import {IExperimentDetail} from '../../../../features/experiments-compare/experiments-compare-models';
|
||||
import {TIME_FORMAT_STRING} from '../../../constants';
|
||||
import {ChangeDetectionStrategy, Component, EventEmitter, Input, Output} from '@angular/core';
|
||||
import {EXPERIMENTS_STATUS_LABELS} from '~/features/experiments/shared/experiments.const';
|
||||
import {IExperimentDetail} from '~/features/experiments-compare/experiments-compare-models';
|
||||
import {TIME_FORMAT_STRING} from '@common/constants';
|
||||
|
||||
@Component({
|
||||
selector: 'sm-experiment-compare-general-data',
|
||||
@@ -24,6 +24,6 @@ export class ExperimentCompareGeneralDataComponent {
|
||||
}
|
||||
|
||||
buildUrl() {
|
||||
return `/projects/${this.experiment.project ? this.experiment.project.id : '*'}/experiments/${this.experiment.id}`;
|
||||
return ['../../', 'experiments', this.experiment.id];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,29 +21,12 @@
|
||||
border-left-color: transparent !important;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-group sm-search {
|
||||
width: 200px;
|
||||
|
||||
.search-input-container {
|
||||
|
||||
.search-input input{
|
||||
border: 1px solid $blue-280;
|
||||
border-right: none;
|
||||
border-radius: 4px 0 0 4px !important;
|
||||
padding-left: 6px !important;
|
||||
}
|
||||
|
||||
i.fa {
|
||||
border-top: 1px solid $blue-280;
|
||||
border-bottom: 1px solid $blue-280;
|
||||
border-right: 1px solid $blue-280;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
::ng-deep .btn-arrow {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 42px;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import {Component, ElementRef, HostListener, Input, OnInit, ViewChild} from '@angular/core';
|
||||
import {PlotlyGraphBase} from '../../../shared/experiment-graphs/single-graph/plotly-graph-base';
|
||||
import {PlotlyGraphBase} from '@common/shared/experiment-graphs/single-graph/plotly-graph-base';
|
||||
import {debounceTime, filter} from 'rxjs/operators';
|
||||
import {ColorHashService} from '../../../shared/services/color-hash/color-hash.service';
|
||||
import {ColorHashService} from '@common/shared/services/color-hash/color-hash.service';
|
||||
import {get, getOr, isEqual, max, min, uniq, cloneDeep} from 'lodash/fp';
|
||||
import {MetricValueType, SelectedMetric} from '../../reducers/experiments-compare-charts.reducer';
|
||||
import {Task} from '../../../../business-logic/model/tasks/task';
|
||||
import {Task} from '~/business-logic/model/tasks/task';
|
||||
import {select} from 'd3-selection';
|
||||
import {sortCol} from '../../../shared/utils/tableParamEncode';
|
||||
import {sortCol} from '@common/shared/utils/tableParamEncode';
|
||||
import {Store} from '@ngrx/store';
|
||||
import {Axis, Color, ColorScale} from 'plotly.js';
|
||||
|
||||
@@ -292,10 +292,10 @@ export class ParallelCoordinatesGraphComponent extends PlotlyGraphBase implement
|
||||
graph.selectAll('.axis-title').text((d: any) => this.wrap(d.key)).append('title').text(d => (d as any).key);
|
||||
graph.selectAll('.axis .tick text').text((d: string) => this.wrap(d)).append('title').text((d: string) => d);
|
||||
graph.selectAll('.axis .tick text').style('pointer-events', 'auto');
|
||||
graph.selectAll('.tick').on('mouseover', (event, d) => {
|
||||
const tick = d as unknown as SVGGElement;
|
||||
graph.selectAll('.tick').on('mouseover', (d, i, e) => {
|
||||
const tick = e[i] as unknown as SVGGElement;
|
||||
const axis = tick.parentNode as SVGGElement;
|
||||
if (axis.lastChild !== tick) {
|
||||
if (axis && axis.lastChild !== tick) {
|
||||
axis.removeChild(tick);
|
||||
axis.appendChild(tick);
|
||||
}
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
import {Injectable} from '@angular/core';
|
||||
import {act, Actions, Effect, ofType} from '@ngrx/effects';
|
||||
import {Actions, createEffect, ofType} from '@ngrx/effects';
|
||||
import {Store} from '@ngrx/store';
|
||||
import {IExperimentCompareChartsState} from '../reducers/experiments-compare-charts.reducer';
|
||||
import * as chartActions from '../actions/experiments-compare-charts.actions';
|
||||
import {GetMultiPlotCharts, GetMultiScalarCharts, setAxisCache} from '../actions/experiments-compare-charts.actions';
|
||||
import {GetMultiPlotCharts, GetMultiScalarCharts} from '../actions/experiments-compare-charts.actions';
|
||||
import {activeLoader, deactivateLoader, setServerError} from '../../core/actions/layout.actions';
|
||||
import {catchError, debounceTime, mergeMap, map, withLatestFrom} from 'rxjs/operators';
|
||||
import {ApiTasksService} from '../../../business-logic/api-services/tasks.service';
|
||||
import {ApiAuthService} from '../../../business-logic/api-services/auth.service';
|
||||
import {BlTasksService} from '../../../business-logic/services/tasks.service';
|
||||
import {ApiEventsService} from '../../../business-logic/api-services/events.service';
|
||||
import {ApiTasksService} from '~/business-logic/api-services/tasks.service';
|
||||
import {ApiAuthService} from '~/business-logic/api-services/auth.service';
|
||||
import {BlTasksService} from '~/business-logic/services/tasks.service';
|
||||
import {ApiEventsService} from '~/business-logic/api-services/events.service';
|
||||
import {requestFailed} from '../../core/actions/http.actions';
|
||||
import {selectCompareHistogramCacheAxisType, selectCompareSelectedSettingsxAxisType} from '../reducers';
|
||||
import {setRefreshing} from '../actions/compare-header.actions';
|
||||
import {ScalarKeyEnum} from '../../../business-logic/model/events/scalarKeyEnum';
|
||||
import {ScalarKeyEnum} from '~/business-logic/model/events/scalarKeyEnum';
|
||||
|
||||
|
||||
@Injectable()
|
||||
@@ -23,14 +23,12 @@ export class ExperimentsCompareChartsEffects {
|
||||
private authApi: ApiAuthService, private taskBl: BlTasksService, private eventsApi: ApiEventsService) {
|
||||
}
|
||||
|
||||
@Effect()
|
||||
activeLoader = this.actions$.pipe(
|
||||
activeLoader = createEffect(() => this.actions$.pipe(
|
||||
ofType(chartActions.GET_MULTI_SCALAR_CHARTS, chartActions.GET_MULTI_PLOT_CHARTS),
|
||||
map(action => activeLoader(action.type))
|
||||
);
|
||||
));
|
||||
|
||||
@Effect()
|
||||
getMultiScalarCharts = this.actions$.pipe(
|
||||
getMultiScalarCharts = createEffect(() => this.actions$.pipe(
|
||||
ofType<GetMultiScalarCharts>(chartActions.GET_MULTI_SCALAR_CHARTS),
|
||||
debounceTime(200),
|
||||
withLatestFrom(this.store.select(selectCompareSelectedSettingsxAxisType), this.store.select(selectCompareHistogramCacheAxisType)),
|
||||
@@ -39,7 +37,7 @@ export class ExperimentsCompareChartsEffects {
|
||||
[ScalarKeyEnum.IsoTime, ScalarKeyEnum.Timestamp].includes(axisType) &&
|
||||
prevAxisType !== axisType
|
||||
) {
|
||||
return [setRefreshing({payload: false}), deactivateLoader(action.type), setAxisCache({axis: axisType})];
|
||||
return [setRefreshing({payload: false}), deactivateLoader(action.type)];
|
||||
}
|
||||
return this.eventsApi.eventsMultiTaskScalarMetricsIterHistogram({
|
||||
tasks: action.payload.taskIds,
|
||||
@@ -57,10 +55,9 @@ export class ExperimentsCompareChartsEffects {
|
||||
])
|
||||
);
|
||||
})
|
||||
);
|
||||
));
|
||||
|
||||
@Effect()
|
||||
getMultiPlotCharts = this.actions$.pipe(
|
||||
getMultiPlotCharts = createEffect(() => this.actions$.pipe(
|
||||
ofType<GetMultiPlotCharts>(chartActions.GET_MULTI_PLOT_CHARTS),
|
||||
debounceTime(200),
|
||||
mergeMap((action) =>
|
||||
@@ -77,6 +74,6 @@ export class ExperimentsCompareChartsEffects {
|
||||
])
|
||||
)
|
||||
)
|
||||
);
|
||||
));
|
||||
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ import {selectRouterParams} from '../../core/reducers/router-reducer';
|
||||
import {selectAppVisible} from '../../core/reducers/view.reducer';
|
||||
import {MINIMUM_ONLY_FIELDS} from '../../experiments/experiment.consts';
|
||||
import * as exSelectors from '../../experiments/reducers';
|
||||
import {selectExperimentsMetricsCols, selectExperimentsTableCols} from '../../experiments/reducers';
|
||||
import {selectExperimentsMetricsCols, selectExperimentsTableCols, selectTableSortFields} from '../../experiments/reducers';
|
||||
import {selectSelectedProjectId} from '../../core/reducers/projects.reducer';
|
||||
import {addMultipleSortColumns} from '../../shared/utils/shared-utils';
|
||||
|
||||
@@ -70,7 +70,7 @@ export class SelectCompareHeaderEffects {
|
||||
tableSortChange = createEffect(() => this.actions.pipe(
|
||||
ofType(compareAddDialogTableSortChanged),
|
||||
withLatestFrom(
|
||||
this.store.select(selectCompareAddTableSortFields),
|
||||
this.store.select(selectTableSortFields),
|
||||
this.store.select(selectSelectedProjectId),
|
||||
this.store.select(selectExperimentsTableCols),
|
||||
this.store.select(selectExperimentsMetricsCols),
|
||||
@@ -93,7 +93,7 @@ export class SelectCompareHeaderEffects {
|
||||
id: action.tasksIds ? action.tasksIds : tasksIds,
|
||||
only_fields: [...new Set([...MINIMUM_ONLY_FIELDS,
|
||||
...flatten(cols.filter(col => col.id !== 'selected' && !col.hidden).map(col => col.getter || col.id)),
|
||||
...(metricCols ? flatten(metricCols.map(col => col.getter || col.id)) : [])])]
|
||||
...(metricCols ? flatten(metricCols.map(col => col.getter || col.id)) : [])])] as string[]
|
||||
}).pipe(
|
||||
mergeMap((res) => [setSearchExperimentsForCompareResults({payload: [...res?.tasks]}), deactivateLoader(action.type)]),
|
||||
)
|
||||
|
||||
@@ -12,8 +12,8 @@ import {
|
||||
import {createReducer, on} from '@ngrx/store';
|
||||
import {Params} from '@angular/router';
|
||||
import {ITableExperiment} from '../../experiments/shared/common-experiment-model.model';
|
||||
import {commonExperimentsInitialState} from '../../experiments/reducers/common-experiments-view.reducer';
|
||||
import {SortMeta} from 'primeng/api';
|
||||
import {FilterMetadata} from 'primeng/api/filtermetadata';
|
||||
|
||||
export interface CompareHeaderState {
|
||||
searchResultsExperiments: ITableExperiment[];
|
||||
@@ -27,8 +27,8 @@ export interface CompareHeaderState {
|
||||
navigationPreferences: Params;
|
||||
experimentsUpdateTime: { [key: string]: Date };
|
||||
projectColumnsSortOrder: { [projectId: string]: SortMeta[] };
|
||||
projectColumnFilters: { [projectId: string]: { [columnId: string]: { value: any; matchMode: string } } };
|
||||
};
|
||||
projectColumnFilters: { [projectId: string]: { [columnId: string]: FilterMetadata } };
|
||||
}
|
||||
|
||||
|
||||
export const initialState: CompareHeaderState = {
|
||||
@@ -67,7 +67,7 @@ const _compareHeader = createReducer(initialState,
|
||||
on(resetSelectCompareHeader, () => ({...initialState})),
|
||||
on(compareAddDialogSetTableSort, (state, action) => {
|
||||
let orders = action.orders.filter(order => action.colIds.includes(order.field));
|
||||
orders = orders.length > 0 ? orders : commonExperimentsInitialState.tableOrders;
|
||||
orders = orders.length > 0 ? orders : null;
|
||||
return {...state, projectColumnsSortOrder: {...state.projectColumnsSortOrder, [action.projectId]: orders}};
|
||||
}),
|
||||
on(compareAddTableFilterInit, (state, action) => ({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {Task} from '../../../business-logic/model/tasks/task';
|
||||
import {Task} from '~/business-logic/model/tasks/task';
|
||||
import {
|
||||
RESET_EXPERIMENT_METRICS,
|
||||
SET_EXPERIMENT_HISTOGRAM,
|
||||
@@ -8,8 +8,8 @@ import {
|
||||
setAxisCache,
|
||||
UPDATE_EXPERIMENT_SETTINGS
|
||||
} from '../actions/experiments-compare-charts.actions';
|
||||
import {ScalarKeyEnum} from '../../../business-logic/model/events/scalarKeyEnum';
|
||||
import {GroupByCharts} from '../../experiments/reducers/common-experiment-output.reducer';
|
||||
import {ScalarKeyEnum} from '~/business-logic/model/events/scalarKeyEnum';
|
||||
import {ExperimentSettings} from '../../experiments/reducers/common-experiment-output.reducer';
|
||||
import {IMultiplot} from '@common/tasks/tasks.utils';
|
||||
|
||||
export type MetricValueType = 'min_value' | 'max_value' | 'value';
|
||||
@@ -42,23 +42,15 @@ export interface IExperimentCompareChartsState {
|
||||
metricsHistogramCharts: any;
|
||||
cachedAxisType: ScalarKeyEnum;
|
||||
metricsPlotsCharts: IMultiplot;
|
||||
settingsList: Array<IExperimentCompareSettings>;
|
||||
settingsList: Array<ExperimentCompareSettings>;
|
||||
searchTerm: string;
|
||||
showSettingsBar: boolean;
|
||||
selectedExperiments: Array<string>;
|
||||
}
|
||||
|
||||
export interface IExperimentCompareSettings {
|
||||
export interface ExperimentCompareSettings extends Omit<ExperimentSettings, 'id' | 'selectedMetric'> {
|
||||
id: Array<Task['id']>;
|
||||
hiddenMetricsScalar: Array<string>;
|
||||
hiddenMetricsPlot: Array<string>;
|
||||
selectedHyperParams: Array<string>;
|
||||
selectedMetric: SelectedMetric;
|
||||
selectedScalar: string;
|
||||
selectedPlot: string;
|
||||
smoothWeight: number;
|
||||
xAxisType: ScalarKeyEnum;
|
||||
groupBy: GroupByCharts;
|
||||
}
|
||||
|
||||
export const initialState: IExperimentCompareChartsState = {
|
||||
@@ -85,13 +77,21 @@ export function experimentsCompareChartsReducer(state: IExperimentCompareChartsS
|
||||
case SET_EXPERIMENT_PLOTS:
|
||||
return {...state, metricsPlotsCharts: action.payload};
|
||||
case UPDATE_EXPERIMENT_SETTINGS: {
|
||||
let newSettings;
|
||||
const isExperimentExists = state.settingsList.find((setting) => setting.id.join() === action.payload.id.join());
|
||||
if (isExperimentExists) {
|
||||
newSettings = state.settingsList.map(setting => setting.id.join() === action.payload.id.join() ? {...setting, ...action.payload.changes} : setting);
|
||||
let newSettings: ExperimentCompareSettings[];
|
||||
const changes = {...action.payload.changes, lastModified: (new Date()).getTime()} as ExperimentCompareSettings;
|
||||
const ids = action.payload.id.join();
|
||||
const experimentExists = state.settingsList.find((setting) => setting.id.join() === ids);
|
||||
const discardBefore = new Date()
|
||||
discardBefore.setMonth(discardBefore.getMonth() - 6);
|
||||
if (experimentExists) {
|
||||
newSettings = state.settingsList
|
||||
.filter(setting => discardBefore < new Date(setting.lastModified || 1648771200000))
|
||||
.map(setting => setting.id.join() === ids ? {...setting, ...changes} : setting);
|
||||
} else {
|
||||
newSettings = state.settingsList.slice();
|
||||
newSettings.push({id: action.payload.id, ...action.payload.changes});
|
||||
newSettings = [
|
||||
...state.settingsList.filter(setting => discardBefore < new Date(setting.lastModified || 1648771200000)),
|
||||
{id: action.payload.id, ...changes}
|
||||
];
|
||||
}
|
||||
return {...state, settingsList: newSettings};
|
||||
}
|
||||
|
||||
@@ -1,22 +1,18 @@
|
||||
import {ActionReducerMap, createSelector} from '@ngrx/store';
|
||||
import {ExperimentCompareDetailsState, experimentsCompareDetailsReducer} from './experiments-compare-details.reducer';
|
||||
import {experimentsCompareChartsReducer, GroupedHyperParams, IExperimentCompareChartsState, IExperimentCompareSettings, MetricOption, MetricValueType} from './experiments-compare-charts.reducer';
|
||||
import {experimentsCompareChartsReducer, GroupedHyperParams, IExperimentCompareChartsState, ExperimentCompareSettings, MetricOption, MetricValueType} from './experiments-compare-charts.reducer';
|
||||
import {experimentsCompareMetricsValuesReducer, IExperimentCompareMetricsValuesState, MetricSortBy} from './experiments-compare-metrics-values.reducer';
|
||||
import {experimentsCompareDebugImagesReducer} from './experiments-compare-debug-images.reducer';
|
||||
import {get} from 'lodash/fp';
|
||||
import {Task} from '../../../business-logic/model/tasks/task';
|
||||
import {Task} from '~/business-logic/model/tasks/task';
|
||||
import {compareHeader, CompareHeaderState} from './compare-header.reducer';
|
||||
import {IExperimentDetail} from '../../../features/experiments-compare/experiments-compare-models';
|
||||
import {ScalarKeyEnum} from '../../../business-logic/model/events/scalarKeyEnum';
|
||||
import {IExperimentDetail} from '~/features/experiments-compare/experiments-compare-models';
|
||||
import {ScalarKeyEnum} from '~/business-logic/model/events/scalarKeyEnum';
|
||||
import {scalarsGraphReducer, ScalarsGraphState} from './experiments-compare-scalars-graph.reducer';
|
||||
import {ExperimentParams} from '../shared/experiments-compare-details.model';
|
||||
import {ExperimentCompareParamsState, experimentsCompareParamsReducer} from './experiments-compare-params.reducer';
|
||||
import {GroupByCharts} from '../../experiments/reducers/common-experiment-output.reducer';
|
||||
import {ITableExperiment} from '../../experiments/shared/common-experiment-model.model';
|
||||
import {selectSelectedProjectId} from '../../core/reducers/projects.reducer';
|
||||
import {selectRouterConfig} from '../../core/reducers/router-reducer';
|
||||
import {TABLE_SORT_ORDER} from '../../shared/ui-components/data/table/table.consts';
|
||||
import { EXPERIMENTS_TABLE_COL_FIELDS } from '../../../features/experiments/shared/experiments.const';
|
||||
|
||||
export const experimentsCompareReducers: ActionReducerMap<any, any> = {
|
||||
details : experimentsCompareDetailsReducer,
|
||||
@@ -44,21 +40,22 @@ export const selectExperimentIdsParams = createSelector(selectExperimentsParams,
|
||||
|
||||
|
||||
// select experiments for compare and header
|
||||
export const selectCompareHeader = createSelector(experimentsCompare, (state): CompareHeaderState => state ? state.compareHeader : {});
|
||||
export const selectCompareHeader = createSelector(experimentsCompare, state => (state?.compareHeader ?? {}) as CompareHeaderState);
|
||||
export const selectIsCompare = createSelector(selectRouterConfig, (config): boolean => config?.includes('compare-experiments'));
|
||||
export const selectIsPipelines = createSelector(selectRouterConfig, (config): boolean => config?.[0] === 'pipelines');
|
||||
|
||||
export const selectCompareAddTableSortFields = createSelector(selectCompareHeader, selectSelectedProjectId,
|
||||
(state, projectId) => state.projectColumnsSortOrder?.[projectId] || [{field: EXPERIMENTS_TABLE_COL_FIELDS.LAST_UPDATE, order: TABLE_SORT_ORDER.DESC}]);
|
||||
(state, projectId) => state.projectColumnsSortOrder?.[projectId] || null);
|
||||
export const selectCompareAddTableFilters = createSelector(selectCompareHeader, selectSelectedProjectId,
|
||||
(state, projectId) => state.projectColumnFilters?.[projectId] || {});
|
||||
export const selectSelectedExperimentsForCompareAdd = createSelector(selectCompareHeader, (state): ITableExperiment[] => state ? state.searchResultsExperiments : []);
|
||||
export const selectExperimentsForCompareSearchTerm = createSelector(selectCompareHeader, (state) => state?.searchTerm);
|
||||
export const selectShowAddExperimentsForCompare = createSelector(selectCompareHeader, (state) => state?.showSearch);
|
||||
export const selectHideIdenticalFields = createSelector(selectCompareHeader, (state) => state?.hideIdenticalRows);
|
||||
export const selectShowScalarsOptions = createSelector(selectCompareHeader, (state) => state?.showScalarOptions);
|
||||
export const selectRefreshing = createSelector(selectCompareHeader, (state) => state ? {refreshing: state.refreshing, autoRefresh: state.autoRefresh} : {refreshing: false, autoRefresh: false});
|
||||
export const selectExperimentsUpdateTime = createSelector(selectCompareHeader, (state) => state ? state.experimentsUpdateTime : {});
|
||||
export const selectNavigationPreferences = createSelector(selectCompareHeader, (state) => state ? state.navigationPreferences : {});
|
||||
export const selectSelectedExperimentsForCompareAdd = createSelector(selectCompareHeader, state => state?.searchResultsExperiments);
|
||||
export const selectExperimentsForCompareSearchTerm = createSelector(selectCompareHeader, state => state?.searchTerm);
|
||||
export const selectShowAddExperimentsForCompare = createSelector(selectCompareHeader, state => state?.showSearch);
|
||||
export const selectHideIdenticalFields = createSelector(selectCompareHeader, state => state?.hideIdenticalRows);
|
||||
export const selectShowScalarsOptions = createSelector(selectCompareHeader, state => state?.showScalarOptions);
|
||||
export const selectRefreshing = createSelector(selectCompareHeader, state => state ? {refreshing: state.refreshing, autoRefresh: state.autoRefresh} : {refreshing: false, autoRefresh: false});
|
||||
export const selectExperimentsUpdateTime = createSelector(selectCompareHeader, state => state ? state.experimentsUpdateTime : {});
|
||||
export const selectNavigationPreferences = createSelector(selectCompareHeader, state => state ? state.navigationPreferences : {});
|
||||
|
||||
// Metric Values
|
||||
export const compareMetricsValues = createSelector(experimentsCompare, (state): IExperimentCompareMetricsValuesState => state ? state.metricsValues : {});
|
||||
@@ -68,30 +65,30 @@ export const selectCompareMetricsValuesSortConfig = createSelector(compareMetric
|
||||
// Charts
|
||||
export const compareCharts = createSelector(experimentsCompare, (state): IExperimentCompareChartsState => state ? state.charts : {});
|
||||
export const selectSelectedExperiments = createSelector(compareCharts, (state): Array<string> => state ? state.selectedExperiments : []);
|
||||
export const selectCompareHistogramCacheAxisType = createSelector(compareCharts, (state) => state.cachedAxisType);
|
||||
export const selectCompareHistogramCacheAxisType = createSelector(compareCharts, state => state.cachedAxisType);
|
||||
export const selectCompareTasksPlotCharts = createSelector(compareCharts, state => state.metricsPlotsCharts);
|
||||
|
||||
export const selectSelectedExperimentSettings = createSelector(compareCharts, selectSelectedExperiments,
|
||||
(output, currentExperiments): IExperimentCompareSettings => output.settingsList && output.settingsList.find((setting) => currentExperiments && setting.id.join() === currentExperiments.join()));
|
||||
(output, currentExperiments): ExperimentCompareSettings => output.settingsList && output.settingsList.find((setting) => currentExperiments && setting.id.join() === currentExperiments.join()));
|
||||
|
||||
export const selectSelectedSettingsHiddenPlot = createSelector(selectSelectedExperimentSettings,
|
||||
(settings): Array<string> => get('hiddenMetricsPlot', settings) || []);
|
||||
(settings): Array<string> => settings?.hiddenMetricsPlot || []);
|
||||
|
||||
export const selectSelectedSettigsHyperParams = createSelector(selectSelectedExperimentSettings,
|
||||
(settings): Array<string> => get('selectedHyperParams', settings) || []);
|
||||
export const selectSelectedSettingsHyperParams = createSelector(selectSelectedExperimentSettings,
|
||||
(settings): Array<string> => settings?.selectedHyperParams || []);
|
||||
|
||||
export const selectSelectedSettigsMetric = createSelector(selectSelectedExperimentSettings,
|
||||
(settings) => get('selectedMetric', settings) || null);
|
||||
export const selectSelectedSettingsMetric = createSelector(selectSelectedExperimentSettings,
|
||||
(settings) => settings?.selectedMetric || null);
|
||||
|
||||
export const selectSelectedSettingsHiddenScalar = createSelector(selectSelectedExperimentSettings,
|
||||
(settings): Array<string> => get('hiddenMetricsScalar', settings) || []);
|
||||
(settings): Array<string> => settings?.hiddenMetricsScalar || []);
|
||||
|
||||
export const selectExperimentMetricsSearchTerm = createSelector(compareCharts, (state) => state.searchTerm);
|
||||
export const selectCompareSelectedSettingsSmoothWeight = createSelector(selectSelectedExperimentSettings,
|
||||
(settings): number => get('smoothWeight', settings) || 0);
|
||||
(settings): number => settings?.smoothWeight || 0);
|
||||
|
||||
export const selectCompareSelectedSettingsxAxisType = createSelector(selectSelectedExperimentSettings,
|
||||
(settings): ScalarKeyEnum => get('xAxisType', settings) || ScalarKeyEnum.Iter);
|
||||
settings => settings?.xAxisType ?? ScalarKeyEnum.Iter as ScalarKeyEnum);
|
||||
|
||||
export const selectCompareSelectedSettingsGroupBy = createSelector(selectSelectedExperimentSettings,
|
||||
(settings): GroupByCharts => settings?.groupBy || GroupByCharts.None);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import {Action, createAction, props} from '@ngrx/store';
|
||||
import {ISelectedExperiment} from '../../../features/experiments/shared/experiment-info.model';
|
||||
import {IExperimentSettings} from '../reducers/common-experiment-output.reducer';
|
||||
import {ScalarKeyEnum} from '../../../business-logic/model/events/scalarKeyEnum';
|
||||
import {MetricsPlotEvent} from '../../../business-logic/model/events/metricsPlotEvent';
|
||||
import {EventsScalarMetricsIterRawRequest} from '../../../business-logic/model/events/eventsScalarMetricsIterRawRequest';
|
||||
import {EventsScalarMetricsIterRawResponse} from '../../../business-logic/model/events/eventsScalarMetricsIterRawResponse';
|
||||
import {ISelectedExperiment} from '~/features/experiments/shared/experiment-info.model';
|
||||
import {ExperimentSettings} from '../reducers/common-experiment-output.reducer';
|
||||
import {ScalarKeyEnum} from '~/business-logic/model/events/scalarKeyEnum';
|
||||
import {MetricsPlotEvent} from '~/business-logic/model/events/metricsPlotEvent';
|
||||
import {EventsScalarMetricsIterRawRequest} from '~/business-logic/model/events/eventsScalarMetricsIterRawRequest';
|
||||
import {EventsScalarMetricsIterRawResponse} from '~/business-logic/model/events/eventsScalarMetricsIterRawResponse';
|
||||
|
||||
export const EXPERIMENTS_OUTPUT_PREFIX = 'EXPERIMENTS_OUTPUT_';
|
||||
|
||||
@@ -114,7 +114,7 @@ export const setExperimentLog = createAction(
|
||||
export class SetExperimentSettings implements Action {
|
||||
readonly type = UPDATE_EXPERIMENT_SETTINGS;
|
||||
|
||||
constructor(public payload: { id: string; changes: Partial<IExperimentSettings> }) {
|
||||
constructor(public payload: { id: string; changes: Partial<ExperimentSettings> }) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
import {Action, createAction, props} from '@ngrx/store';
|
||||
import {Task} from '../../../business-logic/model/tasks/task';
|
||||
import {IExperimentInfo, ISelectedExperiment} from '../../../features/experiments/shared/experiment-info.model';
|
||||
import {Model} from '../../../business-logic/model/models/model';
|
||||
import {Task} from '~/business-logic/model/tasks/task';
|
||||
import {IExperimentInfo, ISelectedExperiment} from '~/features/experiments/shared/experiment-info.model';
|
||||
import {ITableExperiment} from '../shared/common-experiment-model.model';
|
||||
import {ParamsItem} from '../../../business-logic/model/tasks/paramsItem';
|
||||
import {ConfigurationItem} from '../../../business-logic/model/tasks/configurationItem';
|
||||
import {IExperimentInfoState} from '../../../features/experiments/reducers/experiment-info.reducer';
|
||||
import {experimentSectionsEnum} from '../../../features/experiments/shared/experiments.const';
|
||||
import {ParamsItem} from '~/business-logic/model/tasks/paramsItem';
|
||||
import {ConfigurationItem} from '~/business-logic/model/tasks/configurationItem';
|
||||
import {IExperimentInfoState} from '~/features/experiments/reducers/experiment-info.reducer';
|
||||
import {ActivatedRoute} from '@angular/router';
|
||||
import {ITask} from '../../../business-logic/model/al-task';
|
||||
|
||||
export const EXPERIMENTS_INFO_PREFIX = 'EXPERIMENTS_INFO_';
|
||||
export const GET_EXPERIMENT_INFO = EXPERIMENTS_INFO_PREFIX + 'GET_EXPERIMENT_INFO';
|
||||
@@ -113,7 +110,21 @@ export const setExperimentSaving = createAction(
|
||||
EXPERIMENTS_INFO_PREFIX + 'SET_SAVING', props<{ saving: boolean }>());
|
||||
|
||||
export const getExperimentConfigurationObj = createAction(
|
||||
EXPERIMENTS_INFO_PREFIX + 'GET_CONFIGURATION_OBJ');
|
||||
EXPERIMENTS_INFO_PREFIX + 'GET_CONFIGURATION_OBJ',
|
||||
);
|
||||
export const getPipelineConfigurationObj = createAction(
|
||||
EXPERIMENTS_INFO_PREFIX + 'GET_PIPELINE_CONFIGURATION_OBJ',
|
||||
);
|
||||
|
||||
export const getSelectedPipelineStep = createAction(
|
||||
EXPERIMENTS_INFO_PREFIX + 'GET_PIPELINE_STEP',
|
||||
props<{ id:string }>()
|
||||
);
|
||||
|
||||
export const setSelectedPipelineStep = createAction(
|
||||
EXPERIMENTS_INFO_PREFIX + 'SET_PIPELINE_STEP',
|
||||
props<{ step:IExperimentInfo }>()
|
||||
);
|
||||
|
||||
export const updateExperimentAtPath = createAction(
|
||||
EXPERIMENTS_INFO_PREFIX + 'UPDATE_EXPERIMENT_AT_PATH',
|
||||
@@ -167,7 +178,6 @@ export class DeactivateEdit implements Action {
|
||||
|
||||
export class SetExperimentFormErrors implements Action {
|
||||
readonly type = SET_EXPERIMENT_FORM_ERRORS;
|
||||
|
||||
constructor(public payload: { [key: string]: any } | null) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import {Action, createAction, props} from '@ngrx/store';
|
||||
import {ISelectedExperiment} from '../../../features/experiments/shared/experiment-info.model';
|
||||
import {Project} from '../../../business-logic/model/projects/project';
|
||||
import {Queue} from '../../../business-logic/model/queues/queue';
|
||||
import {ISelectedExperiment} from '~/features/experiments/shared/experiment-info.model';
|
||||
import {Project} from '~/business-logic/model/projects/project';
|
||||
import {Queue} from '~/business-logic/model/queues/queue';
|
||||
import {CloneExperimentPayload, ITableExperiment} from '../shared/common-experiment-model.model';
|
||||
import {EntityTypeEnum} from '~/shared/constants/non-common-consts';
|
||||
import { PipelinesStartPipelineRequest } from '~/business-logic/model/pipelines/pipelinesStartPipelineRequest';
|
||||
|
||||
export const EXPERIMENTS_INFO_PREFIX = 'EXPERIMENTS_INFO_';
|
||||
|
||||
@@ -19,6 +21,21 @@ export const stopClicked = createAction(
|
||||
EXPERIMENTS_INFO_PREFIX + '[stop experiments]',
|
||||
props<{ selectedEntities: ISelectedExperiment[] }>()
|
||||
);
|
||||
export const startPipeline = createAction(
|
||||
EXPERIMENTS_INFO_PREFIX + '[start pipeline]',
|
||||
props<PipelinesStartPipelineRequest>()
|
||||
);
|
||||
|
||||
export const getControllerForStartPipelineDialog = createAction(
|
||||
EXPERIMENTS_INFO_PREFIX + '[Get Controller For Start Pipeline]',
|
||||
props<{task:string}>()
|
||||
);
|
||||
|
||||
export const setControllerForStartPipelineDialog = createAction(
|
||||
EXPERIMENTS_INFO_PREFIX + '[Set Controller For Start Pipeline]',
|
||||
props<{task:Task}>()
|
||||
);
|
||||
|
||||
|
||||
export const changeProjectRequested = createAction(
|
||||
EXPERIMENTS_INFO_PREFIX + '[change project requested]',
|
||||
@@ -42,14 +59,9 @@ export const addTag = createAction(
|
||||
props<{ experiments: Partial<ITableExperiment>[]; tag: string }>()
|
||||
);
|
||||
|
||||
export const getAllTasksChildren = createAction(
|
||||
export const abortAllChildren = createAction(
|
||||
EXPERIMENTS_INFO_PREFIX + '[get all tasks children]',
|
||||
props<{ experiments: string[]}>()
|
||||
);
|
||||
|
||||
export const setAllTasksChildren = createAction(
|
||||
EXPERIMENTS_INFO_PREFIX + '[set all tasks children]',
|
||||
props<{ experiments: ITableExperiment[]}>()
|
||||
props<{ experiments: ISelectedExperiment[]}>()
|
||||
);
|
||||
|
||||
export const removeTag = createAction(
|
||||
@@ -78,10 +90,10 @@ export const enqueueClicked = createAction(
|
||||
|
||||
export const archiveSelectedExperiments = createAction(
|
||||
EXPERIMENTS_INFO_PREFIX + '[archive selected experiments]',
|
||||
props<{ selectedEntities: ISelectedExperiment[]; skipUndo?: boolean }>()
|
||||
props<{ selectedEntities: ISelectedExperiment[]; skipUndo?: boolean; entityType?: EntityTypeEnum }>()
|
||||
);
|
||||
|
||||
export const restoreSelectedExperiments = createAction(
|
||||
EXPERIMENTS_INFO_PREFIX + '[restore selected experiments]',
|
||||
props<{ selectedEntities: ISelectedExperiment[]; skipUndo?: boolean }>()
|
||||
props<{ selectedEntities: ISelectedExperiment[]; skipUndo?: boolean; entityType?: EntityTypeEnum }>()
|
||||
);
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import {createAction, props} from '@ngrx/store';
|
||||
import {ITableExperiment} from '../shared/common-experiment-model.model';
|
||||
import {ISmCol} from '../../shared/ui-components/data/table/table.consts';
|
||||
import {MetricVariantResult} from '../../../business-logic/model/projects/metricVariantResult';
|
||||
import {MetricVariantResult} from '~/business-logic/model/projects/metricVariantResult';
|
||||
import {TableFilter} from '../../shared/utils/tableParamEncode';
|
||||
import {User} from '../../../business-logic/model/users/user';
|
||||
import {ProjectsGetTaskParentsResponseParents} from '../../../business-logic/model/projects/projectsGetTaskParentsResponseParents';
|
||||
import {User} from '~/business-logic/model/users/user';
|
||||
import {ProjectsGetTaskParentsResponseParents} from '~/business-logic/model/projects/projectsGetTaskParentsResponseParents';
|
||||
import {SortMeta} from 'primeng/api';
|
||||
import {CountAvailableAndIsDisableSelectedFiltered} from '@common/shared/entity-page/items.utils';
|
||||
import {TasksEnqueueManyResponseSucceeded} from '../../../business-logic/model/tasks/tasksEnqueueManyResponseSucceeded';
|
||||
import {TasksEnqueueManyResponseSucceeded} from '~/business-logic/model/tasks/tasksEnqueueManyResponseSucceeded';
|
||||
import {EXPERIMENTS_INFO_PREFIX} from '@common/experiments/actions/common-experiments-menu.actions';
|
||||
|
||||
export const EXPERIMENTS_PREFIX = 'EXPERIMENTS_';
|
||||
@@ -18,6 +18,11 @@ export const getExperimentsWithPageSize = createAction(EXPERIMENTS_PREFIX + ' [g
|
||||
props<{pageSize: number}>());
|
||||
export const getNextExperiments = createAction(EXPERIMENTS_PREFIX + '[get next experiments]');
|
||||
|
||||
export const setTableCols = createAction(
|
||||
EXPERIMENTS_PREFIX + ' [set table cols]',
|
||||
props<{ cols: ISmCol[]}>()
|
||||
);
|
||||
|
||||
export const refreshExperiments = createAction(
|
||||
EXPERIMENTS_PREFIX + ' [refresh experiment]',
|
||||
props<{ hideLoader: boolean; autoRefresh?: boolean}>()
|
||||
@@ -25,7 +30,7 @@ export const refreshExperiments = createAction(
|
||||
|
||||
export const setExperiments = createAction(
|
||||
EXPERIMENTS_PREFIX + ' [set experiments]',
|
||||
props<{experiments: ITableExperiment[]}>()
|
||||
props<{experiments: ITableExperiment[], noPreferences?: boolean}>()
|
||||
);
|
||||
|
||||
export const setExperimentInPlace = createAction(
|
||||
@@ -63,6 +68,8 @@ export const setSelectedExperiments = createAction(
|
||||
props<{experiments: ITableExperiment[]}>()
|
||||
);
|
||||
|
||||
export const updateUrlParams = createAction(EXPERIMENTS_PREFIX + '[update URL params from state]');
|
||||
|
||||
export const setSelectedExperiment = createAction(
|
||||
EXPERIMENTS_PREFIX + ' [set selected experiment]',
|
||||
props<{experiment: ITableExperiment}>()
|
||||
@@ -83,10 +90,14 @@ export const toggleColHidden = createAction(
|
||||
props<{columnId: string; projectId: string}>()
|
||||
);
|
||||
|
||||
export const setHiddenColumns = createAction(
|
||||
EXPERIMENTS_PREFIX + 'SET_HIDDEN_COLS',
|
||||
export const setVisibleColumnsForProject = createAction(
|
||||
EXPERIMENTS_PREFIX + 'SET_HIDDEN_COLS_FOR_PROJECT',
|
||||
props<{ visibleColumns: string[]; projectId: string }>()
|
||||
);
|
||||
export const setHiddenCols = createAction(
|
||||
EXPERIMENTS_PREFIX + 'SET_HIDDEN_COLS',
|
||||
props<{ hiddenCols: { [key: string]: boolean } }>()
|
||||
);
|
||||
|
||||
export const setUsers = createAction(
|
||||
EXPERIMENTS_PREFIX + 'SET_USERS',
|
||||
@@ -109,7 +120,7 @@ export const getFilteredUsers = createAction(EXPERIMENTS_PREFIX + 'GET_FILTERED_
|
||||
|
||||
export const tableFilterChanged = createAction(
|
||||
EXPERIMENTS_PREFIX + '[table filter changed]',
|
||||
props<{filter: TableFilter; projectId: string}>()
|
||||
props<{filters: TableFilter[]; projectId: string}>()
|
||||
);
|
||||
|
||||
export const tableSortChanged = createAction(
|
||||
@@ -186,7 +197,7 @@ export const setColumnWidth = createAction(
|
||||
|
||||
export const setColsOrderForProject = createAction(
|
||||
EXPERIMENTS_PREFIX + ' [set cols order]',
|
||||
props<{ cols: string[]; project: string; fromUrl?: boolean }>()
|
||||
props<{ cols: string[]; project: string;}>()
|
||||
);
|
||||
|
||||
export const clearHyperParamsCols = createAction(
|
||||
@@ -199,13 +210,6 @@ export const resetSortOrder = createAction(
|
||||
props<{sortIndex: number; projectId: string}>()
|
||||
);
|
||||
|
||||
export const setArchive = createAction(
|
||||
EXPERIMENTS_PREFIX + 'SET_ARCHIVE',
|
||||
props<{ archive: boolean }>()
|
||||
);
|
||||
|
||||
export const afterSetArchive = createAction(EXPERIMENTS_PREFIX + 'AFTER_SET_ARCHIVE');
|
||||
|
||||
export const setSplitSize = createAction(EXPERIMENTS_PREFIX + 'SET_SPLIT_SIZE', props<{ splitSize: number }>());
|
||||
|
||||
export const hyperParamSelectedInfoExperiments = createAction(
|
||||
|
||||
@@ -11,7 +11,6 @@ import {ExperimentHeaderComponent} from './dumb/experiment-header/experiment-hea
|
||||
import {ExperimentInfoHeaderComponent} from './dumb/experiment-info-header/experiment-info-header.component';
|
||||
import {ExperimentInfoGeneralComponent} from './containers/experiment-info-general/experiment-info-general.component';
|
||||
import {ExperimentGeneralInfoComponent} from './dumb/experiment-general-info/experiment-general-info.component';
|
||||
import {ExperimentNetworkDesignFormComponent} from './dumb/experiment-network-design-form/experiment-network-design-form.component';
|
||||
import {ExperimentModelsFormViewComponent} from './dumb/experiment-models-form-view/experiment-models-form-view.component';
|
||||
import {ExperimentExecutionSourceCodeComponent} from './dumb/experiment-execution-source-code/experiment-execution-source-code.component';
|
||||
import {ExperimentExecutionParametersComponent} from './dumb/experiment-execution-parameters/experiment-execution-parameters.component';
|
||||
@@ -21,7 +20,7 @@ import {ModelAutoPopulateDialogComponent} from './dumb/model-auto-populate-dialo
|
||||
import {ExperimentTableCardComponent} from './dumb/experiment-table-card/experiment-table-card.component';
|
||||
import {SMSharedModule} from '../shared/shared.module';
|
||||
import {CommonLayoutModule} from '../layout/layout.module';
|
||||
import {ExperimentSharedModule} from '../../features/experiments/shared/experiment-shared.module';
|
||||
import {ExperimentSharedModule} from '~/features/experiments/shared/experiment-shared.module';
|
||||
import {CommonExperimentSharedModule} from './shared/common-experiment-shared.module';
|
||||
import {RouterModule} from '@angular/router';
|
||||
import {SMMaterialModule} from '../shared/material/material.module';
|
||||
@@ -47,7 +46,7 @@ import {NoUnderscorePipe} from '../shared/pipes/no-underscore.pipe';
|
||||
import {ExperimentHyperParamsNavbarComponent} from './dumb/experiment-hyper-params-navbar/experiment-hyper-params-navbar.component';
|
||||
import {ExperimentInfoTaskModelComponent} from './containers/experiment-info-task-model/experiment-info-task-model.component';
|
||||
import {ExperimentInfoHyperParametersFormContainerComponent} from './containers/experiment-info-hyper-parameters-form-container/experiment-info-hyper-parameters-form-container.component';
|
||||
import {SharedModule} from '../../shared/shared.module';
|
||||
import {SharedModule} from '~/shared/shared.module';
|
||||
import {CommonDeleteDialogModule} from '../shared/entity-page/entity-delete/common-delete-dialog.module';
|
||||
import {ExperimentInfoEditDescriptionComponent} from './dumb/experiment-info-edit-description/experiment-info-edit-description.component';
|
||||
import {ExperimentOutputLogModule} from './shared/experiment-output-log/experiment-output-log.module';
|
||||
@@ -71,7 +70,6 @@ import { GetVariantWithoutRoundPipe } from './dumb/experiments-table/hyper-param
|
||||
ExperimentInfoTaskModelComponent,
|
||||
ExperimentInfoGeneralComponent,
|
||||
ExperimentGeneralInfoComponent,
|
||||
ExperimentNetworkDesignFormComponent,
|
||||
ExperimentModelsFormViewComponent,
|
||||
ExperimentOutputModelViewComponent,
|
||||
ExperimentExecutionSourceCodeComponent,
|
||||
@@ -98,7 +96,7 @@ import { GetVariantWithoutRoundPipe } from './dumb/experiments-table/hyper-param
|
||||
ExperimentInfoHeaderComponent,
|
||||
ExperimentExecutionSourceCodeComponent,
|
||||
SelectMetricForCustomColComponent,
|
||||
ExperimentExecutionParametersComponent,ExperimentsTableComponent],
|
||||
ExperimentExecutionParametersComponent, ExperimentsTableComponent, ExperimentHeaderComponent],
|
||||
imports: [
|
||||
AngularSplitModule,
|
||||
ScrollingModule,
|
||||
|
||||
@@ -59,13 +59,12 @@
|
||||
>
|
||||
<button extra-buttons
|
||||
*ngIf="formData.diff && editable && !showExtraDataSpinner"
|
||||
class="btn-dark-fill mr-3 flex-1"
|
||||
class="btn-dark-fill terminal mr-3 flex-1"
|
||||
(click)="diffSection.editModeChanged(true)">EDIT</button>
|
||||
<button extra-buttons
|
||||
*ngIf="formData.diff && editable && !showExtraDataSpinner"
|
||||
class="btn-dark-fill mr-3 flex-1"
|
||||
class="btn-dark-fill terminal mr-3 flex-1"
|
||||
(click)="discardDiff()">
|
||||
<i class="p-1 fa fa-trash"></i>
|
||||
DISCARD DIFFS
|
||||
</button>
|
||||
</sm-scroll-textarea>
|
||||
@@ -90,13 +89,12 @@
|
||||
[formData]="formData.requirements?.pip">
|
||||
<button extra-buttons
|
||||
*ngIf="formData?.requirements?.pip && editable && !showExtraDataSpinner"
|
||||
class="btn-dark-fill mr-3 flex-1"
|
||||
class="btn-dark-fill terminal mr-3 flex-1"
|
||||
(click)="requirementsSection.editModeChanged(true)">EDIT</button>
|
||||
<button extra-buttons
|
||||
*ngIf="formData.requirements?.pip && editable && !showExtraDataSpinner"
|
||||
class="btn-dark-fill mr-3 flex-1"
|
||||
class="btn-dark-fill terminal mr-3 flex-1"
|
||||
(click)="clearInstalledPackages()">
|
||||
<i class="p-1 fa fa-trash"></i>
|
||||
CLEAR
|
||||
</button>
|
||||
</sm-scroll-textarea>
|
||||
@@ -144,13 +142,12 @@
|
||||
[formData]="formData?.container?.setup_shell_script">
|
||||
<button extra-buttons
|
||||
*ngIf="formData?.container?.setup_shell_script && editable && !showExtraDataSpinner"
|
||||
class="btn-dark-fill mr-3 flex-1"
|
||||
class="btn-dark-fill terminal mr-3 flex-1"
|
||||
(click)="containerSetupShellSection.editModeChanged(true)">EDIT</button>
|
||||
<button extra-buttons
|
||||
*ngIf="formData.container?.setup_shell_script && editable && !showExtraDataSpinner"
|
||||
class="btn-dark-fill mr-3 flex-1"
|
||||
class="btn-dark-fill terminal mr-3 flex-1"
|
||||
(click)="clearSetupShellScript()">
|
||||
<i class="p-1 fa fa-trash"></i>
|
||||
CLEAR
|
||||
</button>
|
||||
</sm-scroll-textarea>
|
||||
|
||||
@@ -68,12 +68,6 @@
|
||||
padding: 5px 15px;
|
||||
}
|
||||
|
||||
.btn-dark-fill {
|
||||
background-color: $blue-600;
|
||||
color: #a7b2d8;
|
||||
margin: 0 6px !important;
|
||||
}
|
||||
|
||||
.copy-textarea {
|
||||
position: absolute;
|
||||
right: 32px;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<sm-overlay [backdropActive]="backdropActive$|async"></sm-overlay>
|
||||
<sm-editable-section #parameterSection
|
||||
class="light-theme"
|
||||
*ngIf="(selectedSectionHyperParams$| async).length>0 || propSection"
|
||||
[editable]="(!isExample) && ((editable$ | async) || propSection)"
|
||||
[disableSave]="!executionParamsForm?.hyperParameters?.form?.valid"
|
||||
@@ -10,14 +11,15 @@
|
||||
<sm-section-header [label]="(selectedSection | replaceViaMapPipe:sectionReplaceMap) | uppercase "></sm-section-header>
|
||||
<sm-search search-button
|
||||
#search
|
||||
class="table-search dark-theme"
|
||||
[enableJumpToNextResult]="true"
|
||||
[minimumChars]="0"
|
||||
class="table-search"
|
||||
[value]="searchedText"
|
||||
[enableNavigation]="true"
|
||||
[minimumChars]="1"
|
||||
[debounceTime]="0"
|
||||
[expandOnHover]="true"
|
||||
[searchResultsCount]="searchResultsCount"
|
||||
[searchCounterIndex]="executionParamsForm.matchIndex"
|
||||
(valueChanged)="searchTable($event)"
|
||||
(jumpToResult)="executionParamsForm.jumpToResult($event)"
|
||||
></sm-search>
|
||||
<sm-experiment-execution-parameters
|
||||
#executionParamsForm
|
||||
@@ -29,6 +31,6 @@
|
||||
(formDataChanged)="onFormValuesChanged($event)"
|
||||
(searchCounterChanged)="searchCounterChanged($event)"
|
||||
(resetSearch)="search.clear(false)"
|
||||
(scrollToResultCounterChanged)="scrollIndexCounterChanged($event)"
|
||||
(scrollToResultCounterReset)="scrollIndexCounterReset()"
|
||||
></sm-experiment-execution-parameters>
|
||||
</sm-editable-section>
|
||||
|
||||
@@ -15,8 +15,9 @@
|
||||
height: calc(100% - 42px);
|
||||
}
|
||||
sm-search.table-search {
|
||||
padding-right: 2px;
|
||||
border-radius: 4px;
|
||||
color: #a7b2d8 !important;
|
||||
color: $blue-280 !important;
|
||||
background-color: $blue-600 !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,11 +7,11 @@ import {
|
||||
selectIsSelectedExperimentInDev
|
||||
} from '../../reducers';
|
||||
import {ICommonExperimentInfoState} from '../../reducers/common-experiment-info.reducer';
|
||||
import {IExperimentInfo} from '../../../../features/experiments/shared/experiment-info.model';
|
||||
import {selectBackdropActive} from '../../../core/reducers/view.reducer';
|
||||
import {IExperimentInfo} from '~/features/experiments/shared/experiment-info.model';
|
||||
import {selectBackdropActive} from '@common/core/reducers/view.reducer';
|
||||
import {Observable, Subscription} from 'rxjs';
|
||||
import {selectIsExperimentEditable, selectSelectedExperiment} from '../../../../features/experiments/reducers';
|
||||
import {selectRouterConfig} from '../../../core/reducers/router-reducer';
|
||||
import {selectIsExperimentEditable, selectSelectedExperiment} from '~/features/experiments/reducers';
|
||||
import {selectRouterConfig} from '@common/core/reducers/router-reducer';
|
||||
import {
|
||||
ActivateEdit,
|
||||
CancelExperimentEdit,
|
||||
@@ -21,11 +21,11 @@ import {
|
||||
SetExperimentFormErrors,
|
||||
updateExperimentAtPath
|
||||
} from '../../actions/common-experiments-info.actions';
|
||||
import {ParamsItem} from '../../../../business-logic/model/tasks/paramsItem';
|
||||
import {ParamsItem} from '~/business-logic/model/tasks/paramsItem';
|
||||
import {HELP_TEXTS} from '../../shared/common-experiments.const';
|
||||
import {Router} from '@angular/router';
|
||||
import {ExperimentExecutionParametersComponent} from '../../dumb/experiment-execution-parameters/experiment-execution-parameters.component';
|
||||
import {isReadOnly} from '../../../shared/utils/shared-utils';
|
||||
import {isReadOnly} from '@common/shared/utils/shared-utils';
|
||||
|
||||
@Component({
|
||||
selector : 'sm-experiment-info-hyper-parameters-form-container',
|
||||
@@ -112,9 +112,16 @@ export class ExperimentInfoHyperParametersFormContainerComponent implements OnIn
|
||||
this.store.dispatch(new DeactivateEdit());
|
||||
}
|
||||
|
||||
searchTable($event: string) {
|
||||
this.searchedText = $event;
|
||||
this.cdr.detectChanges();
|
||||
searchTable(value: string) {
|
||||
const searchBackward = value === null;
|
||||
if (this.searchedText !== value && !searchBackward) {
|
||||
this.searchedText = value;
|
||||
this.scrollIndexCounter = -1;
|
||||
this.searchResultsCount = 0;
|
||||
this.executionParamsForm.resetIndex();
|
||||
this.cdr.detectChanges();
|
||||
}
|
||||
this.executionParamsForm.jumpToNextResult(!searchBackward)
|
||||
}
|
||||
|
||||
searchCounterChanged(count: number) {
|
||||
@@ -122,8 +129,8 @@ export class ExperimentInfoHyperParametersFormContainerComponent implements OnIn
|
||||
this.cdr.detectChanges();
|
||||
}
|
||||
|
||||
scrollIndexCounterChanged(counterIndex: number) {
|
||||
this.scrollIndexCounter = counterIndex;
|
||||
scrollIndexCounterReset() {
|
||||
this.scrollIndexCounter = -1;
|
||||
this.cdr.detectChanges();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,20 +26,16 @@
|
||||
</sm-experiment-models-form-view>
|
||||
</sm-editable-section>
|
||||
<sm-editable-section class="editable-design"
|
||||
#prototext
|
||||
[saving]="saving"
|
||||
[editable]="false"
|
||||
[disableInEditMode]="true"
|
||||
containerClass="h-100"
|
||||
(cancelClicked)="cancelModelChange()">
|
||||
<sm-section-header *ngIf="model?.id" label="MODEL CONFIGURATION"></sm-section-header>
|
||||
<sm-experiment-network-design-form
|
||||
#networkDesignForm
|
||||
*ngIf="model?.id"
|
||||
<sm-scroll-textarea
|
||||
class="flex-grow-1"
|
||||
[editable]="false"
|
||||
[formData]="inputDesign"
|
||||
>
|
||||
</sm-experiment-network-design-form>
|
||||
></sm-scroll-textarea>
|
||||
</sm-editable-section>
|
||||
|
||||
</ng-template>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user