Co-authored-by: shallegro <shay@allego.ai>
6
.github/workflows/build.yml
vendored
@@ -30,3 +30,9 @@ jobs:
|
||||
|
||||
- name: Check for production build
|
||||
run: test -f build/browser/index.html
|
||||
|
||||
- name: Run widget build
|
||||
run: npm run build-widgets
|
||||
|
||||
- name: Check for widget build
|
||||
run: test -f dist/report-widgets/browser/index.html
|
||||
|
||||
20
angular.json
@@ -23,11 +23,12 @@
|
||||
"inlineStyleLanguage": "scss",
|
||||
"stylePreprocessorOptions": {
|
||||
"includePaths": [
|
||||
"",
|
||||
"src/app/webapp-common/shared/ui-components/styles/",
|
||||
"src/app/webapp-common/styles/",
|
||||
"."
|
||||
]
|
||||
],
|
||||
"sass": {
|
||||
"silenceDeprecations": ["import", "mixed-decls"]
|
||||
}
|
||||
},
|
||||
"assets": [
|
||||
"src/assets",
|
||||
@@ -43,6 +44,7 @@
|
||||
}
|
||||
],
|
||||
"styles": [
|
||||
"src/app/webapp-common/assets/fonts/heebo.css",
|
||||
"node_modules/ngx-markdown-editor/assets/highlight.js/agate.min.css",
|
||||
{
|
||||
"bundleName": "global-styles",
|
||||
@@ -174,7 +176,7 @@
|
||||
"stylePreprocessorOptions": {
|
||||
"includePaths": [
|
||||
"",
|
||||
"src/app/webapp-common/shared/ui-components/styles/"
|
||||
"src/app/webapp-common/styles/"
|
||||
]
|
||||
},
|
||||
"assets": [
|
||||
@@ -231,8 +233,7 @@
|
||||
"stylePreprocessorOptions": {
|
||||
"includePaths": [
|
||||
"",
|
||||
"src/app/webapp-common/styles/",
|
||||
"src/app/webapp-common/shared/ui-components/styles/"
|
||||
"src/app/webapp-common/styles/"
|
||||
]
|
||||
},
|
||||
"styles": [
|
||||
@@ -258,7 +259,10 @@
|
||||
"taira",
|
||||
"url"
|
||||
],
|
||||
"browser": "src/app/webapp-common/clearml-applications/report-widgets/src/main.ts"
|
||||
"browser": "src/app/webapp-common/clearml-applications/report-widgets/src/main.ts",
|
||||
"polyfills": [
|
||||
"zone.js"
|
||||
]
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
@@ -355,7 +359,7 @@
|
||||
"schematicCollections": [
|
||||
"@angular-eslint/schematics",
|
||||
"@ngrx/schematics",
|
||||
"ngxtension"
|
||||
"ngxtension-plugin"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
13642
package-lock.json
generated
117
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "clearml-webapp",
|
||||
"version": "2.0.0",
|
||||
"version": "2.1.0",
|
||||
"license": "",
|
||||
"scripts": {
|
||||
"ng": "ng",
|
||||
@@ -19,46 +19,49 @@
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@angular/animations": "^18.2.12",
|
||||
"@angular/cdk": "^18.2.14",
|
||||
"@angular/common": "^18.2.12",
|
||||
"@angular/compiler": "^18.2.12",
|
||||
"@angular/core": "^18.2.12",
|
||||
"@angular/forms": "^18.2.12",
|
||||
"@angular/material": "^18.2.14",
|
||||
"@angular/platform-browser": "^18.2.12",
|
||||
"@angular/platform-browser-dynamic": "^18.2.12",
|
||||
"@angular/platform-server": "^18.2.12",
|
||||
"@angular/router": "^18.2.12",
|
||||
"@angular/service-worker": "^18.2.12",
|
||||
"@angular/youtube-player": "^18.2.14",
|
||||
"@aws-sdk/client-s3": "^3.693.0",
|
||||
"@aws-sdk/s3-request-presigner": "^3.693.0",
|
||||
"@angular/animations": "19.1.5",
|
||||
"@angular/cdk": "19.1.3",
|
||||
"@angular/common": "19.1.5",
|
||||
"@angular/compiler": "19.1.5",
|
||||
"@angular/core": "19.1.5",
|
||||
"@angular/forms": "19.1.5",
|
||||
"@angular/material": "19.1.3",
|
||||
"@angular/platform-browser": "19.1.5",
|
||||
"@angular/platform-browser-dynamic": "19.1.5",
|
||||
"@angular/platform-server": "19.1.5",
|
||||
"@angular/router": "19.1.5",
|
||||
"@angular/service-worker": "19.1.5",
|
||||
"@angular/youtube-player": "19.1.3",
|
||||
"@aws-sdk/client-s3": "^3.782.0",
|
||||
"@aws-sdk/s3-request-presigner": "^3.782.0",
|
||||
"@ctrl/ngx-github-buttons": "^9.0.0",
|
||||
"@ctrl/tinycolor": "^4.1.0",
|
||||
"@ngneat/dag": "^2.0.0",
|
||||
"@ngrx/component": "^18.1.1",
|
||||
"@ngrx/effects": "^18.1.1",
|
||||
"@ngrx/entity": "^18.1.1",
|
||||
"@ngrx/operators": "^18.1.1",
|
||||
"@ngrx/router-store": "^18.1.1",
|
||||
"@ngrx/store": "^18.1.1",
|
||||
"@typescript-eslint/types": "^8.15.0",
|
||||
"ace-builds": "^1.36.5",
|
||||
"@ngrx/component": "19.1.0",
|
||||
"@ngrx/effects": "19.1.0",
|
||||
"@ngrx/entity": "19.1.0",
|
||||
"@ngrx/operators": "19.1.0",
|
||||
"@ngrx/router-store": "19.1.0",
|
||||
"@ngrx/signals": "19.1.0",
|
||||
"@ngrx/store": "19.1.0",
|
||||
"@primeng/themes": "^19.0.10",
|
||||
"@typescript-eslint/types": "^8.29.1",
|
||||
"ace-builds": "^1.39.1",
|
||||
"angular-resizable-element": "^7.0.2",
|
||||
"angular-split": "^18.0.0",
|
||||
"angular-split": "^19.0.0",
|
||||
"ansi-to-html": "^0.7.2",
|
||||
"bootstrap": "^5.3.3",
|
||||
"chart.js": "^4.4.6",
|
||||
"bootstrap": "^5.3.5",
|
||||
"chart.js": "^4.4.8",
|
||||
"chartjs-adapter-date-fns": "^3.0.0",
|
||||
"chartjs-plugin-annotation": "^3.1.0",
|
||||
"chartjs-plugin-zoom": "^2.1.0",
|
||||
"chartjs-plugin-zoom": "^2.2.0",
|
||||
"curved-arrows": "^0.3.0",
|
||||
"d3-interpolate": "^3.0.1",
|
||||
"d3-selection": "^3.0.0",
|
||||
"date-fns": "^4.1.0",
|
||||
"diff": "^7.0.0",
|
||||
"dom-to-image": "^2.6.0",
|
||||
"dompurify": "^3.2.0",
|
||||
"dompurify": "^3.2.5",
|
||||
"export-to-csv": "^1.4.0",
|
||||
"filesize": "^10.1.6",
|
||||
"has-ansi": "^6.0.0",
|
||||
@@ -66,54 +69,54 @@
|
||||
"lodash-es": "^4.17.21",
|
||||
"lucene": "^2.1.1",
|
||||
"marked": "^12.0.2",
|
||||
"ng2-charts": "^6.0.1",
|
||||
"ng2-charts": "^8.0.0",
|
||||
"ngx-clipboard": "^16.0.0",
|
||||
"ngx-color-picker": "^17.0.0",
|
||||
"ngx-device-detector": "^8.0.0",
|
||||
"ngx-color-picker": "^19.0.0",
|
||||
"ngx-device-detector": "^9.0.0",
|
||||
"ngx-markdown-editor": "^5.3.4",
|
||||
"ngx-print": "^1.5.1",
|
||||
"ngx-print": "^2.0.0",
|
||||
"ngx-window-token": "^7.0.0",
|
||||
"ngxtension": "^4.1.0",
|
||||
"ngxtension": "^5.0.0",
|
||||
"object-hash": "^3.0.0",
|
||||
"primeicons": "^7.0.0",
|
||||
"primeng": "^17.18.15",
|
||||
"rxjs": "^7.8.1",
|
||||
"primeng": "^19.0.10",
|
||||
"rxjs": "^7.8.2",
|
||||
"string-to-color": "^2.2.2",
|
||||
"taira": "^3.2.2",
|
||||
"tslib": "^2.8.1",
|
||||
"url": "^0.11.4",
|
||||
"uuid": "^11.0.3",
|
||||
"uuid": "^11.1.0",
|
||||
"zone.js": "~0.15.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "^18.2.12",
|
||||
"@angular-devkit/core": "^18.2.12",
|
||||
"@angular-devkit/schematics": "^18.2.12",
|
||||
"@angular-devkit/schematics-cli": "^18.2.12",
|
||||
"@angular/cli": "^18.2.12",
|
||||
"@angular/compiler-cli": "^18.2.12",
|
||||
"@angular/language-service": "^18.2.12",
|
||||
"@ngrx/eslint-plugin": "^18.1.1",
|
||||
"@ngrx/schematics": "^18.1.1",
|
||||
"@ngrx/store-devtools": "^18.1.1",
|
||||
"@angular-devkit/build-angular": "^19.2.12",
|
||||
"@angular-devkit/core": "19.1.6",
|
||||
"@angular-devkit/schematics": "19.1.6",
|
||||
"@angular-devkit/schematics-cli": "19.1.6",
|
||||
"@angular/cli": "19.1.6",
|
||||
"@angular/compiler-cli": "19.1.5",
|
||||
"@angular/language-service": "19.1.5",
|
||||
"@ngrx/eslint-plugin": "19.1.0",
|
||||
"@ngrx/schematics": "19.1.0",
|
||||
"@ngrx/store-devtools": "19.1.0",
|
||||
"@types/d3-interpolate": "^3.0.4",
|
||||
"@types/d3-selection": "^3.0.11",
|
||||
"@types/diff": "^6.0.0",
|
||||
"@types/diff": "^7.0.2",
|
||||
"@types/dom-to-image": "^2.6.7",
|
||||
"@types/dompurify": "^3.0.5",
|
||||
"@types/has-ansi": "^5.0.2",
|
||||
"@types/jasmine": "^5.1.4",
|
||||
"@types/jasmine": "^5.1.7",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"@types/node": "^22.9.0",
|
||||
"@types/plotly.js": "^2.35.0",
|
||||
"@types/node": "^22.14.0",
|
||||
"@types/plotly.js": "^2.35.4",
|
||||
"@types/tinycolor2": "^1.4.6",
|
||||
"@types/uuid": "^10.0.0",
|
||||
"angular-eslint": "^18.4.1",
|
||||
"eslint": "^9.15.0",
|
||||
"angular-eslint": "^19.3.0",
|
||||
"eslint": "^9.24.0",
|
||||
"eslint-plugin-import": "2.31.0",
|
||||
"eslint-plugin-jsdoc": "^50.5.0",
|
||||
"eslint-plugin-jsdoc": "^50.6.9",
|
||||
"eslint-plugin-prefer-arrow": "1.2.3",
|
||||
"primeng-sass-theme": "github:primefaces/primeng-sass-theme",
|
||||
"typescript": "^5.5.4",
|
||||
"typescript-eslint": "^8.15.0"
|
||||
"typescript": "^5.7.3",
|
||||
"typescript-eslint": "^8.29.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,12 +25,13 @@ import {ThemeService} from '@common/shared/services/theme.service';
|
||||
import {takeUntilDestroyed} from '@angular/core/rxjs-interop';
|
||||
|
||||
@Component({
|
||||
selector: 'sm-root',
|
||||
templateUrl: 'app.component.html',
|
||||
styleUrls: ['app.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
providers: [ThemeService]
|
||||
selector: 'sm-root',
|
||||
templateUrl: 'app.component.html',
|
||||
styleUrls: ['app.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
providers: [ThemeService],
|
||||
standalone: false
|
||||
})
|
||||
export class AppComponent {
|
||||
private router = inject(Router);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {APP_INITIALIZER, inject, NgModule} from '@angular/core';
|
||||
import {APP_INITIALIZER, inject, NgModule, provideAppInitializer} from '@angular/core';
|
||||
import {BrowserModule} from '@angular/platform-browser';
|
||||
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
|
||||
import {PreloadAllModules, RouteReuseStrategy, RouterModule} from '@angular/router';
|
||||
@@ -17,10 +17,8 @@ import {NotifierModule} from '@common/angular-notifier';
|
||||
import {LayoutModule} from './layout/layout.module';
|
||||
import {ColorHashService} from '@common/shared/services/color-hash/color-hash.service';
|
||||
import {SharedModule} from './shared/shared.module';
|
||||
import {ConfigurationService} from '@common/shared/services/configuration.service';
|
||||
import {ProjectsSharedModule} from './features/projects/shared/projects-shared.module';
|
||||
import {MAT_FORM_FIELD_DEFAULT_OPTIONS} from '@angular/material/form-field';
|
||||
import {LoginService} from '~/shared/services/login.service';
|
||||
import {ExperimentSharedModule} from '~/features/experiments/shared/experiment-shared.module';
|
||||
import {loadUserAndPreferences} from '~/core/app-init';
|
||||
import {MAT_TOOLTIP_DEFAULT_OPTIONS, MatTooltipDefaultOptions} from '@angular/material/tooltip';
|
||||
@@ -30,6 +28,8 @@ import {SpinnerComponent} from '@common/shared/ui-components/overlay/spinner/spi
|
||||
import {MatIconRegistry} from '@angular/material/icon';
|
||||
import {provideCharts, withDefaultRegisterables} from 'ng2-charts';
|
||||
import {PushPipe} from '@ngrx/component';
|
||||
import { providePrimeNG } from 'primeng/config';
|
||||
import {cmlPreset} from '@common/styles/prime.preset';
|
||||
|
||||
@NgModule({
|
||||
declarations : [AppComponent],
|
||||
@@ -68,13 +68,8 @@ import {PushPipe} from '@ngrx/component';
|
||||
],
|
||||
providers: [
|
||||
UserPreferences,
|
||||
{provide: MAT_FORM_FIELD_DEFAULT_OPTIONS, useValue: {floatLabel: 'always'}},
|
||||
{
|
||||
provide : APP_INITIALIZER,
|
||||
deps: [LoginService, ConfigurationService],
|
||||
useFactory: loadUserAndPreferences,
|
||||
multi : true,
|
||||
},
|
||||
{provide: MAT_FORM_FIELD_DEFAULT_OPTIONS, useValue: {floatLabel: 'always', appearance: 'outline'}},
|
||||
provideAppInitializer(() => loadUserAndPreferences()),
|
||||
ColorHashService,
|
||||
{provide: HTTP_INTERCEPTORS, useClass: WebappInterceptor, multi: true},
|
||||
{provide: RouteReuseStrategy, useClass: CustomReuseStrategy},
|
||||
@@ -83,6 +78,11 @@ import {PushPipe} from '@ngrx/component';
|
||||
useValue: {position: 'above'} as MatTooltipDefaultOptions
|
||||
},
|
||||
provideCharts(withDefaultRegisterables()),
|
||||
providePrimeNG({
|
||||
theme: {
|
||||
preset: cmlPreset
|
||||
}
|
||||
})
|
||||
],
|
||||
bootstrap : [AppComponent],
|
||||
exports : []
|
||||
|
||||
@@ -34,6 +34,7 @@ export const routes: Routes = [
|
||||
{path: '', pathMatch: 'full', children: [], canActivate: [projectRedirectGuardGuard]},
|
||||
{
|
||||
path: 'overview',
|
||||
data: {search: false},
|
||||
loadChildren: () => import('./webapp-common/project-info/project-info.module').then(m => m.ProjectInfoModule),
|
||||
canDeactivate: [resetContextMenuGuard]
|
||||
},
|
||||
@@ -52,7 +53,7 @@ export const routes: Routes = [
|
||||
{path: 'compare-experiments', redirectTo: 'compare-tasks'},
|
||||
{
|
||||
path: 'compare-tasks',
|
||||
data: {entityType: EntityTypeEnum.experiment},
|
||||
data: {entityType: EntityTypeEnum.experiment, search: false},
|
||||
loadChildren: () =>
|
||||
import('./webapp-common/experiments-compare/experiments-compare.module').then(m => m.ExperimentsCompareModule)
|
||||
},
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import {LoginService} from '~/shared/services/login.service';
|
||||
import {ConfigurationService} from '@common/shared/services/configuration.service';
|
||||
import {combineLatest} from 'rxjs';
|
||||
import {switchMap} from 'rxjs';
|
||||
import {inject} from '@angular/core';
|
||||
|
||||
export const loadUserAndPreferences = (
|
||||
loginService: LoginService,
|
||||
confService: ConfigurationService,
|
||||
): () => Promise<any> => (): Promise<any> => new Promise((resolve) => {
|
||||
combineLatest([
|
||||
confService.initConfigurationService(),
|
||||
loginService.initCredentials()
|
||||
])
|
||||
.subscribe(() => loginService.loginFlow(resolve));
|
||||
});
|
||||
export const loadUserAndPreferences = ()=>
|
||||
new Promise((resolve) => {
|
||||
const loginService = inject(LoginService);
|
||||
const confService = inject(ConfigurationService);
|
||||
|
||||
confService.initConfigurationService()
|
||||
.pipe(switchMap(() => loginService.initCredentials()))
|
||||
.subscribe(() => loginService.loginFlow(resolve));
|
||||
});
|
||||
|
||||
@@ -2,9 +2,11 @@ import {commonAuthReducer, initAuth, selectAuth} from '@common/core/reducers/com
|
||||
import {createReducer, createSelector} from '@ngrx/store';
|
||||
|
||||
const extraCredentials = [];
|
||||
const services = [];
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
export const selectExtraCredentials = createSelector(selectAuth, state => extraCredentials);
|
||||
export const selectCompanyPreSignServices = createSelector(selectAuth, state => services);
|
||||
|
||||
export const authReducer = createReducer(
|
||||
initAuth,
|
||||
|
||||
@@ -1,24 +1,12 @@
|
||||
import {Component} from '@angular/core';
|
||||
import {DashboardSearchBaseComponent} from '@common/dashboard/dashboard-search.component.base';
|
||||
import {selectIsSearching} from '@common/common-search/common-search.reducer';
|
||||
import {takeUntilDestroyed} from '@angular/core/rxjs-interop';
|
||||
import {debounceTime, filter} from 'rxjs/operators';
|
||||
|
||||
@Component({
|
||||
selector: 'sm-dashboard-search',
|
||||
templateUrl: './dashboard-search.component.html',
|
||||
styleUrls: ['./dashboard-search.component.scss'],
|
||||
selector: 'sm-dashboard-search',
|
||||
templateUrl: './dashboard-search.component.html',
|
||||
styleUrls: ['./dashboard-search.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class DashboardSearchComponent extends DashboardSearchBaseComponent {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.store.select(selectIsSearching)
|
||||
.pipe(
|
||||
debounceTime(200),
|
||||
takeUntilDestroyed(),
|
||||
filter(active => !active)
|
||||
)
|
||||
.subscribe(() => this.router.navigate(['dashboard'], ));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="h-100">
|
||||
<div>
|
||||
<mat-tab-group
|
||||
[selectedIndex]="activeIndex()"
|
||||
(selectedTabChange)="activeLinkChanged.emit(activeLinksList[$event.index].name)"
|
||||
@@ -11,6 +11,9 @@
|
||||
}
|
||||
</mat-tab-group>
|
||||
<div class="page-container">
|
||||
@if (getResults()?.length === 0) {
|
||||
<span class="no-data">No data to show</span>
|
||||
} @else if(getResults()){
|
||||
<sm-virtual-grid
|
||||
[cardTemplate]="
|
||||
activeLink() === searchPages.projects ? ProjectTemplate :
|
||||
@@ -27,6 +30,7 @@
|
||||
(loadMoreClicked)="loadMoreClicked.emit()"
|
||||
>
|
||||
</sm-virtual-grid>
|
||||
}
|
||||
</div>
|
||||
|
||||
<ng-template #ProjectTemplate let-project>
|
||||
|
||||
@@ -1,8 +1,22 @@
|
||||
.mat-mdc-tab-group {
|
||||
--mat-tab-header-label-text-size: 14px;
|
||||
border-bottom: 1px solid var(--color-outline-variant);
|
||||
margin: 24px 0;
|
||||
height: 49px;
|
||||
|
||||
}
|
||||
|
||||
.page-container {
|
||||
height: calc(100% - 67px);
|
||||
height: calc(90vh - 224px);
|
||||
width: calc(90vw - 96px);
|
||||
margin-top: 18px;
|
||||
|
||||
.no-data {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: var(--color-outline);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,9 +7,10 @@ import {activeLinksList, ActiveSearchLink, activeSearchLink} from '~/features/da
|
||||
import {IReport} from '@common/reports/reports.consts';
|
||||
|
||||
@Component({
|
||||
selector: 'sm-search-results-page',
|
||||
templateUrl: './search-results-page.component.html',
|
||||
styleUrls: ['./search-results-page.component.scss']
|
||||
selector: 'sm-search-results-page',
|
||||
templateUrl: './search-results-page.component.html',
|
||||
styleUrls: ['./search-results-page.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class SearchResultsPageComponent {
|
||||
protected readonly searchPages = activeSearchLink;
|
||||
@@ -71,6 +72,8 @@ export class SearchResultsPageComponent {
|
||||
case activeSearchLink.models:
|
||||
return 264;
|
||||
case activeSearchLink.pipelines:
|
||||
case activeSearchLink.reports:
|
||||
case activeSearchLink.openDatasets:
|
||||
return 226;
|
||||
default:
|
||||
return 250;
|
||||
|
||||
@@ -35,7 +35,10 @@ import {MatTab, MatTabGroup} from '@angular/material/tabs';
|
||||
MatTabGroup,
|
||||
MatTab,
|
||||
],
|
||||
declarations:[
|
||||
exports: [
|
||||
DashboardSearchComponent
|
||||
],
|
||||
declarations: [
|
||||
SearchResultsPageComponent, DashboardSearchComponent
|
||||
]
|
||||
})
|
||||
|
||||
@@ -17,9 +17,10 @@ import {selectActiveSearch} from '@common/common-search/common-search.reducer';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'sm-dashboard',
|
||||
templateUrl: './dashboard.component.html',
|
||||
styleUrls: ['./dashboard.component.scss']
|
||||
selector: 'sm-dashboard',
|
||||
templateUrl: './dashboard.component.html',
|
||||
styleUrls: ['./dashboard.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class DashboardComponent implements OnInit, OnDestroy {
|
||||
private store = inject(Store);
|
||||
|
||||
@@ -12,22 +12,21 @@ import {MatIcon} from '@angular/material/icon';
|
||||
import {ClickStopPropagationDirective} from '@common/shared/ui-components/directives/click-stop-propagation.directive';
|
||||
|
||||
@Component({
|
||||
selector: 'sm-nested-datasets-page',
|
||||
templateUrl: './nested-datasets-page.component.html',
|
||||
styleUrls: [
|
||||
'../../../webapp-common/nested-project-view/nested-project-view-page/nested-project-view-page.component.scss',
|
||||
'../../../webapp-common/datasets/open-datasets/open-datasets.component.scss'
|
||||
],
|
||||
imports: [
|
||||
ProjectsSharedModule,
|
||||
AsyncPipe,
|
||||
CircleCounterComponent,
|
||||
TagListComponent,
|
||||
MatButton,
|
||||
MatIcon,
|
||||
ClickStopPropagationDirective
|
||||
],
|
||||
standalone: true
|
||||
selector: 'sm-nested-datasets-page',
|
||||
templateUrl: './nested-datasets-page.component.html',
|
||||
styleUrls: [
|
||||
'../../../webapp-common/nested-project-view/nested-project-view-page/nested-project-view-page.component.scss',
|
||||
'../../../webapp-common/datasets/open-datasets/open-datasets.component.scss'
|
||||
],
|
||||
imports: [
|
||||
ProjectsSharedModule,
|
||||
AsyncPipe,
|
||||
CircleCounterComponent,
|
||||
TagListComponent,
|
||||
MatButton,
|
||||
MatIcon,
|
||||
ClickStopPropagationDirective
|
||||
]
|
||||
})
|
||||
export class NestedDatasetsPageComponent extends CommonProjectsPageComponent {
|
||||
entityTypeEnum = ProjectTypeEnum;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
.tab-nav {
|
||||
display: grid;
|
||||
grid-template-columns: 200px 1fr 200px;
|
||||
border-bottom: 1px solid #efefef;
|
||||
border-bottom: 1px solid var(--color-surface-container-high);
|
||||
|
||||
&.minimized {
|
||||
grid-template-columns: 0 1fr 108px;
|
||||
|
||||
@@ -3,10 +3,11 @@ import {Link} from '@common/shared/components/router-tab-nav-bar/router-tab-nav-
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'sm-experiment-info-navbar',
|
||||
templateUrl: './experiment-info-navbar.component.html',
|
||||
styleUrls: ['./experiment-info-navbar.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
selector: 'sm-experiment-info-navbar',
|
||||
templateUrl: './experiment-info-navbar.component.html',
|
||||
styleUrls: ['./experiment-info-navbar.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone: false
|
||||
})
|
||||
export class ExperimentInfoNavbarComponent {
|
||||
public baseInfoRoute: string[];
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import {Component, computed, Signal} from '@angular/core';
|
||||
import {Component, computed} from '@angular/core';
|
||||
import {ExperimentMenuComponent} from '@common/experiments/shared/components/experiment-menu/experiment-menu.component';
|
||||
|
||||
@Component({
|
||||
selector: 'sm-experiment-menu-extended',
|
||||
templateUrl: '../../../../webapp-common/experiments/shared/components/experiment-menu/experiment-menu.component.html',
|
||||
styleUrls: ['../../../../webapp-common/experiments/shared/components/experiment-menu/experiment-menu.component.scss']
|
||||
selector: 'sm-experiment-menu-extended',
|
||||
templateUrl: '../../../../webapp-common/experiments/shared/components/experiment-menu/experiment-menu.component.html',
|
||||
styleUrls: ['../../../../webapp-common/experiments/shared/components/experiment-menu/experiment-menu.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class ExperimentMenuExtendedComponent extends ExperimentMenuComponent{
|
||||
contextMenu = computed(() => this as ExperimentMenuComponent);
|
||||
|
||||
@@ -39,15 +39,19 @@
|
||||
class="graph-settings-menu"
|
||||
(click)="$event.stopPropagation()"
|
||||
[verticalLayout]="true"
|
||||
[smoothWeight]="smoothWeight$ | ngrxPush"
|
||||
[smoothType]="smoothType$ | ngrxPush"
|
||||
[xAxisType]="xAxisType$ | ngrxPush"
|
||||
[groupBy]="groupBy$ | ngrxPush"
|
||||
[smoothWeight]="smoothWeight()"
|
||||
[smoothSigma]="smoothSigma()"
|
||||
[smoothType]="smoothType()"
|
||||
[xAxisType]="xAxisType()"
|
||||
[groupBy]="groupBy()"
|
||||
[clearable]="projectId === '*' ? null : !isProjectLevel()"
|
||||
[groupByOptions]="groupByOptions"
|
||||
(changeWeight)="changeSmoothness($event)"
|
||||
(changeSigma)="changeSigma($event)"
|
||||
(changeXAxisType)="changeXAxisType($event)"
|
||||
(changeGroupBy)="changeGroupBy($event)"
|
||||
(changeSmoothType)="changeSmoothType($event)"
|
||||
(setToProject)="setToProject()"
|
||||
></sm-graph-settings-bar>
|
||||
</mat-menu>
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import {Component} from '@angular/core';
|
||||
import {BaseExperimentOutputComponent} from '../../../../webapp-common/experiments/containers/experiment-ouptut/base-experiment-output.component';
|
||||
import {BaseExperimentOutputComponent} from '@common/experiments/containers/experiment-ouptut/base-experiment-output.component';
|
||||
|
||||
@Component({
|
||||
selector: 'sm-experiment-output',
|
||||
templateUrl: './experiment-output.component.html',
|
||||
styleUrls: ['../../../../webapp-common/experiments/containers/experiment-ouptut/base-experiment-output.component.scss']
|
||||
styleUrls: ['../../../../webapp-common/experiments/containers/experiment-ouptut/base-experiment-output.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class ExperimentOutputComponent extends BaseExperimentOutputComponent {
|
||||
public overflow: boolean;
|
||||
|
||||
@@ -11,68 +11,32 @@ import {ExperimentGraphsModule} from '@common/shared/experiment-graphs/experimen
|
||||
import {ExperimentCompareSharedModule} from '@common/experiments-compare/shared/experiment-compare-shared.module';
|
||||
import {AngularSplitModule} from 'angular-split';
|
||||
import {DebugImagesModule} from '@common/debug-images/debug-images.module';
|
||||
import {
|
||||
ExperimentInfoExecutionComponent
|
||||
} from '@common/experiments/containers/experiment-info-execution/experiment-info-execution.component';
|
||||
import {ExperimentInfoExecutionComponent} from '@common/experiments/containers/experiment-info-execution/experiment-info-execution.component';
|
||||
import {MatSidenavModule} from '@angular/material/sidenav';
|
||||
import {MatListModule} from '@angular/material/list';
|
||||
import {ExperimentOutputComponent} from './containers/experiment-ouptut/experiment-output.component';
|
||||
import {ExperimentInfoNavbarComponent} from './containers/experiment-info-navbar/experiment-info-navbar.component';
|
||||
import {
|
||||
ExperimentInfoHyperParametersComponent
|
||||
} from '@common/experiments/containers/experiment-info-hyper-parameters/experiment-info-hyper-parameters.component';
|
||||
import {
|
||||
ExperimentInfoArtifactItemComponent
|
||||
} from '@common/experiments/containers/experiment-info-artifact-item/experiment-info-artifact-item.component';
|
||||
import {
|
||||
ExperimentGeneralInfoComponent
|
||||
} from '@common/experiments/dumb/experiment-general-info/experiment-general-info.component';
|
||||
import {
|
||||
ExperimentArtifactItemViewComponent
|
||||
} from '@common/experiments/dumb/experiment-artifact-item-view/experiment-artifact-item-view.component';
|
||||
import {
|
||||
ExperimentHyperParamsNavbarComponent
|
||||
} from '@common/experiments/dumb/experiment-hyper-params-navbar/experiment-hyper-params-navbar.component';
|
||||
import {
|
||||
ExperimentExecutionSourceCodeComponent
|
||||
} from '@common/experiments/dumb/experiment-execution-source-code/experiment-execution-source-code.component';
|
||||
import {
|
||||
ExperimentInfoEditDescriptionComponent
|
||||
} from '@common/experiments/dumb/experiment-info-edit-description/experiment-info-edit-description.component';
|
||||
import {
|
||||
ExperimentOutputModelViewComponent
|
||||
} from '@common/experiments/dumb/experiment-output-model-view/experiment-output-model-view.component';
|
||||
import {
|
||||
ExperimentInfoGeneralComponent
|
||||
} from '@common/experiments/containers/experiment-info-general/experiment-info-general.component';
|
||||
import {ExperimentInfoHyperParametersComponent} from '@common/experiments/containers/experiment-info-hyper-parameters/experiment-info-hyper-parameters.component';
|
||||
import {ExperimentInfoArtifactItemComponent} from '@common/experiments/containers/experiment-info-artifact-item/experiment-info-artifact-item.component';
|
||||
import {ExperimentArtifactItemViewComponent} from '@common/experiments/dumb/experiment-artifact-item-view/experiment-artifact-item-view.component';
|
||||
import {ExperimentHyperParamsNavbarComponent} from '@common/experiments/dumb/experiment-hyper-params-navbar/experiment-hyper-params-navbar.component';
|
||||
import {ExperimentExecutionSourceCodeComponent} from '@common/experiments/dumb/experiment-execution-source-code/experiment-execution-source-code.component';
|
||||
import {ExperimentInfoEditDescriptionComponent} from '@common/experiments/dumb/experiment-info-edit-description/experiment-info-edit-description.component';
|
||||
import {ExperimentOutputModelViewComponent} from '@common/experiments/dumb/experiment-output-model-view/experiment-output-model-view.component';
|
||||
import {ExperimentInfoGeneralComponent} from '@common/experiments/containers/experiment-info-general/experiment-info-general.component';
|
||||
import {BaseClickableArtifactComponent} from '@common/experiments/dumb/base-clickable-artifact.component';
|
||||
import {
|
||||
ExperimentModelsFormViewComponent
|
||||
} from '@common/experiments/dumb/experiment-models-form-view/experiment-models-form-view.component';
|
||||
import {
|
||||
ExperimentInfoArtifactsComponent
|
||||
} from '@common/experiments/containers/experiment-info-aritfacts/experiment-info-artifacts.component';
|
||||
import {
|
||||
ExperimentInfoHeaderComponent
|
||||
} from '@common/experiments/dumb/experiment-info-header/experiment-info-header.component';
|
||||
import {
|
||||
ExperimentInfoTaskModelComponent
|
||||
} from '@common/experiments/containers/experiment-info-task-model/experiment-info-task-model.component';
|
||||
import {
|
||||
ExperimentOutputScalarsComponent
|
||||
} from '@common/experiments/containers/experiment-output-scalars/experiment-output-scalars.component';
|
||||
import {
|
||||
ExperimentInfoModelComponent
|
||||
} from '@common/experiments/containers/experiment-info-model/experiment-info-model.component';
|
||||
import {
|
||||
ExperimentInfoHyperParametersFormContainerComponent
|
||||
} from '@common/experiments/containers/experiment-info-hyper-parameters-form-container/experiment-info-hyper-parameters-form-container.component';
|
||||
import {ExperimentModelsFormViewComponent} from '@common/experiments/dumb/experiment-models-form-view/experiment-models-form-view.component';
|
||||
import {ExperimentInfoArtifactsComponent} from '@common/experiments/containers/experiment-info-aritfacts/experiment-info-artifacts.component';
|
||||
import {ExperimentInfoHeaderComponent} from '@common/experiments/dumb/experiment-info-header/experiment-info-header.component';
|
||||
import {ExperimentInfoTaskModelComponent} from '@common/experiments/containers/experiment-info-task-model/experiment-info-task-model.component';
|
||||
import {ExperimentOutputScalarsComponent} from '@common/experiments/containers/experiment-output-scalars/experiment-output-scalars.component';
|
||||
import {ExperimentInfoModelComponent} from '@common/experiments/containers/experiment-info-model/experiment-info-model.component';
|
||||
import {ExperimentInfoHyperParametersFormContainerComponent} from '@common/experiments/containers/experiment-info-hyper-parameters-form-container/experiment-info-hyper-parameters-form-container.component';
|
||||
import {ExperimentOutputLogModule} from '@common/experiments/shared/experiment-output-log/experiment-output-log.module';
|
||||
import {RouterModule} from '@angular/router';
|
||||
import {ScrollingModule} from '@angular/cdk/scrolling';
|
||||
import {MatProgressSpinnerModule} from '@angular/material/progress-spinner';
|
||||
import {MatRadioModule} from '@angular/material/radio';
|
||||
import {SharedModule} from '~/shared/shared.module';
|
||||
import {MAT_AUTOCOMPLETE_SCROLL_STRATEGY} from '@angular/material/autocomplete';
|
||||
import {scrollFactory} from '@common/shared/utils/scroll-factory';
|
||||
import {Overlay} from '@angular/cdk/overlay';
|
||||
@@ -81,9 +45,7 @@ import {RouterTabNavBarComponent} from '@common/shared/components/router-tab-nav
|
||||
import {MatTabsModule} from '@angular/material/tabs';
|
||||
import {OverlayComponent} from '@common/shared/ui-components/overlay/overlay/overlay.component';
|
||||
import {RefreshButtonComponent} from '@common/shared/components/refresh-button/refresh-button.component';
|
||||
import {
|
||||
InfoHeaderStatusIconLabelComponent
|
||||
} from '@common/shared/experiment-info-header-status-icon-label/info-header-status-icon-label.component';
|
||||
import {InfoHeaderStatusIconLabelComponent} from '@common/shared/experiment-info-header-status-icon-label/info-header-status-icon-label.component';
|
||||
import {NAPipe} from '@common/shared/pipes/na.pipe';
|
||||
import {SortPipe} from '@common/shared/pipes/sort.pipe';
|
||||
import {safeAngularUrlParameterPipe} from '@common/shared/pipes/safeAngularUrlParameter.pipe';
|
||||
@@ -100,120 +62,114 @@ import {InlineEditComponent} from '@common/shared/ui-components/inputs/inline-ed
|
||||
import {TagsMenuComponent} from '@common/shared/ui-components/tags/tags-menu/tags-menu.component';
|
||||
import {EntityFooterComponent} from '@common/shared/entity-page/entity-footer/entity-footer.component';
|
||||
import {MenuComponent} from '@common/shared/ui-components/panel/menu/menu.component';
|
||||
import {
|
||||
ExperimentTypeIconLabelComponent
|
||||
} from '@common/shared/experiment-type-icon-label/experiment-type-icon-label.component';
|
||||
import {ExperimentTypeIconLabelComponent} from '@common/shared/experiment-type-icon-label/experiment-type-icon-label.component';
|
||||
import {SearchComponent} from '@common/shared/ui-components/inputs/search/search.component';
|
||||
import {IdBadgeComponent} from '@common/shared/components/id-badge/id-badge.component';
|
||||
import {ScrollTextareaComponent} from '@common/shared/components/scroll-textarea/scroll-textarea.component';
|
||||
import {TagListComponent} from '@common/shared/ui-components/tags/tag-list/tag-list.component';
|
||||
import {TooltipDirective} from '@common/shared/ui-components/indicators/tooltip/tooltip.directive';
|
||||
import {LabeledRowComponent} from '@common/shared/ui-components/data/labeled-row/labeled-row.component';
|
||||
import {
|
||||
SelectableGroupedFilterListComponent
|
||||
} from '@common/shared/ui-components/data/selectable-grouped-filter-list/selectable-grouped-filter-list.component';
|
||||
import {SelectableGroupedFilterListComponent} from '@common/shared/ui-components/data/selectable-grouped-filter-list/selectable-grouped-filter-list.component';
|
||||
import {EditableSectionComponent} from '@common/shared/ui-components/panel/editable-section/editable-section.component';
|
||||
import {MatMenuModule} from '@angular/material/menu';
|
||||
import {MatExpansionModule} from '@angular/material/expansion';
|
||||
import {MatInputModule} from '@angular/material/input';
|
||||
import {MatSelectModule} from '@angular/material/select';
|
||||
import {HesitateDirective} from '@common/shared/ui-components/directives/hesitate.directive';
|
||||
import {
|
||||
ShowTooltipIfEllipsisDirective
|
||||
} from '@common/shared/ui-components/indicators/tooltip/show-tooltip-if-ellipsis.directive';
|
||||
import {ShowTooltipIfEllipsisDirective} from '@common/shared/ui-components/indicators/tooltip/show-tooltip-if-ellipsis.directive';
|
||||
import {SelectQueueModule} from '@common/experiments/shared/components/select-queue/select-queue.module';
|
||||
import {PushPipe} from '@ngrx/component';
|
||||
import {ExperimentHeaderComponent} from '@common/experiments/dumb/experiment-header/experiment-header.component';
|
||||
import {
|
||||
ExperimentOperationsLogComponent
|
||||
} from '@common/experiments/dumb/experiment-operations-log/experiment-operations-log.component';
|
||||
import {
|
||||
ExperimentArtifactsNavbarComponent
|
||||
} from '@common/experiments/dumb/experiment-artifacts-navbar/experiment-artifacts-navbar.component';
|
||||
import {ExperimentOperationsLogComponent} from '@common/experiments/dumb/experiment-operations-log/experiment-operations-log.component';
|
||||
import {ExperimentArtifactsNavbarComponent} from '@common/experiments/dumb/experiment-artifacts-navbar/experiment-artifacts-navbar.component';
|
||||
import {CommonDeleteDialogModule} from '@common/shared/entity-page/entity-delete/common-delete-dialog.module';
|
||||
import {MatIcon} from '@angular/material/icon';
|
||||
import {MatButton, MatIconButton} from '@angular/material/button';
|
||||
import {GraphSettingsBarComponent} from '@common/shared/experiment-graphs/graph-settings-bar/graph-settings-bar.component';
|
||||
import {MatSlideToggle} from '@angular/material/slide-toggle';
|
||||
import {ExperimentDetailsComponent} from '@common/experiments/dumb/experiment-details/experiment-details.component';
|
||||
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
FormsModule,
|
||||
LayoutModule,
|
||||
ReactiveFormsModule,
|
||||
CommonModule,
|
||||
ExperimentRouterModule,
|
||||
ExperimentSharedModule,
|
||||
ExperimentGraphsModule,
|
||||
SelectModelModule,
|
||||
DebugImagesModule,
|
||||
ExperimentCompareSharedModule,
|
||||
MatSidenavModule,
|
||||
MatListModule,
|
||||
AngularSplitModule,
|
||||
ScrollingModule,
|
||||
RouterModule,
|
||||
SharedModule,
|
||||
ExperimentOutputLogModule,
|
||||
MatProgressSpinnerModule,
|
||||
MatRadioModule,
|
||||
RouterTabNavBarComponent,
|
||||
MatTabsModule,
|
||||
RouterTabNavBarComponent,
|
||||
OverlayComponent,
|
||||
RefreshButtonComponent,
|
||||
InfoHeaderStatusIconLabelComponent,
|
||||
NAPipe,
|
||||
SortPipe,
|
||||
safeAngularUrlParameterPipe,
|
||||
ReplaceViaMapPipe,
|
||||
FilterOutPipe,
|
||||
DurationPipe,
|
||||
FilterInternalPipe,
|
||||
FileSizePipe,
|
||||
HideRedactedArgumentsPipe,
|
||||
MenuItemComponent,
|
||||
CopyClipboardComponent,
|
||||
SectionHeaderComponent,
|
||||
InlineEditComponent,
|
||||
TagsMenuComponent,
|
||||
EntityFooterComponent,
|
||||
MenuComponent,
|
||||
ExperimentTypeIconLabelComponent,
|
||||
SearchComponent,
|
||||
IdBadgeComponent,
|
||||
ScrollTextareaComponent,
|
||||
TagListComponent,
|
||||
TooltipDirective,
|
||||
LabeledRowComponent,
|
||||
EditableSectionComponent,
|
||||
SelectableGroupedFilterListComponent,
|
||||
MatMenuModule,
|
||||
MatExpansionModule,
|
||||
MatInputModule,
|
||||
MatSelectModule,
|
||||
HesitateDirective,
|
||||
ShowTooltipIfEllipsisDirective,
|
||||
SelectQueueModule,
|
||||
PushPipe,
|
||||
ExperimentHeaderComponent,
|
||||
ExperimentOperationsLogComponent,
|
||||
ExperimentArtifactsNavbarComponent,
|
||||
CommonDeleteDialogModule,
|
||||
MatIcon,
|
||||
MatButton,
|
||||
MatIconButton
|
||||
],
|
||||
imports: [
|
||||
MatTabsModule,
|
||||
MatMenuModule,
|
||||
MatExpansionModule,
|
||||
MatInputModule,
|
||||
MatSelectModule,
|
||||
MatSlideToggle,
|
||||
MatButton,
|
||||
MatIcon,
|
||||
MatIconButton,
|
||||
MatListModule,
|
||||
MatRadioModule,
|
||||
MatSidenavModule,
|
||||
MatProgressSpinnerModule,
|
||||
FormsModule,
|
||||
LayoutModule,
|
||||
ReactiveFormsModule,
|
||||
CommonModule,
|
||||
ExperimentRouterModule,
|
||||
ExperimentGraphsModule,
|
||||
SelectModelModule,
|
||||
DebugImagesModule,
|
||||
ExperimentCompareSharedModule,
|
||||
AngularSplitModule,
|
||||
ScrollingModule,
|
||||
CommonDeleteDialogModule,
|
||||
RouterModule,
|
||||
ExperimentOutputLogModule,
|
||||
ExperimentSharedModule,
|
||||
RouterTabNavBarComponent,
|
||||
HesitateDirective,
|
||||
NAPipe,
|
||||
SortPipe,
|
||||
safeAngularUrlParameterPipe,
|
||||
ReplaceViaMapPipe,
|
||||
FilterOutPipe,
|
||||
DurationPipe,
|
||||
FilterInternalPipe,
|
||||
FileSizePipe,
|
||||
HideRedactedArgumentsPipe,
|
||||
InfoHeaderStatusIconLabelComponent,
|
||||
MenuItemComponent,
|
||||
CopyClipboardComponent,
|
||||
SectionHeaderComponent,
|
||||
InlineEditComponent,
|
||||
TagsMenuComponent,
|
||||
EntityFooterComponent,
|
||||
MenuComponent,
|
||||
ExperimentTypeIconLabelComponent,
|
||||
SearchComponent,
|
||||
IdBadgeComponent,
|
||||
ScrollTextareaComponent,
|
||||
TagListComponent,
|
||||
TooltipDirective,
|
||||
LabeledRowComponent,
|
||||
EditableSectionComponent,
|
||||
SelectableGroupedFilterListComponent,
|
||||
OverlayComponent,
|
||||
RefreshButtonComponent,
|
||||
HesitateDirective,
|
||||
ShowTooltipIfEllipsisDirective,
|
||||
SelectQueueModule,
|
||||
PushPipe,
|
||||
ExperimentHeaderComponent,
|
||||
ExperimentOperationsLogComponent,
|
||||
ExperimentArtifactsNavbarComponent,
|
||||
GraphSettingsBarComponent,
|
||||
],
|
||||
declarations: [
|
||||
ExperimentsComponent,
|
||||
ExperimentInfoExecutionComponent,
|
||||
ExperimentOutputComponent,
|
||||
ExperimentInfoExecutionComponent,
|
||||
ExperimentInfoNavbarComponent,
|
||||
ExperimentsComponent,
|
||||
BaseClickableArtifactComponent,
|
||||
ExperimentInfoHeaderComponent,
|
||||
ExperimentInfoModelComponent,
|
||||
ExperimentInfoTaskModelComponent,
|
||||
ExperimentInfoGeneralComponent,
|
||||
ExperimentGeneralInfoComponent,
|
||||
ExperimentDetailsComponent,
|
||||
ExperimentModelsFormViewComponent,
|
||||
ExperimentOutputModelViewComponent,
|
||||
ExperimentExecutionSourceCodeComponent,
|
||||
|
||||
@@ -4,10 +4,11 @@ import {experimentOutputReducer, ExperimentOutputState, experimentOutputInitStat
|
||||
import {experimentsViewReducer, ExperimentsViewState, experimentsViewInitialState} from '@common/experiments/reducers/experiments-view.reducer';
|
||||
import {IExperimentInfo} from '../shared/experiment-info.model';
|
||||
import {TaskStatusEnum} from '~/business-logic/model/tasks/taskStatusEnum';
|
||||
import {selectSelectedModel} from '@common/models/reducers';
|
||||
import {selectModelId, selectSelectedModel} from '@common/models/reducers';
|
||||
import {selectCurrentUser} from '@common/core/reducers/users-reducer';
|
||||
import {isReadOnly} from '@common/shared/utils/is-read-only';
|
||||
import {isSharedAndNotOwner} from '@common/shared/utils/is-shared-and-not-owner';
|
||||
import { selectSelectedProjectId } from '@common/core/reducers/projects.reducer';
|
||||
|
||||
export interface ExperimentState {
|
||||
view: ExperimentsViewState;
|
||||
@@ -60,6 +61,12 @@ export const selectExperimentFormValidity = createSelector(selectExperimentInfoD
|
||||
return !error;
|
||||
});
|
||||
|
||||
export const selectSelectedModelSettings = createSelector(experimentOutput, selectSelectedModel,
|
||||
(output, currentModel): ExperimentSettings =>
|
||||
output.settingsList && output.settingsList.find((setting) => currentModel && setting.id === currentModel.id));
|
||||
export const selectOutputSettings = createSelector(experimentOutput, state => state.settingsList);
|
||||
export const selectSelectedModelSettings = createSelector(experimentOutput, selectModelId, selectSelectedProjectId,
|
||||
(output, modelId, projectId): Partial<ExperimentSettings> => {
|
||||
if (output.settingsList && modelId) {
|
||||
return output.settingsList.find((setting) => setting.id === modelId) ?? output.settingsList.find((setting) => setting.id === projectId) ?? {};
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -58,7 +58,6 @@ import {TableComponent} from '@common/shared/ui-components/data/table/table.comp
|
||||
import {MatSelectModule} from '@angular/material/select';
|
||||
import {ButtonToggleComponent} from '@common/shared/ui-components/inputs/button-toggle/button-toggle.component';
|
||||
import {GroupedCheckedFilterListComponent} from '@common/shared/ui-components/data/grouped-checked-filter-list/grouped-checked-filter-list.component';
|
||||
import {SelectableFilterListComponent} from '@common/shared/ui-components/data/selectable-filter-list/selectable-filter-list.component';
|
||||
import {TableCardComponent} from '@common/shared/ui-components/data/table-card/table-card.component';
|
||||
import {ToggleArchiveComponent} from '@common/shared/ui-components/buttons/toggle-archive/toggle-archive.component';
|
||||
import {RefreshButtonComponent} from '@common/shared/components/refresh-button/refresh-button.component';
|
||||
@@ -80,6 +79,10 @@ import {MatDialogActions, MatDialogClose} from '@angular/material/dialog';
|
||||
import {IsRowSelectedPipe} from '@common/shared/ui-components/data/table/is-rwo-selected.pipe';
|
||||
import {MiniTagsListComponent} from '@common/shared/ui-components/tags/user-tag/mini-tags-list/mini-tags-list.component';
|
||||
import {TableCardFilterComponent} from '@common/shared/ui-components/data/table/table-card-filter-template/table-card-filter.component';
|
||||
import {SelectableGroupedFilterListComponent} from '@common/shared/ui-components/data/selectable-grouped-filter-list/selectable-grouped-filter-list.component';
|
||||
import {JsonIndentPipe} from '@common/experiments/dumb/experiment-execution-parameters/json-indent.pipe';
|
||||
import {MultiLineTooltipComponent} from '@common/shared/components/multi-line-tooltip/multi-line-tooltip.component';
|
||||
import {MatDivider} from '@angular/material/divider';
|
||||
|
||||
export const experimentSyncedKeys = [
|
||||
'view.projectColumnsSortOrder',
|
||||
@@ -178,7 +181,6 @@ const DECLARATIONS = [
|
||||
MatSelectModule,
|
||||
ButtonToggleComponent,
|
||||
GroupedCheckedFilterListComponent,
|
||||
SelectableFilterListComponent,
|
||||
TableCardComponent,
|
||||
ToggleArchiveComponent,
|
||||
RefreshButtonComponent,
|
||||
@@ -203,6 +205,10 @@ const DECLARATIONS = [
|
||||
MiniTagsListComponent,
|
||||
TableCardFilterComponent,
|
||||
ReactiveFormsModule,
|
||||
SelectableGroupedFilterListComponent,
|
||||
JsonIndentPipe,
|
||||
MultiLineTooltipComponent,
|
||||
MatDivider,
|
||||
],
|
||||
declarations : [...DECLARATIONS],
|
||||
providers : [
|
||||
|
||||
@@ -1,18 +1,12 @@
|
||||
import {Model} from '../../../business-logic/model/models/model';
|
||||
import {ISelectedExperiment} from './experiment-info.model';
|
||||
import {isExample} from '../../../webapp-common/shared/utils/shared-utils';
|
||||
import {isExample} from '@common/shared/utils/shared-utils';
|
||||
import {ExperimentTagsEnum} from '~/features/experiments/shared/experiments.const';
|
||||
|
||||
|
||||
export function areLabelsEqualss(modelLabels: Model['labels'], labels: Model['labels']) {
|
||||
return true;
|
||||
}
|
||||
|
||||
export function isDevelopment(entity): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
export function getSystemTags(experiment: ISelectedExperiment) {
|
||||
export function getSystemTags(experiment: {system_tags?: string[]}) {
|
||||
const ignoredTags: string[] = [ExperimentTagsEnum.Hidden, ExperimentTagsEnum.Development];
|
||||
ignoredTags.push(ExperimentTagsEnum.Pipeline, ExperimentTagsEnum.Dataset);
|
||||
if (experiment?.system_tags?.includes(ExperimentTagsEnum.Dataset) || experiment?.system_tags?.includes(ExperimentTagsEnum.Pipeline)) {
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import {Component, signal} from '@angular/core';
|
||||
import {ModelMenuComponent} from '../../../../webapp-common/models/containers/model-menu/model-menu.component';
|
||||
import {ModelMenuComponent} from '@common/models/containers/model-menu/model-menu.component';
|
||||
|
||||
@Component({
|
||||
selector: 'sm-model-menu-extended',
|
||||
templateUrl: '../../../../webapp-common/models/containers/model-menu/model-menu.component.html',
|
||||
styleUrls: ['../../../../webapp-common/models/containers/model-menu/model-menu.component.scss']
|
||||
styleUrls: ['../../../../webapp-common/models/containers/model-menu/model-menu.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class ModelMenuExtendedComponent extends ModelMenuComponent {
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'sm-not-found',
|
||||
templateUrl: './not-found.component.html',
|
||||
styleUrls: ['./not-found.component.scss']
|
||||
selector: 'sm-not-found',
|
||||
templateUrl: './not-found.component.html',
|
||||
styleUrls: ['./not-found.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class NotFoundComponent implements OnInit {
|
||||
|
||||
|
||||
@@ -1,13 +1,19 @@
|
||||
import {Component} from '@angular/core';
|
||||
import {ProjectCardMenuComponent} from '@common/shared/ui-components/panel/project-card-menu/project-card-menu.component';
|
||||
import {MenuItemComponent} from '@common/shared/ui-components/panel/menu-item/menu-item.component';
|
||||
import {MenuComponent} from '@common/shared/ui-components/panel/menu/menu.component';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'sm-project-card-menu-extended',
|
||||
templateUrl: '../../../../webapp-common/shared/ui-components/panel/project-card-menu/project-card-menu.component.html',
|
||||
styleUrls: ['../../../../webapp-common/shared/ui-components/panel/project-card-menu/project-card-menu.component.scss']
|
||||
styleUrls: ['../../../../webapp-common/shared/ui-components/panel/project-card-menu/project-card-menu.component.scss'],
|
||||
imports: [
|
||||
MenuItemComponent,
|
||||
MenuComponent,
|
||||
]
|
||||
})
|
||||
export class ProjectCardMenuExtendedComponent extends ProjectCardMenuComponent{
|
||||
export class ProjectCardMenuExtendedComponent extends ProjectCardMenuComponent {
|
||||
set contextMenu(data) {}
|
||||
get contextMenu() {
|
||||
return this;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import {NgModule} from '@angular/core';
|
||||
import {CommonModule} from '@angular/common';
|
||||
import {FormsModule, ReactiveFormsModule} from '@angular/forms';
|
||||
import {ProjectCardMenuExtendedComponent} from '~/features/projects/containers/project-card-menu-extended/project-card-menu-extended.component';
|
||||
import {ProjectCardMenuComponent} from '@common/shared/ui-components/panel/project-card-menu/project-card-menu.component';
|
||||
import {PipelineCardMenuComponent} from '@common/pipelines/pipeline-card-menu/pipeline-card-menu.component';
|
||||
import {ScrollingModule} from '@angular/cdk/scrolling';
|
||||
@@ -36,11 +35,13 @@ import {DotsLoadMoreComponent} from '@common/shared/ui-components/indicators/dot
|
||||
import {MatTab, MatTabGroup} from '@angular/material/tabs';
|
||||
import {MatIcon} from '@angular/material/icon';
|
||||
import {MatIconButton} from '@angular/material/button';
|
||||
import {CommonSearchComponent} from '@common/common-search/containers/common-search/common-search.component';
|
||||
import {PushPipe} from '@ngrx/component';
|
||||
|
||||
const _declarations = [
|
||||
ProjectCardMenuExtendedComponent,
|
||||
PipelineCardMenuComponent,
|
||||
PipelinesEmptyStateComponent,
|
||||
NestedCardComponent,
|
||||
PipelineCardMenuComponent,
|
||||
DatasetEmptyComponent,
|
||||
NestedProjectViewPageComponent,
|
||||
ProjectsHeaderComponent
|
||||
@@ -73,14 +74,16 @@ const _declarations = [
|
||||
TooltipDirective,
|
||||
ButtonToggleComponent,
|
||||
ShowTooltipIfEllipsisDirective,
|
||||
PushPipe,
|
||||
DotsLoadMoreComponent,
|
||||
MatTabGroup,
|
||||
MatTab,
|
||||
MatIconButton,
|
||||
MatIcon,
|
||||
MatIconButton
|
||||
CommonSearchComponent
|
||||
],
|
||||
declarations: [..._declarations, PipelinesEmptyStateComponent],
|
||||
exports: [..._declarations, PipelinesEmptyStateComponent]
|
||||
declarations: [..._declarations],
|
||||
exports: [..._declarations]
|
||||
})
|
||||
export class ProjectsSharedModule {
|
||||
}
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
<div class="no-data-center">
|
||||
<mat-icon fontSet="al" fontIcon="al-ico-model-endpoints" class="xxxl"></mat-icon>
|
||||
<span class="message">MODEL ENDPOINTS WILL APPEAR HERE</span>
|
||||
<span class="sub-message">
|
||||
Monitor models deployed with <a href="https://github.com/allegroai/clearml-serving" target="_blank">clearml-serving</a>
|
||||
or the <a href="https://github.com/allegroai/clearml" target="_blank">ClearML</a> HttpRouter class
|
||||
</span>
|
||||
<mat-icon fontSet="al" fontIcon="al-ico-model-endpoints" class="xxl"></mat-icon>
|
||||
@if (isLoading()) {
|
||||
<span class="message">NO MODEL ENDPOINTS CURRENTLY BEING SET UP</span>
|
||||
} @else {
|
||||
<span class="message">NO ACTIVE MODEL ENDPOINTS</span>
|
||||
<span class="sub-message">Monitor models deployed with <a href="https://github.com/allegroai/clearml-serving" target="_blank">
|
||||
clearml-serving</a>
|
||||
or the <a href="https://github.com/allegroai/clearml" target="_blank">ClearML</a> HttpRouter class
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -8,14 +8,11 @@ a[href]:hover {
|
||||
justify-content: center;
|
||||
gap: 24px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.al-icon {
|
||||
color: var(--color-tint-14);
|
||||
color: var(--color-empty-state);
|
||||
}
|
||||
|
||||
.message {
|
||||
font-size: 20px;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
import { Component } from '@angular/core';
|
||||
import {RouterLink} from '@angular/router';
|
||||
import {MatIcon} from '@angular/material/icon';
|
||||
import {ChangeDetectionStrategy, Component, input} from '@angular/core';
|
||||
import { MatIcon } from '@angular/material/icon';
|
||||
|
||||
@Component({
|
||||
selector: 'sm-serving-empty-state',
|
||||
standalone: true,
|
||||
imports: [
|
||||
RouterLink,
|
||||
MatIcon
|
||||
],
|
||||
templateUrl: './serving-empty-state.component.html',
|
||||
styleUrl: './serving-empty-state.component.scss'
|
||||
selector: 'sm-serving-empty-state',
|
||||
imports: [
|
||||
MatIcon
|
||||
],
|
||||
templateUrl: './serving-empty-state.component.html',
|
||||
styleUrl: './serving-empty-state.component.scss',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class ServingEmptyStateComponent {
|
||||
|
||||
isLoading = input<boolean>(false);
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ import {Component} from '@angular/core';
|
||||
@Component({
|
||||
selector: 'sm-admin-footer-actions',
|
||||
templateUrl: './admin-footer-actions.component.html',
|
||||
styleUrls: ['./admin-footer-actions.component.scss']
|
||||
styleUrls: ['./admin-footer-actions.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class AdminFooterActionsComponent {
|
||||
constructor() { }
|
||||
}
|
||||
|
||||
@@ -8,15 +8,14 @@ import {DialogTemplateComponent} from '@common/shared/ui-components/overlay/dial
|
||||
import {AdminDialogTemplateComponent} from '@common/settings/admin/admin-dialog-template/admin-dialog-template.component';
|
||||
|
||||
@Component({
|
||||
selector: 'sm-create-credential-dialog',
|
||||
templateUrl: './create-credential-dialog.component.html',
|
||||
styleUrls: ['./create-credential-dialog.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone: true,
|
||||
imports: [
|
||||
DialogTemplateComponent,
|
||||
AdminDialogTemplateComponent
|
||||
]
|
||||
selector: 'sm-create-credential-dialog',
|
||||
templateUrl: './create-credential-dialog.component.html',
|
||||
styleUrls: ['./create-credential-dialog.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [
|
||||
DialogTemplateComponent,
|
||||
AdminDialogTemplateComponent
|
||||
]
|
||||
})
|
||||
export class CreateCredentialDialogComponent {
|
||||
private store = inject(Store);
|
||||
|
||||
@@ -7,13 +7,12 @@ import {ConfigurationService} from '@common/shared/services/configuration.servic
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'sm-usage-stats',
|
||||
templateUrl: './usage-stats.component.html',
|
||||
styleUrls: ['./usage-stats.component.scss'],
|
||||
imports: [
|
||||
MatSlideToggle
|
||||
],
|
||||
standalone: true
|
||||
selector: 'sm-usage-stats',
|
||||
templateUrl: './usage-stats.component.html',
|
||||
styleUrls: ['./usage-stats.component.scss'],
|
||||
imports: [
|
||||
MatSlideToggle
|
||||
]
|
||||
})
|
||||
export class UsageStatsComponent {
|
||||
private store = inject(Store);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<header>
|
||||
<div class="title">
|
||||
API credentials
|
||||
API CREDENTIALS
|
||||
<mat-icon
|
||||
class="info sm"
|
||||
fontSet="al" fontIcon="al-ico-info-circle"
|
||||
|
||||
@@ -12,11 +12,12 @@ import {CreateCredentialDialogComponent} from '~/features/settings/containers/ad
|
||||
@Component({
|
||||
selector: 'sm-user-credentials',
|
||||
templateUrl: './user-credentials.component.html',
|
||||
styleUrls: ['./user-credentials.component.scss']
|
||||
styleUrls: ['./user-credentials.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class UserCredentialsComponent implements OnInit, OnDestroy {
|
||||
|
||||
public credentials$: Observable<{ [workspaceId: string]: CredentialKeyExt[] }>;
|
||||
public credentials$: Observable<Record<string, CredentialKeyExt[]>>;
|
||||
private newCredentialSub: Subscription;
|
||||
creatingCredentials = false;
|
||||
private user: GetCurrentUserResponseUserObject;
|
||||
|
||||
@@ -3,7 +3,8 @@ import {Component, input} from '@angular/core';
|
||||
@Component({
|
||||
selector: 'sm-user-data',
|
||||
templateUrl: './user-data.component.html',
|
||||
styleUrls: ['./user-data.component.scss']
|
||||
styleUrls: ['./user-data.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class UserDataComponent {
|
||||
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
<section>
|
||||
<header>
|
||||
<div class="title">USER PREFERENCES</div>
|
||||
</header>
|
||||
<main class="main">
|
||||
<sm-profile-preferences></sm-profile-preferences>
|
||||
<sm-profile-key-storage></sm-profile-key-storage>
|
||||
</main>
|
||||
</section>
|
||||
<header>
|
||||
<div class="title">USER PREFERENCES</div>
|
||||
</header>
|
||||
<main class="main">
|
||||
<sm-profile-preferences class="section"></sm-profile-preferences>
|
||||
<sm-profile-key-storage></sm-profile-key-storage>
|
||||
</main>
|
||||
|
||||
@@ -1,21 +1,24 @@
|
||||
@import 'variables';
|
||||
@use '../layout/layout';
|
||||
|
||||
:host {
|
||||
header {
|
||||
padding: 20px 24px;
|
||||
}
|
||||
display: block;
|
||||
height: 100%;
|
||||
padding-bottom: 12px;
|
||||
|
||||
.main {
|
||||
padding: 0 24px;
|
||||
}
|
||||
|
||||
.section {
|
||||
margin: 6px 0 24px;
|
||||
padding-bottom: 12px;
|
||||
display: grid;
|
||||
grid-template-rows: auto minmax(0, 1fr);
|
||||
height: calc(100% - 64px);
|
||||
padding-left: 24px;
|
||||
}
|
||||
|
||||
.title {
|
||||
color: $white;
|
||||
color: var(--color-on-primary-container);
|
||||
font-size: 16px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0 24px;
|
||||
height: layout.$project-header-height;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,14 +3,13 @@ import {ProfilePreferencesComponent} from '@common/settings/admin/profile-prefer
|
||||
import {ProfileKeyStorageComponent} from '@common/settings/admin/profile-key-storage/profile-key-storage.component';
|
||||
|
||||
@Component({
|
||||
selector: 'sm-webapp-configuration',
|
||||
standalone: true,
|
||||
imports: [
|
||||
ProfilePreferencesComponent,
|
||||
ProfileKeyStorageComponent,
|
||||
],
|
||||
templateUrl: './webapp-configuration.component.html',
|
||||
styleUrl: './webapp-configuration.component.scss'
|
||||
selector: 'sm-webapp-configuration',
|
||||
imports: [
|
||||
ProfilePreferencesComponent,
|
||||
ProfileKeyStorageComponent,
|
||||
],
|
||||
templateUrl: './webapp-configuration.component.html',
|
||||
styleUrl: './webapp-configuration.component.scss'
|
||||
})
|
||||
export class WebappConfigurationComponent {
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ const routes: Routes = [
|
||||
workspaceNeutral: true,
|
||||
route: '/settings/storage-credentials',
|
||||
staticBreadcrumb: [[settingsBreadcrumb, {
|
||||
name: 'Storage Credentials',
|
||||
name: 'Storage Cleanup',
|
||||
type: CrumbTypeEnum.SubFeature
|
||||
}]]
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<mat-drawer-container class="settings-container">
|
||||
<mat-drawer mode="side" opened>
|
||||
<mat-list class="pointer" style="padding-top: 24px;">
|
||||
<mat-list-item routerLinkActive="active" routerLink="profile"> Profile </mat-list-item>
|
||||
<mat-list-item routerLinkActive="active" routerLink="webapp-configuration"> Configuration </mat-list-item>
|
||||
<mat-list-item routerLinkActive="active" routerLink="workspace-configuration"> Workspace </mat-list-item>
|
||||
<mat-list-item routerLinkActive="active" routerLink="storage-credentials"> Storage Credentials </mat-list-item>
|
||||
<mat-list-item routerLinkActive="active" routerLink="profile">Profile</mat-list-item>
|
||||
<mat-list-item routerLinkActive="active" routerLink="webapp-configuration">Configuration</mat-list-item>
|
||||
<mat-list-item routerLinkActive="active" routerLink="workspace-configuration">Workspace</mat-list-item>
|
||||
<mat-list-item routerLinkActive="active" routerLink="storage-credentials">Storage Cleanup</mat-list-item>
|
||||
</mat-list>
|
||||
</mat-drawer>
|
||||
<mat-drawer-content>
|
||||
|
||||
@@ -3,7 +3,9 @@ import {Component} from '@angular/core';
|
||||
@Component({
|
||||
selector: 'sm-settings',
|
||||
templateUrl: './settings.component.html',
|
||||
styleUrls: ['../../webapp-common/settings/settings.component.scss']
|
||||
styleUrls: ['../../webapp-common/settings/settings.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class SettingsComponent {
|
||||
|
||||
}
|
||||
|
||||
@@ -50,10 +50,10 @@ import {settingsFeatureKey, settingsReducers} from '~/features/settings/settings
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
SettingsComponent,
|
||||
UserDataComponent,
|
||||
UserCredentialsComponent,
|
||||
AdminFooterActionsComponent,
|
||||
UserDataComponent,
|
||||
SettingsComponent,
|
||||
UserCredentialsComponent,
|
||||
AdminCredentialTableComponent,
|
||||
AdminFooterComponent,
|
||||
ProfileNameComponent,
|
||||
|
||||
@@ -9,7 +9,8 @@ import {takeUntilDestroyed} from '@angular/core/rxjs-interop';
|
||||
@Component({
|
||||
selector: 'sm-orchestration',
|
||||
templateUrl: './orchestration.component.html',
|
||||
styleUrls: ['./orchestration.component.scss']
|
||||
styleUrls: ['./orchestration.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class OrchestrationComponent {
|
||||
private store = inject(Store);
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import {Component} from '@angular/core';
|
||||
import {QueuesMenuComponent} from '../../../webapp-common/workers-and-queues/dumb/queues-menu/queues-menu.component';
|
||||
import {QueuesMenuComponent} from '@common/workers-and-queues/dumb/queues-menu/queues-menu.component';
|
||||
|
||||
@Component({
|
||||
selector: 'sm-queues-menu-extended',
|
||||
templateUrl: '../../../webapp-common/workers-and-queues/dumb/queues-menu/queues-menu.component.html',
|
||||
styleUrls: ['../../../webapp-common/workers-and-queues/dumb/queues-menu/queues-menu.component.scss']
|
||||
styleUrls: ['../../../webapp-common/workers-and-queues/dumb/queues-menu/queues-menu.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class QueuesMenuExtendedComponent extends QueuesMenuComponent{
|
||||
set contextMenu(data) {}
|
||||
|
||||
@@ -4,7 +4,8 @@ import {WorkersComponent} from '@common/workers-and-queues/containers/workers/wo
|
||||
import {QueuesComponent} from '@common/workers-and-queues/containers/queues/queues.component';
|
||||
import {WorkersAndQueuesResolver} from '~/shared/resolvers/workers-and-queues.resolver';
|
||||
import {CrumbTypeEnum} from '@common/layout/breadcrumbs/breadcrumbs.component';
|
||||
import {OrchestrationComponent} from "~/features/workers-and-queues/orchestration.component";
|
||||
import {OrchestrationComponent} from '~/features/workers-and-queues/orchestration.component';
|
||||
import {resetContextMenuGuard} from '@common/shared/guards/resetContextMenuGuard.guard';
|
||||
|
||||
const wQBreadcrumb = [[{
|
||||
name: 'WORKERS AND QUEUES',
|
||||
@@ -14,6 +15,7 @@ export const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: OrchestrationComponent,
|
||||
canDeactivate: [resetContextMenuGuard],
|
||||
resolve: {
|
||||
queuesManager: WorkersAndQueuesResolver
|
||||
},
|
||||
|
||||
@@ -110,7 +110,6 @@ import {MatButton, MatIconButton} from '@angular/material/button';
|
||||
QueuesMenuComponent,
|
||||
QueuesMenuExtendedComponent
|
||||
],
|
||||
|
||||
})
|
||||
export class WorkersAndQueuesModule {
|
||||
}
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import {Component} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'sm-header-user-menu-actions',
|
||||
templateUrl: './header-user-menu-actions.component.html',
|
||||
styleUrls: ['./header-user-menu-actions.component.scss']
|
||||
selector: 'sm-header-user-menu-actions',
|
||||
templateUrl: './header-user-menu-actions.component.html',
|
||||
styleUrls: ['./header-user-menu-actions.component.scss'],
|
||||
})
|
||||
export class HeaderUserMenuActionsComponent {
|
||||
|
||||
constructor() {}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,8 @@ import {MAT_TOOLTIP_DEFAULT_OPTIONS, MatTooltipDefaultOptions} from '@angular/ma
|
||||
provide: MAT_TOOLTIP_DEFAULT_OPTIONS,
|
||||
useValue: {showDelay: 0, position: 'right'} as MatTooltipDefaultOptions
|
||||
},
|
||||
]
|
||||
],
|
||||
standalone: false
|
||||
})
|
||||
export class SideNavComponent {
|
||||
public store = inject(Store);
|
||||
|
||||
@@ -32,7 +32,7 @@ export const EXPERIMENTS_STATUS_LABELS = {
|
||||
[TaskStatusEnum.Completed] : 'Completed',
|
||||
[TaskStatusEnum.Published] : 'Published',
|
||||
[TaskStatusEnum.Failed] : 'Failed',
|
||||
[TaskStatusEnum.Stopped] : 'Completed',
|
||||
[TaskStatusEnum.Stopped] : 'Aborted',
|
||||
[TaskStatusEnum.Closed] : 'Closed',
|
||||
[TaskTypeEnum.Testing] : 'Testing',
|
||||
[TaskTypeEnum.Training] : 'Training',
|
||||
|
||||
@@ -23,12 +23,13 @@ import {NotifierNotificationComponent} from './notifier-notification.component';
|
||||
* strategy onPush, which means that we handle change detection manually in order to get the best performance. (#perfmatters)
|
||||
*/
|
||||
@Component({
|
||||
changeDetection: ChangeDetectionStrategy.OnPush, // (#perfmatters)
|
||||
host: {
|
||||
class: 'notifier__container'
|
||||
},
|
||||
selector: 'notifier-container',
|
||||
templateUrl: './notifier-container.component.html'
|
||||
changeDetection: ChangeDetectionStrategy.OnPush, // (#perfmatters)
|
||||
host: {
|
||||
class: 'notifier__container'
|
||||
},
|
||||
selector: 'notifier-container',
|
||||
templateUrl: './notifier-container.component.html',
|
||||
standalone: false
|
||||
})
|
||||
export class NotifierContainerComponent implements OnDestroy, OnInit {
|
||||
|
||||
|
||||
@@ -16,20 +16,21 @@ import {NotifierTimerService} from '../services/notifier-timer.service';
|
||||
* mouse movements.
|
||||
*/
|
||||
@Component({
|
||||
changeDetection: ChangeDetectionStrategy.OnPush, // (#perfmatters)
|
||||
host: {
|
||||
'(click)': 'onNotificationClick()',
|
||||
'(mouseout)': 'onNotificationMouseout()',
|
||||
'(mouseover)': 'onNotificationMouseover()',
|
||||
class: 'notifier__notification'
|
||||
},
|
||||
providers: [
|
||||
// We provide the timer to the component's local injector, so that every notification components gets its own
|
||||
// instance of the timer service, thus running their timers independently from each other
|
||||
NotifierTimerService
|
||||
],
|
||||
selector: 'notifier-notification',
|
||||
templateUrl: './notifier-notification.component.html'
|
||||
changeDetection: ChangeDetectionStrategy.OnPush, // (#perfmatters)
|
||||
host: {
|
||||
'(click)': 'onNotificationClick()',
|
||||
'(mouseout)': 'onNotificationMouseout()',
|
||||
'(mouseover)': 'onNotificationMouseover()',
|
||||
class: 'notifier__notification'
|
||||
},
|
||||
providers: [
|
||||
// We provide the timer to the component's local injector, so that every notification components gets its own
|
||||
// instance of the timer service, thus running their timers independently from each other
|
||||
NotifierTimerService
|
||||
],
|
||||
selector: 'notifier-notification',
|
||||
templateUrl: './notifier-notification.component.html',
|
||||
standalone: false
|
||||
})
|
||||
export class NotifierNotificationComponent implements AfterViewInit {
|
||||
|
||||
|
||||
@@ -8,14 +8,14 @@
|
||||
// We do *NOT* use the partial syntax, and also explicitely write out the file type, so compiling works properly.
|
||||
|
||||
// Core
|
||||
@import "styles/core";
|
||||
@forward "styles/core";
|
||||
|
||||
// Themes
|
||||
@import "styles/themes/theme-material";
|
||||
@forward "styles/themes/theme-material";
|
||||
|
||||
// Types
|
||||
@import "styles/types/type-default";
|
||||
@import "styles/types/type-error";
|
||||
@import "styles/types/type-info";
|
||||
@import "styles/types/type-success";
|
||||
@import "styles/types/type-warning";
|
||||
@forward "styles/types/type-default";
|
||||
@forward "styles/types/type-error";
|
||||
@forward "styles/types/type-info";
|
||||
@forward "styles/types/type-success";
|
||||
@forward "styles/types/type-warning";
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
.notifier {
|
||||
|
||||
&__container {
|
||||
ul {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
|
||||
@@ -18,6 +18,9 @@ $notifier-shadow-color: rgba(0, 0, 0, .2) !default;
|
||||
&--warning {
|
||||
border-left-color: var(--color-warning);
|
||||
}
|
||||
&--warn {
|
||||
border-left-color: var(--color-warning);
|
||||
}
|
||||
&--error {
|
||||
border-left-color: var(--color-failed);
|
||||
}
|
||||
|
||||
@@ -1,301 +1,309 @@
|
||||
@use "sass:string";
|
||||
$icomoon-font-family: "trains" !default;
|
||||
$icomoon-font-path: "fonts" !default;
|
||||
|
||||
$al-ico-enterprise-rocket: unquote('"\\ea19"');
|
||||
$al-ico-no-data-table: unquote('"\\ea18"');
|
||||
$al-ico-palette: unquote('"\\e900"');
|
||||
$al-ico-log: unquote('"\\ea16"');
|
||||
$al-ico-debug-samples: unquote('"\\ea15"');
|
||||
$al-ico-artifacts: unquote('"\\ea14"');
|
||||
$al-ico-close-circle: unquote('"\\ea13"');
|
||||
$al-ico-bullhorn: unquote('"\\ea12"');
|
||||
$al-ico-view-horizontal: unquote('"\\ea11"');
|
||||
$al-ico-model-endpoints: unquote('"\\ea08"');
|
||||
$al-ico-vm: unquote('"\\ea0c"');
|
||||
$al-ico-retry: unquote('"\\ea07"');
|
||||
$al-ico-link-off: unquote('"\\ea05"');
|
||||
$al-ico-policy: unquote('"\\e9d5"');
|
||||
$al-ico-info-group: unquote('"\\e944"');
|
||||
$al-ico-advanced-filters: unquote('"\\e911"');
|
||||
$al-ico-triggers-scheduled: unquote('"\\ea06"');
|
||||
$al-ico-queue: unquote('"\\ea01"');
|
||||
$al-ico-link-plus: unquote('"\\ea02"');
|
||||
$al-ico-drag-vertical: unquote('"\\ea03"');
|
||||
$al-ico-drag-horizontal: unquote('"\\ea04"');
|
||||
$al-ico-admin-support: unquote('"\\ea00"');
|
||||
$al-ico-scatter-view: unquote('"\\e9ff"');
|
||||
$al-ico-schedulers: unquote('"\\e9fb"');
|
||||
$al-ico-triggers: unquote('"\\e9fc"');
|
||||
$al-ico-autoscalers: unquote('"\\e9fd"');
|
||||
$al-ico-automation: unquote('"\\e9fe"');
|
||||
$al-ico-charts-view: unquote('"\\e9f9"');
|
||||
$al-ico-compact-view: unquote('"\\e9fa"');
|
||||
$al-ico-tune: unquote('"\\e9f8"');
|
||||
$al-ico-equal-outline: unquote('"\\e9f7"');
|
||||
$al-ico-maximize: unquote('"\\e9f6"');
|
||||
$al-ico-gpu-card: unquote('"\\e9f4"');
|
||||
$al-ico-legend: unquote('"\\e9f3"');
|
||||
$al-ico-model-filled: unquote('"\\e9f2"');
|
||||
$al-ico-type-report: unquote('"\\e9f1"');
|
||||
$al-ico-info-circle-outline: unquote('"\\e9f0"');
|
||||
$al-ico-ghost: unquote('"\\e9ef"');
|
||||
$al-ico-flat-view: unquote('"\\e9ee"');
|
||||
$al-ico-camera: unquote('"\\e9ed"');
|
||||
$al-ico-markdown: unquote('"\\e9ec"');
|
||||
$al-ico-hor-expand: unquote('"\\e9ea"');
|
||||
$al-ico-hor-minimize: unquote('"\\e9eb"');
|
||||
$al-ico-pdf: unquote('"\\e9e9"');
|
||||
$al-ico-reports: unquote('"\\e9e8"');
|
||||
$al-ico-gpu: unquote('"\\e9e7"');
|
||||
$al-ico-project-path: unquote('"\\e9e6"');
|
||||
$al-ico-tree-view: unquote('"\\e9e5"');
|
||||
$al-ico-sort-asc: unquote('"\\e9e3"');
|
||||
$al-ico-sort-desc: unquote('"\\e9e4"');
|
||||
$al-ico-grid-view: unquote('"\\e9e0"');
|
||||
$al-ico-connect: unquote('"\\e9de"');
|
||||
$al-ico-disconnect: unquote('"\\e9da"');
|
||||
$al-ico-trash-all: unquote('"\\e9d9"');
|
||||
$al-ico-drag: unquote('"\\e9d8"');
|
||||
$al-ico-py: unquote('"\\e9d7"');
|
||||
$al-ico-file: unquote('"\\e9d3"');
|
||||
$al-ico-txt: unquote('"\\e9d6"');
|
||||
$al-ico-pkl: unquote('"\\e9cd"');
|
||||
$al-ico-image: unquote('"\\e958"');
|
||||
$al-ico-zip: unquote('"\\e9ce"');
|
||||
$al-ico-code-file: unquote('"\\e9a4"');
|
||||
$al-ico-audio: unquote('"\\e9d0"');
|
||||
$al-ico-upload: unquote('"\\e9cc"');
|
||||
$al-ico-min-panel: unquote('"\\e9ca"');
|
||||
$al-ico-max-panel: unquote('"\\e9cb"');
|
||||
$al-ico-datasets: unquote('"\\e90b"');
|
||||
$al-ico-t-logo-b: unquote('"\\e908"');
|
||||
$al-ico-bars-menu: unquote('"\\e933"');
|
||||
$al-ico-home: unquote('"\\e909"');
|
||||
$al-ico-projects: unquote('"\\e90a"');
|
||||
$al-ico-queues: unquote('"\\e90c"');
|
||||
$al-ico-annotator: unquote('"\\e90d"');
|
||||
$al-ico-account: unquote('"\\e998"');
|
||||
$al-ico-compare: unquote('"\\e93f"');
|
||||
$al-ico-archive: unquote('"\\e92c"');
|
||||
$al-ico-cloud-head: unquote('"\\e9a6"');
|
||||
$al-ico-how-to: unquote('"\\e997"');
|
||||
$al-ico-compare-c: unquote('"\\e93a"');
|
||||
$al-ico-published-title: unquote('"\\e9d2"');
|
||||
$al-ico-publish: unquote('"\\e9cf"');
|
||||
$al-ico-unpublish: unquote('"\\ea0f"');
|
||||
$al-ico-published: unquote('"\\e9d1"');
|
||||
$al-ico-info: unquote('"\\e99b"');
|
||||
$al-ico-warn: unquote('"\\ea10"');
|
||||
$al-ico-settings: unquote('"\\e9e2"');
|
||||
$al-ico-trash: unquote('"\\ea0b"');
|
||||
$al-ico-arrow-from-right: unquote('"\\e92e"');
|
||||
$al-ico-arrow-from-left: unquote('"\\e92d"');
|
||||
$al-ico-arrow-to-bottom: unquote('"\\e92f"');
|
||||
$al-ico-arrow-to-top: unquote('"\\e930"');
|
||||
$al-ico-training: unquote('"\\e90e"');
|
||||
$al-ico-test: unquote('"\\ea09"');
|
||||
$al-ico-testing: unquote('"\\ea0a"');
|
||||
$al-ico-type-training: unquote('"\\ea33"');
|
||||
$al-ico-type-testing: unquote('"\\ea32"');
|
||||
$al-ico-type-data-processing: unquote('"\\ea2c"');
|
||||
$al-ico-type-qc: unquote('"\\ea30"');
|
||||
$al-ico-type-service: unquote('"\\ea31"');
|
||||
$al-ico-type-optimizer: unquote('"\\ea2f"');
|
||||
$al-ico-type-monitor: unquote('"\\ea2e"');
|
||||
$al-ico-type-inference: unquote('"\\ea2d"');
|
||||
$al-ico-type-application: unquote('"\\ea29"');
|
||||
$al-ico-type-controller: unquote('"\\ea2a"');
|
||||
$al-ico-type-custom: unquote('"\\ea2b"');
|
||||
$al-ico-how-to1: unquote('"\\e90f"');
|
||||
$al-ico-model: unquote('"\\e910"');
|
||||
$al-ico-dialog-x: unquote('"\\e980"');
|
||||
$al-ico-temp-image: unquote('"\\e912"');
|
||||
$al-ico-temp-list-alt: unquote('"\\e913"');
|
||||
$al-ico-dog: unquote('"\\e914"');
|
||||
$al-ico-alert-purple: unquote('"\\e927"');
|
||||
$al-ico-back: unquote('"\\e931"');
|
||||
$al-ico-cat: unquote('"\\e936"');
|
||||
$al-ico-clone: unquote('"\\e937"');
|
||||
$al-ico-completed: unquote('"\\e940"');
|
||||
$al-ico-data-audit: unquote('"\\e943"');
|
||||
$al-ico-download-frames: unquote('"\\e982"');
|
||||
$al-ico-dropdown-arrow: unquote('"\\e984"');
|
||||
$al-ico-ellipse-icon: unquote('"\\e986"');
|
||||
$al-ico-filter: unquote('"\\e992"');
|
||||
$al-ico-fit: unquote('"\\e995"');
|
||||
$al-ico-id: unquote('"\\e999"');
|
||||
$al-ico-info-max: unquote('"\\e99c"');
|
||||
$al-ico-info-min: unquote('"\\e99d"');
|
||||
$al-ico-keypoint: unquote('"\\e99f"');
|
||||
$al-ico-list-view: unquote('"\\e9a5"');
|
||||
$al-ico-minus: unquote('"\\e9a7"');
|
||||
$al-ico-previous: unquote('"\\e9bb"');
|
||||
$al-ico-next: unquote('"\\e9af"');
|
||||
$al-ico-plus: unquote('"\\e9b8"');
|
||||
$al-ico-polygon: unquote('"\\e9b9"');
|
||||
$al-ico-pytorch-icon: unquote('"\\e9d4"');
|
||||
$al-ico-rectangle: unquote('"\\e9db"');
|
||||
$al-ico-running: unquote('"\\e9df"');
|
||||
$al-ico-setup: unquote('"\\ea0d"');
|
||||
$al-ico-undo: unquote('"\\ea0e"');
|
||||
$al-ico-zoom-1-to-1: unquote('"\\ea25"');
|
||||
$al-ico-zoom-in: unquote('"\\ea26"');
|
||||
$al-ico-zoom-out: unquote('"\\ea27"');
|
||||
$al-ico-search: unquote('"\\e9e1"');
|
||||
$al-ico-zoom-to-fit: unquote('"\\ea28"');
|
||||
$al-ico-reset: unquote('"\\e9dd"');
|
||||
$al-ico-import: unquote('"\\e99e"');
|
||||
$al-ico-export: unquote('"\\e9b6"');
|
||||
$al-ico-between: unquote('"\\e934"');
|
||||
$al-ico-next-batch: unquote('"\\e9b0"');
|
||||
$al-ico-prev-batch: unquote('"\\e9ba"');
|
||||
$al-ico-back-to-top: unquote('"\\e932"');
|
||||
$al-ico-redo: unquote('"\\e9dc"');
|
||||
$al-ico-download: unquote('"\\e981"');
|
||||
$al-ico-edit: unquote('"\\e983"');
|
||||
$al-ico-pending: unquote('"\\e9b7"');
|
||||
$al-ico-sqr-empty: unquote('"\\e925"');
|
||||
$al-ico-success: unquote('"\\e9f5"');
|
||||
$al-ico-alert-outline: unquote('"\\e926"');
|
||||
$al-ico-github: unquote('"\\e915"');
|
||||
$al-ico-description: unquote('"\\e916"');
|
||||
$al-ico-line-expand: unquote('"\\e901"');
|
||||
$al-ico-user-logout: unquote('"\\e902"');
|
||||
$al-ico-documentation: unquote('"\\e919"');
|
||||
$al-ico-frame-rule: unquote('"\\e91a"');
|
||||
$al-ico-source-rule: unquote('"\\e91b"');
|
||||
$al-ico-get-link-dialog: unquote('"\\e91d"');
|
||||
$al-ico-iteration: unquote('"\\e91e"');
|
||||
$al-ico-mapping: unquote('"\\e91f"');
|
||||
$al-ico-labels: unquote('"\\e920"');
|
||||
$al-ico-augmentation: unquote('"\\e921"');
|
||||
$al-ico-filter-outlined: unquote('"\\e922"');
|
||||
$al-ico-input-data: unquote('"\\e923"');
|
||||
$al-ico-help-outlined: unquote('"\\e924"');
|
||||
$al-ico-email: unquote('"\\e928"');
|
||||
$al-ico-tips: unquote('"\\e929"');
|
||||
$al-ico-caret-right: unquote('"\\e92a"');
|
||||
$al-ico-currently-active: unquote('"\\e92b"');
|
||||
$al-ico-complete: unquote('"\\e92b"');
|
||||
$al-ico-access-key: unquote('"\\e935"');
|
||||
$al-ico-alert: unquote('"\\e9b3"');
|
||||
$al-ico-users: unquote('"\\e91c"');
|
||||
$al-ico-exit-archive: unquote('"\\e938"');
|
||||
$al-ico-calendar: unquote('"\\e939"');
|
||||
$al-ico-time: unquote('"\\e93b"');
|
||||
$al-ico-add: unquote('"\\e93c"');
|
||||
$al-ico-time-colon: unquote('"\\e93d"');
|
||||
$al-ico-regex: unquote('"\\e93e"');
|
||||
$al-ico-filter-on-path1: unquote('"\\e941"');
|
||||
$al-ico-filter-on-path2: unquote('"\\e942"');
|
||||
$al-ico-filter-off: unquote('"\\e945"');
|
||||
$al-ico-sort-off: unquote('"\\e946"');
|
||||
$al-ico-sort-on-down-path1: unquote('"\\e947"');
|
||||
$al-ico-sort-on-down-path2: unquote('"\\e948"');
|
||||
$al-ico-sort-on-up-path1: unquote('"\\e949"');
|
||||
$al-ico-sort-on-up-path2: unquote('"\\e94a"');
|
||||
$al-ico-arrow-left: unquote('"\\e94b"');
|
||||
$al-ico-arrow-right: unquote('"\\e94c"');
|
||||
$al-ico-step-backward: unquote('"\\e94d"');
|
||||
$al-ico-step-forward: unquote('"\\e94e"');
|
||||
$al-ico-backward: unquote('"\\e94f"');
|
||||
$al-ico-forward: unquote('"\\e950"');
|
||||
$al-ico-copy-to-clipboard: unquote('"\\e951"');
|
||||
$al-ico-card-example: unquote('"\\e952"');
|
||||
$al-ico-bold: unquote('"\\e953"');
|
||||
$al-ico-italic: unquote('"\\e954"');
|
||||
$al-ico-heading: unquote('"\\e955"');
|
||||
$al-ico-quote: unquote('"\\e956"');
|
||||
$al-ico-link: unquote('"\\e957"');
|
||||
$al-ico-code: unquote('"\\e959"');
|
||||
$al-ico-list-bulleted: unquote('"\\e95a"');
|
||||
$al-ico-list-numbered: unquote('"\\e95b"');
|
||||
$al-ico-me: unquote('"\\e95c"');
|
||||
$al-ico-team: unquote('"\\e95d"');
|
||||
$al-ico-task-desc: unquote('"\\e95e"');
|
||||
$al-ico-dots: unquote('"\\e95f"');
|
||||
$al-ico-move-to: unquote('"\\e960"');
|
||||
$al-ico-abort: unquote('"\\e961"');
|
||||
$al-ico-extend: unquote('"\\e962"');
|
||||
$al-ico-reset-exp: unquote('"\\e963"');
|
||||
$al-ico-tag: unquote('"\\e964"');
|
||||
$al-ico-shared-item: unquote('"\\e965"');
|
||||
$al-ico-restore: unquote('"\\e966"');
|
||||
$al-ico-workers: unquote('"\\e967"');
|
||||
$al-ico-dots-v-menu: unquote('"\\e96a"');
|
||||
$al-ico-d-menu-down: unquote('"\\e96b"');
|
||||
$al-ico-d-menu-up: unquote('"\\e96c"');
|
||||
$al-ico-slash: unquote('"\\e96d"');
|
||||
$al-ico-info-circle: unquote('"\\e96e"');
|
||||
$al-ico-annotate: unquote('"\\e96f"');
|
||||
$al-ico-task-desc-outline: unquote('"\\e970"');
|
||||
$al-ico-manage-queue: unquote('"\\e968"');
|
||||
$al-ico-enqueue: unquote('"\\e969"');
|
||||
$al-ico-dequeue: unquote('"\\e971"');
|
||||
$al-ico-applications: unquote('"\\e972"');
|
||||
$al-ico-ico-chevron-up: unquote('"\\e973"');
|
||||
$al-ico-ico-chevron-down: unquote('"\\e974"');
|
||||
$al-ico-no-data-graph: unquote('"\\e975"');
|
||||
$al-ico-no-scatter-graph: unquote('"\\e976"');
|
||||
$al-ico-auto-refresh-play-path1: unquote('"\\e977"');
|
||||
$al-ico-auto-refresh-play-path2: unquote('"\\e978"');
|
||||
$al-ico-auto-refresh-pause-path1: unquote('"\\e979"');
|
||||
$al-ico-auto-refresh-pause-path2: unquote('"\\e97a"');
|
||||
$al-ico-sqr-ok: unquote('"\\e97b"');
|
||||
$al-ico-sqr-cancel: unquote('"\\e97c"');
|
||||
$al-ico-queue-lg: unquote('"\\e97d"');
|
||||
$al-ico-started-lg: unquote('"\\e97e"');
|
||||
$al-ico-admin: unquote('"\\e97f"');
|
||||
$al-ico-projects-outlined: unquote('"\\e985"');
|
||||
$al-ico-datasets-outlined: unquote('"\\e987"');
|
||||
$al-ico-hide: unquote('"\\e988"');
|
||||
$al-ico-show: unquote('"\\e989"');
|
||||
$al-ico-metadata: unquote('"\\e98a"');
|
||||
$al-ico-filter-reset-path1: unquote('"\\e98b"');
|
||||
$al-ico-filter-reset-path2: unquote('"\\e98c"');
|
||||
$al-ico-version-label: unquote('"\\e98d"');
|
||||
$al-ico-plugin: unquote('"\\e98e"');
|
||||
$al-ico-abort-all: unquote('"\\e98f"');
|
||||
$al-ico-refresh: unquote('"\\e990"');
|
||||
$al-ico-rocket: unquote('"\\e991"');
|
||||
$al-ico-logout: unquote('"\\e993"');
|
||||
$al-ico-settings-alert-path1: unquote('"\\e994"');
|
||||
$al-ico-settings-alert-path2: unquote('"\\e996"');
|
||||
$al-ico-platform: unquote('"\\e99a"');
|
||||
$al-ico-creditcard: unquote('"\\e9a0"');
|
||||
$al-ico-star: unquote('"\\e9a1"');
|
||||
$al-ico-email-check: unquote('"\\e9a2"');
|
||||
$al-ico-slack: unquote('"\\e9a3"');
|
||||
$al-ico-youtube: unquote('"\\e9a8"');
|
||||
$al-ico-lock: unquote('"\\e9a9"');
|
||||
$al-ico-lock-open: unquote('"\\e9aa"');
|
||||
$al-ico-no-code: unquote('"\\e9ab"');
|
||||
$al-ico-calendar-checked: unquote('"\\e9ad"');
|
||||
$al-ico-no-source: unquote('"\\e9ae"');
|
||||
$al-ico-arrow-up: unquote('"\\e9b1"');
|
||||
$al-ico-arrow-down: unquote('"\\e9b2"');
|
||||
$al-ico-error-circle: unquote('"\\e9b4"');
|
||||
$al-ico-pipelines: unquote('"\\e9b5"');
|
||||
$al-ico-console: unquote('"\\e9bc"');
|
||||
$al-ico-link-arrow: unquote('"\\e9bf"');
|
||||
$al-ico-broken-file: unquote('"\\e9c0"');
|
||||
$al-ico-run: unquote('"\\e9c1"');
|
||||
$al-ico-table-view: unquote('"\\e9c2"');
|
||||
$al-ico-experiment-view: unquote('"\\e9c3"');
|
||||
$al-ico-code-square: unquote('"\\e9c4"');
|
||||
$al-ico-video: unquote('"\\e9c5"');
|
||||
$al-ico-less-than: unquote('"\\e9c6"');
|
||||
$al-ico-greater-than: unquote('"\\e9c7"');
|
||||
$al-ico-eye-outline: unquote('"\\e9c8"');
|
||||
$al-ico-csv: unquote('"\\e9c9"');
|
||||
$al-ico-status-draft: unquote('"\\e903"');
|
||||
$al-ico-status-published: unquote('"\\e906"');
|
||||
$al-ico-status-aborted-sec: unquote('"\\e918"');
|
||||
$al-ico-status-pending: unquote('"\\e904"');
|
||||
$al-ico-status-skipped: unquote('"\\e9bd"');
|
||||
$al-ico-status-cached: unquote('"\\e9be"');
|
||||
$al-ico-status-executed: unquote('"\\e9ac"');
|
||||
$al-ico-status-running: unquote('"\\e905"');
|
||||
$al-ico-status-failed: unquote('"\\e907"');
|
||||
$al-ico-status-aborted: unquote('"\\e917"');
|
||||
$al-ico-status-completed: unquote('"\\ea17"');
|
||||
$al-ico-app-gateway: string.unquote('"\\ea20"');
|
||||
$al-ico-distance: string.unquote('"\\ea1f"');
|
||||
$al-ico-pin: string.unquote('"\\ea1d"');
|
||||
$al-ico-pin-off: string.unquote('"\\ea1c"');
|
||||
$al-ico-nearest: string.unquote('"\\ea1e"');
|
||||
$al-ico-no-data-code: string.unquote('"\\ea1b"');
|
||||
$al-ico-no-data-markdown: string.unquote('"\\ea1a"');
|
||||
$al-ico-enterprise-rocket: string.unquote('"\\ea19"');
|
||||
$al-ico-no-data-table: string.unquote('"\\ea18"');
|
||||
$al-ico-palette: string.unquote('"\\e900"');
|
||||
$al-ico-log: string.unquote('"\\ea16"');
|
||||
$al-ico-debug-samples: string.unquote('"\\ea15"');
|
||||
$al-ico-artifacts: string.unquote('"\\ea14"');
|
||||
$al-ico-close-circle: string.unquote('"\\ea13"');
|
||||
$al-ico-bullhorn: string.unquote('"\\ea12"');
|
||||
$al-ico-view-horizontal: string.unquote('"\\ea11"');
|
||||
$al-ico-model-endpoints: string.unquote('"\\ea08"');
|
||||
$al-ico-vm: string.unquote('"\\ea0c"');
|
||||
$al-ico-retry: string.unquote('"\\ea07"');
|
||||
$al-ico-link-off: string.unquote('"\\ea05"');
|
||||
$al-ico-policy: string.unquote('"\\e9d5"');
|
||||
$al-ico-info-group: string.unquote('"\\e944"');
|
||||
$al-ico-advanced-filters: string.unquote('"\\e911"');
|
||||
$al-ico-triggers-scheduled: string.unquote('"\\ea06"');
|
||||
$al-ico-queue: string.unquote('"\\ea01"');
|
||||
$al-ico-link-plus: string.unquote('"\\ea02"');
|
||||
$al-ico-drag-vertical: string.unquote('"\\ea03"');
|
||||
$al-ico-drag-horizontal: string.unquote('"\\ea04"');
|
||||
$al-ico-admin-support: string.unquote('"\\ea00"');
|
||||
$al-ico-scatter-view: string.unquote('"\\e9ff"');
|
||||
$al-ico-schedulers: string.unquote('"\\e9fb"');
|
||||
$al-ico-triggers: string.unquote('"\\e9fc"');
|
||||
$al-ico-autoscalers: string.unquote('"\\e9fd"');
|
||||
$al-ico-automation: string.unquote('"\\e9fe"');
|
||||
$al-ico-charts-view: string.unquote('"\\e9f9"');
|
||||
$al-ico-compact-view: string.unquote('"\\e9fa"');
|
||||
$al-ico-tune: string.unquote('"\\e9f8"');
|
||||
$al-ico-equal-outline: string.unquote('"\\e9f7"');
|
||||
$al-ico-maximize: string.unquote('"\\e9f6"');
|
||||
$al-ico-gpu-card: string.unquote('"\\e9f4"');
|
||||
$al-ico-legend: string.unquote('"\\e9f3"');
|
||||
$al-ico-model-filled: string.unquote('"\\e9f2"');
|
||||
$al-ico-type-report: string.unquote('"\\e9f1"');
|
||||
$al-ico-info-circle-outline: string.unquote('"\\e9f0"');
|
||||
$al-ico-ghost: string.unquote('"\\e9ef"');
|
||||
$al-ico-flat-view: string.unquote('"\\e9ee"');
|
||||
$al-ico-camera: string.unquote('"\\e9ed"');
|
||||
$al-ico-markdown: string.unquote('"\\e9ec"');
|
||||
$al-ico-hor-expand: string.unquote('"\\e9ea"');
|
||||
$al-ico-hor-minimize: string.unquote('"\\e9eb"');
|
||||
$al-ico-pdf: string.unquote('"\\e9e9"');
|
||||
$al-ico-reports: string.unquote('"\\e9e8"');
|
||||
$al-ico-gpu: string.unquote('"\\e9e7"');
|
||||
$al-ico-project-path: string.unquote('"\\e9e6"');
|
||||
$al-ico-tree-view: string.unquote('"\\e9e5"');
|
||||
$al-ico-sort-asc: string.unquote('"\\e9e3"');
|
||||
$al-ico-sort-desc: string.unquote('"\\e9e4"');
|
||||
$al-ico-grid-view: string.unquote('"\\e9e0"');
|
||||
$al-ico-connect: string.unquote('"\\e9de"');
|
||||
$al-ico-disconnect: string.unquote('"\\e9da"');
|
||||
$al-ico-trash-all: string.unquote('"\\e9d9"');
|
||||
$al-ico-drag: string.unquote('"\\e9d8"');
|
||||
$al-ico-py: string.unquote('"\\e9d7"');
|
||||
$al-ico-file: string.unquote('"\\e9d3"');
|
||||
$al-ico-txt: string.unquote('"\\e9d6"');
|
||||
$al-ico-pkl: string.unquote('"\\e9cd"');
|
||||
$al-ico-image: string.unquote('"\\e958"');
|
||||
$al-ico-zip: string.unquote('"\\e9ce"');
|
||||
$al-ico-code-file: string.unquote('"\\e9a4"');
|
||||
$al-ico-audio: string.unquote('"\\e9d0"');
|
||||
$al-ico-upload: string.unquote('"\\e9cc"');
|
||||
$al-ico-min-panel: string.unquote('"\\e9ca"');
|
||||
$al-ico-max-panel: string.unquote('"\\e9cb"');
|
||||
$al-ico-datasets: string.unquote('"\\e90b"');
|
||||
$al-ico-t-logo-b: string.unquote('"\\e908"');
|
||||
$al-ico-bars-menu: string.unquote('"\\e933"');
|
||||
$al-ico-home: string.unquote('"\\e909"');
|
||||
$al-ico-projects: string.unquote('"\\e90a"');
|
||||
$al-ico-queues: string.unquote('"\\e90c"');
|
||||
$al-ico-annotator: string.unquote('"\\e90d"');
|
||||
$al-ico-account: string.unquote('"\\e998"');
|
||||
$al-ico-compare: string.unquote('"\\e93f"');
|
||||
$al-ico-archive: string.unquote('"\\e92c"');
|
||||
$al-ico-cloud-head: string.unquote('"\\e9a6"');
|
||||
$al-ico-how-to: string.unquote('"\\e997"');
|
||||
$al-ico-compare-c: string.unquote('"\\e93a"');
|
||||
$al-ico-published-title: string.unquote('"\\e9d2"');
|
||||
$al-ico-publish: string.unquote('"\\e9cf"');
|
||||
$al-ico-unpublish: string.unquote('"\\ea0f"');
|
||||
$al-ico-published: string.unquote('"\\e9d1"');
|
||||
$al-ico-info: string.unquote('"\\e99b"');
|
||||
$al-ico-warn: string.unquote('"\\ea10"');
|
||||
$al-ico-settings: string.unquote('"\\e9e2"');
|
||||
$al-ico-trash: string.unquote('"\\ea0b"');
|
||||
$al-ico-arrow-from-right: string.unquote('"\\e92e"');
|
||||
$al-ico-arrow-from-left: string.unquote('"\\e92d"');
|
||||
$al-ico-arrow-to-bottom: string.unquote('"\\e92f"');
|
||||
$al-ico-arrow-to-top: string.unquote('"\\e930"');
|
||||
$al-ico-training: string.unquote('"\\e90e"');
|
||||
$al-ico-test: string.unquote('"\\ea09"');
|
||||
$al-ico-testing: string.unquote('"\\ea0a"');
|
||||
$al-ico-type-training: string.unquote('"\\ea33"');
|
||||
$al-ico-type-testing: string.unquote('"\\ea32"');
|
||||
$al-ico-type-data-processing: string.unquote('"\\ea2c"');
|
||||
$al-ico-type-qc: string.unquote('"\\ea30"');
|
||||
$al-ico-type-service: string.unquote('"\\ea31"');
|
||||
$al-ico-type-optimizer: string.unquote('"\\ea2f"');
|
||||
$al-ico-type-monitor: string.unquote('"\\ea2e"');
|
||||
$al-ico-type-inference: string.unquote('"\\ea2d"');
|
||||
$al-ico-type-application: string.unquote('"\\ea29"');
|
||||
$al-ico-type-controller: string.unquote('"\\ea2a"');
|
||||
$al-ico-type-custom: string.unquote('"\\ea2b"');
|
||||
$al-ico-how-to1: string.unquote('"\\e90f"');
|
||||
$al-ico-model: string.unquote('"\\e910"');
|
||||
$al-ico-dialog-x: string.unquote('"\\e980"');
|
||||
$al-ico-temp-image: string.unquote('"\\e912"');
|
||||
$al-ico-temp-list-alt: string.unquote('"\\e913"');
|
||||
$al-ico-dog: string.unquote('"\\e914"');
|
||||
$al-ico-alert-purple: string.unquote('"\\e927"');
|
||||
$al-ico-back: string.unquote('"\\e931"');
|
||||
$al-ico-cat: string.unquote('"\\e936"');
|
||||
$al-ico-clone: string.unquote('"\\e937"');
|
||||
$al-ico-completed: string.unquote('"\\e940"');
|
||||
$al-ico-data-audit: string.unquote('"\\e943"');
|
||||
$al-ico-download-frames: string.unquote('"\\e982"');
|
||||
$al-ico-dropdown-arrow: string.unquote('"\\e984"');
|
||||
$al-ico-ellipse-icon: string.unquote('"\\e986"');
|
||||
$al-ico-filter: string.unquote('"\\e992"');
|
||||
$al-ico-fit: string.unquote('"\\e995"');
|
||||
$al-ico-id: string.unquote('"\\e999"');
|
||||
$al-ico-info-max: string.unquote('"\\e99c"');
|
||||
$al-ico-info-min: string.unquote('"\\e99d"');
|
||||
$al-ico-keypoint: string.unquote('"\\e99f"');
|
||||
$al-ico-list-view: string.unquote('"\\e9a5"');
|
||||
$al-ico-minus: string.unquote('"\\e9a7"');
|
||||
$al-ico-previous: string.unquote('"\\e9bb"');
|
||||
$al-ico-next: string.unquote('"\\e9af"');
|
||||
$al-ico-plus: string.unquote('"\\e9b8"');
|
||||
$al-ico-polygon: string.unquote('"\\e9b9"');
|
||||
$al-ico-pytorch-icon: string.unquote('"\\e9d4"');
|
||||
$al-ico-rectangle: string.unquote('"\\e9db"');
|
||||
$al-ico-running: string.unquote('"\\e9df"');
|
||||
$al-ico-setup: string.unquote('"\\ea0d"');
|
||||
$al-ico-undo: string.unquote('"\\ea0e"');
|
||||
$al-ico-zoom-1-to-1: string.unquote('"\\ea25"');
|
||||
$al-ico-zoom-in: string.unquote('"\\ea26"');
|
||||
$al-ico-zoom-out: string.unquote('"\\ea27"');
|
||||
$al-ico-search: string.unquote('"\\e9e1"');
|
||||
$al-ico-zoom-to-fit: string.unquote('"\\ea28"');
|
||||
$al-ico-reset: string.unquote('"\\e9dd"');
|
||||
$al-ico-import: string.unquote('"\\e99e"');
|
||||
$al-ico-export: string.unquote('"\\e9b6"');
|
||||
$al-ico-between: string.unquote('"\\e934"');
|
||||
$al-ico-next-batch: string.unquote('"\\e9b0"');
|
||||
$al-ico-prev-batch: string.unquote('"\\e9ba"');
|
||||
$al-ico-back-to-top: string.unquote('"\\e932"');
|
||||
$al-ico-redo: string.unquote('"\\e9dc"');
|
||||
$al-ico-download: string.unquote('"\\e981"');
|
||||
$al-ico-edit: string.unquote('"\\e983"');
|
||||
$al-ico-pending: string.unquote('"\\e9b7"');
|
||||
$al-ico-sqr-empty: string.unquote('"\\e925"');
|
||||
$al-ico-success: string.unquote('"\\e9f5"');
|
||||
$al-ico-alert-outline: string.unquote('"\\e926"');
|
||||
$al-ico-github: string.unquote('"\\e915"');
|
||||
$al-ico-description: string.unquote('"\\e916"');
|
||||
$al-ico-line-expand: string.unquote('"\\e901"');
|
||||
$al-ico-user-logout: string.unquote('"\\e902"');
|
||||
$al-ico-documentation: string.unquote('"\\e919"');
|
||||
$al-ico-frame-rule: string.unquote('"\\e91a"');
|
||||
$al-ico-source-rule: string.unquote('"\\e91b"');
|
||||
$al-ico-get-link-dialog: string.unquote('"\\e91d"');
|
||||
$al-ico-iteration: string.unquote('"\\e91e"');
|
||||
$al-ico-mapping: string.unquote('"\\e91f"');
|
||||
$al-ico-labels: string.unquote('"\\e920"');
|
||||
$al-ico-augmentation: string.unquote('"\\e921"');
|
||||
$al-ico-filter-outlined: string.unquote('"\\e922"');
|
||||
$al-ico-input-data: string.unquote('"\\e923"');
|
||||
$al-ico-help-outlined: string.unquote('"\\e924"');
|
||||
$al-ico-email: string.unquote('"\\e928"');
|
||||
$al-ico-tips: string.unquote('"\\e929"');
|
||||
$al-ico-caret-right: string.unquote('"\\e92a"');
|
||||
$al-ico-currently-active: string.unquote('"\\e92b"');
|
||||
$al-ico-complete: string.unquote('"\\e92b"');
|
||||
$al-ico-access-key: string.unquote('"\\e935"');
|
||||
$al-ico-alert: string.unquote('"\\e9b3"');
|
||||
$al-ico-users: string.unquote('"\\e91c"');
|
||||
$al-ico-exit-archive: string.unquote('"\\e938"');
|
||||
$al-ico-calendar: string.unquote('"\\e939"');
|
||||
$al-ico-time: string.unquote('"\\e93b"');
|
||||
$al-ico-add: string.unquote('"\\e93c"');
|
||||
$al-ico-time-colon: string.unquote('"\\e93d"');
|
||||
$al-ico-regex: string.unquote('"\\e93e"');
|
||||
$al-ico-filter-on-path1: string.unquote('"\\e941"');
|
||||
$al-ico-filter-on-path2: string.unquote('"\\e942"');
|
||||
$al-ico-filter-off: string.unquote('"\\e945"');
|
||||
$al-ico-sort-off: string.unquote('"\\e946"');
|
||||
$al-ico-sort-on-down-path1: string.unquote('"\\e947"');
|
||||
$al-ico-sort-on-down-path2: string.unquote('"\\e948"');
|
||||
$al-ico-sort-on-up-path1: string.unquote('"\\e949"');
|
||||
$al-ico-sort-on-up-path2: string.unquote('"\\e94a"');
|
||||
$al-ico-arrow-left: string.unquote('"\\e94b"');
|
||||
$al-ico-arrow-right: string.unquote('"\\e94c"');
|
||||
$al-ico-step-backward: string.unquote('"\\e94d"');
|
||||
$al-ico-step-forward: string.unquote('"\\e94e"');
|
||||
$al-ico-backward: string.unquote('"\\e94f"');
|
||||
$al-ico-forward: string.unquote('"\\e950"');
|
||||
$al-ico-copy-to-clipboard: string.unquote('"\\e951"');
|
||||
$al-ico-card-example: string.unquote('"\\e952"');
|
||||
$al-ico-bold: string.unquote('"\\e953"');
|
||||
$al-ico-italic: string.unquote('"\\e954"');
|
||||
$al-ico-heading: string.unquote('"\\e955"');
|
||||
$al-ico-quote: string.unquote('"\\e956"');
|
||||
$al-ico-link: string.unquote('"\\e957"');
|
||||
$al-ico-code: string.unquote('"\\e959"');
|
||||
$al-ico-list-bulleted: string.unquote('"\\e95a"');
|
||||
$al-ico-list-numbered: string.unquote('"\\e95b"');
|
||||
$al-ico-me: string.unquote('"\\e95c"');
|
||||
$al-ico-team: string.unquote('"\\e95d"');
|
||||
$al-ico-task-desc: string.unquote('"\\e95e"');
|
||||
$al-ico-dots: string.unquote('"\\e95f"');
|
||||
$al-ico-move-to: string.unquote('"\\e960"');
|
||||
$al-ico-abort: string.unquote('"\\e961"');
|
||||
$al-ico-extend: string.unquote('"\\e962"');
|
||||
$al-ico-reset-exp: string.unquote('"\\e963"');
|
||||
$al-ico-tag: string.unquote('"\\e964"');
|
||||
$al-ico-shared-item: string.unquote('"\\e965"');
|
||||
$al-ico-restore: string.unquote('"\\e966"');
|
||||
$al-ico-workers: string.unquote('"\\e967"');
|
||||
$al-ico-dots-v-menu: string.unquote('"\\e96a"');
|
||||
$al-ico-d-menu-down: string.unquote('"\\e96b"');
|
||||
$al-ico-d-menu-up: string.unquote('"\\e96c"');
|
||||
$al-ico-slash: string.unquote('"\\e96d"');
|
||||
$al-ico-info-circle: string.unquote('"\\e96e"');
|
||||
$al-ico-annotate: string.unquote('"\\e96f"');
|
||||
$al-ico-task-desc-outline: string.unquote('"\\e970"');
|
||||
$al-ico-manage-queue: string.unquote('"\\e968"');
|
||||
$al-ico-enqueue: string.unquote('"\\e969"');
|
||||
$al-ico-dequeue: string.unquote('"\\e971"');
|
||||
$al-ico-applications: string.unquote('"\\e972"');
|
||||
$al-ico-ico-chevron-up: string.unquote('"\\e973"');
|
||||
$al-ico-ico-chevron-down: string.unquote('"\\e974"');
|
||||
$al-ico-no-data-graph: string.unquote('"\\e975"');
|
||||
$al-ico-no-scatter-graph: string.unquote('"\\e976"');
|
||||
$al-ico-auto-refresh-play-path1: string.unquote('"\\e977"');
|
||||
$al-ico-auto-refresh-play-path2: string.unquote('"\\e978"');
|
||||
$al-ico-auto-refresh-pause-path1: string.unquote('"\\e979"');
|
||||
$al-ico-auto-refresh-pause-path2: string.unquote('"\\e97a"');
|
||||
$al-ico-sqr-ok: string.unquote('"\\e97b"');
|
||||
$al-ico-sqr-cancel: string.unquote('"\\e97c"');
|
||||
$al-ico-queue-lg: string.unquote('"\\e97d"');
|
||||
$al-ico-started-lg: string.unquote('"\\e97e"');
|
||||
$al-ico-admin: string.unquote('"\\e97f"');
|
||||
$al-ico-projects-outlined: string.unquote('"\\e985"');
|
||||
$al-ico-datasets-outlined: string.unquote('"\\e987"');
|
||||
$al-ico-hide: string.unquote('"\\e988"');
|
||||
$al-ico-show: string.unquote('"\\e989"');
|
||||
$al-ico-metadata: string.unquote('"\\e98a"');
|
||||
$al-ico-filter-reset-path1: string.unquote('"\\e98b"');
|
||||
$al-ico-filter-reset-path2: string.unquote('"\\e98c"');
|
||||
$al-ico-version-label: string.unquote('"\\e98d"');
|
||||
$al-ico-plugin: string.unquote('"\\e98e"');
|
||||
$al-ico-abort-all: string.unquote('"\\e98f"');
|
||||
$al-ico-refresh: string.unquote('"\\e990"');
|
||||
$al-ico-rocket: string.unquote('"\\e991"');
|
||||
$al-ico-logout: string.unquote('"\\e993"');
|
||||
$al-ico-settings-alert-path1: string.unquote('"\\e994"');
|
||||
$al-ico-settings-alert-path2: string.unquote('"\\e996"');
|
||||
$al-ico-platform: string.unquote('"\\e99a"');
|
||||
$al-ico-creditcard: string.unquote('"\\e9a0"');
|
||||
$al-ico-star: string.unquote('"\\e9a1"');
|
||||
$al-ico-email-check: string.unquote('"\\e9a2"');
|
||||
$al-ico-slack: string.unquote('"\\e9a3"');
|
||||
$al-ico-youtube: string.unquote('"\\e9a8"');
|
||||
$al-ico-lock: string.unquote('"\\e9a9"');
|
||||
$al-ico-lock-open: string.unquote('"\\e9aa"');
|
||||
$al-ico-no-code: string.unquote('"\\e9ab"');
|
||||
$al-ico-calendar-checked: string.unquote('"\\e9ad"');
|
||||
$al-ico-no-source: string.unquote('"\\e9ae"');
|
||||
$al-ico-arrow-up: string.unquote('"\\e9b1"');
|
||||
$al-ico-arrow-down: string.unquote('"\\e9b2"');
|
||||
$al-ico-error-circle: string.unquote('"\\e9b4"');
|
||||
$al-ico-pipelines: string.unquote('"\\e9b5"');
|
||||
$al-ico-console: string.unquote('"\\e9bc"');
|
||||
$al-ico-link-arrow: string.unquote('"\\e9bf"');
|
||||
$al-ico-broken-file: string.unquote('"\\e9c0"');
|
||||
$al-ico-run: string.unquote('"\\e9c1"');
|
||||
$al-ico-table-view: string.unquote('"\\e9c2"');
|
||||
$al-ico-experiment-view: string.unquote('"\\e9c3"');
|
||||
$al-ico-code-square: string.unquote('"\\e9c4"');
|
||||
$al-ico-video: string.unquote('"\\e9c5"');
|
||||
$al-ico-less-than: string.unquote('"\\e9c6"');
|
||||
$al-ico-greater-than: string.unquote('"\\e9c7"');
|
||||
$al-ico-eye-outline: string.unquote('"\\e9c8"');
|
||||
$al-ico-csv: string.unquote('"\\e9c9"');
|
||||
$al-ico-status-draft: string.unquote('"\\e903"');
|
||||
$al-ico-status-published: string.unquote('"\\e906"');
|
||||
$al-ico-status-aborted-sec: string.unquote('"\\e918"');
|
||||
$al-ico-status-pending: string.unquote('"\\e904"');
|
||||
$al-ico-status-skipped: string.unquote('"\\e9bd"');
|
||||
$al-ico-status-cached: string.unquote('"\\e9be"');
|
||||
$al-ico-status-executed: string.unquote('"\\e9ac"');
|
||||
$al-ico-status-running: string.unquote('"\\e905"');
|
||||
$al-ico-status-failed: string.unquote('"\\e907"');
|
||||
$al-ico-status-aborted: string.unquote('"\\e917"');
|
||||
$al-ico-status-completed: string.unquote('"\\ea17"');
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="88" height="88" viewBox="0 0 88 88">
|
||||
<g>
|
||||
<path fill="none" d="M0 0H88V88H0z" transform="translate(10 5) translate(-10 -5)"/>
|
||||
<path fill="#2c3246" d="M30 40.37V30h3.05l3.05 3.813L39.15 30h3.05v10.37h-3.05v-5.947l-3.05 3.812-3.05-3.813v5.948zm19.063 0l-4.575-5.033h3.05V30h3.05v5.338h3.05z" transform="translate(10 5) translate(-21.187 -21.187)"/>
|
||||
<path d="M26.587 89.6a2.608 2.608 0 0 1-2.606-2.609v-6.4h-5.929a2.608 2.608 0 0 1-2.609-2.606v-6.173H9.279A2.61 2.61 0 0 1 6.67 69.2v-65a2.608 2.608 0 0 1 2.609-2.6h49.082a2.608 2.608 0 0 1 2.609 2.6v6.164h6.164a2.61 2.61 0 0 1 2.609 2.609v6.4h5.926a2.608 2.608 0 0 1 2.609 2.609v65a2.61 2.61 0 0 1-2.609 2.618H26.587zm2.613-5.223h43.863V24.593h-3.32v53.384a2.61 2.61 0 0 1-2.609 2.609H29.2zm-8.537-9.009h43.862V15.584H60.97V69.2a2.61 2.61 0 0 1-2.609 2.609h-37.7zm-8.771-8.773h43.86V16.88L45.682 6.81H11.888zm7.586-8.806a2.606 2.606 0 0 1-2.606-2.606 2.608 2.608 0 0 1 2.606-2.609h5.218a2.608 2.608 0 1 1 0 5.215h-5.223zm0-9.484a2.606 2.606 0 0 1-2.611-2.605 2.606 2.606 0 0 1 2.606-2.609h24.186a2.608 2.608 0 1 1 0 5.215H19.473zm0-9.484a2.608 2.608 0 0 1-2.606-2.609 2.606 2.606 0 0 1 2.601-2.612h14.7a2.608 2.608 0 1 1 0 5.215h-14.7z" transform="translate(10 5) translate(-8.474 -6.595)" style="isolation:isolate" fill="#2c3246"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.3 KiB |
@@ -1,81 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink" width="64px" height="64px" viewBox="0 0 64 64">
|
||||
|
||||
<style>
|
||||
|
||||
#t-dots #t-clipper-path rect,
|
||||
#b-dots path,
|
||||
#b-dots g,
|
||||
.hourglass {
|
||||
animation-duration: 5s;
|
||||
animation-delay: 1s;
|
||||
animation-iteration-count: infinite;
|
||||
}
|
||||
.hourglass {
|
||||
transform-origin: center;
|
||||
animation-name: hourglass-rotation;
|
||||
}
|
||||
#t-dots #t-clipper-path rect {
|
||||
animation-name: t-clipper;
|
||||
}
|
||||
#b-dots path {
|
||||
transform: translateY(21px);
|
||||
animation-name: b-dots;
|
||||
}
|
||||
#b-dots g {
|
||||
animation-name: b-dots-g;
|
||||
}
|
||||
|
||||
|
||||
@keyframes t-clipper {
|
||||
0%{}
|
||||
50%{transform: translateY(22px);}
|
||||
100%{transform: translateY(22px);}
|
||||
}
|
||||
@keyframes b-dots {
|
||||
0%{}
|
||||
50%{transform: translateY(0);}
|
||||
100%{transform: translateY(0);}
|
||||
}
|
||||
@keyframes b-dots-g {
|
||||
0%{}
|
||||
85%{transform: translateY(0);}
|
||||
100%{transform: translateY(-6px);}
|
||||
}
|
||||
@keyframes hourglass-rotation {
|
||||
50%{transform: rotateZ(0);}
|
||||
100%{transform: rotateZ(180deg);}
|
||||
}
|
||||
</style>
|
||||
|
||||
<polygon points="45 37.22 50 32.22 45 27.22 45 37.22" fill="#5a658e"/>
|
||||
<polygon points="20 27.22 20 37.22 25 32.22 20 27.22" fill="#5a658e"/>
|
||||
<polygon points="12 37.22 17 32.22 12 27.22 12 37.22" fill="#5a658e"/>
|
||||
<g class="hourglass">
|
||||
|
||||
<path d="M32,33.41l8,8V52H24V41.41ZM24,12V22.59l8,8,8-8V12Z" fill="#1a1e2c"/>
|
||||
|
||||
<g id="t-dots">
|
||||
<clipPath id="t-clipper-path" fill="white">
|
||||
<rect x="22.05" y="19.95" width="19.9" height="11"/>
|
||||
</clipPath>
|
||||
|
||||
<path fill="#5a658e" clip-path="url(#t-clipper-path)" d="M41,19v3.18s-5,8.41-9,8.41-9-8.41-9-8.41V19Z"></path>
|
||||
|
||||
</g>
|
||||
|
||||
<g id="b-dots">
|
||||
<clipPath id="bottom-clip-path" fill="white">
|
||||
<rect x="22.05" y="37.76" width="19.9" height="15"/>
|
||||
</clipPath>
|
||||
|
||||
<g clip-path="url(#bottom-clip-path)">
|
||||
<path fill="#5a658e" d="M24,52H40V48.49S36,40,32,40s-8,8.51-8,8.51Z"></path>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<path d="M24,12V22.59l8,8,8-8V12Zm14,9.76-6,6-6-6V14H38ZM24,41.41V52H40V41.41l-8-8ZM38,50H26V42.24l6-6,6,6Z" fill="#1a1e2c"/>
|
||||
|
||||
<path d="M44,52H42V40.59L33.41,32,42,23.41V12h2a1,1,0,0,0,0-2H20a1,1,0,0,0,0,2h2V23.41L30.59,32,22,40.59V52H20a1,1,0,0,0,0,2H44a1,1,0,0,0,0-2ZM24,22.59V12H40V22.59l-8,8ZM40,52H24V41.41l8-8,8,8Z" fill="#5a658e"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.3 KiB |
@@ -1,14 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink" width="64px" height="64px" viewBox="0 0 64 64">
|
||||
<path d="M55,32A23,23,0,1,1,11.93,20.76l-2.5.4a1,1,0,0,1-.31-2L14,18.41a1,1,0,0,1,1.14.81l.93,5a1,1,0,0,1-.8,1.17h-.18a1,1,0,0,1-1-.81l-.5-2.7A21,21,0,1,0,32,11a1,1,0,0,1,0-2A23,23,0,0,1,55,32ZM32,50a1,1,0,0,0,1-1V47.21a1,1,0,0,0-2,0V49A1,1,0,0,0,32,50Zm0-32.21a1,1,0,0,0,1-1V15a1,1,0,0,0-2,0v1.79A1,1,0,0,0,32,17.79ZM20.54,22A1,1,0,0,0,22,22a1,1,0,0,0,0-1.41l-1.26-1.27a1,1,0,0,0-1.42,1.42ZM20,45a1,1,0,0,0,.71-.29L22,43.46a1,1,0,1,0-1.41-1.41l-1.27,1.26a1,1,0,0,0,0,1.42A1,1,0,0,0,20,45ZM42.76,22.24a1,1,0,0,0,.7-.29l1.27-1.26a1,1,0,0,0-1.42-1.42l-1.26,1.27a1,1,0,0,0,0,1.41A1,1,0,0,0,42.76,22.24ZM14,32a1,1,0,0,0,1,1h1.79a1,1,0,0,0,0-2H15A1,1,0,0,0,14,32Zm35,1a1,1,0,0,0,0-2H47.21a1,1,0,0,0,0,2Zm-7,10.46,1.26,1.27a1,1,0,0,0,1.42,0,1,1,0,0,0,0-1.42l-1.27-1.26a1,1,0,1,0-1.41,1.41Z" fill="#5a658e"/>
|
||||
<g id="seconds">
|
||||
<line fill="none" stroke="#5a658e" stroke-width="2" stroke-miterlimit="10" x1="32" y1="32" x2="32" y2="20" stroke-linecap="round"/>
|
||||
</g>
|
||||
<circle cx="32" cy="32" r="2" fill="#5a658e"/>
|
||||
<circle cx="32" cy="32" r="1" fill="#1a1e2c"/>
|
||||
|
||||
<defs>
|
||||
<animateTransform type="rotate" fill="remove" restart="always" calcMode="linear" accumulate="none" additive="sum" xlink:href="#seconds" repeatCount="indefinite" dur="15s" to="360 32 32" from="0 32 32" attributeName="transform" attributeType="xml">
|
||||
</animateTransform>
|
||||
</defs>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 258 KiB |
|
Before Width: | Height: | Size: 180 KiB After Width: | Height: | Size: 127 KiB |
|
Before Width: | Height: | Size: 172 KiB After Width: | Height: | Size: 125 KiB |
|
Before Width: | Height: | Size: 148 KiB After Width: | Height: | Size: 180 KiB |
|
Before Width: | Height: | Size: 156 KiB After Width: | Height: | Size: 182 KiB |
BIN
src/app/webapp-common/assets/marketing/apps-remote-dark.png
Normal file
|
After Width: | Height: | Size: 176 KiB |
BIN
src/app/webapp-common/assets/marketing/apps-remote-light.png
Normal file
|
After Width: | Height: | Size: 182 KiB |
|
Before Width: | Height: | Size: 898 KiB After Width: | Height: | Size: 820 KiB |
|
Before Width: | Height: | Size: 898 KiB After Width: | Height: | Size: 817 KiB |
@@ -1,7 +1,7 @@
|
||||
@if (activated) {
|
||||
@if (signIsNeeded$() === false) {
|
||||
@if (noPermissions$() === false) {
|
||||
<a class="webapp-link" [href]="webappLink" target="_blank" [class.dark-theme]="isDarkTheme">
|
||||
<a class="webapp-link" [href]="" (click)="$event.preventDefault(); navigateToSource()" [class.dark-theme]="isDarkTheme">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
||||
<path d="m2.67,14.66c-.74,0-1.33-.6-1.33-1.33h0V2.67c0-.74.6-1.33,1.33-1.33h5.33v1.33H2.67v10.67h10.67v-5.33h1.34v5.33c0,.74-.6,1.33-1.34,1.33H2.67Zm4.86-7.14l4.86-4.86h-1.72v-1.33h4v4h-1.33v-1.72l-4.86,4.86-.95-.94Z" fill="#8492c2"/>
|
||||
</svg>
|
||||
@@ -22,6 +22,7 @@
|
||||
[identifier]="'report-widget'"
|
||||
[width]="400"
|
||||
[xAxisType]="xaxis"
|
||||
[moveLegendToTitle]="checkIfLegendToTitle(plotData)"
|
||||
[isCompare]="$any(plotData)?.plotParsed?.data?.[0]?.type !== 'parcoords'"
|
||||
[noMargins]="true"
|
||||
[hideMaximize]="hideMaximize"
|
||||
@@ -85,7 +86,7 @@
|
||||
|
||||
|
||||
<ng-template #csvButtonTemplate>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
|
||||
<path
|
||||
d="M15,8V2l6,6h-6ZM21,9v11c0,1.1-.9,2-2,2H5c-1.1,0-2-.9-2-2V4c0-1.1.9-2,2-2h9v7h7ZM8.83,12.28c-.18-.09-.37-.16-.57-.21s-.42-.07-.64-.07c-.79,0-1.39.26-1.8.78s-.62,1.27-.62,2.25.21,1.73.62,2.25,1.01.78,1.8.78c.22,0,.43-.02.63-.07s.39-.12.57-.21v-1.28c-.2.18-.39.32-.58.4s-.38.13-.58.13c-.42,0-.74-.17-.96-.5s-.32-.83-.32-1.49.11-1.16.32-1.49.53-.5.96-.5c.2,0,.39.04.58.13s.38.22.58.4v-1.28ZM13.76,16.3c0-.43-.11-.79-.33-1.07s-.57-.51-1.04-.68l-.5-.19c-.34-.13-.57-.24-.68-.35s-.16-.24-.16-.4c0-.21.07-.37.22-.48s.36-.17.64-.17c.25,0,.5.05.76.14s.51.22.75.4v-1.12c-.26-.12-.53-.21-.8-.27s-.54-.09-.8-.09c-.59,0-1.06.15-1.39.45s-.51.72-.51,1.25c0,.41.1.74.31.98s.6.48,1.18.7l.57.21c.2.08.35.18.45.31s.16.28.16.46c0,.23-.08.41-.23.54s-.38.19-.66.19-.57-.05-.85-.16-.59-.27-.89-.49v1.19c.27.14.55.24.84.31s.58.1.87.1c.7,0,1.23-.15,1.58-.44s.52-.73.52-1.32ZM18.83,12.11h-1.16l-1.03,4.87-1.02-4.87h-1.16l1.39,5.83h1.6l1.39-5.83Z"
|
||||
fill="#8492c2"/>
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
} from '@angular/core';
|
||||
import {Store} from '@ngrx/store';
|
||||
import {MatDialog} from '@angular/material/dialog';
|
||||
import {debounceTime, filter, map, switchMap, take} from 'rxjs/operators';
|
||||
import {filter, map, switchMap, take} from 'rxjs/operators';
|
||||
import {Environment} from '../environments/base';
|
||||
import {getParcoords, getPlot, getSample, getScalar, getSingleValues, reportsPlotlyReady} from './app.actions';
|
||||
import {appFeature} from './app.reducer';
|
||||
@@ -17,7 +17,7 @@ import {ExtFrame} from '@common/shared/single-graph/plotly-graph-base';
|
||||
import {DebugSample} from '@common/shared/debug-sample/debug-sample.reducer';
|
||||
import {getSignedUrl, setS3Credentials} from '@common/core/actions/common-auth.actions';
|
||||
import {ConfigurationService} from '@common/shared/services/configuration.service';
|
||||
import {_mergeVariants, allowedMergedTypes, convertMultiPlots, createMultiSingleValuesChart, mergeMultiMetricsGroupedVariant, prepareGraph, prepareMultiPlots, tryParseJson} from '@common/tasks/tasks.utils';
|
||||
import {_mergeVariants, allowedMergedTypes, checkIfLegendToTitle, convertMultiPlots, createMultiSingleValuesChart, mergeMultiMetricsGroupedVariant, prepareGraph, prepareMultiPlots, tryParseJson} from '@common/tasks/tasks.utils';
|
||||
import {selectSignedUrl} from '@common/core/reducers/common-auth-reducer';
|
||||
import {loadExternalLibrary} from '@common/shared/utils/load-external-library';
|
||||
import {ImageViewerComponent} from '@common/shared/debug-sample/image-viewer/image-viewer.component';
|
||||
@@ -40,8 +40,6 @@ import {
|
||||
} from '@common/shared/single-value-summary-table/single-value-summary-table.component';
|
||||
import {MetricVariantResult} from '~/business-logic/model/projects/metricVariantResult';
|
||||
import {SingleGraphStateModule} from '@common/shared/single-graph/single-graph-state.module';
|
||||
import {takeUntilDestroyed} from '@angular/core/rxjs-interop';
|
||||
import {BreakpointObserver, BreakpointState} from '@angular/cdk/layout';
|
||||
import {DOCUMENT} from '@angular/common';
|
||||
|
||||
|
||||
@@ -52,27 +50,26 @@ export interface SelectedMetricVariant extends MetricVariantResult {
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'sm-widget-root',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrls: ['./app.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone: true,
|
||||
imports: [
|
||||
SingleGraphStateModule,
|
||||
SingleGraphModule,
|
||||
DebugSampleModule,
|
||||
ParallelCoordinatesGraphComponent,
|
||||
SingleValueSummaryTableComponent
|
||||
]
|
||||
selector: 'sm-widget-root',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrls: ['./app.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [
|
||||
SingleGraphStateModule,
|
||||
SingleGraphModule,
|
||||
DebugSampleModule,
|
||||
ParallelCoordinatesGraphComponent,
|
||||
SingleValueSummaryTableComponent
|
||||
]
|
||||
})
|
||||
export class AppComponent implements OnInit {
|
||||
private store = inject(Store);
|
||||
private configService = inject(ConfigurationService);
|
||||
private dialog = inject(MatDialog);
|
||||
private cdr = inject(ChangeDetectorRef);
|
||||
private breakpointObserver = inject(BreakpointObserver);
|
||||
private renderer = inject(Renderer2);
|
||||
private readonly document = inject(DOCUMENT);
|
||||
protected readonly checkIfLegendToTitle = checkIfLegendToTitle;
|
||||
|
||||
protected title = 'report-widgets';
|
||||
public plotData: ExtFrame;
|
||||
@@ -87,12 +84,12 @@ export class AppComponent implements OnInit {
|
||||
public hideMaximize: 'show' | 'hide' | 'disabled' = 'show';
|
||||
protected signIsNeeded$ = this.store.selectSignal(appFeature.selectSignIsNeeded);
|
||||
protected noPermissions$ = this.store.selectSignal(appFeature.selectNoPermissions);
|
||||
public isDarkTheme: boolean;
|
||||
private tasksData = this.store.selectSignal(appFeature.selectTaskData);
|
||||
public isDarkTheme = false;
|
||||
public externalTool = false;
|
||||
public parcoordsData: { experiments: ExtraTask[]; params: string[]; metrics: SelectedMetricVariant[] };
|
||||
@ViewChild(SingleGraphComponent) 'singleGraph': SingleGraphComponent;
|
||||
public singleValueData: EventsGetTaskSingleValueMetricsResponseValues[];
|
||||
public webappLink: string;
|
||||
public readonly xaxis: ScalarKeyEnum;
|
||||
|
||||
@HostListener('window:resize')
|
||||
@@ -106,7 +103,6 @@ export class AppComponent implements OnInit {
|
||||
});
|
||||
this.searchParams = new URLSearchParams(window.location.search);
|
||||
this.type = this.searchParams.get('type') as WidgetTypes;
|
||||
this.webappLink = this.buildSourceLink(this.searchParams, '*', null);
|
||||
this.singleGraphHeight = window.innerHeight;
|
||||
this.otherSearchParams = this.getOtherSearchParams();
|
||||
this.xaxis = this.searchParams.get('xaxis') as ScalarKeyEnum;
|
||||
@@ -136,7 +132,7 @@ export class AppComponent implements OnInit {
|
||||
if (!(window.top as any).holdIframe) {
|
||||
this.activate();
|
||||
}
|
||||
} catch (e) {
|
||||
} catch {
|
||||
this.externalTool = true;
|
||||
this.hideMaximize = 'hide';
|
||||
console.log('no-access-to-parent-window');
|
||||
@@ -180,7 +176,7 @@ export class AppComponent implements OnInit {
|
||||
if (window.top.document.body.parentElement.className) {
|
||||
this.isDarkTheme = window.top.document.body.parentElement.classList.contains('dark-mode');
|
||||
}
|
||||
} catch (e) {
|
||||
} catch {
|
||||
this.isDarkTheme = this.searchParams.get('light') ? this.searchParams.get('light') === 'false' : !this.isDarkTheme;
|
||||
}
|
||||
this.renderer.addClass(this.document.documentElement, `${this.isDarkTheme ? 'dark' : 'light'}-mode`);
|
||||
@@ -219,15 +215,15 @@ export class AppComponent implements OnInit {
|
||||
take(1))
|
||||
.subscribe((metricsPlots) => {
|
||||
this.plotLoaded = true;
|
||||
if (this.searchParams.getAll('objects').length < 2) {
|
||||
if (this.tasksData().sourceTasks.length < 2) {
|
||||
const merged = this.mergeVariants(metricsPlots as ReportsApiMultiplotsResponse);
|
||||
this.plotData = {...Object.values(merged)[0], ...Object.values(merged)[0].plotParsed};
|
||||
} else {
|
||||
const {merged} = prepareMultiPlots(metricsPlots as ReportsApiMultiplotsResponse);
|
||||
const newGraphs = convertMultiPlots(merged);
|
||||
const originalObject = this.searchParams.get('objects');
|
||||
const series = this.searchParams.get('series');
|
||||
this.plotData = series ? Object.values(newGraphs)[0].find(a => (a.data[0] as any).seriesName === series) :
|
||||
const series = this.searchParams.getAll('series');
|
||||
this.plotData = series?.length > 0 ? Object.values(newGraphs)[0].find(a => series.includes((a.data[0] as any).seriesName)) :
|
||||
Object.values(newGraphs)[0]?.find(a => originalObject === (a.task ?? a.data[0].task)) ??
|
||||
Object.values(newGraphs)[0]?.[0];
|
||||
}
|
||||
@@ -436,16 +432,23 @@ export class AppComponent implements OnInit {
|
||||
return {metric: lastMetric.metric, variant: lastMetric.variant};
|
||||
}
|
||||
|
||||
private buildSourceLink(searchParams: URLSearchParams, project: string, tasks: string[]): string {
|
||||
protected navigateToSource() {
|
||||
const a = document.createElement('a');
|
||||
a.href = this.buildSourceLink(this.searchParams, '*');
|
||||
a.target = '_blank';
|
||||
a.click();
|
||||
}
|
||||
|
||||
private buildSourceLink(searchParams: URLSearchParams, project: string): string {
|
||||
const isModels = searchParams.has('models') || this.searchParams.get('objectType') === 'model';
|
||||
const objects = searchParams.getAll('objects');
|
||||
const variants = searchParams.getAll('variants');
|
||||
const metricsPath = searchParams.getAll('metrics');
|
||||
let entityIds = objects.length > 0 ? objects : searchParams.getAll(isModels ? 'models' : 'tasks');
|
||||
if (entityIds.length === 0 && tasks?.length > 0) {
|
||||
entityIds = tasks;
|
||||
if (entityIds.length === 0 && this.tasksData().sourceTasks.length > 0) {
|
||||
entityIds = this.tasksData().sourceTasks.slice(0,100);
|
||||
}
|
||||
const isCompare = entityIds.length > 1;
|
||||
const isCompare =this.tasksData().sourceTasks.length > 1;
|
||||
let url = `${window.location.origin.replace('4201', '4200')}/projects/${project ?? '*'}/`;
|
||||
if (isCompare) {
|
||||
url += `${isModels ? 'compare-models;ids=' : 'compare-tasks;ids='}${entityIds.filter(id => !!id).join(',')}/${
|
||||
@@ -469,11 +472,11 @@ export class AppComponent implements OnInit {
|
||||
switch (type) {
|
||||
case 'single':
|
||||
case 'scalar':
|
||||
return 'info-output/metrics/scalar';
|
||||
return 'output/metrics/scalar';
|
||||
case 'plot':
|
||||
return 'info-output/metrics/plots';
|
||||
return 'output/metrics/plots';
|
||||
case 'sample':
|
||||
return 'info-output/debugImages';
|
||||
return 'output/debugImages';
|
||||
}
|
||||
}
|
||||
return '';
|
||||
|
||||
@@ -61,12 +61,13 @@ export class AppEffects {
|
||||
{headers: this.getHeaders(action.company)}
|
||||
)),
|
||||
mergeMap((res) => [
|
||||
setPlotData({data: res.data.plots as unknown as ReportsApiMultiplotsResponse}),
|
||||
setTaskData({
|
||||
sourceProject: (res.data.tasks[0]?.project as any).id,
|
||||
sourceTasks: res.data.tasks.map(t => t.id),
|
||||
appId: (res.data.tasks[0] as any)?.application?.app_id?.id
|
||||
})]),
|
||||
}),
|
||||
setPlotData({data: res.data.plots as unknown as ReportsApiMultiplotsResponse})
|
||||
]),
|
||||
catchError(error => [requestFailed(error), ...(error.status === 403 ? [setNoPermissions()] : [])])
|
||||
));
|
||||
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
@import "customizations/colors";
|
||||
@import "customizations/form-fields";
|
||||
@import "customizations/dialogs";
|
||||
@import "customizations/scrollbar";
|
||||
@import "customizations/tooltip";
|
||||
@import "customizations/slide-toggle";
|
||||
@forward "customizations/colors";
|
||||
@forward "customizations/form-fields";
|
||||
@forward "customizations/dialogs";
|
||||
@forward "customizations/scrollbar";
|
||||
@forward "customizations/tooltip";
|
||||
@forward "customizations/slide-toggle";
|
||||
@use "customizations/colors";
|
||||
@use "customizations/dialogs";
|
||||
|
||||
|
||||
body {
|
||||
color: var(--color-on-surface-variant);
|
||||
}
|
||||
|
||||
@mixin components($theme) {
|
||||
@include generate-colors($theme);
|
||||
@include form-fields($theme);
|
||||
@include dialogs($theme);
|
||||
@include colors.generate-colors($theme);
|
||||
@include dialogs.dialogs($theme);
|
||||
}
|
||||
|
||||
@@ -1,22 +1,24 @@
|
||||
@use '../../../../../../../../node_modules/@angular/material/index' as mat;
|
||||
@use "../../../../../styles/variables";
|
||||
|
||||
//@import "../assets/fonts/trains-icons.scss";
|
||||
//@import "reboot";
|
||||
//@import "minimal-bootstrap";
|
||||
//@import "layout";
|
||||
//@import "utilities";
|
||||
@import "themes";
|
||||
@import "./customizations";
|
||||
@import "../../../../../styles/icons"; //needs a clean from sass vars
|
||||
|
||||
//@use "../assets/fonts/trains-icons.scss";
|
||||
//@use "reboot";
|
||||
//@use "minimal-bootstrap";
|
||||
//@use "layout";
|
||||
//@use "utilities";
|
||||
@use "themes";
|
||||
@use "./customizations";
|
||||
@forward "../../../../../styles/icons"; //needs a clean from sass vars
|
||||
|
||||
:root {
|
||||
@include mat.all-component-themes($theme);
|
||||
@include components($theme);
|
||||
@include mat.all-component-themes(themes.$theme);
|
||||
@include mat.system-level-colors(themes.$theme);
|
||||
@include customizations.components(themes.$theme);
|
||||
|
||||
&.dark-mode {
|
||||
@include mat.all-component-colors($dark-theme);
|
||||
@include components($dark-theme);
|
||||
@include mat.all-component-colors(themes.$dark-theme);
|
||||
@include mat.system-level-colors(themes.$dark-theme);
|
||||
@include customizations.components(themes.$dark-theme);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +28,6 @@ $purple: #4d66ff;
|
||||
$white-primary-text: rgba(white, 0.87);
|
||||
$dark-primary-text: rgba(black, 0.87);
|
||||
|
||||
@import "../../../../../styles/variables";
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
@@ -38,6 +39,10 @@ html, body {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
--mat-select-trigger-text-size: 14px;
|
||||
|
||||
&.dark-mode {
|
||||
background-color: var(--color-surface-container-lowest);
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
../../../../
|
||||
@@ -0,0 +1 @@
|
||||
../../../../../assets/
|
||||
@@ -25,7 +25,6 @@ export interface Environment {
|
||||
fileBaseUrl: string;
|
||||
displayedServerUrls?: {apiServer?: string; filesServer?: string};
|
||||
alternativeFilesBaseUrl?: string;
|
||||
demo: boolean;
|
||||
headerPrefix: string;
|
||||
version: string;
|
||||
userKey: string;
|
||||
@@ -76,7 +75,6 @@ export const BASE_ENV: Environment = {
|
||||
accountAdministration: true,
|
||||
production: true,
|
||||
cookieName: 'allegro_token',
|
||||
demo: false,
|
||||
updateCheck: false,
|
||||
autoLogin: false,
|
||||
apiBaseUrl: null,
|
||||
|
||||
@@ -6,6 +6,18 @@
|
||||
<base href="/">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||
<style>
|
||||
@media (prefers-color-scheme: dark) {
|
||||
html:not(.light-mode) {
|
||||
background-color: var(--color-shadow);
|
||||
}
|
||||
}
|
||||
@media (prefers-color-scheme: light) {
|
||||
html:not(.dark-mode) {
|
||||
background-color: white;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<sm-widget-root style="width: 100%; height: 100%"></sm-widget-root>
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
<span class="search-container" [class.open]="isSearching$ | ngrxPush">
|
||||
<div class="search-icon-container">
|
||||
<button [disabled]="isSearching() && !searchElem().searchBarInput().nativeElement.value " mat-icon-button (click)="isSearching()? clearSearch():openSearch()" data-id="searchIcon" class="me-2 search-icon" [class.open]="isSearching()" >
|
||||
<mat-icon fontSet="al" [fontIcon]="searchElem().searchBarInput().nativeElement.value ?'al-ico-dialog-x':'al-ico-search'" data-id="search Icon"></mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
<span class="search-container" [class.open]="isSearching()">
|
||||
<sm-search
|
||||
#searchComponent
|
||||
class="search-header"
|
||||
class="outline contained-icon"
|
||||
[class.regex-error]="regexError"
|
||||
[value]="(searchQuery$ | ngrxPush)?.original"
|
||||
[placeholder]="searchPlaceholder$ | ngrxPush"
|
||||
[placeholder]="searchPlaceholder()"
|
||||
[hideIcons]="true"
|
||||
[minimumChars]="minChars"
|
||||
(focusout)="onSearchFocusOut()"
|
||||
@@ -13,29 +18,16 @@
|
||||
@if (regexError) {
|
||||
<mat-icon class="error regexp" fontSet="al" fontIcon="al-ico-error-circle" inline [smTooltip]="regexError" [matTooltipPosition]="'below'"></mat-icon>
|
||||
}
|
||||
<button mat-icon-button
|
||||
class="regexp sm"
|
||||
[class.active]="regExp"
|
||||
smClickStopPropagation
|
||||
[smTooltip]="'Regex'" [matTooltipPosition]="'below'"
|
||||
(click)="toggleRegExp(); searchComponent.searchBarInput.nativeElement.focus();"
|
||||
@if (showRegex$ | ngrxPush) {
|
||||
<button mat-icon-button
|
||||
class="regexp sm"
|
||||
[class.active]="regExp"
|
||||
smClickStopPropagation
|
||||
[smTooltip]="'Regex'" [matTooltipPosition]="'below'"
|
||||
(click)="toggleRegExp(); searchComponent.searchBarInput().nativeElement.focus();"
|
||||
>
|
||||
<mat-icon fontSet="al" fontIcon="al-ico-regex" data-id="enableRegexButton"></mat-icon>
|
||||
</button>
|
||||
}
|
||||
</sm-search>
|
||||
</span>
|
||||
@if (searchActive) {
|
||||
@if ((isSearching$ | ngrxPush)) {
|
||||
<button mat-icon-button (click)="clearSearch()" smClickStopPropagation>
|
||||
<mat-icon
|
||||
fontSet="al"
|
||||
fontIcon="al-ico-dialog-x"
|
||||
data-id="closeSearchButton">
|
||||
</mat-icon>
|
||||
</button>
|
||||
} @else {
|
||||
<button mat-icon-button (click)="openSearch()" data-id="searchIcon">
|
||||
<mat-icon fontSet="al" fontIcon="al-ico-search" data-id="search Icon"></mat-icon>
|
||||
</button>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,28 @@
|
||||
@import "variables";
|
||||
|
||||
:host {
|
||||
position: absolute;
|
||||
height: 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
right: 110px;
|
||||
// background-color: var(--color-surface-container-low);
|
||||
z-index: 1;
|
||||
padding-left: 20px;
|
||||
|
||||
.search-icon-container {
|
||||
width: 284px;
|
||||
position: absolute;
|
||||
|
||||
.search-icon {
|
||||
transition: left 0.35s ease-in-out;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
|
||||
|
||||
&.open {
|
||||
left: 247px;
|
||||
}
|
||||
|
||||
.al-ico-search {
|
||||
color: var(--color-primary);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.search-container {
|
||||
width: 0;
|
||||
@@ -24,11 +38,11 @@
|
||||
|
||||
.regexp {
|
||||
position: absolute;
|
||||
right: 8px;
|
||||
right: 36px;
|
||||
|
||||
&.active {
|
||||
color: var(--color-on-secondary);
|
||||
background-color: var(--color-secondary);
|
||||
color: var(--color-on-primary);
|
||||
background-color: var(--color-primary);
|
||||
}
|
||||
|
||||
&.error {
|
||||
@@ -37,7 +51,7 @@
|
||||
}
|
||||
|
||||
.al-ico-error-circle {
|
||||
right: 48px;
|
||||
right: 60px;
|
||||
}
|
||||
|
||||
.al-ico-dialog-x {
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit, ViewChild} from '@angular/core';
|
||||
import {ChangeDetectionStrategy, Component, inject, input, OnDestroy, viewChild} from '@angular/core';
|
||||
import {ActivatedRoute, NavigationEnd, Router} from '@angular/router';
|
||||
import {Store} from '@ngrx/store';
|
||||
import {setSearching, setSearchQuery} from '../../common-search.actions';
|
||||
import {SearchState, selectIsSearching, selectPlaceholder, selectSearchQuery} from '../../common-search.reducer';
|
||||
import {Observable} from 'rxjs';
|
||||
import {debounceTime, distinctUntilChanged, filter, tap} from 'rxjs/operators';
|
||||
import {resetSearch, setSearching, setSearchQuery} from '../../common-search.actions';
|
||||
import {selectIsSearching, selectPlaceholder, selectSearchQuery} from '../../common-search.reducer';
|
||||
import {Observable, timer} from 'rxjs';
|
||||
import {debounce, distinctUntilChanged, filter, tap} from 'rxjs/operators';
|
||||
import {SearchComponent} from '@common/shared/ui-components/inputs/search/search.component';
|
||||
import {PushPipe} from '@ngrx/component';
|
||||
import {TooltipDirective} from '@common/shared/ui-components/indicators/tooltip/tooltip.directive';
|
||||
import {ClickStopPropagationDirective} from '@common/shared/ui-components/directives/click-stop-propagation.directive';
|
||||
import {MatIconButton} from '@angular/material/button';
|
||||
import {MatIcon} from '@angular/material/icon';
|
||||
import {takeUntilDestroyed, toObservable} from '@angular/core/rxjs-interop';
|
||||
|
||||
@Component({
|
||||
selector: 'sm-common-search',
|
||||
templateUrl: './common-search.component.html',
|
||||
styleUrls: ['./common-search.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone: true,
|
||||
imports: [
|
||||
SearchComponent,
|
||||
PushPipe,
|
||||
@@ -27,22 +27,31 @@ import {MatIcon} from '@angular/material/icon';
|
||||
MatIcon
|
||||
]
|
||||
})
|
||||
export class CommonSearchComponent implements OnInit {
|
||||
public searchQuery$: Observable<SearchState['searchQuery']>;
|
||||
public isSearching$: Observable<boolean>;
|
||||
public searchPlaceholder$: Observable<string>;
|
||||
public searchActive: boolean;
|
||||
export class CommonSearchComponent implements OnDestroy {
|
||||
private store = inject(Store);
|
||||
private router = inject(Router);
|
||||
private route = inject(ActivatedRoute);
|
||||
|
||||
public searchActive = input(false);
|
||||
|
||||
@ViewChild(SearchComponent) searchElem: SearchComponent;
|
||||
public regExp = false;
|
||||
private closeTimer: number;
|
||||
minChars = 3;
|
||||
public regexError: boolean;
|
||||
protected minChars = 3;
|
||||
protected regexError: boolean;
|
||||
protected searchQuery$ = this.store.select(selectSearchQuery).pipe(tap(searchQuery => this.regExp = searchQuery?.regExp));
|
||||
protected isSearching = this.store.selectSignal(selectIsSearching);
|
||||
protected searchPlaceholder = this.store.selectSignal(selectPlaceholder);
|
||||
|
||||
protected searchElem = viewChild(SearchComponent);
|
||||
private waitForRegex = false
|
||||
protected showRegex$: Observable<boolean>;
|
||||
|
||||
constructor() {
|
||||
this.showRegex$ = toObservable(this.isSearching).pipe(debounce((isSearching) => timer(isSearching ? 350 : 0)));
|
||||
|
||||
constructor(private store: Store, private router: Router, private route: ActivatedRoute, private cdr: ChangeDetectorRef) {
|
||||
this.router.events
|
||||
.pipe(
|
||||
takeUntilDestroyed(),
|
||||
filter(event => event instanceof NavigationEnd),
|
||||
distinctUntilChanged((pe: NavigationEnd, ce: NavigationEnd) => {
|
||||
const pURL = new URLSearchParams(pe.url.split('?')?.[1]);
|
||||
@@ -60,12 +69,12 @@ export class CommonSearchComponent implements OnInit {
|
||||
if (query) {
|
||||
this.openSearch();
|
||||
} else {
|
||||
if (document.activeElement !== this.searchElem.searchBarInput.nativeElement) {
|
||||
this.store.dispatch(setSearching({payload: false}))
|
||||
if (document.activeElement !== this.searchElem()?.searchBarInput().nativeElement) {
|
||||
this.store.dispatch(setSearching({payload: false}));
|
||||
}
|
||||
}
|
||||
})
|
||||
if( this.route.snapshot.queryParams.q) {
|
||||
});
|
||||
if (this.route.snapshot.queryParams.q) {
|
||||
const query = this.route.snapshot.queryParams?.q ?? '';
|
||||
const qregex = this.route.snapshot.queryParams?.qreg ?? false;
|
||||
this.store.dispatch(setSearchQuery({
|
||||
@@ -73,19 +82,12 @@ export class CommonSearchComponent implements OnInit {
|
||||
regExp: qregex,
|
||||
original: query
|
||||
}));
|
||||
setTimeout( () => this.openSearch());
|
||||
setTimeout(() => this.openSearch());
|
||||
}
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.searchQuery$ = this.store.select(selectSearchQuery).pipe(tap(searchQuery => this.regExp = searchQuery?.regExp));
|
||||
this.isSearching$ = this.store.select(selectIsSearching);
|
||||
this.searchPlaceholder$ = this.store.select(selectPlaceholder).pipe(debounceTime(0));
|
||||
this.router.events.pipe(filter(event => event instanceof NavigationEnd))
|
||||
.subscribe(() => {
|
||||
this.setSearchActive();
|
||||
});
|
||||
setTimeout(this.setSearchActive.bind(this));
|
||||
ngOnDestroy(): void {
|
||||
this.store.dispatch(resetSearch());
|
||||
}
|
||||
|
||||
|
||||
@@ -101,9 +103,10 @@ export class CommonSearchComponent implements OnInit {
|
||||
replaceUrl: true,
|
||||
queryParamsHandling: 'merge',
|
||||
queryParams: {
|
||||
q: query || undefined
|
||||
q: query || undefined,
|
||||
qreg: this.regExp ? this.regExp : undefined
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
} catch (e) {
|
||||
this.regexError = e.message?.replace(/:.+:/, ':');
|
||||
@@ -112,44 +115,37 @@ export class CommonSearchComponent implements OnInit {
|
||||
|
||||
openSearch() {
|
||||
window.clearTimeout(this.closeTimer);
|
||||
this.searchElem.searchBarInput.nativeElement.focus();
|
||||
this.searchElem().searchBarInput().nativeElement.focus();
|
||||
this.store.dispatch(setSearching({payload: true}));
|
||||
}
|
||||
|
||||
onSearchFocusOut() {
|
||||
if (!this.searchElem.searchBarInput.nativeElement.value) {
|
||||
window.clearTimeout(this.closeTimer);
|
||||
if (!this.waitForRegex && !this.searchElem().searchBarInput().nativeElement.value) {
|
||||
this.closeTimer = window.setTimeout(() => this.store.dispatch(setSearching({payload: false})), 200);
|
||||
}
|
||||
}
|
||||
|
||||
private setSearchActive() {
|
||||
let route = this.route.snapshot;
|
||||
let showSearch = false;
|
||||
while (route.firstChild) {
|
||||
route = route.firstChild;
|
||||
if (route.data.search !== undefined) {
|
||||
showSearch = route.data.search;
|
||||
}
|
||||
}
|
||||
this.searchActive = showSearch;
|
||||
this.cdr.detectChanges();
|
||||
}
|
||||
|
||||
clearSearch() {
|
||||
this.searchElem.clear();
|
||||
this.searchElem().clear();
|
||||
this.store.dispatch(setSearching({payload: false}));
|
||||
document.body.focus();
|
||||
setTimeout( () =>this.searchElem.searchBarInput.nativeElement.blur(), 100);
|
||||
setTimeout(() => this.searchElem().searchBarInput().nativeElement.blur(), 100);
|
||||
}
|
||||
|
||||
toggleRegExp() {
|
||||
this.regExp = !this.regExp;
|
||||
this.router.navigate([], {
|
||||
relativeTo: this.route,
|
||||
replaceUrl: true,
|
||||
queryParamsHandling: 'merge',
|
||||
queryParams: {
|
||||
qreg: this.regExp ? this.regExp : undefined}
|
||||
})
|
||||
if (this.searchElem().searchBarInput().nativeElement.value) {
|
||||
this.router.navigate([], {
|
||||
relativeTo: this.route,
|
||||
replaceUrl: true,
|
||||
queryParamsHandling: 'merge',
|
||||
queryParams: {qreg: this.regExp ? this.regExp : undefined}
|
||||
});
|
||||
}
|
||||
this.waitForRegex = true;
|
||||
window.setTimeout(() => this.waitForRegex = false, 200);
|
||||
this.searchElem().searchBarInput().nativeElement.focus();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ export const systemThemeChanged = createAction(
|
||||
|
||||
export const setForcedTheme = createAction(
|
||||
VIEW_PREFIX + '[set forced theme]',
|
||||
props<{ theme: 'light' | 'dark'; default: 'light' | 'dark' }>()
|
||||
props<{ theme: 'light' | 'dark'; default?: 'light' | 'dark' }>()
|
||||
);
|
||||
|
||||
export const setThemeColors = createAction(
|
||||
|
||||
@@ -58,6 +58,11 @@ export const setSelectedProject = createAction(
|
||||
props<{ project: Project }>()
|
||||
);
|
||||
|
||||
export const setSelectedProjectSimple = createAction(
|
||||
PROJECTS_PREFIX + 'SET_SELECTED_PROJECT_SIMPLE',
|
||||
props<{ project: Project }>()
|
||||
);
|
||||
|
||||
export const setProjectAncestors = createAction(
|
||||
PROJECTS_PREFIX + 'SET_PROJECT_ANCESTORS',
|
||||
props<{ projects: Project[] }>()
|
||||
|
||||
@@ -28,7 +28,7 @@ import {isGoogleCloudUrl, SignResponse} from '@common/settings/admin/base-admin-
|
||||
import {isFileserverUrl} from '~/shared/utils/url';
|
||||
import {selectRouterQueryParams} from '@common/core/reducers/router-reducer';
|
||||
import {concatLatestFrom} from '@ngrx/operators';
|
||||
import {selectExtraCredentials} from '~/core/reducers/auth.reducers';
|
||||
import {selectCompanyPreSignServices, selectExtraCredentials} from '~/core/reducers/auth.reducers';
|
||||
import {ErrorService} from '@common/shared/services/error.service';
|
||||
|
||||
@Injectable()
|
||||
@@ -183,13 +183,15 @@ export class CommonAuthEffects {
|
||||
mergeMap(([action, prevSigns]) =>
|
||||
forkJoin(action.sign.map(req =>
|
||||
of(action).pipe(
|
||||
concatLatestFrom(() =>
|
||||
this.store.select(selectSignedUrl(req.url))
|
||||
),
|
||||
switchMap(([, signedUrl]) => (!signedUrl?.expires || signedUrl.expires < (new Date()).getTime() ||
|
||||
(isFileserverUrl(req.url) && req.config?.disableCache) ||
|
||||
(req.config?.error && isGoogleCloudUrl(req.url) && !signedUrl.signed.includes('X-Amz-Signature'))
|
||||
) ? this.adminService.signUrlIfNeeded(req.url, req.config, prevSigns[req.url]) : of({type: 'none'})),
|
||||
concatLatestFrom(() => [
|
||||
this.store.select(selectSignedUrl(req.url)),
|
||||
this.store.select(selectCompanyPreSignServices)
|
||||
]),
|
||||
switchMap(([, signedUrl, preSignService]) => (!signedUrl?.expires || signedUrl.expires < (new Date()).getTime() ||
|
||||
(isFileserverUrl(req.url) && req.config?.disableCache) ||
|
||||
(req.config?.error && isGoogleCloudUrl(req.url) && !signedUrl.signed.includes('X-Amz-Signature')) ||
|
||||
preSignService.length > 0
|
||||
) ? this.adminService.signUrlIfNeeded(req.url, req.config, prevSigns[req.url]) : of({type: 'none'})),
|
||||
map(res => ({res, orgUrl: req.url}))
|
||||
)
|
||||
)).pipe(
|
||||
@@ -250,9 +252,9 @@ export class CommonAuthEffects {
|
||||
.pipe(
|
||||
concatLatestFrom(() => this.store.select(selectS3BucketCredentialsBucketCredentials)),
|
||||
switchMap(([data, bucketCredentials]) => {
|
||||
const actions = [...this.signAfterPopup];
|
||||
this.signAfterPopup = [];
|
||||
let actions = [];
|
||||
if (data) {
|
||||
actions = [...this.signAfterPopup];
|
||||
if (!data.success) {
|
||||
const emptyCredentials = bucketCredentials.find((cred => cred?.Bucket === data.Bucket)) === undefined;
|
||||
const dontAskAgainForBucketName = emptyCredentials ? '' : data.Bucket + data.Endpoint;
|
||||
@@ -260,6 +262,7 @@ export class CommonAuthEffects {
|
||||
}
|
||||
return [authActions.saveS3Credentials({newCredential: data}), ...actions];
|
||||
}
|
||||
this.signAfterPopup = [];
|
||||
return actions;
|
||||
}),
|
||||
finalize(() => action?.credentials?.Bucket && delete this.openPopup[action.credentials.Bucket])
|
||||
|
||||
@@ -49,11 +49,11 @@ export interface RootProjects {
|
||||
projectTags: string[];
|
||||
companyTags: string[];
|
||||
systemTags: string[];
|
||||
tagsColors: { [tag: string]: TagColor };
|
||||
tagsColors: Record<string, TagColor>;
|
||||
tagsFilterByProject: boolean;
|
||||
graphVariant: { [project: string]: ISmCol[] };
|
||||
graphVariant: Record<string, ISmCol[]>;
|
||||
graphData: ScatterPlotPoint[];
|
||||
hiddenStates: { [state: string]: boolean };
|
||||
hiddenStates: Record<string, boolean>;
|
||||
lastUpdate: string;
|
||||
users: User[];
|
||||
allUsers: User[];
|
||||
@@ -61,9 +61,9 @@ export interface RootProjects {
|
||||
showHidden: boolean;
|
||||
hideExamples: boolean;
|
||||
blockUserScript: boolean;
|
||||
mainPageTagsFilter: { [Feature: string]: { tags: string[]; filterMatchMode: string } };
|
||||
mainPageTagsFilter: Record<string, { tags: string[]; filterMatchMode: string }>;
|
||||
mainPageTagsFilterMatchMode: string;
|
||||
defaultNestedModeForFeature: { [feature: string]: boolean };
|
||||
defaultNestedModeForFeature: Record<string, boolean>;
|
||||
selectedSubFeature: IBreadcrumbsLink;
|
||||
tablesFilterProjectsOptions: Partial<ProjectsGetAllResponseSingle>[];
|
||||
projectsOptionsScrollId: string;
|
||||
@@ -116,7 +116,7 @@ export const selectProjectTags = createSelector(projects, state => state.project
|
||||
export const selectMainPageTagsFilter = createSelector(projects, selectProjectType,(state, projectType) => projectType? state.mainPageTagsFilter[projectType]?.tags : []);
|
||||
export const selectMainPageTagsFilterMatchMode = createSelector(projects, selectProjectType, (state, projectType) => projectType? state.mainPageTagsFilter[projectType]?.filterMatchMode : null);
|
||||
export const selectCompanyTags = createSelector(projects, state => state.companyTags);
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
|
||||
export const selectProjectSystemTags = createSelector(projects, state => getSystemTags({system_tags: state.systemTags} as ITableExperiment));
|
||||
export const selectTagsColors = createSelector(projects, state => state?.tagsColors);
|
||||
export const selectLastUpdate = createSelector(projects, state => state.lastUpdate);
|
||||
@@ -138,7 +138,7 @@ export const selectSelectedProjectUsers = createSelector(selectSelectedProjectId
|
||||
(projectId, projectUsers, allUsers) => projectId === '*' ? allUsers : projectUsers);
|
||||
export const selectTablesFilterProjectsOptions = createSelector(projects, state => state.tablesFilterProjectsOptions);
|
||||
export const selectMyProjects = createSelector(selectTablesFilterProjectsOptions,
|
||||
projects => projects?.filter(project => project?.company?.id)
|
||||
projects => projects? projects?.filter(project => project?.company?.id): null
|
||||
);
|
||||
|
||||
export const selectReadOnlyProjects = createSelector(selectTablesFilterProjectsOptions,
|
||||
@@ -162,6 +162,10 @@ export const projectsReducer = createReducer(
|
||||
selectedProject: action.project,
|
||||
extraUsers: []
|
||||
})),
|
||||
on(projectsActions.setSelectedProjectSimple, (state, action): RootProjects => ({
|
||||
...state,
|
||||
selectedProject: action.project
|
||||
})),
|
||||
on(projectsActions.setProjectAncestors, (state, action): RootProjects => ({
|
||||
...state,
|
||||
projectAncestors: action.projects
|
||||
@@ -256,7 +260,7 @@ export const projectsReducer = createReducer(
|
||||
on(projectsActions.setTablesFilterProjectsOptions, (state, action): RootProjects => ({
|
||||
...state,
|
||||
tablesFilterProjectsOptions: action.loadMore ? uniqBy((state.tablesFilterProjectsOptions || []).concat(action.projects), 'id') : uniqBy(action.projects, 'id'),
|
||||
projectsOptionsScrollId: action.scrollId
|
||||
projectsOptionsScrollId: action.scrollId
|
||||
})),
|
||||
on(projectsActions.getTablesFilterProjectsOptions, (state, action): RootProjects => ({...state, ...(!action.loadMore && {tablesFilterProjectsOptions: null, projectsOptionsScrollId: null})})),
|
||||
);
|
||||
|
||||
@@ -157,7 +157,11 @@ export const viewReducers = [
|
||||
on(layoutActions.visibilityChanged, (state, action): ViewState => ({...state, applicationVisible: action.visible})),
|
||||
on(layoutActions.userThemeChanged, (state, action): ViewState => ({...state, theme: action.theme})),
|
||||
on(layoutActions.systemThemeChanged, (state, action): ViewState => ({...state, systemTheme: action.theme})),
|
||||
on(layoutActions.setForcedTheme, (state, action): ViewState => ({...state, forcedTheme: action.theme, defaultTheme: action.theme})),
|
||||
on(layoutActions.setForcedTheme, (state, action): ViewState => ({
|
||||
...state,
|
||||
forcedTheme: action.theme,
|
||||
...(action.default && {defaultTheme: action.theme})
|
||||
})),
|
||||
on(layoutActions.setThemeColors, (state, action): ViewState => ({...state, themeColors: action.colors})),
|
||||
on(layoutActions.setScaleFactor, (state, action): ViewState => ({...state, scaleFactor: action.scale})),
|
||||
on(layoutActions.firstLogin, (state, action): ViewState => ({
|
||||
@@ -203,7 +207,7 @@ export const viewReducers = [
|
||||
neverShowChangesAgain: action.version
|
||||
})),
|
||||
on(setBreadcrumbs, (state, action): ViewState => ({
|
||||
...state, breadcrumbs: action.breadcrumbs, ...(action.workspaceNeutral !== undefined && {workspaceNeutral: action.workspaceNeutral})
|
||||
...state, breadcrumbs: action.breadcrumbs, workspaceNeutral: action.workspaceNeutral !== undefined ? action.workspaceNeutral: false
|
||||
})),
|
||||
on(headerActions.reset, (state): ViewState => ({
|
||||
...state, headerMenuActiveFeature: initViewState.headerMenuActiveFeature, headerMenu: initViewState.headerMenu
|
||||
|
||||
@@ -68,7 +68,7 @@ export const searchExperiments = createAction(
|
||||
|
||||
export const setExperimentsResults = createAction(
|
||||
SEARCH_PREFIX + 'SET_EXPERIMENTS',
|
||||
props<{ experiments: Task[]; scrollId: string }>()
|
||||
props<{ tasks: Task[]; scrollId: string }>()
|
||||
);
|
||||
|
||||
export const searchModels = createAction(
|
||||
|
||||
@@ -117,7 +117,7 @@ export class DashboardSearchEffects {
|
||||
this.store.select(selectActiveSearch),
|
||||
this.store.select(selectSearchTerm)
|
||||
]),
|
||||
mergeMap(([, active, term]) => {
|
||||
switchMap(([, active, term]) => {
|
||||
const actionsToFire = [];
|
||||
if (!active) {
|
||||
// actionsToFire.push(searchClear());
|
||||
@@ -181,7 +181,7 @@ export class DashboardSearchEffects {
|
||||
order_by: orderBy,
|
||||
/* eslint-enable @typescript-eslint/naming-convention */
|
||||
}).pipe(
|
||||
mergeMap(res => [setProjectsResults({
|
||||
switchMap(res => [setProjectsResults({
|
||||
projects: res.projects,
|
||||
scrollId: res.scroll_id
|
||||
}), deactivateLoader(action.type)]),
|
||||
@@ -315,7 +315,7 @@ export class DashboardSearchEffects {
|
||||
/* eslint-enable @typescript-eslint/naming-convention */
|
||||
}).pipe(
|
||||
mergeMap(res => [setExperimentsResults({
|
||||
experiments: res.tasks,
|
||||
tasks: res.tasks,
|
||||
scrollId: res.scroll_id
|
||||
}), deactivateLoader(action.type)]),
|
||||
catchError(error => [deactivateLoader(action.type), requestFailed(error)])))
|
||||
|
||||
@@ -19,7 +19,7 @@ import {setFilterByUser} from '@common/core/actions/users.actions';
|
||||
|
||||
export interface DashboardSearchState {
|
||||
projects: Project[];
|
||||
experiments: Task[];
|
||||
tasks: Task[];
|
||||
models: Model[];
|
||||
pipelines: Project[];
|
||||
reports: IReport[];
|
||||
@@ -40,7 +40,7 @@ export const searchInitialState: DashboardSearchState = {
|
||||
pipelines: [],
|
||||
openDatasets: [],
|
||||
users: [],
|
||||
experiments: [],
|
||||
tasks: [],
|
||||
models: [],
|
||||
reports: [],
|
||||
resultsCount: null,
|
||||
@@ -78,7 +78,7 @@ export const dashboardSearchReducers = [
|
||||
})),
|
||||
on(setExperimentsResults, (state, action): DashboardSearchState => ({
|
||||
...state,
|
||||
experiments: action.scrollId === state.scrollIds?.[activeSearchLink.experiments] ? state.experiments.concat(action.experiments) : action.experiments,
|
||||
tasks: action.scrollId === state.scrollIds?.[activeSearchLink.experiments] ? state.tasks.concat(action.tasks) : action.tasks,
|
||||
scrollIds: {...state.scrollIds, [activeSearchLink.experiments]: action.scrollId}
|
||||
})),
|
||||
on(setModelsResults, (state, action): DashboardSearchState => ({
|
||||
@@ -98,6 +98,8 @@ export const dashboardSearchReducers = [
|
||||
[activeSearchLink.experiments]: [],
|
||||
[activeSearchLink.pipelines]: [],
|
||||
[activeSearchLink.projects]: [],
|
||||
[activeSearchLink.openDatasets]: [],
|
||||
[activeSearchLink.reports]: [],
|
||||
})),
|
||||
on(searchClear, (state): DashboardSearchState => ({...state, ...searchInitialState})),
|
||||
] as ReducerTypes<DashboardSearchState, ActionCreator[]>[];
|
||||
@@ -109,7 +111,7 @@ export const dashboardSearchReducer = createReducer(
|
||||
|
||||
export const selectSearch = createFeatureSelector<DashboardSearchState>('search');
|
||||
export const selectProjectsResults = createSelector(selectSearch, (state: DashboardSearchState): Array<Project> => state.projects);
|
||||
export const selectExperimentsResults = createSelector(selectSearch, (state: DashboardSearchState): Array<Task> => state.experiments);
|
||||
export const selectExperimentsResults = createSelector(selectSearch, (state: DashboardSearchState): Array<Task> => state.tasks);
|
||||
export const selectModelsResults = createSelector(selectSearch, (state: DashboardSearchState): Array<Model> => state.models);
|
||||
export const selectReportsResults = createSelector(selectSearch, (state: DashboardSearchState): Array<IReport> => state.reports);
|
||||
export const selectPipelinesResults = createSelector(selectSearch, (state: DashboardSearchState): Array<Project> => state.pipelines);
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
<sm-dialog-template>
|
||||
<div class="content">
|
||||
<div class="search-container">
|
||||
<div></div>
|
||||
<sm-search
|
||||
#searchComponent
|
||||
class="outline"
|
||||
[class.regex-error]="regexError"
|
||||
[value]="(searchQuery$ | ngrxPush)?.query"
|
||||
[hideIcons]="true"
|
||||
[minimumChars]="3"
|
||||
(valueChanged)="search($event)"
|
||||
>
|
||||
@if (regexError) {
|
||||
<mat-icon class="error regexp" fontSet="al" fontIcon="al-ico-error-circle" inline [smTooltip]="regexError" [matTooltipPosition]="'below'"></mat-icon>
|
||||
}
|
||||
<button mat-icon-button
|
||||
class="regexp sm"
|
||||
[class.active]="regExp"
|
||||
smClickStopPropagation
|
||||
[smTooltip]="'Regex'" [matTooltipPosition]="'below'"
|
||||
(click)="toggleRegExp(); searchComponent.searchBarInput().nativeElement.focus();"
|
||||
>
|
||||
<mat-icon fontSet="al" fontIcon="al-ico-regex" data-id="enableRegexButton"></mat-icon>
|
||||
</button>
|
||||
</sm-search>
|
||||
<sm-show-only-user-work></sm-show-only-user-work>
|
||||
</div>
|
||||
<sm-dashboard-search (itemSelected)="closeDialog()"></sm-dashboard-search>
|
||||
</div>
|
||||
</sm-dialog-template>
|
||||
@@ -0,0 +1,29 @@
|
||||
|
||||
|
||||
:host {
|
||||
.content{
|
||||
padding-top: 24px;
|
||||
}
|
||||
.search-container{
|
||||
display: grid;
|
||||
grid-auto-columns: minmax(0, 1fr);
|
||||
grid-auto-flow: column;
|
||||
sm-show-only-user-work{
|
||||
margin-left: 12px;
|
||||
}
|
||||
}
|
||||
.regexp {
|
||||
position: absolute;
|
||||
right: 8px;
|
||||
|
||||
&.active {
|
||||
color: var(--color-on-primary);
|
||||
background-color: var(--color-primary);
|
||||
}
|
||||
|
||||
&.error {
|
||||
width: 20px;
|
||||
right: 36px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { GlobalSearchDialogComponent } from './global-search-dialog.component';
|
||||
|
||||
describe('GlobalSearchDialogComponent', () => {
|
||||
let component: GlobalSearchDialogComponent;
|
||||
let fixture: ComponentFixture<GlobalSearchDialogComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [GlobalSearchDialogComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(GlobalSearchDialogComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,132 @@
|
||||
import {ChangeDetectorRef, Component, inject, OnDestroy} from '@angular/core';
|
||||
import {SearchComponent} from '@common/shared/ui-components/inputs/search/search.component';
|
||||
import {DashboardSearchModule} from '~/features/dashboard-search/dashboard-search.module';
|
||||
import {DialogTemplateComponent} from '@common/shared/ui-components/overlay/dialog-template/dialog-template.component';
|
||||
import {Store} from '@ngrx/store';
|
||||
import {searchSetTerm} from '@common/dashboard-search/dashboard-search.actions';
|
||||
import {ActivatedRoute, NavigationEnd, Router} from '@angular/router';
|
||||
import {ClickStopPropagationDirective} from '@common/shared/ui-components/directives/click-stop-propagation.directive';
|
||||
import {MatIcon} from '@angular/material/icon';
|
||||
import {MatIconButton} from '@angular/material/button';
|
||||
import {PushPipe} from '@ngrx/component';
|
||||
import {TooltipDirective} from '@common/shared/ui-components/indicators/tooltip/tooltip.directive';
|
||||
import {distinctUntilChanged, filter} from 'rxjs/operators';
|
||||
import {selectSearchTerm} from '@common/dashboard-search/dashboard-search.reducer';
|
||||
import {Observable} from 'rxjs';
|
||||
import {ShowOnlyUserWorkComponent} from '@common/shared/components/show-only-user-work/show-only-user-work.component';
|
||||
import {MatDialogRef} from '@angular/material/dialog';
|
||||
|
||||
@Component({
|
||||
selector: 'sm-global-search-dialog',
|
||||
imports: [
|
||||
SearchComponent,
|
||||
DashboardSearchModule,
|
||||
DialogTemplateComponent,
|
||||
ClickStopPropagationDirective,
|
||||
MatIcon,
|
||||
MatIconButton,
|
||||
PushPipe,
|
||||
TooltipDirective,
|
||||
ShowOnlyUserWorkComponent
|
||||
],
|
||||
templateUrl: './global-search-dialog.component.html',
|
||||
styleUrl: './global-search-dialog.component.scss'
|
||||
})
|
||||
export class GlobalSearchDialogComponent implements OnDestroy {
|
||||
|
||||
private store = inject(Store);
|
||||
private router = inject(Router);
|
||||
private route = inject(ActivatedRoute);
|
||||
public regExp = false;
|
||||
public regexError: boolean;
|
||||
protected dialogRef = inject<MatDialogRef<GlobalSearchDialogComponent>>(MatDialogRef<GlobalSearchDialogComponent>);
|
||||
|
||||
|
||||
public searchQuery$: Observable<{ query: string; regExp?: boolean; original?: string }>;
|
||||
private itemSelected = false;
|
||||
|
||||
constructor() {
|
||||
this.searchQuery$ = this.store.select(selectSearchTerm);
|
||||
this.router.events
|
||||
.pipe(
|
||||
filter(event => event instanceof NavigationEnd),
|
||||
distinctUntilChanged((pe: NavigationEnd, ce: NavigationEnd) => {
|
||||
const pURL = new URLSearchParams(pe.url.split('?')?.[1]);
|
||||
const cURL = new URLSearchParams(ce.url.split('?')?.[1]);
|
||||
return pURL.get('gq') === cURL.get('gq') && pURL.get('gqreg') === cURL.get('gqreg');
|
||||
})
|
||||
).subscribe(() => {
|
||||
const query = this.route.snapshot.queryParams?.gq ?? '';
|
||||
const qregex = this.route.snapshot.queryParams?.gqreg === 'true';
|
||||
this.regExp = qregex;
|
||||
this.store.dispatch(searchSetTerm({
|
||||
query: qregex ? query : query.trim(),
|
||||
regExp: qregex,
|
||||
}));
|
||||
});
|
||||
if (this.route.snapshot.queryParams.gq) {
|
||||
const query = this.route.snapshot.queryParams?.gq ?? '';
|
||||
const qregex = this.route.snapshot.queryParams?.gqreg ?? false;
|
||||
this.store.dispatch(searchSetTerm({
|
||||
query: qregex ? query : query.trim(),
|
||||
regExp: qregex,
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
if (!this.itemSelected) {
|
||||
this.router.navigate([], {
|
||||
relativeTo: this.route,
|
||||
replaceUrl: true,
|
||||
queryParamsHandling: 'merge',
|
||||
queryParams: {
|
||||
gq: undefined,
|
||||
gqreg: undefined,
|
||||
tab: undefined
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public search(query: string) {
|
||||
try {
|
||||
if (this.regExp) {
|
||||
new RegExp(query);
|
||||
}
|
||||
this.regexError = null;
|
||||
this.router.navigate([], {
|
||||
relativeTo: this.route,
|
||||
replaceUrl: true,
|
||||
queryParamsHandling: 'merge',
|
||||
queryParams: {
|
||||
gq: query || undefined
|
||||
}
|
||||
});
|
||||
|
||||
} catch (e) {
|
||||
this.regexError = e.message?.replace(/:.+:/, ':');
|
||||
}
|
||||
}
|
||||
|
||||
toggleRegExp() {
|
||||
this.regExp = !this.regExp;
|
||||
if(!this.regExp) {
|
||||
this.regexError = null;
|
||||
}
|
||||
this.router.navigate([], {
|
||||
relativeTo: this.route,
|
||||
replaceUrl: true,
|
||||
queryParamsHandling: 'merge',
|
||||
queryParams: {
|
||||
gqreg: this.regExp ? this.regExp : undefined
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
closeDialog() {
|
||||
this.itemSelected = true;
|
||||
this.dialogRef.close();
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "mixins/common";
|
||||
@use "mixins/common";
|
||||
|
||||
:host {
|
||||
.recent-header {
|
||||
@@ -15,6 +15,6 @@
|
||||
}
|
||||
|
||||
.recent-title {
|
||||
@include recent-title();
|
||||
@include common.recent-title();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,10 +4,11 @@ import {IRecentTask} from '../../common-dashboard.reducer';
|
||||
import {ITask} from '~/business-logic/model/al-task';
|
||||
|
||||
@Component({
|
||||
selector: 'sm-dashboard-experiments',
|
||||
templateUrl: './dashboard-experiments.component.html',
|
||||
styleUrls: ['./dashboard-experiments.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
selector: 'sm-dashboard-experiments',
|
||||
templateUrl: './dashboard-experiments.component.html',
|
||||
styleUrls: ['./dashboard-experiments.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone: false
|
||||
})
|
||||
export class DashboardExperimentsComponent {
|
||||
private router = inject(Router);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "mixins/common";
|
||||
@use "mixins/common";
|
||||
|
||||
.view-all {
|
||||
font-size: 12px;
|
||||
@@ -16,8 +16,8 @@
|
||||
.sm-card-list-header {
|
||||
grid-column: 1 / -1;
|
||||
padding: 0;
|
||||
height: unset;
|
||||
height: 38px;
|
||||
}
|
||||
.recent-title {
|
||||
@include recent-title();
|
||||
@include common.recent-title();
|
||||
}
|
||||
|
||||
@@ -14,9 +14,10 @@ import {CARDS_IN_ROW} from '../../common-dashboard.const';
|
||||
import {takeUntilDestroyed} from '@angular/core/rxjs-interop';
|
||||
|
||||
@Component({
|
||||
selector : 'sm-dashboard-projects',
|
||||
templateUrl: './dashboard-projects.component.html',
|
||||
styleUrls : ['./dashboard-projects.component.scss']
|
||||
selector: 'sm-dashboard-projects',
|
||||
templateUrl: './dashboard-projects.component.html',
|
||||
styleUrls: ['./dashboard-projects.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class DashboardProjectsComponent {
|
||||
private store = inject(Store);
|
||||
|
||||