mirror of
https://github.com/clearml/clearml-web
synced 2025-06-26 18:27:02 +00:00
release 1.8
This commit is contained in:
7649
package-lock.json
generated
7649
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
115
package.json
115
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "clearml-webapp",
|
||||
"version": "1.7.0",
|
||||
"version": "1.8.0",
|
||||
"license": "",
|
||||
"scripts": {
|
||||
"ng": "ng",
|
||||
@@ -17,86 +17,87 @@
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@angular/animations": "^14.1.0",
|
||||
"@angular/cdk": "^14.1.0",
|
||||
"@angular/common": "^14.1.0",
|
||||
"@angular/compiler": "^14.1.0",
|
||||
"@angular/core": "^14.1.0",
|
||||
"@angular/forms": "^14.1.0",
|
||||
"@angular/material": "^14.1.0",
|
||||
"@angular/platform-browser": "^14.1.0",
|
||||
"@angular/platform-browser-dynamic": "^14.1.0",
|
||||
"@angular/platform-server": "^14.1.0",
|
||||
"@angular/router": "^14.1.0",
|
||||
"@angular/service-worker": "^14.1.0",
|
||||
"@angular/youtube-player": "^14.1.0",
|
||||
"@aws-sdk/client-s3": "^3.118.1",
|
||||
"@aws-sdk/s3-request-presigner": "^3.118.1",
|
||||
"@angular/animations": "^14.2.8",
|
||||
"@angular/cdk": "^14.2.6",
|
||||
"@angular/common": "^14.2.8",
|
||||
"@angular/compiler": "^14.2.8",
|
||||
"@angular/core": "^14.2.8",
|
||||
"@angular/forms": "^14.2.8",
|
||||
"@angular/material": "^14.2.6",
|
||||
"@angular/platform-browser": "^14.2.8",
|
||||
"@angular/platform-browser-dynamic": "^14.2.8",
|
||||
"@angular/platform-server": "^14.2.8",
|
||||
"@angular/router": "^14.2.8",
|
||||
"@angular/service-worker": "^14.2.8",
|
||||
"@angular/youtube-player": "^14.2.6",
|
||||
"@aws-sdk/client-s3": "^3.197.0",
|
||||
"@aws-sdk/s3-request-presigner": "^3.197.0",
|
||||
"@ngneat/dag": "^2.0.0",
|
||||
"@ngrx/effects": "^14.0.2",
|
||||
"@ngrx/entity": "^14.0.2",
|
||||
"@ngrx/router-store": "^14.0.2",
|
||||
"@ngrx/store": "^14.0.2",
|
||||
"ace-builds": "^1.6.1",
|
||||
"angular-google-tag-manager": "^1.6.0",
|
||||
"angular-resizable-element": "^5.0.0",
|
||||
"angular-split": "^13.2.0",
|
||||
"@ngrx/effects": "^14.3.2",
|
||||
"@ngrx/entity": "^14.3.2",
|
||||
"@ngrx/router-store": "^14.3.2",
|
||||
"@ngrx/store": "^14.3.2",
|
||||
"ace-builds": "^1.12.3",
|
||||
"angular-google-tag-manager": "^1.6.1",
|
||||
"angular-resizable-element": "^6.0.0",
|
||||
"angular-split": "^14.1.0",
|
||||
"ansi-to-html": "^0.7.2",
|
||||
"bootstrap": "^4.6.1",
|
||||
"bootstrap": "^4.6.2",
|
||||
"britecharts": "^2.18.0",
|
||||
"curved-arrows": "^0.1.0",
|
||||
"d3-selection": "^3.0.0",
|
||||
"diff": "^5.1.0",
|
||||
"dom-to-image": "^2.6.0",
|
||||
"filesize": "^9.0.11",
|
||||
"filesize": "^10.0.5",
|
||||
"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": "^15.1.0",
|
||||
"ngx-color-picker": "^12.0.1",
|
||||
"ngx-markdown-editor": "^4.0.0",
|
||||
"ngx-color-picker": "^13.0.0",
|
||||
"ngx-device-detector": "^4.0.1",
|
||||
"ngx-markdown-editor": "^4.2.0",
|
||||
"ngx-window-token": "^6.0.0",
|
||||
"object-hash": "^3.0.0",
|
||||
"primeicons": "^5.0.0",
|
||||
"primeng": "^14.1.0",
|
||||
"primeicons": "^6.0.1",
|
||||
"primeng": "^14.1.2",
|
||||
"process": "^0.11.10",
|
||||
"rxjs": "^7.5.5",
|
||||
"rxjs": "^7.5.7",
|
||||
"string-to-color": "^2.2.2",
|
||||
"tslib": "^2.4.0",
|
||||
"url": "^0.11.0",
|
||||
"uuid": "^8.3.2",
|
||||
"zone.js": "~0.11.6"
|
||||
"uuid": "^9.0.0",
|
||||
"zone.js": "~0.11.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "^14.1.0",
|
||||
"@angular-devkit/core": "^14.1.0",
|
||||
"@angular-devkit/schematics": "^14.1.0",
|
||||
"@angular-devkit/schematics-cli": "^14.0.3",
|
||||
"@angular-eslint/builder": "^14.0.2",
|
||||
"@angular-eslint/eslint-plugin": "^14.0.2",
|
||||
"@angular-eslint/eslint-plugin-template": "^14.0.2",
|
||||
"@angular-eslint/schematics": "14.0.2",
|
||||
"@angular-eslint/template-parser": "^14.0.2",
|
||||
"@angular/cli": "^14.1.0",
|
||||
"@angular/compiler-cli": "^14.1.0",
|
||||
"@angular/language-service": "^14.1.0",
|
||||
"@fortawesome/fontawesome-free": "^6.1.1",
|
||||
"@ngrx/schematics": "^14.0.2",
|
||||
"@ngrx/store-devtools": "^14.0.2",
|
||||
"@types/d3-selection": "^3.0.2",
|
||||
"@types/lodash": "^4.14.182",
|
||||
"@types/node": "^16.11.19",
|
||||
"@types/plotly.js": "^1.54.22",
|
||||
"@angular-devkit/build-angular": "^14.2.7",
|
||||
"@angular-devkit/core": "^14.2.7",
|
||||
"@angular-devkit/schematics": "^14.2.7",
|
||||
"@angular-devkit/schematics-cli": "^14.2.7",
|
||||
"@angular-eslint/builder": "^14.1.2",
|
||||
"@angular-eslint/eslint-plugin": "^14.1.2",
|
||||
"@angular-eslint/eslint-plugin-template": "^14.1.2",
|
||||
"@angular-eslint/schematics": "14.1.2",
|
||||
"@angular-eslint/template-parser": "^14.1.2",
|
||||
"@angular/cli": "^14.2.7",
|
||||
"@angular/compiler-cli": "^14.2.8",
|
||||
"@angular/language-service": "^14.2.8",
|
||||
"@fortawesome/fontawesome-free": "^6.2.0",
|
||||
"@ngrx/schematics": "^14.3.2",
|
||||
"@ngrx/store-devtools": "^14.3.2",
|
||||
"@types/d3-selection": "^3.0.3",
|
||||
"@types/lodash": "^4.14.186",
|
||||
"@types/node": "^16.18.2",
|
||||
"@types/plotly.js": "^2.12.8",
|
||||
"@types/uuid": "^8.3.4",
|
||||
"@typescript-eslint/eslint-plugin": "^5.30.0",
|
||||
"@typescript-eslint/parser": "^5.30.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.41.0",
|
||||
"@typescript-eslint/parser": "^5.41.0",
|
||||
"codelyzer": "^6.0.2",
|
||||
"eslint": "^8.18.0",
|
||||
"eslint": "^8.26.0",
|
||||
"eslint-plugin-import": "2.26.0",
|
||||
"eslint-plugin-jsdoc": "39.3.3",
|
||||
"eslint-plugin-jsdoc": "39.3.25",
|
||||
"eslint-plugin-prefer-arrow": "1.2.3",
|
||||
"typescript": "~4.7.4"
|
||||
"typescript": "~4.8.4"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ export const routes: Routes = [
|
||||
{
|
||||
path: 'dashboard',
|
||||
loadChildren: () => import('./features/dashboard/dashboard.module').then(m => m.DashboardModule),
|
||||
data: {search: true},
|
||||
data: {search: true, userFocus: true},
|
||||
},
|
||||
{
|
||||
path: 'projects',
|
||||
|
||||
@@ -21,10 +21,6 @@ export interface EventsGetPlotSampleRequest {
|
||||
* Metric name
|
||||
*/
|
||||
metric: string;
|
||||
/**
|
||||
* Metric variant
|
||||
*/
|
||||
variant: string;
|
||||
/**
|
||||
* The iteration to bring plot from. If not specified then the latest reported plot is retrieved
|
||||
*/
|
||||
|
||||
@@ -25,4 +25,8 @@ export interface EventsNextPlotSampleRequest {
|
||||
* If set then get the either previous variant event from the current iteration or (if does not exist) the last variant event from the previous iteration. Otherwise next variant event from the current iteration or first variant event from the next iteration
|
||||
*/
|
||||
navigate_earlier?: boolean;
|
||||
/**
|
||||
* If set then navigate to the next/previous iteration
|
||||
*/
|
||||
next_iteration?: boolean;
|
||||
}
|
||||
|
||||
@@ -18,9 +18,9 @@ export interface PlotSampleResponse {
|
||||
*/
|
||||
scroll_id?: string;
|
||||
/**
|
||||
* Plot event
|
||||
* Plot events
|
||||
*/
|
||||
event?: object;
|
||||
events?: Array<object>;
|
||||
/**
|
||||
* minimal valid iteration for the variant
|
||||
*/
|
||||
|
||||
@@ -25,17 +25,20 @@ export interface OrganizationGetEntitiesCountRequest {
|
||||
* Search criteria for models
|
||||
*/
|
||||
models?: object;
|
||||
/**
|
||||
* Search criteria for dataviews
|
||||
*/
|
||||
dataviews?: object;
|
||||
/**
|
||||
* Search criteria for hyper datasets
|
||||
*/
|
||||
hyper_datasets?: object;
|
||||
/**
|
||||
* Search criteria for pipelines
|
||||
*/
|
||||
pipelines?: object;
|
||||
/**
|
||||
* Search criteria for datasets
|
||||
*/
|
||||
datasets: object;
|
||||
/**
|
||||
* If set to 'true' then hidden projects and tasks are included in the search results
|
||||
*/
|
||||
search_hidden?: boolean;
|
||||
/**
|
||||
* The list of users that were active in the project. If passes then the resulting projects are filtered to the ones that have tasks created by these users
|
||||
*/
|
||||
active_users?: string[];
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ export class ProjectsEffects {
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
id: [action.projectId],
|
||||
include_stats: true,
|
||||
...(!showHidden && {include_stats_filter: {system_tags: ['-pipeline']}}),
|
||||
...(!showHidden && {include_stats_filter: {system_tags: ['-pipeline', '-dataset']}}),
|
||||
...(showOnlyUserWork && {active_users: [user.id]}),
|
||||
...(showHidden && {search_hidden: true}),
|
||||
...((action.example !== false || this.fetchingExampleExperiment === action.projectId) && {check_own_contents: true}),
|
||||
|
||||
@@ -1,21 +1,33 @@
|
||||
import {Injectable} from '@angular/core';
|
||||
import {Actions, createEffect, ofType} from '@ngrx/effects';
|
||||
import {map, switchMap} from 'rxjs/operators';
|
||||
import {map, switchMap, withLatestFrom} from 'rxjs/operators';
|
||||
import {getResultsCount, setResultsCount} from '@common/dashboard-search/dashboard-search.actions';
|
||||
import {getEntityStatQuery} from '@common/dashboard-search/dashboard-search.effects';
|
||||
import {ApiOrganizationService} from '~/business-logic/api-services/organization.service';
|
||||
import {Store} from '@ngrx/store';
|
||||
import {selectCurrentUser, selectShowOnlyUserWork} from '@common/core/reducers/users-reducer';
|
||||
import {selectShowHidden} from '@common/core/reducers/projects.reducer';
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class DashboardSearchEffects {
|
||||
constructor(
|
||||
private actions: Actions,
|
||||
private store: Store,
|
||||
public organizationApi: ApiOrganizationService) {
|
||||
}
|
||||
|
||||
getResultsCount = createEffect(() => this.actions.pipe(
|
||||
ofType(getResultsCount),
|
||||
switchMap(action => this.organizationApi.organizationGetEntitiesCount({
|
||||
withLatestFrom(
|
||||
this.store.select(selectShowOnlyUserWork),
|
||||
this.store.select(selectCurrentUser),
|
||||
this.store.select(selectShowHidden),
|
||||
),
|
||||
switchMap(([action, userFocus, user, hidden]) => this.organizationApi.organizationGetEntitiesCount({
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
...(userFocus && {active_users: [user.id]}),
|
||||
...(hidden && {search_hidden: true}),
|
||||
...getEntityStatQuery(action)
|
||||
})),
|
||||
map(({tasks: experiments, ...rest}) =>
|
||||
|
||||
@@ -3,18 +3,18 @@ import {
|
||||
CommonProjectReadyForDeletion,
|
||||
commonProjectsInitState,
|
||||
commonProjectsReducers,
|
||||
ICommonProjectsState
|
||||
CommonProjectsState
|
||||
} from '@common/projects/common-projects.reducer';
|
||||
import {checkProjectForDeletion, resetReadyToDelete, setProjectReadyForDeletion} from '@common/projects/common-projects.actions';
|
||||
|
||||
export type IProjectReadyForDeletion = CommonProjectReadyForDeletion;
|
||||
|
||||
export interface IProjectsState extends ICommonProjectsState {
|
||||
export interface ProjectsState extends CommonProjectsState {
|
||||
|
||||
projectReadyForDeletion: IProjectReadyForDeletion;
|
||||
}
|
||||
|
||||
const projectsInitState: IProjectsState = {
|
||||
const projectsInitState: ProjectsState = {
|
||||
...commonProjectsInitState,
|
||||
projectReadyForDeletion: {
|
||||
project: null, experiments: null, models: null
|
||||
@@ -41,7 +41,7 @@ export const projectsReducer = createReducer(
|
||||
...commonProjectsReducers
|
||||
);
|
||||
|
||||
export const projects = state => state.projects as IProjectsState;
|
||||
export const projects = state => state.projects as ProjectsState;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
export const selectShowHidden = createSelector(projects, (state) => false);
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
&.first {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.section {
|
||||
@@ -21,7 +20,7 @@
|
||||
|
||||
.info {
|
||||
margin-left: 12px;
|
||||
color: $light-grey-blue;
|
||||
color: $blue-400;
|
||||
|
||||
&:hover {
|
||||
color: $purple;
|
||||
|
||||
@@ -1,92 +1,52 @@
|
||||
<div class="side-nav">
|
||||
<div class="item logo">
|
||||
<div class="item-icon">
|
||||
<img src="assets/c-logo.svg?v=1" class="logo-a" alt="logo">
|
||||
</div>
|
||||
</div>
|
||||
<div class="logo">
|
||||
<img src="assets/c-logo.svg?v=1" class="logo-a" alt="logo" width="64" height="64">
|
||||
</div>
|
||||
|
||||
<ng-container *ngIf="currentUser">
|
||||
<a class="item d-block"
|
||||
<ng-container *ngIf="currentUser">
|
||||
<div #container class="items-container" [class.on-scrolling]="scrolling">
|
||||
<a class="item al-ico-home"
|
||||
routerLink="/dashboard"
|
||||
routerLinkActive="active"
|
||||
(click)="resetSearch()"
|
||||
smTooltip="DASHBOARD"
|
||||
[matTooltipShowDelay]="0"
|
||||
matTooltipPosition="right"
|
||||
>
|
||||
<div class="item-icon">
|
||||
<i class="al-icon al-ico-home al-color blue-300"></i>
|
||||
</div>
|
||||
<div class="caption">dashboard</div>
|
||||
matTooltipPosition="right">
|
||||
</a>
|
||||
|
||||
<a class="item d-block"
|
||||
<a class="item al-ico-projects"
|
||||
smTooltip="PROJECTS"
|
||||
[matTooltipShowDelay]="0"
|
||||
matTooltipPosition="right"
|
||||
routerLink="/projects"
|
||||
routerLinkActive="active"
|
||||
>
|
||||
<div class="item-icon">
|
||||
<i class="al-icon al-ico-projects al-color blue-300"></i>
|
||||
</div>
|
||||
<div class="caption">projects</div>
|
||||
routerLinkActive="active">
|
||||
</a>
|
||||
<a class="item d-block"
|
||||
routerLink="/pipelines"
|
||||
routerLinkActive="active"
|
||||
smTooltip="PIPELINES"
|
||||
[matTooltipShowDelay]="0"
|
||||
matTooltipPosition="right">
|
||||
<div class="item-icon">
|
||||
<i class="al-icon al-ico-pipelines al-color blue-300"></i>
|
||||
</div>
|
||||
<div class="caption">pipelines</div>
|
||||
</a>
|
||||
<a class="item d-block"
|
||||
<a class="item al-ico-datasets"
|
||||
routerLink="/datasets"
|
||||
routerLinkActive="active"
|
||||
smTooltip="DATASETS"
|
||||
[matTooltipShowDelay]="0"
|
||||
matTooltipPosition="right">
|
||||
<div class="item-icon">
|
||||
<i class="al-icon al-ico-datasets al-color blue-300"></i>
|
||||
</div>
|
||||
<div class="caption">datasets</div>
|
||||
</a>
|
||||
<a class="item d-block"
|
||||
<a class="item al-ico-pipelines"
|
||||
routerLink="/pipelines"
|
||||
routerLinkActive="active"
|
||||
smTooltip="PIPELINES"
|
||||
[matTooltipShowDelay]="0"
|
||||
matTooltipPosition="right">
|
||||
</a>
|
||||
<a class="item al-ico-queues"
|
||||
routerLink="/workers-and-queues"
|
||||
routerLinkActive="active"
|
||||
smTooltip="WORKERS & QUEUES"
|
||||
[matTooltipShowDelay]="0"
|
||||
matTooltipPosition="right">
|
||||
<div class="item-icon">
|
||||
<i class="al-icon al-ico-queues al-color blue-300"></i>
|
||||
</div>
|
||||
<div class="caption">workers & queues</div>
|
||||
</a>
|
||||
|
||||
</ng-container>
|
||||
<div *ngIf="currentUser" class="account">
|
||||
<a *ngIf="environment.whiteLabelLink" class="item d-block" target="_blank"
|
||||
[smTooltip]="environment.whiteLabelLink.tooltip"
|
||||
[matTooltipShowDelay]="0"
|
||||
matTooltipPosition="right"
|
||||
[href]="environment.whiteLabelLink.link">
|
||||
<div class="item-icon"
|
||||
[style.background-image]="'url(' + environment.whiteLabelLink.logo + ')'"
|
||||
style="width: 64px; height: 64px"
|
||||
>
|
||||
</div>
|
||||
<div class="caption">Ignite</div>
|
||||
</a>
|
||||
<a *ngIf="environment.slackLink" class="item d-block" [href]="environment.slackLink"
|
||||
target="_blank"
|
||||
smTooltip="Community support on Slack" [matTooltipShowDelay]="0" matTooltipPosition="right">
|
||||
<div class="item-icon">
|
||||
<i class="al-icon al-ico-slack md al-color blue-300"></i>
|
||||
</div>
|
||||
<div class="caption">Slack</div>
|
||||
</a>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<div *ngIf="currentUser" class="account">
|
||||
<a *ngIf="environment.slackLink" class="item" [href]="environment.slackLink"
|
||||
target="_blank"
|
||||
smTooltip="Community support on Slack" [matTooltipShowDelay]="0" matTooltipPosition="right">
|
||||
<i class="i-slack-mark-color"></i>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -1,95 +1,82 @@
|
||||
@import "../../webapp-common/shared/ui-components/styles/variables";
|
||||
@import "variables";
|
||||
|
||||
$transition-delay: 0.1;
|
||||
$transition-speed: 0.15;
|
||||
$link-item-size: 64px;
|
||||
$icon-size: 24px;
|
||||
|
||||
.side-nav {
|
||||
z-index: 1000;
|
||||
background-color: $blue-600;
|
||||
:host {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
width: $side-bar-close-width;
|
||||
position: relative;
|
||||
transition: width $transition-speed + s;
|
||||
transition-delay: $transition-delay + s;
|
||||
overflow: hidden;
|
||||
|
||||
.item.logo {
|
||||
background: $eggplant-purple;
|
||||
cursor: default;
|
||||
|
||||
.item-icon {
|
||||
transition: opacity $transition-speed + $transition-delay + s;
|
||||
opacity: 1;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: $eggplant-purple;
|
||||
box-shadow: unset;
|
||||
|
||||
}
|
||||
background-color: $blue-600;
|
||||
|
||||
.logo {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
background: $blue-700;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: $blue-250;
|
||||
.items-container {
|
||||
text-align: center;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
scrollbar-width: thin; /* Firefox */
|
||||
-ms-overflow-style: none; /* IE 10+ */
|
||||
&.on-scrolling {
|
||||
box-shadow: 0 3px 3px rgba(0,0,0,0.3) inset, 0 -3px 3px rgba(0,0,0,0.3) inset;
|
||||
}
|
||||
}
|
||||
|
||||
.items-container::-webkit-scrollbar-track {
|
||||
box-shadow: none;
|
||||
-webkit-box-shadow: none !important;
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
.items-container::-webkit-scrollbar {
|
||||
width: 2px !important;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.items-container::-webkit-scrollbar-thumb {
|
||||
border-radius: unset;
|
||||
border: none;
|
||||
}
|
||||
|
||||
|
||||
.item {
|
||||
width: 100%;
|
||||
height: $side-bar-close-width;
|
||||
line-height: $side-bar-close-width;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
|
||||
.fa-24 {
|
||||
font-size: 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: $link-item-size;
|
||||
height: $link-item-size;
|
||||
color: $blue-300;
|
||||
margin: 0 auto;
|
||||
// ICON SIZE
|
||||
&:before {
|
||||
font-size: $icon-size;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: $blue-200;
|
||||
background-color: $blue-500;
|
||||
box-shadow: inset 0 -1px 0 0 #252b3d;
|
||||
|
||||
.caption {
|
||||
opacity: 1;
|
||||
}
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.item-icon {
|
||||
width: $side-bar-close-width;
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
color: #a7b2d8;
|
||||
i{
|
||||
line-height: 64px;
|
||||
height: 64px;
|
||||
width: 64px;
|
||||
}
|
||||
&.active:before {
|
||||
color: $neon-yellow
|
||||
}
|
||||
}
|
||||
|
||||
&.active {
|
||||
.item-icon i {
|
||||
color: $neon-yellow
|
||||
}
|
||||
}
|
||||
|
||||
.caption {
|
||||
transition: opacity $transition-speed + s;
|
||||
position: absolute;
|
||||
left: $side-bar-close-width;
|
||||
text-transform: uppercase;
|
||||
font-size: 15px;
|
||||
opacity: 0.4;
|
||||
color: $blue-250;
|
||||
}
|
||||
.i-slack-mark-color {
|
||||
width: $icon-size;
|
||||
height: $icon-size;
|
||||
background-size: $icon-size;
|
||||
}
|
||||
|
||||
.account {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-top: auto;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,28 +1,43 @@
|
||||
import { selectCurrentUser } from './../../webapp-common/core/reducers/users-reducer';
|
||||
import {Component} from '@angular/core';
|
||||
import {selectCurrentUser} from '@common/core/reducers/users-reducer';
|
||||
import {AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, ViewChild} from '@angular/core';
|
||||
import {Store} from '@ngrx/store';
|
||||
import {selectSelectedProjectId} from '../../webapp-common/core/reducers/projects.reducer';
|
||||
import {Observable} from 'rxjs';
|
||||
import {Router} from '@angular/router';
|
||||
import {ConfigurationService} from '../../webapp-common/shared/services/configuration.service';
|
||||
import {searchDeactivate} from '../../webapp-common/dashboard-search/dashboard-search.actions';
|
||||
import {selectSelectedProjectId} from '@common/core/reducers/projects.reducer';
|
||||
import {fromEvent, Observable} from 'rxjs';
|
||||
import {ConfigurationService} from '@common/shared/services/configuration.service';
|
||||
import {searchDeactivate} from '@common/dashboard-search/dashboard-search.actions';
|
||||
|
||||
@Component({
|
||||
selector : 'sm-side-nav',
|
||||
templateUrl: './side-nav.component.html',
|
||||
styleUrls : ['./side-nav.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class SideNavComponent {
|
||||
export class SideNavComponent implements AfterViewInit {
|
||||
public selectedProjectId$: Observable<any>;
|
||||
currentUser: any;
|
||||
environment = ConfigurationService.globalEnvironment;
|
||||
public scrolling: boolean;
|
||||
|
||||
@ViewChild('container') container: ElementRef<HTMLDivElement>;
|
||||
|
||||
|
||||
constructor(public store: Store<any>, private router: Router) {
|
||||
constructor(public store: Store<any>, private cdr: ChangeDetectorRef) {
|
||||
this.selectedProjectId$ = this.store.select(selectSelectedProjectId);
|
||||
this.store.select(selectCurrentUser).subscribe((res) => this.currentUser = res);
|
||||
|
||||
fromEvent(window, 'resize').subscribe(() => {
|
||||
const scrolling = this.container.nativeElement.scrollHeight > this.container.nativeElement.clientHeight;
|
||||
if (scrolling !== this.scrolling) {
|
||||
this.scrolling = scrolling;
|
||||
this.cdr.detectChanges();
|
||||
}
|
||||
this.scrolling = scrolling;
|
||||
});
|
||||
}
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
this.scrolling = this.container.nativeElement.scrollHeight > this.container.nativeElement.clientHeight;
|
||||
}
|
||||
|
||||
public resetSearch() {
|
||||
this.store.dispatch(searchDeactivate());
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
@font-face {
|
||||
font-family: '#{$icomoon-font-family}';
|
||||
src: url('./#{$icomoon-font-family}.ttf?ttf?vsfnj4') format('truetype');
|
||||
src: url('./#{$icomoon-font-family}.ttf?84hl5c') format('truetype');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: block;
|
||||
@@ -23,6 +23,21 @@
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.al-ico-gpu {
|
||||
&:before {
|
||||
content: $al-ico-gpu;
|
||||
}
|
||||
}
|
||||
.al-ico-project-path {
|
||||
&:before {
|
||||
content: $al-ico-project-path;
|
||||
}
|
||||
}
|
||||
.al-ico-tree-view {
|
||||
&:before {
|
||||
content: $al-ico-tree-view;
|
||||
}
|
||||
}
|
||||
.al-ico-sort-asc {
|
||||
&:before {
|
||||
content: $al-ico-sort-asc;
|
||||
@@ -721,52 +736,53 @@
|
||||
.al-ico-filter-on .path1 {
|
||||
&:before {
|
||||
content: $al-ico-filter-on-path1;
|
||||
color: rgb(211, 255, 0);
|
||||
color: $neon-yellow; // don't overwrite
|
||||
// color: rgb(211, 255, 0);
|
||||
}
|
||||
}
|
||||
.al-ico-filter-on .path2 {
|
||||
&:before {
|
||||
content: $al-ico-filter-on-path2;
|
||||
margin-left: -1em;
|
||||
color: rgb(132, 146, 194);
|
||||
color: $blue-300; // don't overwrite
|
||||
}
|
||||
}
|
||||
.al-ico-filter-off {
|
||||
&:before {
|
||||
content: $al-ico-filter-off;
|
||||
color: #8492c2;
|
||||
color: $blue-400; // don't overwrite
|
||||
}
|
||||
}
|
||||
.al-ico-sort-off {
|
||||
&:before {
|
||||
content: $al-ico-sort-off;
|
||||
color: #5a658e;
|
||||
color: $blue-400; // don't overwrite
|
||||
}
|
||||
}
|
||||
.al-ico-sort-on-down .path1 {
|
||||
&:before {
|
||||
content: $al-ico-sort-on-down-path1;
|
||||
color: rgb(90, 101, 142);
|
||||
color: $blue-400; // don't overwrite
|
||||
}
|
||||
}
|
||||
.al-ico-sort-on-down .path2 {
|
||||
&:before {
|
||||
content: $al-ico-sort-on-down-path2;
|
||||
margin-left: -1em;
|
||||
color: rgb(195, 205, 240);
|
||||
color: $blue-200; // don't overwrite
|
||||
}
|
||||
}
|
||||
.al-ico-sort-on-up .path1 {
|
||||
&:before {
|
||||
content: $al-ico-sort-on-up-path1;
|
||||
color: rgb(90, 101, 142);
|
||||
color: $blue-400; // don't overwrite
|
||||
}
|
||||
}
|
||||
.al-ico-sort-on-up .path2 {
|
||||
&:before {
|
||||
content: $al-ico-sort-on-up-path2;
|
||||
margin-left: -1em;
|
||||
color: rgb(195, 205, 240);
|
||||
color: $blue-200; // don't overwrite
|
||||
}
|
||||
}
|
||||
.al-ico-arrow-left {
|
||||
@@ -992,27 +1008,28 @@
|
||||
.al-ico-auto-refresh-play .path1 {
|
||||
&:before {
|
||||
content: $al-ico-auto-refresh-play-path1;
|
||||
color: rgb(90, 101, 142);
|
||||
color: $blue-300; // don't overwrite
|
||||
}
|
||||
}
|
||||
.al-ico-auto-refresh-play .path2 {
|
||||
&:before {
|
||||
content: $al-ico-auto-refresh-play-path2;
|
||||
margin-left: -1em;
|
||||
color: rgb(211, 253, 0);
|
||||
color: $neon-yellow; // don't overwrite
|
||||
}
|
||||
}
|
||||
.al-ico-auto-refresh-pause .path1 {
|
||||
&:before {
|
||||
content: $al-ico-auto-refresh-pause-path1;
|
||||
color: rgb(90, 101, 142);
|
||||
color: $blue-300; // don't overwrite
|
||||
}
|
||||
}
|
||||
.al-ico-auto-refresh-pause .path2 {
|
||||
&:before {
|
||||
content: $al-ico-auto-refresh-pause-path2;
|
||||
margin-left: -1em;
|
||||
color: rgb(211, 253, 0);
|
||||
color: $neon-yellow; // don't overwrite
|
||||
// color: rgb(211, 253, 0);
|
||||
}
|
||||
}
|
||||
.al-ico-sqr-ok {
|
||||
@@ -1068,14 +1085,15 @@
|
||||
.al-ico-filter-reset .path1 {
|
||||
&:before {
|
||||
content: $al-ico-filter-reset-path1;
|
||||
color: rgb(90, 101, 142);
|
||||
color: $blue-300; // don't overwrite
|
||||
}
|
||||
}
|
||||
.al-ico-filter-reset .path2 {
|
||||
&:before {
|
||||
content: $al-ico-filter-reset-path2;
|
||||
margin-left: -1em;
|
||||
color: rgb(237, 138, 131);
|
||||
color: lighten($failed-red, 10%); // don't overwrite
|
||||
// color: rgb(237, 138, 131);
|
||||
}
|
||||
}
|
||||
.al-ico-version-label {
|
||||
@@ -1111,14 +1129,15 @@
|
||||
.al-ico-settings-alert .path1 {
|
||||
&:before {
|
||||
content: $al-ico-settings-alert-path1;
|
||||
color: rgb(0, 0, 0);
|
||||
color: $black; // don't overwrite
|
||||
}
|
||||
}
|
||||
.al-ico-settings-alert .path2 {
|
||||
&:before {
|
||||
content: $al-ico-settings-alert-path2;
|
||||
margin-left: -1em;
|
||||
color: rgb(211, 255, 0);
|
||||
color: $neon-yellow; // don't overwrite
|
||||
// color: rgb(211, 255, 0);
|
||||
}
|
||||
}
|
||||
.al-ico-platform {
|
||||
|
||||
Binary file not shown.
@@ -1,6 +1,9 @@
|
||||
$icomoon-font-family: "trains" !default;
|
||||
$icomoon-font-path: "fonts" !default;
|
||||
|
||||
$al-ico-gpu: "\e9e7";
|
||||
$al-ico-project-path: "\e9e6";
|
||||
$al-ico-tree-view: "\e9e5";
|
||||
$al-ico-sort-asc: "\e9e3";
|
||||
$al-ico-sort-desc: "\e9e4";
|
||||
$al-ico-grid-view: "\e9e0";
|
||||
|
||||
6
src/app/webapp-common/assets/icons/slack-mark-color.svg
Normal file
6
src/app/webapp-common/assets/icons/slack-mark-color.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<path d="M5.06,15.17c0,1.39-1.13,2.52-2.52,2.52S.02,16.56,.02,15.17s1.13-2.52,2.52-2.52h2.52v2.52Zm1.26,0c0-1.39,1.13-2.52,2.52-2.52s2.52,1.13,2.52,2.52v6.3c0,1.39-1.13,2.52-2.52,2.52s-2.52-1.13-2.52-2.52v-6.3Z" fill="#e01e5a"/>
|
||||
<path d="M8.84,5.05c-1.39,0-2.52-1.13-2.52-2.52S7.45,0,8.84,0s2.52,1.13,2.52,2.52v2.52h-2.52Zm0,1.28c1.39,0,2.52,1.13,2.52,2.52s-1.13,2.52-2.52,2.52H2.52c-1.39,0-2.52-1.13-2.52-2.52s1.13-2.52,2.52-2.52h6.32Z" fill="#36c5f0"/>
|
||||
<path d="M18.94,8.85c0-1.39,1.13-2.52,2.52-2.52s2.52,1.13,2.52,2.52-1.13,2.52-2.52,2.52h-2.52v-2.52Zm-1.26,0c0,1.39-1.13,2.52-2.52,2.52s-2.52-1.13-2.52-2.52V2.53c0-1.39,1.13-2.52,2.52-2.52s2.52,1.13,2.52,2.52c0,0,0,6.32,0,6.32Z" fill="#2eb67d"/>
|
||||
<path d="M15.16,18.95c1.39,0,2.52,1.13,2.52,2.52s-1.13,2.52-2.52,2.52-2.52-1.13-2.52-2.52v-2.52h2.52Zm0-1.26c-1.39,0-2.52-1.13-2.52-2.52s1.13-2.52,2.52-2.52h6.32c1.39,0,2.52,1.13,2.52,2.52s-1.13,2.52-2.52,2.52h-6.32Z" fill="#ecb22e"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1011 B |
File diff suppressed because one or more lines are too long
@@ -20,8 +20,8 @@
|
||||
</sm-search>
|
||||
</span>
|
||||
<ng-container *ngIf="searchActive">
|
||||
<i *ngIf="(isSearching$ | async); else searchIcon" class="fa fa-times pointer" (click)="clearSearch()" smClickStopPropagation></i>
|
||||
<i *ngIf="(isSearching$ | async); else searchIcon" class="al-icon al-ico-dialog-x pointer" (click)="clearSearch()" smClickStopPropagation></i>
|
||||
<ng-template #searchIcon>
|
||||
<i class="fa fa-search pointer" (click)="openSearch()"></i>
|
||||
<i class="al-icon al-ico-search pointer" (click)="openSearch()"></i>
|
||||
</ng-template>
|
||||
</ng-container>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "../../../shared/ui-components/styles/variables";
|
||||
@import "variables";
|
||||
|
||||
:host {
|
||||
position: relative;
|
||||
@@ -41,9 +41,8 @@
|
||||
|
||||
}
|
||||
|
||||
i.fa {
|
||||
color: $blue-grey;
|
||||
font-size: 18px;
|
||||
.al-icon {
|
||||
color: $blue-300;
|
||||
margin-left: auto;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
@@ -55,8 +54,8 @@
|
||||
color: $blue-200;
|
||||
}
|
||||
}
|
||||
i.fa-times {
|
||||
margin-right:4px;
|
||||
.al-ico-dialog-x {
|
||||
transform: scale(0.9);
|
||||
}
|
||||
|
||||
::ng-deep sm-search.regex-error input {
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
@import "angular-notifier/styles.scss";
|
||||
@import "angular-notifier/styles/themes/theme-material.scss";
|
||||
@import "shared/ui-components/styles/notifications";
|
||||
@import "~britecharts/src/styles/charts/line";
|
||||
@import "~britecharts/src/styles/charts/donut";
|
||||
@import "~britecharts/src/styles/common/legend";
|
||||
@import "~britecharts/src/styles/common/tooltip";
|
||||
@import "~britecharts/src/styles/common/axes";
|
||||
@import "~britecharts/src/styles/common/grid";
|
||||
// @import "~ngx-markdown-editor/assets/highlight.js/agate.min.css";
|
||||
@import "britecharts/src/styles/charts/line";
|
||||
@import "britecharts/src/styles/charts/donut";
|
||||
@import "britecharts/src/styles/common/legend";
|
||||
@import "britecharts/src/styles/common/tooltip";
|
||||
@import "britecharts/src/styles/common/axes";
|
||||
@import "britecharts/src/styles/common/grid";
|
||||
// @import "ngx-markdown-editor/assets/highlight.js/agate.min.css";
|
||||
@import "shared/ui-components/styles/material-palette";
|
||||
@import "assets/fonts/trains-icons.scss";
|
||||
@import "layout/layout";
|
||||
@@ -95,6 +95,14 @@ $sm-theme: mat.define-light-theme($sm-theme-primary, $sm-theme-accent, $sm-theme
|
||||
@include mat.pseudo-checkbox-color($light-theme);
|
||||
@include mat.divider-color($light-theme);
|
||||
|
||||
mat-progress-bar {
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 0 0 1px $white, 0 0 0 3px lighten($purple, 30%);
|
||||
}
|
||||
.mat-progress-bar-fill::after {
|
||||
background-color: lighten($purple, 10%);
|
||||
}
|
||||
|
||||
.mat-checkbox-frame,
|
||||
.mat-radio-outer-circle {
|
||||
border-color: $purple;
|
||||
@@ -289,7 +297,7 @@ button {
|
||||
}
|
||||
|
||||
.color-neon-yellow {
|
||||
color: $neon-yellow;
|
||||
color: $neon-yellow !important;
|
||||
}
|
||||
|
||||
.background-neon-green {
|
||||
@@ -511,9 +519,10 @@ html {
|
||||
|
||||
.sm-menu-header {
|
||||
text-align: center;
|
||||
padding: 15px 15px;
|
||||
padding: 12px;
|
||||
background: $blue-25;
|
||||
color: $blue-400;
|
||||
border-bottom: 1px solid $blue-200;
|
||||
}
|
||||
|
||||
.mat-menu-content .mat-menu-item {
|
||||
@@ -576,36 +585,6 @@ $type-colors: (
|
||||
date: #05668D,
|
||||
);
|
||||
|
||||
.dark-theme {
|
||||
.ngx-json-viewer {
|
||||
background-color: $blue-800;
|
||||
overflow: unset !important;
|
||||
height: 99% !important;
|
||||
font-size: 11px !important;
|
||||
line-height: 11px !important;
|
||||
|
||||
.segment .segment-main {
|
||||
.toggler {
|
||||
font-size: 16px !important;
|
||||
line-height: 4px !important;
|
||||
}
|
||||
|
||||
.segment-key {
|
||||
color: $blue-250 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@each $type, $color in $type-colors {
|
||||
.segment-type-#{$type} > .segment-main > .segment-value {
|
||||
color: $color !important;
|
||||
}
|
||||
}
|
||||
|
||||
.segment-type-link > .segment-main > .segment-value > a {
|
||||
color: #ff8400 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.mat-expansion-panel.allegro-style {
|
||||
width: 100%;
|
||||
@@ -731,7 +710,7 @@ button.btn.button-outline-dark {
|
||||
.sm-card-list-layout {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, 352px);
|
||||
grid-gap: 32px 24px;
|
||||
grid-gap: 24px;
|
||||
padding: 0 24px 24px;
|
||||
justify-content: center;
|
||||
|
||||
@@ -751,7 +730,7 @@ button.btn.button-outline-dark {
|
||||
.sm-card-list-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding-top: $projects-header-padding;
|
||||
padding: $projects-header-padding 0 $projects-header-padding * 0.5;
|
||||
|
||||
.recent-title {
|
||||
display: flex;
|
||||
|
||||
@@ -67,6 +67,7 @@ export const ICONS = {
|
||||
ARROW_DOWN: 'al-ico-ico-chevron-down',
|
||||
ARROW_UP: 'al-ico-ico-chevron-up',
|
||||
RUN: 'al-ico-run',
|
||||
METADATA: 'al-ico-metadata',
|
||||
};
|
||||
|
||||
export type IconNames = keyof typeof ICONS;
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
import {HTTP_PREFIX} from '../../../app.constants';
|
||||
import {omit} from 'lodash/fp';
|
||||
import {HTTP_PREFIX} from '~/app.constants';
|
||||
import {HttpErrorResponse} from '@angular/common/http';
|
||||
import {createAction, props} from '@ngrx/store';
|
||||
|
||||
export const requestFailed = createAction(
|
||||
HTTP_PREFIX + 'REQUEST_FAILED',
|
||||
(err: HttpErrorResponse) => ({err: omit(['headers'], err)})
|
||||
(err: HttpErrorResponse) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const {headers, ...others} = err;
|
||||
return {err: {...others, error: {meta: others.error.meta}}};
|
||||
}
|
||||
);
|
||||
|
||||
export const apiRequest = createAction(
|
||||
|
||||
@@ -85,7 +85,8 @@ export const setDeep = createAction(
|
||||
);
|
||||
|
||||
export const getTags = createAction(
|
||||
PROJECTS_PREFIX + '[get tags]'
|
||||
PROJECTS_PREFIX + '[get tags]',
|
||||
(project = null) => ({projectId: project})
|
||||
);
|
||||
|
||||
export const getCompanyTags = createAction(
|
||||
|
||||
@@ -53,6 +53,12 @@ export class ProjectsEffects {
|
||||
map(action => activeLoader(action.type))
|
||||
));
|
||||
|
||||
setProject = createEffect(() => this.actions$.pipe(
|
||||
ofType(actions.setSelectedProject),
|
||||
switchMap(action => [actions.getCompanyTags()]
|
||||
.concat(!!action.project?.id ? [actions.getTags(action.project.id)] : []))
|
||||
));
|
||||
|
||||
getProjects$ = createEffect(() => this.actions$.pipe(
|
||||
ofType(actions.getAllSystemProjects),
|
||||
withLatestFrom(
|
||||
@@ -154,22 +160,28 @@ export class ProjectsEffects {
|
||||
ofType(actions.getTags),
|
||||
withLatestFrom(this.store.select(selectRouterParams).pipe(
|
||||
map(params => (params === null || params?.projectId === '*') ? [] : [params.projectId]))),
|
||||
switchMap(([action, projects]) => forkJoin([
|
||||
this.projectsApi.projectsGetTaskTags({projects}),
|
||||
this.projectsApi.projectsGetModelTags({projects})]
|
||||
).pipe(
|
||||
map((res: [ProjectsGetTaskTagsResponse, ProjectsGetModelTagsResponse]) =>
|
||||
Array.from(new Set(res[0].tags.concat(res[1].tags))).sort()),
|
||||
mergeMap((tags: string[]) => [
|
||||
actions.setTags({tags}),
|
||||
deactivateLoader(action.type)
|
||||
]),
|
||||
catchError(error => [
|
||||
requestFailed(error),
|
||||
deactivateLoader(action.type),
|
||||
setServerError(error, null, 'Fetch tags failed')]
|
||||
)
|
||||
))
|
||||
switchMap(([action, projects]) => {
|
||||
const ids = action?.projectId ? [action.projectId] : projects;
|
||||
if (ids.length === 0 || !ids[0]) {
|
||||
return EMPTY;
|
||||
}
|
||||
return forkJoin([
|
||||
this.projectsApi.projectsGetTaskTags({projects: action?.projectId ? [action.projectId] : projects}),
|
||||
this.projectsApi.projectsGetModelTags({projects: action?.projectId ? [action.projectId] : projects})]
|
||||
).pipe(
|
||||
map((res: [ProjectsGetTaskTagsResponse, ProjectsGetModelTagsResponse]) =>
|
||||
Array.from(new Set(res[0].tags.concat(res[1].tags))).sort()),
|
||||
mergeMap((tags: string[]) => [
|
||||
actions.setTags({tags}),
|
||||
deactivateLoader(action.type)
|
||||
]),
|
||||
catchError(error => [
|
||||
requestFailed(error),
|
||||
deactivateLoader(action.type),
|
||||
setServerError(error, null, 'Fetch tags failed')]
|
||||
)
|
||||
);
|
||||
})
|
||||
));
|
||||
|
||||
openMoreInfoPopupEffect = createEffect(() => this.actions$.pipe(
|
||||
|
||||
@@ -31,6 +31,7 @@ import {escapeRegex} from '../shared/utils/shared-utils';
|
||||
import {isEqual} from 'lodash/fp';
|
||||
import {activeSearchLink} from '~/features/dashboard-search/dashboard-search.consts';
|
||||
import {EmptyAction} from '~/app.constants';
|
||||
import {selectCurrentUser, selectShowOnlyUserWork} from '@common/core/reducers/users-reducer';
|
||||
|
||||
export const getEntityStatQuery = action => ({
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
@@ -46,26 +47,27 @@ export const getEntityStatQuery = action => ({
|
||||
fields: ['name', 'id']
|
||||
},
|
||||
type: ['__$not', 'annotation_manual', '__$not', 'annotation', '__$not', 'dataset_import'],
|
||||
system_tags: ['-archived', '-pipeline', '-dataset']
|
||||
system_tags: ['-archived', '-pipeline', '-dataset'],
|
||||
},
|
||||
models: {_any_: {
|
||||
...(action.query && {pattern: action.regExp ? action.query : escapeRegex(action.query)}),
|
||||
fields: ['name', 'id']
|
||||
}},
|
||||
},
|
||||
},
|
||||
datasets: {_any_: {
|
||||
...(action.query && {pattern: action.regExp ? action.query : escapeRegex(action.query)}),
|
||||
fields: ['basename', 'id']
|
||||
},
|
||||
search_hidden: true,
|
||||
system_tags: ['dataset'],
|
||||
name: '/\\.datasets/'
|
||||
name: '/\\.datasets/',
|
||||
},
|
||||
pipelines: {_any_: {
|
||||
...(action.query && {pattern: action.regExp ? action.query : escapeRegex(action.query)}),
|
||||
fields: ['basename', 'id']
|
||||
},
|
||||
search_hidden: true,
|
||||
system_tags: ['pipeline']
|
||||
system_tags: ['pipeline'],
|
||||
}
|
||||
/* eslint-enable @typescript-eslint/naming-convention */
|
||||
});
|
||||
@@ -90,7 +92,8 @@ export class DashboardSearchEffects {
|
||||
ofType(searchStart),
|
||||
withLatestFrom(
|
||||
this.store.select(selectActiveSearch),
|
||||
this.store.select(selectSearchTerm)),
|
||||
this.store.select(selectSearchTerm)
|
||||
),
|
||||
mergeMap(([action, active, term]) => {
|
||||
const actionsToFire = [];
|
||||
if (!active) {
|
||||
@@ -108,7 +111,8 @@ export class DashboardSearchEffects {
|
||||
getCurrentPageResults = createEffect(() => this.actions.pipe(
|
||||
ofType(getCurrentPageResults),
|
||||
withLatestFrom(
|
||||
this.store.select(selectSearchTerm)),
|
||||
this.store.select(selectSearchTerm)
|
||||
),
|
||||
map(([action, term]) => {
|
||||
switch (action.activeLink) {
|
||||
case activeSearchLink.experiments:
|
||||
@@ -129,8 +133,12 @@ export class DashboardSearchEffects {
|
||||
|
||||
searchProjects = createEffect(() => this.actions.pipe(
|
||||
ofType(searchProjects),
|
||||
withLatestFrom(this.store.select(selectSearchScrollIds)),
|
||||
switchMap(([action, scrollIds]) => this.projectsApi.projectsGetAllEx({
|
||||
withLatestFrom(
|
||||
this.store.select(selectSearchScrollIds),
|
||||
this.store.select(selectShowOnlyUserWork),
|
||||
this.store.select(selectCurrentUser),
|
||||
),
|
||||
switchMap(([action, scrollIds, userFocus, user]) => this.projectsApi.projectsGetAllEx({
|
||||
_any_: {
|
||||
...(action.query && {pattern: action.regExp ? action.query : escapeRegex(action.query)}),
|
||||
fields: ['basename', 'id']
|
||||
@@ -140,6 +148,7 @@ export class DashboardSearchEffects {
|
||||
stats_for_state: ProjectsGetAllExRequest.StatsForStateEnum.Active,
|
||||
scroll_id: scrollIds?.[activeSearchLink.projects] || null,
|
||||
size: SEARCH_PAGE_SIZE,
|
||||
...(userFocus && {active_users: [user.id]}),
|
||||
include_stats: true,
|
||||
only_fields: ['name', 'company', 'user', 'created', 'default_output_destination', 'basename']
|
||||
/* eslint-enable @typescript-eslint/naming-convention */
|
||||
@@ -150,8 +159,12 @@ export class DashboardSearchEffects {
|
||||
|
||||
searchPipelines = createEffect(() => this.actions.pipe(
|
||||
ofType(searchPipelines),
|
||||
withLatestFrom(this.store.select(selectSearchScrollIds)),
|
||||
switchMap(([action, scrollIds]) => this.projectsApi.projectsGetAllEx({
|
||||
withLatestFrom(
|
||||
this.store.select(selectSearchScrollIds),
|
||||
this.store.select(selectShowOnlyUserWork),
|
||||
this.store.select(selectCurrentUser),
|
||||
),
|
||||
switchMap(([action, scrollIds, userFocus, user]) => this.projectsApi.projectsGetAllEx({
|
||||
_any_: {
|
||||
...(action.query && {pattern: action.regExp ? action.query : escapeRegex(action.query)}),
|
||||
fields: ['basename', 'id']
|
||||
@@ -163,6 +176,7 @@ export class DashboardSearchEffects {
|
||||
stats_for_state: ProjectsGetAllExRequest.StatsForStateEnum.Active,
|
||||
scroll_id: scrollIds?.[activeSearchLink.pipelines] || null,
|
||||
size: SEARCH_PAGE_SIZE,
|
||||
...(userFocus && {active_users: [user.id]}),
|
||||
include_stats: true,
|
||||
only_fields: ['name', 'company', 'user', 'created', 'default_output_destination', 'tags', 'system_tags', 'basename']
|
||||
/* eslint-enable @typescript-eslint/naming-convention */
|
||||
@@ -173,8 +187,12 @@ export class DashboardSearchEffects {
|
||||
|
||||
searchOpenDatasets = createEffect(() => this.actions.pipe(
|
||||
ofType(searchOpenDatasets),
|
||||
withLatestFrom(this.store.select(selectSearchScrollIds)),
|
||||
switchMap(([action, scrollIds]) => this.projectsApi.projectsGetAllEx({
|
||||
withLatestFrom(
|
||||
this.store.select(selectSearchScrollIds),
|
||||
this.store.select(selectShowOnlyUserWork),
|
||||
this.store.select(selectCurrentUser),
|
||||
),
|
||||
switchMap(([action, scrollIds, userFocus, user]) => this.projectsApi.projectsGetAllEx({
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
_any_: {
|
||||
...(action.query && {pattern: action.regExp ? action.query : escapeRegex(action.query)}),
|
||||
@@ -187,6 +205,7 @@ export class DashboardSearchEffects {
|
||||
stats_for_state: ProjectsGetAllExRequest.StatsForStateEnum.Active,
|
||||
scroll_id: scrollIds?.[activeSearchLink.openDatasets] || null,
|
||||
size: SEARCH_PAGE_SIZE,
|
||||
...(userFocus && {active_users: [user.id]}),
|
||||
include_dataset_stats: true,
|
||||
stats_with_children: false,
|
||||
include_stats: true,
|
||||
@@ -200,8 +219,12 @@ export class DashboardSearchEffects {
|
||||
|
||||
searchModels = createEffect(() => this.actions.pipe(
|
||||
ofType(searchModels),
|
||||
withLatestFrom(this.store.select(selectSearchScrollIds)),
|
||||
switchMap(([action, scrollIds]) => this.modelsApi.modelsGetAllEx({
|
||||
withLatestFrom(
|
||||
this.store.select(selectSearchScrollIds),
|
||||
this.store.select(selectShowOnlyUserWork),
|
||||
this.store.select(selectCurrentUser),
|
||||
),
|
||||
switchMap(([action, scrollIds, userFocus, user]) => this.modelsApi.modelsGetAllEx({
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
_any_: {
|
||||
...(action.query && {pattern: action.regExp ? action.query : escapeRegex(action.query)}),
|
||||
@@ -209,6 +232,7 @@ export class DashboardSearchEffects {
|
||||
},
|
||||
scroll_id: scrollIds?.[activeSearchLink.models] || null,
|
||||
size: SEARCH_PAGE_SIZE,
|
||||
...(userFocus && {user: [user.id]}),
|
||||
system_tags: ['-archived'],
|
||||
include_stats: true,
|
||||
only_fields: ['ready', 'created', 'framework', 'user.name', 'name', 'parent.name', 'task.name', 'id', 'company']
|
||||
@@ -220,8 +244,12 @@ export class DashboardSearchEffects {
|
||||
|
||||
searchExperiments = createEffect(() => this.actions.pipe(
|
||||
ofType(searchExperiments),
|
||||
withLatestFrom(this.store.select(selectSearchScrollIds)),
|
||||
switchMap(([action, scrollIds]) => this.experimentsApi.tasksGetAllEx({
|
||||
withLatestFrom(
|
||||
this.store.select(selectSearchScrollIds),
|
||||
this.store.select(selectShowOnlyUserWork),
|
||||
this.store.select(selectCurrentUser),
|
||||
),
|
||||
switchMap(([action, scrollIds, userFocus, user]) => this.experimentsApi.tasksGetAllEx({
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
_any_: {
|
||||
...(action.query && {pattern: action.regExp ? action.query : escapeRegex(action.query)}),
|
||||
@@ -229,6 +257,7 @@ export class DashboardSearchEffects {
|
||||
},
|
||||
scroll_id: scrollIds?.[activeSearchLink.experiments] || null,
|
||||
size: SEARCH_PAGE_SIZE,
|
||||
...(userFocus && {user: [user.id]}),
|
||||
only_fields: EXPERIMENT_SEARCH_ONLY_FIELDS,
|
||||
type: ['__$not', 'annotation_manual', '__$not', 'annotation', '__$not', 'dataset_import'],
|
||||
system_tags: ['-archived', '-pipeline', '-dataset']
|
||||
|
||||
@@ -6,8 +6,9 @@
|
||||
<div>
|
||||
<button *ngIf="(recentProjectsList$ | async).length >= cardsInRow || overflow"
|
||||
class="btn btn-cml-primary d-flex align-items-center"
|
||||
data-id="New Project"
|
||||
(click)="openCreateProjectDialog()">
|
||||
<i class="al-icon al-color sm blue-400 al-ico-add mr-2"></i>NEW PROJECT
|
||||
<i class="al-icon sm al-ico-add mr-2"></i>NEW PROJECT
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,7 +4,7 @@ import {Model} from '~/business-logic/model/models/model';
|
||||
import {clearSearchResults, getCurrentPageResults, searchClear, searchDeactivate, searchStart} from '../dashboard-search/dashboard-search.actions';
|
||||
import {IRecentTask} from './common-dashboard.reducer';
|
||||
import {ITask} from '~/business-logic/model/al-task';
|
||||
import {Observable, Subscription} from 'rxjs';
|
||||
import {combineLatest, Observable, Subscription} from 'rxjs';
|
||||
import {SearchState, selectSearchQuery} from '../common-search/common-search.reducer';
|
||||
import {Store} from '@ngrx/store';
|
||||
import {
|
||||
@@ -17,6 +17,7 @@ import {isExample} from '../shared/utils/shared-utils';
|
||||
import {activeLinksList, ActiveSearchLink, activeSearchLink} from '~/features/dashboard-search/dashboard-search.consts';
|
||||
import {Component, OnDestroy, OnInit} from '@angular/core';
|
||||
import {Router} from '@angular/router';
|
||||
import { selectShowOnlyUserWork } from '@common/core/reducers/users-reducer';
|
||||
|
||||
@Component({
|
||||
selector: 'sm-dashboard-search-base',
|
||||
@@ -69,9 +70,7 @@ export class DashboardSearchBaseComponent implements OnInit, OnDestroy{
|
||||
public ngOnInit(): void {
|
||||
this.allResultsSubscription = this.resultsCount$.pipe(
|
||||
filter(resultsCount => !!resultsCount),
|
||||
).subscribe((resultsCount) => {
|
||||
return this.setFirstActiveLink(resultsCount);
|
||||
});
|
||||
).subscribe((resultsCount) => this.setFirstActiveLink(resultsCount));
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
@@ -89,9 +88,12 @@ export class DashboardSearchBaseComponent implements OnInit, OnDestroy{
|
||||
syncAppSearch() {
|
||||
this.store.dispatch(initSearch({payload: 'Search for all'}));
|
||||
|
||||
this.searchSubs = this.searchQuery$
|
||||
this.searchSubs = combineLatest([
|
||||
this.searchQuery$,
|
||||
this.store.select(selectShowOnlyUserWork),
|
||||
])
|
||||
.pipe(skip(1))
|
||||
.subscribe(query => this.searchTermChanged(query?.query, query?.regExp));
|
||||
.subscribe(([query]) => this.searchTermChanged(query?.query, query?.regExp));
|
||||
|
||||
this.searchSubs.add(this.store.select(selectSearchScrollIds).subscribe(scrollIds => this.scrollIds = scrollIds));
|
||||
}
|
||||
|
||||
@@ -14,10 +14,12 @@
|
||||
pattern="^[^/]+$"
|
||||
[inlineDisabled]="true"
|
||||
(textChanged)="prepareProjectNameForChange($event)"
|
||||
(inlineActiveStateChanged)="projectNameEditActiveChanged($event)"
|
||||
|
||||
>
|
||||
<span class="project-name" [smTooltip]="project.name">{{project.name | shortProjectName}}</span>
|
||||
<span class="d-flex align-items-center"><span class="project-name"
|
||||
[smTooltip]="project.name | cleanProjectPath">{{project.name | shortProjectName}}</span>
|
||||
<i *ngIf="project.name | cleanProjectPath: false" [smTooltip]="project.name | cleanProjectPath:false"
|
||||
class="al-icon al-ico-project-path sm ml-2"></i></span>
|
||||
</sm-inline-edit>
|
||||
<sm-pipeline-card-menu
|
||||
class="menu-wrapper"
|
||||
@@ -31,7 +33,9 @@
|
||||
></sm-pipeline-card-menu>
|
||||
</div>
|
||||
<div *ngIf="project.last_update; else: noRun" class="last-run">Updated {{project.last_update | timeAgo}}</div>
|
||||
<ng-template #noRun><div class="last-run"></div></ng-template>
|
||||
<ng-template #noRun>
|
||||
<div class="last-run"></div>
|
||||
</ng-template>
|
||||
</div>
|
||||
<div class="d-flex justify-content-around w-100">
|
||||
<sm-circle-counter
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
}
|
||||
|
||||
.project-name {
|
||||
max-width: 280px;
|
||||
max-width: 250px;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
[filetype="html"]::before,
|
||||
[filetype="yaml"]::before,
|
||||
[filetype="json"]::before {
|
||||
content: "\e9a4"; // code-icon
|
||||
content: "\e9a4"; // al-ico-code
|
||||
color: #a35151;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,10 +34,13 @@ export class SimpleDatasetVersionInfoComponent extends PipelineControllerInfoCom
|
||||
) {
|
||||
super(_dagManager, store, cdr, zone);
|
||||
}
|
||||
|
||||
convertPipelineToDagModel(pipeline): PipelineItem[] {
|
||||
const res = super.convertPipelineToDagModel(pipeline);
|
||||
if (res?.length > 0) {
|
||||
window.setTimeout(() => this.selectStep(last(res)), 1000);
|
||||
} else if (this.infoData?.id){
|
||||
this.store.dispatch(getSelectedPipelineStep({id: this.infoData.id}));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<div *ngIf="activateFromMenuButton" [matMenuTriggerFor]="experimentMenu"
|
||||
class="p-0 cell menu-button al-icon sm-md al-color light-grey-blue al-ico-bars-menu"
|
||||
class="p-0 cell menu-button al-icon sm-md al-color blue-300 al-ico-bars-menu"
|
||||
></div>
|
||||
<div *ngIf="!activateFromMenuButton" #contextTrigger
|
||||
style="visibility: hidden; position: fixed"
|
||||
@@ -9,7 +9,7 @@
|
||||
</div>
|
||||
<mat-menu #experimentMenu="matMenu" [hasBackdrop]="false">
|
||||
<button *ngIf="tableMode" mat-menu-item (click)="toggleDetails()">
|
||||
<i [class]="'al-icon '+ ICONS.DETAILS + ' sm-md'"></i>Details
|
||||
<i [class]="'al-icon '+ icons.DETAILS + ' sm-md'"></i>Details
|
||||
</button>
|
||||
<hr *ngIf="tableMode">
|
||||
<button mat-menu-item
|
||||
@@ -17,19 +17,19 @@
|
||||
[disabled]="selectedDisableAvailable[menuItems.tags]?.disable"
|
||||
(menuOpened)="tagMenuOpened()"
|
||||
(menuClosed)="tagMenuClosed()">
|
||||
<i [class]="'al-icon ' + ICONS.TAG + ' sm-md'">
|
||||
<i [class]="'al-icon ' + icons.TAG + ' sm-md'">
|
||||
</i><span>{{selectedDisableAvailable[menuItems.tags]?.available | menuItemText : 'Add Tag' : selectedDisableAvailableIsMultiple }}</span>
|
||||
</button>
|
||||
|
||||
<button mat-menu-item (click)="restoreArchive(entityTypeEnum.dataset)"
|
||||
[disabled]="selectedDisableAvailable[menuItems.archive]?.disable">
|
||||
<i class="al-icon sm-md" [class]="isArchive ? ICONS.RESTORE : ICONS.ARCHIVE"></i>
|
||||
<i class="al-icon sm-md" [class]="isArchive ? icons.RESTORE : icons.ARCHIVE"></i>
|
||||
{{selectedDisableAvailable[menuItems.archive]?.available | menuItemText : isArchive ? 'Restore from Archive' : 'Archive' : selectedDisableAvailableIsMultiple}}
|
||||
</button>
|
||||
|
||||
<button mat-menu-item (click)="deleteExperimentPopup(entityTypeEnum.dataset, true)"
|
||||
[disabled]="selectedDisableAvailable[menuItems.delete]?.disable" *ngIf="isArchive">
|
||||
<i [class]="'al-icon ' + ICONS.REMOVE + ' sm-md'"></i>
|
||||
<i [class]="'al-icon ' + icons.REMOVE + ' sm-md'"></i>
|
||||
{{selectedDisableAvailable[menuItems.delete]?.available | menuItemText : 'Delete' : selectedDisableAvailableIsMultiple}}
|
||||
</button>
|
||||
</mat-menu>
|
||||
|
||||
@@ -50,7 +50,8 @@ export class SimpleDatasetVersionsComponent extends ControllersComponent impleme
|
||||
if (!this.route.snapshot.firstChild?.params.versionId) {
|
||||
this.store.dispatch(experimentsActions.experimentSelectionChanged({
|
||||
experiment: this.firstExperiment,
|
||||
project: this.selectedProject
|
||||
project: this.selectedProject,
|
||||
replaceURL: true
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<button
|
||||
class="btn btn-cml-primary d-flex align-items-center"
|
||||
(click)="createDataset()">
|
||||
<i class="al-icon al-color blue-400 al-ico-add sm mr-2"></i>NEW DATASET
|
||||
<i class="al-icon al-ico-add sm mr-2"></i>NEW DATASET
|
||||
</button>
|
||||
</sm-projects-header>
|
||||
<ng-container *ngFor="let project of projects; trackBy: trackById ;let last=last">
|
||||
|
||||
@@ -20,7 +20,7 @@ export const getDebugImagesMetrics = createAction(
|
||||
|
||||
export const refreshDebugImagesMetrics = createAction(
|
||||
DEBUG_IMAGES_PREFIX + 'REFRESH_DEBUG_IMAGES_METRICS',
|
||||
props<{ tasks: string[], autoRefresh?: boolean }>()
|
||||
props<{ tasks: string[]; autoRefresh?: boolean }>()
|
||||
);
|
||||
|
||||
export const fetchExperiments = createAction(
|
||||
@@ -69,7 +69,10 @@ export const setBeginningOfTime = createAction(
|
||||
);
|
||||
|
||||
export const getDebugImageSample = createAction(DEBUG_IMAGES_PREFIX + 'GET_DEBUG_IMAGES_FOR_ITERATION', props<{ task: string; metric: string; variant: string; iteration: number; isAllMetrics: boolean }>());
|
||||
export const getNextDebugImageSample = createAction(DEBUG_IMAGES_PREFIX + 'GET_NEXT_DEBUG_IMAGE', props<{ task: string; navigateEarlier: boolean }>());
|
||||
export const getNextDebugImageSample = createAction(
|
||||
DEBUG_IMAGES_PREFIX + 'GET_NEXT_DEBUG_IMAGE',
|
||||
props<{ task: string; navigateEarlier: boolean; iteration?: boolean }>()
|
||||
);
|
||||
export const setCurrentDebugImage = createAction(DEBUG_IMAGES_PREFIX + 'SET_DEBUG_IMAGES_FOR_ITERATION', props<{ event: any }>());
|
||||
export const setDebugImageViewerScrollId = createAction(DEBUG_IMAGES_PREFIX + 'SET_DEBUG_IMAGE_VIEWER_SCROLL_ID', props<{ scrollId: string }>());
|
||||
export const setDebugImageIterations = createAction(DEBUG_IMAGES_PREFIX + 'SET_DEBUG_IMAGE_ITERATIONS', props<EventsGetDebugImageIterationsResponse>());
|
||||
|
||||
@@ -178,7 +178,8 @@ export class DebugImagesEffects {
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
task: action.task,
|
||||
scroll_id: scrollId,
|
||||
navigate_earlier: action.navigateEarlier
|
||||
navigate_earlier: action.navigateEarlier,
|
||||
...(action.iteration && {next_iteration: true})
|
||||
/* eslint-enable @typescript-eslint/naming-convention */
|
||||
})
|
||||
.pipe(
|
||||
@@ -191,7 +192,7 @@ export class DebugImagesEffects {
|
||||
setDebugImageIterations({min_iteration: res.min_iteration, max_iteration: res.max_iteration}),
|
||||
setCurrentDebugImage({event: res.event}), deactivateLoader(action.type),
|
||||
setDebugImageViewerScrollId({scrollId: res.scroll_id}),
|
||||
action.navigateEarlier ? setViewerBeginningOfTime({beginningOfTime: false}) : setViewerEndOfTime({endOfTime: false})
|
||||
!action.navigateEarlier ? setViewerBeginningOfTime({beginningOfTime: false}) : setViewerEndOfTime({endOfTime: false})
|
||||
];
|
||||
}
|
||||
}),
|
||||
|
||||
@@ -30,21 +30,21 @@
|
||||
|
||||
<div [ngClass]="{'disabled': (beginningOfTime$| async)[experimentId]}"
|
||||
(click)="nextBatch({task: experimentId, metric: metricSelect.value})"
|
||||
class="al-icon al-ico-next-batch al-color light-grey-blue"
|
||||
class="al-icon al-ico-next-batch al-color blue-300"
|
||||
smTooltip="Older images"></div>
|
||||
|
||||
<b class="text-right">{{debugImages?.[experimentId]?.data.slice(-1)[0].iter}}</b>
|
||||
<b class="text-right">{{debugImages?.[experimentId]?.data?.slice(-1)[0].iter}}</b>
|
||||
<div class="al-icon al-ico-between al-color light-blue-grey"></div>
|
||||
<b>{{debugImages?.[experimentId]?.data?.[0].iter}}</b>
|
||||
|
||||
<div [ngClass]="{'disabled': (timeIsNow$| async)[experimentId]}"
|
||||
(click)="(!timeIsNow[experimentId]) && previousBatch({task: experimentId, metric: metricSelect.value})"
|
||||
class="al-icon al-ico-prev-batch al-color light-grey-blue"
|
||||
class="al-icon al-ico-prev-batch al-color blue-300"
|
||||
smTooltip="Newer images"></div>
|
||||
|
||||
<div [ngClass]="{'disabled': (timeIsNow$| async)[experimentId] && !allowAutorefresh }"
|
||||
(click)="(!(timeIsNow[experimentId] && !allowAutorefresh)) && backToNow({task: experimentId, metric: metricSelect.value})"
|
||||
class="al-icon al-ico-back-to-top al-color light-grey-blue"
|
||||
class="al-icon al-ico-back-to-top al-color blue-300"
|
||||
smTooltip="Newest samples"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
}
|
||||
}
|
||||
.navigator-container{
|
||||
height: 60px;
|
||||
|
||||
&.active{
|
||||
background: $blue-50;
|
||||
}
|
||||
|
||||
@@ -156,7 +156,6 @@ export class DebugImagesComponent implements OnInit, OnDestroy, OnChanges {
|
||||
return acc;
|
||||
}), {}))
|
||||
).subscribe(debugImages => {
|
||||
console.log(debugImages);
|
||||
this.debugImages = debugImages;
|
||||
if (debugImages === null) {
|
||||
return;
|
||||
|
||||
@@ -176,7 +176,7 @@ $extra-header-min-height: 50px;
|
||||
width: 24px;
|
||||
margin-left: auto;
|
||||
cursor: pointer;
|
||||
color: $light-grey-blue;
|
||||
color: $blue-300;
|
||||
|
||||
&:hover {
|
||||
color: $blue-400;
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
[selectFilteredItems]="selectShowIdenticalHyperParams$ | async"
|
||||
[selectedItemsListMapper]="selectedItemsListMapper"
|
||||
selectedItemsListPrefix=""
|
||||
[limitSelection]="10"
|
||||
[limitSelection]="50"
|
||||
(selectedItems)="selectedParamsChanged($event)"
|
||||
(clearSelection)="clearSelection()"
|
||||
>
|
||||
|
||||
@@ -56,10 +56,10 @@
|
||||
<div class="buttons">
|
||||
<button type="submit"
|
||||
(click)="applyChanges()"
|
||||
class="btn btn-neon yes-button">
|
||||
class="btn btn-neon yes-button" data-id="ApplyButton">
|
||||
APPLY
|
||||
</button>
|
||||
<button (click)="closeDialog()" class="btn btn-outline-neon">
|
||||
<button (click)="closeDialog()" class="btn btn-outline-neon" data-id ="CancelButton">
|
||||
CANCEL
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
<span class="dot-container">
|
||||
<span #dot class="dot pallete-cursor"
|
||||
[style.background-color]="experimentsColors[experiment.id]"
|
||||
smChooseColor [colorButtonRef]="dot"
|
||||
[defaultColor]="experimentsColors[getExperimentNameForColor(experiment)]"
|
||||
[colorButtonRef]="dot"
|
||||
[smChooseColor]="experimentsColors[getExperimentNameForColor(experiment)]"
|
||||
[stringToColor]="getExperimentNameForColor(experiment)">
|
||||
</span>
|
||||
</span>
|
||||
|
||||
@@ -8,7 +8,7 @@ import {Task} from '~/business-logic/model/tasks/task';
|
||||
import {select} from 'd3-selection';
|
||||
import {sortCol} from '@common/shared/utils/tableParamEncode';
|
||||
import {Store} from '@ngrx/store';
|
||||
import {Axis, Color, ColorScale} from 'plotly.js';
|
||||
import {Axis, Color, ColorBar, ColorScale} from 'plotly.js';
|
||||
import domtoimage from 'dom-to-image/dist/dom-to-image.min';
|
||||
import {from} from 'rxjs';
|
||||
|
||||
@@ -28,10 +28,13 @@ interface Dimension extends Partial<Axis> {
|
||||
|
||||
interface ParaPlotData {
|
||||
type: string;
|
||||
labelangle: 'auto' | number;
|
||||
labelside?: 'top' | 'bottom';
|
||||
dimensions: Dimension[];
|
||||
line: {
|
||||
color: Color;
|
||||
colorscale?: ColorScale;
|
||||
colorbar?: Partial<ColorBar>;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -185,6 +188,7 @@ export class ParallelCoordinatesGraphComponent extends PlotlyGraphBaseComponent
|
||||
if (this.parameters && filteredExperiments.length > 0) {
|
||||
const trace = {
|
||||
type: 'parcoords',
|
||||
labelangle: 30,
|
||||
dimensions: this.parameters.map((parameter) => {
|
||||
parameter = `${parameter}.value`;
|
||||
const allValuesIncludingNull = this.experiments.map(experiment => get(parameter, experiment.hyperparams));
|
||||
@@ -209,7 +213,8 @@ export class ParallelCoordinatesGraphComponent extends PlotlyGraphBaseComponent
|
||||
tickvals,
|
||||
values: filteredExperiments.map((experiment) => (textVal[['', undefined].includes(get(parameter, experiment.hyperparams)) ? 'N/A' : get(parameter, experiment.hyperparams)])),
|
||||
range: [0, max(tickvals)],
|
||||
constraintrange
|
||||
constraintrange,
|
||||
|
||||
};
|
||||
})
|
||||
} as ParaPlotData ;
|
||||
|
||||
@@ -125,9 +125,11 @@ export const toggleSettings = createAction(EXPERIMENTS_OUTPUT_PREFIX + 'TOGGLE_S
|
||||
|
||||
export const getPlotSample = createAction(
|
||||
EXPERIMENTS_OUTPUT_PREFIX + 'GET_PLOT_FOR_ITERATION',
|
||||
props<{ task: string; metric: string; variant: string; iteration: number }>()
|
||||
props<{ task: string; metric: string; iteration: number }>()
|
||||
);
|
||||
export const getNextPlotSample = createAction(EXPERIMENTS_OUTPUT_PREFIX + 'GET_NEXT_PLOT', props<{ task: string; navigateEarlier: boolean }>());
|
||||
export const getNextPlotSample = createAction(
|
||||
EXPERIMENTS_OUTPUT_PREFIX + 'GET_NEXT_PLOT',
|
||||
props<{ task: string; navigateEarlier: boolean; iteration?: boolean }>());
|
||||
export const setCurrentPlot = createAction(EXPERIMENTS_OUTPUT_PREFIX + 'SET_PLOT_FOR_ITERATION', props<{ event: any }>());
|
||||
export const setPlotViewerScrollId = createAction(EXPERIMENTS_OUTPUT_PREFIX + 'SET_PLOT_VIEWER_SCROLL_ID', props<{ scrollId: string }>());
|
||||
export const setPlotIterations = createAction(EXPERIMENTS_OUTPUT_PREFIX + 'SET_PLOT_ITERATIONS', props<PlotSampleResponse>());
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {Action, createAction, props} from '@ngrx/store';
|
||||
import {createAction, props} from '@ngrx/store';
|
||||
import {IExperimentInfo, ISelectedExperiment} from '~/features/experiments/shared/experiment-info.model';
|
||||
import {Project} from '~/business-logic/model/projects/project';
|
||||
import {Queue} from '~/business-logic/model/queues/queue';
|
||||
@@ -8,9 +8,6 @@ import { PipelinesStartPipelineRequest } from '~/business-logic/model/pipelines/
|
||||
|
||||
export const EXPERIMENTS_INFO_PREFIX = 'EXPERIMENTS_INFO_';
|
||||
|
||||
// EVENTS:
|
||||
export const CLONE_EXPERIMENT_CLICKED = EXPERIMENTS_INFO_PREFIX + 'CLONE_EXPERIMENT_CLICKED';
|
||||
|
||||
|
||||
export const publishClicked = createAction(
|
||||
EXPERIMENTS_INFO_PREFIX + '[publish experiments]',
|
||||
@@ -28,7 +25,7 @@ export const startPipeline = createAction(
|
||||
|
||||
export const getControllerForStartPipelineDialog = createAction(
|
||||
EXPERIMENTS_INFO_PREFIX + '[Get Controller For Start Pipeline]',
|
||||
props<{task:string}>()
|
||||
props<{task: string}>()
|
||||
);
|
||||
|
||||
export const setControllerForStartPipelineDialog = createAction(
|
||||
@@ -47,12 +44,10 @@ export const dequeueClicked = createAction(
|
||||
props<{ selectedEntities: ISelectedExperiment[] }>()
|
||||
);
|
||||
|
||||
export class CloneExperimentClicked implements Action {
|
||||
readonly type = CLONE_EXPERIMENT_CLICKED;
|
||||
|
||||
constructor(public payload: { originExperiment: ISelectedExperiment; cloneData: CloneExperimentPayload }) {
|
||||
}
|
||||
}
|
||||
export const cloneExperimentClicked = createAction(
|
||||
EXPERIMENTS_INFO_PREFIX + 'CLONE_EXPERIMENT_CLICKED',
|
||||
props<{ originExperiment: ISelectedExperiment; cloneData: CloneExperimentPayload }>()
|
||||
);
|
||||
|
||||
export const addTag = createAction(
|
||||
EXPERIMENTS_INFO_PREFIX + '[add tag to experiment]',
|
||||
@@ -85,7 +80,7 @@ export const navigateToQueue = createAction(
|
||||
|
||||
export const enqueueClicked = createAction(
|
||||
EXPERIMENTS_INFO_PREFIX + '[enqueue experiments]',
|
||||
props<{ selectedEntities: ISelectedExperiment[]; queue: Queue }>()
|
||||
props<{ selectedEntities: ISelectedExperiment[]; queue: Queue; verifyWatchers: boolean }>()
|
||||
);
|
||||
|
||||
export const archiveSelectedExperiments = createAction(
|
||||
|
||||
@@ -81,7 +81,7 @@ export const setSelectedExperiment = createAction(
|
||||
|
||||
export const experimentSelectionChanged = createAction(
|
||||
EXPERIMENTS_PREFIX + ' [experiment selection changed]',
|
||||
props<{ experiment: { id?: string }; project?: string }>()
|
||||
props<{ experiment: { id?: string }; project?: string; replaceURL?: boolean }>()
|
||||
);
|
||||
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
[isGroupGraphs]="true"
|
||||
[hiddenList]="listOfHidden | async"
|
||||
[metrics]="graphs"
|
||||
[legendStringLength]="minimized? 14 : undefined"
|
||||
[legendStringLength]="minimized ? 14 : 19"
|
||||
[minimized]="minimized"
|
||||
[splitSize]="splitSize$ | async"
|
||||
[isDarkTheme]="dark"
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
[experimentName]="experimentName"
|
||||
[hiddenList]="listOfHidden | async"
|
||||
[smoothWeight]="smoothWeight$ | async"
|
||||
[legendStringLength]="minimized? 14 : undefined"
|
||||
[legendStringLength]="minimized ? 14 : 19"
|
||||
[minimized]="minimized"
|
||||
[xAxisType]="xAxisType$ | async"
|
||||
[groupBy]="groupBy"
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import {Component, OnDestroy} from '@angular/core';
|
||||
import {Component} from '@angular/core';
|
||||
import {Store} from '@ngrx/store';
|
||||
import {filter, map, take} from 'rxjs/operators';
|
||||
import {Subscription} from 'rxjs';
|
||||
import {selectSignedUrl} from '../../core/reducers/common-auth-reducer';
|
||||
import {AdminService} from '~/shared/services/admin.service';
|
||||
import {getSignedUrl} from '../../core/actions/common-auth.actions';
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<sm-menu
|
||||
[iconClass]="'al-icon al-ico-settings al-color pointer create-new-icon ' + (disabled ? 'pointer-events-none blue-600' : 'blue-400')"
|
||||
[iconClass]="'al-icon al-ico-settings al-color pointer create-new-icon ' + (disabled ? 'pointer-events-none blue-600' : 'blue-300')"
|
||||
smMenuClass="light-theme custom-columns"
|
||||
data-id="CustomizeColumn"
|
||||
buttonTooltip="Customize table"
|
||||
[showButton]="false"
|
||||
(click)="!disabled && getMetricsToDisplay.emit()"
|
||||
@@ -23,13 +24,13 @@
|
||||
smClickStopPropagation
|
||||
[ngClass]="{disabled: !metricVariants.length}"
|
||||
(click)="$event.stopPropagation(); metricVariants.length && setMode(CustomColumnMode.Metrics)"
|
||||
><i class="al-icon al-ico-add sm mr-1"></i><span class="caption">METRIC</span>
|
||||
><i class="al-icon al-ico-add sm mr-1"></i><span data-id="Metric Button" class="caption">METRIC</span>
|
||||
</div>
|
||||
<div class="add-button metrics-button"
|
||||
smClickStopPropagation
|
||||
[ngClass]="{disabled: !hasHyperParams}"
|
||||
(click)="$event.stopPropagation(); hasHyperParams && setMode(CustomColumnMode.HyperParams)"
|
||||
><i class="al-icon al-ico-add sm mr-1"></i><span class="caption">HYPER PARAMETERS</span>
|
||||
><i class="al-icon al-ico-add sm mr-1"></i><span data-id="Hyper Parameters Button" class="caption">HYPER PARAMETERS</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -41,6 +42,7 @@
|
||||
(selectedMetricToShow)="selectedMetricToShow.emit($event)">
|
||||
</sm-select-metric-for-custom-col>
|
||||
<sm-select-hyper-params-for-custom-col *ngIf="customColumnMode === CustomColumnMode.HyperParams"
|
||||
class="hyper-params-custom-col"
|
||||
[tableCols]="tableCols"
|
||||
[hyperParams]="hyperParams"
|
||||
(goBack)="setMode(CustomColumnMode.Standard)"
|
||||
|
||||
@@ -9,25 +9,26 @@
|
||||
|
||||
.custom-column-buttons {
|
||||
display: flex;
|
||||
border-top: 1px solid #C3CDEF;
|
||||
font-weight: 500;
|
||||
color: $light-grey-blue;
|
||||
color: $blue-400;
|
||||
background: $faint-gray;
|
||||
cursor: pointer;
|
||||
|
||||
div:not(.disabled):hover {
|
||||
color: $blue-400;
|
||||
color: $blue-300;
|
||||
transition: color 0.3s;
|
||||
}
|
||||
|
||||
.metrics-button {
|
||||
width: 50%;
|
||||
white-space: nowrap;
|
||||
border-right: 1px solid #C3CDEF;
|
||||
|
||||
.caption {
|
||||
margin-top: 2px;
|
||||
}
|
||||
&:first-child {
|
||||
border-right: 1px solid $blue-200;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +61,6 @@ sm-select-metric-for-custom-col {
|
||||
display: block;
|
||||
height: 640px;
|
||||
max-height: calc(100vh - 120px);
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.custom-columns-disabled {
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
matInput/>
|
||||
</mat-form-field>
|
||||
<div class="remove-step">
|
||||
<i (click)="removeRow(index)" class="al-icon al-ico-trash al-color blue-300 sm-md pointer flashing-icon mb-2"></i>
|
||||
<i (click)="removeRow(index)" class="al-icon al-ico-trash al-color blue-400 sm-md pointer flashing-icon mb-2"></i>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
[numSelected]="1"
|
||||
(tagSelected)="addTag($event)"
|
||||
></sm-experiment-menu-extended>
|
||||
<div *ngIf="minimized" (click)="closeInfoClicked.emit()" class="d-flex align-items-center line-item">
|
||||
<div *ngIf="minimized" (click)="closeInfoClicked.emit()" class="d-flex align-items-center line-item" data-id="Cross Button">
|
||||
<i class="al-icon al-ico-dialog-x pointer"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
<sm-id-badge *ngIf="model?.id" class="ml-3" [id]="model.id"></sm-id-badge>
|
||||
</div>
|
||||
<ng-container *ngIf="editable">
|
||||
<i class="al-icon al-ico-edit al-color blue-300 sm-md pointer mx-3" smTooltip="Select model" (click)="chooseModel()"></i>
|
||||
<i *ngIf="model?.id" class="al-icon al-ico-trash al-color blue-300 sm-md pointer" smTooltip="Remove model" (click)="removeModel()"></i>
|
||||
<i class="al-icon al-ico-edit al-color blue-400 sm-md pointer mx-3" smTooltip="Select model" (click)="chooseModel()"></i>
|
||||
<i *ngIf="model?.id" class="al-icon al-ico-trash al-color blue-400 sm-md pointer" smTooltip="Remove model" (click)="removeModel()"></i>
|
||||
</ng-container>
|
||||
</div>
|
||||
</sm-labeled-row>
|
||||
|
||||
@@ -55,13 +55,13 @@
|
||||
(formDataChanged)="headerCheckboxClicked()"
|
||||
inputClassName="table-check-box select-col-checkbox"
|
||||
></sm-checkbox-control>
|
||||
<div class="al-icon al-ico-dropdown-arrow sm drop-down" [matMenuTriggerFor]="selectionMenu"></div>
|
||||
<div class="al-icon al-ico-dropdown-arrow sm drop-down" data-id="Checkbox Dropdown" [matMenuTriggerFor]="selectionMenu"></div>
|
||||
</div>
|
||||
<mat-menu class="light-theme" #selectionMenu="matMenu">
|
||||
<div *ngIf="entityType === entityTypes.experiment" class="menu-title">Select from project</div>
|
||||
<button mat-menu-item (click)="selectAll()">All</button>
|
||||
<button mat-menu-item (click)="emitSelection([])">None</button>
|
||||
<button mat-menu-item (click)="selectAll(true)">All matching filter</button>
|
||||
<button mat-menu-item data-id="All Option" (click)="selectAll()">All</button>
|
||||
<button mat-menu-item data-id="None Option" (click)="emitSelection([])">None</button>
|
||||
<button mat-menu-item data-id="All Matching Filter Option" (click)="selectAll(true)">All matching filter</button>
|
||||
</mat-menu>
|
||||
</ng-template>
|
||||
<!--FILTER TEMPLATE-->
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, OnDestroy, OnInit, Output, TemplateRef,} from '@angular/core';
|
||||
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, OnDestroy, OnInit, Output, TemplateRef} from '@angular/core';
|
||||
import {TIME_FORMAT_STRING} from '@common/constants';
|
||||
import {ColHeaderTypeEnum, ISmCol} from '@common/shared/ui-components/data/table/table.consts';
|
||||
import {FILTERED_EXPERIMENTS_STATUS_OPTIONS} from '../../shared/common-experiments.const';
|
||||
import {get, uniq} from 'lodash/fp';
|
||||
import {FilterMetadata} from 'primeng/api/filtermetadata';
|
||||
import {ITableExperiment} from '../../shared/common-experiment-model.model';
|
||||
import {EXPERIMENTS_TABLE_COL_FIELDS,} from '~/features/experiments/shared/experiments.const';
|
||||
import {EXPERIMENTS_TABLE_COL_FIELDS} from '~/features/experiments/shared/experiments.const';
|
||||
import {BaseTableView} from '@common/shared/ui-components/data/table/base-table-view';
|
||||
import {getSystemTags, isDevelopment} from '~/features/experiments/shared/experiments.utils';
|
||||
import {User} from '~/business-logic/model/users/user';
|
||||
@@ -284,7 +284,7 @@ export class ExperimentsTableComponent extends BaseTableView implements OnInit,
|
||||
if (!data?.single) {
|
||||
this.contextExperiment = this._experiments.find(experiment => experiment.id === data.rowData.id);
|
||||
if (!this.selectedExperiments.map(exp => exp.id).includes(this.contextExperiment.id)) {
|
||||
this.prevSelected = this.contextExperiment;
|
||||
this.prevSelected = this.contextExperiment.id;
|
||||
this.emitSelection([this.contextExperiment]);
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<div class="modal-container">
|
||||
<div class="viewer-header">
|
||||
<div class="image-title third">
|
||||
{{currentDebugImage?.metric? (currentDebugImage?.metric + ' - ' + currentDebugImage?.variant) : ''}}
|
||||
<input #fakeInput name="Don't remove - it take the autofocus from slider" width="0" height="0" style="opacity: 0">
|
||||
<h1 [smTooltip]="currentDebugImage?.metric? (currentDebugImage?.metric + ' - ' + currentDebugImage?.variant) : ''" smShowTooltipIfEllipsis>{{currentDebugImage?.metric? (currentDebugImage?.metric + ' - ' + currentDebugImage?.variant) : ''}}</h1>
|
||||
<input #fakeInput name="Don't remove - it take the autofocus from slider" class="invisible">
|
||||
</div>
|
||||
<div class="third viewer-iteration">
|
||||
<div *ngIf="minMaxIterations$| async as minMaxIterations">
|
||||
@@ -24,10 +24,10 @@
|
||||
<div class="d-flex third">
|
||||
<div (click)="downloadImage()" smTooltip="Download" class="download icon-container"
|
||||
[style.visibility]="(url | isVideo) ? 'hidden' : 'visible'">
|
||||
<i class="al-icon al-ico-download al-color light-grey-blue"></i>
|
||||
<i class="al-icon al-ico-download al-color blue-400"></i>
|
||||
</div>
|
||||
<div (click)="closeImageViewer()" smTooltip="Close" class="icon-container">
|
||||
<i class="al-icon al-ico-dialog-x al-color blue-400 light-grey-blue"></i>
|
||||
<i class="al-icon al-ico-dialog-x al-color blue-400"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -52,21 +52,21 @@
|
||||
class="fit-to-screen d-flex flex-column justify-content-around align-items-center controller icon-container"
|
||||
smTooltip="Fit to window" matTooltipPosition="left"
|
||||
[class.disabled]="scale===autoFitScale">
|
||||
<i class="al-icon al-ico-fit al-color light-grey-blue"></i>
|
||||
<i class="al-icon al-ico-fit al-color blue-400"></i>
|
||||
</div>
|
||||
|
||||
<div class="zoom controller d-flex flex-column justify-content-around align-items-center">
|
||||
<div class="icon-container">
|
||||
<i class="al-icon al-ico-plus al-color light-grey-blue" (click)="calculateNewScale(true)" smTooltip="Zoom in"
|
||||
<i class="al-icon al-ico-plus al-color blue-400" (click)="calculateNewScale(true)" smTooltip="Zoom in"
|
||||
matTooltipPosition="left"></i>
|
||||
</div>
|
||||
<div class="d-flex flex-column justify-content-around align-items-center icon-container" (click)="resetScale()"
|
||||
smTooltip="Zoom to 1:1" matTooltipPosition="left"
|
||||
[class.disabled]="scale===1">
|
||||
<i class="al-icon al-ico-zoom-1-to-1 al-color light-grey-blue sm-md"></i>
|
||||
<i class="al-icon al-ico-zoom-1-to-1 al-color blue-400 sm-md"></i>
|
||||
</div>
|
||||
<div class="icon-container">
|
||||
<div class="al-icon al-ico-minus al-color light-grey-blue" (click)="calculateNewScale(false)"
|
||||
<div class="al-icon al-ico-minus al-color blue-400" (click)="calculateNewScale(false)"
|
||||
smTooltip="Zoom out" matTooltipPosition="left"></div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -74,10 +74,10 @@
|
||||
<div class="navigation">
|
||||
<div class="icon-container controller d-flex flex-column justify-content-around align-items-center next"
|
||||
(click)="canGoNext() && next()" [class.disabled]="endOfTime$ | async">
|
||||
<i class="al-icon al-ico-next al-color light-grey-blue"></i></div>
|
||||
<i class="al-icon al-ico-next al-color blue-400"></i></div>
|
||||
<div class="icon-container controller d-flex flex-column justify-content-around align-items-center previous"
|
||||
(click)="canGoBack() && previous()" [class.disabled]="beginningOfTime$ | async">
|
||||
<i class="al-icon al-ico-previous al-color light-grey-blue"></i></div>
|
||||
<i class="al-icon al-ico-previous al-color blue-400"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0 24px;
|
||||
width: 100%;
|
||||
height: 58px;
|
||||
background-color: white;
|
||||
@@ -24,22 +25,38 @@
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: $blue-400;
|
||||
font-size: 18px;
|
||||
line-height: 1.5;
|
||||
font-size: 16px;
|
||||
|
||||
.number {
|
||||
color: $blue-500;
|
||||
}
|
||||
|
||||
mat-slider.mat-slider-horizontal {
|
||||
min-width: 280px;
|
||||
@media screen and (min-width: 960px) {
|
||||
mat-slider.mat-slider-horizontal {
|
||||
min-width: 280px;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.image-title {
|
||||
font-size: 18px;
|
||||
color: $blue-500;
|
||||
h1 {
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
color: $blue-500;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
padding:0;
|
||||
margin:0;
|
||||
}
|
||||
.invisible {
|
||||
position: absolute;
|
||||
width:0;
|
||||
height:0;
|
||||
padding: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.download {
|
||||
|
||||
@@ -90,6 +90,12 @@ export class ImageViewerComponent implements OnInit, OnDestroy {
|
||||
case 'ArrowLeft':
|
||||
this.previous();
|
||||
break;
|
||||
case 'ArrowUp':
|
||||
this.nextIteration();
|
||||
break;
|
||||
case 'ArrowDown':
|
||||
this.previousIteration();
|
||||
break;
|
||||
case '+':
|
||||
this.calculateNewScale(true);
|
||||
break;
|
||||
@@ -197,6 +203,20 @@ export class ImageViewerComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
}
|
||||
|
||||
private nextIteration() {
|
||||
if (this.canGoNext() && this.currentDebugImage) {
|
||||
this.imageLoaded = false;
|
||||
this.store.dispatch(getNextDebugImageSample({task: this.currentDebugImage.task, navigateEarlier: false, iteration: true}));
|
||||
}
|
||||
}
|
||||
|
||||
previousIteration() {
|
||||
if (this.canGoBack() && this.currentDebugImage) {
|
||||
this.imageLoaded = false;
|
||||
this.store.dispatch(getNextDebugImageSample({task: this.currentDebugImage.task, navigateEarlier: true, iteration: true}));
|
||||
}
|
||||
}
|
||||
|
||||
closeImageViewer() {
|
||||
this.store.dispatch(resetViewer());
|
||||
this.dialogRef.close();
|
||||
@@ -315,4 +335,5 @@ export class ImageViewerComponent implements OnInit, OnDestroy {
|
||||
showImage() {
|
||||
this.imageLoaded = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
<div smClickStopPropagation class="d-flex justify-content-between hyper-params-container">
|
||||
<i (click)="goBack.emit()" class="al-icon sm-md al-ico-back pointer" smClickStopPropagation></i>
|
||||
<div class="hyper-param-header">SELECT HYPER PARAMETERS TO DISPLAY
|
||||
</div>
|
||||
<div smClickStopPropagation class="head">
|
||||
<i (click)="goBack.emit()" data-id="Back Button" class="al-icon sm-md al-ico-back pointer m-auto" smClickStopPropagation></i>
|
||||
<h3>SELECT HYPER PARAMETERS TO DISPLAY</h3>
|
||||
</div>
|
||||
<hr style="margin: 0">
|
||||
<sm-grouped-checked-filter-list
|
||||
smClickStopPropagation
|
||||
[itemsList]="hyperParams"
|
||||
|
||||
@@ -1,25 +1,31 @@
|
||||
@import "../../../shared/ui-components/styles/variables";
|
||||
@import "variables";
|
||||
|
||||
:host {
|
||||
display: block;
|
||||
height: 640px;
|
||||
max-height: calc(100vh - 120px);
|
||||
width: 370px;
|
||||
}
|
||||
|
||||
.head {
|
||||
margin-bottom: 12px;
|
||||
padding: 12px;
|
||||
display: grid;
|
||||
grid-template-columns: 20px 1fr 20px;
|
||||
gap: 6px;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
border-bottom: 1px solid $blue-200;
|
||||
h3 {
|
||||
color: $blue-400;
|
||||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
sm-grouped-checked-filter-list {
|
||||
height: calc(100% - 52px);
|
||||
padding: 15px 0 0 15px;
|
||||
height: calc(100% - 58px);
|
||||
::ng-deep .actions {
|
||||
padding-top: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.hyper-param-header {
|
||||
color: $blue-400;
|
||||
flex-basis: 84%
|
||||
}
|
||||
|
||||
.hyper-params-container {
|
||||
padding: 15px
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
<div smClickStopPropagation class="w-100 h-100">
|
||||
<div *ngIf="goBack.observed" class="d-flex justify-content-between p-3">
|
||||
<i (click)="goBack.emit()" class="al-icon sm-md al-ico-back pointer" smClickStopPropagation></i>
|
||||
<div class="title">SELECT METRIC TO DISPLAY
|
||||
</div>
|
||||
<div smClickStopPropagation class="d-flex flex-column w-100 h-100">
|
||||
<div *ngIf="goBack.observed" class="head">
|
||||
<i (click)="goBack.emit()" data-id="Back button" class="al-icon sm-md al-ico-back pointer m-auto" smClickStopPropagation></i>
|
||||
<h3>SELECT METRIC TO DISPLAY</h3>
|
||||
</div>
|
||||
|
||||
|
||||
<sm-search
|
||||
class="underline-search"
|
||||
[value]="searchText"
|
||||
|
||||
@@ -1,9 +1,26 @@
|
||||
@import "variables";
|
||||
|
||||
:host {
|
||||
.title {
|
||||
color: $blue-400;
|
||||
flex-basis: 84%;
|
||||
|
||||
.head {
|
||||
margin-bottom: 12px;
|
||||
padding: 12px;
|
||||
display: grid;
|
||||
grid-template-columns: 20px 1fr 20px;
|
||||
gap: 6px;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
border-bottom: 1px solid $blue-200;
|
||||
h3 {
|
||||
color: $blue-400;
|
||||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
sm-search {
|
||||
margin: 0 12px;
|
||||
}
|
||||
|
||||
.variant-label {
|
||||
@@ -63,12 +80,13 @@
|
||||
}
|
||||
|
||||
.metrics {
|
||||
height: calc(100% - 32px);
|
||||
height: calc(100% - 34px);
|
||||
width: 100%;
|
||||
overflow-y: scroll;
|
||||
padding-left: 12px;
|
||||
|
||||
&.has-title {
|
||||
height: calc(100% - #{32px + 49px});
|
||||
// height: calc(100% - #{90px});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ import {ScalarKeyEnum} from '~/business-logic/model/events/scalarKeyEnum';
|
||||
import {EMPTY} from 'rxjs';
|
||||
import {selectSelectedExperiment} from '~/features/experiments/reducers';
|
||||
import {IExperimentInfo} from '~/features/experiments/shared/experiment-info.model';
|
||||
import {PlotSampleResponse} from '~/business-logic/model/events/plotSampleResponse';
|
||||
|
||||
|
||||
@Injectable()
|
||||
@@ -212,16 +213,15 @@ export class CommonExperimentOutputEffects {
|
||||
task: action.task,
|
||||
iteration: action.iteration,
|
||||
metric: action.metric,
|
||||
variant: action.variant,
|
||||
scroll_id: scrollId,
|
||||
navigate_current_metric: false
|
||||
/* eslint-enable @typescript-eslint/naming-convention */
|
||||
})
|
||||
.pipe(
|
||||
mergeMap(res => [
|
||||
mergeMap((res: PlotSampleResponse) => [
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
outputActions.setPlotIterations({min_iteration: res.min_iteration, max_iteration: res.max_iteration}),
|
||||
outputActions.setCurrentPlot({event: res.event}), deactivateLoader(action.type),
|
||||
outputActions.setCurrentPlot({event: res.events}), deactivateLoader(action.type),
|
||||
outputActions.setPlotViewerScrollId({scrollId: res.scroll_id}),
|
||||
]),
|
||||
catchError(error => [requestFailed(error), deactivateLoader(action.type)])
|
||||
@@ -237,20 +237,21 @@ export class CommonExperimentOutputEffects {
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
task: action.task,
|
||||
scroll_id: scrollId,
|
||||
navigate_earlier: action.navigateEarlier
|
||||
navigate_earlier: action.navigateEarlier,
|
||||
...(action.iteration && {next_iteration: true})
|
||||
/* eslint-enable @typescript-eslint/naming-convention */
|
||||
})
|
||||
.pipe(
|
||||
mergeMap(res => {
|
||||
if (!res.event) {
|
||||
if (res.events.length === 0) {
|
||||
return [action.navigateEarlier ? outputActions.setViewerBeginningOfTime({beginningOfTime: true}) : outputActions.setViewerEndOfTime({endOfTime: true})];
|
||||
} else {
|
||||
return [
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
outputActions.setPlotIterations({min_iteration: res.min_iteration, max_iteration: res.max_iteration}),
|
||||
outputActions.setCurrentPlot({event: res.event}), deactivateLoader(action.type),
|
||||
outputActions.setCurrentPlot({event: res.events}), deactivateLoader(action.type),
|
||||
outputActions.setPlotViewerScrollId({scrollId: res.scroll_id}),
|
||||
action.navigateEarlier ? outputActions.setViewerBeginningOfTime({beginningOfTime: false}) : outputActions.setViewerEndOfTime({endOfTime: false})
|
||||
!action.navigateEarlier ? outputActions.setViewerBeginningOfTime({beginningOfTime: false}) : outputActions.setViewerEndOfTime({endOfTime: false})
|
||||
];
|
||||
}
|
||||
}),
|
||||
|
||||
@@ -64,6 +64,7 @@ import {PIPELINE_INFO_ONLY_FIELDS} from '@common/pipelines-controller/controller
|
||||
import {TasksGetByIdExResponse} from '~/business-logic/model/tasks/tasksGetByIdExResponse';
|
||||
import {ARTIFACTS_ONLY_FIELDS} from '@common/experiments/experiment.consts';
|
||||
import {ITask} from '~/business-logic/model/al-task';
|
||||
import {getTags} from '@common/core/actions/projects.actions';
|
||||
|
||||
|
||||
@Injectable()
|
||||
@@ -344,10 +345,11 @@ export class CommonExperimentsInfoEffects {
|
||||
return [
|
||||
commonInfoActions.experimentUpdatedSuccessfully({id: action.id}),
|
||||
updateExperiment({id: action.id, changes}),
|
||||
selectedExperiment?.id === action.id ? commonInfoActions.updateExperimentInfoData({
|
||||
id: action.id,
|
||||
changes
|
||||
}) : new EmptyAction()
|
||||
...(selectedExperiment?.id === action.id ?
|
||||
[commonInfoActions.updateExperimentInfoData({ id: action.id, changes })] :
|
||||
[]
|
||||
),
|
||||
...(changes.tags ? [getTags()] : [])
|
||||
];
|
||||
}),
|
||||
catchError((err: HttpErrorResponse) => [
|
||||
|
||||
@@ -7,7 +7,7 @@ import {BlTasksService} from '~/business-logic/services/tasks.service';
|
||||
import {ApiEventsService} from '~/business-logic/api-services/events.service';
|
||||
import {Router} from '@angular/router';
|
||||
import {catchError, map, mergeMap, switchMap, tap, withLatestFrom} from 'rxjs/operators';
|
||||
import {activeLoader, addMessage, deactivateLoader, setServerError} from '../../core/actions/layout.actions';
|
||||
import {activeLoader, addMessage, deactivateLoader, neverShowPopupAgain, setServerError} from '../../core/actions/layout.actions';
|
||||
import * as menuActions from '../actions/common-experiments-menu.actions';
|
||||
import {stopClicked} from '../actions/common-experiments-menu.actions';
|
||||
import {Observable, of} from 'rxjs';
|
||||
@@ -45,6 +45,8 @@ import {get} from 'lodash/fp';
|
||||
import {TaskTypeEnum} from '~/business-logic/model/tasks/taskTypeEnum';
|
||||
import {TaskStatusEnum} from '~/business-logic/model/tasks/taskStatusEnum';
|
||||
import {TasksCloneRequest} from '~/business-logic/model/tasks/tasksCloneRequest';
|
||||
import {WelcomeMessageComponent} from '@common/layout/welcome-message/welcome-message.component';
|
||||
import {selectNeverShowPopups} from '@common/core/reducers/view.reducer';
|
||||
|
||||
export const getChildrenExperiments = (tasksApi, parents, filters?: { [key: string]: any }): Observable<Task[]> =>
|
||||
tasksApi.tasksGetAllEx({
|
||||
@@ -101,11 +103,27 @@ export class CommonExperimentsMenuEffects {
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
ids,
|
||||
queue: action.queue.id, ...((!action.queue.id) && {queue_name: action.queue.name}),
|
||||
validate_tasks: true
|
||||
validate_tasks: true,
|
||||
...( action.verifyWatchers && {verify_watched_queue: true})
|
||||
/* eslint-enable @typescript-eslint/naming-convention */
|
||||
})
|
||||
.pipe(
|
||||
mergeMap(res => this.updateExperimentsSuccess(action, MenuItems.enqueue, ids, selectedEntity, res)),
|
||||
withLatestFrom(this.store.select(selectNeverShowPopups)),
|
||||
tap(([res, neverShowAgainPopups]) => {
|
||||
if (res.queue_watched === false && !neverShowAgainPopups.includes('orphanedQueue')) {
|
||||
this.dialog.open(WelcomeMessageComponent, {
|
||||
data: {
|
||||
queue: res.queue,
|
||||
step: 2
|
||||
}
|
||||
}).afterClosed().subscribe(doNotShowAgain => {
|
||||
if (doNotShowAgain) {
|
||||
this.store.dispatch(neverShowPopupAgain({popupId: 'orphanedQueue'}));
|
||||
}
|
||||
});
|
||||
}
|
||||
}),
|
||||
mergeMap(([res]) => this.updateExperimentsSuccess(action, MenuItems.enqueue, ids, selectedEntity, res)),
|
||||
catchError(error => this.updateExperimentFailed(action.type, error))
|
||||
);
|
||||
}
|
||||
@@ -182,32 +200,26 @@ export class CommonExperimentsMenuEffects {
|
||||
|
||||
|
||||
cloneExperimentRequested$ = createEffect(() => this.actions$.pipe(
|
||||
ofType<menuActions.CloneExperimentClicked>(menuActions.CLONE_EXPERIMENT_CLICKED),
|
||||
ofType(menuActions.cloneExperimentClicked),
|
||||
withLatestFrom(this.store.select(selectTableMode)),
|
||||
switchMap(([action, tableMode]) => this.apiTasks.tasksClone({
|
||||
task: action.payload.originExperiment.id,
|
||||
switchMap(([action, ]) => this.apiTasks.tasksClone({
|
||||
task: action.originExperiment.id,
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
new_task_project: action.payload.cloneData.project,
|
||||
new_task_comment: action.payload.cloneData.comment,
|
||||
new_task_name: action.payload.cloneData.name,
|
||||
new_project_name: action.payload.cloneData.newProjectName
|
||||
new_task_project: action.cloneData.project,
|
||||
new_task_comment: action.cloneData.comment,
|
||||
new_task_name: action.cloneData.name,
|
||||
new_project_name: action.cloneData.newProjectName
|
||||
/* eslint-enable @typescript-eslint/naming-convention */
|
||||
} as TasksCloneRequest)
|
||||
.pipe(
|
||||
mergeMap(res => [
|
||||
viewActions.getExperiments(),
|
||||
viewActions.setSelectedExperiments({
|
||||
experiments: (tableMode === 'info' ? [] :
|
||||
[{id: res?.id}
|
||||
])
|
||||
}),
|
||||
viewActions.experimentSelectionChanged({
|
||||
experiment: tableMode === 'info'? {id: res.id}: null ,
|
||||
project: action.payload.cloneData.project ? action.payload.cloneData.project : res?.new_project?.id
|
||||
}),
|
||||
deactivateLoader(action.type),
|
||||
...action.payload.cloneData.newProjectName ? [getAllSystemProjects()] : [],
|
||||
]),
|
||||
mergeMap(res => {
|
||||
this.router.navigate(['projects', action.cloneData.project, 'experiments', res.id]);
|
||||
return [
|
||||
viewActions.getExperiments(),
|
||||
deactivateLoader(action.type),
|
||||
...action.cloneData.newProjectName ? [getAllSystemProjects()] : [],
|
||||
];
|
||||
}),
|
||||
catchError(error => [
|
||||
deactivateLoader(action.type),
|
||||
setServerError(error, null, 'Clone Experiment failed'),
|
||||
|
||||
@@ -176,7 +176,7 @@ export class CommonExperimentsViewEffects {
|
||||
|
||||
lockRefresh = false;
|
||||
refreshExperiments = createEffect(() => this.actions$.pipe(
|
||||
ofType<ReturnType<typeof exActions.refreshExperiments>>(exActions.refreshExperiments),
|
||||
ofType(exActions.refreshExperiments),
|
||||
filter(() => !this.lockRefresh),
|
||||
withLatestFrom(
|
||||
this.store.select(exSelectors.selectCurrentScrollId),
|
||||
@@ -232,7 +232,7 @@ export class CommonExperimentsViewEffects {
|
||||
return [
|
||||
requestFailed(error),
|
||||
deactivateLoader(action.type),
|
||||
addMessage('warn', 'Fetch Experiments failed', error?.meta && [{name: 'More info', actions: [setServerError(error, null, 'Fetch Experiments failed')]}])
|
||||
...(action.autoRefresh ? [] : [addMessage('warn', 'Fetch Experiments failed', error?.meta && [{name: 'More info', actions: [setServerError(error, null, 'Fetch Experiments failed')]}])])
|
||||
];
|
||||
})
|
||||
);
|
||||
@@ -281,7 +281,8 @@ export class CommonExperimentsViewEffects {
|
||||
experimentSelectionChanged = createEffect(() => this.actions$.pipe(
|
||||
ofType(exActions.experimentSelectionChanged),
|
||||
withLatestFrom(this.store.select(selectRouterConfig)),
|
||||
tap(([action, routeConfig]) => this.navigateAfterExperimentSelectionChanged(action.experiment as ITableExperiment, action.project, routeConfig)),
|
||||
tap(([action, routeConfig]) =>
|
||||
this.navigateAfterExperimentSelectionChanged(action.experiment as ITableExperiment, action.project, routeConfig, action.replaceURL)),
|
||||
mergeMap(() => [exActions.setTableMode({mode: 'info'})])
|
||||
));
|
||||
|
||||
@@ -518,7 +519,7 @@ export class CommonExperimentsViewEffects {
|
||||
})
|
||||
));
|
||||
|
||||
navigateAfterExperimentSelectionChanged(selectedExperiment: ITableExperiment, experimentProject: string, routeConfig: string[]) {
|
||||
navigateAfterExperimentSelectionChanged(selectedExperiment: ITableExperiment, experimentProject: string, routeConfig: string[], replaceUrl=false) {
|
||||
const module = routeConfig.includes('datasets') ? 'datasets/simple' : routeConfig.includes('pipelines') ? 'pipelines' : 'projects';
|
||||
// wow angular really suck...
|
||||
const activeChild = get('firstChild.firstChild.firstChild.firstChild.firstChild.firstChild', this.route);
|
||||
@@ -528,7 +529,7 @@ export class CommonExperimentsViewEffects {
|
||||
[module, experimentProject, 'experiments', selectedExperiment.id].concat(activeChild ? activeChildUrl.split('/') : []),
|
||||
{queryParamsHandling: 'preserve'}
|
||||
) :
|
||||
this.router.navigate([module, experimentProject, 'experiments'], {queryParamsHandling: 'preserve'});
|
||||
this.router.navigate([module, experimentProject, 'experiments'], {queryParamsHandling: 'preserve', replaceUrl});
|
||||
}
|
||||
|
||||
getGetAllQuery({
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
<button
|
||||
class="btn btn-cml-primary d-flex justify-content-between align-items-center mr-3"
|
||||
[disabled]="isArchived$ | async"
|
||||
data-id="New Experiment"
|
||||
(click)="newExperiment()"
|
||||
[smTooltip]="isSmallScreen ? 'NEW EXPERIMENT' : ''"
|
||||
>
|
||||
|
||||
@@ -141,9 +141,9 @@ export class ExperimentsComponent extends BaseEntityPageComponent implements OnI
|
||||
protected route: ActivatedRoute,
|
||||
protected router: Router,
|
||||
protected dialog: MatDialog,
|
||||
protected refresh: RefreshService
|
||||
protected refresh: RefreshService,
|
||||
) {
|
||||
super(store, route, router, dialog, refresh);
|
||||
super(store, route, router, dialog, refresh, syncSelector);
|
||||
this.selectSplitSize$ = this.store.select(selectSplitSize);
|
||||
this.isPipeline$ = this.store.select(selectIsPipelines);
|
||||
this.tableSortFields$ = this.store.select(selectTableSortFields).pipe(tap(field => this.sortFields = field));
|
||||
@@ -352,7 +352,7 @@ export class ExperimentsComponent extends BaseEntityPageComponent implements OnI
|
||||
this.compareExperiments();
|
||||
break;
|
||||
case MenuItems.archive:
|
||||
this.contextMenu.restoreArchive();
|
||||
this.contextMenu.restoreArchive(item.entitiesType);
|
||||
break;
|
||||
case MenuItems.reset:
|
||||
this.contextMenu.resetPopup();
|
||||
|
||||
@@ -11,10 +11,10 @@
|
||||
</ng-template>
|
||||
<div class="buttons">
|
||||
<button (click)="closeDialog(true)" [disabled]="!(shouldBeAbortedTasks?.length>0)"
|
||||
class="btn btn-neon yes-button">
|
||||
class="btn btn-neon yes-button" data-id ="AbortButton">
|
||||
ABORT
|
||||
</button>
|
||||
<button (click)="closeDialog(false)" class="btn btn-outline-neon">
|
||||
<button (click)="closeDialog(false)" class="btn btn-outline-neon" data-id ="CancelButton">
|
||||
CANCEL
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -56,10 +56,10 @@
|
||||
</ng-form>
|
||||
<div class="buttons">
|
||||
<button [disabled]="moveToForm.invalid" (click)="closeDialog(true)" cdkFocusInitial
|
||||
class="btn btn-neon yes-button" #moveButton>
|
||||
class="btn btn-neon yes-button" data-id="MoveButton" #moveButton>
|
||||
MOVE
|
||||
</button>
|
||||
<button (click)="closeDialog(false)" class="btn btn-outline-neon">
|
||||
<button (click)="closeDialog(false)" class="btn btn-outline-neon" data-id ="CancelButton">
|
||||
CANCEL
|
||||
</button>
|
||||
|
||||
|
||||
@@ -82,10 +82,10 @@
|
||||
|
||||
<div class="buttons">
|
||||
<button cdkFocusInitial (click)="closeDialog(true)" [disabled]="!cloneForm.valid"
|
||||
class="btn btn-neon yes-button" #cloneButton>
|
||||
class="btn btn-neon yes-button" data-id="CloneButton" #cloneButton>
|
||||
{{extend ? 'EXTEND' : 'CLONE'}}
|
||||
</button>
|
||||
<button (click)="closeDialog(false)" class="btn btn-outline-neon">
|
||||
<button (click)="closeDialog(false)" class="btn btn-outline-neon" data-id ="CancelButton">
|
||||
CANCEL
|
||||
</button>
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog';
|
||||
import {Project} from '../../../../../business-logic/model/projects/project';
|
||||
import {Project} from '~/business-logic/model/projects/project';
|
||||
import {Component, ElementRef, Inject, OnDestroy, OnInit, ViewChild} from '@angular/core';
|
||||
import {Store} from '@ngrx/store';
|
||||
import {NgForm} from '@angular/forms';
|
||||
import {Observable, Subscription} from 'rxjs';
|
||||
import {selectRootProjects} from '../../../../core/reducers/projects.reducer';
|
||||
import {getAllSystemProjects} from '../../../../core/actions/projects.actions';
|
||||
import {selectRootProjects} from '@common/core/reducers/projects.reducer';
|
||||
import {getAllSystemProjects} from '@common/core/actions/projects.actions';
|
||||
import {map} from 'rxjs/operators';
|
||||
import {isReadOnly} from '../../../../shared/utils/shared-utils';
|
||||
import {isReadOnly} from '@common/shared/utils/shared-utils';
|
||||
import {CloneForm} from '../../common-experiment-model.model';
|
||||
import {isEqual} from 'lodash/fp';
|
||||
|
||||
@@ -18,7 +18,6 @@ import {isEqual} from 'lodash/fp';
|
||||
})
|
||||
export class CloneDialogComponent implements OnInit, OnDestroy {
|
||||
|
||||
CLONE_NAME_PREFIX;
|
||||
public reference: string;
|
||||
public header: string;
|
||||
public type: string;
|
||||
@@ -28,10 +27,11 @@ export class CloneDialogComponent implements OnInit, OnDestroy {
|
||||
name: null,
|
||||
comment: null
|
||||
} as CloneForm;
|
||||
public projects: { label: string; value: string }[];
|
||||
|
||||
private readonly defaultProjectId: string;
|
||||
private projectsSub: Subscription;
|
||||
public projects: { label: string; value: string }[];
|
||||
private readonly cloneNamePrefix: string;
|
||||
|
||||
@ViewChild('cloneForm', {static: true}) cloneForm: NgForm;
|
||||
@ViewChild('cloneButton', {static: true}) cloneButton: ElementRef;
|
||||
@@ -54,20 +54,20 @@ export class CloneDialogComponent implements OnInit, OnDestroy {
|
||||
public dialogRef: MatDialogRef<CloneDialogComponent>
|
||||
) {
|
||||
this.readOnlyProjects$ = this.store.select(selectRootProjects)
|
||||
.pipe(map(projects => projects.filter(project => isReadOnly(project)).map(project => project.name)));
|
||||
.pipe(map(projects => projects?.filter(project => isReadOnly(project)).map(project => project.name)));
|
||||
this.projects$ = this.store.select(selectRootProjects)
|
||||
.pipe(map(projects => projects.filter(project => !isReadOnly(project))));
|
||||
.pipe(map(projects => projects?.filter(project => !isReadOnly(project))));
|
||||
this.defaultProjectId = data.defaultProject;
|
||||
this.header = `${data.extend ? 'Extend' : 'Clone'} ${data.type}`;
|
||||
this.CLONE_NAME_PREFIX = data.extend ? '' : 'Clone Of ';
|
||||
this.cloneNamePrefix = data.extend ? '' : 'Clone Of ';
|
||||
this.type = data.type.toLowerCase();
|
||||
this.reference = data.defaultName;
|
||||
this.extend = data.extend;
|
||||
this.formData.name = this.CLONE_NAME_PREFIX;
|
||||
this.formData.name = this.cloneNamePrefix;
|
||||
setTimeout(() => {
|
||||
this.formData = {
|
||||
...this.formData,
|
||||
name: this.extend ? '' : this.CLONE_NAME_PREFIX + data.defaultName,
|
||||
name: this.extend ? '' : this.cloneNamePrefix + data.defaultName,
|
||||
comment: data.defaultComment || '',
|
||||
};
|
||||
});
|
||||
@@ -81,7 +81,7 @@ export class CloneDialogComponent implements OnInit, OnDestroy {
|
||||
ngOnInit(): void {
|
||||
this.store.dispatch(getAllSystemProjects());
|
||||
this.projectsSub = this.projects$.subscribe(projects => {
|
||||
const projectList = projects.map(project => ({value: project.id, label: project.name}));
|
||||
const projectList = projects?.map(project => ({value: project.id, label: project.name}));
|
||||
if (!isEqual(projectList, this.projects)) {
|
||||
this.projects = projectList;
|
||||
const defaultProject = this.projects.find(project => project.value === this.defaultProjectId);
|
||||
|
||||
@@ -9,26 +9,26 @@
|
||||
</div>
|
||||
<mat-menu #experimentMenu="matMenu" [hasBackdrop]="backdrop" classList="light-theme">
|
||||
<ng-container *ngIf="selectedDisableAvailable[menuItems.queue]">
|
||||
<button *ngIf="tableMode" mat-menu-item (click)="toggleDetails()">
|
||||
<i [class]="'al-icon '+ ICONS.DETAILS + ' sm-md'"></i>Details
|
||||
<button *ngIf="tableMode" mat-menu-item (click)="toggleDetails()" data-id="Details Option">
|
||||
<i [class]="'al-icon '+ icons.DETAILS + ' sm-md'"></i>Details
|
||||
</button>
|
||||
|
||||
<button mat-menu-item (click)="toggleFullScreen(minimizedView)" [disabled]="isSharedAndNotOwner">
|
||||
<i [class]="'al-icon '+ ICONS.CHART + ' sm-md'"></i>
|
||||
<button mat-menu-item (click)="toggleFullScreen(minimizedView)" [disabled]="isSharedAndNotOwner" data-id="View Full Screen Option">
|
||||
<i [class]="'al-icon '+ icons.CHART + ' sm-md'"></i>
|
||||
{{minimizedView ? 'View Full Screen' : 'View in Experiment Table'}}
|
||||
</button>
|
||||
|
||||
<hr>
|
||||
|
||||
<button mat-menu-item (click)="manageQueueClicked()"
|
||||
[disabled]="selectedDisableAvailable[menuItems.queue].disable">
|
||||
<i [class]="'al-icon '+ ICONS.QUEUED + ' sm-md'"></i>
|
||||
[disabled]="selectedDisableAvailable[menuItems.queue].disable" data-id="Manage Queue Option">
|
||||
<i [class]="'al-icon '+ icons.QUEUED + ' sm-md'"></i>
|
||||
{{selectedDisableAvailable[menuItems.queue]?.available | menuItemText : 'Manage Queue' : selectedDisableAvailableIsMultiple}}
|
||||
</button>
|
||||
|
||||
<button mat-menu-item (click)="viewWorkerClicked()"
|
||||
[disabled]="selectedDisableAvailable[menuItems.viewWorker].disable">
|
||||
<i [class]="'al-icon '+ ICONS.WORKER + ' sm-md'"></i>
|
||||
[disabled]="selectedDisableAvailable[menuItems.viewWorker].disable" data-id="View Worker Option">
|
||||
<i [class]="'al-icon '+ icons.WORKER + ' sm-md'"></i>
|
||||
{{selectedDisableAvailable[menuItems.viewWorker]?.available | menuItemText : 'View Worker' : selectedDisableAvailableIsMultiple}}
|
||||
</button>
|
||||
|
||||
@@ -36,72 +36,72 @@
|
||||
|
||||
<button mat-menu-item (click)="shareExperimentPopup()" *ngIf="isCommunity"
|
||||
[disabled]="isExample || numSelected > 1 || isArchive">
|
||||
<i [class]="'al-icon ' + ICONS.SHARE + ' sm-md'"></i>Share
|
||||
<i [class]="'al-icon ' + icons.SHARE + ' sm-md'"></i>Share
|
||||
</button>
|
||||
|
||||
<button mat-menu-item (click)="deleteExperimentPopup()"
|
||||
[disabled]="selectedDisableAvailable[menuItems.delete].disable" *ngIf="isArchive">
|
||||
<i [class]="'al-icon ' + ICONS.REMOVE + ' sm-md'"></i>
|
||||
[disabled]="selectedDisableAvailable[menuItems.delete].disable" *ngIf="isArchive" data-id="Delete Option">
|
||||
<i [class]="'al-icon ' + icons.REMOVE + ' sm-md'"></i>
|
||||
{{selectedDisableAvailable[menuItems.delete].available | menuItemText : 'Delete' : selectedDisableAvailableIsMultiple}}
|
||||
</button>
|
||||
|
||||
<button mat-menu-item (click)="restoreArchive()"
|
||||
<button mat-menu-item (click)="restoreArchive()" data-id="Archive Option"
|
||||
[disabled]="selectedDisableAvailable[menuItems.archive].disable">
|
||||
<i class="al-icon sm-md" [class]="isArchive ? ICONS.RESTORE : ICONS.ARCHIVE"></i>
|
||||
<i class="al-icon sm-md" [class]="isArchive ? icons.RESTORE : icons.ARCHIVE"></i>
|
||||
{{selectedDisableAvailable[menuItems.archive].available | menuItemText : isArchive ? 'Restore from Archive' : 'Archive' : selectedDisableAvailableIsMultiple}}
|
||||
</button>
|
||||
|
||||
<button mat-menu-item (click)="enqueuePopup()"
|
||||
<button mat-menu-item (click)="enqueuePopup()" data-id="Enqueue Option"
|
||||
*ngIf="!selectedDisableAvailable[menuItems.enqueue].disable && !isArchive"
|
||||
[disabled]="selectedDisableAvailable[menuItems.enqueue].disable">
|
||||
<i [class]="'al-icon ' + ICONS.ENQUEUE + ' sm-md'"></i>
|
||||
<i [class]="'al-icon ' + icons.ENQUEUE + ' sm-md'"></i>
|
||||
{{selectedDisableAvailable[menuItems.enqueue]?.available | menuItemText : 'Enqueue' : selectedDisableAvailableIsMultiple}}
|
||||
</button>
|
||||
|
||||
<button mat-menu-item (click)="dequeuePopup()"
|
||||
<button mat-menu-item (click)="dequeuePopup()" data-id="Dequeue Option"
|
||||
*ngIf="!selectedDisableAvailable[menuItems.dequeue].disable"
|
||||
[disabled]="selectedDisableAvailable[menuItems.dequeue]?.disable">
|
||||
<i [class]="'al-icon ' + ICONS.DEQUEUE + ' sm-md'"></i>
|
||||
<i [class]="'al-icon ' + icons.DEQUEUE + ' sm-md'"></i>
|
||||
{{selectedDisableAvailable[menuItems.dequeue]?.available | menuItemText : 'Dequeue' : selectedDisableAvailableIsMultiple}}
|
||||
</button>
|
||||
|
||||
<button mat-menu-item (click)="resetPopup()" [disabled]="selectedDisableAvailable[menuItems.reset].disable">
|
||||
<i [class]="'al-icon ' + ICONS.RESET + ' sm-md'"></i>
|
||||
<button mat-menu-item (click)="resetPopup()" data-id="Reset Option" [disabled]="selectedDisableAvailable[menuItems.reset].disable">
|
||||
<i [class]="'al-icon ' + icons.RESET + ' sm-md'"></i>
|
||||
{{selectedDisableAvailable[menuItems.reset].available | menuItemText : 'Reset' : selectedDisableAvailableIsMultiple}}
|
||||
</button>
|
||||
|
||||
<button mat-menu-item (click)="stopPopup()" [disabled]="selectedDisableAvailable[menuItems.abort].disable">
|
||||
<i [class]="'al-icon ' + ICONS.STOPPED + ' sm-md'"></i>
|
||||
<button mat-menu-item (click)="stopPopup()" data-id="Abort Option" [disabled]="selectedDisableAvailable[menuItems.abort].disable">
|
||||
<i [class]="'al-icon ' + icons.STOPPED + ' sm-md'"></i>
|
||||
{{selectedDisableAvailable[menuItems.abort].available | menuItemText : 'Abort' : selectedDisableAvailableIsMultiple }}
|
||||
</button>
|
||||
|
||||
<button mat-menu-item (click)="stopAllChildrenPopup()" *ngIf="!selectedDisableAvailable[menuItems.abortAllChildren]?.disable">
|
||||
<i [class]="'al-icon ' + ICONS.STOPPED_ALL + ' sm-md'"></i>
|
||||
<i [class]="'al-icon ' + icons.STOPPED_ALL + ' sm-md'"></i>
|
||||
{{selectedDisableAvailable[menuItems.abortAllChildren]?.available | menuItemText : 'Abort All Children' : selectedDisableAvailableIsMultiple }}
|
||||
</button>
|
||||
<button
|
||||
mat-menu-item
|
||||
(click)="publishPopup()"
|
||||
(click)="publishPopup()" data-id="Publish Option"
|
||||
[disabled]="selectedDisableAvailable[menuItems.publish].disable">
|
||||
<i [class]="'al-icon ' + ICONS.PUBLISHED + ' sm-md'"></i>
|
||||
<i [class]="'al-icon ' + icons.PUBLISHED + ' sm-md'"></i>
|
||||
{{selectedDisableAvailable[menuItems.publish].available | menuItemText : 'Publish' : selectedDisableAvailableIsMultiple }}
|
||||
</button>
|
||||
<hr>
|
||||
<button mat-menu-item
|
||||
[matMenuTriggerFor]="tagMenu"
|
||||
[matMenuTriggerFor]="tagMenu" data-id="Add Tag Option"
|
||||
[disabled]="selectedDisableAvailable[menuItems.tags]?.disable"
|
||||
(menuOpened)="tagMenuOpened()"
|
||||
(menuClosed)="tagMenuClosed()">
|
||||
<i [class]="'al-icon ' + ICONS.TAG + ' sm-md'">
|
||||
<i [class]="'al-icon ' + icons.TAG + ' sm-md'">
|
||||
</i><span>{{selectedDisableAvailable[menuItems.tags]?.available | menuItemText : 'Add Tag' : selectedDisableAvailableIsMultiple }}</span>
|
||||
</button>
|
||||
<hr>
|
||||
<button mat-menu-item (click)="clonePopup()">
|
||||
<i [class]="'al-icon ' + ICONS.CLONE + ' sm-md'"></i>Clone
|
||||
<button mat-menu-item (click)="clonePopup()" data-id="Clone Option">
|
||||
<i [class]="'al-icon ' + icons.CLONE + ' sm-md'"></i>Clone
|
||||
</button>
|
||||
<button mat-menu-item (click)="moveToProjectPopup()"
|
||||
<button mat-menu-item (click)="moveToProjectPopup()" data-id="Move To Project Option"
|
||||
[disabled]="selectedDisableAvailable[menuItems.moveTo].disable">
|
||||
<i [class]="'al-icon ' + ICONS.MOVE_TO + ' sm-md'"></i>
|
||||
<i [class]="'al-icon ' + icons.MOVE_TO + ' sm-md'"></i>
|
||||
{{selectedDisableAvailable[menuItems.moveTo].available | menuItemText : 'Move to Project' : selectedDisableAvailableIsMultiple}}
|
||||
</button>
|
||||
<ng-content select="[extended]"></ng-content>
|
||||
|
||||
@@ -2,7 +2,7 @@ import {MatDialog, MatDialogRef} from '@angular/material/dialog';
|
||||
import {ActivatedRoute, Router} from '@angular/router';
|
||||
import {Store} from '@ngrx/store';
|
||||
import {get} from 'lodash/fp';
|
||||
import {filter, take, withLatestFrom} from 'rxjs/operators';
|
||||
import {filter, take} from 'rxjs/operators';
|
||||
import {ICONS} from '@common/constants';
|
||||
import {Queue} from '~/business-logic/model/queues/queue';
|
||||
import {TaskStatusEnum} from '~/business-logic/model/tasks/taskStatusEnum';
|
||||
@@ -42,9 +42,7 @@ import {
|
||||
selectionDisabledPublishExperiments,
|
||||
selectionDisabledReset
|
||||
} from '@common/shared/entity-page/items.utils';
|
||||
import {WelcomeMessageComponent} from '@common/layout/welcome-message/welcome-message.component';
|
||||
import {resetOutput} from '@common/experiments/actions/common-experiment-output.actions';
|
||||
import {updateManyExperiment} from '../../../actions/common-experiments-view.actions';
|
||||
|
||||
|
||||
@Component({
|
||||
@@ -53,16 +51,18 @@ import {updateManyExperiment} from '../../../actions/common-experiments-view.act
|
||||
styleUrls: ['./experiment-menu.component.scss']
|
||||
})
|
||||
export class ExperimentMenuComponent extends BaseContextMenuComponent implements OnInit {
|
||||
readonly ICONS = ICONS;
|
||||
readonly TaskStatusEnum = TaskStatusEnum;
|
||||
readonly TaskTypeEnum = TaskTypeEnum;
|
||||
readonly icons = ICONS;
|
||||
readonly taskStatusEnum = TaskStatusEnum;
|
||||
readonly taskTypeEnum = TaskTypeEnum;
|
||||
|
||||
public open: boolean;
|
||||
public isExample: boolean;
|
||||
public isArchive: boolean;
|
||||
public selectionHasExamples: boolean;
|
||||
public isCommunity: boolean;
|
||||
protected _experiment: ISelectedExperiment = null;
|
||||
private _selectedExperiments: ISelectedExperiment[];
|
||||
|
||||
@Input() selectedExperiment: any;
|
||||
@Input() isSharedAndNotOwner = false;
|
||||
@Input() tagsFilterByProject: boolean;
|
||||
@@ -77,8 +77,10 @@ export class ExperimentMenuComponent extends BaseContextMenuComponent implements
|
||||
this.isArchive = experiment?.system_tags?.includes('archived');
|
||||
}
|
||||
|
||||
get experiment() {
|
||||
return this._experiment;
|
||||
}
|
||||
|
||||
@Output() tagSelected = new EventEmitter<string>();
|
||||
@Input() neverShowPopups;
|
||||
@Input() minimizedView: boolean;
|
||||
|
||||
@@ -90,12 +92,7 @@ export class ExperimentMenuComponent extends BaseContextMenuComponent implements
|
||||
get selectedExperiments(): ISelectedExperiment[] {
|
||||
return this._selectedExperiments;
|
||||
}
|
||||
|
||||
get experiment() {
|
||||
return this._experiment;
|
||||
}
|
||||
|
||||
public isCommunity: boolean;
|
||||
@Output() tagSelected = new EventEmitter<string>();
|
||||
|
||||
constructor(
|
||||
protected blTaskService: BlTasksService,
|
||||
@@ -125,7 +122,7 @@ export class ExperimentMenuComponent extends BaseContextMenuComponent implements
|
||||
const showShareWarningDialog = selectedExperiments.find(item => item?.system_tags.includes('shared')) &&
|
||||
!this.syncSelector.selectSync(selectNeverShowPopups)?.includes('archive-shared-task');
|
||||
if (showShareWarningDialog) {
|
||||
this.showConfirmArchiveExperiments(this.store, this.dialog, selectedExperiments);
|
||||
this.showConfirmArchiveExperiments(this.store, this.dialog, selectedExperiments, entityType);
|
||||
} else {
|
||||
this.store.dispatch(commonMenuActions.archiveSelectedExperiments({selectedEntities: selectedExperiments, entityType}));
|
||||
}
|
||||
@@ -154,23 +151,10 @@ export class ExperimentMenuComponent extends BaseContextMenuComponent implements
|
||||
data: {taskIds: selectedExperiments.map(exp => exp.id), reference: selectedExperiments[0].name}
|
||||
});
|
||||
|
||||
selectQueueDialog.afterClosed().pipe(withLatestFrom(this.store.select(selectNeverShowPopups))).subscribe(([res, neverShowAgainPopups]) => {
|
||||
selectQueueDialog.afterClosed().subscribe(res => {
|
||||
if (res && res.confirmed) {
|
||||
this.enqueueExperiment(res.queue, selectedExperiments);
|
||||
this.blTaskService.setPreviouslyUsedQueue(res.queue);
|
||||
if (((!res.queue.workers) || res.queue.workers.length === 0) && (!neverShowAgainPopups.includes('orphanedQueue'))) {
|
||||
const orphanedQueueDialog: MatDialogRef<WelcomeMessageComponent> = this.dialog.open(WelcomeMessageComponent, {
|
||||
data: {
|
||||
queue: res.queue,
|
||||
step: 2
|
||||
}
|
||||
});
|
||||
orphanedQueueDialog.afterClosed().subscribe((doNotShowAgain) => {
|
||||
if (doNotShowAgain) {
|
||||
this.store.dispatch(neverShowPopupAgain({popupId: 'orphanedQueue'}));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -205,7 +189,7 @@ export class ExperimentMenuComponent extends BaseContextMenuComponent implements
|
||||
}
|
||||
|
||||
private enqueueExperiment(queue, selectedExperiments) {
|
||||
this.store.dispatch(commonMenuActions.enqueueClicked({selectedEntities: selectedExperiments, queue}));
|
||||
this.store.dispatch(commonMenuActions.enqueueClicked({selectedEntities: selectedExperiments, queue, verifyWatchers: true}));
|
||||
}
|
||||
|
||||
private dequeueExperiment(selectedExperiments) {
|
||||
@@ -358,7 +342,7 @@ export class ExperimentMenuComponent extends BaseContextMenuComponent implements
|
||||
}
|
||||
|
||||
cloneExperiment(cloneData) {
|
||||
this.store.dispatch(new commonMenuActions.CloneExperimentClicked({
|
||||
this.store.dispatch(commonMenuActions.cloneExperimentClicked({
|
||||
originExperiment: this._experiment,
|
||||
cloneData: {
|
||||
...cloneData,
|
||||
@@ -395,7 +379,7 @@ export class ExperimentMenuComponent extends BaseContextMenuComponent implements
|
||||
});
|
||||
}
|
||||
|
||||
showConfirmArchiveExperiments(store: Store, dialog: MatDialog, selectedExperiments: ISelectedExperiment[]): void {
|
||||
showConfirmArchiveExperiments(store: Store, dialog: MatDialog, selectedExperiments: ISelectedExperiment[], entityType: EntityTypeEnum): void {
|
||||
const confirmDialogRef = dialog.open(ConfirmDialogComponent, {
|
||||
data: {
|
||||
title: 'ARCHIVE A PUBLICLY SHARED TASK',
|
||||
@@ -409,7 +393,7 @@ export class ExperimentMenuComponent extends BaseContextMenuComponent implements
|
||||
});
|
||||
confirmDialogRef.afterClosed().subscribe((confirmed) => {
|
||||
if (confirmed) {
|
||||
store.dispatch(archiveSelectedExperiments({selectedEntities: selectedExperiments}));
|
||||
store.dispatch(archiveSelectedExperiments({selectedEntities: selectedExperiments, entityType}));
|
||||
if (confirmed.neverShowAgain) {
|
||||
store.dispatch(neverShowPopupAgain({popupId: 'archive-shared-task'}));
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
::ng-deep .ui-state-highlight{
|
||||
sm-experiment-status-icon-label, sm-experiment-type-icon-label {
|
||||
.published, .created, .in_progress, .queued, .failed, .stopped, .training, .testing, .completed, .aborted{
|
||||
color: $almost-white;
|
||||
color: $blue-50;
|
||||
filter: brightness(0) invert(1);
|
||||
}
|
||||
}
|
||||
@@ -68,7 +68,7 @@
|
||||
::ng-deep .selected {
|
||||
sm-experiment-status-icon-label, sm-experiment-type-icon-label {
|
||||
.published, .created, .in_progress, .queued, .failed, .stopped, .training, .testing, .completed, .aborted{
|
||||
color: $almost-white;
|
||||
color: $blue-50;
|
||||
filter: brightness(0) invert(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,13 +13,16 @@
|
||||
class="thin short"
|
||||
floatLabel="always">
|
||||
<mat-label class="field-label">Queue</mat-label>
|
||||
<input type="text"
|
||||
#text
|
||||
tabindex="0"
|
||||
matInput
|
||||
smRequiredAutocompleteSelectionValidator
|
||||
[formControl]="queueControl"
|
||||
[matAutocomplete]="auto">
|
||||
<input
|
||||
type="text"
|
||||
#text
|
||||
data-id="Select Queue"
|
||||
tabindex="0"
|
||||
matInput
|
||||
smRequiredAutocompleteSelectionValidator
|
||||
[formControl]="queueControl"
|
||||
[matAutocomplete]="auto"
|
||||
>
|
||||
<mat-autocomplete
|
||||
class="light-theme"
|
||||
[displayWith]="displayFn"
|
||||
@@ -27,11 +30,11 @@
|
||||
>
|
||||
<mat-option
|
||||
class="item"
|
||||
*ngIf="(userAllowedToCreateQueue$ | async) &&(queueControl.value && !(displayFn(queueControl.value) | stringIncludedInArray:queuesNames))"
|
||||
*ngIf="(userAllowedToCreateQueue$ | async) && queueControl.value && !(displayFn(queueControl.value) | stringIncludedInArray: queuesNames)"
|
||||
[value]="{name:queueControl.value}"
|
||||
>"{{displayFn(queueControl.value)}}"<span class="new">(Create New)</span></mat-option>
|
||||
<mat-option
|
||||
*ngFor="let option of filteredOptions | async; trackBy: trackById"
|
||||
*ngFor="let option of filteredOptions$ | async; trackBy: trackById"
|
||||
[value]="option"
|
||||
[smTooltip]="option.name" smShowTooltipIfEllipsis
|
||||
>
|
||||
@@ -48,10 +51,10 @@
|
||||
|
||||
</form>
|
||||
<div class="buttons">
|
||||
<button (click)="closeDialog(false)" class="btn btn-outline-neon">
|
||||
<button (click)="closeDialog(false)" class="btn btn-outline-neon" data-id ="CancelButton">
|
||||
CANCEL
|
||||
</button>
|
||||
<button (click)="closeDialog(true)" class="btn btn-neon yes-button" [disabled]="!queueControl.valid">
|
||||
<button (click)="closeDialog(true)" class="btn btn-neon yes-button" [disabled]="!queueControl.valid" data-id="EnqueueButton">
|
||||
ENQUEUE
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
p {
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
color: $dusk-two;
|
||||
color: $blue-450;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import {Queue} from '~/business-logic/model/queues/queue';
|
||||
import {ConfirmDialogComponent} from '@common/shared/ui-components/overlay/confirm-dialog/confirm-dialog.component';
|
||||
import {BlTasksService} from '~/business-logic/services/tasks.service';
|
||||
import {filter, map, startWith} from 'rxjs/operators';
|
||||
import {Observable, Subscription} from 'rxjs';
|
||||
import {combineLatest, Observable, Subscription} from 'rxjs';
|
||||
import {userAllowedToCreateQueue$} from '~/core/reducers/users.reducer';
|
||||
import {trackById} from '@common/shared/utils/forms-track-by';
|
||||
import {FormControl} from '@angular/forms';
|
||||
@@ -34,7 +34,8 @@ export class SelectQueueComponent implements OnInit, OnDestroy {
|
||||
split = splitLine;
|
||||
displayFn = (item: any): string => typeof item === 'string' ? item : item?.name;
|
||||
trackById = trackById;
|
||||
public filteredOptions: Observable<Queue[]>;
|
||||
public filteredOptions$: Observable<Queue[]>;
|
||||
defaultQueue: Queue;
|
||||
|
||||
constructor(
|
||||
public dialogRef: MatDialogRef<ConfirmDialogComponent>,
|
||||
@@ -56,8 +57,8 @@ export class SelectQueueComponent implements OnInit, OnDestroy {
|
||||
if (queues) {
|
||||
this.queues = queues;
|
||||
this.queuesNames = queues.map(q => q.name);
|
||||
const selectedQueue = this.blTaskService.getDefaultQueue(this.queues) || queues[0];
|
||||
this.queueControl.setValue(selectedQueue, {emitEvent: false});
|
||||
this.defaultQueue = this.blTaskService.getDefaultQueue(this.queues) || queues[0];
|
||||
this.queueControl.reset(this.defaultQueue, {emitEvent: false});
|
||||
this.cdr.detectChanges();
|
||||
}
|
||||
});
|
||||
@@ -65,16 +66,22 @@ export class SelectQueueComponent implements OnInit, OnDestroy {
|
||||
|
||||
ngOnInit() {
|
||||
this.store.dispatch(new GetQueuesForEnqueue());
|
||||
this.filteredOptions = this.queueControl.valueChanges.pipe(
|
||||
startWith(''),
|
||||
map(value => {
|
||||
if (!this.queues) {
|
||||
return [];
|
||||
}
|
||||
const name = (typeof value === 'string' ? value : value?.name).toLowerCase();
|
||||
return name ? this.queues.filter(q => q.name.toLowerCase().includes(name)) : this.queues.slice();
|
||||
}),
|
||||
);
|
||||
this.filteredOptions$ = combineLatest([
|
||||
this.queueControl.valueChanges.pipe(startWith('')),
|
||||
this.queues$
|
||||
])
|
||||
.pipe(
|
||||
map(([value, queues]) => {
|
||||
if (!queues) {
|
||||
return [];
|
||||
}
|
||||
const name = (typeof value === 'string' ? value : value?.name).toLowerCase();
|
||||
if (this.queueControl.pristine || !name) {
|
||||
return queues;
|
||||
}
|
||||
return queues.filter(q => q.name.toLowerCase().includes(name));
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
closeDialog(confirmed) {
|
||||
|
||||
@@ -70,9 +70,7 @@ export const prepareNames = (data: IBreadcrumbs, customProject?: boolean, fullSc
|
||||
const project = prepareLinkData(data.project, true);
|
||||
if (data.project) {
|
||||
let subProjectsNames = [data.project?.name];
|
||||
if (!customProject) {
|
||||
subProjectsNames = data.project?.name?.split('/');
|
||||
}
|
||||
subProjectsNames = data.project?.name?.split('/').filter(name=> !['.datasets', '.pipelines'].includes(name));
|
||||
const allProjects = [
|
||||
...(data.projects || []),
|
||||
{id: '*', name: 'All Experiments'},
|
||||
@@ -81,13 +79,14 @@ export const prepareNames = (data: IBreadcrumbs, customProject?: boolean, fullSc
|
||||
let currentName = '';
|
||||
const subProjects = subProjectsNames.map(name => {
|
||||
currentName += currentName ? ('/' + name) : name;
|
||||
return allProjects.find(proj => currentName === proj.name);
|
||||
return allProjects.find(proj => currentName === proj.name.replace('/.datasets', '').replace('/.pipelines', ''));
|
||||
}) || [];
|
||||
|
||||
const subProjectsLinks = subProjects.map((subProject, index, arr) => ({
|
||||
name: subProject?.name.substring(subProject?.name.lastIndexOf('/') + 1),
|
||||
url: customProject ?
|
||||
data.project?.system_tags?.includes('pipeline') ? `pipelines/${subProject?.id}/experiments` : `datasets/simple/${subProject?.id}` :
|
||||
name: subProjectsNames[index],
|
||||
url: customProject ? (( index===subProjects.length-1) ?
|
||||
(data.project?.system_tags?.includes('pipeline') ?
|
||||
`pipelines/${subProject?.id}/experiments` : `datasets/simple/${subProject?.id}`): null)
|
||||
:
|
||||
fullScreen && index === (arr.length - 1) ? `projects/${subProject?.id}/experiments/${data?.experiment?.id}` :
|
||||
subProject?.name === data.project?.name && data.project?.sub_projects?.length === 0 ?
|
||||
`projects/${subProject?.id}` :
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
<div class="share-menu-container" smClickStopPropagation>
|
||||
<div class="d-flex align-items-center justify-content-between top">
|
||||
<div class="share-title">SHARE VIEW</div>
|
||||
<i class="pointer al-icon al-ico-dialog-x al-color blue-400 sm-md close-dialog"
|
||||
<i class="pointer al-icon al-ico-dialog-x al-color blue-300 sm-md close-dialog"
|
||||
(click)="menuTrigger.closeMenu()" smClickStopPropagation></i>
|
||||
</div>
|
||||
<div class="copy-title">Copy the following URL to share this view with others</div>
|
||||
|
||||
@@ -23,11 +23,11 @@
|
||||
<div class="right-buttons">
|
||||
<sm-common-search #search [class.share-view]="isShareMode"></sm-common-search>
|
||||
|
||||
<a class="pointer resources-trigger" [matMenuTriggerFor]="resourcesMenu">
|
||||
<i class="far al-ico-help-outlined"></i>
|
||||
<a class="d-flex pointer resources-trigger" [matMenuTriggerFor]="resourcesMenu">
|
||||
<i class="al-icon al-ico-help-outlined" data-id="help Icon"></i>
|
||||
</a>
|
||||
<a class="pointer menu-trigger position-relative" [matMenuTriggerFor]="profileMenu">
|
||||
<img alt="avatar" class="avatar" *ngIf="(user | async).avatar; else iconAvatar" [src]="(user | async).avatar">
|
||||
<img alt="avatar" class="avatar" data-id="Avatar" *ngIf="(user | async).avatar; else iconAvatar" [src]="(user | async).avatar">
|
||||
<ng-template #iconAvatar>
|
||||
<div class="user-icon">
|
||||
<i class="al-icon al-ico-account sm-md"></i>
|
||||
@@ -44,7 +44,7 @@
|
||||
Settings
|
||||
</button>
|
||||
<sm-header-user-menu-actions></sm-header-user-menu-actions>
|
||||
<button mat-menu-item (click)="logout()">
|
||||
<button mat-menu-item (click)="logout()" data-id="Logout">
|
||||
<span class="al-ico-logout al-icon icon sm-md"></span>
|
||||
Logout
|
||||
</button>
|
||||
@@ -71,7 +71,7 @@
|
||||
<i class="al-icon sm-md al-ico-applications"></i>ClearML Apps Introduction
|
||||
</button>
|
||||
</ng-container>
|
||||
<button mat-menu-item (click)="navigate('https://www.clear.ml/contact-us/')">
|
||||
<button mat-menu-item (click)="navigate('mailto:support@clear.ml')">
|
||||
<i class="al-icon sm-md al-ico-email"></i>Contact Us
|
||||
</button>
|
||||
</mat-menu>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
@import "../../layout/layout";
|
||||
@import "../../shared/ui-components/styles/variables";
|
||||
@import "variables";
|
||||
|
||||
:host {
|
||||
display: block;
|
||||
@@ -40,16 +40,18 @@
|
||||
width: 95%;
|
||||
}
|
||||
|
||||
.resources-trigger {
|
||||
display: flex;
|
||||
color: $blue-300;
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
color: $blue-200;
|
||||
}
|
||||
}
|
||||
|
||||
sm-common-search, .resources-trigger {
|
||||
sm-common-search,
|
||||
.resources-trigger {
|
||||
margin-right: 24px;
|
||||
background-color: $header-backgroud;
|
||||
|
||||
i {
|
||||
font-size: 24px;
|
||||
line-height: 24px;
|
||||
color: $light-grey-blue;
|
||||
}
|
||||
}
|
||||
|
||||
.menu-trigger {
|
||||
@@ -75,7 +77,7 @@
|
||||
flex: 0 0 32px;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
background-color: $light-grey-blue;
|
||||
background-color: $blue-300;
|
||||
color: $header-backgroud;
|
||||
border-radius: 50%;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "../../shared/ui-components/styles/variables";
|
||||
@import "variables";
|
||||
|
||||
$lg-breakpoint: map-get($grid-breakpoints, lg);
|
||||
:host {
|
||||
@@ -7,6 +7,7 @@ $lg-breakpoint: map-get($grid-breakpoints, lg);
|
||||
margin-left: $side-bar-close-width;
|
||||
.nav-bar-items-container {
|
||||
display: flex;
|
||||
gap: 1px;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {Component, OnDestroy, OnInit} from '@angular/core';
|
||||
import {ChangeDetectionStrategy, Component, OnDestroy, OnInit} from '@angular/core';
|
||||
import {select, Store} from '@ngrx/store';
|
||||
import { MatDialog, MatDialogRef } from '@angular/material/dialog';
|
||||
import {selectNotification} from '../../core/reducers/view.reducer';
|
||||
@@ -10,7 +10,8 @@ import {ConfirmDialogComponent} from '../../shared/ui-components/overlay/confirm
|
||||
@Component({
|
||||
selector : 'sm-server-notification-dialog-container',
|
||||
templateUrl: './server-notification-dialog-container.component.html',
|
||||
styleUrls : ['./server-notification-dialog-container.component.scss']
|
||||
styleUrls : ['./server-notification-dialog-container.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class ServerNotificationDialogContainerComponent implements OnInit, OnDestroy {
|
||||
private notificationSubscription: Subscription;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
// import {mobilecheck} from '../shared/utils/mobile';
|
||||
import {CommercialContext, Environment} from '../../../environments/base';
|
||||
import {ConfigurationService} from '@common/shared/services/configuration.service';
|
||||
|
||||
@@ -14,11 +13,6 @@ export class LoginPageComponent implements OnInit {
|
||||
public commercialContext: CommercialContext;
|
||||
public environment: Environment;
|
||||
|
||||
|
||||
constructor() {
|
||||
// this.mobile = mobilecheck();
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.environment = ConfigurationService.globalEnvironment;
|
||||
this.commercialContext = ConfigurationService.globalEnvironment.communityContext;
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
<a class="link" target="_blank"
|
||||
href="https://join.slack.com/t/allegroai-trains/shared_invite/enQtOTQyMTI1MzQxMzE4LTY5NTUxOTY1NmQ1MzQ5MjRhMGRhZmM4ODE5NTNjMTg2NTBlZGQzZGVkMWU3ZDg1MGE1MjQxNDEzMWU2NmVjZmY">
|
||||
<i class="al-icon al-ico-slack sm"></i><span class="text">Community on Slack</span></a>
|
||||
<a class="link" *ngIf="true" href="https://www.clear.ml/contact-us" target="_blank"><i class="al-icon al-ico-email sm"></i><span class="text">Contact
|
||||
Us</span></a>
|
||||
<a class="link" href="mailto:support@clear.ml" target="_blank"><i class="al-icon al-ico-email sm"></i><span class="text">Contact us</span></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
[name]="'metadataItemValue-'|uuid"
|
||||
matInput>
|
||||
</mat-form-field>
|
||||
<i (click)="removeRow(i)" class="al-icon al-ico-trash al-color blue-300 sm-md pointer flashing-icon mb-2"></i>
|
||||
<i (click)="removeRow(i)" class="al-icon al-ico-trash al-color blue-400 sm-md pointer flashing-icon mb-2"></i>
|
||||
</div>
|
||||
<button class="btn btn-cml-primary plus mt-2" (click)="addRow()"><i
|
||||
class="al-icon al-color blue-400 sm al-ico-plus d-flex align-items-center"></i>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<sm-menu
|
||||
[iconClass]="'al-icon al-ico-settings al-color pointer create-new-icon ' + (disabled ? 'blue-600' : 'blue-400')"
|
||||
[iconClass]="'al-icon al-ico-settings al-color pointer create-new-icon ' + (disabled ? 'blue-600' : 'blue-300')"
|
||||
buttonTooltip="Customize table"
|
||||
smMenuClass="light-theme custom-columns"
|
||||
[showButton]="false"
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
.custom-column-buttons {
|
||||
display: flex;
|
||||
font-weight: 500;
|
||||
color: $light-grey-blue;
|
||||
color: $blue-400;
|
||||
background: $faint-gray;
|
||||
cursor: pointer;
|
||||
.add-button {
|
||||
@@ -21,7 +21,7 @@
|
||||
}
|
||||
|
||||
div:not(.disabled):hover {
|
||||
color: $blue-400;
|
||||
color: $blue-300;
|
||||
transition: color 0.3s;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import {ChangeDetectionStrategy, Component, EventEmitter, Input, Output} from '@angular/core';
|
||||
import {getOr} from 'lodash/fp';
|
||||
import {SelectedModel} from '../../shared/models.model';
|
||||
import {NA} from '../../../../app.constants';
|
||||
import {TAGS} from '../../../tasks/tasks.constants';
|
||||
import {NA} from '~/app.constants';
|
||||
import {TAGS} from '@common/tasks/tasks.constants';
|
||||
import {DatePipe} from '@angular/common';
|
||||
import {TIME_FORMAT_STRING} from '../../../constants';
|
||||
import {TIME_FORMAT_STRING} from '@common/constants';
|
||||
import {Store} from '@ngrx/store';
|
||||
import {ActivateModelEdit, CancelModelEdit} from '../../actions/models-info.actions';
|
||||
import {AdminService} from '~/shared/services/admin.service';
|
||||
import {getSignedUrl} from '../../../core/actions/common-auth.actions';
|
||||
import {selectSignedUrl} from '../../../core/reducers/common-auth-reducer';
|
||||
import {getSignedUrl} from '@common/core/actions/common-auth.actions';
|
||||
import {selectSignedUrl} from '@common/core/reducers/common-auth-reducer';
|
||||
import {filter, map, take} from 'rxjs/operators';
|
||||
|
||||
@Component({
|
||||
@@ -22,7 +22,7 @@ export class ModelGeneralInfoComponent {
|
||||
constructor(private datePipe: DatePipe, private store: Store<any>, private adminService: AdminService) {
|
||||
}
|
||||
|
||||
public kpis: {label: string; value: string, downloadable?: boolean; href?: string; task?: string}[];
|
||||
public kpis: {label: string; value: string; downloadable?: boolean; href?: string; task?: string}[];
|
||||
private _model: SelectedModel;
|
||||
public isLocalFile: boolean;
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
</div>
|
||||
|
||||
<div class="input-container col-2 remove-step">
|
||||
<i (click)="removeRow(i)" class="al-icon al-ico-trash al-color blue-300 sm-md pointer flashing-icon mb-2"></i>
|
||||
<i (click)="removeRow(i)" class="al-icon al-ico-trash al-color blue-400 sm-md pointer flashing-icon mb-2"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -12,11 +12,11 @@ import * as viewActions from '../actions/models-view.actions';
|
||||
import {ModelInfoState} from '../reducers/model-info.reducer';
|
||||
import {MODELS_INFO_ONLY_FIELDS} from '../shared/models.const';
|
||||
import {selectSelectedModel} from '../reducers';
|
||||
import {EmptyAction} from '~/app.constants';
|
||||
import {SelectedModel} from '../shared/models.model';
|
||||
import {selectActiveWorkspace} from '../../core/reducers/users-reducer';
|
||||
import {isExample, isSharedAndNotOwner} from '../../shared/utils/shared-utils';
|
||||
import {resetActiveSection} from '../actions/models-info.actions';
|
||||
import {getTags} from '@common/core/actions/projects.actions';
|
||||
|
||||
@Injectable()
|
||||
export class ModelsInfoEffects {
|
||||
@@ -116,10 +116,11 @@ export class ModelsInfoEffects {
|
||||
const changes = res?.fields || action.changes;
|
||||
return [
|
||||
viewActions.updateModel({id: action.id, changes}),
|
||||
selectedModel?.id === action.id ? new infoActions.ModelDetailsUpdated({
|
||||
id: action.id,
|
||||
changes
|
||||
}) : new EmptyAction()
|
||||
...(selectedModel?.id === action.id ?
|
||||
[new infoActions.ModelDetailsUpdated({ id: action.id, changes })]
|
||||
: []
|
||||
),
|
||||
...(changes.tags ? [getTags()] : [])
|
||||
];
|
||||
}),
|
||||
catchError(err => [
|
||||
|
||||
@@ -50,6 +50,7 @@ import {PublishFooterItem} from '../shared/entity-page/footer-items/publish-foot
|
||||
import {HasReadOnlyFooterItem} from '../shared/entity-page/footer-items/has-read-only-footer-item';
|
||||
import {SelectedTagsFooterItem} from '../shared/entity-page/footer-items/selected-tags-footer-item';
|
||||
import {RefreshService} from '@common/core/services/refresh.service';
|
||||
import {SmSyncStateSelectorService} from '../core/services/sync-state-selector.service';
|
||||
|
||||
|
||||
@Component({
|
||||
@@ -103,9 +104,10 @@ export class ModelsComponent extends BaseEntityPageComponent implements OnInit,
|
||||
protected route: ActivatedRoute,
|
||||
protected router: Router,
|
||||
protected dialog: MatDialog,
|
||||
protected refresh: RefreshService
|
||||
protected refresh: RefreshService,
|
||||
protected syncSelector: SmSyncStateSelectorService,
|
||||
) {
|
||||
super(store, route, router, dialog, refresh);
|
||||
super(store, route, router, dialog, refresh, syncSelector);
|
||||
this.selectSplitSize$ = this.store.select(modelsSelectors.selectSplitSize);
|
||||
this.tableSortFields$ = this.store.select(modelsSelectors.selectTableSortFields);
|
||||
this.selectedModel$ = this.store.select(modelsSelectors.selectSelectedTableModel);
|
||||
|
||||
@@ -167,7 +167,7 @@ export class ModelsTableComponent extends BaseTableView {
|
||||
this.filtersValues[MODELS_TABLE_COL_FIELDS.PROJECT] = get([MODELS_TABLE_COL_FIELDS.PROJECT, 'value'], filters) || [];
|
||||
this.filtersMatch[MODELS_TABLE_COL_FIELDS.TAGS] = filters?.[MODELS_TABLE_COL_FIELDS.TAGS]?.matchMode || '';
|
||||
this.filtersSubValues[MODELS_TABLE_COL_FIELDS.TAGS] = get(['system_tags', 'value'], filters) || [];
|
||||
//dynamic filters
|
||||
// dynamic filters
|
||||
const filtersValues = createFiltersFromStore(filters || {}, false);
|
||||
this.filtersValues = Object.assign({}, {...this.filtersValues}, {...filtersValues});
|
||||
}
|
||||
@@ -315,10 +315,10 @@ export class ModelsTableComponent extends BaseTableView {
|
||||
}
|
||||
this.singleRowContext = !!data?.single;
|
||||
this.menuBackdrop = !!data?.backdrop;
|
||||
if(!data?.single) {
|
||||
if (!data?.single) {
|
||||
this.contextModel = this.models.find(model => model.id === data.rowData.id);
|
||||
if (!this.selectedModels.map(model => model.id).includes(this.contextModel.id)) {
|
||||
this.prevSelected = this.contextModel;
|
||||
this.prevSelected = this.contextModel.id;
|
||||
this.emitSelection([this.contextModel]);
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -53,7 +53,7 @@ $log-header-height: 48px;
|
||||
column-gap: 24px;
|
||||
padding: 0 24px;
|
||||
background-color: $blue-700;
|
||||
border-bottom: 1px solid #303443;
|
||||
border-bottom: 1px solid $dark-border;
|
||||
color: $blue-100;
|
||||
box-shadow: 0 -2px 6px rgb(0 0 0 / 40%);
|
||||
|
||||
|
||||
@@ -145,7 +145,6 @@ export class PipelineControllerInfoComponent implements OnInit, AfterViewInit, O
|
||||
.pipe(filter(model => model?.length > 0), tap((model: any[]) =>
|
||||
model.forEach(row => this.chartWidth = Math.max(this.chartWidth, row.length * 300))));
|
||||
const pipelineObject = this.getTreeObject(task);
|
||||
if (pipelineObject) {
|
||||
this.pipelineController = this.convertPipelineToDagModel(pipelineObject);
|
||||
this.resetUninitializedRunningFields();
|
||||
this._dagManager.setNewItemsArrayAsDagModel(this.pipelineController);
|
||||
@@ -158,7 +157,7 @@ export class PipelineControllerInfoComponent implements OnInit, AfterViewInit, O
|
||||
this.drawLines();
|
||||
this.cdr.detectChanges();
|
||||
}, 0);
|
||||
}
|
||||
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user