diff options
Diffstat (limited to 'src')
184 files changed, 46345 insertions, 0 deletions
diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts new file mode 100644 index 0000000..0f5a50e --- /dev/null +++ b/src/app/app-routing.module.ts @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; +import { PageNotFoundComponent } from './components/page-not-found/page-not-found'; +import { StatusPageComponent } from './components/shared/status-page/status-page.component'; + +const routes: Routes = [ + { + path: 'dashboard', + loadChildren: () => import('./modules/dashboard/dashboard.module').then(m => m.DashboardModule), + }, + { + path: 'app-starter', + loadChildren: () => import('./modules/app-starter/app-starter.module').then(m => m.AppStarterModule), + }, + { path: 'statusPage', component: StatusPageComponent }, + { path: '', redirectTo: '/dashboard', pathMatch: 'full' }, + { + path: 'user-administration', + loadChildren: () => + import('./modules/user-administration/user-administration.module').then(m => m.UserAdministrationModule), + }, + { + path: 'not-found', + component: PageNotFoundComponent, + }, + { + path: '**', + redirectTo: 'not-found', + }, +]; + +@NgModule({ + imports: [RouterModule.forRoot(routes, { relativeLinkResolution: 'legacy', onSameUrlNavigation: 'reload' })], + exports: [RouterModule], +}) +export class AppRoutingModule {} diff --git a/src/app/app.component.css b/src/app/app.component.css new file mode 100644 index 0000000..7c4cb60 --- /dev/null +++ b/src/app/app.component.css @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +*:focus { + outline: 3px dashed; +} + +.wrapper { + display: flex; + height: calc(100vh - 55px); + width: 100%; + align-items: stretch; +} + +a[data-toggle='collapse'] { + position: relative; +} + +.dropdown-toggle::after { + display: block; + position: absolute; + top: 50%; + right: 20px; + transform: translateY(-50%); +} + +.bi-list:focus, +.bi-list:hover { + outline: none; +} + +.bi-list:hover { + background-color: #cb026e; + border-radius: 2px; +} + +main.container-fluid { + overflow-x: hidden; +} + +.loading-spinner { + position: fixed; + top: 0; + left: 0; + bottom: 0; + right: 0; + z-index: 1001; + /*background-color: rgba(0, 0, 0, 0.5);*/ +} + +.large-spinner { + width: 6rem; + height: 6rem; +} + +.loading-text { + width: 90px; + position: absolute; + top: calc(50% - 15px); + left: calc(50% - 45px); + text-align: center; +} + +.spinner-border { + animation: spinner-border 1s linear infinite !important; +} diff --git a/src/app/app.component.html b/src/app/app.component.html new file mode 100644 index 0000000..327725c --- /dev/null +++ b/src/app/app.component.html @@ -0,0 +1,52 @@ +<!-- + ~ Copyright (c) 2022. Deutsche Telekom AG + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + ~ + ~ SPDX-License-Identifier: Apache-2.0 + --> + +<app-header + (collapse)="collapseChanged()" + class="sticky-top" +></app-header> +<div class="wrapper"> + <aside class="h-100 pt-2" id="nav-sidebar" [attr.aria-label]="'layout.sidebar' | translate"> + <app-sidemenu [isSidebarCollapsed]="isCollapsed"></app-sidemenu> + </aside> + <main + [attr.accesskey]='ACCESS_KEY.SHORTCUT_2' + id="main" + tabindex="-1" + class="container-fluid px-5 position-relative" + [attr.aria-label]="'layout.main.mainContent' | translate" + > + <ng-container *ngIf="loading$ | async"> + <div + [style.left.px]="isCollapsed ? 60 : 250" + class="row justify-content-center align-items-center loading-spinner" + > + <div class="loading-text text-primary">{{ 'common.loading' | translate }}</div> + <div class="spinner-border text-primary large-spinner" role="status"></div> + </div> + </ng-container> + <div + class="position-absolute right-10 mt-3" + style="z-index: 999" + [attr.aria-label]="'layout.main.alerts' | translate" + > + <app-alert></app-alert> + </div> + <router-outlet class="p-2"></router-outlet> + </main> +</div> diff --git a/src/app/app.component.spec.ts b/src/app/app.component.spec.ts new file mode 100644 index 0000000..8e7c92c --- /dev/null +++ b/src/app/app.component.spec.ts @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { TestBed, waitForAsync } from '@angular/core/testing'; +import { RouterTestingModule } from '@angular/router/testing'; +import { AppComponent } from './app.component'; +import { AppStarterComponent } from './modules/app-starter/app-starter.component'; +import { OAuthLogger, OAuthService, UrlHelperService } from 'angular-oauth2-oidc'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { AlertModule } from './modules/alerting'; +import { SidemenuComponent } from './components/layout/sidemenu/sidemenu.component'; +import { HeaderComponent } from './components/layout/header/header/header.component'; +import { TranslateModule } from '@ngx-translate/core'; +import { HasPermissionsDirective } from './directives/has-permissions.directive'; +import { LoadingIndicatorService } from './services/loading-indicator.service'; + +describe('AppComponent', () => { + let component: AppComponent; + beforeEach( + waitForAsync(() => { + TestBed.configureTestingModule({ + declarations: [ + AppComponent, + AppStarterComponent, + SidemenuComponent, + HeaderComponent, + HasPermissionsDirective, + ], + imports: [RouterTestingModule, HttpClientTestingModule, AlertModule, TranslateModule], + providers: [ + AppComponent, + UrlHelperService, + OAuthService, + OAuthLogger, + LoadingIndicatorService + ], + }).compileComponents(); + component = TestBed.inject(AppComponent); + }), + ); + it('should create the app', () => { + expect(component).toBeTruthy(); + }); + + it(`should have as title 'frontend'`, () => { + expect(component.title).toEqual('frontend'); + }); +}); diff --git a/src/app/app.component.ts b/src/app/app.component.ts new file mode 100644 index 0000000..1eacc21 --- /dev/null +++ b/src/app/app.component.ts @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Component, Inject } from '@angular/core'; +import { AlertService } from './modules/alerting'; +import { environment } from '../environments/environment'; +import { DOCUMENT } from '@angular/common'; +import { LoadingIndicatorService } from 'src/app/services/loading-indicator.service'; +import { KeyboardShortcuts } from './services/shortcut.service'; + +@Component({ + selector: 'app-root', + templateUrl: './app.component.html', + styleUrls: ['./app.component.css'], +}) +export class AppComponent { + title = 'frontend'; + isCustomStyleEnabled = environment.customStyleEnabled; + readonly loading$ = this.loadingIndicator.isVisible(); + public isCollapsed = false + public ACCESS_KEY = KeyboardShortcuts; + + constructor( + protected alertService: AlertService, + private loadingIndicator: LoadingIndicatorService, + @Inject(DOCUMENT) private document: Document, + ) { + } + + collapseChanged() { + this.isCollapsed = !this.isCollapsed; + + } +} diff --git a/src/app/app.module.ts b/src/app/app.module.ts new file mode 100644 index 0000000..faeb566 --- /dev/null +++ b/src/app/app.module.ts @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { BrowserModule } from '@angular/platform-browser'; +import { NgModule } from '@angular/core'; +import { AppRoutingModule } from './app-routing.module'; +import { AppComponent } from './app.component'; +import { HeaderComponent } from './components/layout/header/header/header.component'; +import { OAuthModule, OAuthStorage } from 'angular-oauth2-oidc'; +import { AuthConfigModule } from './modules/auth/auth.config.module'; +import { HttpClientModule } from '@angular/common/http'; +import { AlertModule } from './modules/alerting'; +import { ModalContentComponent } from './components/modal/modal-content'; +import { RequestCache, RequestCacheService } from './services/cacheservice/request-cache.service'; +import { httpInterceptorProviders } from './http-interceptors/interceptors'; +import { SidemenuComponent } from './components/layout/sidemenu/sidemenu.component'; +import { ConfirmationModalComponent } from './components/shared/confirmation-modal/confirmation-modal.component'; +import { environment } from '../environments/environment'; +import { ApiModule, Configuration } from '../../openapi/output'; +import { LoadingIndicatorService } from 'src/app/services/loading-indicator.service'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { PageNotFoundComponent } from './components/page-not-found/page-not-found'; +import { RouteReuseStrategy } from '@angular/router'; +import { AppRouteReuseStrategy } from './router.strategy'; +import { StatusPageComponent } from './components/shared/status-page/status-page.component'; +import { UserAdministrationModule } from './modules/user-administration/user-administration.module'; +import { SharedModule } from './shared.module'; +import { AppStarterModule } from './modules/app-starter/app-starter.module'; +import { DashboardModule } from './modules/dashboard/dashboard.module'; +// Sentry.init({ +// dsn: 'http://726f0fcf0f55429eb1c7e613d25d2daf@10.212.1.83:9000/2', + +// // Enable performance metrics: https://docs.sentry.io/performance-monitoring/getting-started/?platform=javascript +// integrations: [new TracingIntegrations.BrowserTracing()], +// tracesSampleRate: 0.2, +// }); + +// @Injectable() +// export class SentryErrorHandler implements ErrorHandler { +// constructor() {} +// handleError(error: any) { +// Sentry.captureException(error.originalError || error); +// throw error; +// } +// } + +export function changeConfig() { + return new Configuration({ basePath: environment.backendServerUrl }); +} + +@NgModule({ + declarations: [ + AppComponent, + HeaderComponent, + ModalContentComponent, + SidemenuComponent, + PageNotFoundComponent, + ConfirmationModalComponent, + StatusPageComponent, + ], + imports: [ + BrowserModule, + AppRoutingModule, + HttpClientModule, + AuthConfigModule, + AlertModule, + AuthConfigModule, + ApiModule.forRoot(changeConfig), + OAuthModule.forRoot({ resourceServer: { sendAccessToken: false } }), + BrowserAnimationsModule, + UserAdministrationModule, + DashboardModule, + SharedModule, + AppStarterModule, + ], + // { provide: ErrorHandler, useClass: SentryErrorHandler }, + providers: [ + { provide: RequestCache, useClass: RequestCacheService }, + httpInterceptorProviders, + { provide: OAuthStorage, useValue: localStorage }, + LoadingIndicatorService, + { provide: RouteReuseStrategy, useClass: AppRouteReuseStrategy }, + ], + bootstrap: [AppComponent], + entryComponents: [ModalContentComponent, ConfirmationModalComponent], +}) +export class AppModule {} diff --git a/src/app/components/layout/header/header/header.component.css b/src/app/components/layout/header/header/header.component.css new file mode 100644 index 0000000..21de90f --- /dev/null +++ b/src/app/components/layout/header/header/header.component.css @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +.navbar { + background-color: #e7e6e6; +} + +.bi-list { + font-size: 1.5rem; +} + +.dropdown-menu { + border-radius: 10px; + border: 0.5px solid #b2b2b2; + text-align: center; + box-shadow: 3px 3px 20px lightslategray; +} + +#dropdown-user, +#dropdown-settings { + text-align: left; +} + +#dropdownMenu:hover, +#dropdownMenu:focus { + background-color: #e7e6e6; +} + +.dropdown-divider { + border-color: #b2b2b2; +} + +.navbar-collapse.collapse.in { + display: inline-block; +} + +.dropdown-toggle::after { + content: initial; +} + +.navbar-toggler { + color: black; +} + +.sidebar-toggler { + background-color: transparent; + border-style: none; +} + +.btn-account { + color: black; + background-color: transparent; + border-style: none; + font-size: 21px; + line-height: 1.225; +} + +.btn:hover { + background-color: #e7e6e6; +} + +/* Make ONAP logo as large as the Telekom one */ +.brand-image { + height: 36px; +} + +.bi.bi-person-fill, +.bi.bi-caret-down-fill { + color: black; +} + +/* Add a clearly visible outline while tabbing */ +:focus-visible { + box-shadow: 0 0 0 2px black; +} +dl > * { + text-align: left; +} + +hr { + margin-top: 1.4rem; + margin-bottom: 1.4rem; + border: 0; + border-top: 1px solid; +} + +.btn { + white-space: nowrap; + display: block; +} + +.btn:hover { + color: var(--black); +} + +.btn-sm, +.btn-group-sm > .btn { + padding: 0.4rem 1.5rem 0.476rem; +} diff --git a/src/app/components/layout/header/header/header.component.html b/src/app/components/layout/header/header/header.component.html new file mode 100644 index 0000000..8e23ffd --- /dev/null +++ b/src/app/components/layout/header/header/header.component.html @@ -0,0 +1,142 @@ +<!-- + ~ Copyright (c) 2022. Deutsche Telekom AG + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + ~ + ~ SPDX-License-Identifier: Apache-2.0 + --> + +<nav id="brand-bar" class="navbar navbar-light navbar-expand pl-2"> + <button + type="button" + id="sidebarCollapse" + class="sidebar-toggler" + (click)="toggleSidenav()" + [attr.aria-label]="'layout.header.sidebarToggler' | translate" + > + <i class="bi bi-list" aria-hidden="true"></i> + </button> + + <!-- Logo as Home Button --> + <a class="ml-3" [routerLink]="['/']"> + <img + class="brand-image pl-0" + id="img-logo" + src="assets/images/onap-logo.png" + alt="{{ 'layout.header.logo.onap' | translate }}" + /> + </a> + + <div class="d-flex ml-auto align-items-baseline"> + <button + class="btn btn-invisible p-2 pointer" + [attr.accesskey]="ACCESS_KEY.SHORTCUT_0" + (click)="openCanvas(content)" + [attr.aria-label]="'Help'" + [ngbTooltip]="'Help'" + > + <i aria-hidden="true" class="bi bi-question-circle black"></i> + </button> + <button + *ngIf="!isFullScreen" + class="btn btn-invisible pointer p-2 qa_btn_open_fullscreen" + [attr.aria-label]="'layout.header.button.openFullscreen' | translate" + [ngbTooltip]="'Full screen'" + (click)="openFullscreen()" + > + <i aria-hidden="true" class="bi bi-arrows-fullscreen black"></i> + </button> + <button + *ngIf="isFullScreen" + class="btn btn-invisible pointer p-2 qa_btn_cls_fullscreen" + [attr.aria-label]="'layout.header.button.closeFullscreen' | translate" + [ngbTooltip]="'Exit full screen'" + (click)="closeFullscreen()" + > + <i aria-hidden="true" class="bi bi-fullscreen-exit black"></i> + </button> + </div> + + <!-- Dropdown menu --> + <div ngbDropdown #userAccountDropdown="ngbDropdown" display="dynamic"> + <button + ngbDropdownToggle + id="dropdownMenu" + class="btn btn-account px-3 tab-focus" + [attr.aria-label]="'layout.header.button.useraccount' | translate" + aria-haspopup="true" + > + <i class="bi bi-person-fill" aria-hidden="true"></i> + <i class="bi bi-caret-down-fill" aria-hidden="true"></i> + </button> + <div class="dropdown-menu-right px-4" ngbDropdownMenu aria-labelledby="dropdownMenu" + style="z-index: 9999; min-width: 380px"> + <div class="d-flex justify-content-between align-items-center"> + <div> + <i aria-hidden="true" class="bi bi-person"></i> + {{ profile }} + </div> + <button + class="btn btn-sm btn-primary font-weight-bold" + (click)="userAccountDropdown.close(); logOut()" + [attr.aria-label]="'layout.header.button.logout' | translate" + > + {{ 'layout.header.button.logout' | translate }} + </button> + </div> + <hr /> + <dl> + <dt>{{ 'layout.header.info.name' | translate }}</dt> + <dd>{{ profile }}</dd> + <dt>{{ 'layout.header.info.mail' | translate }}</dt> + <dd>{{ email }}</dd> + </dl> + <hr /> + <button + type="button" + class="btn btn-sm btn-outline-secondary" + placement="top" + container="body" + triggers="click:blur" + [ngbTooltip]="'userAdministration.form.title.changePasswordTooltip' | translate" + > + {{ 'userAdministration.form.title.changePassword' | translate }} + </button> + </div> + </div> +</nav> + +<ng-template #content let-offcanvas> + <div class="offcanvas-header"> + <div class="d-flex"> + <h3 class="mb-0 mr-1">{{ 'layout.header.shortcuts.heading' | translate }}</h3> + </div> + <button + type="button" + class="align-self-center btn-close" + [attr.aria-label]="'common.buttons.close' | translate" + (click)="offcanvas.dismiss(content)" + ></button> + </div> + <div class="offcanvas-body"> + <p class="border-bottom pb-2" *ngFor="let shortcut of shortcuts | keyvalue"> + {{ shortcut.key }} - {{ shortcut.value }} + </p> + <div class="text-muted small"> + <p>{{ 'layout.header.shortcuts.helpText' | translate }}</p> + <div [innerHTML]="'layout.header.shortcuts.helpBrowser1' | translate"></div> + <div [innerHTML]="'layout.header.shortcuts.helpBrowser2' | translate"></div> + <div [innerHTML]="'layout.header.shortcuts.helpBrowser3' | translate"></div> + </div> + </div> +</ng-template> diff --git a/src/app/components/layout/header/header/header.component.spec.ts b/src/app/components/layout/header/header/header.component.spec.ts new file mode 100644 index 0000000..cb40e73 --- /dev/null +++ b/src/app/components/layout/header/header/header.component.spec.ts @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { HeaderComponent } from './header.component'; + +describe('HeaderComponent', () => { + let component: HeaderComponent; + let fixture: ComponentFixture<HeaderComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [HeaderComponent], + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(HeaderComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/components/layout/header/header/header.component.ts b/src/app/components/layout/header/header/header.component.ts new file mode 100644 index 0000000..f5c1a1c --- /dev/null +++ b/src/app/components/layout/header/header/header.component.ts @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { + Component, + Output, + EventEmitter, + OnInit, + HostListener, + ElementRef, + ViewChild, + TemplateRef, +} from '@angular/core'; +import { OAuthService } from 'angular-oauth2-oidc'; +import { FullscreenService } from 'src/app/services/fullscreen.service'; +import { environment } from 'src/environments/environment'; +import { KeyboardShortcuts, ShortcutService } from 'src/app/services/shortcut.service'; +import { NgbOffcanvas } from '@ng-bootstrap/ng-bootstrap'; + +@Component({ + selector: 'app-header', + templateUrl: './header.component.html', + styleUrls: ['./header.component.css'], +}) +export class HeaderComponent implements OnInit { +@Output() collapse = new EventEmitter<void>() + + /** + * + * @param {OAuthService} oauthService + */ + isOnapTheme = false; + switchToMainContent: string = ''; + isFullScreen = false; + changePasswordUrl = `${environment.keycloakEditProfile}/password`; + shortcuts: Map<KeyboardShortcuts,string> = this.shortcutService.getShortcuts(); + + public ACCESS_KEY = KeyboardShortcuts; + @ViewChild('myNavElement') myNavElement!: ElementRef; + + constructor( + private readonly fullscreenService: FullscreenService, + private readonly oauthService: OAuthService, + private offcanvasService: NgbOffcanvas, + private shortcutService: ShortcutService + ) {} + ngOnInit(): void { + this.checkScreenMode(); + } + + @HostListener('document:fullscreenchange', ['$event']) + @HostListener('document:webkitfullscreenchange', ['$event']) + @HostListener('document:mozfullscreenchange', ['$event']) + @HostListener('document:MSFullscreenChange', ['$event']) + private checkScreenMode() { + this.isFullScreen = !!document.fullscreenElement; + } + + public openFullscreen() { + this.fullscreenService.enter(); + } + public closeFullscreen() { + this.fullscreenService.leave(); + } + + public logIn() { + this.oauthService.initCodeFlow(); + } + + public logOut() { + this.oauthService.logOut(); + } + + get profile() { + const claims = Object(this.oauthService.getIdentityClaims()); + return claims.given_name ? claims.given_name : 'no Name'; + } + + get email() { + const claims = Object(this.oauthService.getIdentityClaims()); + return claims.email ? claims.email : 'no Email'; + } + + public toggleSidenav() { + this.collapse.emit(); + } + + + public openCanvas(content: TemplateRef<any>) { + const isCanvasOpened = this.offcanvasService.hasOpenOffcanvas(); + if (isCanvasOpened) { + this.offcanvasService.dismiss(); + } else { + this.offcanvasService.open(content, { ariaLabelledBy: 'Keyboard shortcuts', position: 'end' }); + } + } +} diff --git a/src/app/components/layout/sidemenu/sidemenu.component.css b/src/app/components/layout/sidemenu/sidemenu.component.css new file mode 100644 index 0000000..23831b7 --- /dev/null +++ b/src/app/components/layout/sidemenu/sidemenu.component.css @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +/* Sidebar container with nav menu */ +#sidebar-container { + margin-right: -1px; + flex: 0 0 230px; + border-right-style: solid; + border-right-width: 1px; + border-right-color: #b2b2b2; +} + +/* Menu item*/ +.nav a { + height: 50px; + color: black; +} + +/* Li elements from sidemenu. Thanks to padding is :focus pseudo-class visible for keyboard users*/ +.nav li { + padding: 2px; +} + +/* Separators */ +.sidebar-separator-title { + height: 2em; +} + +/* Sidebar sizes when collapsed*/ +.sidebar-collapsed { + min-width: 60px !important; + max-width: 63px !important; + height: auto; +} + +/* Sidebar sizes when expanded*/ +.sidebar-expanded { + min-width: 250px; + max-width: 250px; + height: 100%; + display: block; + border-right-style: solid; + border-right-width: 1px; + border-right-color: #c5c5c5; +} + +/* Hide list item and grouping item title if container sidebar is collapsed */ +.sidebar-collapsed a.nav-link span, +.sidebar-collapsed li.sidebar-separator-title small { + display: none !important; +} + +/* Hide grouping item icon if container sidebar is collapsed */ +.sidebar-expanded ul li.sidebar-separator-title i, +.sidebar-expanded ul li.sidebar-separator-title img { + display: none !important; +} + +/* Show grouping item icon if container sidebar is collapsed */ +.sidebar-collapsed ul li.sidebar-separator-title i, +.sidebar-collapsed ul li.sidebar-separator-title img { + display: inline-block; +} + +/* All list items */ +.nav-link { + border-style: none; + display: block !important; + padding: 0.75rem 1rem; +} + +ul { + list-style-type: none; +} + +.active-menu-item { + background-color: var(--active-gray); + color: black; + border-top-left-radius: 0.25rem !important; + border-bottom-left-radius: 0.25rem !important; + border-left: 2px solid var(--primary) !important; +} + +.nav.inner li { + border: none; +} + +.portal-version-title, +.portal-version-number { + font-size: 13px; +} + +img { + width: 18px; + height: 19px; + vertical-align: -0.125em; +} diff --git a/src/app/components/layout/sidemenu/sidemenu.component.html b/src/app/components/layout/sidemenu/sidemenu.component.html new file mode 100644 index 0000000..fd97c50 --- /dev/null +++ b/src/app/components/layout/sidemenu/sidemenu.component.html @@ -0,0 +1,51 @@ +<!-- + ~ Copyright (c) 2022. Deutsche Telekom AG + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + ~ + ~ SPDX-License-Identifier: Apache-2.0 + --> + + +<nav + [class.sidebar-collapsed]="isSidebarCollapsed" + id="sidebar-container" + class="sidebar-expanded overflow-auto d-flex flex-column justify-content-between" + [attr.aria-label]="'layout.menu.mainMenu' | translate" +> + <ul class="nav flex-column flex-nowrap" [attr.aria-label]="'layout.menu.menuItems' | translate"> + <li class="nav-item"> + <a #test [attr.accesskey]='ACCESS_KEY.SHORTCUT_6' class="nav-link" routerLinkActive="active-menu-item" [routerLink]="['/dashboard']"> + <i class="bi bi-house-door mr-4" aria-hidden="true"></i> + <span class="d-sm-inline qa_menu_home">{{ 'layout.menu.items.dashboard' | translate }}</span></a + > + </li> + <li class="nav-item"> + <a class="nav-link" routerLinkActive="active-menu-item" [routerLink]="['/app-starter']"> + <i class="bi bi-grid mr-4" aria-hidden="true"></i> + <span class="d-sm-inline qa_menu_app_starter">{{ 'layout.menu.items.appStarter' | translate }}</span></a + > + </li> + + <li class="nav-item" [appHasPermissions]="'users.administration.list'"> + <a class="nav-link" routerLinkActive="active-menu-item" routerLink="/user-administration"> + <i class="bi bi-people mr-4" aria-hidden="true"></i> + <span class="d-sm-inline qa_menu_users">{{ 'layout.menu.items.users' | translate }}</span></a + > + </li> + </ul> + <div [ngClass]="isSidebarCollapsed ? 'flex-column' : 'flex-row'" class="d-flex justify-content-center text-center"> + <h5 class="portal-version-title mr-1" id="portal-version">Portal Version:</h5> + <span class="portal-version-number" aria-labelledby="portal-version" (click)='test.blur()'>{{versionNumber}}</span> + </div> +</nav> diff --git a/src/app/components/layout/sidemenu/sidemenu.component.spec.ts b/src/app/components/layout/sidemenu/sidemenu.component.spec.ts new file mode 100644 index 0000000..1067c49 --- /dev/null +++ b/src/app/components/layout/sidemenu/sidemenu.component.spec.ts @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SidemenuComponent } from './sidemenu.component'; + +describe('SidemenuComponent', () => { + let component: SidemenuComponent; + let fixture: ComponentFixture<SidemenuComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [SidemenuComponent], + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(SidemenuComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/components/layout/sidemenu/sidemenu.component.ts b/src/app/components/layout/sidemenu/sidemenu.component.ts new file mode 100644 index 0000000..1f5c123 --- /dev/null +++ b/src/app/components/layout/sidemenu/sidemenu.component.ts @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +import { Component, Injectable, Input } from '@angular/core'; +import { environment } from 'src/environments/environment'; +import VersionJson from 'src/assets/version.json'; +import { KeyboardShortcuts } from '../../../services/shortcut.service'; + +@Injectable({ + providedIn: 'root', +}) +@Component({ + selector: 'app-sidemenu', + templateUrl: './sidemenu.component.html', + styleUrls: ['./sidemenu.component.css'], +}) +export class SidemenuComponent { + versionNumber: string; + + @Input() isSidebarCollapsed = false; + + public ACCESS_KEY = KeyboardShortcuts; + public keycloakEditProfile = environment.keycloakEditProfile; + public isKpiDashboardSubMenuCollapsed = false; + + constructor() { + this.versionNumber = VersionJson.number; + } + collapsed() { + this.isKpiDashboardSubMenuCollapsed = !this.isKpiDashboardSubMenuCollapsed; + } +} diff --git a/src/app/components/modal/modal-content.html b/src/app/components/modal/modal-content.html new file mode 100644 index 0000000..ec3b6c4 --- /dev/null +++ b/src/app/components/modal/modal-content.html @@ -0,0 +1,30 @@ +<!-- + ~ Copyright (c) 2022. Deutsche Telekom AG + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + ~ + ~ SPDX-License-Identifier: Apache-2.0 + --> + + +<div class="modal-body m-3" style="text-align: justify"> + <h4 class="modal-title">{{'modal.error.accessDenied' | translate}}</h4> + <p><br />{{'modal.error.accessDenied' | translate}}</p> + <details> + <summary>{{'modal.error.details' | translate}}</summary> + <p>{{message}}</p> + </details> + <div style="text-align: right"> + <button class="btn btn-primary" (click)="oauthService.logOut()">Logout</button> + </div> +</div> diff --git a/src/app/components/modal/modal-content.ts b/src/app/components/modal/modal-content.ts new file mode 100644 index 0000000..01211df --- /dev/null +++ b/src/app/components/modal/modal-content.ts @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Component, Input } from '@angular/core'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { OAuthService } from 'angular-oauth2-oidc'; + +@Component({ + selector: 'app-modal-content', + templateUrl: './modal-content.html', +}) +export class ModalContentComponent { + @Input() message: any; + + constructor(public activeModal: NgbActiveModal, public oauthService: OAuthService) {} +} diff --git a/src/app/components/modal/modal.service.ts b/src/app/components/modal/modal.service.ts new file mode 100644 index 0000000..083bcb1 --- /dev/null +++ b/src/app/components/modal/modal.service.ts @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Injectable } from '@angular/core'; +import { NgbModal, NgbModalConfig } from '@ng-bootstrap/ng-bootstrap'; +import { ModalContentComponent } from './modal-content'; + +@Injectable({ + providedIn: 'root', +}) +export class ModalService { + constructor(private modalService: NgbModal, private modalConfig: NgbModalConfig) { + // customize default values of modals used by this component tree + modalConfig.backdrop = 'static'; + modalConfig.keyboard = false; + } + + open(message: string) { + const modalRef = this.modalService.open(ModalContentComponent,{backdropClass:'backdropClass'}); + modalRef.componentInstance.message = message; + } +} diff --git a/src/app/components/page-not-found/page-not-found.css b/src/app/components/page-not-found/page-not-found.css new file mode 100644 index 0000000..2c10482 --- /dev/null +++ b/src/app/components/page-not-found/page-not-found.css @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +.wrapper { + position: fixed; + top: 50%; + left: 50%; + transform: translate(-40%, -50%); +} + +.woman-img { + height: 350px; +} + +.icon { + position: absolute; + top: 5px; + font-size: 30px; + color: var(--primary); +} diff --git a/src/app/components/page-not-found/page-not-found.html b/src/app/components/page-not-found/page-not-found.html new file mode 100644 index 0000000..6ad90c6 --- /dev/null +++ b/src/app/components/page-not-found/page-not-found.html @@ -0,0 +1,29 @@ +<!-- + ~ Copyright (c) 2022. Deutsche Telekom AG + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + ~ + ~ SPDX-License-Identifier: Apache-2.0 + --> + + +<div class="container text-center wrapper"> + <img + class="woman-img mb-5" + src="assets/images/icons/standing-woman.svg" + alt="{{'pageNotFound.imgAltText' | translate}}" + /> + <i class="bi bi-x-circle-fill icon" aria-hidden="true"></i> + <h3 class="mb-3">{{'pageNotFound.text' | translate}}</h3> + <button type="button" class="btn btn-primary" routerLink="/dashboard">{{'pageNotFound.button' | translate}}</button> +</div> diff --git a/src/app/components/page-not-found/page-not-found.ts b/src/app/components/page-not-found/page-not-found.ts new file mode 100644 index 0000000..88cdc01 --- /dev/null +++ b/src/app/components/page-not-found/page-not-found.ts @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-page-not-found', + templateUrl: './page-not-found.html', + styleUrls: ['./page-not-found.css'], +}) +export class PageNotFoundComponent {} diff --git a/src/app/components/shared/breadcrumb-item/breadcrumb-item.component.html b/src/app/components/shared/breadcrumb-item/breadcrumb-item.component.html new file mode 100644 index 0000000..72d5c79 --- /dev/null +++ b/src/app/components/shared/breadcrumb-item/breadcrumb-item.component.html @@ -0,0 +1,22 @@ +<!-- + ~ Copyright (c) 2022. Deutsche Telekom AG + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + ~ + ~ SPDX-License-Identifier: Apache-2.0 + --> + + +<ng-template> + <ng-content></ng-content> +</ng-template> diff --git a/src/app/components/shared/breadcrumb-item/breadcrumb-item.component.ts b/src/app/components/shared/breadcrumb-item/breadcrumb-item.component.ts new file mode 100644 index 0000000..5f74fff --- /dev/null +++ b/src/app/components/shared/breadcrumb-item/breadcrumb-item.component.ts @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Component, TemplateRef, ViewChild } from '@angular/core'; + +@Component({ + selector: 'app-breadcrumb-item', + templateUrl: './breadcrumb-item.component.html', +}) +export class BreadcrumbItemComponent { + @ViewChild(TemplateRef, { static: true }) + readonly template!: TemplateRef<any>; +} diff --git a/src/app/components/shared/breadcrumb/breadcrumb.component.html b/src/app/components/shared/breadcrumb/breadcrumb.component.html new file mode 100644 index 0000000..e6cdba5 --- /dev/null +++ b/src/app/components/shared/breadcrumb/breadcrumb.component.html @@ -0,0 +1,26 @@ +<!-- + ~ Copyright (c) 2022. Deutsche Telekom AG + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + ~ + ~ SPDX-License-Identifier: Apache-2.0 + --> + + +<nav [attr.aria-label]="'layout.main.breadcrumb' | translate"> + <ol class="breadcrumb"> + <li *ngFor="let item of items; index as i" class="breadcrumb-item"> + <ng-container *ngTemplateOutlet="item.template" accessKey='3'></ng-container> + </li> + </ol> +</nav> diff --git a/src/app/components/shared/breadcrumb/breadcrumb.component.ts b/src/app/components/shared/breadcrumb/breadcrumb.component.ts new file mode 100644 index 0000000..864a9ff --- /dev/null +++ b/src/app/components/shared/breadcrumb/breadcrumb.component.ts @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Component, ContentChildren, QueryList } from '@angular/core'; +import { BreadcrumbItemComponent } from '../breadcrumb-item/breadcrumb-item.component'; + +@Component({ + selector: 'app-breadcrumb', + templateUrl: './breadcrumb.component.html', +}) +export class BreadcrumbComponent { + @ContentChildren(BreadcrumbItemComponent) + readonly items!: QueryList<BreadcrumbItemComponent>; +} diff --git a/src/app/components/shared/confirmation-modal/confirmation-modal.component.html b/src/app/components/shared/confirmation-modal/confirmation-modal.component.html new file mode 100644 index 0000000..4f26c5d --- /dev/null +++ b/src/app/components/shared/confirmation-modal/confirmation-modal.component.html @@ -0,0 +1,35 @@ +<!-- + ~ Copyright (c) 2022. Deutsche Telekom AG + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + ~ + ~ SPDX-License-Identifier: Apache-2.0 + --> + + +<div class="modal-header qa_modal_header"> + <h4 class="modal-title qa_modal_title" id="modal-title"> + <strong>{{ title }}</strong> + </h4> +</div> +<div class="modal-body qa_modal_body"> + <p> + {{ text }} + </p> +</div> +<div *ngIf='showOkBtn || showCancelBtn' class="modal-footer qa_modal_footer"> + <button *ngIf='showCancelBtn' type="button" class="btn btn-default qa_cancel_button" (click)="activeModal.close(false)"> + {{ cancelText }} + </button> + <button *ngIf='showOkBtn' type="button" class="btn btn-danger qa_apply_button" (click)="activeModal.close(true)">{{ okText }}</button> +</div> diff --git a/src/app/components/shared/confirmation-modal/confirmation-modal.component.spec.ts b/src/app/components/shared/confirmation-modal/confirmation-modal.component.spec.ts new file mode 100644 index 0000000..b7b5110 --- /dev/null +++ b/src/app/components/shared/confirmation-modal/confirmation-modal.component.spec.ts @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + diff --git a/src/app/components/shared/confirmation-modal/confirmation-modal.component.ts b/src/app/components/shared/confirmation-modal/confirmation-modal.component.ts new file mode 100644 index 0000000..023ba5e --- /dev/null +++ b/src/app/components/shared/confirmation-modal/confirmation-modal.component.ts @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Component, Input } from '@angular/core'; +import { TranslateService } from '@ngx-translate/core'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; + +@Component({ + selector: 'app-confirmation-modal', + templateUrl: './confirmation-modal.component.html' +}) +export class ConfirmationModalComponent { + constructor(public activeModal: NgbActiveModal, private readonly translateService: TranslateService) {} + + @Input() showOkBtn = true; + @Input() showCancelBtn = true; + + @Input() + okText = this.translateService.instant('common.buttons.save'); + cancelText = this.translateService.instant('common.buttons.cancel'); + title = ''; + text = ''; +} diff --git a/src/app/components/shared/loading-spinner/loading-spinner.component.html b/src/app/components/shared/loading-spinner/loading-spinner.component.html new file mode 100644 index 0000000..f9dd6ab --- /dev/null +++ b/src/app/components/shared/loading-spinner/loading-spinner.component.html @@ -0,0 +1,21 @@ +<!-- + ~ Copyright (c) 2022. Deutsche Telekom AG + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + ~ + ~ SPDX-License-Identifier: Apache-2.0 + --> + +<div class="spinner-border spinner-border-sm text-light qa_alarm_spinner" role="status"> + <span class="sr-only">{{'common.loading' | translate}}</span> +</div> diff --git a/src/app/components/shared/loading-spinner/loading-spinner.component.ts b/src/app/components/shared/loading-spinner/loading-spinner.component.ts new file mode 100644 index 0000000..c99a085 --- /dev/null +++ b/src/app/components/shared/loading-spinner/loading-spinner.component.ts @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-loading-spinner', + templateUrl: './loading-spinner.component.html', +}) +export class LoadingSpinnerComponent { +} diff --git a/src/app/components/shared/pagination/pagination.component.css b/src/app/components/shared/pagination/pagination.component.css new file mode 100644 index 0000000..b864207 --- /dev/null +++ b/src/app/components/shared/pagination/pagination.component.css @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +ngb-pagination::ng-deep li .page-link:focus { + box-shadow: 0 0 0 0.2rem rgb(0 123 255 / 25%); + border-color: #00a0de; +} diff --git a/src/app/components/shared/pagination/pagination.component.html b/src/app/components/shared/pagination/pagination.component.html new file mode 100644 index 0000000..ad198fc --- /dev/null +++ b/src/app/components/shared/pagination/pagination.component.html @@ -0,0 +1,48 @@ +<!-- + ~ Copyright (c) 2022. Deutsche Telekom AG + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + ~ + ~ SPDX-License-Identifier: Apache-2.0 + --> + + +<div class="d-flex flex-wrap justify-content-between mt-3"> + <div> + <ngb-pagination + [collectionSize]="collectionSize" + [pageSize]="pageSize" + [page]="page" + (pageChange)="emitPageChange($event)" + ></ngb-pagination> + <span class="ml-2 small"> + {{ 'common.pagination.totalCount' | translate: { value: collectionSize } }} + </span> + </div> + <div> + <label for="item-select" class="sr-only"> + {{ 'common.select.description' | translate }} + </label> + <select + id="item-select" + class="custom-select" + style="width: auto" + [ngModel]="pageSize" + (ngModelChange)="emitModelChange($event)" + > + <option *ngFor="let n of itemsPerPage" [ngValue]="n"> + {{ 'common.select.itemsPerPage' | translate: { value: n } }} + </option> + </select> + </div> +</div> diff --git a/src/app/components/shared/pagination/pagination.component.spec.ts b/src/app/components/shared/pagination/pagination.component.spec.ts new file mode 100644 index 0000000..7ffe9fc --- /dev/null +++ b/src/app/components/shared/pagination/pagination.component.spec.ts @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { PaginationComponent } from './pagination.component'; + +describe('PaginationComponent', () => { + let component: PaginationComponent; + let fixture: ComponentFixture<PaginationComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [PaginationComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(PaginationComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/components/shared/pagination/pagination.component.ts b/src/app/components/shared/pagination/pagination.component.ts new file mode 100644 index 0000000..fee827d --- /dev/null +++ b/src/app/components/shared/pagination/pagination.component.ts @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { NgbPaginationConfig } from '@ng-bootstrap/ng-bootstrap'; + +/** + * This is a wrapper component for the `ngbPagination` component of ngBootstrap ([official wiki page](https://ng-bootstrap.github.io/#/components/pagination/overview)). + * This contains the pagination element, as well as the selection element for the page size. + * + * + * Deal with both using the `pageChange` and `pageSizeChange` events, i.e in your template: + * ``` html + * <app-pagination + * [collectionSize]="..." + [pageSize]="..." + [page]="..." + * (pageChange)="changePage($event)" + * (pageSizeChange)="changePageSize($event)" + * > + * </app-pagination> + * ``` + */ +@Component({ + selector: 'app-pagination', + templateUrl: './pagination.component.html', + styleUrls: ['./pagination.component.css'], + providers: [NgbPaginationConfig], +}) +export class PaginationComponent { + /** + * This event is fired when an item in the `select`-element is changed + */ + @Output() pageSizeChange: EventEmitter<number> = new EventEmitter<number>(); + + /** + * Specify what page sizes should be selectable by the user. + */ + @Input() itemsPerPage = [10, 20, 50]; + + @Output() pageChange: EventEmitter<number> = new EventEmitter<number>(); + @Input() collectionSize = 10; + @Input() pageSize = 10; + @Input() page = 1; + + constructor(config: NgbPaginationConfig) { + config.boundaryLinks = true; + config.directionLinks = true; + config.disabled = false; + config.ellipses = false; + config.maxSize = 3; + config.pageSize = 10; + config.rotate = true; + config.size = 'sm'; + } + + /** + * Emit the currently selected page from the `ngb-Pagination` + * @param page the page that is selected + */ + emitPageChange(page: number) { + this.pageChange.emit(page); + } + + /** + * Emit the currently selected page size from the `select` + * @param size the number of items per page that is selected + */ + emitModelChange(size: number) { + this.pageSizeChange.emit(size); + } +} diff --git a/src/app/components/shared/status-page/status-page.component.css b/src/app/components/shared/status-page/status-page.component.css new file mode 100644 index 0000000..b7b5110 --- /dev/null +++ b/src/app/components/shared/status-page/status-page.component.css @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + diff --git a/src/app/components/shared/status-page/status-page.component.html b/src/app/components/shared/status-page/status-page.component.html new file mode 100644 index 0000000..28e65c6 --- /dev/null +++ b/src/app/components/shared/status-page/status-page.component.html @@ -0,0 +1,23 @@ +<!-- + ~ Copyright (c) 2022. Deutsche Telekom AG + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + ~ + ~ SPDX-License-Identifier: Apache-2.0 + --> + + +<div class="d-flex justify-content-center align-items-center flex-column h-100"> + <h2 class="text-center">{{header}}</h2> + <h3>{{message}}</h3> +</div> diff --git a/src/app/components/shared/status-page/status-page.component.spec.ts b/src/app/components/shared/status-page/status-page.component.spec.ts new file mode 100644 index 0000000..f8c547e --- /dev/null +++ b/src/app/components/shared/status-page/status-page.component.spec.ts @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { StatusPageComponent } from './status-page.component'; + +describe('StatusPageComponent', () => { + let component: StatusPageComponent; + let fixture: ComponentFixture<StatusPageComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ StatusPageComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(StatusPageComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/components/shared/status-page/status-page.component.ts b/src/app/components/shared/status-page/status-page.component.ts new file mode 100644 index 0000000..3cbbf46 --- /dev/null +++ b/src/app/components/shared/status-page/status-page.component.ts @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Component } from '@angular/core'; +import { Router } from '@angular/router'; + +@Component({ + selector: 'app-status-page', + templateUrl: './status-page.component.html', + styleUrls: ['./status-page.component.css'], +}) +export class StatusPageComponent { + header: string; + message: string; + + constructor(private router: Router) { + const data = this.router.getCurrentNavigation(); + this.header = data?.extras?.state?.header; + this.message = data?.extras?.state?.message; + } +} diff --git a/src/app/components/shared/table-skeleton/table-skeleton.component.css b/src/app/components/shared/table-skeleton/table-skeleton.component.css new file mode 100644 index 0000000..0870694 --- /dev/null +++ b/src/app/components/shared/table-skeleton/table-skeleton.component.css @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +@keyframes ghost { + from { + background-position: 0 0; + } + to { + background-position: 100vw 0; + } +} + +.line { + width: 100%; + height: 50px; + margin-top: 10px; + border-radius: 3px; + background: linear-gradient(90deg, #f0f0f0, #d8d6d6, #f0f0f0) 0 0/ 80vh 100% fixed; + background-color: var(--secondary); + animation: ghost 4000ms infinite linear; +} diff --git a/src/app/components/shared/table-skeleton/table-skeleton.component.html b/src/app/components/shared/table-skeleton/table-skeleton.component.html new file mode 100644 index 0000000..717da1f --- /dev/null +++ b/src/app/components/shared/table-skeleton/table-skeleton.component.html @@ -0,0 +1,31 @@ +<!-- + ~ Copyright (c) 2022. Deutsche Telekom AG + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + ~ + ~ SPDX-License-Identifier: Apache-2.0 + --> + + +<div id="table-skeleton"> + <div class="line"></div> + <div class="line"></div> + <div class="line"></div> + <div class="line"></div> + <div class="line"></div> + <div class="line"></div> + <div class="line"></div> + <div class="line"></div> + <div class="line"></div> + <div class="line"></div> +</div> diff --git a/src/app/components/shared/table-skeleton/table-skeleton.component.ts b/src/app/components/shared/table-skeleton/table-skeleton.component.ts new file mode 100644 index 0000000..41638fe --- /dev/null +++ b/src/app/components/shared/table-skeleton/table-skeleton.component.ts @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { ChangeDetectionStrategy, Component } from '@angular/core'; + +@Component({ + selector: 'app-table-skeleton', + templateUrl: './table-skeleton.component.html', + styleUrls: ['./table-skeleton.component.css'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class TableSkeletonComponent { +} diff --git a/src/app/directives/has-permissions.directive.ts b/src/app/directives/has-permissions.directive.ts new file mode 100644 index 0000000..994cee8 --- /dev/null +++ b/src/app/directives/has-permissions.directive.ts @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Directive, ElementRef, Inject, Input } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { ACL_CONFIG, AclConfig } from '../modules/auth/injection-tokens'; +import { AuthService } from '../services/auth.service'; +import { takeUntil } from 'rxjs/operators'; +import { UnsubscribeService } from '../services/unsubscribe/unsubscribe.service'; + +@Directive({ + selector: '[appHasPermissions]', + providers: [UnsubscribeService] +}) +export class HasPermissionsDirective { + @Input() appHasPermissions = ''; + constructor( + private el: ElementRef, + readonly httpClient: HttpClient, + readonly authService: AuthService, + @Inject(ACL_CONFIG) readonly acl: AclConfig, + private unsubscribeService: UnsubscribeService + ) { + // for unknown reasons this must be wrapped in set timeout, otherwise appHasPermissions is sometimes empty string + setTimeout(() => { + this.el.nativeElement.style.display = 'none'; + this.authService + .loadCachedUserProfile() + .pipe(takeUntil(this.unsubscribeService.unsubscribe$)) + .subscribe(userProfile => { + const intersectionOfRoles = Object.keys(acl).filter(value => userProfile?.roles.includes(value)); + for (const role of intersectionOfRoles) { + if (acl[role].includes(this.appHasPermissions)) { + this.el.nativeElement.style.display = 'initial'; + return; + } + } + }) + }, 0); + } +} diff --git a/src/app/directives/hide-empty.directive.ts b/src/app/directives/hide-empty.directive.ts new file mode 100644 index 0000000..c6ee8a6 --- /dev/null +++ b/src/app/directives/hide-empty.directive.ts @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { AfterViewChecked, Directive, ElementRef, Input, OnChanges, SimpleChanges } from '@angular/core'; + +//This directive we are using in switch functionality at attribute pane. We can hide attributes without value or show all the attributes. +// We are using this directive in the html file in the element (div) that wraps all the app-detail-rows. + +@Directive({ + selector: '[appHideEmptyDetailRow]', +}) +export class HideEmptyDetailRowDirective implements OnChanges, AfterViewChecked { + @Input() appHideEmptyDetailRow!: boolean; + constructor(private el: ElementRef) {} + + ngOnChanges(changes: SimpleChanges) { + if (changes.appHideEmptyDetailRow && this.el.nativeElement.textContent) { + this.setVisibility(this.el); + } + } + + ngAfterViewChecked() { + if (this.appHideEmptyDetailRow && this.el.nativeElement.textContent) { + this.setVisibility(this.el); + } + } + + public setVisibility(ref: ElementRef) { + if (this.appHideEmptyDetailRow) { + const detailRows = ref.nativeElement.querySelectorAll('app-detail-row'); + detailRows.forEach((item: any) => { + const span = item.querySelector('span'); + if(!span){ + return; + } + if (span.textContent === '' || span.textContent === '-') { + item.style.display = 'none'; + } else { + item.style.display = 'block'; + } + }); + } else { + const detailRows = ref.nativeElement.querySelectorAll('app-detail-row'); + detailRows.forEach((item: any) => { + item.style.display = 'block'; + }); + } + } +} diff --git a/src/app/errorhandling/global-error-handler.ts b/src/app/errorhandling/global-error-handler.ts new file mode 100644 index 0000000..0886232 --- /dev/null +++ b/src/app/errorhandling/global-error-handler.ts @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { ErrorHandler, Injectable, Injector } from '@angular/core'; +import { HttpErrorResponse } from '@angular/common/http'; +import { AlertService } from '../modules/alerting'; + +/** + * This class is intended for global error handling + */ +// See: https://pusher.com/tutorials/error-handling-angular-part-1 +@Injectable() +export class GlobalErrorHandler implements ErrorHandler { + constructor(private injector: Injector, private alertService: AlertService) {} + + handleError(error: Error | HttpErrorResponse) { + this.alertService.error(error.message); + } +} diff --git a/src/app/guards/auth.guard.ts b/src/app/guards/auth.guard.ts new file mode 100644 index 0000000..54ede0f --- /dev/null +++ b/src/app/guards/auth.guard.ts @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Injectable } from '@angular/core'; +import { CanActivate, UrlTree } from '@angular/router'; +import { Observable } from 'rxjs'; +import { AuthService } from '../services/auth.service'; + +/** + * grants permissions based on the `AuthService` + */ +@Injectable({ + providedIn: 'root', +}) +export class AuthGuard implements CanActivate { + roles: string = ''; + + constructor(private authService: AuthService) {} + + canActivate(): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree { + return this.authService.hasPermissions(); + } +} diff --git a/src/app/guards/edit-user.can-activate.guard.ts b/src/app/guards/edit-user.can-activate.guard.ts new file mode 100644 index 0000000..81fc36e --- /dev/null +++ b/src/app/guards/edit-user.can-activate.guard.ts @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Injectable } from '@angular/core'; +import { ActivatedRouteSnapshot, CanActivate, Router } from '@angular/router'; +import { Observable, of } from 'rxjs'; +import { UsersService } from '../../../openapi/output'; +import { catchError, map } from 'rxjs/operators'; +import { TranslateService } from '@ngx-translate/core'; +@Injectable({ + providedIn: 'root', +}) +export class EditUserCanActivateGuard implements CanActivate { + constructor(private usersService: UsersService, private router: Router, private translateService: TranslateService) {} + canActivate(route: ActivatedRouteSnapshot): Observable<boolean> { + const userId = route.paramMap.get('userId'); + if (userId) { + return this.usersService.getUser(userId).pipe( + catchError(() => { + this.router.navigate(['/statusPage'], { + state: { + header: this.translateService.instant('userAdministration.messages.warnings.userDeleted.header'), + message: this.translateService.instant('userAdministration.messages.warnings.userDeleted.message'), + }, + }); + return of(false); + }), + map(() => { + return true; + }), + ); + } + return of(false); + } +} diff --git a/src/app/guards/has-permissions.guard.ts b/src/app/guards/has-permissions.guard.ts new file mode 100644 index 0000000..cc04673 --- /dev/null +++ b/src/app/guards/has-permissions.guard.ts @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Inject, Injectable } from '@angular/core'; +import { ActivatedRouteSnapshot, CanActivate, Router, UrlTree } from '@angular/router'; +import { Observable } from 'rxjs'; +import { HttpClient } from '@angular/common/http'; +import { ACL_CONFIG, AclConfig } from '../modules/auth/injection-tokens'; +import { AuthService } from '../services/auth.service'; +import { TranslateService } from '@ngx-translate/core'; +import { map } from 'rxjs/operators'; + +@Injectable({ + providedIn: 'root', +}) +export class HasPermissionsGuard implements CanActivate { + constructor( + private readonly authService: AuthService, + private readonly httpClient: HttpClient, + private readonly router: Router, + private readonly translateService: TranslateService, + @Inject(ACL_CONFIG) readonly acl: AclConfig, + ) {} + + canActivate( + next: ActivatedRouteSnapshot, + ): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree { + return this.authService.loadCachedUserProfile().pipe( + map(userProfile => { + // filter out the keys (the onap_ roles) that the user does not have + const intersectionOfRoles = Object.keys(this.acl).filter(role => userProfile?.roles.includes(role)); + return this.hasPermissions(next.data.permission, intersectionOfRoles); + })); + } + + /** + * Check if a user has a given permission. + * @param permission the permission, as defined in the acl.json + * @param roles the roles that the user possesses + * @returns true if the user has the needed permission + */ + private hasPermissions(permission: string, roles: string[]) { + for (const role of roles) { + if (this.acl[role].includes(permission)) { + return true; + } + } + this.router.navigate(['/statusPage'], { + state: { + header: this.translateService.instant('common.noPermissions.noPermissions'), + message: this.translateService.instant('common.noPermissions.support'), + }, + }); + return false; + } +} diff --git a/src/app/guards/pending-changes.guard.ts b/src/app/guards/pending-changes.guard.ts new file mode 100644 index 0000000..625a7b1 --- /dev/null +++ b/src/app/guards/pending-changes.guard.ts @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { CanDeactivate } from '@angular/router'; +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { TranslateService } from '@ngx-translate/core'; + +export interface ComponentCanDeactivate { + canDeactivate: () => boolean; +} + +@Injectable() +export class PendingChangesGuard implements CanDeactivate<ComponentCanDeactivate> { + constructor(public translateService: TranslateService) {} + + canDeactivate(component: ComponentCanDeactivate): boolean | Observable<boolean> { + // if there are no pending changes, just allow deactivation; else confirm first + return component.canDeactivate() + ? true + : // NOTE: this warning message will only be shown when navigating elsewhere within your angular app; + // when navigating away from your angular app, the browser will show a generic warning message + // see http://stackoverflow.com/a/42207299/7307355 + confirm(this.translateService.instant('serviceModels.warningMessage.warning')); + } +} diff --git a/src/app/helpers/filter-helpers.ts b/src/app/helpers/filter-helpers.ts new file mode 100644 index 0000000..cc9f13e --- /dev/null +++ b/src/app/helpers/filter-helpers.ts @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +import { Filter } from 'src/app/helpers/listing'; + +/** + * The JSONPath Filter Operators that are used for comparison (subset of [these](https://www.postgresql.org/docs/current/functions-json.html#FUNCTIONS-SQLJSON-FILTER-EX-TABLE)). + * For instance: + * ``` + * $.id == 1 + * $.type like_regex "type_(a|b)" + * ``` + */ +export enum FilterOperator { + EQUAL = ' == ', + NOT_EQUAL = ' != ', + LIKE_REGEX = ' like_regex ', + OR = ' || ', + EQUAL_IN = ' IN ' +} + +/** + * Turns a Filter that is not formatted into a valid JSONPath one + * @param filter the filter that is not in JSONPath format + * @param string pass string: true if you want a return type string + * @returns a Filter with formatted: true or a string when parameter string: true + */ +export function createJsonPathFilter(filter: Filter): Filter; +export function createJsonPathFilter(filter: Filter, returnsString: true): string; +export function createJsonPathFilter(filter: Filter, returnsString = false): Filter | string { + // like_regex only works with strings + if (filter.operator === FilterOperator.LIKE_REGEX) { + if (returnsString) { + return createFilter(addFieldPrefix(filter.parameter), filter.operator, toSearchRegex(filter.value.toString())); + } + return { + parameter: addFieldPrefix(filter.parameter), + operator: filter.operator, + value: toSearchRegex(filter.value.toString()), + }; + } + if (typeof filter.value === 'number') { + if (returnsString) { + return createFilter(addFieldPrefix(filter.parameter), filter.operator, filter.value.toString()); + } + return { + parameter: addFieldPrefix(filter.parameter), + operator: filter.operator, + value: filter.value, + }; + } + if (returnsString) { + return createFilter(addFieldPrefix(filter.parameter), filter.operator, quote(filter.value)); + } + return { + parameter: addFieldPrefix(filter.parameter), + operator: filter.operator, + value: quote(filter.value), + }; +} + +/** + * Concatenates the provided input into a string. + * @param parameter the field to filter + * @param value the value it should match + * @param operator the operator for comparison (`==`,`!=`,`like_regex`,...) + * @param forApi + * @returns a concatenated string + */ +export function createFilter(parameter: string, operator: FilterOperator, value: string | string[], forApi= false): string { + if (forApi && operator === FilterOperator.EQUAL_IN) { + const valueArray = Array.isArray(value) ? value : value.split(','); + return addParentheses(createOrCondition(composeFilterFromArray(valueArray,parameter,FilterOperator.EQUAL))); + } + return `${parameter}${operator}${value}`; +} +/** + * Create array of composed filter + * @param value array of strings e.g array of IDs for alarms + * @param parameter the field to filter e.g $.id + * @param operator the operator for comparison + * @returns a string[] + */ +function composeFilterFromArray(value: string[], parameter: string, operator: FilterOperator): string[] { + return value + .reduce((acc: string[], curr) => [...acc, `${parameter}${operator}${curr}`], []) +} +/** + * Join array of string using '||' operator + * @param value string[] + * @returns a string + */ +function createOrCondition(value: string[]) { + return value.join(FilterOperator.OR) +} +/** + * Wraps a string in parentheses `"string"` -> `("string")` + * @param value string to wrap in quotes + * @returns a string wrapped in quotes + */ +function addParentheses(value: string) { + return ` ( ${value} ) ` +} +/** + * Wraps a string in quotes `"string"` -> `"'string'"` + * @param value string to wrap in quotes + * @returns a string wrapped in quotes + */ +export function quote(value: string): string { + return `"${value}"`; +} + +/** + * Add a `$.` prefix to the provided field + * @param value the field to match against + * @returns the field with a `$.` prefix + */ +export function addFieldPrefix(value: string): string { + return `$.${value}`; +} + +/** + * Concatenate a list of categories into a regex expression for alternative matches. + * I.e `[a,b,c]` -> `"^(a|b|c)$"` + * @param categories the alternative values that should be matched + * @returns a regex expression of alternative matches + */ +export function toCategoricalRegex(categories: string[]): string { + return `"^(${categories.join('|')})$"`; +} + +/** + * Extracts the list of categories from a given regular expression. + * I.e `"^(a|b|c)$"` -> `[a,b,c]` + * @param regex a regex expression of alternative matches + * @returns the categories from the regex + */ +export function fromCategoricalRegex(regex: string): string[] { + let strippedRegex = regex.slice(3, regex.length - 3); + return strippedRegex.split('|'); +} + +/** + * Turns the given searchTerm into a case insensitive value to be used with like_regex + * I.e `term` -> `"term" flag "i"` + * @param searchTerm the search term + * @returns the term in the format to be used with like_regex + */ +export function toSearchRegex(searchTerm: string): string { + return `"${searchTerm}" + flag "i"`; +} + +/** + * Strips the value of a like_regex filter off its formatting. + * I.e `"value" flag "i"` -> `value` + * @param regex the value for the `like_regex` operation + * @returns the value without quotes and flags + */ +export function fromSearchRegex(regex: string): string { + const rawValue = regex?.split(' ')[0]; + if (rawValue.charAt(0) != '"' || rawValue.charAt(rawValue.length - 1) != '"') { + throw new Error('Error while extracting the value from the url. Is it in the correct format?'); + } + return rawValue.substring(1, rawValue.length - 1); +} + +/** + * Join the individual filters with `&&` into a long expression + * @param filters the array of filter strings + * @returns a long filter string chained by `&&`'s + */ +export function composeFilter(filters: string[]): string { + return filters.join('&&'); +} + +/** + * Turn the provided string of filters into a Map of filters + * @param filter the filter string + * @returns a Map of filters + */ +export function parseFilterFromUrl(filter: string | null): Map<string, Filter> { + if (!filter) { + return new Map<string, Filter>(); + } + const filters = filter.split('&&'); + return splitFilterByOperator(filters); +} + +/** + * Parse a list of strings in filter format into a Map of Filters + * @param filters list of strings in format `['']` + * @returns a map of Filters + */ +function splitFilterByOperator(filters: string[]): Map<string, Filter> { + const mappedFilters = new Map<string, Filter>(); + filters + .map(filter => { + if (filter.includes(FilterOperator.EQUAL_IN)) { + const [parameter, value] = filter.split(FilterOperator.EQUAL_IN); + return { parameter, value, operator: FilterOperator.EQUAL_IN }; + } + if (filter.includes(FilterOperator.EQUAL)) { + const [parameter, value] = filter.split(FilterOperator.EQUAL); + return { parameter, value, operator: FilterOperator.EQUAL }; + } + if (filter.includes(FilterOperator.NOT_EQUAL)) { + const [parameter, value] = filter.split(FilterOperator.NOT_EQUAL); + return { parameter, value, operator: FilterOperator.NOT_EQUAL }; + } + if (filter.includes(FilterOperator.LIKE_REGEX)) { + const [parameter, value] = filter.split(FilterOperator.LIKE_REGEX); + return { parameter, value, operator: FilterOperator.LIKE_REGEX }; + } + throw new Error('Unsupported operator'); + }) + .forEach(item => mappedFilters.set(item.parameter, item)); + return mappedFilters; +} + +/** + * Transforms the map of filters back into a JSONPATH filter string + * @param filters + * @param forApi + * @returns a string containing all filter expressions or undefined if size of the Filter Map is 0 + */ +export function filterBuilder(filters: Map<string, Filter>, forApi=false): string | undefined { + if (filters.size === 0) { + return undefined; + } + const filtersString: string[] = []; + for (const [, filter] of filters.entries()) { + filtersString.push( + createFilter( + filter.parameter, + filter.operator, + filter.value.toString(), + forApi), + ); + } + return composeFilter(filtersString); +} diff --git a/src/app/helpers/form-validators.ts b/src/app/helpers/form-validators.ts new file mode 100644 index 0000000..6cd3acd --- /dev/null +++ b/src/app/helpers/form-validators.ts @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { AbstractControl, ValidationErrors } from '@angular/forms'; + +export class WhiteSpaceValidator { + static noWhiteSpace(control: AbstractControl): ValidationErrors | null { + if (control.value !== null) { + if ((control.value as string).indexOf(' ') >= 0) { + return { noWhiteSpace: true }; + } + return null; + } + return null; + } +} diff --git a/src/app/helpers/helpers.ts b/src/app/helpers/helpers.ts new file mode 100644 index 0000000..7c03dbd --- /dev/null +++ b/src/app/helpers/helpers.ts @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { FormArray, FormGroup } from '@angular/forms'; + +export function isNotUndefined<T>(val: T | undefined): val is T { + return val !== undefined; +} + +export function isNotNull<T>(val: T | null): val is T { + return val !== null; +} + +export function markAsDirtyAndValidate(formGroup: FormGroup): void { + Object.values(formGroup.controls).forEach(control => { + control.markAsDirty(); + control.updateValueAndValidity(); + }); +} + +export function isNullOrUndefined(val: any): boolean { + return val === null || val === undefined; +} + +export function isNotNullOrUndefined(val: any): boolean { + return val !== null && val !== undefined; +} + +export function isNullOrUndefinedOrEmptyString(val: any): boolean { + return val === null || val === undefined || val === ''; +} + +export function isEmptyArray(array: any[]):boolean { + return !array.length +} + +export function getRandomNumber(min: number, max: number) { + return Math.floor(Math.random() * (max - min + 1)) + min; +} + +export function areFormControlsValid(form: FormGroup): boolean { + const formControls = Object.keys(form.controls) + .map(key => form.controls[key]) + .filter(control => !(control instanceof FormArray)); + return formControls.find(control => control.invalid && (control.dirty || control.touched)) === undefined; +} + +export function isString(value: any): boolean { + return typeof value === 'string' || value instanceof String; +} + +export function resetSelectDefaultValue(cssSelector: string): void { + setTimeout(() => { + const element = document.querySelector(cssSelector); + if (element) { + //@ts-ignore + document.querySelector(cssSelector)?.selectedIndex = -1; + } + }, 0); +} diff --git a/src/app/helpers/listing.ts b/src/app/helpers/listing.ts new file mode 100644 index 0000000..66d1ae0 --- /dev/null +++ b/src/app/helpers/listing.ts @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Router } from '@angular/router'; +import { filterBuilder, FilterOperator } from 'src/app/helpers/filter-helpers'; + +/** + * A JSONPath filter. One or more `Filter`s can be passed to the `filter=` param of the alarm API. + */ +export interface Filter { + /** + * The field to compare against, i.e `$.type` + */ + parameter: string; + /** + * The JSONPath Filter Operators that are used for comparison (subset of [these](https://www.postgresql.org/docs/current/functions-json.html#FUNCTIONS-SQLJSON-FILTER-EX-TABLE)). + * For instance `==` and `like_regex`: + * ``` + * $.id == 1 + * $.type like_regex "type_(a|b)" + * ``` + */ + operator: FilterOperator; + /** + * The value or pattern that the field should have, i.e `"type_(a|b)"` + */ + value: string | number; +} + +/** + * This represents one filter expression for one column. + * Use `undefined` to signal removal of the filter. + * + * Note that parameter needs to be the complete param (i.e `$.column`). + * That is necessary because this will be the key when parsing the filter expression into a map. + */ +export type ColumnFilter = { + parameter: string; + filter: Filter | undefined; +}; + +export function changePage(router: Router, page: number): void { + router.navigate([], { queryParams: { page }, queryParamsHandling: 'merge' }); +} + +export function changePageSize(router: Router, pageSize: number): void { + router.navigate([], { + queryParams: { page: 1, pageSize }, + queryParamsHandling: 'merge', + }); +} + +export function changeFilter(router: Router, value: string | undefined): void { + router.navigate([], { + queryParams: { filter: value ? value.trim() : undefined, page: 1 }, + queryParamsHandling: 'merge', + }); +} + +/** + * Format a JSONPath filter expression into the format required by the angular router. + * Add or update this filter param in the router. + * @param router the angular router + * @param filters the filter expression in JSONPath format + * @param path path for new router link + * @param params other queryParams + */ +export function changeFiltersInRouter(router: Router, filters: Map<string, Filter>, params?: { [key: string]: any }, path?: any[]): void { + const composedFilter = filters.size > 0 ? filterBuilder(filters) : undefined; + router.navigate(path ?? [], { + queryParams: { filter: composedFilter, ...params, page: 1 }, + queryParamsHandling: 'merge', + }); +} diff --git a/src/app/helpers/sorting-helpers.ts b/src/app/helpers/sorting-helpers.ts new file mode 100644 index 0000000..94ec9ef --- /dev/null +++ b/src/app/helpers/sorting-helpers.ts @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Sort, SortDirection } from '../components/shared/sort/sort.component'; +import { Router } from '@angular/router'; + +export function parseSortStringToSort(str: string): Sort { + return str.startsWith('-') + ? { parameter: str.split('-')[1], direction: SortDirection.DESC } + : { parameter: str, direction: SortDirection.ASC }; +} +export function applyNewSorting(router: Router, sort: Sort) { + if (sort.direction === SortDirection.NONE) { + router.navigate([], { + queryParams: { page: 1, sort: null }, + queryParamsHandling: 'merge', + }); + } else { + router.navigate([], { + queryParams: { page: 1, sort: sort.direction === SortDirection.ASC ? sort.parameter : '-' + sort.parameter }, + queryParamsHandling: 'merge', + }); + } +} +export function parseSortToSortString(sort: Sort): string { + if (sort.direction === SortDirection.ASC) { + return sort.parameter; + } + if (sort.direction === SortDirection.DESC) { + return '-' + sort.parameter; + } + return ''; +} + +export function parseSortToSortJsonString(sort: Sort): string { + if (sort.direction === SortDirection.ASC) { + return '$.' + sort.parameter; + } + if (sort.direction === SortDirection.DESC) { + return '-$.' + sort.parameter; + } + return ''; +} diff --git a/src/app/http-interceptors/auth.interceptor.ts b/src/app/http-interceptors/auth.interceptor.ts new file mode 100644 index 0000000..fc13e70 --- /dev/null +++ b/src/app/http-interceptors/auth.interceptor.ts @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Injectable } from '@angular/core'; +import { OAuthStorage } from 'angular-oauth2-oidc'; +import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http'; + +import { Observable, throwError } from 'rxjs'; +import { environment } from '../../environments/environment'; + +@Injectable() +export class AuthInterceptor implements HttpInterceptor { + constructor(private authStorage: OAuthStorage) {} + + public intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { + const url = req.url.toLowerCase(); + if (!url.startsWith(environment.backendServerUrl) && !url.startsWith(environment.loggingUrl)) { + return next.handle(req); + } + + const accessToken = this.authStorage.getItem('access_token'); + const idToken = this.authStorage.getItem('id_token'); + if (accessToken === null || idToken === null) { + return throwError(new Error('Missing access or ID token')); + } + const headers = req.headers + .set('Authorization', `Bearer ${accessToken}`) + .set('X-Auth-Identity', `Bearer ${idToken}`); + req = req.clone({ headers }); + + return next.handle(req); + } +} diff --git a/src/app/http-interceptors/caching-interceptor.ts b/src/app/http-interceptors/caching-interceptor.ts new file mode 100644 index 0000000..df13376 --- /dev/null +++ b/src/app/http-interceptors/caching-interceptor.ts @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { Observable, of } from 'rxjs'; +import { startWith, tap } from 'rxjs/operators'; + +import { RequestCache } from '../services/cacheservice/request-cache.service'; +import { urlTileApi } from '../services/tileservice/tiles.service'; + +/** + * Interceptor that returns HttpResponses from cache and updates cache if outdated + * This applies to GET requests from specified urls (specified in this class) + */ +@Injectable() +// https://angular.io/guide/http#using-interceptors-for-caching +// https://github.com/angular/angular/blob/master/aio/content/examples/http/src/app/http-interceptors/caching-interceptor.ts +export class CachingInterceptor implements HttpInterceptor { + private cachedUrls: Array<string> = [ + urlTileApi, + window.location.origin + '/keycloak/auth/realms/ONAP/protocol/openid-connect/userinfo', + ]; + + // cache is the cache service that supports get() and put() + constructor(private cache: RequestCache) {} + + intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { + // continue if not cacheable. + if (!this.isCacheable(request)) { + return next.handle(request); + } + + const cachedResponse = this.cache.get(request); + + // when a custom 'x-refresh' header is set, refresh the cash + // (see https://github.com/angular/angular/blob/master/aio/content/examples/http/src/app/package-search/package-search.service.ts) + if (request.headers.get('x-refresh')) { + const results$ = this.getUpdatedResponse(request, next, this.cache); + return cachedResponse ? results$.pipe(startWith(cachedResponse)) : results$; + } + // cache-or-fetch + return cachedResponse ? of(cachedResponse) : this.getUpdatedResponse(request, next, this.cache); + } + + /** + * Checks if the request is cacheable. + * This is true if the request is a http GET and the url is defined in this method + * (-> urlTileApi) + */ + private isCacheable(req: HttpRequest<any>): boolean { + // Only GET requests are cacheable + return ( + req.method === 'GET' && + // Only the tile api is cacheable in this app + -1 < this.cachedUrls.indexOf(req.url) + ); + } + + /** + * Get server response observable by sending request to `next()`. + * Will add the response to the cache on the way out. + */ + private getUpdatedResponse( + req: HttpRequest<any>, + next: HttpHandler, + cache: RequestCache, + ): Observable<HttpEvent<any>> { + return next.handle(req.clone()).pipe( + tap(event => { + // There may be other events besides the response. + if (event instanceof HttpResponse) { + cache.put(req, event); // Update the cache. + } + }), + ); + } +} diff --git a/src/app/http-interceptors/http-error.interceptor.ts b/src/app/http-interceptors/http-error.interceptor.ts new file mode 100644 index 0000000..61d55e0 --- /dev/null +++ b/src/app/http-interceptors/http-error.interceptor.ts @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { Observable, throwError, TimeoutError } from 'rxjs'; +import { catchError } from 'rxjs/operators'; +import { AlertService } from '../modules/alerting'; +import { TranslateService } from '@ngx-translate/core'; +import { Problem } from '../../../openapi/output'; +import { Router } from '@angular/router'; +import { DEFAULT_TIMEOUT } from './timeout.interceptor'; + +/** + * This class adds global handling of http-request related errors + */ + +export enum RequestMethod { + DELETE = 'DELETE', + POST = 'POST', + GET = 'GET', +} + +interface ProblemDetail { + errorDetail: Problem; + requestId?: string; + urlTree: string[]; +} +@Injectable() +export class HttpErrorInterceptor implements HttpInterceptor { + errorDetail!: Problem; + constructor(private alertService: AlertService, private translateService: TranslateService, private router: Router) {} + + intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { + return next.handle(request).pipe( + catchError(rsp => { + const urlTree = this.router.url.split('/'); + this.errorDetail = this.createErrorDetail(rsp); + const requestId = request.headers.get('x-request-id') || undefined; + const detail: ProblemDetail = { + errorDetail: this.errorDetail, + requestId, + urlTree, + }; + + if (request.url.includes('onap_logging')) { + this.alertService.warn(this.translateService.instant('common.block.logging'), { + id: 'onap_logging', + }); + return throwError(this.errorDetail); + } + if (request.method === RequestMethod.POST && request.url.includes('keycloak')) { + this.alertService.error(this.translateService.instant('common.block.authorization'), { + id: 'keycloak', + }); + return throwError(this.errorDetail); + } + if (request.url.includes('preferences')) { + this.getPreferenceMessage(request, detail); + return throwError(this.errorDetail); + } + if (request.url.includes('actions')) { + this.getActionMessage(request, detail); + return throwError(this.errorDetail); + } + + switch (urlTree[1].split('?')[0]) { + case 'user-administration': + this.getUserAdministrationMessage(request, detail, urlTree); + break; + case 'dashboard': + this.getErrorMessage('dashboard', detail); + break; + case 'app-starter': + this.getErrorMessage('appStarter', detail); + break; + default: + this.getErrorMessage('defaultMessage', detail); + break; + } + return throwError(this.errorDetail); + }), + ); + } + + private getUserAdministrationMessage(request: HttpRequest<any>, detail: ProblemDetail, urlTree: string[]) { + if (request.method === RequestMethod.DELETE) { + return this.getErrorMessage('userAdministration.delete', detail); + } + if (urlTree.includes('create')) { + return this.getErrorMessage('userAdministration.create', detail); + } + if (urlTree.includes('edit')) { + return this.getErrorMessage('userAdministration.edit', detail); + } + } + + private getActionMessage(request: HttpRequest<any>, detail: ProblemDetail) { + if (request.method === RequestMethod.POST) { + return this.getErrorMessage('saveAction', detail); + } + this.getErrorMessage('loadAction', detail); + } + + private getPreferenceMessage(request: HttpRequest<any>, detail: ProblemDetail) { + if (request.method === RequestMethod.POST) { + return this.getErrorMessage('savePreferences', detail); + } + this.getErrorMessage('loadPreferences', detail); + } + + private createErrorDetail(response: any): Problem { + if (response instanceof TimeoutError) { + return { + detail: this.translateService.instant('common.block.timeout', { value: DEFAULT_TIMEOUT / 1000 }), + title: response.name, + status: 408, + }; + } + return response.error ? response.error : response; + } + + private getErrorMessage(type: string, detail: ProblemDetail) { + this.alertService.error(`${this.translateService.instant('common.block.' + type)}`, detail); + } +} diff --git a/src/app/http-interceptors/interceptors.ts b/src/app/http-interceptors/interceptors.ts new file mode 100644 index 0000000..5fd0a97 --- /dev/null +++ b/src/app/http-interceptors/interceptors.ts @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +/* "Barrel" of Http Interceptors */ +import { HTTP_INTERCEPTORS } from '@angular/common/http'; +import { CachingInterceptor } from './caching-interceptor'; +import { HttpErrorInterceptor } from './http-error.interceptor'; +import { MockInterceptor } from './mock.interceptor'; +import { LoadingIndicatorInterceptor } from 'src/app/http-interceptors/loading-indicator.interceptor'; +import { RequestidInterceptor } from './requestid.interceptor'; +import { TimeoutInterceptor } from './timeout.interceptor'; +import { LoggingInterceptor } from './logging.interceptor'; + +/** Http interceptor providers in outside-in order + * Gathers all the interceptor providers into an httpInterceptorProviders array + */ +// https://angular.io/guide/http#provide-the-interceptor +export const httpInterceptorProviders = [ + { provide: HTTP_INTERCEPTORS, useClass: MockInterceptor, multi: true }, + { provide: HTTP_INTERCEPTORS, useClass: TimeoutInterceptor, multi: true }, + { provide: HTTP_INTERCEPTORS, useClass: LoadingIndicatorInterceptor, multi: true }, + { provide: HTTP_INTERCEPTORS, useClass: RequestidInterceptor, multi: true }, + { provide: HTTP_INTERCEPTORS, useClass: HttpErrorInterceptor, multi: true }, + { provide: HTTP_INTERCEPTORS, useClass: CachingInterceptor, multi: true }, + { provide: HTTP_INTERCEPTORS, useClass: LoggingInterceptor, multi: true }, +]; diff --git a/src/app/http-interceptors/loading-indicator.interceptor.ts b/src/app/http-interceptors/loading-indicator.interceptor.ts new file mode 100644 index 0000000..d48d04f --- /dev/null +++ b/src/app/http-interceptors/loading-indicator.interceptor.ts @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Injectable } from '@angular/core'; +import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http'; +import { Observable } from 'rxjs'; +import { finalize } from 'rxjs/operators'; +import { LoadingIndicatorService } from 'src/app/services/loading-indicator.service'; + +@Injectable() +export class LoadingIndicatorInterceptor implements HttpInterceptor { + readonly excludedUrls = ['preferences', 'actions']; + + constructor(private readonly loadingIndicator: LoadingIndicatorService) {} + + intercept(req: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> { + if (this.excludedUrls.some(url => req.url.includes(url))) { + return next.handle(req); + } + + this.loadingIndicator.show(); + return next.handle(req).pipe(finalize(() => this.loadingIndicator.hide())); + + } +} diff --git a/src/app/http-interceptors/logging.interceptor.ts b/src/app/http-interceptors/logging.interceptor.ts new file mode 100644 index 0000000..8975868 --- /dev/null +++ b/src/app/http-interceptors/logging.interceptor.ts @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Injectable } from '@angular/core'; +import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse } from '@angular/common/http'; +import { Observable } from 'rxjs'; +import { environment } from '../../environments/environment'; +import { take, tap } from 'rxjs/operators'; +import { LoggingService } from '../services/logging.service'; + +@Injectable() +export class LoggingInterceptor implements HttpInterceptor { + constructor(private readonly loggingService: LoggingService) {} + + intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> { + if (environment.loggingEnabled) { + if ( + request.url.toLowerCase().startsWith(environment.backendServerUrl) && + !request.url.toLowerCase().startsWith(environment.loggingUrl) + ) { + const requestMessage = `Portal-ui - request - X-Request-Id <${request.headers.get('x-request-id')}> <${ + request.method + }> <${request.url}>`; + this.loggingService + .writeLog(`'@timestamp': ${new Date().toISOString()}, message: ${requestMessage}`) + .pipe(take(1)) + .subscribe(); + + return next.handle(request).pipe( + tap((event: HttpEvent<any>) => { + if (event instanceof HttpResponse) { + const requestId = event.headers.get('x-request-id'); + const responseMessage = `Portal-ui - response - X-Request-Id <${requestId ?? 'Not set'}> <${ + event.status + }>`; + this.loggingService + .writeLog(`'@timestamp': ${new Date().toISOString()}, message: ${responseMessage}`) + .pipe(take(1)) + .subscribe(); + } + }), + ); + } + return next.handle(request); + } + return next.handle(request); + } +} diff --git a/src/app/http-interceptors/mock.interceptor.ts b/src/app/http-interceptors/mock.interceptor.ts new file mode 100644 index 0000000..6fcb122 --- /dev/null +++ b/src/app/http-interceptors/mock.interceptor.ts @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; + +/** + * This Interceptor reroutes URLs that are defined in the `matchers` array to [Wiremock](https://wiremock.org/) endpoints. + * This is useful, when the real api is not yet available. + */ +@Injectable() +export class MockInterceptor implements HttpInterceptor { + // list of all available RegExp URL matchers + // !! do not forget to remove matcher when API implementation is ready !! + private readonly matchers: RegExp[] = [ + // for example: + // /tiles/ + ]; + + intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { + let newRequest = request; + + if (this.matchers.some(matcher => request.url.match(matcher))) { + console.warn(`MockInterceptor is enabled for URL: '${request.url}'`); + // intentional usage of .replace instead of .replaceAll to replace only first instance + newRequest = request.clone({ + url: request.url.replace('/api/', '/mock-api/'), + }); + } + + return next.handle(newRequest); + } +} diff --git a/src/app/http-interceptors/requestid.interceptor.ts b/src/app/http-interceptors/requestid.interceptor.ts new file mode 100644 index 0000000..6c3c912 --- /dev/null +++ b/src/app/http-interceptors/requestid.interceptor.ts @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Injectable } from '@angular/core'; +import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http'; +import { Observable } from 'rxjs'; +import { environment } from 'src/environments/environment'; +import { v4 as uuid } from 'uuid'; + +@Injectable() +export class RequestidInterceptor implements HttpInterceptor { + intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> { + // this is skipping everything that is not /api (like /keycloak) + if (!request.url.toLowerCase().startsWith(environment.backendServerUrl)) { + return next.handle(request); + } + + request = request.clone({ setHeaders: { 'X-Request-Id': uuid() } }); + return next.handle(request); + } +} diff --git a/src/app/http-interceptors/timeout.interceptor.ts b/src/app/http-interceptors/timeout.interceptor.ts new file mode 100644 index 0000000..e320b79 --- /dev/null +++ b/src/app/http-interceptors/timeout.interceptor.ts @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Injectable } from '@angular/core'; +import { + HttpRequest, + HttpHandler, + HttpEvent, + HttpInterceptor +} from '@angular/common/http'; +import { Observable, throwError, TimeoutError } from 'rxjs'; +import { catchError, timeout } from 'rxjs/operators'; +import { AlertService } from '../modules/alerting'; +import { TranslateService } from '@ngx-translate/core'; + +//60 seconds +export const DEFAULT_TIMEOUT = 60000; + +@Injectable() +export class TimeoutInterceptor implements HttpInterceptor { + + constructor(private alertService: AlertService, private translateService: TranslateService) {} + intercept(req: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>>{ + + return next.handle(req).pipe( + timeout(DEFAULT_TIMEOUT), + catchError(err => { + if (err instanceof TimeoutError) { + this.alertService.error(this.translateService.instant('common.messages.timeout')) + } + return throwError(err); + }) + ); + } +} diff --git a/src/app/model/dashboard.model.ts b/src/app/model/dashboard.model.ts new file mode 100644 index 0000000..2f501c3 --- /dev/null +++ b/src/app/model/dashboard.model.ts @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +export enum DashboardApplications { + USER_LAST_ACTION_TILE = 'USER_LAST_ACTION_TILE', +} +export interface DashboardTileSettings { + type: DashboardApplications; + displayed: boolean; +} diff --git a/src/app/model/environment.model.ts b/src/app/model/environment.model.ts new file mode 100644 index 0000000..5bfb615 --- /dev/null +++ b/src/app/model/environment.model.ts @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +export interface Environment { + customStyleEnabled: boolean; + backendServerUrl: string; + hostname: string; + keycloakEditProfile: string; + production: boolean; + keycloak: KeycloakEnvironment; + dateTimeFormat: string; + loggingUrl: string; + loggingEnabled: boolean + supportUrlLink: string + +} + +export interface KeycloakEnvironment { + issuer: string; + redirectUri: string; + clientId: string; + responseType: string; + scope: string; + requireHttps: boolean; + showDebugInformation: boolean; + disableAtHashCheck: boolean; + skipIssuerCheck: boolean; + strictDiscoveryDocumentValidation: boolean; +} diff --git a/src/app/model/tile.ts b/src/app/model/tile.ts new file mode 100644 index 0000000..c23482e --- /dev/null +++ b/src/app/model/tile.ts @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +export interface TilesListResponse { + items: Tile[]; +} +export interface Tile { + id: number; + title: string; + imageUrl: string; + imageAltText: string; + description: string; + redirectUrl: string; + headers?: string; + groups: Group[]; + roles: Role[]; +} + +export enum Group { + ADMIN = 'ADMIN', + DEVELOPER = 'DEVELOPER', + OPERATOR = 'OPERATOR', +} + +export enum Role { + ONAP_OPERATOR = 'ONAP_OPERATOR', + ONAP_DESIGNER = 'ONAP_DESIGNER', + ONAP_ADMIN = 'ONAP_ADMIN', +} + + diff --git a/src/app/model/user-last-action.model.ts b/src/app/model/user-last-action.model.ts new file mode 100644 index 0000000..8941f18 --- /dev/null +++ b/src/app/model/user-last-action.model.ts @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +export enum ActionFilter { + ALL = 'ALL', + SEARCH = 'SEARCH', + ACTION = 'ACTION', +} + +export enum ActionType { + SEARCH = 'SEARCH', + VIEW = 'VIEW', + EDIT = 'EDIT', + DEPLOY = 'DEPLOY', + DELETE = 'DELETE', + CREATE = 'CREATE', + CLEAR = 'CLEAR', + ACK = 'ACK', + UNACK = 'UNACK', +} + +export enum ActionInterval { + LAST1H = '1H', + LAST4H = '4H', + LAST1D = '1D', + ALL = 'ALL', +} + +export enum EntityType { + USERADMINISTRATION = 'USERADMINISTRATION', +} + +export interface EntityUserHistoryActionModel { + userId: string; + userName: string; +} + +export interface CreateActionModel<T> { + type: ActionType; + entity: EntityType; + entityParams: T; +} + +export interface ActionRowModel<T> { + actionCreatedAt: string; + type: ActionType; + entity: EntityType; + entityParams: T; +} + +export interface ActionModel { + actionCreatedAt: string; + type: ActionType; + entity: EntityType; + entityParams: EntityTypeModel; +} + +export type EntityTypeModel = + | EntityUserHistoryActionModel diff --git a/src/app/model/user-preferences.model.ts b/src/app/model/user-preferences.model.ts new file mode 100644 index 0000000..61f9718 --- /dev/null +++ b/src/app/model/user-preferences.model.ts @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + + +import { DashboardApplications } from './dashboard.model'; +import { ActionFilter, ActionInterval } from './user-last-action.model'; + +export const STATE_KEYS = { + DASHBOARD: 'dashboard', + APPS: 'apps', + TILES: 'availableTiles', + USER_ACTIONS: 'lastUserAction', + FILTER_TYPE:'filterType', + INTERVAL: 'interval' +}; + + +export interface DashboardModel { + apps: DashboardAppsModel; +} + +export interface DashboardAppsModel { + availableTiles: DashboardTileSettings[]; + lastUserAction: LastUserActionSettings; +} + +export interface UserPreferencesModel { + dashboard: DashboardModel; +} + +export interface UpdateUserPreferenceModel { + dashboard?: { + apps?: { + availableTiles?: DashboardTileSettings[]; + lastUserAction?: LastUserActionSettings; + }; + }; +} + +export interface DashboardTileSettings { + type: DashboardApplications; + displayed: boolean; +} + +export interface LastUserActionSettings { + interval: ActionInterval; + filterType: ActionFilter; +} + +const availableDashboardApps: DashboardTileSettings[] = [ + { + type: DashboardApplications.USER_LAST_ACTION_TILE, + displayed: true, + }, +]; + +export const defaultLastUserActionSettings: LastUserActionSettings = { + interval: ActionInterval.LAST1H, + filterType: ActionFilter.ALL, +}; + +export const defaultUserSettings: UserPreferencesModel = { + dashboard: { + apps: { + availableTiles: availableDashboardApps, + lastUserAction: defaultLastUserActionSettings, + }, + }, +}; + +export const DASHBOARD_SECTION = 'dashboard'; diff --git a/src/app/model/validation-pattern.model.ts b/src/app/model/validation-pattern.model.ts new file mode 100644 index 0000000..d611d44 --- /dev/null +++ b/src/app/model/validation-pattern.model.ts @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +export const VALIDATION_PATTERN = "[\\w,/!=§#@€:µ.+?' \\-\\u00C0-\\u017F]*"; +export const NON_WHITE_SPACE_PATTERN = new RegExp('\\S'); + + //Info from team Euler --> predefined regexp in SO service instance name is: +// public static final String VALID_INSTANCE_NAME_FORMAT = "^[a-zA-Z][a-zA-Z0-9._-]*$"; +// thanks to that we will avoid the error during model deployment +export const VALID_INSTANCE_NAME_FORMAT_PATTERN = "^[a-zA-Z][a-zA-Z0-9._-]*$"; diff --git a/src/app/modules/alerting/alert.component.css b/src/app/modules/alerting/alert.component.css new file mode 100644 index 0000000..aeadd64 --- /dev/null +++ b/src/app/modules/alerting/alert.component.css @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +span { + width: 500px; +} +.alert-success { + color: #6bb324 !important; +} + +.alert-success > button.close::before { + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M15.81,14.99l-6.99-7l6.99-7c0.24-0.24,0.2-0.63-0.04-0.83c-0.24-0.2-0.59-0.2-0.79,0l-6.99,7l-6.99-7 C0.75-0.08,0.36-0.04,0.16,0.2c-0.2,0.24-0.2,0.59,0,0.79l6.99,7l-6.99,7c-0.24,0.24-0.2,0.63,0.04,0.83c0.24,0.2,0.59,0.2,0.79,0 l6.99-7l6.99,7c0.24,0.24,0.59,0.24,0.83,0.04C16.04,15.66,16.08,15.26,15.81,14.99C15.85,15.03,15.81,15.03,15.81,14.99z' fill='%236bb324'/%3E%3C/svg%3E") !important; +} +.alert-info { + color: #00a0de !important; +} + +.alert-info > button.close::before { + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M15.81,14.99l-6.99-7l6.99-7c0.24-0.24,0.2-0.63-0.04-0.83c-0.24-0.2-0.59-0.2-0.79,0l-6.99,7l-6.99-7 C0.75-0.08,0.36-0.04,0.16,0.2c-0.2,0.24-0.2,0.59,0,0.79l6.99,7l-6.99,7c-0.24,0.24-0.2,0.63,0.04,0.83c0.24,0.2,0.59,0.2,0.79,0 l6.99-7l6.99,7c0.24,0.24,0.59,0.24,0.83,0.04C16.04,15.66,16.08,15.26,15.81,14.99C15.85,15.03,15.81,15.03,15.81,14.99z' fill='%2300a0de'/%3E%3C/svg%3E") !important; +} +.alert-warning { + color: #87604e !important; + border-color: #87604e !important; +} + +.alert-warning > button.close::before { + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M15.81,14.99l-6.99-7l6.99-7c0.24-0.24,0.2-0.63-0.04-0.83c-0.24-0.2-0.59-0.2-0.79,0l-6.99,7l-6.99-7 C0.75-0.08,0.36-0.04,0.16,0.2c-0.2,0.24-0.2,0.59,0,0.79l6.99,7l-6.99,7c-0.24,0.24-0.2,0.63,0.04,0.83c0.24,0.2,0.59,0.2,0.79,0 l6.99-7l6.99,7c0.24,0.24,0.59,0.24,0.83,0.04C16.04,15.66,16.08,15.26,15.81,14.99C15.85,15.03,15.81,15.03,15.81,14.99z' fill='%2387604E'/%3E%3C/svg%3E") !important; +} +.alert-danger { + color: #d90000 !important; +} + +.alert-danger > button.close::before { + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M15.81,14.99l-6.99-7l6.99-7c0.24-0.24,0.2-0.63-0.04-0.83c-0.24-0.2-0.59-0.2-0.79,0l-6.99,7l-6.99-7 C0.75-0.08,0.36-0.04,0.16,0.2c-0.2,0.24-0.2,0.59,0,0.79l6.99,7l-6.99,7c-0.24,0.24-0.2,0.63,0.04,0.83c0.24,0.2,0.59,0.2,0.79,0 l6.99-7l6.99,7c0.24,0.24,0.59,0.24,0.83,0.04C16.04,15.66,16.08,15.26,15.81,14.99C15.85,15.03,15.81,15.03,15.81,14.99z' fill='%23d90000'/%3E%3C/svg%3E") !important; +} + +.custom-margin { + margin-right: 20px; +} + +i.bi { + font-size: 22px; +} + +.text-breaking { + word-break: break-word; +} diff --git a/src/app/modules/alerting/alert.component.html b/src/app/modules/alerting/alert.component.html new file mode 100644 index 0000000..157966f --- /dev/null +++ b/src/app/modules/alerting/alert.component.html @@ -0,0 +1,106 @@ +<!-- + ~ Copyright (c) 2022. Deutsche Telekom AG + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + ~ + ~ SPDX-License-Identifier: Apache-2.0 + --> + + +<div class="d-flex justify-content-center"> + <span> + <ngb-alert *ngFor="let alert of alerts" type="alert" class="{{ cssClass(alert) }}" [dismissible]="false"> + <button + type="button" + class="close" + [attr.aria-label]="'common.buttons.close' | translate" + (click)="removeAlert(alert)" + ></button> + <div class="d-flex text-breaking"> + <i + class="bi custom-margin" + [class.bi-info-circle-fill]="informativeAlerts.includes(alert.type)" + [class.bi-exclamation-triangle-fill]="!informativeAlerts.includes(alert.type)" + aria-hidden="true" + ></i> + + <div *ngIf="alert.type === AlertType.Error"> + <ng-container *ngIf="alert.id === 'keycloak'; else defaultErrorAlert"> + <span>{{ alert.message }}</span> + <ng-container *ngTemplateOutlet="supportTpl"></ng-container> + </ng-container> + </div> + + <div *ngIf="alert.type !== AlertType.Error"> + <span class="text-justify">{{ alert.message }}</span> + <ng-container *ngIf="alert.id === 'onap_logging'"> + <span>{{ 'common.alert.contactSupport.part1' | translate }}</span> + <a [href]="environment.supportUrlLink">{{ 'common.alert.support' | translate }}</a> + </ng-container> + </div> + </div> + + <ng-template #defaultErrorAlert> + <span *ngIf="alert.urlTree">{{ alert.message }}</span> + <span *ngIf="!alert.errorDetail">{{ alert.message }}</span> + <div *ngIf="alert?.errorDetail?.downstreamSystem as downstreamSystem"> + <span *ngIf="downstreamSystem"> + {{ 'common.alert.errorReporter' | translate: { system: 'common.systems.' + downstreamSystem | translate } }} + </span> + </div> + <div *ngIf="alert.errorDetail?.detail as detail"> + "{{ alert.errorDetail?.detail }}" + <div + *ngIf=" + alert.errorDetail?.downstreamSystem === DownstreamSystem.KEYCLOAK && + alert.errorDetail?.downstreamStatus === 409 + " + > + <span *ngIf="detail.split(' ').pop() === 'username'"> + {{ 'common.block.userAdministration.helpUserNameExists' | translate }} + </span> + <span *ngIf="detail.split(' ').pop() === 'email'"> + {{ 'common.block.userAdministration.helpUserEmailExists' | translate }} + </span> + </div> + </div> + <ng-container *ngTemplateOutlet="supportTpl"></ng-container> + </ng-template> + <ng-template #supportTpl> + <div> + {{ 'common.alert.support' | translate }} + <button + class="btn btn-sm p-0" + (click)="collapse.toggle()" + [attr.aria-expanded]="!isCollapsed" + aria-controls="collapseSupportInfo" + > + <i *ngIf="isCollapsed" class="bi bi-chevron-right text-danger" style="font-size: 18px" aria-hidden="true" [attr.aria-label]="'common.buttons.openSupportLink' | translate"></i> + <i *ngIf="!isCollapsed" class="bi bi-chevron-down text-danger" style="font-size: 18px" aria-hidden="true" [attr.aria-label]="'common.buttons.closeSupportLink' | translate"></i> + </button> + </div> + + <div #collapse="ngbCollapse" [(ngbCollapse)]="isCollapsed"> + <span>{{ 'common.alert.contactSupport.part1' | translate }}</span + ><a [href]="environment.supportUrlLink" target="_blank">{{ 'common.alert.support' | translate }}</a> + <ng-container *ngIf="alert?.requestId"> + <span>{{ 'common.alert.contactSupport.part2' | translate }}</span> + <div> + {{ alert?.requestId }} + </div> + </ng-container> + </div> + </ng-template> + </ngb-alert> + </span> +</div> diff --git a/src/app/modules/alerting/alert.component.spec.ts b/src/app/modules/alerting/alert.component.spec.ts new file mode 100644 index 0000000..abaf52e --- /dev/null +++ b/src/app/modules/alerting/alert.component.spec.ts @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { AlertComponent } from './alert.component'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { Router } from '@angular/router'; + +describe('AlertComponent', () => { + let component: AlertComponent; + let fixture: ComponentFixture<AlertComponent>; + const router = jasmine.createSpyObj('Router', ['navigate']); + beforeEach(async(() => { + TestBed.configureTestingModule({ + providers: [AlertComponent, { provide: Router, useValue: router }], + }).compileComponents(); + fixture = TestBed.createComponent(AlertComponent); + component = fixture.componentInstance; + })); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('Setting value to id properties', () => { + component.id = 'testId'; + fixture.detectChanges(); + }); + it('Setting value to fade properties', () => { + expect(component.fade).toBe(true); + component.fade = false; + fixture.detectChanges(); + }); +}); diff --git a/src/app/modules/alerting/alert.component.ts b/src/app/modules/alerting/alert.component.ts new file mode 100644 index 0000000..91d22f4 --- /dev/null +++ b/src/app/modules/alerting/alert.component.ts @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Component, Input, OnInit } from '@angular/core'; +import { NavigationStart, Router } from '@angular/router'; +import { Subscription } from 'rxjs'; + +import { Alert, AlertType } from './alert.model'; +import { AlertService } from './alert.service'; +import { UnsubscribeService } from 'src/app/services/unsubscribe/unsubscribe.service'; +import { takeUntil } from 'rxjs/operators'; +import { environment } from 'src/environments/environment'; +import { Problem } from '../../../../openapi/output'; +import DownstreamSystemEnum = Problem.DownstreamSystemEnum; + +@Component({ + selector: 'app-alert', + templateUrl: 'alert.component.html', + styleUrls: ['alert.component.css'], + providers: [UnsubscribeService], +}) +export class AlertComponent implements OnInit { + @Input() id = 'default-alert'; + @Input() fade = true; + + isCollapsed = true; + informativeAlerts: AlertType[] = [AlertType.Success, AlertType.Info]; + alerts: Alert[] = []; + alertSubscription!: Subscription; + routeSubscription!: Subscription; + AlertType = AlertType; + environment = environment; + DownstreamSystem = DownstreamSystemEnum; + constructor( + private router: Router, + private alertService: AlertService, + private unsubscribeService: UnsubscribeService, + ) {} + + ngOnInit() { + // subscribe to new alert notifications + this.alertSubscription = this.alertService.alerts + .pipe(takeUntil(this.unsubscribeService.unsubscribe$)) + .subscribe(alert => { + // clear alerts when an empty alert is received + if (!alert.message) { + // filter out alerts without 'keepAfterRouteChange' flag + this.alerts = this.alerts.filter(x => x.keepAfterRouteChange); + + // remove 'keepAfterRouteChange' flag on the rest + this.alerts.forEach(x => delete x.keepAfterRouteChange); + return; + } + if (this.alerts.filter(a => a.message === alert.message).length === 0) { + // add alert to array + this.alerts.push(alert); + } + // auto close alert if required + if (alert.type === AlertType.Warning) { + setTimeout(() => this.removeAlert(alert), 10000); + } + }); + + // clear alerts on location change + this.routeSubscription = this.router.events + .pipe(takeUntil(this.unsubscribeService.unsubscribe$)) + .subscribe(event => { + if (event instanceof NavigationStart) { + this.alertService.clear(this.id); + } + }); + } + + removeAlert(alert: Alert) { + // check if already removed to prevent error on auto close + if (!this.alerts.includes(alert)) { + return; + } + + if (this.fade) { + // fade out alert + this.alerts.find(x => x === alert)!.fade = true; + + // remove alert after faded out + setTimeout(() => { + this.alerts = this.alerts.filter(x => x !== alert); + }, 250); + } else { + // remove alert + this.alerts = this.alerts.filter(x => x !== alert); + } + } + + cssClass(alert: Alert) { + if (!alert) { + return; + } + + const classes = ['show', 'alert', 'alert-dismissable']; + + const alertTypeClass = { + /* + [AlertType.Success]: 'alert alert-success', + [AlertType.Error]: 'alert alert-danger', + [AlertType.Info]: 'alert alert-info', + [AlertType.Warning]: 'alert alert-warning' + */ + [AlertType.Success]: 'alert-success', + [AlertType.Error]: 'alert-danger', + [AlertType.Info]: 'alert-info', + [AlertType.Warning]: 'alert-warning', + }; + + classes.push(alertTypeClass[alert.type]); + + if (alert.fade) { + classes.push('fade'); + } + + return classes.join(' '); + } +} diff --git a/src/app/modules/alerting/alert.model.ts b/src/app/modules/alerting/alert.model.ts new file mode 100644 index 0000000..6e280ce --- /dev/null +++ b/src/app/modules/alerting/alert.model.ts @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Inject, Injectable } from '@angular/core'; +import { Problem } from '../../../../openapi/output'; + +@Injectable({ providedIn: 'root' }) +export class Alert { + id?: string; + type!: AlertType; + message?: string; + autoClose?: boolean; + keepAfterRouteChange?: boolean; + fade?: boolean; + errorDetail?: Problem; + requestId?: string; + urlTree?: string[] + + constructor(@Inject(Alert) init?: Partial<Alert>) { + Object.assign(this, init); + } +} + + + +export enum AlertType { + Success, + Error, + Info, + Warning, +} diff --git a/src/app/modules/alerting/alert.module.ts b/src/app/modules/alerting/alert.module.ts new file mode 100644 index 0000000..064bb32 --- /dev/null +++ b/src/app/modules/alerting/alert.module.ts @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { NgModule } from '@angular/core'; +import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; +import { CommonModule } from '@angular/common'; + +import { AlertComponent } from './alert.component'; +import { TranslateModule } from '@ngx-translate/core'; + +@NgModule({ + imports: [CommonModule, NgbModule, TranslateModule], + declarations: [AlertComponent], + exports: [AlertComponent], +}) +export class AlertModule {} diff --git a/src/app/modules/alerting/alert.service.spec.ts b/src/app/modules/alerting/alert.service.spec.ts new file mode 100644 index 0000000..5c9d219 --- /dev/null +++ b/src/app/modules/alerting/alert.service.spec.ts @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +// https://dev.to/coly010/unit-testing-angular-services-1anm +import { Alert, AlertType } from './alert.model'; +import { TestBed } from '@angular/core/testing'; +import { AlertModule } from './alert.module'; +import { AlertService } from './alert.service'; +import { Subject } from 'rxjs'; +import SpyObj = jasmine.SpyObj; + +/** + * describe sets up the Test Suite for the TileService + */ +describe('AlertService', () => { + let service: AlertService; + let mockAlert: Alert; + let message: string; + let spyAlert: SpyObj<any>; + let subject: Subject<Alert>; + + /** + * beforeEach tells the test runner to run this code before every test in the Test Suite + * It is using Angular's TestBed to create the testing environment and finally it is injecting the TilesService + * and placing a reference to it in the service variable defined earlier. + */ + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [AlertService, AlertModule, Subject], + }); + service = TestBed.inject(AlertService); + subject = TestBed.inject(Subject); + mockAlert = TestBed.inject(Alert); + spyAlert = spyOn(service, 'alert'); + message = 'This is a test-alert'; + mockAlert.message = message; + }); + + it('should be create', () => { + expect(service).toBeTruthy(); + }); + /** + * tests for the alert methods info, warning, error and success with a spyobject + */ + it('should return success alert', () => { + mockAlert.type = AlertType.Success; + service.success(message); + expect(spyAlert).toHaveBeenCalledWith(mockAlert); + }); + + it('should return warning alert', () => { + mockAlert.type = AlertType.Warning; + service.warn(message); + expect(spyAlert).toHaveBeenCalledWith(mockAlert); + }); + + it('should return error alert', () => { + mockAlert.type = AlertType.Error; + service.error(message); + expect(spyAlert).toHaveBeenCalledWith(mockAlert); + }); + + it('should return info alert', () => { + mockAlert.type = AlertType.Info; + service.info(message); + expect(spyAlert).toHaveBeenCalledWith(mockAlert); + }); + + it('clear ', () => { + subject = service['subject']; + const spy = spyOn(subject, 'next'); + const alert = new Alert(); + alert.id = 'default-alert'; + service.clear(); + expect(spy).toHaveBeenCalledWith(alert); + }); +}); diff --git a/src/app/modules/alerting/alert.service.ts b/src/app/modules/alerting/alert.service.ts new file mode 100644 index 0000000..4d81397 --- /dev/null +++ b/src/app/modules/alerting/alert.service.ts @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Injectable } from '@angular/core'; +import { Observable, Subject } from 'rxjs'; +import { filter } from 'rxjs/operators'; + +import { Alert, AlertType } from './alert.model'; + +@Injectable({ providedIn: 'root' }) +export class AlertService { + private subject = new Subject<Alert>(); + private defaultId = 'default-alert'; + + // enable subscribing to alerts observable + onAlert(id = this.defaultId): Observable<Alert> { + return this.subject.asObservable().pipe(filter(x => x && x.id === id)); + } + get alerts() { + return this.subject; + } + + // convenience methods + success(message: string, options?: Partial<Alert>) { + this.alert(new Alert({ ...options, type: AlertType.Success, message })); + } + + error(message: string, options?: Partial<Alert>) { + this.alert(new Alert({ ...options, type: AlertType.Error, message })); + } + + info(message: string, options?: Partial<Alert>) { + this.alert(new Alert({ ...options, type: AlertType.Info, message })); + } + + warn(message: string, options?: Partial<Alert>) { + this.alert(new Alert({ ...options, type: AlertType.Warning, message })); + } + + // main alert method + alert(alert: Alert) { + alert.id = alert.id || this.defaultId; + this.subject.next(alert); + } + + // clear alerts + clear(id = this.defaultId) { + this.subject.next(new Alert({ id })); + } +} diff --git a/src/app/modules/alerting/index.ts b/src/app/modules/alerting/index.ts new file mode 100644 index 0000000..492986c --- /dev/null +++ b/src/app/modules/alerting/index.ts @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +export * from './alert.module'; +export * from './alert.service'; +export * from './alert.model'; diff --git a/src/app/modules/app-starter/app-starter-routing.module.ts b/src/app/modules/app-starter/app-starter-routing.module.ts new file mode 100644 index 0000000..6696d3a --- /dev/null +++ b/src/app/modules/app-starter/app-starter-routing.module.ts @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; +import { AppStarterComponent } from './app-starter.component'; +import { AuthGuard } from '../../guards/auth.guard'; + +const routes: Routes = [{ path: '', component: AppStarterComponent, canActivate: [AuthGuard] }]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule], +}) +export class AppStarterRoutingModule {} diff --git a/src/app/modules/app-starter/app-starter.component.css b/src/app/modules/app-starter/app-starter.component.css new file mode 100644 index 0000000..8ec276c --- /dev/null +++ b/src/app/modules/app-starter/app-starter.component.css @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +.card-img-top { + width: 60%; + height: 5vw; + object-fit: contain; +} + +.card-deck > div { + display: flex; + flex: 1 0 0; + flex-direction: column; +} + +.card-deck > div:not(:last-child) { + margin-right: 15px; +} + +.card-deck { + width: 90%; + margin-left: 2%; +} + +.card-deck > div:not(:first-child) { + margin-left: 15px; +} + +.my-group-title { + color: var(--primary); +} + +.card { + border-radius: 20px; + cursor: pointer; + transition: 0.4s; + min-width: 200px; + max-width: 200px; + min-height: 250px; + max-height: 250px; + text-align: center; + margin-right: 2.25rem; +} + +.card-body { + padding-bottom: 0; +} + +.card-title { + min-height: 87px; + font-size: 14px; +} + +/* Works together with bootstraps responsive image class +https://stackoverflow.com/questions/53721711/how-to-set-responsive-images-max-width-bootstrap-4#53723494 +*/ +.img-max { + max-width: 115px; + width: 100%; +} + +.card:hover { + transform: scale(1.1, 1.1); + box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); +} + +.disabled-card:hover { + transform: none !important; + box-shadow: none !important; + transition: none !important; +} + +a, +a:hover { + color: #262626; + text-decoration: none; +} + +a:hover { + cursor: pointer; +} + +.nav-tabs, +.nav-links { + border-bottom: 1px solid #b2b2b2; +} + +.nav-link { + background-color: transparent; +} +.nav-tabs .nav-link.active, +.nav-tabs .nav-item.show .nav-link { + color: var(--primary); + background-color: #fff; + border-color: #b2b2b2 #b2b2b2 #fff; +} + +.nav-link:focus { + border-style: none; +} + +/* I will leave this for future purpose in case we will have disabled tiles in the Portal */ +/* .disabled-tiles { + opacity: 0.5; + cursor: not-allowed !important; +} */ diff --git a/src/app/modules/app-starter/app-starter.component.html b/src/app/modules/app-starter/app-starter.component.html new file mode 100644 index 0000000..aae2bf3 --- /dev/null +++ b/src/app/modules/app-starter/app-starter.component.html @@ -0,0 +1,47 @@ +<!-- + ~ Copyright (c) 2022. Deutsche Telekom AG + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + ~ + ~ SPDX-License-Identifier: Apache-2.0 + --> + + +<app-breadcrumb> + <app-breadcrumb-item> + <a [routerLink]="['/dashboard']">{{ 'layout.menu.items.home' | translate }}</a> + </app-breadcrumb-item> + <app-breadcrumb-item> + <span aria-current="page">{{ 'appStarter.title' | translate }}</span> + </app-breadcrumb-item> +</app-breadcrumb> +<h2>{{ 'appStarter.title' | translate }}</h2> +<hr /> +<div class="d-flex flex-wrap cards my-5"> + <ng-container *ngIf="tiles$ | async as tiles"> + <div class="card mb-5 qa_tiles_wrapper" *ngFor="let tile of tiles" [ngbTooltip]="'appStarter.tiles.tooltips.enum.' + tile.id | translate"> + <a class="card-block stretched-link text-decoration-none my-3 qa_tiles_not_disabled" [href]="tile.redirectUrl" target="_blank"> + <img + src="assets/images/tiles/{{ tile.imageUrl }}" + class="img-fluid img-max rounded my-2 qa_tiles_not_disabled_img" + alt="{{ tile.imageAltText }}" + /> + <div class="card-body qa_tiles_not_disabled_body"> + <p class="card-title qa_tiles_not_disabled_title">{{ tile.title }}</p> + </div> + </a> + </div> + </ng-container> +</div> + + diff --git a/src/app/modules/app-starter/app-starter.component.ts b/src/app/modules/app-starter/app-starter.component.ts new file mode 100644 index 0000000..c08467f --- /dev/null +++ b/src/app/modules/app-starter/app-starter.component.ts @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Component, OnInit } from '@angular/core'; +import { map } from 'rxjs/operators'; +import { environment } from 'src/environments/environment'; +import { from, Observable, of } from 'rxjs'; +import { Tile } from 'src/app/model/tile'; + +@Component({ + selector: 'app-app-starter', + templateUrl: './app-starter.component.html', + styleUrls: ['./app-starter.component.css'], +}) +export class AppStarterComponent implements OnInit { + //I will leave this for future purpose in case we will have disabled tiles in the Portal + // disabledTiles:number[] = [11,12,13] + + private readonly hostname = environment.hostname.replace('portal-ui-', ''); + + public readonly tiles$: Observable<Tile[]> = from(fetch('/assets/tiles/tiles.json?t=' + Date.now()).then(rsp => rsp.json())) + .pipe( + map(tiles => (tiles.items as Tile[])), + map(tiles => tiles.map(tile => ({ ...tile, redirectUrl: tile.redirectUrl.replace(/HOSTNAME/i, this.hostname) }))), + ); + + + ngOnInit(): void {} +} diff --git a/src/app/modules/app-starter/app-starter.module.ts b/src/app/modules/app-starter/app-starter.module.ts new file mode 100644 index 0000000..ebbd0ce --- /dev/null +++ b/src/app/modules/app-starter/app-starter.module.ts @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { NgModule } from '@angular/core'; +import { AppStarterComponent } from './app-starter.component'; +import { AppStarterRoutingModule } from './app-starter-routing.module'; +import { SharedModule } from '../../shared.module'; + +@NgModule({ + declarations: [AppStarterComponent], + imports: [AppStarterRoutingModule, SharedModule], +}) +export class AppStarterModule {} diff --git a/src/app/modules/auth/auth.config.module.ts b/src/app/modules/auth/auth.config.module.ts new file mode 100644 index 0000000..7f70ba6 --- /dev/null +++ b/src/app/modules/auth/auth.config.module.ts @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { APP_INITIALIZER, NgModule } from '@angular/core'; +import { AuthConfig } from 'angular-oauth2-oidc'; + +import { authConfig } from './auth.config'; +import { HTTP_INTERCEPTORS } from '@angular/common/http'; +import { AuthInterceptor } from '../../http-interceptors/auth.interceptor'; +import { AuthConfigService } from '../../services/authconfig.service'; + +export function init_app(authConfigService: AuthConfigService) { + return () => authConfigService.initAuth(); +} + +@NgModule({ + providers: [ + { provide: AuthConfig, useValue: authConfig }, + AuthConfigService, + { + provide: APP_INITIALIZER, + useFactory: init_app, + deps: [AuthConfigService], + multi: true, + }, + { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true }, + ], + declarations: [], +}) +export class AuthConfigModule {} diff --git a/src/app/modules/auth/auth.config.ts b/src/app/modules/auth/auth.config.ts new file mode 100644 index 0000000..3414edd --- /dev/null +++ b/src/app/modules/auth/auth.config.ts @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { AuthConfig } from 'angular-oauth2-oidc'; +import { environment } from '../../../environments/environment'; + +export const authConfig: AuthConfig = { + // Url of the Identity Provider + issuer: environment.keycloak.issuer, + + // URL of the SPA to redirect the user to after login + redirectUri: environment.keycloak.redirectUri, + + // The SPA's id. + // The SPA is registerd with this id at the auth-serverß + clientId: environment.keycloak.clientId, + + responseType: environment.keycloak.responseType, + // set the scope for the permissions the client should request + // The first three are defined by OIDC. + scope: environment.keycloak.scope, + // Remove the requirement of using Https to simplify the demo + // THIS SHOULD NOT BE USED IN PRODUCTION + // USE A CERTIFICATE FOR YOUR IDP + // IN PRODUCTION + requireHttps: environment.keycloak.requireHttps, + // at_hash is not present in JWT token + showDebugInformation: environment.keycloak.showDebugInformation, + disableAtHashCheck: environment.keycloak.disableAtHashCheck, + skipIssuerCheck: environment.keycloak.skipIssuerCheck, + strictDiscoveryDocumentValidation: environment.keycloak.strictDiscoveryDocumentValidation, +}; diff --git a/src/app/modules/auth/injection-tokens.ts b/src/app/modules/auth/injection-tokens.ts new file mode 100644 index 0000000..140b83c --- /dev/null +++ b/src/app/modules/auth/injection-tokens.ts @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { InjectionToken } from '@angular/core'; + +export interface AclConfig { + [key: string]: string[]; +} + +export const ACL_CONFIG = new InjectionToken<AclConfig>('ACL_CONFIG'); diff --git a/src/app/modules/dashboard/apps/user-last-action-tile/action-button/action-button.component.css b/src/app/modules/dashboard/apps/user-last-action-tile/action-button/action-button.component.css new file mode 100644 index 0000000..b7b5110 --- /dev/null +++ b/src/app/modules/dashboard/apps/user-last-action-tile/action-button/action-button.component.css @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + diff --git a/src/app/modules/dashboard/apps/user-last-action-tile/action-button/action-button.component.html b/src/app/modules/dashboard/apps/user-last-action-tile/action-button/action-button.component.html new file mode 100644 index 0000000..2c35f19 --- /dev/null +++ b/src/app/modules/dashboard/apps/user-last-action-tile/action-button/action-button.component.html @@ -0,0 +1,63 @@ +<!-- + ~ Copyright (c) 2022. Deutsche Telekom AG + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + ~ + ~ SPDX-License-Identifier: Apache-2.0 + --> + + +<ng-container *ngIf="action"> + <button + *ngIf="action.type | in: REPEAT_ACTIONS" + class="btn btn-invisible p-0 qa_repeat_action" + (click)="onButtonClick(action)" + [attr.aria-label]="'dashboard.apps.userLastAction.tooltip.repeatAction' | translate" + [ngbTooltip]="repeatActionTooltipContent" + container="body" + > + <i class="bi bi-arrow-clockwise pointer" aria-hidden="true"></i> + </button> + <button + *ngIf="action.type | in: VIEW_ACTIONS" + class="btn btn-invisible p-0 qa_view_action" + (click)="onButtonClick(action)" + [attr.aria-label]="'dashboard.apps.userLastAction.tooltip.viewAction' | translate" + [ngbTooltip]="viewActionTooltipContent" + container="body" + > + <i class="bi bi-eyeglasses" aria-hidden="true"></i> + </button> + + <ng-template #repeatActionTooltipContent> + <span + >{{ 'dashboard.apps.userLastAction.actionType.' + action.type | translate }} + {{ 'dashboard.apps.userLastAction.tooltip.again' | translate }} + {{ 'dashboard.apps.userLastAction.entityType.' + action.entity | translate }} + {{ message }}</span + > + </ng-template> + <ng-template #viewActionTooltipContent> + <span + >{{ 'dashboard.apps.userLastAction.actionType.' + ActionType.VIEW | translate }} + <span *ngIf="action.type === ActionType.DEPLOY"> + {{ 'dashboard.apps.userLastAction.tooltip.statusOf' | translate }} + </span> + {{ 'dashboard.apps.userLastAction.entityType.' + action.entity | translate }} + <span *ngIf="action.type === ActionType.DEPLOY"> + {{ 'dashboard.apps.userLastAction.tooltip.deployment' | translate }} + </span> + {{ message }}</span + > + </ng-template> +</ng-container> diff --git a/src/app/modules/dashboard/apps/user-last-action-tile/action-button/action-button.component.ts b/src/app/modules/dashboard/apps/user-last-action-tile/action-button/action-button.component.ts new file mode 100644 index 0000000..b30a35e --- /dev/null +++ b/src/app/modules/dashboard/apps/user-last-action-tile/action-button/action-button.component.ts @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { ActionModel, ActionRowModel, ActionType, EntityTypeModel } from '../../../../../model/user-last-action.model'; + +@Component({ + selector: 'app-action-button', + templateUrl: './action-button.component.html', + styleUrls: ['./action-button.component.css'], +}) +export class ActionButtonComponent { + public readonly VIEW_ACTIONS = [ActionType.ACK, ActionType.UNACK, ActionType.CLEAR, ActionType.DEPLOY]; + public readonly REPEAT_ACTIONS = [ActionType.SEARCH, ActionType.VIEW, ActionType.EDIT]; + ActionType = ActionType; + + @Input() action: ActionRowModel<EntityTypeModel> | undefined; + @Input() message: string | undefined; + @Output() btnClick = new EventEmitter<ActionModel>(); + + public onButtonClick(action: ActionModel): void { + this.btnClick.emit(action); + } +} diff --git a/src/app/modules/dashboard/apps/user-last-action-tile/action-row/action-row.component.css b/src/app/modules/dashboard/apps/user-last-action-tile/action-row/action-row.component.css new file mode 100644 index 0000000..c6f52a8 --- /dev/null +++ b/src/app/modules/dashboard/apps/user-last-action-tile/action-row/action-row.component.css @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +img { + height: 20px; + width: 20px; +} diff --git a/src/app/modules/dashboard/apps/user-last-action-tile/action-row/action-row.component.html b/src/app/modules/dashboard/apps/user-last-action-tile/action-row/action-row.component.html new file mode 100644 index 0000000..62cf722 --- /dev/null +++ b/src/app/modules/dashboard/apps/user-last-action-tile/action-row/action-row.component.html @@ -0,0 +1,105 @@ +<!-- + ~ Copyright (c) 2022. Deutsche Telekom AG + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + ~ + ~ SPDX-License-Identifier: Apache-2.0 + --> + + +<ng-container *ngIf="action"> + <div class="row py-2 border-bottom"> + <div class="col-3"> + <div class="d-flex justify-content-between"> + <span + class="qa_action_created_at" + container="body" + [ngbTooltip]="action.actionCreatedAt | date: FULL_DATE_FORMAT" + >{{ + (action.actionCreatedAt | isToday) + ? (action.actionCreatedAt | date: TIME_FORMAT) + : (action.actionCreatedAt | date: DATE_FORMAT) + }}</span + > + <ng-container [ngSwitch]="action.type"> + <ng-template [ngSwitchCase]="ActionType.CREATE"> + <img + class="qa_create_icon" + src='../../../../../../assets/images/icons/install_graphical.svg' + [attr.alt]="'dashboard.apps.userLastAction.actionType.CREATE' | translate" + /> + </ng-template> + <ng-template [ngSwitchCase]="ActionType.DELETE"> + <img + class="qa_delete_icon" + src='../../../../../../assets/images/icons/eraser_graphical.svg' + [attr.alt]="'dashboard.apps.userLastAction.actionType.DELETE' | translate" + /> + </ng-template> + <ng-template [ngSwitchCase]="ActionType.SEARCH"> + <img + class="qa_search_icon" + src='../../../../../../assets/images/icons/search_graphical.svg' + [attr.alt]="'dashboard.apps.userLastAction.actionType.SEARCH' | translate" + /> + </ng-template> + <ng-template [ngSwitchCase]="ActionType.VIEW"> + <img + class="qa_view_icon" + src='../../../../../../assets/images/icons/visible_graphical.svg' + [attr.alt]="'dashboard.apps.userLastAction.actionType.VIEW' | translate" + /> + </ng-template> + <ng-template [ngSwitchCase]="ActionType.EDIT"> + <img + class="qa_edit_icon" + src='../../../../../../assets/images/icons/edit_graphical.svg' + [attr.alt]="'dashboard.apps.userLastAction.actionType.EDIT' | translate" + /> + </ng-template> + <ng-template [ngSwitchCase]="ActionType.CLEAR"> + <img + class="qa_clear_icon" + src='../../../../../../assets/images/icons/brush_graphical.svg' + [attr.alt]="'dashboard.apps.userLastAction.actionType.CLEAR' | translate" + /> + </ng-template> + <ng-template [ngSwitchCase]="ActionType.ACK"> + <img + class="qa_ack_icon" + src='../../../../../../assets/images/icons/thumbs-up_graphical.svg' + [attr.alt]="'dashboard.apps.userLastAction.actionType.ACK' | translate" + /> + </ng-template> + <ng-template [ngSwitchCase]="ActionType.UNACK"> + <img + class="qa_unack_icon" + src='../../../../../../assets/images/icons/thumbs-down_graphical.svg' + [attr.alt]="'dashboard.apps.userLastAction.actionType.UNACK' | translate" + /> + </ng-template> + <ng-template [ngSwitchCase]="ActionType.DEPLOY"> + <img + class="qa_deployment_icon" + src='../../../../../../assets/images/icons/crane_graphical.svg' + [attr.alt]="'dashboard.apps.userLastAction.actionType.DEPLOY' | translate" + /> + </ng-template> + </ng-container> + </div> + </div> + <div class="col-9"> + <ng-content></ng-content> + </div> + </div> +</ng-container> diff --git a/src/app/modules/dashboard/apps/user-last-action-tile/action-row/action-row.component.ts b/src/app/modules/dashboard/apps/user-last-action-tile/action-row/action-row.component.ts new file mode 100644 index 0000000..89e7950 --- /dev/null +++ b/src/app/modules/dashboard/apps/user-last-action-tile/action-row/action-row.component.ts @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Component, Input } from '@angular/core'; +import { ActionModel, ActionType, EntityType } from '../../../../../model/user-last-action.model'; + +@Component({ + selector: 'app-action-row', + templateUrl: './action-row.component.html', + styleUrls: ['./action-row.component.css'], +}) +export class ActionRowComponent { + readonly FULL_DATE_FORMAT = 'E, d MMM Y HH:mm'; + readonly TIME_FORMAT = 'HH:mm'; + readonly DATE_FORMAT = 'd MMM'; + ActionType = ActionType; + EntityType = EntityType; + @Input() action: ActionModel | undefined; +} diff --git a/src/app/modules/dashboard/apps/user-last-action-tile/entity-user-administration-row/entity-user-administration-row.component.css b/src/app/modules/dashboard/apps/user-last-action-tile/entity-user-administration-row/entity-user-administration-row.component.css new file mode 100644 index 0000000..b7b5110 --- /dev/null +++ b/src/app/modules/dashboard/apps/user-last-action-tile/entity-user-administration-row/entity-user-administration-row.component.css @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + diff --git a/src/app/modules/dashboard/apps/user-last-action-tile/entity-user-administration-row/entity-user-administration-row.component.html b/src/app/modules/dashboard/apps/user-last-action-tile/entity-user-administration-row/entity-user-administration-row.component.html new file mode 100644 index 0000000..54f71c6 --- /dev/null +++ b/src/app/modules/dashboard/apps/user-last-action-tile/entity-user-administration-row/entity-user-administration-row.component.html @@ -0,0 +1,33 @@ +<!-- + ~ Copyright (c) 2022. Deutsche Telekom AG + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + ~ + ~ SPDX-License-Identifier: Apache-2.0 + --> + + +<div class="d-flex justify-content-between" *ngIf='action'> + <span class="d-inline-block text-truncate w-100" + >{{ 'dashboard.apps.userLastAction.actionType.' + action.type | translate }} + {{ 'dashboard.apps.userLastAction.entityType.' + action.entity | translate | colon }} + {{ action.entityParams.userName }} + </span> + + <app-action-button + *ngIf="action.type === ActionType.EDIT" + [message]="action.entityParams.userName" + [action]="action" + (btnClick)="repeatAction(action)" + ></app-action-button> +</div> diff --git a/src/app/modules/dashboard/apps/user-last-action-tile/entity-user-administration-row/entity-user-administration-row.component.ts b/src/app/modules/dashboard/apps/user-last-action-tile/entity-user-administration-row/entity-user-administration-row.component.ts new file mode 100644 index 0000000..b55ad17 --- /dev/null +++ b/src/app/modules/dashboard/apps/user-last-action-tile/entity-user-administration-row/entity-user-administration-row.component.ts @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Component, Input } from '@angular/core'; +import { ActionRowModel, ActionType, EntityUserHistoryActionModel } from '../../../../../model/user-last-action.model'; +import { Router } from '@angular/router'; + +@Component({ + selector: 'app-entity-user-administration-row', + templateUrl: './entity-user-administration-row.component.html', + styleUrls: ['./entity-user-administration-row.component.css'], +}) +export class EntityUserAdministrationRowComponent { + ActionType = ActionType; + @Input() + action: ActionRowModel<EntityUserHistoryActionModel> | undefined; + + constructor(private router: Router) {} + + public repeatAction(action: ActionRowModel<EntityUserHistoryActionModel>): void { + this.router.navigate(['user-administration', action.entityParams.userId, 'edit']); + } +} diff --git a/src/app/modules/dashboard/apps/user-last-action-tile/user-last-action-tile.component.css b/src/app/modules/dashboard/apps/user-last-action-tile/user-last-action-tile.component.css new file mode 100644 index 0000000..60842fa --- /dev/null +++ b/src/app/modules/dashboard/apps/user-last-action-tile/user-last-action-tile.component.css @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +img { + height: 20px; + width: 20px; +} + +.bg-color-inherit { + background-color: inherit; +} diff --git a/src/app/modules/dashboard/apps/user-last-action-tile/user-last-action-tile.component.html b/src/app/modules/dashboard/apps/user-last-action-tile/user-last-action-tile.component.html new file mode 100644 index 0000000..d696728 --- /dev/null +++ b/src/app/modules/dashboard/apps/user-last-action-tile/user-last-action-tile.component.html @@ -0,0 +1,85 @@ +<!-- + ~ Copyright (c) 2022. Deutsche Telekom AG + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + ~ + ~ SPDX-License-Identifier: Apache-2.0 + --> + +<ng-template #template> + <ng-container *ngIf="actions$ | async as actions"> + <div class="col-xl-4 col-lg-6 col-sm-12 my-2 qa_USER_LAST_ACTION_TILE" cdkDrag> + <div class="shadow card" style="height: 334.867px"> + <div class="card-header pl-3"> + <div class="d-flex" *ngIf="actionFilterType$ | async as selectedFilter"> + <div class="d-flex align-items-center"> + <i + class="bi bi-arrows-move text-primary draggable text-primary pr-2" + cdkDragHandle + aria-hidden="true" + ></i> + <label class="d-none" for="filterSelect" + >{{ 'dashboard.apps.userLastAction.filter.label' | translate + }}{{ 'dashboard.apps.userLastAction.filter.type.' + selectedFilter | translate }}</label + > + <select + id="filterSelect" + [ngModel]="selectedFilter" + (ngModelChange)="changeFilterType.next($event)" + class="form-select-sm font-weight-bolder bg-color-inherit" + > + <option *ngFor="let filter of actionsFilter" [ngValue]="filter" class="font-weight-normal"> + {{ 'dashboard.apps.userLastAction.filter.type.' + filter | translate }} + </option> + </select> + </div> + <div class="d-flex" *ngIf="actionIntervalType$ | async as selectedInterval"> + <label class="d-none" for="intervalSelect" + >{{ 'dashboard.apps.userLastAction.filter.label' | translate + }}{{ 'dashboard.apps.userLastAction.filter.interval.' + selectedInterval | translate }}</label + > + <select + id="intervalSelect" + [ngModel]="selectedInterval" + (ngModelChange)="changeIntervalType.next($event)" + class="form-select-sm font-weight-bold bg-color-inherit" + > + <option *ngFor="let interval of intervals" [ngValue]="interval" class="font-weight-normal"> + {{ 'dashboard.apps.userLastAction.filter.interval.' + interval | translate }} + </option> + </select> + </div> + </div> + </div> + <div class="card-body overflow-auto"> + <ng-container *ngIf="actions.length > 0; else noData"> + <div *ngFor="let action of actions"> + <app-action-row [action]="action"> + <app-entity-user-administration-row + *ngIf="action.entity === EntityType.USERADMINISTRATION" + [action]="$any(action)" + ></app-entity-user-administration-row> + </app-action-row> + </div> + </ng-container> + </div> + <div class="card-footer"></div> + </div> + </div> + </ng-container> +</ng-template> +<ng-template #noData> + <div class="d-flex justify-content-center qa_class_no_data"> + {{ 'common.filters.noResults' | translate }} + </div> +</ng-template> diff --git a/src/app/modules/dashboard/apps/user-last-action-tile/user-last-action-tile.component.ts b/src/app/modules/dashboard/apps/user-last-action-tile/user-last-action-tile.component.ts new file mode 100644 index 0000000..c03016f --- /dev/null +++ b/src/app/modules/dashboard/apps/user-last-action-tile/user-last-action-tile.component.ts @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Component, OnInit, TemplateRef, ViewChild, ViewContainerRef } from '@angular/core'; +import { + ActionFilter, + ActionInterval, + ActionModel, + ActionType, + EntityType, +} from '../../../../model/user-last-action.model'; +import { ActionsListResponse } from '../../../../../../openapi/output'; +import { combineLatest, merge, Subject } from 'rxjs'; +import { map, scan, shareReplay, switchMap } from 'rxjs/operators'; +import { UnsubscribeService } from '../../../../services/unsubscribe/unsubscribe.service'; +import { selectDistinctState, UserSettingsService } from '../../../../services/user-settings.service'; +import { LastUserActionSettings, STATE_KEYS } from '../../../../model/user-preferences.model'; +import { HistoryService } from '../../../../services/history.service'; + +@Component({ + selector: 'app-user-last-action-tile', + templateUrl: './user-last-action-tile.component.html', + styleUrls: ['./user-last-action-tile.component.css'], + providers: [UnsubscribeService], +}) +export class UserLastActionTileComponent implements OnInit { + public readonly actionsFilter: ActionFilter[] = Object.values(ActionFilter); + public readonly intervals: ActionInterval[] = Object.values(ActionInterval); + public readonly ActionType = ActionType; + public readonly EntityType = EntityType; + public changeFilterType: Subject<ActionFilter> = new Subject<ActionFilter>(); + public changeIntervalType: Subject<ActionInterval> = new Subject<ActionInterval>(); + + @ViewChild('template', { static: true }) template!: TemplateRef<unknown>; + + constructor( + private viewContainerRef: ViewContainerRef, + private historyService: HistoryService, + private unsubscribeService: UnsubscribeService, + private userSettingsService: UserSettingsService, + ) {} + + private userActionsSettings$ = this.userSettingsService + .selectLastUserAction() + .pipe(shareReplay({ refCount: true, bufferSize: 1 })); + + public actionFilterType$ = this.userActionsSettings$.pipe( + selectDistinctState<LastUserActionSettings, ActionFilter>(STATE_KEYS.FILTER_TYPE), + shareReplay({ refCount: true, bufferSize: 1 }), + ); + + public actionIntervalType$ = this.userActionsSettings$.pipe( + selectDistinctState<LastUserActionSettings, ActionInterval>(STATE_KEYS.INTERVAL), + shareReplay({ refCount: true, bufferSize: 1 }), + ); + + public actions$ = combineLatest([this.actionFilterType$, this.actionIntervalType$]).pipe( + switchMap(([filter, interval]) => { + const mappedInterval = UserLastActionTileComponent.mapActionInterval(interval); + return this.historyService.getUserActions(mappedInterval).pipe( + map(actions => UserLastActionTileComponent.mapActionsFromResponse(actions)), + map(actions => this.filterBySelectedFilterType(filter, actions)), + ); + }), + ); + + private commands$ = merge( + this.changeIntervalType.pipe(map(interval => ({ interval: interval }))), + this.changeFilterType.pipe(map(filterType => ({ filterType: filterType }))), + ); + + private settings$ = this.userActionsSettings$.pipe( + switchMap(data => this.commands$.pipe(scan((settings, change) => ({ ...settings, ...change }), data))), + ); + + ngOnInit(): void { + this.viewContainerRef.createEmbeddedView(this.template); + + this.settings$ + .pipe( + switchMap(lastUserAction => + this.userSettingsService.updatePreferences({ + dashboard: { + apps: { + lastUserAction, + }, + }, + }), + ), + ) + .subscribe(); + } + + private static mapActionsFromResponse(actions: ActionsListResponse): ActionModel[] { + return actions.items.map((action: any) => { + return { + actionCreatedAt: action.actionCreatedAt, + type: action.action.type, + entity: action.action.entity, + entityParams: { + ...action.action.entityParams, + }, + }; + }); + } + + private static mapActionInterval(interval: ActionInterval): number | undefined { + switch (interval) { + case ActionInterval.ALL: + return undefined; + case ActionInterval.LAST1D: + return 24; + case ActionInterval.LAST1H: + return 1; + case ActionInterval.LAST4H: + return 4; + } + } + + private filterBySelectedFilterType(filter: ActionFilter, actions: ActionModel[]): ActionModel[] { + if (filter === ActionFilter.ALL) { + return actions; + } else if (filter === ActionFilter.SEARCH) { + return actions.filter(action => action.type === ActionType.SEARCH); + } else { + return actions.filter(action => action.type !== ActionType.SEARCH); + } + } +} diff --git a/src/app/modules/dashboard/dashboard-routing.module.ts b/src/app/modules/dashboard/dashboard-routing.module.ts new file mode 100644 index 0000000..68833ba --- /dev/null +++ b/src/app/modules/dashboard/dashboard-routing.module.ts @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; +import { AuthGuard } from '../../guards/auth.guard'; +import { DashboardComponent } from './dashboard.component'; + +const routes: Routes = [{ path: '', component: DashboardComponent, canActivate: [AuthGuard] }]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule], +}) +export class DashboardRoutingModule {} diff --git a/src/app/modules/dashboard/dashboard.component.css b/src/app/modules/dashboard/dashboard.component.css new file mode 100644 index 0000000..bdf57d6 --- /dev/null +++ b/src/app/modules/dashboard/dashboard.component.css @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +p { + margin-bottom: 0 !important; +} +li { + list-style-type: none; +} + +.row > * { + flex-shrink: 0; + width: initial; + max-width: initial; + padding-right: initial; + padding-left: initial; + margin-top: initial; +} diff --git a/src/app/modules/dashboard/dashboard.component.html b/src/app/modules/dashboard/dashboard.component.html new file mode 100644 index 0000000..76a8e96 --- /dev/null +++ b/src/app/modules/dashboard/dashboard.component.html @@ -0,0 +1,77 @@ +<!-- + ~ Copyright (c) 2022. Deutsche Telekom AG + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + ~ + ~ SPDX-License-Identifier: Apache-2.0 + --> + + +<app-breadcrumb> + <app-breadcrumb-item> + <span aria-current="page">{{ 'layout.menu.items.dashboard' | translate }}</span> + </app-breadcrumb-item> +</app-breadcrumb> +<ng-container *ngIf="tiles$ | async as apps"> + <div class="w-100 d-flex justify-content-between"> + <h2 class="qa_title">{{ 'layout.menu.items.dashboard' | translate }}</h2> + <ul> + <li + #settingsDrop="ngbDropdown" + [ngbTooltip]="'dashboard.tooltips.settings' | translate" + class="qa_alarm_auto_settings" + ngbDropdown + > + <button + [attr.aria-label]="'dashboard.showSettings' | translate" + class="btn btn-outline-secondary no-border qa_dashboard_show_and_hide_settings_btn" + id="dropdownColumnSettings" + ngbDropdownToggle + > + <i aria-hidden="true" class="bi bi-gear-fill text-muted"></i> + </button> + <div aria-labelledby="dropdownColumnSettings" ngbDropdownMenu style="min-width: 250px"> + <p class="px-4 small text-muted mb-1">{{ 'dashboard.selectApplications' | translate }}</p> + <form class="px-4 py-3 d-flex flex-column align-items-start"> + <div + [appHasPermissions]="'dashboard.tile.' + app.type" + *ngFor="let app of apps" + class="d-flex justify-content-center" + > + <ng-container *ngIf="'dashboard.tile.' + app.type | hasPermission | async"> + <input + type="checkbox" + [(ngModel)]="app.displayed" + (ngModelChange)="updateAction.next(app)" + [ngModelOptions]="{ standalone: true }" + [ngClass]="'qa_dashboard_show_app_' + app.type" + /> + <p class="ml-2">{{ 'dashboard.apps.' + app.type | translate }}</p> + </ng-container> + </div> + </form> + </div> + </li> + </ul> + </div> + <hr /> + <div class="row" cdkDropList (cdkDropListDropped)="dropAction.next($event)"> + <ng-container *ngFor="let app of apps | map: filterDisplayedTiles"> + <ng-container *ngIf="'dashboard.tile.' + app.type | hasPermission | async"> + <ng-container *ngIf="app.type === DashboardApplications.USER_LAST_ACTION_TILE"> + <app-user-last-action-tile></app-user-last-action-tile> + </ng-container> + </ng-container> + </ng-container> + </div> +</ng-container> diff --git a/src/app/modules/dashboard/dashboard.component.ts b/src/app/modules/dashboard/dashboard.component.ts new file mode 100644 index 0000000..043ab6b --- /dev/null +++ b/src/app/modules/dashboard/dashboard.component.ts @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Component, OnInit } from '@angular/core'; +import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop'; +import { UserSettingsService } from '../../services/user-settings.service'; +import { DashboardApplications, DashboardTileSettings } from '../../model/dashboard.model'; +import { UnsubscribeService } from '../../services/unsubscribe/unsubscribe.service'; +import { map, shareReplay, switchMap, takeUntil } from 'rxjs/operators'; +import { merge, Observable, Subject } from 'rxjs'; + +@Component({ + selector: 'app-dashboard', + templateUrl: './dashboard.component.html', + styleUrls: ['./dashboard.component.css'], + providers: [UnsubscribeService], +}) +export class DashboardComponent implements OnInit { + DashboardApplications = DashboardApplications; + + public dropAction = new Subject<CdkDragDrop<string[]>>(); + public updateAction = new Subject<DashboardTileSettings>(); + + constructor(private unsubscribeService: UnsubscribeService, private userSettingsService: UserSettingsService) {} + + public tiles$: Observable<DashboardTileSettings[]> = this.userSettingsService + .selectDashboardAvailableTiles() + .pipe(shareReplay({ refCount: true, bufferSize: 1 })); + + filterDisplayedTiles(tiles: DashboardTileSettings[]): DashboardTileSettings[] { + return tiles.filter(tile => tile.displayed); + } + + public visibleTiles$: Observable<DashboardTileSettings[]> = this.tiles$.pipe( + switchMap(tiles => + this.updateAction.pipe( + map(updatedTile => { + const index = tiles.findIndex(tile => tile.type === updatedTile.type); + tiles[index].displayed = updatedTile.displayed; + return [...tiles]; + }), + ), + ), + ); + + public movedTiles$: Observable<DashboardTileSettings[]> = this.tiles$.pipe( + switchMap(tiles => + this.dropAction.pipe( + map(event => { + moveItemInArray(tiles, event.previousIndex, event.currentIndex); + return tiles; + }), + ), + ), + ); + ngOnInit() { + merge(this.visibleTiles$, this.movedTiles$) + .pipe( + takeUntil(this.unsubscribeService.unsubscribe$), + switchMap(availableTiles => + this.userSettingsService.updatePreferences({ + dashboard: { + apps: { + availableTiles, + }, + }, + }), + ), + ) + .subscribe(); + } +} diff --git a/src/app/modules/dashboard/dashboard.module.ts b/src/app/modules/dashboard/dashboard.module.ts new file mode 100644 index 0000000..8d63307 --- /dev/null +++ b/src/app/modules/dashboard/dashboard.module.ts @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +import { NgModule } from '@angular/core'; +import { DashboardRoutingModule } from './dashboard-routing.module'; +import { SharedModule } from '../../shared.module'; +import { + EntityUserAdministrationRowComponent, +} from './apps/user-last-action-tile/entity-user-administration-row/entity-user-administration-row.component'; +import { ActionButtonComponent } from './apps/user-last-action-tile/action-button/action-button.component'; +import { ActionRowComponent } from './apps/user-last-action-tile/action-row/action-row.component'; +import { UserLastActionTileComponent } from './apps/user-last-action-tile/user-last-action-tile.component'; +import { DashboardComponent } from './dashboard.component'; +import { DragDropModule } from '@angular/cdk/drag-drop'; + +@NgModule({ + declarations: [ + DashboardComponent, + UserLastActionTileComponent, + ActionRowComponent, + ActionButtonComponent, + EntityUserAdministrationRowComponent, + ], + imports: [DashboardRoutingModule, SharedModule, DragDropModule], +}) +export class DashboardModule {} diff --git a/src/app/modules/i18n/i18n.module.ts b/src/app/modules/i18n/i18n.module.ts new file mode 100644 index 0000000..52bedbe --- /dev/null +++ b/src/app/modules/i18n/i18n.module.ts @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { HttpClient, HttpClientModule } from '@angular/common/http'; +import { TranslateLoader, TranslateModule, TranslateService } from '@ngx-translate/core'; +import { TranslateHttpLoader } from '@ngx-translate/http-loader'; + +@NgModule({ + declarations: [], + imports: [ + CommonModule, + HttpClientModule, + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useFactory: translateLoaderFactory, + deps: [HttpClient], + }, + }), + ], + exports: [TranslateModule], +}) +export class I18nModule { + constructor(translate: TranslateService) { + translate.addLangs(['en', 'de']); + const browserLang = translate.getBrowserLang(); + translate.use(browserLang.match(/en|de/) ? browserLang : 'en'); + } +} + +export function translateLoaderFactory(httpClient: HttpClient) { + return new TranslateHttpLoader(httpClient, 'assets/i18n/', `.json?t=${new Date().getTime()}`); +} diff --git a/src/app/modules/user-administration/user-administration-form/user-administration-form.component.css b/src/app/modules/user-administration/user-administration-form/user-administration-form.component.css new file mode 100644 index 0000000..f056ef5 --- /dev/null +++ b/src/app/modules/user-administration/user-administration-form/user-administration-form.component.css @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +.custom-invalid-feedback { + width: 100%; + margin-top: 0.25rem; + font-size: 84%; + padding: 0.3rem 0.375rem; + color: var(--dark); + background-color: rgba(217, 0, 0, 0.1); + border-radius: 0.25rem; +} + +.custom-control-input:checked ~ .custom-control-label::before { + background-color: var(--primary); + border-color: #e20088; +} + +.custom-control-input:focus ~ .custom-control-label::before { + box-shadow: 0 0 0 0.2rem rgba(226, 0, 136, 0.25); + border-color: rgba(226, 0, 136, 0.25); +} diff --git a/src/app/modules/user-administration/user-administration-form/user-administration-form.component.html b/src/app/modules/user-administration/user-administration-form/user-administration-form.component.html new file mode 100644 index 0000000..66ede05 --- /dev/null +++ b/src/app/modules/user-administration/user-administration-form/user-administration-form.component.html @@ -0,0 +1,205 @@ +<!-- + ~ Copyright (c) 2022. Deutsche Telekom AG + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + ~ + ~ SPDX-License-Identifier: Apache-2.0 + --> + + +<app-breadcrumb> + <app-breadcrumb-item> + <a [routerLink]="['/dashboard']">{{ 'layout.menu.items.home' | translate }}</a> + </app-breadcrumb-item> + <app-breadcrumb-item> + <a [routerLink]="['/user-administration', 'list']">{{ 'userAdministration.list.title' | translate }}</a> + </app-breadcrumb-item> + <ng-container *ngIf="userId === null"> + <app-breadcrumb-item> + <span aria-current="page">{{ 'userAdministration.form.title.create' | translate }}</span> + </app-breadcrumb-item> + </ng-container> + <ng-container *ngIf="user"> + <app-breadcrumb-item> + <a [routerLink]="['/user-administration', user.id, 'detail']">{{ user.username }}</a> + </app-breadcrumb-item> + <app-breadcrumb-item> + <span aria-current="page">{{ 'userAdministration.form.title.edit' | translate }}</span> + </app-breadcrumb-item> + </ng-container> +</app-breadcrumb> + +<h2 class="py-2 qa_title"> + {{ (userId === null ? 'userAdministration.form.title.create' : 'userAdministration.form.title.edit') | translate }} +</h2> +<hr /> + +<div class="row"> + <!-- Set User Data--> + <div class="col-12 col-lg-6"> + <h4 class="text-monospace border-bottom text-secondary pb-2"> + {{ 'userAdministration.form.headings.setUserData' | translate }} + </h4> + <form class="mb-5" [formGroup]="keycloakUserForm" novalidate> + <div class="form-group row"> + <label class="col-xl-3 col-form-label" for="id">{{ 'userAdministration.fields.id' | translate }}</label> + <div class="col-xl-9"> + <input formControlName="id" class="form-control" id="id" readonly /> + </div> + </div> + <div class="form-group row"> + <label class="col-xl-3 col-form-label" for="username">{{ + 'userAdministration.fields.userName' | translate + }}</label> + <div class="col-xl-9"> + <input + formControlName="username" + class="form-control" + id="username" + [attr.readonly]="this.userId" + [class.is-invalid]="isFormControlInvalid(userName)" + required + aria-required="true" + /> + <div *ngIf="userName && userName?.errors?.required" class="invalid-feedback qa_required_user_name"> + {{ 'common.required' | translate }} + </div> + <div *ngIf="userName && userName?.errors?.pattern" class="invalid-feedback qa_invalid_user_name"> + {{ 'common.form.feedback.invalidCharacters' | translate }} + </div> + </div> + </div> + <div class="form-group row"> + <label class="col-xl-3 col-form-label" for="email">{{ 'userAdministration.fields.email' | translate }}</label> + <div class="col-xl-9"> + <input + formControlName="email" + type="email" + class="form-control" + id="email" + [class.is-invalid]="isFormControlInvalid(email)" + /> + <div *ngIf="email && email?.errors?.email" class="invalid-feedback qa_wrong_format_email"> + {{ 'common.form.feedback.emailWrongFormat' | translate }} + </div> + <div *ngIf="email && email?.errors?.pattern" class="invalid-feedback qa_invalid_email"> + {{ 'common.form.feedback.invalidCharacters' | translate }} + </div> + <div *ngIf="email && email?.errors?.required" class="invalid-feedback qa_required_email"> + {{ 'common.form.feedback.required' | translate }} + </div> + </div> + </div> + <div class="form-group row"> + <label class="col-xl-3 col-form-label" for="firstName">{{ + 'userAdministration.fields.firstName' | translate + }}</label> + <div class="col-xl-9"> + <input + formControlName="firstName" + class="form-control" + id="firstName" + [class.is-invalid]="isFormControlInvalid(firstName)" + /> + <div *ngIf="firstName && firstName?.errors?.pattern" class="invalid-feedback qa_invalid_first_name"> + {{ 'common.form.feedback.invalidCharacters' | translate }} + </div> + </div> + </div> + <div class="form-group row"> + <label class="col-xl-3 col-form-label" for="lastName">{{ + 'userAdministration.fields.lastName' | translate + }}</label> + <div class="col-xl-9"> + <input + formControlName="lastName" + class="form-control" + id="lastName" + [class.is-invalid]="isFormControlInvalid(lastName)" + /> + <div *ngIf="lastName && lastName?.errors?.pattern" class="invalid-feedback qa_invalid_last_name"> + {{ 'common.form.feedback.invalidCharacters' | translate }} + </div> + </div> + </div> + </form> + <!-- SET ROLES--> + <div class="mb-5" style="min-height: 150px"> + <h4 class="text-monospace border-bottom text-secondary pb-2"> + {{ 'userAdministration.form.headings.setRoles.title' | translate }} + </h4> + + <div class="form-row"> + <div class="col-xl-3 col-form-label">{{ 'userAdministration.form.headings.setRoles.title' | translate }}</div> + <div class="col-xl-9"> + <div class="row" style="padding: 0 15px"> + <div class="col-xl-5 p-3 border border-radius mb-md-2" style="min-height: 125px"> + <h5 class="qa_available_roles"> + {{ 'userAdministration.form.headings.setRoles.available' | translate }} + </h5> + <ng-container *ngFor="let checkbox of checkBoxes.available"> + <ng-container *ngIf="checkbox.name.startsWith('onap_')"> + <div class="form-check"> + <input + type="checkbox" + class="form-check-input qa_checkbox_available" + [attr.aria-labelledby]="checkbox.name" + [value]="checkbox.id" + (change)="onCheckboxChange(checkbox.id, true)" + /> + <label class="form-check-label" [attr.id]="checkbox.name">{{ checkbox.name }}</label> + </div> + </ng-container> + </ng-container> + </div> + <div class="col-xl-2"></div> + <div class="col-xl-5 p-3 border border-radius" style="min-height: 125px"> + <h5 class="qa_assigned_roles">{{ 'userAdministration.form.headings.setRoles.assigned' | translate }}</h5> + <ng-container *ngFor="let checkbox of checkBoxes.assigned"> + <ng-container *ngIf="checkbox.name.startsWith('onap_')"> + <div class="form-check"> + <input + type="checkbox" + class="form-check-input qa_checkbox_assigned" + [attr.aria-labelledby]="checkbox.name" + [value]="checkbox.id" + (change)="onCheckboxChange(checkbox.id, false)" + [checked]="true" + /> + <label class="form-check-label" [attr.id]="checkbox.name">{{ checkbox.name }}</label> + </div> + </ng-container> + </ng-container> + </div> + </div> + </div> + </div> + </div> + + <div class="float-right"> + <ng-container *ngIf="userId === null"> + <button class="btn btn-secondary qa_submit_cancel" [routerLink]="['../', 'list']"> + {{ 'common.buttons.cancel' | translate }} + </button> + </ng-container> + <ng-container *ngIf="userId !== null"> + <button class="btn btn-secondary qa_submit_cancel" [routerLink]="['../../list']"> + {{ 'common.buttons.cancel' | translate }} + </button> + </ng-container> + <button type="submit" class="btn btn-primary qa_submit_button ml-2" (click)="onSubmit()"> + {{ 'common.buttons.save' | translate }} + </button> + </div> + </div> +</div> diff --git a/src/app/modules/user-administration/user-administration-form/user-administration-form.component.spec.ts b/src/app/modules/user-administration/user-administration-form/user-administration-form.component.spec.ts new file mode 100644 index 0000000..def957f --- /dev/null +++ b/src/app/modules/user-administration/user-administration-form/user-administration-form.component.spec.ts @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { UserAdministrationFormComponent } from './user-administration-form.component'; + +describe('UserAdministrationFormComponent', () => { + let component: UserAdministrationFormComponent; + let fixture: ComponentFixture<UserAdministrationFormComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [UserAdministrationFormComponent], + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(UserAdministrationFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/modules/user-administration/user-administration-form/user-administration-form.component.ts b/src/app/modules/user-administration/user-administration-form/user-administration-form.component.ts new file mode 100644 index 0000000..7df2700 --- /dev/null +++ b/src/app/modules/user-administration/user-administration-form/user-administration-form.component.ts @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Component, OnInit } from '@angular/core'; +import { AbstractControl, FormControl, FormGroup, Validators } from '@angular/forms'; +import { + CreateUserRequest, + Role, + RoleListResponse, + RolesService, + UpdateUserRequest, + UserResponse, + UsersService, +} from 'openapi/output'; +import { AlertService } from 'src/app/modules/alerting'; +import { ActivatedRoute, Router } from '@angular/router'; +import { TranslateService } from '@ngx-translate/core'; +import { UnsubscribeService } from 'src/app/services/unsubscribe/unsubscribe.service'; +import { NON_WHITE_SPACE_PATTERN, VALIDATION_PATTERN } from 'src/app/model/validation-pattern.model'; +import { map, switchMap, take, takeUntil } from 'rxjs/operators'; +import { markAsDirtyAndValidate } from 'src/app/helpers/helpers'; +import { forkJoin, Observable, zip } from 'rxjs'; +import { ActionType, EntityType } from '../../../model/user-last-action.model'; +import { HistoryService } from '../../../services/history.service'; + +@Component({ + selector: 'app-user-administration-form', + templateUrl: './user-administration-form.component.html', + styleUrls: ['./user-administration-form.component.css'], + providers: [UnsubscribeService], +}) +export class UserAdministrationFormComponent implements OnInit { + public readonly userId: string | null; + public readonly keycloakUserForm: FormGroup; + public user: UserResponse | undefined = undefined; + + public checkBoxes: { + assigned: Role[]; + available: Role[]; + } = { + assigned: [], + available: [], + }; + + constructor( + private readonly alertService: AlertService, + private readonly route: ActivatedRoute, + private readonly userAdministrationService: UsersService, + private readonly rolesService: RolesService, + private readonly router: Router, + private readonly translateService: TranslateService, + private readonly unsubscribeService: UnsubscribeService, + private readonly historyService: HistoryService, + ) { + this.userId = this.route.snapshot.paramMap.get('userId'); + + this.keycloakUserForm = new FormGroup({ + id: new FormControl({ value: null, disabled: true }), + username: new FormControl({ value: null, disabled: this.userId !== null }, [ + Validators.required, + Validators.maxLength(50), + Validators.pattern(VALIDATION_PATTERN), + Validators.pattern(NON_WHITE_SPACE_PATTERN), + ]), + email: new FormControl(null, [Validators.email, Validators.required, Validators.pattern(VALIDATION_PATTERN)]), + firstName: new FormControl(null, [Validators.pattern(VALIDATION_PATTERN)]), + lastName: new FormControl(null, [Validators.pattern(VALIDATION_PATTERN)]), + }); + } + + ngOnInit(): void { + if (this.userId !== null) { + this.userAdministrationService + .getUser(this.userId) + .pipe(takeUntil(this.unsubscribeService.unsubscribe$)) + .subscribe(user => { + this.user = user; + this.keycloakUserForm.patchValue({ + id: user.id, + username: user.username, + email: user.email, + firstName: user.firstName, + lastName: user.lastName, + }); + }); + + zip( + this.userAdministrationService.listAvailableRoles(this.userId).pipe(map(available => available.items)), + this.userAdministrationService.listAssignedRoles(this.userId).pipe(map(assigned => assigned.items)), + ) + .pipe(takeUntil(this.unsubscribeService.unsubscribe$)) + .subscribe(([available, assigned]) => { + this.checkBoxes = { available, assigned }; + }); + } else { + this.rolesService + .listRoles() + .pipe( + takeUntil(this.unsubscribeService.unsubscribe$), + map(available => available.items), + ) + .subscribe(available => { + this.checkBoxes.available = available; + }); + } + } + + get userName(): FormControl { + return this.keycloakUserForm.get('username') as FormControl; + } + + get email(): FormControl { + return this.keycloakUserForm.get('email') as FormControl; + } + + get firstName(): FormControl { + return this.keycloakUserForm.get('firstName') as FormControl; + } + + get lastName(): FormControl { + return this.keycloakUserForm.get('lastName') as FormControl; + } + + public onSubmit(): void { + markAsDirtyAndValidate(this.keycloakUserForm); + if (this.keycloakUserForm.valid) { + const formValue = this.keycloakUserForm.getRawValue(); + if (this.userId === null) { + this.userAdministrationService + .createUser(this.createUserRequest(formValue)) + .pipe( + switchMap((data: UserResponse) => + this.historyService.createUserHistoryAction({ + type: ActionType.CREATE, + entity: EntityType.USERADMINISTRATION, + entityParams: { userName: data.username, userId: data.id }, + }), + ), + take(1), + ) + .subscribe(() => { + this.alertService.success(this.translateService.instant('userAdministration.messages.success.created'), { + keepAfterRouteChange: true, + autoClose: true, + }); + this.router.navigate(['../list'], { relativeTo: this.route }); + }); + } else { + this.updateUserData( + this.userAdministrationService.updateUser(this.userId, this.updateUserRequest(formValue)), + this.userAdministrationService.updateAssignedRoles(this.userId, undefined, this.checkBoxes.assigned), + ); + } + } + } + + public isFormControlInvalid(formControl: AbstractControl | null): boolean { + if (formControl !== null) { + return formControl && formControl?.invalid && (formControl?.dirty || formControl?.touched); + } + return false; + } + + public onCheckboxChange(roleId: string, checked: boolean): void { + if (checked) { + const checkedObj = { ...this.checkBoxes.available.find(({ id }) => id === roleId) } as Role; + this.checkBoxes.assigned.push(checkedObj); + this.checkBoxes.available = this.checkBoxes.available.filter(({ id }) => id !== roleId); + } else { + const uncheckedObj = { ...this.checkBoxes.assigned.find(({ id }) => id === roleId) } as Role; + this.checkBoxes.available.push(uncheckedObj); + this.checkBoxes.assigned = this.checkBoxes.assigned.filter(({ id }) => id !== roleId); + } + } + + private createUserRequest(formValue: any): CreateUserRequest { + return { + username: formValue.username, + email: formValue.email, + firstName: formValue.firstName, + lastName: formValue.lastName, + enabled: true, + roles: this.checkBoxes.assigned, + }; + } + + private updateUserRequest(formValue: any): UpdateUserRequest { + return { + email: formValue.email, + firstName: formValue.firstName, + lastName: formValue.lastName, + enabled: true, + }; + } + + private updateUserData(userResponse: Observable<UserResponse>, roleResponse: Observable<RoleListResponse>): void { + forkJoin([userResponse, roleResponse]) + .pipe( + switchMap(([,]) => + this.historyService.createUserHistoryAction({ + type: ActionType.EDIT, + entity: EntityType.USERADMINISTRATION, + entityParams: { userName: this.user!.username, userId: this.user!.id }, + }), + ), + take(1), + ) + .subscribe(() => { + this.alertService.success(this.translateService.instant('userAdministration.messages.success.updated'), { + keepAfterRouteChange: true, + autoClose: true, + }); + this.router.navigate(['../../list'], { relativeTo: this.route }); + }); + } +} diff --git a/src/app/modules/user-administration/user-administration-list/user-administration-list.component.css b/src/app/modules/user-administration/user-administration-list/user-administration-list.component.css new file mode 100644 index 0000000..b8d5a0e --- /dev/null +++ b/src/app/modules/user-administration/user-administration-list/user-administration-list.component.css @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +.btn-outline-secondary { + color: var(--dark-gray) !important; + border-color: var(--dark-gray) !important; +} +.btn-outline-secondary:hover { + color: var(--light-gray) !important; + background-color: var(--dark-gray) !important; + border-color: var(--dark-gray) !important; +} diff --git a/src/app/modules/user-administration/user-administration-list/user-administration-list.component.html b/src/app/modules/user-administration/user-administration-list/user-administration-list.component.html new file mode 100644 index 0000000..d205ee2 --- /dev/null +++ b/src/app/modules/user-administration/user-administration-list/user-administration-list.component.html @@ -0,0 +1,159 @@ +<!-- + ~ Copyright (c) 2022. Deutsche Telekom AG + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + ~ + ~ SPDX-License-Identifier: Apache-2.0 + --> + + +<ng-container + *ngIf=" + { + users: result$ | async, + page: page$ | async, + pageSize: pageSize$ | async + } as vm; + else loading + " +> + <app-breadcrumb> + <app-breadcrumb-item> + <a [routerLink]="['/dashboard']">{{ 'layout.menu.items.home' | translate }}</a> + </app-breadcrumb-item> + <app-breadcrumb-item> + <span aria-current="page">{{ 'userAdministration.list.title' | translate }}</span> + </app-breadcrumb-item> + </app-breadcrumb> + <h2>{{ 'userAdministration.list.title' | translate }}</h2> + <hr /> + <div class="d-flex justify-content-between"> + <button + class="btn btn-primary qa_create_button ml-auto" + [appHasPermissions]="'users.administration.create'" + type="button" + [routerLink]="['../', 'create']" + > + {{ 'userAdministration.buttons.createUser' | translate }} + </button> + </div> + + <div class="row"> + <div class="col"> + <div class="table-responsive"> + <table class="table table-sm table-striped"> + <caption> + {{ + 'userAdministration.list.tableCaption' | translate + }} + </caption> + <thead> + <tr> + <th class="qa_user_name_header" scope="col">{{ 'userAdministration.fields.userName' | translate }}</th> + <th class="qa_first_name_header" scope="col">{{ 'userAdministration.fields.firstName' | translate }}</th> + <th class="qa_last_name_header" scope="col">{{ 'userAdministration.fields.lastName' | translate }}</th> + <th class="qa_email_header" scope="col">{{ 'userAdministration.fields.email' | translate }}</th> + <th class="qa_assigned_roles_header" scope="col"> + {{ 'userAdministration.fields.assignedRoles' | translate }} + </th> + <th class="qa_actions_header" scope="col" style="width: 11%"> + {{ 'userAdministration.fields.actions' | translate }} + </th> + </tr> + </thead> + <tbody> + <ng-container *ngIf="vm.users as users"> + <tr *ngFor="let user of users.items"> + <td>{{ user.username }}</td> + <td>{{ user.firstName }}</td> + <td>{{ user.lastName }}</td> + <td> + <a [href]="'mailto:' + user.email">{{ user.email }}</a> + </td> + <td> + <ng-container *ngFor="let role of user.realmRoles; let last = last"> + <span>{{ role }}<span *ngIf="!last">, </span> </span> + </ng-container> + </td> + <td> + <div class="d-flex" *ngIf="loggedUserId$ | async as userId"> + <ng-container *ngIf="userId === user.id; else elseBlock"> + <span + class="d-inline-block" + tabindex="0" + placement="top" + container="body" + [ngbTooltip]="'common.buttons.notPossibleDelete' | translate" + > + <button + class="btn btn-sm btn-outline-danger qa_delete_button mr-2" + type="button" + [appHasPermissions]="'users.administration.delete'" + [attr.aria-label]="'common.buttons.delete' | translate" + disabled + > + <i class="bi bi-trash" aria-hidden="true"></i> + </button> + </span> + </ng-container> + <ng-template #elseBlock> + <button + class="btn btn-sm btn-outline-danger qa_delete_button mr-2" + type="button" + placement="top" + container="body" + [appHasPermissions]="'users.administration.delete'" + [ngbTooltip]="'common.buttons.delete' | translate" + [attr.aria-label]="'common.buttons.delete' | translate" + (click)="openModal(user.id, user.username)" + > + <i class="bi bi-trash" aria-hidden="true"></i> + </button> + </ng-template> + + <button + class="btn btn-sm btn-outline-secondary qa_edit_button" + type="button" + placement="top" + container="body" + [appHasPermissions]="'users.administration.edit'" + [ngbTooltip]="'common.buttons.edit' | translate" + [routerLink]="['../', user.id, 'edit']" + [attr.aria-label]="'common.buttons.edit' | translate" + > + <i class="bi bi-pencil" aria-hidden="true"></i> + </button> + </div> + </td> + </tr> + </ng-container> + </tbody> + </table> + </div> + + <app-pagination + *ngIf="vm.users && vm.users.totalCount > 10" + [collectionSize]="vm.users.totalCount || 0" + [page]="vm.page || 1" + [pageSize]="vm.pageSize || 10" + (pageChange)="changePage($event)" + (pageSizeChange)="changePageSize($event)" + > + </app-pagination> + </div> + </div> +</ng-container> + +<ng-template #loading> + <app-table-skeleton></app-table-skeleton> +</ng-template> diff --git a/src/app/modules/user-administration/user-administration-list/user-administration-list.component.spec.ts b/src/app/modules/user-administration/user-administration-list/user-administration-list.component.spec.ts new file mode 100644 index 0000000..db24b11 --- /dev/null +++ b/src/app/modules/user-administration/user-administration-list/user-administration-list.component.spec.ts @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { UserAdministrationListComponent } from './user-administration-list.component'; + +describe('UserAdministrationComponent', () => { + let component: UserAdministrationListComponent; + let fixture: ComponentFixture<UserAdministrationListComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [UserAdministrationListComponent], + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(UserAdministrationListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/modules/user-administration/user-administration-list/user-administration-list.component.ts b/src/app/modules/user-administration/user-administration-list/user-administration-list.component.ts new file mode 100644 index 0000000..30637a1 --- /dev/null +++ b/src/app/modules/user-administration/user-administration-list/user-administration-list.component.ts @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Component } from '@angular/core'; +import { map, repeatWhen, shareReplay, switchMap, takeUntil, tap } from 'rxjs/operators'; +import { AlertService } from 'src/app/modules/alerting'; +import { TranslateService } from '@ngx-translate/core'; +import { UnsubscribeService } from 'src/app/services/unsubscribe/unsubscribe.service'; +import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { ConfirmationModalComponent } from 'src/app/components/shared/confirmation-modal/confirmation-modal.component'; +import { BehaviorSubject, combineLatest, EMPTY, Subject } from 'rxjs'; +import { UsersService } from 'openapi/output'; +import { ActionType, EntityType } from '../../../model/user-last-action.model'; +import { HistoryService } from '../../../services/history.service'; +import { AuthService } from '../../../services/auth.service'; + +@Component({ + selector: 'app-user-administration-list', + templateUrl: './user-administration-list.component.html', + styleUrls: ['./user-administration-list.component.css'], + providers: [UnsubscribeService], +}) +export class UserAdministrationListComponent { + readonly page$ = new BehaviorSubject<number>(1); + readonly pageSize$ = new BehaviorSubject<number>(10); + readonly loggedUserId$ = this.authService.loadCachedUserProfile().pipe( + takeUntil(this.unsubscribeService.unsubscribe$), + map(userInfo => userInfo!.sub)); + + private readonly reload$ = new Subject<void>(); + readonly result$ = combineLatest([this.page$, this.pageSize$]).pipe( + switchMap(([page, pageSize]) => { + return this.userAdministrationService.listUsers(page, pageSize).pipe( + map(response => { + return { + ...response, + items: response.items.map(user => ({ + ...user, + realmRoles: user.realmRoles?.filter(role => role.startsWith('onap_')), + })), + }; + }), + repeatWhen(() => this.reload$), + ); + }), + shareReplay({ refCount: true, bufferSize: 1 }), + ); + + constructor( + private readonly userAdministrationService: UsersService, + private readonly alertService: AlertService, + private readonly translateService: TranslateService, + private readonly modalService: NgbModal, + private readonly unsubscribeService: UnsubscribeService, + private readonly authService: AuthService, + private readonly historyService: HistoryService, + ) { + } + + changePage(page: number): void { + this.page$.next(page); + } + + changePageSize(pageSize: number): void { + this.pageSize$.next(pageSize); + } + + openModal(userId: string, userName: string): void { + // open confirmation modal for user deletion + const modalRef = this.modalService.open(ConfirmationModalComponent,{backdropClass:'backdropClass'}); + modalRef.componentInstance.okText = this.translateService.instant('common.buttons.delete'); + modalRef.componentInstance.title = this.translateService.instant('userAdministration.list.modal.delete.title'); + modalRef.componentInstance.text = this.translateService.instant('userAdministration.list.modal.delete.text', { + userName, + }); + modalRef.closed + .pipe( + takeUntil(this.unsubscribeService.unsubscribe$), + switchMap((confirm: boolean) => { + if (confirm) { + return this.userAdministrationService.deleteUser(userId).pipe( + switchMap(() => + this.historyService.createUserHistoryAction({ + type: ActionType.DELETE, + entity: EntityType.USERADMINISTRATION, + entityParams: { userName, userId }, + }), + ), + ); + } + return EMPTY; + }), + tap(() => { + this.alertService.success(this.translateService.instant('userAdministration.messages.success.deleted'), { + keepAfterRouteChange: true, + autoClose: true, + }); + }), + ) + .subscribe(() => this.reload$.next()); + } +} diff --git a/src/app/modules/user-administration/user-administration-routing.module.ts b/src/app/modules/user-administration/user-administration-routing.module.ts new file mode 100644 index 0000000..7d1a8db --- /dev/null +++ b/src/app/modules/user-administration/user-administration-routing.module.ts @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; +import { UserAdministrationListComponent } from './user-administration-list/user-administration-list.component'; +import { AuthGuard } from '../../guards/auth.guard'; +import { HasPermissionsGuard } from '../../guards/has-permissions.guard'; +import { UserAdministrationFormComponent } from './user-administration-form/user-administration-form.component'; +import { EditUserCanActivateGuard } from '../../guards/edit-user.can-activate.guard'; + +const routes: Routes = [ + { path: '', redirectTo: 'list', pathMatch: 'full' }, + { + path: 'list', + component: UserAdministrationListComponent, + canActivate: [AuthGuard, HasPermissionsGuard], + data: { permission: 'users.administration.list' }, + }, + { + path: 'create', + component: UserAdministrationFormComponent, + canActivate: [AuthGuard, HasPermissionsGuard], + data: { permission: 'users.administration.create' }, + }, + { + path: ':userId/edit', + component: UserAdministrationFormComponent, + canActivate: [AuthGuard, HasPermissionsGuard, EditUserCanActivateGuard], + data: { permission: 'users.administration.edit' }, + }, +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule], +}) +export class UserAdministrationRoutingModule {} diff --git a/src/app/modules/user-administration/user-administration.module.ts b/src/app/modules/user-administration/user-administration.module.ts new file mode 100644 index 0000000..799d405 --- /dev/null +++ b/src/app/modules/user-administration/user-administration.module.ts @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { NgModule } from '@angular/core'; +import { UserAdministrationListComponent } from './user-administration-list/user-administration-list.component'; +import { UserAdministrationFormComponent } from './user-administration-form/user-administration-form.component'; +import { UserAdministrationRoutingModule } from './user-administration-routing.module'; +import { SharedModule } from '../../shared.module'; + +@NgModule({ + declarations: [UserAdministrationListComponent, UserAdministrationFormComponent], + imports: [UserAdministrationRoutingModule, SharedModule], +}) +export class UserAdministrationModule {} diff --git a/src/app/package.json b/src/app/package.json new file mode 100644 index 0000000..1706abd --- /dev/null +++ b/src/app/package.json @@ -0,0 +1,6 @@ +{
+ "name": "frontend",
+ "private": true,
+ "description": "This is a special package.json file that is not used by package managers. It is however used to tell the tools and bundlers whether the code under this directory is free of code with non-local side-effect. Any code that does have non-local side-effects can't be well optimized (tree-shaken) and will result in unnecessary increased payload size. It should be safe to set this option to 'false' for new applications, but existing code bases could be broken when built with the production config if the application code does contain non-local side-effects that the application depends on.",
+ "sideEffects": false
+}
diff --git a/src/app/pipes/colon.pipe.ts b/src/app/pipes/colon.pipe.ts new file mode 100644 index 0000000..fe0b50b --- /dev/null +++ b/src/app/pipes/colon.pipe.ts @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Pipe, PipeTransform } from '@angular/core'; + +@Pipe({ + name: 'colon', +}) +export class ColonPipe implements PipeTransform { + transform(value: string): string { + return `${value}: `; + } +} diff --git a/src/app/pipes/guard-type.pipe.ts b/src/app/pipes/guard-type.pipe.ts new file mode 100644 index 0000000..0c2b847 --- /dev/null +++ b/src/app/pipes/guard-type.pipe.ts @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Pipe, PipeTransform } from '@angular/core'; + +export type TypeGuard<A, B extends A> = (a: A) => a is B; + +// https://github.com/angular/angular/issues/34522#issuecomment-762973301 +@Pipe({ + name: 'guardType', +}) +export class GuardTypePipe implements PipeTransform { + transform<A, B extends A>(value: A, typeGuard: TypeGuard<A, B>): B | undefined { + return typeGuard(value) ? value : undefined; + } +} diff --git a/src/app/pipes/has-permission.pipe.ts b/src/app/pipes/has-permission.pipe.ts new file mode 100644 index 0000000..a22b034 --- /dev/null +++ b/src/app/pipes/has-permission.pipe.ts @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Inject, Pipe, PipeTransform } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { ACL_CONFIG, AclConfig } from '../modules/auth/injection-tokens'; +import { AuthService } from '../services/auth.service'; +import { Observable } from 'rxjs'; +import { map, take } from 'rxjs/operators'; + +/* + hasPermission pipe returns Promise<boolean | void> value based on the authentication file (acl.json) and user's role. + Using the pipe we are able to show/hide the elements in the app for specific user role. + Input parameter is the string from the acl.json + USAGE: *ngIf="'dashboard.tile.KPI_DASHBOARD_TILE' | hasPermission | async" +*/ +@Pipe({ + name: 'hasPermission', +}) +export class HasPermissionPipe implements PipeTransform { + constructor( + readonly httpClient: HttpClient, + readonly authService: AuthService, + @Inject(ACL_CONFIG) readonly acl: AclConfig, + ) {} + + transform(value: string): Observable<boolean | void> { + return this.authService + .loadCachedUserProfile() + .pipe( + take(1), + map((userProfile) => { + const intersectionOfRoles = Object.keys(this.acl).filter(role => userProfile?.roles.includes(role)); + for (const role of intersectionOfRoles) { + if (this.acl[role].includes(value)) { + return true; + } + } + return false; + })) + } +} diff --git a/src/app/pipes/in.pipe.ts b/src/app/pipes/in.pipe.ts new file mode 100644 index 0000000..df6e8cc --- /dev/null +++ b/src/app/pipes/in.pipe.ts @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Pipe, PipeTransform } from '@angular/core'; + +@Pipe({ + name: 'in', +}) +export class InPipe implements PipeTransform { + transform(value: string, array: string[] | Set<any>): boolean { + if (array instanceof Array) { + return array.includes(value); + } + if (array instanceof Set) { + return array.has(value); + } else { + throw new Error('unsupported type'); + } + } +} diff --git a/src/app/pipes/is-today.pipe.ts b/src/app/pipes/is-today.pipe.ts new file mode 100644 index 0000000..1d2f17a --- /dev/null +++ b/src/app/pipes/is-today.pipe.ts @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Pipe, PipeTransform } from '@angular/core'; + +// return true if given parameter is today else return false + +@Pipe({ + name: 'isToday', +}) +export class IsTodayPipe implements PipeTransform { + transform(value: string | Date | number): boolean { + const date = new Date(value); + const today = new Date(); + return ( + date.getDate() == today.getDate() && + date.getMonth() == today.getMonth() && + date.getFullYear() == today.getFullYear() + ); + } +} diff --git a/src/app/pipes/map.pipe.ts b/src/app/pipes/map.pipe.ts new file mode 100644 index 0000000..e2c88a9 --- /dev/null +++ b/src/app/pipes/map.pipe.ts @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Pipe, PipeTransform } from '@angular/core'; + +@Pipe({ + name: 'map', + pure: false +}) +/* + MapPipe allows us to run a function in a template + for example, you need to filter out some elements from the array before displaying these elements. You can call a function for getting filtered array + directly from template, but this function will be triggered everytime when user interacts with page. + MapPipe allows you to call a function through this pipe, so function will be called only when necessary. + Usage: + we have function in .ts file that's called filterZeroValues + in template we can use this function: + *ngFor="let item in elements | map : filterZeroValues" + where the first parameter of map pipe is function to be called, and other parameters will be passed as arguments to this function + Important note: as you can see from implementation, elements array will be passed to your function as a first argument +*/ +export class MapPipe implements PipeTransform { + + transform<T, R>( + thisArg: T, + project: (t:T, ...others: any[]) => R, + ...args: any[] + ): R { + return project(thisArg, ...args); + } + +} diff --git a/src/app/pipes/translate-mock.pipe.ts b/src/app/pipes/translate-mock.pipe.ts new file mode 100644 index 0000000..80c68a7 --- /dev/null +++ b/src/app/pipes/translate-mock.pipe.ts @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Pipe, PipeTransform } from "@angular/core"; +/** + * This class can be used to mock the `translate` pipe in jasmine test cases. + * + * Usage: + * ``` typescript + * TestBed.configureTestingModule({ + declarations: [TranslatePipeMock,...], + providers: [{ provide: TranslatePipe, useClass: TranslatePipeMock },...] +}).compileComponents(); +* ``` +*/ +// Courtesy of: https://github.com/ngx-translate/core/issues/636#issuecomment-451137902 +@Pipe({ + name: 'translate' +}) +export class TranslatePipeMock implements PipeTransform { + public name = 'translate'; + + public transform(query: string): any { + return query; + } +} diff --git a/src/app/router.strategy.ts b/src/app/router.strategy.ts new file mode 100644 index 0000000..c80682e --- /dev/null +++ b/src/app/router.strategy.ts @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import {ActivatedRouteSnapshot, DetachedRouteHandle, BaseRouteReuseStrategy} from '@angular/router'; + +export class AppRouteReuseStrategy implements BaseRouteReuseStrategy { + public shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean { + if(future.data.reuseComponent) { + return false + } + return (future.routeConfig === curr.routeConfig); + } + + retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle | null { + return true; + } + + shouldAttach(route: ActivatedRouteSnapshot): boolean { + return false; + } + + shouldDetach(route: ActivatedRouteSnapshot): boolean { + return false; + } + + store(route: ActivatedRouteSnapshot, detachedTree: DetachedRouteHandle): void; + store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle | null): void; + store(route: ActivatedRouteSnapshot, detachedTree: DetachedRouteHandle | null): void { + //this is intentional + } + +} diff --git a/src/app/services/auth.service.ts b/src/app/services/auth.service.ts new file mode 100644 index 0000000..8988196 --- /dev/null +++ b/src/app/services/auth.service.ts @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Injectable } from '@angular/core'; +import { OAuthService, UserInfo } from 'angular-oauth2-oidc'; +import { catchError, filter, map } from 'rxjs/operators'; +import { NavigationStart, Router } from '@angular/router'; +import { AlertService } from '../modules/alerting'; +import { TranslateService } from '@ngx-translate/core'; +import { BehaviorSubject, EMPTY, Observable, of } from 'rxjs'; + +/** + * Provides check for roles and token + */ +@Injectable({ + providedIn: 'root', +}) +export class AuthService { + userProfile$ = new BehaviorSubject<UserInfo | undefined>(undefined); + constructor(private readonly oauthService: OAuthService, private router: Router, private alertService: AlertService, private translateService: TranslateService) { + //renew cache every page reload + router.events.pipe( + filter((e): e is NavigationStart => e instanceof NavigationStart) + ).subscribe(() => { + try { + return this.loadUserProfile().then(userInfo => this.userProfile$.next(userInfo)).catch(e => {throw e}) + }catch (e) { + this.alertService.error(this.translateService.instant('common.messages.keycloakAccessTokenNotValid'), {id: "keycloak", keepAfterRouteChange: true}) + return Promise.resolve(null); + } + }); + } + + userProfileCache: UserInfo | undefined = undefined; + + /** + * Convenience method of `hasValidAccessToken()` and `hasSufficientRoles()` + * Asynchronous because the needed UserInfo is fetched from Keycloak + */ + hasPermissions(): Observable<boolean> { + if (this.hasValidAccessToken()) { + return this.hasSufficientRoles(); + } + return of(false); + } + + /** + * This answers: 'What if the user has an account, but without any permissions?' + * Asynchronous because the needed UserInfo is fetched from Keycloak + */ + hasSufficientRoles(): Observable<boolean> { + return this.loadCachedUserProfile().pipe(map(info => info?.roles.join(',') !== 'offline_access')); + } + + loadCachedUserProfile(): Observable<UserInfo | undefined> { + return this.userProfile$.pipe( + filter(userProfile => userProfile !== undefined), + catchError(err => { + console.error(err); + return EMPTY + })); + } + + /** + * Wrapper for `hasValidAccessToken` from OAuthService + */ + hasValidAccessToken(): boolean { + return this.oauthService.hasValidAccessToken(); + } + /* + * Private method = should not be used outside of this class, because it triggers additional request for userprofile + * */ + private loadUserProfile():Promise<UserInfo> { + // in version 12.2 loadUserProfile() Promise returns data of type object instead of UserInfo + //@ts-ignore + return this.oauthService.loadUserProfile().then(userInfo => userInfo.info as UserInfo) + } +} diff --git a/src/app/services/authconfig.service.ts b/src/app/services/authconfig.service.ts new file mode 100644 index 0000000..5ced9a1 --- /dev/null +++ b/src/app/services/authconfig.service.ts @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Injectable } from '@angular/core'; +import { AuthConfig, NullValidationHandler, OAuthService } from 'angular-oauth2-oidc'; + +@Injectable() +export class AuthConfigService { + constructor(private readonly oauthService: OAuthService, private readonly authConfig: AuthConfig) {} + + async initAuth(): Promise<any> { + return new Promise<void>((resolveFn, rejectFn) => { + // setup oauthService + this.oauthService.configure(this.authConfig); + this.oauthService.tokenValidationHandler = new NullValidationHandler(); + + this.oauthService.loadDiscoveryDocumentAndLogin().then(isLoggedIn => { + if (isLoggedIn) { + this.oauthService.setupAutomaticSilentRefresh(); + resolveFn(); + } else { + this.oauthService.initImplicitFlow(); + rejectFn(); + } + }).catch(() => { + //@ts-ignore + window.location.href = './keycloak-error.html' + }); + }); + } +} diff --git a/src/app/services/cacheservice/request-cache.service.spec.ts b/src/app/services/cacheservice/request-cache.service.spec.ts new file mode 100644 index 0000000..c9f931e --- /dev/null +++ b/src/app/services/cacheservice/request-cache.service.spec.ts @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { TestBed } from '@angular/core/testing'; + +import { RequestCacheService } from './request-cache.service'; + +describe('RequestCacheService', () => { + let service: RequestCacheService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(RequestCacheService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/services/cacheservice/request-cache.service.ts b/src/app/services/cacheservice/request-cache.service.ts new file mode 100644 index 0000000..3d2047f --- /dev/null +++ b/src/app/services/cacheservice/request-cache.service.ts @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { HttpRequest, HttpResponse } from '@angular/common/http'; +import { Injectable } from '@angular/core'; + +const maxAge = 60000; + +@Injectable({ + providedIn: 'root', +}) +// https://github.com/angular/angular/blob/master/aio/content/examples/http/src/app/request-cache.service.ts +export class RequestCacheService implements RequestCache { + // The cache is a Map of (most importantly but not exclusively) HttpResponses + cache = new Map<string, RequestCacheEntry>(); + + /** + * Get an http request from cache + * @param request the http request that should be retrieved from cache + */ + get(request: HttpRequest<any>): HttpResponse<any> | undefined { + const requestUrl = request.urlWithParams; + const cachedResponse = this.cache.get(requestUrl); + + if (!cachedResponse) { + return undefined; + } + + const isExpired = cachedResponse.lastRead < Date.now() - maxAge; + + + return isExpired ? undefined : cachedResponse.response; + } + + /** + * Put a http response for a given request url (taken from the request object) in the cache + * @param request the http request that should be associated with the http response + * @param response the http response that should be stored in cache + */ + put(request: HttpRequest<any>, response: HttpResponse<any>): void { + const requestUrl = request.urlWithParams; + + // Map a request url to an object + const newEntry = { requestUrl, response, lastRead: Date.now() }; + this.cache.set(requestUrl, newEntry); + + // Remove expired entries from the cache + const expired = Date.now() - maxAge; + this.cache.forEach(entry => { + if (entry.lastRead < expired) { + this.cache.delete(entry.requestUrl); + } + }); + } +} + +/** + * Service that manages the cache. + * `get()` HttpResponses from cache and `put()` responses into the cache + */ +export abstract class RequestCache { + abstract get(request: HttpRequest<any>): HttpResponse<any> | undefined; + abstract put(request: HttpRequest<any>, response: HttpResponse<any>): void; +} + +/** + * Wrapper Object that stores the HttpResponse together with the `requestUrl` of the request and the `lastRead` time it was cached + */ +export interface RequestCacheEntry { + requestUrl: string; + response: HttpResponse<any>; + lastRead: number; +} diff --git a/src/app/services/fullscreen.service.ts b/src/app/services/fullscreen.service.ts new file mode 100644 index 0000000..91ceec9 --- /dev/null +++ b/src/app/services/fullscreen.service.ts @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Injectable } from '@angular/core'; + +@Injectable({ + providedIn: 'root', +}) +export class FullscreenService { + private doc = <FullScreenDocument>document; + + enter() { + const el = this.doc.documentElement; + if (el.requestFullscreen) el.requestFullscreen(); + else if (el.msRequestFullscreen) el.msRequestFullscreen(); + else if (el.mozRequestFullScreen) el.mozRequestFullScreen(); + else if (el.webkitRequestFullscreen) el.webkitRequestFullscreen(); + } + + leave() { + if (this.doc.exitFullscreen) this.doc.exitFullscreen(); + else if (this.doc.msExitFullscreen) this.doc.msExitFullscreen(); + else if (this.doc.mozCancelFullScreen) this.doc.mozCancelFullScreen(); + else if (this.doc.webkitExitFullscreen) this.doc.webkitExitFullscreen(); + } +} + +interface FullScreenDocument extends HTMLDocument { + documentElement: FullScreenDocumentElement; + mozFullScreenElement?: Element; + msFullscreenElement?: Element; + webkitFullscreenElement?: Element; + msExitFullscreen?: () => void; + mozCancelFullScreen?: () => void; + webkitExitFullscreen?: () => void; +} + +interface FullScreenDocumentElement extends HTMLElement { + msRequestFullscreen?: () => void; + mozRequestFullScreen?: () => void; + webkitRequestFullscreen?: () => void; +} diff --git a/src/app/services/history.service.ts b/src/app/services/history.service.ts new file mode 100644 index 0000000..2924f39 --- /dev/null +++ b/src/app/services/history.service.ts @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Injectable } from '@angular/core'; +import { + ActionType, + CreateActionModel, + EntityType, + EntityUserHistoryActionModel, +} from '../model/user-last-action.model'; +import { ActionsListResponse, ActionsResponse, ActionsService } from '../../../openapi/output'; +import { OAuthService } from 'angular-oauth2-oidc'; +import { Observable } from 'rxjs'; + +@Injectable({ + providedIn: 'root', +}) +export class HistoryService { + constructor(private readonly actionService: ActionsService, private readonly oauthService: OAuthService) {} + + public getUserActions(interval: number | undefined): Observable<ActionsListResponse> { + const userId = Object(this.oauthService.getIdentityClaims()).sub; + return this.actionService.getActions(userId, 1, 1000, interval); + } + + public createUserHistoryAction(action: CreateActionModel<EntityUserHistoryActionModel>): Observable<ActionsResponse> { + let mappedAction = { + type: action.type, + entity: action.entity, + entityParams: { + userName: action.entityParams.userName, + userId: action.entityParams.userId, + }, + }; + return this.createAction(mappedAction); + } + + private createAction(action: { + type: ActionType; + entity: EntityType; + entityParams: { [key: string]: string | undefined}; + }): Observable<ActionsResponse> { + const userId = Object(this.oauthService.getIdentityClaims()).sub; + const actionCreatedAt = new Date().toISOString(); + return this.actionService.createAction(userId, undefined, { + userId, + actionCreatedAt, + action, + }); + } +} diff --git a/src/app/services/loading-indicator.service.ts b/src/app/services/loading-indicator.service.ts new file mode 100644 index 0000000..727edd4 --- /dev/null +++ b/src/app/services/loading-indicator.service.ts @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Injectable } from '@angular/core'; +import { BehaviorSubject, Observable } from 'rxjs'; +import { debounceTime } from 'rxjs/operators'; + +@Injectable() +export class LoadingIndicatorService { + private isVisible$ = new BehaviorSubject<boolean>(false); + private timeDelay = 500; + private counter = 0; + + show(): void { + this.counter++; + if (this.counter > 0) { + setTimeout(() => this.isVisible$.next(true), 0); + } + } + + hide(): void { + this.counter--; + if (this.counter === 0) { + setTimeout(() => this.isVisible$.next(false), 0); + } + } + + isVisible(): Observable<boolean> { + return this.isVisible$.pipe(debounceTime(this.timeDelay)); + } +} diff --git a/src/app/services/logging.service.ts b/src/app/services/logging.service.ts new file mode 100644 index 0000000..5250fda --- /dev/null +++ b/src/app/services/logging.service.ts @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { Observable } from 'rxjs'; +import { environment } from '../../environments/environment'; + +@Injectable({ + providedIn: 'root', +}) +export class LoggingService { + constructor(private readonly httpClient: HttpClient) {} + + writeLog(message: string): Observable<string> { + return this.httpClient.post(environment.loggingUrl, message, { responseType: 'text' }); + } +} diff --git a/src/app/services/shortcut.service.ts b/src/app/services/shortcut.service.ts new file mode 100644 index 0000000..750ab5b --- /dev/null +++ b/src/app/services/shortcut.service.ts @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +import { Injectable } from '@angular/core'; +import { TranslateService } from '@ngx-translate/core'; + +export enum KeyboardShortcuts { + SHORTCUT_0 = '0', + SHORTCUT_1 = '1', + SHORTCUT_2 = '2', + SHORTCUT_4 = '4', + SHORTCUT_6 = '6', +} + +@Injectable({ + providedIn: 'root' +}) + +export class ShortcutService { + + private shortcuts = new Map<KeyboardShortcuts, string>([ + [KeyboardShortcuts.SHORTCUT_0, this.translateService.instant('layout.header.shortcuts.details')], + [KeyboardShortcuts.SHORTCUT_1, this.translateService.instant('layout.header.shortcuts.home')], + [KeyboardShortcuts.SHORTCUT_2, this.translateService.instant('layout.header.shortcuts.main')], + [KeyboardShortcuts.SHORTCUT_4, this.translateService.instant('layout.header.shortcuts.search')], + [KeyboardShortcuts.SHORTCUT_6, this.translateService.instant('layout.header.shortcuts.menu')], + ]); + + constructor(private translateService: TranslateService) { } + + public getShortcuts(): Map<KeyboardShortcuts,string> { + return this.shortcuts; + } +} diff --git a/src/app/services/tileservice/tiles.service.spec.ts b/src/app/services/tileservice/tiles.service.spec.ts new file mode 100644 index 0000000..f7f4369 --- /dev/null +++ b/src/app/services/tileservice/tiles.service.spec.ts @@ -0,0 +1,488 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { TestBed, waitForAsync } from '@angular/core/testing'; +import { Tile } from '../../model/tile'; +import { TilesService } from './tiles.service'; +import { HttpErrorResponse } from '@angular/common/http'; +import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; +import { environment } from '../../../environments/environment'; +import { OAuthLogger, OAuthService, UrlHelperService } from 'angular-oauth2-oidc'; + +// https://dev.to/coly010/unit-testing-angular-services-1anm + +/** + * describe sets up the Test Suite for the TileService + */ +describe('TilesService', () => { + /** + * let service declares a Test Suite-scoped variable where we will store a reference to our service + */ + let service: TilesService; + let mockTile: Tile; + let httpmock: HttpTestingController; + let errmsg: string; + + const backendServerUrlTest = environment.backendServerUrl + '/tiles'; + /** + * beforeEach tells the test runner to run this code before every test in the Test Suite + * It is using Angular's TestBed to create the testing environment. Finally it is injecting the TilesService + * and placing a reference to it in the service variable defined earlier. + */ + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [HttpClientTestingModule], + providers: [TilesService, OAuthService, UrlHelperService, OAuthLogger], + }); + service = TestBed.inject(TilesService); + httpmock = TestBed.inject(HttpTestingController); + mockTile = { + id: 1, + title: 'NewTile1', + description: 'New Tile for frontend test', + imageUrl: 'https://www.onap.org/wp-content/uploads/sites/20/2017/02/logo_onap_2017.png', + imageAltText: 'Onap Image', + redirectUrl: 'www.onap.org', + headers: 'This is a header', + groups: [], + roles: [], + }; + // responseTile = { + // id: 2, + // title: 'NewTile1', + // description: 'New Tile for frontend test', + // imageUrl: 'https://www.onap.org/wp-content/uploads/sites/20/2017/02/logo_onap_2017.png', + // imageAltText: 'Onap Image', + // redirectUrl: 'www.onap.org', + // headers: 'This is a header', + // groups: [], + // roles: [], + // }; + }); + + /** + * After every test, assert that there are no more pending requests. + */ + afterEach(() => { + httpmock.verify(); + }); + + /** + * the it() function creates a new test with the title 'should be created' + * This test is expecting the service varibale to truthy, in otherwords, + * it should have been instantiated correctly by the Angular TestBed. + */ + it('should be created', () => { + expect(service).toBeTruthy(); + }); + + /** + * TileService method tests begin + * Testing getTiles + */ + describe('#getTiles', () => { + // let expectedTiles: Tile[]; + + beforeEach(() => { + // expectedTiles = [mockTile, responseTile]; + }); + + /** + * testing method getTiles() to get all existing tiles + */ + /* + it('should return expected tiles (called once)', (done: DoneFn) => { + service.getTiles().subscribe(response => { + expect(response).toEqual(expectedTiles, 'should return expected tiles'); + // done() to be called after asynchronous calls (https://angular.io/guide/testing-services) + done(); + }); + + // TileService should have made one request to GET tiles from expected URL + const req = httpmock.expectOne(backendServerUrlTest); + expect(req.request.method).toEqual('GET'); + + // Respond with the expected mock tiles + req.flush(expectedTiles); + }); +*/ + /** + * TODO: Maybe it makes sense to inform the user that no tiles are displayed + * testing method getTiles() in case there are no tiles in the database + */ + /* + it('should be OK returning no tiles', (done: DoneFn) => { + service.getTiles().subscribe(response => { + expect(response.length).toEqual(0, 'should have empty tiles array'); + done(); + }); + + const req = httpmock.expectOne(backendServerUrlTest); + expect(req.request.method).toEqual('GET'); + + req.flush([]); // Respond with no tile + }); +*/ + /** + * testing method getTiles() in case the backend responds with 404 Not Found + * This service reports the error but finds a way to let the app keep going. + */ + + /* + it('should handle 404 error', (done: DoneFn) => { + errmsg = '404 error'; + + service.getTiles().subscribe( + response => fail('should fail with the 404 error'), + (err: HttpErrorResponse) => { + expect(err.status).toEqual(404); + expect(err.error).toEqual(errmsg); + }, + ); + + // Make an HTTP Get Request + // service.getTiles().then( + // response => fail('should have failed with the 404 error'), + // (err: HttpErrorResponse) => { + // expect(err.status).toEqual(404); + // expect(err.error).toEqual(errmsg); + // } + // ); + + const req = httpmock.expectOne(backendServerUrlTest); + expect(req.request.method).toEqual('GET'); + + // respond with a 404 and the error message in the body --> TODO Frontend GUI must react correctly + req.flush(errmsg, { status: 404, statusText: 'Not Found' }); + }); + */ + + /** + * testing getTiles() when method is called multiple times + * TODO: expect cached results + */ + /* + it('should return expected tiles (called multiple times)', () => { + service.getTiles().subscribe(); + service.getTiles().subscribe(); + service.getTiles().subscribe(response => { + expect(response).toEqual(expectedTiles, 'should return expected tiles'); + }); + + const req = httpmock.match(backendServerUrlTest); + expect(req.length).toEqual(3, 'calls to getTiles()'); + + // Respond to each request with different mock tile results + req[0].flush([]); + req[1].flush([mockTile]); + req[2].flush(expectedTiles); + });*/ + }); + + /** + * Tests for getTileByID() + */ + describe('#getTileByID', () => { + /** + * testing method getTilesById() to return the specific tile with right id + */ + it('should return expected tile by id', () => { + service.getTileById(mockTile.id).then(response => { + expect(response).toEqual(mockTile, 'should return expected tile'); + }); + + const req = httpmock.expectOne(backendServerUrlTest + '/' + mockTile.id); + expect(req.request.method).toEqual('GET'); + + // Respond with the mock tiles + req.flush(mockTile); + }); + + /** + * testing method getTileByID() in case the backend responds with 404 Not Found and the tile does not exist + */ + it( + 'getTileById(): should handle 404 error', + waitForAsync(() => { + errmsg = '404 error'; + // Make an HTTP Get Request + service.getTileById(mockTile.id).then( + () => fail('should have failed with the 404 error'), + (err: HttpErrorResponse) => { + expect(err.status).toEqual(404); + expect(err.error).toEqual(errmsg); + }, + ); + + const req = httpmock.expectOne(backendServerUrlTest + '/' + mockTile.id); + expect(req.request.method).toEqual('GET'); + + req.flush(errmsg, { status: 404, statusText: 'Not Found' }); + }), + ); + }); + /** + * Tests for update an existing tile + */ + describe('#updateTiles', () => { + /** + * testing method updateTiles() + */ + it('should update a tile and return it', () => { + mockTile.title = 'Update title'; + + service.updateTiles(mockTile).then(response => { + expect(response.title).toEqual('Update title', 'should return tile'); + }); + // TileService should have made one request to PUT + const req = httpmock.expectOne(backendServerUrlTest + '/' + mockTile.id); + expect(req.request.method).toEqual('PUT'); + expect(req.request.body).toEqual(mockTile); + + req.flush(mockTile); + }); + + /** + * testing method updateTiles() in case the backend responds with 404 Not Found and the tile does not exist + */ + it( + 'updateTiles(): should handle 404 error', + waitForAsync(() => { + errmsg = '404 error'; + // Make an HTTP Get Request + service.updateTiles(mockTile).then( + () => fail('should have failed with the 404 error'), + (err: HttpErrorResponse) => { + expect(err.status).toEqual(404); + expect(err.error).toEqual(errmsg); + }, + ); + + const req = httpmock.expectOne(backendServerUrlTest + '/' + mockTile.id); + expect(req.request.method).toEqual('PUT'); + + req.flush(errmsg, { status: 404, statusText: 'Not Found' }); + }), + ); + + /** + * testing method updateTiles() in case the backend responds with 401 Unauthorized + */ + it( + 'updateTiles(): should handle 401 error', + waitForAsync(() => { + errmsg = '401 error'; + // Make an HTTP Get Request + service.updateTiles(mockTile).then( + () => fail('should have failed with the 401 error'), + (err: HttpErrorResponse) => { + expect(err.status).toEqual(401); + expect(err.error).toEqual(errmsg); + }, + ); + + const req = httpmock.expectOne(backendServerUrlTest + '/' + mockTile.id); + expect(req.request.method).toEqual('PUT'); + + req.flush(errmsg, { status: 401, statusText: 'Not Found' }); + }), + ); + + /** + * testing method updateTiles() in case the backend responds with 403 Forbidden + */ + it( + 'updateTiles(): should handle 403 error', + waitForAsync(() => { + errmsg = '403 error'; + // Make an HTTP Get Request + service.updateTiles(mockTile).then( + () => fail('should have failed with the 404 error'), + (err: HttpErrorResponse) => { + expect(err.status).toEqual(403); + }, + ); + + const req = httpmock.expectOne(backendServerUrlTest + '/' + mockTile.id); + expect(req.request.method).toEqual('PUT'); + + req.flush(errmsg, { status: 403, statusText: 'Not Found' }); + }), + ); + }); + /* + * Test save a new tile + */ + describe('#saveTiles', () => { + /* + * testing saveTiles() to save a new tile + */ + it( + 'should save a tile correctly (mocked http post request)', + waitForAsync(() => { + service.saveTiles(mockTile).then(response => { + expect(response.id).toBe(1); + expect(response.title).toBe('NewTile1'); + expect(response.redirectUrl).toBe('www.onap.org'); + expect(response.imageAltText).toBe('Onap Image'); + expect(response.imageUrl).toBe('https://www.onap.org/wp-content/uploads/sites/20/2017/02/logo_onap_2017.png'); + expect(response.description).toBe('New Tile for frontend test'); + expect(response.headers).toBe('This is a header'); + }); + /* + * Checking that there ist just one request and check the type of request + * 'flush'/ respond with mock data, run then-block in line 64 and check the except commands + */ + const req = httpmock.expectOne(backendServerUrlTest); + expect(req.request.method).toEqual('POST'); + req.flush(mockTile); + }), + ); + /** + * testing method saveTiles() in case the backend answers with an 401 responds + */ + it( + 'saveTiles(): should handle 401 error', + waitForAsync(() => { + errmsg = '401 error'; + // Make an HTTP Get Request + service.saveTiles(mockTile).then( + () => fail('should have failed with the 401 error'), + (err: HttpErrorResponse) => { + expect(err.status).toEqual(401); + expect(err.error).toEqual(errmsg); + }, + ); + + const req = httpmock.expectOne(backendServerUrlTest); + expect(req.request.method).toEqual('POST'); + + req.flush(errmsg, { status: 401, statusText: 'Not Found' }); + }), + ); + + it( + 'saveTiles(): should handle 403 error', + waitForAsync(() => { + errmsg = '403 error'; + // Make an HTTP Get Request + service.saveTiles(mockTile).then( + () => fail('should have failed with the 401 error'), + (err: HttpErrorResponse) => { + expect(err.status).toEqual(403); + expect(err.error).toEqual(errmsg); + }, + ); + + const req = httpmock.expectOne(backendServerUrlTest); + expect(req.request.method).toEqual('POST'); + + req.flush(errmsg, { status: 403, statusText: 'Forbidden' }); + }), + ); + }); + /** + * testing delete a tile + */ + describe('#deleteTiles', () => { + /** + * testing method deleteTile() + */ + it( + 'should delete a tile correctly (mocked http delete request)', + waitForAsync(() => { + service.deleteTile(mockTile).then(response => { + expect(response).toBeDefined(); + }); + const req = httpmock.expectOne(environment.backendServerUrl + '/tiles/' + mockTile.id); + expect(req.request.method).toEqual('DELETE'); + req.flush({}); + }), + ); + + /** + * testing method deleteTiles() in case the backend responds with 404 Not Found and the tile does not exist + */ + it( + 'deleteTiles(): should handle 404 error', + waitForAsync(() => { + errmsg = '404 error'; + // Make an HTTP Get Request + service.deleteTile(mockTile).then( + () => fail('should have failed with the 404 error'), + (err: HttpErrorResponse) => { + expect(err.status).toEqual(404); + expect(err.error).toEqual(errmsg); + }, + ); + + const req = httpmock.expectOne(backendServerUrlTest + '/' + mockTile.id); + expect(req.request.method).toEqual('DELETE'); + + req.flush(errmsg, { status: 404, statusText: 'Not Found' }); + }), + ); + + /** + * testing method deleteTiles() in case the backend responds with 401 Unauthorized + */ + it( + 'deleteTiles(): should handle 401 error', + waitForAsync(() => { + errmsg = '401 error'; + // Make an HTTP Get Request + service.deleteTile(mockTile).then( + () => fail('should have failed with the 401 error'), + (err: HttpErrorResponse) => { + expect(err.status).toEqual(401); + expect(err.error).toEqual(errmsg); + }, + ); + + const req = httpmock.expectOne(backendServerUrlTest + '/' + mockTile.id); + expect(req.request.method).toEqual('DELETE'); + + req.flush(errmsg, { status: 401, statusText: 'Unauthorized' }); + }), + ); + + /** + * testing method deleteTiles() in case the backend responds with 403 Forbidden + */ + it( + 'deleteTiles(): should handle 403 error', + waitForAsync(() => { + errmsg = '403 error'; + // Make an HTTP Get Request + service.deleteTile(mockTile).then( + () => fail('should have failed with the 404 error'), + (err: HttpErrorResponse) => { + expect(err.status).toEqual(403); + expect(err.error).toEqual(errmsg); + }, + ); + + const req = httpmock.expectOne(backendServerUrlTest + '/' + mockTile.id); + expect(req.request.method).toEqual('DELETE'); + + req.flush(errmsg, { status: 403, statusText: 'Forbidden' }); + }), + ); + }); +}); diff --git a/src/app/services/tileservice/tiles.service.ts b/src/app/services/tileservice/tiles.service.ts new file mode 100644 index 0000000..167e42a --- /dev/null +++ b/src/app/services/tileservice/tiles.service.ts @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { HttpClient, HttpHeaders } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { environment } from 'src/environments/environment'; +import { Tile, TilesListResponse } from '../../model/tile'; +import { map } from 'rxjs/operators'; + +export const urlTileApi = environment.backendServerUrl + '/tiles'; + +@Injectable({ + providedIn: 'root', +}) +// Tutorial on the http client: https://angular.io/tutorial/toh-pt6#get-heroes-with-httpclient +export class TilesService { + constructor(private httpClient: HttpClient) {} + /** + * GET tiles from the server + */ + getTiles(refresh = false): Observable<Tile[]> { + if (refresh) { + const headers = new HttpHeaders({ 'x-refresh': 'true' }); + return this.httpClient + .get<TilesListResponse>(urlTileApi, { headers }) + .pipe(map(tilesListResponse => tilesListResponse.items)); + } + + return this.httpClient.get<TilesListResponse>(urlTileApi).pipe(map(tilesListResponse => tilesListResponse.items)); + } + + /** + * GET tile by id + * @param id to get specific tile + */ + getTileById(id: number): Promise<Tile> { + return this.httpClient.get<Tile>(urlTileApi + '/' + id).toPromise(); + } + + /** + * POST: add a new tile to the database + * @param tile + * @returns the new saved tile + */ + saveTiles(tile: Tile): Promise<Tile> { + const options = { + headers: new HttpHeaders({ 'Content-Type': 'application/json' }), + }; + return this.httpClient.post<Tile>(urlTileApi, tile, options).toPromise(); + } + + /** + * PUT: update the tile on the server + * @returns the updated hero + * @param tile + */ + updateTiles(tile: Tile): Promise<Tile> { + const options = { + headers: new HttpHeaders({ 'Content-Type': 'application/json' }), + }; + return this.httpClient.put<Tile>(urlTileApi + '/' + tile.id, tile, options).toPromise(); + } + + /** + * DELETE: delete the tile from the server + * @param tile to delete + */ + deleteTile(tile: Tile): Promise<void> { + return this.httpClient.delete<void>(urlTileApi + '/' + tile.id).toPromise(); + } +} diff --git a/src/app/services/unsubscribe/unsubscribe.service.ts b/src/app/services/unsubscribe/unsubscribe.service.ts new file mode 100644 index 0000000..b27f6d8 --- /dev/null +++ b/src/app/services/unsubscribe/unsubscribe.service.ts @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Injectable, OnDestroy } from '@angular/core'; +import { Subject } from 'rxjs'; + +@Injectable() +export class UnsubscribeService implements OnDestroy { + private readonly sub$ = new Subject<void>(); + public readonly unsubscribe$ = this.sub$.asObservable(); + + ngOnDestroy(): void { + this.sub$.next(); + this.sub$.complete(); + } +} diff --git a/src/app/services/user-settings.service.ts b/src/app/services/user-settings.service.ts new file mode 100644 index 0000000..cbaa992 --- /dev/null +++ b/src/app/services/user-settings.service.ts @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { distinctUntilChanged, map, pluck, switchMap, take } from 'rxjs/operators'; +import { PreferencesResponse, PreferencesService } from '../../../openapi/output'; +import { + DashboardAppsModel, + DashboardModel, + DashboardTileSettings, + defaultUserSettings, + LastUserActionSettings, STATE_KEYS, + UpdateUserPreferenceModel, + UserPreferencesModel, +} from '../model/user-preferences.model'; +import { BehaviorSubject, Observable, pipe, UnaryFunction } from 'rxjs'; +import { mergeWith as _mergeWith, isObject as _isObject } from 'lodash'; +import { isString } from '../helpers/helpers'; +import { Injectable } from '@angular/core'; + +@Injectable({ + providedIn: 'root', +}) +export class UserSettingsService { + private userSettings: UserPreferencesModel = defaultUserSettings; + private preferencesTracker$ = new BehaviorSubject<UserPreferencesModel>(this.userSettings); + + constructor(private preferencesService: PreferencesService) { + this.getPreferences(); + } + + getPreferences$(): Observable<UserPreferencesModel> { + return this.preferencesTracker$.asObservable(); + } + + selectDashboard = () => + this.getPreferences$().pipe(selectDistinctState<UserPreferencesModel, DashboardModel>(STATE_KEYS.DASHBOARD)); + selectDashboardApps = () => + this.selectDashboard().pipe(selectDistinctState<DashboardModel, DashboardAppsModel>(STATE_KEYS.APPS)); + selectDashboardAvailableTiles = () => + this.selectDashboardApps().pipe(selectDistinctState<DashboardAppsModel, DashboardTileSettings[]>(STATE_KEYS.TILES)); + selectLastUserAction = () => + this.selectDashboardApps().pipe( + selectDistinctState<DashboardAppsModel, LastUserActionSettings>(STATE_KEYS.USER_ACTIONS), + ); + + getPreferences(): void { + this.preferencesService + .getPreferences() + .pipe( + map(preferences => { + return _mergeWith({}, defaultUserSettings, preferences.properties, (objValue, srcValue) => { + if ( + (Array.isArray(srcValue) && !srcValue.some(_isObject)) || + isString(srcValue) || + typeof srcValue === 'boolean' || + Number.isInteger(srcValue) + ) { + return srcValue; + } + }) as UserPreferencesModel; + }), + ) + .subscribe(userPreferences => { + this.preferencesTracker$.next(userPreferences); + }); + } + + updatePreferences(preferences: UpdateUserPreferenceModel): Observable<PreferencesResponse> { + return this.getPreferences$().pipe( + take(1), + switchMap(data => { + const properties = _mergeWith({}, data, preferences, (objValue, srcValue) => { + if ( + Array.isArray(srcValue) || + isString(srcValue) || + typeof srcValue === 'boolean' || + Number.isInteger(srcValue) + ) { + return srcValue; + } + }) as UserPreferencesModel; + this.preferencesTracker$.next(properties); + return this.preferencesService.savePreferences({ properties }); + }), + ); + } + + removePreferences(): Observable<PreferencesResponse> { + return this.preferencesService.updatePreferences({ properties: {} }); + } +} + +export function selectDistinctState<T, I>(key: string): UnaryFunction<Observable<T>, Observable<I>> { + return pipe(pluck<T, I>(key), distinctUntilChanged<I>()); +} diff --git a/src/app/shared.module.ts b/src/app/shared.module.ts new file mode 100644 index 0000000..eef81c0 --- /dev/null +++ b/src/app/shared.module.ts @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +import { CommonModule } from '@angular/common'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { TableSkeletonComponent } from './components/shared/table-skeleton/table-skeleton.component'; +import { PaginationComponent } from './components/shared/pagination/pagination.component'; +import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; +import { BreadcrumbComponent } from './components/shared/breadcrumb/breadcrumb.component'; +import { BreadcrumbItemComponent } from './components/shared/breadcrumb-item/breadcrumb-item.component'; +import { NgModule } from '@angular/core'; +import { HasPermissionPipe } from './pipes/has-permission.pipe'; +import { HasPermissionsDirective } from './directives/has-permissions.directive'; +import { ColonPipe } from './pipes/colon.pipe'; +import { DragDropModule } from '@angular/cdk/drag-drop'; +import { I18nModule } from './modules/i18n/i18n.module'; +import { AlertModule } from './modules/alerting'; +import { TranslateModule } from '@ngx-translate/core'; +import { LoadingSpinnerComponent } from './components/shared/loading-spinner/loading-spinner.component'; +import { InPipe } from 'src/app/pipes/in.pipe'; +import { IsTodayPipe } from 'src/app/pipes/is-today.pipe'; +import { MapPipe } from 'src/app/pipes/map.pipe'; + +@NgModule({ + imports: [CommonModule, NgbModule, I18nModule, FormsModule, ReactiveFormsModule, AlertModule, TranslateModule], + declarations: [ + HasPermissionPipe, + ColonPipe, + InPipe, + IsTodayPipe, + MapPipe, + HasPermissionsDirective, + TableSkeletonComponent, + PaginationComponent, + BreadcrumbComponent, + BreadcrumbItemComponent, + LoadingSpinnerComponent, + ], + exports: [ + CommonModule, + FormsModule, + NgbModule, + FormsModule, + ReactiveFormsModule, + DragDropModule, + I18nModule, + FormsModule, + ReactiveFormsModule, + AlertModule, + HasPermissionPipe, + ColonPipe, + InPipe, + IsTodayPipe, + MapPipe, + HasPermissionsDirective, + PaginationComponent, + TableSkeletonComponent, + BreadcrumbComponent, + BreadcrumbItemComponent, + LoadingSpinnerComponent, + ], +}) +export class SharedModule {} diff --git a/src/app/tilesmock.ts b/src/app/tilesmock.ts new file mode 100644 index 0000000..fc5aa40 --- /dev/null +++ b/src/app/tilesmock.ts @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Tile } from './model/tile'; + +export const TILESMOCK: Tile[] = [ + { + id: 1, + title: 'tile1', + image_url: 'tile1.url', + image_alt_text: 'tile1', + description: 'tile1 desc', + redirect_url: 'redirect_url', + headers: 'header tile1', + }, + { + id: 2, + title: 'tile2', + image_url: 'tile2.url', + image_alt_text: 'tile2', + description: 'tile2 desc', + redirect_url: 'redirect_url', + headers: 'header tile2', + }, +]; diff --git a/src/assets/.gitkeep b/src/assets/.gitkeep new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/assets/.gitkeep diff --git a/src/assets/acl.json b/src/assets/acl.json new file mode 100644 index 0000000..73c2fe9 --- /dev/null +++ b/src/assets/acl.json @@ -0,0 +1,44 @@ +{ + "onap_admin": [ + "users.administration.list", + "users.administration.detail", + "users.administration.create", + "users.administration.edit", + "users.administration.delete", + "cellSite.map", + "serviceInstance.list", + "serviceInstance.delete", + "serviceModel.deployment", + "alarm.list", + "topology.instance.view", + "kpi", + "kpi.graphs", + "kpi.grafana", + "dashboard.tile.ALARM_COUNT_TILE", + "dashboard.tile.KPI_GRAPH_TILE", + "dashboard.tile.USER_LAST_ACTION_TILE", + "treeview" + ], + "onap_operator": [ + "cellSite.map", + "serviceInstance.list", + "serviceInstance.delete", + "serviceModel.deployment", + "alarm.list", + "topology.instance.view", + "kpi", + "kpi.graphs", + "kpi.grafana", + "dashboard.tile.ALARM_COUNT_TILE", + "dashboard.tile.KPI_GRAPH_TILE", + "dashboard.tile.USER_LAST_ACTION_TILE", + "treeview" + ], + "onap_designer": [ + "kpi", + "kpi.graphs", + "kpi.grafana", + "dashboard.tile.KPI_GRAPH_TILE", + "dashboard.tile.USER_LAST_ACTION_TILE" + ] +} diff --git a/src/assets/css/bootstrap-icons.css b/src/assets/css/bootstrap-icons.css new file mode 100644 index 0000000..5cc17e5 --- /dev/null +++ b/src/assets/css/bootstrap-icons.css @@ -0,0 +1,5501 @@ + + +@font-face { + font-family: 'bootstrap-icons'; + src: url('../fonts/bootstrap-icons.woff2?856008caa5eb66df68595e734e59580d') format('woff2'), + url('../fonts/bootstrap-icons.woff?856008caa5eb66df68595e734e59580d') format('woff'); +} + +[class^='bi-']::before, +[class*=' bi-']::before { + display: inline-block; + font-family: bootstrap-icons !important; + font-style: normal; + font-weight: normal !important; + font-variant: normal; + text-transform: none; + line-height: 1; + vertical-align: -0.125em; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.bi-alarm-fill::before { + content: '\f101'; +} + +.bi-alarm::before { + content: '\f102'; +} + +.bi-align-bottom::before { + content: '\f103'; +} + +.bi-align-center::before { + content: '\f104'; +} + +.bi-align-end::before { + content: '\f105'; +} + +.bi-align-middle::before { + content: '\f106'; +} + +.bi-align-start::before { + content: '\f107'; +} + +.bi-align-top::before { + content: '\f108'; +} + +.bi-alt::before { + content: '\f109'; +} + +.bi-app-indicator::before { + content: '\f10a'; +} + +.bi-app::before { + content: '\f10b'; +} + +.bi-archive-fill::before { + content: '\f10c'; +} + +.bi-archive::before { + content: '\f10d'; +} + +.bi-arrow-90deg-down::before { + content: '\f10e'; +} + +.bi-arrow-90deg-left::before { + content: '\f10f'; +} + +.bi-arrow-90deg-right::before { + content: '\f110'; +} + +.bi-arrow-90deg-up::before { + content: '\f111'; +} + +.bi-arrow-bar-down::before { + content: '\f112'; +} + +.bi-arrow-bar-left::before { + content: '\f113'; +} + +.bi-arrow-bar-right::before { + content: '\f114'; +} + +.bi-arrow-bar-up::before { + content: '\f115'; +} + +.bi-arrow-clockwise::before { + content: '\f116'; +} + +.bi-arrow-counterclockwise::before { + content: '\f117'; +} + +.bi-arrow-down-circle-fill::before { + content: '\f118'; +} + +.bi-arrow-down-circle::before { + content: '\f119'; +} + +.bi-arrow-down-left-circle-fill::before { + content: '\f11a'; +} + +.bi-arrow-down-left-circle::before { + content: '\f11b'; +} + +.bi-arrow-down-left-square-fill::before { + content: '\f11c'; +} + +.bi-arrow-down-left-square::before { + content: '\f11d'; +} + +.bi-arrow-down-left::before { + content: '\f11e'; +} + +.bi-arrow-down-right-circle-fill::before { + content: '\f11f'; +} + +.bi-arrow-down-right-circle::before { + content: '\f120'; +} + +.bi-arrow-down-right-square-fill::before { + content: '\f121'; +} + +.bi-arrow-down-right-square::before { + content: '\f122'; +} + +.bi-arrow-down-right::before { + content: '\f123'; +} + +.bi-arrow-down-short::before { + content: '\f124'; +} + +.bi-arrow-down-square-fill::before { + content: '\f125'; +} + +.bi-arrow-down-square::before { + content: '\f126'; +} + +.bi-arrow-down-up::before { + content: '\f127'; +} + +.bi-arrow-down::before { + content: '\f128'; +} + +.bi-arrow-left-circle-fill::before { + content: '\f129'; +} + +.bi-arrow-left-circle::before { + content: '\f12a'; +} + +.bi-arrow-left-right::before { + content: '\f12b'; +} + +.bi-arrow-left-short::before { + content: '\f12c'; +} + +.bi-arrow-left-square-fill::before { + content: '\f12d'; +} + +.bi-arrow-left-square::before { + content: '\f12e'; +} + +.bi-arrow-left::before { + content: '\f12f'; +} + +.bi-arrow-repeat::before { + content: '\f130'; +} + +.bi-arrow-return-left::before { + content: '\f131'; +} + +.bi-arrow-return-right::before { + content: '\f132'; +} + +.bi-arrow-right-circle-fill::before { + content: '\f133'; +} + +.bi-arrow-right-circle::before { + content: '\f134'; +} + +.bi-arrow-right-short::before { + content: '\f135'; +} + +.bi-arrow-right-square-fill::before { + content: '\f136'; +} + +.bi-arrow-right-square::before { + content: '\f137'; +} + +.bi-arrow-right::before { + content: '\f138'; +} + +.bi-arrow-up-circle-fill::before { + content: '\f139'; +} + +.bi-arrow-up-circle::before { + content: '\f13a'; +} + +.bi-arrow-up-left-circle-fill::before { + content: '\f13b'; +} + +.bi-arrow-up-left-circle::before { + content: '\f13c'; +} + +.bi-arrow-up-left-square-fill::before { + content: '\f13d'; +} + +.bi-arrow-up-left-square::before { + content: '\f13e'; +} + +.bi-arrow-up-left::before { + content: '\f13f'; +} + +.bi-arrow-up-right-circle-fill::before { + content: '\f140'; +} + +.bi-arrow-up-right-circle::before { + content: '\f141'; +} + +.bi-arrow-up-right-square-fill::before { + content: '\f142'; +} + +.bi-arrow-up-right-square::before { + content: '\f143'; +} + +.bi-arrow-up-right::before { + content: '\f144'; +} + +.bi-arrow-up-short::before { + content: '\f145'; +} + +.bi-arrow-up-square-fill::before { + content: '\f146'; +} + +.bi-arrow-up-square::before { + content: '\f147'; +} + +.bi-arrow-up::before { + content: '\f148'; +} + +.bi-arrows-angle-contract::before { + content: '\f149'; +} + +.bi-arrows-angle-expand::before { + content: '\f14a'; +} + +.bi-arrows-collapse::before { + content: '\f14b'; +} + +.bi-arrows-expand::before { + content: '\f14c'; +} + +.bi-arrows-fullscreen::before { + content: '\f14d'; +} + +.bi-arrows-move::before { + content: '\f14e'; +} + +.bi-aspect-ratio-fill::before { + content: '\f14f'; +} + +.bi-aspect-ratio::before { + content: '\f150'; +} + +.bi-asterisk::before { + content: '\f151'; +} + +.bi-at::before { + content: '\f152'; +} + +.bi-award-fill::before { + content: '\f153'; +} + +.bi-award::before { + content: '\f154'; +} + +.bi-back::before { + content: '\f155'; +} + +.bi-backspace-fill::before { + content: '\f156'; +} + +.bi-backspace-reverse-fill::before { + content: '\f157'; +} + +.bi-backspace-reverse::before { + content: '\f158'; +} + +.bi-backspace::before { + content: '\f159'; +} + +.bi-badge-3d-fill::before { + content: '\f15a'; +} + +.bi-badge-3d::before { + content: '\f15b'; +} + +.bi-badge-4k-fill::before { + content: '\f15c'; +} + +.bi-badge-4k::before { + content: '\f15d'; +} + +.bi-badge-8k-fill::before { + content: '\f15e'; +} + +.bi-badge-8k::before { + content: '\f15f'; +} + +.bi-badge-ad-fill::before { + content: '\f160'; +} + +.bi-badge-ad::before { + content: '\f161'; +} + +.bi-badge-ar-fill::before { + content: '\f162'; +} + +.bi-badge-ar::before { + content: '\f163'; +} + +.bi-badge-cc-fill::before { + content: '\f164'; +} + +.bi-badge-cc::before { + content: '\f165'; +} + +.bi-badge-hd-fill::before { + content: '\f166'; +} + +.bi-badge-hd::before { + content: '\f167'; +} + +.bi-badge-tm-fill::before { + content: '\f168'; +} + +.bi-badge-tm::before { + content: '\f169'; +} + +.bi-badge-vo-fill::before { + content: '\f16a'; +} + +.bi-badge-vo::before { + content: '\f16b'; +} + +.bi-badge-vr-fill::before { + content: '\f16c'; +} + +.bi-badge-vr::before { + content: '\f16d'; +} + +.bi-badge-wc-fill::before { + content: '\f16e'; +} + +.bi-badge-wc::before { + content: '\f16f'; +} + +.bi-bag-check-fill::before { + content: '\f170'; +} + +.bi-bag-check::before { + content: '\f171'; +} + +.bi-bag-dash-fill::before { + content: '\f172'; +} + +.bi-bag-dash::before { + content: '\f173'; +} + +.bi-bag-fill::before { + content: '\f174'; +} + +.bi-bag-plus-fill::before { + content: '\f175'; +} + +.bi-bag-plus::before { + content: '\f176'; +} + +.bi-bag-x-fill::before { + content: '\f177'; +} + +.bi-bag-x::before { + content: '\f178'; +} + +.bi-bag::before { + content: '\f179'; +} + +.bi-bar-chart-fill::before { + content: '\f17a'; +} + +.bi-bar-chart-line-fill::before { + content: '\f17b'; +} + +.bi-bar-chart-line::before { + content: '\f17c'; +} + +.bi-bar-chart-steps::before { + content: '\f17d'; +} + +.bi-bar-chart::before { + content: '\f17e'; +} + +.bi-basket-fill::before { + content: '\f17f'; +} + +.bi-basket::before { + content: '\f180'; +} + +.bi-basket2-fill::before { + content: '\f181'; +} + +.bi-basket2::before { + content: '\f182'; +} + +.bi-basket3-fill::before { + content: '\f183'; +} + +.bi-basket3::before { + content: '\f184'; +} + +.bi-battery-charging::before { + content: '\f185'; +} + +.bi-battery-full::before { + content: '\f186'; +} + +.bi-battery-half::before { + content: '\f187'; +} + +.bi-battery::before { + content: '\f188'; +} + +.bi-bell-fill::before { + content: '\f189'; +} + +.bi-bell::before { + content: '\f18a'; +} + +.bi-bezier::before { + content: '\f18b'; +} + +.bi-bezier2::before { + content: '\f18c'; +} + +.bi-bicycle::before { + content: '\f18d'; +} + +.bi-binoculars-fill::before { + content: '\f18e'; +} + +.bi-binoculars::before { + content: '\f18f'; +} + +.bi-blockquote-left::before { + content: '\f190'; +} + +.bi-blockquote-right::before { + content: '\f191'; +} + +.bi-book-fill::before { + content: '\f192'; +} + +.bi-book-half::before { + content: '\f193'; +} + +.bi-book::before { + content: '\f194'; +} + +.bi-bookmark-check-fill::before { + content: '\f195'; +} + +.bi-bookmark-check::before { + content: '\f196'; +} + +.bi-bookmark-dash-fill::before { + content: '\f197'; +} + +.bi-bookmark-dash::before { + content: '\f198'; +} + +.bi-bookmark-fill::before { + content: '\f199'; +} + +.bi-bookmark-heart-fill::before { + content: '\f19a'; +} + +.bi-bookmark-heart::before { + content: '\f19b'; +} + +.bi-bookmark-plus-fill::before { + content: '\f19c'; +} + +.bi-bookmark-plus::before { + content: '\f19d'; +} + +.bi-bookmark-star-fill::before { + content: '\f19e'; +} + +.bi-bookmark-star::before { + content: '\f19f'; +} + +.bi-bookmark-x-fill::before { + content: '\f1a0'; +} + +.bi-bookmark-x::before { + content: '\f1a1'; +} + +.bi-bookmark::before { + content: '\f1a2'; +} + +.bi-bookmarks-fill::before { + content: '\f1a3'; +} + +.bi-bookmarks::before { + content: '\f1a4'; +} + +.bi-bookshelf::before { + content: '\f1a5'; +} + +.bi-bootstrap-fill::before { + content: '\f1a6'; +} + +.bi-bootstrap-reboot::before { + content: '\f1a7'; +} + +.bi-bootstrap::before { + content: '\f1a8'; +} + +.bi-border-all::before { + content: '\f1a9'; +} + +.bi-border-bottom::before { + content: '\f1aa'; +} + +.bi-border-center::before { + content: '\f1ab'; +} + +.bi-border-inner::before { + content: '\f1ac'; +} + +.bi-border-left::before { + content: '\f1ad'; +} + +.bi-border-middle::before { + content: '\f1ae'; +} + +.bi-border-outer::before { + content: '\f1af'; +} + +.bi-border-right::before { + content: '\f1b0'; +} + +.bi-border-style::before { + content: '\f1b1'; +} + +.bi-border-top::before { + content: '\f1b2'; +} + +.bi-border-width::before { + content: '\f1b3'; +} + +.bi-border::before { + content: '\f1b4'; +} + +.bi-bounding-box-circles::before { + content: '\f1b5'; +} + +.bi-bounding-box::before { + content: '\f1b6'; +} + +.bi-box-arrow-down-left::before { + content: '\f1b7'; +} + +.bi-box-arrow-down-right::before { + content: '\f1b8'; +} + +.bi-box-arrow-down::before { + content: '\f1b9'; +} + +.bi-box-arrow-in-down-left::before { + content: '\f1ba'; +} + +.bi-box-arrow-in-down-right::before { + content: '\f1bb'; +} + +.bi-box-arrow-in-down::before { + content: '\f1bc'; +} + +.bi-box-arrow-in-left::before { + content: '\f1bd'; +} + +.bi-box-arrow-in-right::before { + content: '\f1be'; +} + +.bi-box-arrow-in-up-left::before { + content: '\f1bf'; +} + +.bi-box-arrow-in-up-right::before { + content: '\f1c0'; +} + +.bi-box-arrow-in-up::before { + content: '\f1c1'; +} + +.bi-box-arrow-left::before { + content: '\f1c2'; +} + +.bi-box-arrow-right::before { + content: '\f1c3'; +} + +.bi-box-arrow-up-left::before { + content: '\f1c4'; +} + +.bi-box-arrow-up-right::before { + content: '\f1c5'; +} + +.bi-box-arrow-up::before { + content: '\f1c6'; +} + +.bi-box-seam::before { + content: '\f1c7'; +} + +.bi-box::before { + content: '\f1c8'; +} + +.bi-braces::before { + content: '\f1c9'; +} + +.bi-bricks::before { + content: '\f1ca'; +} + +.bi-briefcase-fill::before { + content: '\f1cb'; +} + +.bi-briefcase::before { + content: '\f1cc'; +} + +.bi-brightness-alt-high-fill::before { + content: '\f1cd'; +} + +.bi-brightness-alt-high::before { + content: '\f1ce'; +} + +.bi-brightness-alt-low-fill::before { + content: '\f1cf'; +} + +.bi-brightness-alt-low::before { + content: '\f1d0'; +} + +.bi-brightness-high-fill::before { + content: '\f1d1'; +} + +.bi-brightness-high::before { + content: '\f1d2'; +} + +.bi-brightness-low-fill::before { + content: '\f1d3'; +} + +.bi-brightness-low::before { + content: '\f1d4'; +} + +.bi-broadcast-pin::before { + content: '\f1d5'; +} + +.bi-broadcast::before { + content: '\f1d6'; +} + +.bi-brush-fill::before { + content: '\f1d7'; +} + +.bi-brush::before { + content: '\f1d8'; +} + +.bi-bucket-fill::before { + content: '\f1d9'; +} + +.bi-bucket::before { + content: '\f1da'; +} + +.bi-bug-fill::before { + content: '\f1db'; +} + +.bi-bug::before { + content: '\f1dc'; +} + +.bi-building::before { + content: '\f1dd'; +} + +.bi-bullseye::before { + content: '\f1de'; +} + +.bi-calculator-fill::before { + content: '\f1df'; +} + +.bi-calculator::before { + content: '\f1e0'; +} + +.bi-calendar-check-fill::before { + content: '\f1e1'; +} + +.bi-calendar-check::before { + content: '\f1e2'; +} + +.bi-calendar-date-fill::before { + content: '\f1e3'; +} + +.bi-calendar-date::before { + content: '\f1e4'; +} + +.bi-calendar-day-fill::before { + content: '\f1e5'; +} + +.bi-calendar-day::before { + content: '\f1e6'; +} + +.bi-calendar-event-fill::before { + content: '\f1e7'; +} + +.bi-calendar-event::before { + content: '\f1e8'; +} + +.bi-calendar-fill::before { + content: '\f1e9'; +} + +.bi-calendar-minus-fill::before { + content: '\f1ea'; +} + +.bi-calendar-minus::before { + content: '\f1eb'; +} + +.bi-calendar-month-fill::before { + content: '\f1ec'; +} + +.bi-calendar-month::before { + content: '\f1ed'; +} + +.bi-calendar-plus-fill::before { + content: '\f1ee'; +} + +.bi-calendar-plus::before { + content: '\f1ef'; +} + +.bi-calendar-range-fill::before { + content: '\f1f0'; +} + +.bi-calendar-range::before { + content: '\f1f1'; +} + +.bi-calendar-week-fill::before { + content: '\f1f2'; +} + +.bi-calendar-week::before { + content: '\f1f3'; +} + +.bi-calendar-x-fill::before { + content: '\f1f4'; +} + +.bi-calendar-x::before { + content: '\f1f5'; +} + +.bi-calendar::before { + content: '\f1f6'; +} + +.bi-calendar2-check-fill::before { + content: '\f1f7'; +} + +.bi-calendar2-check::before { + content: '\f1f8'; +} + +.bi-calendar2-date-fill::before { + content: '\f1f9'; +} + +.bi-calendar2-date::before { + content: '\f1fa'; +} + +.bi-calendar2-day-fill::before { + content: '\f1fb'; +} + +.bi-calendar2-day::before { + content: '\f1fc'; +} + +.bi-calendar2-event-fill::before { + content: '\f1fd'; +} + +.bi-calendar2-event::before { + content: '\f1fe'; +} + +.bi-calendar2-fill::before { + content: '\f1ff'; +} + +.bi-calendar2-minus-fill::before { + content: '\f200'; +} + +.bi-calendar2-minus::before { + content: '\f201'; +} + +.bi-calendar2-month-fill::before { + content: '\f202'; +} + +.bi-calendar2-month::before { + content: '\f203'; +} + +.bi-calendar2-plus-fill::before { + content: '\f204'; +} + +.bi-calendar2-plus::before { + content: '\f205'; +} + +.bi-calendar2-range-fill::before { + content: '\f206'; +} + +.bi-calendar2-range::before { + content: '\f207'; +} + +.bi-calendar2-week-fill::before { + content: '\f208'; +} + +.bi-calendar2-week::before { + content: '\f209'; +} + +.bi-calendar2-x-fill::before { + content: '\f20a'; +} + +.bi-calendar2-x::before { + content: '\f20b'; +} + +.bi-calendar2::before { + content: '\f20c'; +} + +.bi-calendar3-event-fill::before { + content: '\f20d'; +} + +.bi-calendar3-event::before { + content: '\f20e'; +} + +.bi-calendar3-fill::before { + content: '\f20f'; +} + +.bi-calendar3-range-fill::before { + content: '\f210'; +} + +.bi-calendar3-range::before { + content: '\f211'; +} + +.bi-calendar3-week-fill::before { + content: '\f212'; +} + +.bi-calendar3-week::before { + content: '\f213'; +} + +.bi-calendar3::before { + content: '\f214'; +} + +.bi-calendar4-event::before { + content: '\f215'; +} + +.bi-calendar4-range::before { + content: '\f216'; +} + +.bi-calendar4-week::before { + content: '\f217'; +} + +.bi-calendar4::before { + content: '\f218'; +} + +.bi-camera-fill::before { + content: '\f219'; +} + +.bi-camera-reels-fill::before { + content: '\f21a'; +} + +.bi-camera-reels::before { + content: '\f21b'; +} + +.bi-camera-video-fill::before { + content: '\f21c'; +} + +.bi-camera-video-off-fill::before { + content: '\f21d'; +} + +.bi-camera-video-off::before { + content: '\f21e'; +} + +.bi-camera-video::before { + content: '\f21f'; +} + +.bi-camera::before { + content: '\f220'; +} + +.bi-camera2::before { + content: '\f221'; +} + +.bi-capslock-fill::before { + content: '\f222'; +} + +.bi-capslock::before { + content: '\f223'; +} + +.bi-card-checklist::before { + content: '\f224'; +} + +.bi-card-heading::before { + content: '\f225'; +} + +.bi-card-image::before { + content: '\f226'; +} + +.bi-card-list::before { + content: '\f227'; +} + +.bi-card-text::before { + content: '\f228'; +} + +.bi-caret-down-fill::before { + content: '\f229'; +} + +.bi-caret-down-square-fill::before { + content: '\f22a'; +} + +.bi-caret-down-square::before { + content: '\f22b'; +} + +.bi-caret-down::before { + content: '\f22c'; +} + +.bi-caret-left-fill::before { + content: '\f22d'; +} + +.bi-caret-left-square-fill::before { + content: '\f22e'; +} + +.bi-caret-left-square::before { + content: '\f22f'; +} + +.bi-caret-left::before { + content: '\f230'; +} + +.bi-caret-right-fill::before { + content: '\f231'; +} + +.bi-caret-right-square-fill::before { + content: '\f232'; +} + +.bi-caret-right-square::before { + content: '\f233'; +} + +.bi-caret-right::before { + content: '\f234'; +} + +.bi-caret-up-fill::before { + content: '\f235'; +} + +.bi-caret-up-square-fill::before { + content: '\f236'; +} + +.bi-caret-up-square::before { + content: '\f237'; +} + +.bi-caret-up::before { + content: '\f238'; +} + +.bi-cart-check-fill::before { + content: '\f239'; +} + +.bi-cart-check::before { + content: '\f23a'; +} + +.bi-cart-dash-fill::before { + content: '\f23b'; +} + +.bi-cart-dash::before { + content: '\f23c'; +} + +.bi-cart-fill::before { + content: '\f23d'; +} + +.bi-cart-plus-fill::before { + content: '\f23e'; +} + +.bi-cart-plus::before { + content: '\f23f'; +} + +.bi-cart-x-fill::before { + content: '\f240'; +} + +.bi-cart-x::before { + content: '\f241'; +} + +.bi-cart::before { + content: '\f242'; +} + +.bi-cart2::before { + content: '\f243'; +} + +.bi-cart3::before { + content: '\f244'; +} + +.bi-cart4::before { + content: '\f245'; +} + +.bi-cash-stack::before { + content: '\f246'; +} + +.bi-cash::before { + content: '\f247'; +} + +.bi-cast::before { + content: '\f248'; +} + +.bi-chat-dots-fill::before { + content: '\f249'; +} + +.bi-chat-dots::before { + content: '\f24a'; +} + +.bi-chat-fill::before { + content: '\f24b'; +} + +.bi-chat-left-dots-fill::before { + content: '\f24c'; +} + +.bi-chat-left-dots::before { + content: '\f24d'; +} + +.bi-chat-left-fill::before { + content: '\f24e'; +} + +.bi-chat-left-quote-fill::before { + content: '\f24f'; +} + +.bi-chat-left-quote::before { + content: '\f250'; +} + +.bi-chat-left-text-fill::before { + content: '\f251'; +} + +.bi-chat-left-text::before { + content: '\f252'; +} + +.bi-chat-left::before { + content: '\f253'; +} + +.bi-chat-quote-fill::before { + content: '\f254'; +} + +.bi-chat-quote::before { + content: '\f255'; +} + +.bi-chat-right-dots-fill::before { + content: '\f256'; +} + +.bi-chat-right-dots::before { + content: '\f257'; +} + +.bi-chat-right-fill::before { + content: '\f258'; +} + +.bi-chat-right-quote-fill::before { + content: '\f259'; +} + +.bi-chat-right-quote::before { + content: '\f25a'; +} + +.bi-chat-right-text-fill::before { + content: '\f25b'; +} + +.bi-chat-right-text::before { + content: '\f25c'; +} + +.bi-chat-right::before { + content: '\f25d'; +} + +.bi-chat-square-dots-fill::before { + content: '\f25e'; +} + +.bi-chat-square-dots::before { + content: '\f25f'; +} + +.bi-chat-square-fill::before { + content: '\f260'; +} + +.bi-chat-square-quote-fill::before { + content: '\f261'; +} + +.bi-chat-square-quote::before { + content: '\f262'; +} + +.bi-chat-square-text-fill::before { + content: '\f263'; +} + +.bi-chat-square-text::before { + content: '\f264'; +} + +.bi-chat-square::before { + content: '\f265'; +} + +.bi-chat-text-fill::before { + content: '\f266'; +} + +.bi-chat-text::before { + content: '\f267'; +} + +.bi-chat::before { + content: '\f268'; +} + +.bi-check-all::before { + content: '\f269'; +} + +.bi-check-circle-fill::before { + content: '\f26a'; +} + +.bi-check-circle::before { + content: '\f26b'; +} + +.bi-check-square-fill::before { + content: '\f26c'; +} + +.bi-check-square::before { + content: '\f26d'; +} + +.bi-check::before { + content: '\f26e'; +} + +.bi-check2-all::before { + content: '\f26f'; +} + +.bi-check2-circle::before { + content: '\f270'; +} + +.bi-check2-square::before { + content: '\f271'; +} + +.bi-check2::before { + content: '\f272'; +} + +.bi-chevron-bar-contract::before { + content: '\f273'; +} + +.bi-chevron-bar-down::before { + content: '\f274'; +} + +.bi-chevron-bar-expand::before { + content: '\f275'; +} + +.bi-chevron-bar-left::before { + content: '\f276'; +} + +.bi-chevron-bar-right::before { + content: '\f277'; +} + +.bi-chevron-bar-up::before { + content: '\f278'; +} + +.bi-chevron-compact-down::before { + content: '\f279'; +} + +.bi-chevron-compact-left::before { + content: '\f27a'; +} + +.bi-chevron-compact-right::before { + content: '\f27b'; +} + +.bi-chevron-compact-up::before { + content: '\f27c'; +} + +.bi-chevron-contract::before { + content: '\f27d'; +} + +.bi-chevron-double-down::before { + content: '\f27e'; +} + +.bi-chevron-double-left::before { + content: '\f27f'; +} + +.bi-chevron-double-right::before { + content: '\f280'; +} + +.bi-chevron-double-up::before { + content: '\f281'; +} + +.bi-chevron-down::before { + content: '\f282'; +} + +.bi-chevron-expand::before { + content: '\f283'; +} + +.bi-chevron-left::before { + content: '\f284'; +} + +.bi-chevron-right::before { + content: '\f285'; +} + +.bi-chevron-up::before { + content: '\f286'; +} + +.bi-circle-fill::before { + content: '\f287'; +} + +.bi-circle-half::before { + content: '\f288'; +} + +.bi-circle-square::before { + content: '\f289'; +} + +.bi-circle::before { + content: '\f28a'; +} + +.bi-clipboard-check::before { + content: '\f28b'; +} + +.bi-clipboard-data::before { + content: '\f28c'; +} + +.bi-clipboard-minus::before { + content: '\f28d'; +} + +.bi-clipboard-plus::before { + content: '\f28e'; +} + +.bi-clipboard-x::before { + content: '\f28f'; +} + +.bi-clipboard::before { + content: '\f290'; +} + +.bi-clock-fill::before { + content: '\f291'; +} + +.bi-clock-history::before { + content: '\f292'; +} + +.bi-clock::before { + content: '\f293'; +} + +.bi-cloud-arrow-down-fill::before { + content: '\f294'; +} + +.bi-cloud-arrow-down::before { + content: '\f295'; +} + +.bi-cloud-arrow-up-fill::before { + content: '\f296'; +} + +.bi-cloud-arrow-up::before { + content: '\f297'; +} + +.bi-cloud-check-fill::before { + content: '\f298'; +} + +.bi-cloud-check::before { + content: '\f299'; +} + +.bi-cloud-download-fill::before { + content: '\f29a'; +} + +.bi-cloud-download::before { + content: '\f29b'; +} + +.bi-cloud-drizzle-fill::before { + content: '\f29c'; +} + +.bi-cloud-drizzle::before { + content: '\f29d'; +} + +.bi-cloud-fill::before { + content: '\f29e'; +} + +.bi-cloud-fog-fill::before { + content: '\f29f'; +} + +.bi-cloud-fog::before { + content: '\f2a0'; +} + +.bi-cloud-fog2-fill::before { + content: '\f2a1'; +} + +.bi-cloud-fog2::before { + content: '\f2a2'; +} + +.bi-cloud-hail-fill::before { + content: '\f2a3'; +} + +.bi-cloud-hail::before { + content: '\f2a4'; +} + +.bi-cloud-haze-1::before { + content: '\f2a5'; +} + +.bi-cloud-haze-fill::before { + content: '\f2a6'; +} + +.bi-cloud-haze::before { + content: '\f2a7'; +} + +.bi-cloud-haze2-fill::before { + content: '\f2a8'; +} + +.bi-cloud-lightning-fill::before { + content: '\f2a9'; +} + +.bi-cloud-lightning-rain-fill::before { + content: '\f2aa'; +} + +.bi-cloud-lightning-rain::before { + content: '\f2ab'; +} + +.bi-cloud-lightning::before { + content: '\f2ac'; +} + +.bi-cloud-minus-fill::before { + content: '\f2ad'; +} + +.bi-cloud-minus::before { + content: '\f2ae'; +} + +.bi-cloud-moon-fill::before { + content: '\f2af'; +} + +.bi-cloud-moon::before { + content: '\f2b0'; +} + +.bi-cloud-plus-fill::before { + content: '\f2b1'; +} + +.bi-cloud-plus::before { + content: '\f2b2'; +} + +.bi-cloud-rain-fill::before { + content: '\f2b3'; +} + +.bi-cloud-rain-heavy-fill::before { + content: '\f2b4'; +} + +.bi-cloud-rain-heavy::before { + content: '\f2b5'; +} + +.bi-cloud-rain::before { + content: '\f2b6'; +} + +.bi-cloud-slash-fill::before { + content: '\f2b7'; +} + +.bi-cloud-slash::before { + content: '\f2b8'; +} + +.bi-cloud-sleet-fill::before { + content: '\f2b9'; +} + +.bi-cloud-sleet::before { + content: '\f2ba'; +} + +.bi-cloud-snow-fill::before { + content: '\f2bb'; +} + +.bi-cloud-snow::before { + content: '\f2bc'; +} + +.bi-cloud-sun-fill::before { + content: '\f2bd'; +} + +.bi-cloud-sun::before { + content: '\f2be'; +} + +.bi-cloud-upload-fill::before { + content: '\f2bf'; +} + +.bi-cloud-upload::before { + content: '\f2c0'; +} + +.bi-cloud::before { + content: '\f2c1'; +} + +.bi-clouds-fill::before { + content: '\f2c2'; +} + +.bi-clouds::before { + content: '\f2c3'; +} + +.bi-cloudy-fill::before { + content: '\f2c4'; +} + +.bi-cloudy::before { + content: '\f2c5'; +} + +.bi-code-slash::before { + content: '\f2c6'; +} + +.bi-code-square::before { + content: '\f2c7'; +} + +.bi-code::before { + content: '\f2c8'; +} + +.bi-collection-fill::before { + content: '\f2c9'; +} + +.bi-collection-play-fill::before { + content: '\f2ca'; +} + +.bi-collection-play::before { + content: '\f2cb'; +} + +.bi-collection::before { + content: '\f2cc'; +} + +.bi-columns-gap::before { + content: '\f2cd'; +} + +.bi-columns::before { + content: '\f2ce'; +} + +.bi-command::before { + content: '\f2cf'; +} + +.bi-compass-fill::before { + content: '\f2d0'; +} + +.bi-compass::before { + content: '\f2d1'; +} + +.bi-cone-striped::before { + content: '\f2d2'; +} + +.bi-cone::before { + content: '\f2d3'; +} + +.bi-controller::before { + content: '\f2d4'; +} + +.bi-cpu-fill::before { + content: '\f2d5'; +} + +.bi-cpu::before { + content: '\f2d6'; +} + +.bi-credit-card-2-back-fill::before { + content: '\f2d7'; +} + +.bi-credit-card-2-back::before { + content: '\f2d8'; +} + +.bi-credit-card-2-front-fill::before { + content: '\f2d9'; +} + +.bi-credit-card-2-front::before { + content: '\f2da'; +} + +.bi-credit-card-fill::before { + content: '\f2db'; +} + +.bi-credit-card::before { + content: '\f2dc'; +} + +.bi-crop::before { + content: '\f2dd'; +} + +.bi-cup-fill::before { + content: '\f2de'; +} + +.bi-cup-straw::before { + content: '\f2df'; +} + +.bi-cup::before { + content: '\f2e0'; +} + +.bi-cursor-fill::before { + content: '\f2e1'; +} + +.bi-cursor-text::before { + content: '\f2e2'; +} + +.bi-cursor::before { + content: '\f2e3'; +} + +.bi-dash-circle-dotted::before { + content: '\f2e4'; +} + +.bi-dash-circle-fill::before { + content: '\f2e5'; +} + +.bi-dash-circle::before { + content: '\f2e6'; +} + +.bi-dash-square-dotted::before { + content: '\f2e7'; +} + +.bi-dash-square-fill::before { + content: '\f2e8'; +} + +.bi-dash-square::before { + content: '\f2e9'; +} + +.bi-dash::before { + content: '\f2ea'; +} + +.bi-diagram-2-fill::before { + content: '\f2eb'; +} + +.bi-diagram-2::before { + content: '\f2ec'; +} + +.bi-diagram-3-fill::before { + content: '\f2ed'; +} + +.bi-diagram-3::before { + content: '\f2ee'; +} + +.bi-diamond-fill::before { + content: '\f2ef'; +} + +.bi-diamond-half::before { + content: '\f2f0'; +} + +.bi-diamond::before { + content: '\f2f1'; +} + +.bi-dice-1-fill::before { + content: '\f2f2'; +} + +.bi-dice-1::before { + content: '\f2f3'; +} + +.bi-dice-2-fill::before { + content: '\f2f4'; +} + +.bi-dice-2::before { + content: '\f2f5'; +} + +.bi-dice-3-fill::before { + content: '\f2f6'; +} + +.bi-dice-3::before { + content: '\f2f7'; +} + +.bi-dice-4-fill::before { + content: '\f2f8'; +} + +.bi-dice-4::before { + content: '\f2f9'; +} + +.bi-dice-5-fill::before { + content: '\f2fa'; +} + +.bi-dice-5::before { + content: '\f2fb'; +} + +.bi-dice-6-fill::before { + content: '\f2fc'; +} + +.bi-dice-6::before { + content: '\f2fd'; +} + +.bi-disc-fill::before { + content: '\f2fe'; +} + +.bi-disc::before { + content: '\f2ff'; +} + +.bi-discord::before { + content: '\f300'; +} + +.bi-display-fill::before { + content: '\f301'; +} + +.bi-display::before { + content: '\f302'; +} + +.bi-distribute-horizontal::before { + content: '\f303'; +} + +.bi-distribute-vertical::before { + content: '\f304'; +} + +.bi-door-closed-fill::before { + content: '\f305'; +} + +.bi-door-closed::before { + content: '\f306'; +} + +.bi-door-open-fill::before { + content: '\f307'; +} + +.bi-door-open::before { + content: '\f308'; +} + +.bi-dot::before { + content: '\f309'; +} + +.bi-download::before { + content: '\f30a'; +} + +.bi-droplet-fill::before { + content: '\f30b'; +} + +.bi-droplet-half::before { + content: '\f30c'; +} + +.bi-droplet::before { + content: '\f30d'; +} + +.bi-earbuds::before { + content: '\f30e'; +} + +.bi-easel-fill::before { + content: '\f30f'; +} + +.bi-easel::before { + content: '\f310'; +} + +.bi-egg-fill::before { + content: '\f311'; +} + +.bi-egg-fried::before { + content: '\f312'; +} + +.bi-egg::before { + content: '\f313'; +} + +.bi-eject-fill::before { + content: '\f314'; +} + +.bi-eject::before { + content: '\f315'; +} + +.bi-emoji-angry-fill::before { + content: '\f316'; +} + +.bi-emoji-angry::before { + content: '\f317'; +} + +.bi-emoji-dizzy-fill::before { + content: '\f318'; +} + +.bi-emoji-dizzy::before { + content: '\f319'; +} + +.bi-emoji-expressionless-fill::before { + content: '\f31a'; +} + +.bi-emoji-expressionless::before { + content: '\f31b'; +} + +.bi-emoji-frown-fill::before { + content: '\f31c'; +} + +.bi-emoji-frown::before { + content: '\f31d'; +} + +.bi-emoji-heart-eyes-fill::before { + content: '\f31e'; +} + +.bi-emoji-heart-eyes::before { + content: '\f31f'; +} + +.bi-emoji-laughing-fill::before { + content: '\f320'; +} + +.bi-emoji-laughing::before { + content: '\f321'; +} + +.bi-emoji-neutral-fill::before { + content: '\f322'; +} + +.bi-emoji-neutral::before { + content: '\f323'; +} + +.bi-emoji-smile-fill::before { + content: '\f324'; +} + +.bi-emoji-smile-upside-down-fill::before { + content: '\f325'; +} + +.bi-emoji-smile-upside-down::before { + content: '\f326'; +} + +.bi-emoji-smile::before { + content: '\f327'; +} + +.bi-emoji-sunglasses-fill::before { + content: '\f328'; +} + +.bi-emoji-sunglasses::before { + content: '\f329'; +} + +.bi-emoji-wink-fill::before { + content: '\f32a'; +} + +.bi-emoji-wink::before { + content: '\f32b'; +} + +.bi-envelope-fill::before { + content: '\f32c'; +} + +.bi-envelope-open-fill::before { + content: '\f32d'; +} + +.bi-envelope-open::before { + content: '\f32e'; +} + +.bi-envelope::before { + content: '\f32f'; +} + +.bi-eraser-fill::before { + content: '\f330'; +} + +.bi-eraser::before { + content: '\f331'; +} + +.bi-exclamation-circle-fill::before { + content: '\f332'; +} + +.bi-exclamation-circle::before { + content: '\f333'; +} + +.bi-exclamation-diamond-fill::before { + content: '\f334'; +} + +.bi-exclamation-diamond::before { + content: '\f335'; +} + +.bi-exclamation-octagon-fill::before { + content: '\f336'; +} + +.bi-exclamation-octagon::before { + content: '\f337'; +} + +.bi-exclamation-square-fill::before { + content: '\f338'; +} + +.bi-exclamation-square::before { + content: '\f339'; +} + +.bi-exclamation-triangle-fill::before { + content: '\f33a'; +} + +.bi-exclamation-triangle::before { + content: '\f33b'; +} + +.bi-exclamation::before { + content: '\f33c'; +} + +.bi-exclude::before { + content: '\f33d'; +} + +.bi-eye-fill::before { + content: '\f33e'; +} + +.bi-eye-slash-fill::before { + content: '\f33f'; +} + +.bi-eye-slash::before { + content: '\f340'; +} + +.bi-eye::before { + content: '\f341'; +} + +.bi-eyedropper::before { + content: '\f342'; +} + +.bi-eyeglasses::before { + content: '\f343'; +} + +.bi-facebook::before { + content: '\f344'; +} + +.bi-file-arrow-down-fill::before { + content: '\f345'; +} + +.bi-file-arrow-down::before { + content: '\f346'; +} + +.bi-file-arrow-up-fill::before { + content: '\f347'; +} + +.bi-file-arrow-up::before { + content: '\f348'; +} + +.bi-file-bar-graph-fill::before { + content: '\f349'; +} + +.bi-file-bar-graph::before { + content: '\f34a'; +} + +.bi-file-binary-fill::before { + content: '\f34b'; +} + +.bi-file-binary::before { + content: '\f34c'; +} + +.bi-file-break-fill::before { + content: '\f34d'; +} + +.bi-file-break::before { + content: '\f34e'; +} + +.bi-file-check-fill::before { + content: '\f34f'; +} + +.bi-file-check::before { + content: '\f350'; +} + +.bi-file-code-fill::before { + content: '\f351'; +} + +.bi-file-code::before { + content: '\f352'; +} + +.bi-file-diff-fill::before { + content: '\f353'; +} + +.bi-file-diff::before { + content: '\f354'; +} + +.bi-file-earmark-arrow-down-fill::before { + content: '\f355'; +} + +.bi-file-earmark-arrow-down::before { + content: '\f356'; +} + +.bi-file-earmark-arrow-up-fill::before { + content: '\f357'; +} + +.bi-file-earmark-arrow-up::before { + content: '\f358'; +} + +.bi-file-earmark-bar-graph-fill::before { + content: '\f359'; +} + +.bi-file-earmark-bar-graph::before { + content: '\f35a'; +} + +.bi-file-earmark-binary-fill::before { + content: '\f35b'; +} + +.bi-file-earmark-binary::before { + content: '\f35c'; +} + +.bi-file-earmark-break-fill::before { + content: '\f35d'; +} + +.bi-file-earmark-break::before { + content: '\f35e'; +} + +.bi-file-earmark-check-fill::before { + content: '\f35f'; +} + +.bi-file-earmark-check::before { + content: '\f360'; +} + +.bi-file-earmark-code-fill::before { + content: '\f361'; +} + +.bi-file-earmark-code::before { + content: '\f362'; +} + +.bi-file-earmark-diff-fill::before { + content: '\f363'; +} + +.bi-file-earmark-diff::before { + content: '\f364'; +} + +.bi-file-earmark-easel-fill::before { + content: '\f365'; +} + +.bi-file-earmark-easel::before { + content: '\f366'; +} + +.bi-file-earmark-excel-fill::before { + content: '\f367'; +} + +.bi-file-earmark-excel::before { + content: '\f368'; +} + +.bi-file-earmark-fill::before { + content: '\f369'; +} + +.bi-file-earmark-font-fill::before { + content: '\f36a'; +} + +.bi-file-earmark-font::before { + content: '\f36b'; +} + +.bi-file-earmark-image-fill::before { + content: '\f36c'; +} + +.bi-file-earmark-image::before { + content: '\f36d'; +} + +.bi-file-earmark-lock-fill::before { + content: '\f36e'; +} + +.bi-file-earmark-lock::before { + content: '\f36f'; +} + +.bi-file-earmark-lock2-fill::before { + content: '\f370'; +} + +.bi-file-earmark-lock2::before { + content: '\f371'; +} + +.bi-file-earmark-medical-fill::before { + content: '\f372'; +} + +.bi-file-earmark-medical::before { + content: '\f373'; +} + +.bi-file-earmark-minus-fill::before { + content: '\f374'; +} + +.bi-file-earmark-minus::before { + content: '\f375'; +} + +.bi-file-earmark-music-fill::before { + content: '\f376'; +} + +.bi-file-earmark-music::before { + content: '\f377'; +} + +.bi-file-earmark-person-fill::before { + content: '\f378'; +} + +.bi-file-earmark-person::before { + content: '\f379'; +} + +.bi-file-earmark-play-fill::before { + content: '\f37a'; +} + +.bi-file-earmark-play::before { + content: '\f37b'; +} + +.bi-file-earmark-plus-fill::before { + content: '\f37c'; +} + +.bi-file-earmark-plus::before { + content: '\f37d'; +} + +.bi-file-earmark-post-fill::before { + content: '\f37e'; +} + +.bi-file-earmark-post::before { + content: '\f37f'; +} + +.bi-file-earmark-ppt-fill::before { + content: '\f380'; +} + +.bi-file-earmark-ppt::before { + content: '\f381'; +} + +.bi-file-earmark-richtext-fill::before { + content: '\f382'; +} + +.bi-file-earmark-richtext::before { + content: '\f383'; +} + +.bi-file-earmark-ruled-fill::before { + content: '\f384'; +} + +.bi-file-earmark-ruled::before { + content: '\f385'; +} + +.bi-file-earmark-slides-fill::before { + content: '\f386'; +} + +.bi-file-earmark-slides::before { + content: '\f387'; +} + +.bi-file-earmark-spreadsheet-fill::before { + content: '\f388'; +} + +.bi-file-earmark-spreadsheet::before { + content: '\f389'; +} + +.bi-file-earmark-text-fill::before { + content: '\f38a'; +} + +.bi-file-earmark-text::before { + content: '\f38b'; +} + +.bi-file-earmark-word-fill::before { + content: '\f38c'; +} + +.bi-file-earmark-word::before { + content: '\f38d'; +} + +.bi-file-earmark-x-fill::before { + content: '\f38e'; +} + +.bi-file-earmark-x::before { + content: '\f38f'; +} + +.bi-file-earmark-zip-fill::before { + content: '\f390'; +} + +.bi-file-earmark-zip::before { + content: '\f391'; +} + +.bi-file-earmark::before { + content: '\f392'; +} + +.bi-file-easel-fill::before { + content: '\f393'; +} + +.bi-file-easel::before { + content: '\f394'; +} + +.bi-file-excel-fill::before { + content: '\f395'; +} + +.bi-file-excel::before { + content: '\f396'; +} + +.bi-file-fill::before { + content: '\f397'; +} + +.bi-file-font-fill::before { + content: '\f398'; +} + +.bi-file-font::before { + content: '\f399'; +} + +.bi-file-image-fill::before { + content: '\f39a'; +} + +.bi-file-image::before { + content: '\f39b'; +} + +.bi-file-lock-fill::before { + content: '\f39c'; +} + +.bi-file-lock::before { + content: '\f39d'; +} + +.bi-file-lock2-fill::before { + content: '\f39e'; +} + +.bi-file-lock2::before { + content: '\f39f'; +} + +.bi-file-medical-fill::before { + content: '\f3a0'; +} + +.bi-file-medical::before { + content: '\f3a1'; +} + +.bi-file-minus-fill::before { + content: '\f3a2'; +} + +.bi-file-minus::before { + content: '\f3a3'; +} + +.bi-file-music-fill::before { + content: '\f3a4'; +} + +.bi-file-music::before { + content: '\f3a5'; +} + +.bi-file-person-fill::before { + content: '\f3a6'; +} + +.bi-file-person::before { + content: '\f3a7'; +} + +.bi-file-play-fill::before { + content: '\f3a8'; +} + +.bi-file-play::before { + content: '\f3a9'; +} + +.bi-file-plus-fill::before { + content: '\f3aa'; +} + +.bi-file-plus::before { + content: '\f3ab'; +} + +.bi-file-post-fill::before { + content: '\f3ac'; +} + +.bi-file-post::before { + content: '\f3ad'; +} + +.bi-file-ppt-fill::before { + content: '\f3ae'; +} + +.bi-file-ppt::before { + content: '\f3af'; +} + +.bi-file-richtext-fill::before { + content: '\f3b0'; +} + +.bi-file-richtext::before { + content: '\f3b1'; +} + +.bi-file-ruled-fill::before { + content: '\f3b2'; +} + +.bi-file-ruled::before { + content: '\f3b3'; +} + +.bi-file-slides-fill::before { + content: '\f3b4'; +} + +.bi-file-slides::before { + content: '\f3b5'; +} + +.bi-file-spreadsheet-fill::before { + content: '\f3b6'; +} + +.bi-file-spreadsheet::before { + content: '\f3b7'; +} + +.bi-file-text-fill::before { + content: '\f3b8'; +} + +.bi-file-text::before { + content: '\f3b9'; +} + +.bi-file-word-fill::before { + content: '\f3ba'; +} + +.bi-file-word::before { + content: '\f3bb'; +} + +.bi-file-x-fill::before { + content: '\f3bc'; +} + +.bi-file-x::before { + content: '\f3bd'; +} + +.bi-file-zip-fill::before { + content: '\f3be'; +} + +.bi-file-zip::before { + content: '\f3bf'; +} + +.bi-file::before { + content: '\f3c0'; +} + +.bi-files-alt::before { + content: '\f3c1'; +} + +.bi-files::before { + content: '\f3c2'; +} + +.bi-film::before { + content: '\f3c3'; +} + +.bi-filter-circle-fill::before { + content: '\f3c4'; +} + +.bi-filter-circle::before { + content: '\f3c5'; +} + +.bi-filter-left::before { + content: '\f3c6'; +} + +.bi-filter-right::before { + content: '\f3c7'; +} + +.bi-filter-square-fill::before { + content: '\f3c8'; +} + +.bi-filter-square::before { + content: '\f3c9'; +} + +.bi-filter::before { + content: '\f3ca'; +} + +.bi-flag-fill::before { + content: '\f3cb'; +} + +.bi-flag::before { + content: '\f3cc'; +} + +.bi-flower1::before { + content: '\f3cd'; +} + +.bi-flower2::before { + content: '\f3ce'; +} + +.bi-flower3::before { + content: '\f3cf'; +} + +.bi-folder-check::before { + content: '\f3d0'; +} + +.bi-folder-fill::before { + content: '\f3d1'; +} + +.bi-folder-minus::before { + content: '\f3d2'; +} + +.bi-folder-plus::before { + content: '\f3d3'; +} + +.bi-folder-symlink-fill::before { + content: '\f3d4'; +} + +.bi-folder-symlink::before { + content: '\f3d5'; +} + +.bi-folder-x::before { + content: '\f3d6'; +} + +.bi-folder::before { + content: '\f3d7'; +} + +.bi-folder2-open::before { + content: '\f3d8'; +} + +.bi-folder2::before { + content: '\f3d9'; +} + +.bi-fonts::before { + content: '\f3da'; +} + +.bi-forward-fill::before { + content: '\f3db'; +} + +.bi-forward::before { + content: '\f3dc'; +} + +.bi-front::before { + content: '\f3dd'; +} + +.bi-fullscreen-exit::before { + content: '\f3de'; +} + +.bi-fullscreen::before { + content: '\f3df'; +} + +.bi-funnel-fill::before { + content: '\f3e0'; +} + +.bi-funnel::before { + content: '\f3e1'; +} + +.bi-gear-fill::before { + content: '\f3e2'; +} + +.bi-gear-wide-connected::before { + content: '\f3e3'; +} + +.bi-gear-wide::before { + content: '\f3e4'; +} + +.bi-gear::before { + content: '\f3e5'; +} + +.bi-gem::before { + content: '\f3e6'; +} + +.bi-geo-alt-fill::before { + content: '\f3e7'; +} + +.bi-geo-alt::before { + content: '\f3e8'; +} + +.bi-geo-fill::before { + content: '\f3e9'; +} + +.bi-geo::before { + content: '\f3ea'; +} + +.bi-gift-fill::before { + content: '\f3eb'; +} + +.bi-gift::before { + content: '\f3ec'; +} + +.bi-github::before { + content: '\f3ed'; +} + +.bi-globe::before { + content: '\f3ee'; +} + +.bi-globe2::before { + content: '\f3ef'; +} + +.bi-google::before { + content: '\f3f0'; +} + +.bi-graph-down::before { + content: '\f3f1'; +} + +.bi-graph-up::before { + content: '\f3f2'; +} + +.bi-grid-1x2-fill::before { + content: '\f3f3'; +} + +.bi-grid-1x2::before { + content: '\f3f4'; +} + +.bi-grid-3x2-gap-fill::before { + content: '\f3f5'; +} + +.bi-grid-3x2-gap::before { + content: '\f3f6'; +} + +.bi-grid-3x2::before { + content: '\f3f7'; +} + +.bi-grid-3x3-gap-fill::before { + content: '\f3f8'; +} + +.bi-grid-3x3-gap::before { + content: '\f3f9'; +} + +.bi-grid-3x3::before { + content: '\f3fa'; +} + +.bi-grid-fill::before { + content: '\f3fb'; +} + +.bi-grid::before { + content: '\f3fc'; +} + +.bi-grip-horizontal::before { + content: '\f3fd'; +} + +.bi-grip-vertical::before { + content: '\f3fe'; +} + +.bi-hammer::before { + content: '\f3ff'; +} + +.bi-hand-index-fill::before { + content: '\f400'; +} + +.bi-hand-index-thumb-fill::before { + content: '\f401'; +} + +.bi-hand-index-thumb::before { + content: '\f402'; +} + +.bi-hand-index::before { + content: '\f403'; +} + +.bi-hand-thumbs-down-fill::before { + content: '\f404'; +} + +.bi-hand-thumbs-down::before { + content: '\f405'; +} + +.bi-hand-thumbs-up-fill::before { + content: '\f406'; +} + +.bi-hand-thumbs-up::before { + content: '\f407'; +} + +.bi-handbag-fill::before { + content: '\f408'; +} + +.bi-handbag::before { + content: '\f409'; +} + +.bi-hash::before { + content: '\f40a'; +} + +.bi-hdd-fill::before { + content: '\f40b'; +} + +.bi-hdd-network-fill::before { + content: '\f40c'; +} + +.bi-hdd-network::before { + content: '\f40d'; +} + +.bi-hdd-rack-fill::before { + content: '\f40e'; +} + +.bi-hdd-rack::before { + content: '\f40f'; +} + +.bi-hdd-stack-fill::before { + content: '\f410'; +} + +.bi-hdd-stack::before { + content: '\f411'; +} + +.bi-hdd::before { + content: '\f412'; +} + +.bi-headphones::before { + content: '\f413'; +} + +.bi-headset::before { + content: '\f414'; +} + +.bi-heart-fill::before { + content: '\f415'; +} + +.bi-heart-half::before { + content: '\f416'; +} + +.bi-heart::before { + content: '\f417'; +} + +.bi-heptagon-fill::before { + content: '\f418'; +} + +.bi-heptagon-half::before { + content: '\f419'; +} + +.bi-heptagon::before { + content: '\f41a'; +} + +.bi-hexagon-fill::before { + content: '\f41b'; +} + +.bi-hexagon-half::before { + content: '\f41c'; +} + +.bi-hexagon::before { + content: '\f41d'; +} + +.bi-hourglass-bottom::before { + content: '\f41e'; +} + +.bi-hourglass-split::before { + content: '\f41f'; +} + +.bi-hourglass-top::before { + content: '\f420'; +} + +.bi-hourglass::before { + content: '\f421'; +} + +.bi-house-door-fill::before { + content: '\f422'; +} + +.bi-house-door::before { + content: '\f423'; +} + +.bi-house-fill::before { + content: '\f424'; +} + +.bi-house::before { + content: '\f425'; +} + +.bi-hr::before { + content: '\f426'; +} + +.bi-hurricane::before { + content: '\f427'; +} + +.bi-image-alt::before { + content: '\f428'; +} + +.bi-image-fill::before { + content: '\f429'; +} + +.bi-image::before { + content: '\f42a'; +} + +.bi-images::before { + content: '\f42b'; +} + +.bi-inbox-fill::before { + content: '\f42c'; +} + +.bi-inbox::before { + content: '\f42d'; +} + +.bi-inboxes-fill::before { + content: '\f42e'; +} + +.bi-inboxes::before { + content: '\f42f'; +} + +.bi-info-circle-fill::before { + content: '\f430'; +} + +.bi-info-circle::before { + content: '\f431'; +} + +.bi-info-square-fill::before { + content: '\f432'; +} + +.bi-info-square::before { + content: '\f433'; +} + +.bi-info::before { + content: '\f434'; +} + +.bi-input-cursor-text::before { + content: '\f435'; +} + +.bi-input-cursor::before { + content: '\f436'; +} + +.bi-instagram::before { + content: '\f437'; +} + +.bi-intersect::before { + content: '\f438'; +} + +.bi-journal-album::before { + content: '\f439'; +} + +.bi-journal-arrow-down::before { + content: '\f43a'; +} + +.bi-journal-arrow-up::before { + content: '\f43b'; +} + +.bi-journal-bookmark-fill::before { + content: '\f43c'; +} + +.bi-journal-bookmark::before { + content: '\f43d'; +} + +.bi-journal-check::before { + content: '\f43e'; +} + +.bi-journal-code::before { + content: '\f43f'; +} + +.bi-journal-medical::before { + content: '\f440'; +} + +.bi-journal-minus::before { + content: '\f441'; +} + +.bi-journal-plus::before { + content: '\f442'; +} + +.bi-journal-richtext::before { + content: '\f443'; +} + +.bi-journal-text::before { + content: '\f444'; +} + +.bi-journal-x::before { + content: '\f445'; +} + +.bi-journal::before { + content: '\f446'; +} + +.bi-journals::before { + content: '\f447'; +} + +.bi-joystick::before { + content: '\f448'; +} + +.bi-justify-left::before { + content: '\f449'; +} + +.bi-justify-right::before { + content: '\f44a'; +} + +.bi-justify::before { + content: '\f44b'; +} + +.bi-kanban-fill::before { + content: '\f44c'; +} + +.bi-kanban::before { + content: '\f44d'; +} + +.bi-key-fill::before { + content: '\f44e'; +} + +.bi-key::before { + content: '\f44f'; +} + +.bi-keyboard-fill::before { + content: '\f450'; +} + +.bi-keyboard::before { + content: '\f451'; +} + +.bi-ladder::before { + content: '\f452'; +} + +.bi-lamp-fill::before { + content: '\f453'; +} + +.bi-lamp::before { + content: '\f454'; +} + +.bi-laptop-fill::before { + content: '\f455'; +} + +.bi-laptop::before { + content: '\f456'; +} + +.bi-layer-backward::before { + content: '\f457'; +} + +.bi-layer-forward::before { + content: '\f458'; +} + +.bi-layers-fill::before { + content: '\f459'; +} + +.bi-layers-half::before { + content: '\f45a'; +} + +.bi-layers::before { + content: '\f45b'; +} + +.bi-layout-sidebar-inset-reverse::before { + content: '\f45c'; +} + +.bi-layout-sidebar-inset::before { + content: '\f45d'; +} + +.bi-layout-sidebar-reverse::before { + content: '\f45e'; +} + +.bi-layout-sidebar::before { + content: '\f45f'; +} + +.bi-layout-split::before { + content: '\f460'; +} + +.bi-layout-text-sidebar-reverse::before { + content: '\f461'; +} + +.bi-layout-text-sidebar::before { + content: '\f462'; +} + +.bi-layout-text-window-reverse::before { + content: '\f463'; +} + +.bi-layout-text-window::before { + content: '\f464'; +} + +.bi-layout-three-columns::before { + content: '\f465'; +} + +.bi-layout-wtf::before { + content: '\f466'; +} + +.bi-life-preserver::before { + content: '\f467'; +} + +.bi-lightbulb-fill::before { + content: '\f468'; +} + +.bi-lightbulb-off-fill::before { + content: '\f469'; +} + +.bi-lightbulb-off::before { + content: '\f46a'; +} + +.bi-lightbulb::before { + content: '\f46b'; +} + +.bi-lightning-charge-fill::before { + content: '\f46c'; +} + +.bi-lightning-charge::before { + content: '\f46d'; +} + +.bi-lightning-fill::before { + content: '\f46e'; +} + +.bi-lightning::before { + content: '\f46f'; +} + +.bi-link-45deg::before { + content: '\f470'; +} + +.bi-link::before { + content: '\f471'; +} + +.bi-linkedin::before { + content: '\f472'; +} + +.bi-list-check::before { + content: '\f473'; +} + +.bi-list-nested::before { + content: '\f474'; +} + +.bi-list-ol::before { + content: '\f475'; +} + +.bi-list-stars::before { + content: '\f476'; +} + +.bi-list-task::before { + content: '\f477'; +} + +.bi-list-ul::before { + content: '\f478'; +} + +.bi-list::before { + content: '\f479'; +} + +.bi-lock-fill::before { + content: '\f47a'; +} + +.bi-lock::before { + content: '\f47b'; +} + +.bi-mailbox::before { + content: '\f47c'; +} + +.bi-mailbox2::before { + content: '\f47d'; +} + +.bi-map-fill::before { + content: '\f47e'; +} + +.bi-map::before { + content: '\f47f'; +} + +.bi-markdown-fill::before { + content: '\f480'; +} + +.bi-markdown::before { + content: '\f481'; +} + +.bi-mask::before { + content: '\f482'; +} + +.bi-megaphone-fill::before { + content: '\f483'; +} + +.bi-megaphone::before { + content: '\f484'; +} + +.bi-menu-app-fill::before { + content: '\f485'; +} + +.bi-menu-app::before { + content: '\f486'; +} + +.bi-menu-button-fill::before { + content: '\f487'; +} + +.bi-menu-button-wide-fill::before { + content: '\f488'; +} + +.bi-menu-button-wide::before { + content: '\f489'; +} + +.bi-menu-button::before { + content: '\f48a'; +} + +.bi-menu-down::before { + content: '\f48b'; +} + +.bi-menu-up::before { + content: '\f48c'; +} + +.bi-mic-fill::before { + content: '\f48d'; +} + +.bi-mic-mute-fill::before { + content: '\f48e'; +} + +.bi-mic-mute::before { + content: '\f48f'; +} + +.bi-mic::before { + content: '\f490'; +} + +.bi-minecart-loaded::before { + content: '\f491'; +} + +.bi-minecart::before { + content: '\f492'; +} + +.bi-moisture::before { + content: '\f493'; +} + +.bi-moon-fill::before { + content: '\f494'; +} + +.bi-moon-stars-fill::before { + content: '\f495'; +} + +.bi-moon-stars::before { + content: '\f496'; +} + +.bi-moon::before { + content: '\f497'; +} + +.bi-mouse-fill::before { + content: '\f498'; +} + +.bi-mouse::before { + content: '\f499'; +} + +.bi-mouse2-fill::before { + content: '\f49a'; +} + +.bi-mouse2::before { + content: '\f49b'; +} + +.bi-mouse3-fill::before { + content: '\f49c'; +} + +.bi-mouse3::before { + content: '\f49d'; +} + +.bi-music-note-beamed::before { + content: '\f49e'; +} + +.bi-music-note-list::before { + content: '\f49f'; +} + +.bi-music-note::before { + content: '\f4a0'; +} + +.bi-music-player-fill::before { + content: '\f4a1'; +} + +.bi-music-player::before { + content: '\f4a2'; +} + +.bi-newspaper::before { + content: '\f4a3'; +} + +.bi-node-minus-fill::before { + content: '\f4a4'; +} + +.bi-node-minus::before { + content: '\f4a5'; +} + +.bi-node-plus-fill::before { + content: '\f4a6'; +} + +.bi-node-plus::before { + content: '\f4a7'; +} + +.bi-nut-fill::before { + content: '\f4a8'; +} + +.bi-nut::before { + content: '\f4a9'; +} + +.bi-octagon-fill::before { + content: '\f4aa'; +} + +.bi-octagon-half::before { + content: '\f4ab'; +} + +.bi-octagon::before { + content: '\f4ac'; +} + +.bi-option::before { + content: '\f4ad'; +} + +.bi-outlet::before { + content: '\f4ae'; +} + +.bi-paint-bucket::before { + content: '\f4af'; +} + +.bi-palette-fill::before { + content: '\f4b0'; +} + +.bi-palette::before { + content: '\f4b1'; +} + +.bi-palette2::before { + content: '\f4b2'; +} + +.bi-paperclip::before { + content: '\f4b3'; +} + +.bi-paragraph::before { + content: '\f4b4'; +} + +.bi-patch-check-fill::before { + content: '\f4b5'; +} + +.bi-patch-check::before { + content: '\f4b6'; +} + +.bi-patch-exclamation-fill::before { + content: '\f4b7'; +} + +.bi-patch-exclamation::before { + content: '\f4b8'; +} + +.bi-patch-minus-fill::before { + content: '\f4b9'; +} + +.bi-patch-minus::before { + content: '\f4ba'; +} + +.bi-patch-plus-fill::before { + content: '\f4bb'; +} + +.bi-patch-plus::before { + content: '\f4bc'; +} + +.bi-patch-question-fill::before { + content: '\f4bd'; +} + +.bi-patch-question::before { + content: '\f4be'; +} + +.bi-pause-btn-fill::before { + content: '\f4bf'; +} + +.bi-pause-btn::before { + content: '\f4c0'; +} + +.bi-pause-circle-fill::before { + content: '\f4c1'; +} + +.bi-pause-circle::before { + content: '\f4c2'; +} + +.bi-pause-fill::before { + content: '\f4c3'; +} + +.bi-pause::before { + content: '\f4c4'; +} + +.bi-peace-fill::before { + content: '\f4c5'; +} + +.bi-peace::before { + content: '\f4c6'; +} + +.bi-pen-fill::before { + content: '\f4c7'; +} + +.bi-pen::before { + content: '\f4c8'; +} + +.bi-pencil-fill::before { + content: '\f4c9'; +} + +.bi-pencil-square::before { + content: '\f4ca'; +} + +.bi-pencil::before { + content: '\f4cb'; +} + +.bi-pentagon-fill::before { + content: '\f4cc'; +} + +.bi-pentagon-half::before { + content: '\f4cd'; +} + +.bi-pentagon::before { + content: '\f4ce'; +} + +.bi-people-fill::before { + content: '\f4cf'; +} + +.bi-people::before { + content: '\f4d0'; +} + +.bi-percent::before { + content: '\f4d1'; +} + +.bi-person-badge-fill::before { + content: '\f4d2'; +} + +.bi-person-badge::before { + content: '\f4d3'; +} + +.bi-person-bounding-box::before { + content: '\f4d4'; +} + +.bi-person-check-fill::before { + content: '\f4d5'; +} + +.bi-person-check::before { + content: '\f4d6'; +} + +.bi-person-circle::before { + content: '\f4d7'; +} + +.bi-person-dash-fill::before { + content: '\f4d8'; +} + +.bi-person-dash::before { + content: '\f4d9'; +} + +.bi-person-fill::before { + content: '\f4da'; +} + +.bi-person-lines-fill::before { + content: '\f4db'; +} + +.bi-person-plus-fill::before { + content: '\f4dc'; +} + +.bi-person-plus::before { + content: '\f4dd'; +} + +.bi-person-square::before { + content: '\f4de'; +} + +.bi-person-x-fill::before { + content: '\f4df'; +} + +.bi-person-x::before { + content: '\f4e0'; +} + +.bi-person::before { + content: '\f4e1'; +} + +.bi-phone-fill::before { + content: '\f4e2'; +} + +.bi-phone-landscape-fill::before { + content: '\f4e3'; +} + +.bi-phone-landscape::before { + content: '\f4e4'; +} + +.bi-phone-vibrate-fill::before { + content: '\f4e5'; +} + +.bi-phone-vibrate::before { + content: '\f4e6'; +} + +.bi-phone::before { + content: '\f4e7'; +} + +.bi-pie-chart-fill::before { + content: '\f4e8'; +} + +.bi-pie-chart::before { + content: '\f4e9'; +} + +.bi-pin-angle-fill::before { + content: '\f4ea'; +} + +.bi-pin-angle::before { + content: '\f4eb'; +} + +.bi-pin-fill::before { + content: '\f4ec'; +} + +.bi-pin::before { + content: '\f4ed'; +} + +.bi-pip-fill::before { + content: '\f4ee'; +} + +.bi-pip::before { + content: '\f4ef'; +} + +.bi-play-btn-fill::before { + content: '\f4f0'; +} + +.bi-play-btn::before { + content: '\f4f1'; +} + +.bi-play-circle-fill::before { + content: '\f4f2'; +} + +.bi-play-circle::before { + content: '\f4f3'; +} + +.bi-play-fill::before { + content: '\f4f4'; +} + +.bi-play::before { + content: '\f4f5'; +} + +.bi-plug-fill::before { + content: '\f4f6'; +} + +.bi-plug::before { + content: '\f4f7'; +} + +.bi-plus-circle-dotted::before { + content: '\f4f8'; +} + +.bi-plus-circle-fill::before { + content: '\f4f9'; +} + +.bi-plus-circle::before { + content: '\f4fa'; +} + +.bi-plus-square-dotted::before { + content: '\f4fb'; +} + +.bi-plus-square-fill::before { + content: '\f4fc'; +} + +.bi-plus-square::before { + content: '\f4fd'; +} + +.bi-plus::before { + content: '\f4fe'; +} + +.bi-power::before { + content: '\f4ff'; +} + +.bi-printer-fill::before { + content: '\f500'; +} + +.bi-printer::before { + content: '\f501'; +} + +.bi-puzzle-fill::before { + content: '\f502'; +} + +.bi-puzzle::before { + content: '\f503'; +} + +.bi-question-circle-fill::before { + content: '\f504'; +} + +.bi-question-circle::before { + content: '\f505'; +} + +.bi-question-diamond-fill::before { + content: '\f506'; +} + +.bi-question-diamond::before { + content: '\f507'; +} + +.bi-question-octagon-fill::before { + content: '\f508'; +} + +.bi-question-octagon::before { + content: '\f509'; +} + +.bi-question-square-fill::before { + content: '\f50a'; +} + +.bi-question-square::before { + content: '\f50b'; +} + +.bi-question::before { + content: '\f50c'; +} + +.bi-rainbow::before { + content: '\f50d'; +} + +.bi-receipt-cutoff::before { + content: '\f50e'; +} + +.bi-receipt::before { + content: '\f50f'; +} + +.bi-reception-0::before { + content: '\f510'; +} + +.bi-reception-1::before { + content: '\f511'; +} + +.bi-reception-2::before { + content: '\f512'; +} + +.bi-reception-3::before { + content: '\f513'; +} + +.bi-reception-4::before { + content: '\f514'; +} + +.bi-record-btn-fill::before { + content: '\f515'; +} + +.bi-record-btn::before { + content: '\f516'; +} + +.bi-record-circle-fill::before { + content: '\f517'; +} + +.bi-record-circle::before { + content: '\f518'; +} + +.bi-record-fill::before { + content: '\f519'; +} + +.bi-record::before { + content: '\f51a'; +} + +.bi-record2-fill::before { + content: '\f51b'; +} + +.bi-record2::before { + content: '\f51c'; +} + +.bi-reply-all-fill::before { + content: '\f51d'; +} + +.bi-reply-all::before { + content: '\f51e'; +} + +.bi-reply-fill::before { + content: '\f51f'; +} + +.bi-reply::before { + content: '\f520'; +} + +.bi-rss-fill::before { + content: '\f521'; +} + +.bi-rss::before { + content: '\f522'; +} + +.bi-rulers::before { + content: '\f523'; +} + +.bi-save-fill::before { + content: '\f524'; +} + +.bi-save::before { + content: '\f525'; +} + +.bi-save2-fill::before { + content: '\f526'; +} + +.bi-save2::before { + content: '\f527'; +} + +.bi-scissors::before { + content: '\f528'; +} + +.bi-screwdriver::before { + content: '\f529'; +} + +.bi-search::before { + content: '\f52a'; +} + +.bi-segmented-nav::before { + content: '\f52b'; +} + +.bi-server::before { + content: '\f52c'; +} + +.bi-share-fill::before { + content: '\f52d'; +} + +.bi-share::before { + content: '\f52e'; +} + +.bi-shield-check::before { + content: '\f52f'; +} + +.bi-shield-exclamation::before { + content: '\f530'; +} + +.bi-shield-fill-check::before { + content: '\f531'; +} + +.bi-shield-fill-exclamation::before { + content: '\f532'; +} + +.bi-shield-fill-minus::before { + content: '\f533'; +} + +.bi-shield-fill-plus::before { + content: '\f534'; +} + +.bi-shield-fill-x::before { + content: '\f535'; +} + +.bi-shield-fill::before { + content: '\f536'; +} + +.bi-shield-lock-fill::before { + content: '\f537'; +} + +.bi-shield-lock::before { + content: '\f538'; +} + +.bi-shield-minus::before { + content: '\f539'; +} + +.bi-shield-plus::before { + content: '\f53a'; +} + +.bi-shield-shaded::before { + content: '\f53b'; +} + +.bi-shield-slash-fill::before { + content: '\f53c'; +} + +.bi-shield-slash::before { + content: '\f53d'; +} + +.bi-shield-x::before { + content: '\f53e'; +} + +.bi-shield::before { + content: '\f53f'; +} + +.bi-shift-fill::before { + content: '\f540'; +} + +.bi-shift::before { + content: '\f541'; +} + +.bi-shop-window::before { + content: '\f542'; +} + +.bi-shop::before { + content: '\f543'; +} + +.bi-shuffle::before { + content: '\f544'; +} + +.bi-signpost-2-fill::before { + content: '\f545'; +} + +.bi-signpost-2::before { + content: '\f546'; +} + +.bi-signpost-fill::before { + content: '\f547'; +} + +.bi-signpost-split-fill::before { + content: '\f548'; +} + +.bi-signpost-split::before { + content: '\f549'; +} + +.bi-signpost::before { + content: '\f54a'; +} + +.bi-sim-fill::before { + content: '\f54b'; +} + +.bi-sim::before { + content: '\f54c'; +} + +.bi-skip-backward-btn-fill::before { + content: '\f54d'; +} + +.bi-skip-backward-btn::before { + content: '\f54e'; +} + +.bi-skip-backward-circle-fill::before { + content: '\f54f'; +} + +.bi-skip-backward-circle::before { + content: '\f550'; +} + +.bi-skip-backward-fill::before { + content: '\f551'; +} + +.bi-skip-backward::before { + content: '\f552'; +} + +.bi-skip-end-btn-fill::before { + content: '\f553'; +} + +.bi-skip-end-btn::before { + content: '\f554'; +} + +.bi-skip-end-circle-fill::before { + content: '\f555'; +} + +.bi-skip-end-circle::before { + content: '\f556'; +} + +.bi-skip-end-fill::before { + content: '\f557'; +} + +.bi-skip-end::before { + content: '\f558'; +} + +.bi-skip-forward-btn-fill::before { + content: '\f559'; +} + +.bi-skip-forward-btn::before { + content: '\f55a'; +} + +.bi-skip-forward-circle-fill::before { + content: '\f55b'; +} + +.bi-skip-forward-circle::before { + content: '\f55c'; +} + +.bi-skip-forward-fill::before { + content: '\f55d'; +} + +.bi-skip-forward::before { + content: '\f55e'; +} + +.bi-skip-start-btn-fill::before { + content: '\f55f'; +} + +.bi-skip-start-btn::before { + content: '\f560'; +} + +.bi-skip-start-circle-fill::before { + content: '\f561'; +} + +.bi-skip-start-circle::before { + content: '\f562'; +} + +.bi-skip-start-fill::before { + content: '\f563'; +} + +.bi-skip-start::before { + content: '\f564'; +} + +.bi-slack::before { + content: '\f565'; +} + +.bi-slash-circle-fill::before { + content: '\f566'; +} + +.bi-slash-circle::before { + content: '\f567'; +} + +.bi-slash-square-fill::before { + content: '\f568'; +} + +.bi-slash-square::before { + content: '\f569'; +} + +.bi-slash::before { + content: '\f56a'; +} + +.bi-sliders::before { + content: '\f56b'; +} + +.bi-smartwatch::before { + content: '\f56c'; +} + +.bi-snow::before { + content: '\f56d'; +} + +.bi-snow2::before { + content: '\f56e'; +} + +.bi-snow3::before { + content: '\f56f'; +} + +.bi-sort-alpha-down-alt::before { + content: '\f570'; +} + +.bi-sort-alpha-down::before { + content: '\f571'; +} + +.bi-sort-alpha-up-alt::before { + content: '\f572'; +} + +.bi-sort-alpha-up::before { + content: '\f573'; +} + +.bi-sort-down-alt::before { + content: '\f574'; +} + +.bi-sort-down::before { + content: '\f575'; +} + +.bi-sort-numeric-down-alt::before { + content: '\f576'; +} + +.bi-sort-numeric-down::before { + content: '\f577'; +} + +.bi-sort-numeric-up-alt::before { + content: '\f578'; +} + +.bi-sort-numeric-up::before { + content: '\f579'; +} + +.bi-sort-up-alt::before { + content: '\f57a'; +} + +.bi-sort-up::before { + content: '\f57b'; +} + +.bi-soundwave::before { + content: '\f57c'; +} + +.bi-speaker-fill::before { + content: '\f57d'; +} + +.bi-speaker::before { + content: '\f57e'; +} + +.bi-speedometer::before { + content: '\f57f'; +} + +.bi-speedometer2::before { + content: '\f580'; +} + +.bi-spellcheck::before { + content: '\f581'; +} + +.bi-square-fill::before { + content: '\f582'; +} + +.bi-square-half::before { + content: '\f583'; +} + +.bi-square::before { + content: '\f584'; +} + +.bi-stack::before { + content: '\f585'; +} + +.bi-star-fill::before { + content: '\f586'; +} + +.bi-star-half::before { + content: '\f587'; +} + +.bi-star::before { + content: '\f588'; +} + +.bi-stars::before { + content: '\f589'; +} + +.bi-stickies-fill::before { + content: '\f58a'; +} + +.bi-stickies::before { + content: '\f58b'; +} + +.bi-sticky-fill::before { + content: '\f58c'; +} + +.bi-sticky::before { + content: '\f58d'; +} + +.bi-stop-btn-fill::before { + content: '\f58e'; +} + +.bi-stop-btn::before { + content: '\f58f'; +} + +.bi-stop-circle-fill::before { + content: '\f590'; +} + +.bi-stop-circle::before { + content: '\f591'; +} + +.bi-stop-fill::before { + content: '\f592'; +} + +.bi-stop::before { + content: '\f593'; +} + +.bi-stoplights-fill::before { + content: '\f594'; +} + +.bi-stoplights::before { + content: '\f595'; +} + +.bi-stopwatch-fill::before { + content: '\f596'; +} + +.bi-stopwatch::before { + content: '\f597'; +} + +.bi-subtract::before { + content: '\f598'; +} + +.bi-suit-club-fill::before { + content: '\f599'; +} + +.bi-suit-club::before { + content: '\f59a'; +} + +.bi-suit-diamond-fill::before { + content: '\f59b'; +} + +.bi-suit-diamond::before { + content: '\f59c'; +} + +.bi-suit-heart-fill::before { + content: '\f59d'; +} + +.bi-suit-heart::before { + content: '\f59e'; +} + +.bi-suit-spade-fill::before { + content: '\f59f'; +} + +.bi-suit-spade::before { + content: '\f5a0'; +} + +.bi-sun-fill::before { + content: '\f5a1'; +} + +.bi-sun::before { + content: '\f5a2'; +} + +.bi-sunglasses::before { + content: '\f5a3'; +} + +.bi-sunrise-fill::before { + content: '\f5a4'; +} + +.bi-sunrise::before { + content: '\f5a5'; +} + +.bi-sunset-fill::before { + content: '\f5a6'; +} + +.bi-sunset::before { + content: '\f5a7'; +} + +.bi-symmetry-horizontal::before { + content: '\f5a8'; +} + +.bi-symmetry-vertical::before { + content: '\f5a9'; +} + +.bi-table::before { + content: '\f5aa'; +} + +.bi-tablet-fill::before { + content: '\f5ab'; +} + +.bi-tablet-landscape-fill::before { + content: '\f5ac'; +} + +.bi-tablet-landscape::before { + content: '\f5ad'; +} + +.bi-tablet::before { + content: '\f5ae'; +} + +.bi-tag-fill::before { + content: '\f5af'; +} + +.bi-tag::before { + content: '\f5b0'; +} + +.bi-tags-fill::before { + content: '\f5b1'; +} + +.bi-tags::before { + content: '\f5b2'; +} + +.bi-telegram::before { + content: '\f5b3'; +} + +.bi-telephone-fill::before { + content: '\f5b4'; +} + +.bi-telephone-forward-fill::before { + content: '\f5b5'; +} + +.bi-telephone-forward::before { + content: '\f5b6'; +} + +.bi-telephone-inbound-fill::before { + content: '\f5b7'; +} + +.bi-telephone-inbound::before { + content: '\f5b8'; +} + +.bi-telephone-minus-fill::before { + content: '\f5b9'; +} + +.bi-telephone-minus::before { + content: '\f5ba'; +} + +.bi-telephone-outbound-fill::before { + content: '\f5bb'; +} + +.bi-telephone-outbound::before { + content: '\f5bc'; +} + +.bi-telephone-plus-fill::before { + content: '\f5bd'; +} + +.bi-telephone-plus::before { + content: '\f5be'; +} + +.bi-telephone-x-fill::before { + content: '\f5bf'; +} + +.bi-telephone-x::before { + content: '\f5c0'; +} + +.bi-telephone::before { + content: '\f5c1'; +} + +.bi-terminal-fill::before { + content: '\f5c2'; +} + +.bi-terminal::before { + content: '\f5c3'; +} + +.bi-text-center::before { + content: '\f5c4'; +} + +.bi-text-indent-left::before { + content: '\f5c5'; +} + +.bi-text-indent-right::before { + content: '\f5c6'; +} + +.bi-text-left::before { + content: '\f5c7'; +} + +.bi-text-paragraph::before { + content: '\f5c8'; +} + +.bi-text-right::before { + content: '\f5c9'; +} + +.bi-textarea-resize::before { + content: '\f5ca'; +} + +.bi-textarea-t::before { + content: '\f5cb'; +} + +.bi-textarea::before { + content: '\f5cc'; +} + +.bi-thermometer-half::before { + content: '\f5cd'; +} + +.bi-thermometer-high::before { + content: '\f5ce'; +} + +.bi-thermometer-low::before { + content: '\f5cf'; +} + +.bi-thermometer-snow::before { + content: '\f5d0'; +} + +.bi-thermometer-sun::before { + content: '\f5d1'; +} + +.bi-thermometer::before { + content: '\f5d2'; +} + +.bi-three-dots-vertical::before { + content: '\f5d3'; +} + +.bi-three-dots::before { + content: '\f5d4'; +} + +.bi-toggle-off::before { + content: '\f5d5'; +} + +.bi-toggle-on::before { + content: '\f5d6'; +} + +.bi-toggle2-off::before { + content: '\f5d7'; +} + +.bi-toggle2-on::before { + content: '\f5d8'; +} + +.bi-toggles::before { + content: '\f5d9'; +} + +.bi-toggles2::before { + content: '\f5da'; +} + +.bi-tools::before { + content: '\f5db'; +} + +.bi-tornado::before { + content: '\f5dc'; +} + +.bi-trash-fill::before { + content: '\f5dd'; +} + +.bi-trash::before { + content: '\f5de'; +} + +.bi-trash2-fill::before { + content: '\f5df'; +} + +.bi-trash2::before { + content: '\f5e0'; +} + +.bi-tree-fill::before { + content: '\f5e1'; +} + +.bi-tree::before { + content: '\f5e2'; +} + +.bi-triangle-fill::before { + content: '\f5e3'; +} + +.bi-triangle-half::before { + content: '\f5e4'; +} + +.bi-triangle::before { + content: '\f5e5'; +} + +.bi-trophy-fill::before { + content: '\f5e6'; +} + +.bi-trophy::before { + content: '\f5e7'; +} + +.bi-tropical-storm::before { + content: '\f5e8'; +} + +.bi-truck-flatbed::before { + content: '\f5e9'; +} + +.bi-truck::before { + content: '\f5ea'; +} + +.bi-tsunami::before { + content: '\f5eb'; +} + +.bi-tv-fill::before { + content: '\f5ec'; +} + +.bi-tv::before { + content: '\f5ed'; +} + +.bi-twitch::before { + content: '\f5ee'; +} + +.bi-twitter::before { + content: '\f5ef'; +} + +.bi-type-bold::before { + content: '\f5f0'; +} + +.bi-type-h1::before { + content: '\f5f1'; +} + +.bi-type-h2::before { + content: '\f5f2'; +} + +.bi-type-h3::before { + content: '\f5f3'; +} + +.bi-type-italic::before { + content: '\f5f4'; +} + +.bi-type-strikethrough::before { + content: '\f5f5'; +} + +.bi-type-underline::before { + content: '\f5f6'; +} + +.bi-type::before { + content: '\f5f7'; +} + +.bi-ui-checks-grid::before { + content: '\f5f8'; +} + +.bi-ui-checks::before { + content: '\f5f9'; +} + +.bi-ui-radios-grid::before { + content: '\f5fa'; +} + +.bi-ui-radios::before { + content: '\f5fb'; +} + +.bi-umbrella-fill::before { + content: '\f5fc'; +} + +.bi-umbrella::before { + content: '\f5fd'; +} + +.bi-union::before { + content: '\f5fe'; +} + +.bi-unlock-fill::before { + content: '\f5ff'; +} + +.bi-unlock::before { + content: '\f600'; +} + +.bi-upc-scan::before { + content: '\f601'; +} + +.bi-upc::before { + content: '\f602'; +} + +.bi-upload::before { + content: '\f603'; +} + +.bi-vector-pen::before { + content: '\f604'; +} + +.bi-view-list::before { + content: '\f605'; +} + +.bi-view-stacked::before { + content: '\f606'; +} + +.bi-vinyl-fill::before { + content: '\f607'; +} + +.bi-vinyl::before { + content: '\f608'; +} + +.bi-voicemail::before { + content: '\f609'; +} + +.bi-volume-down-fill::before { + content: '\f60a'; +} + +.bi-volume-down::before { + content: '\f60b'; +} + +.bi-volume-mute-fill::before { + content: '\f60c'; +} + +.bi-volume-mute::before { + content: '\f60d'; +} + +.bi-volume-off-fill::before { + content: '\f60e'; +} + +.bi-volume-off::before { + content: '\f60f'; +} + +.bi-volume-up-fill::before { + content: '\f610'; +} + +.bi-volume-up::before { + content: '\f611'; +} + +.bi-vr::before { + content: '\f612'; +} + +.bi-wallet-fill::before { + content: '\f613'; +} + +.bi-wallet::before { + content: '\f614'; +} + +.bi-wallet2::before { + content: '\f615'; +} + +.bi-watch::before { + content: '\f616'; +} + +.bi-water::before { + content: '\f617'; +} + +.bi-whatsapp::before { + content: '\f618'; +} + +.bi-wifi-1::before { + content: '\f619'; +} + +.bi-wifi-2::before { + content: '\f61a'; +} + +.bi-wifi-off::before { + content: '\f61b'; +} + +.bi-wifi::before { + content: '\f61c'; +} + +.bi-wind::before { + content: '\f61d'; +} + +.bi-window-dock::before { + content: '\f61e'; +} + +.bi-window-sidebar::before { + content: '\f61f'; +} + +.bi-window::before { + content: '\f620'; +} + +.bi-wrench::before { + content: '\f621'; +} + +.bi-x-circle-fill::before { + content: '\f622'; +} + +.bi-x-circle::before { + content: '\f623'; +} + +.bi-x-diamond-fill::before { + content: '\f624'; +} + +.bi-x-diamond::before { + content: '\f625'; +} + +.bi-x-octagon-fill::before { + content: '\f626'; +} + +.bi-x-octagon::before { + content: '\f627'; +} + +.bi-x-square-fill::before { + content: '\f628'; +} + +.bi-x-square::before { + content: '\f629'; +} + +.bi-x::before { + content: '\f62a'; +} + +.bi-youtube::before { + content: '\f62b'; +} + +.bi-zoom-in::before { + content: '\f62c'; +} + +.bi-zoom-out::before { + content: '\f62d'; +} + +.bi-bank::before { + content: '\f62e'; +} + +.bi-bank2::before { + content: '\f62f'; +} + +.bi-bell-slash-fill::before { + content: '\f630'; +} + +.bi-bell-slash::before { + content: '\f631'; +} + +.bi-cash-coin::before { + content: '\f632'; +} + +.bi-check-lg::before { + content: '\f633'; +} + +.bi-coin::before { + content: '\f634'; +} + +.bi-currency-bitcoin::before { + content: '\f635'; +} + +.bi-currency-dollar::before { + content: '\f636'; +} + +.bi-currency-euro::before { + content: '\f637'; +} + +.bi-currency-exchange::before { + content: '\f638'; +} + +.bi-currency-pound::before { + content: '\f639'; +} + +.bi-currency-yen::before { + content: '\f63a'; +} + +.bi-dash-lg::before { + content: '\f63b'; +} + +.bi-exclamation-lg::before { + content: '\f63c'; +} + +.bi-file-earmark-pdf-fill::before { + content: '\f63d'; +} + +.bi-file-earmark-pdf::before { + content: '\f63e'; +} + +.bi-file-pdf-fill::before { + content: '\f63f'; +} + +.bi-file-pdf::before { + content: '\f640'; +} + +.bi-gender-ambiguous::before { + content: '\f641'; +} + +.bi-gender-female::before { + content: '\f642'; +} + +.bi-gender-male::before { + content: '\f643'; +} + +.bi-gender-trans::before { + content: '\f644'; +} + +.bi-headset-vr::before { + content: '\f645'; +} + +.bi-info-lg::before { + content: '\f646'; +} + +.bi-mastodon::before { + content: '\f647'; +} + +.bi-messenger::before { + content: '\f648'; +} + +.bi-piggy-bank-fill::before { + content: '\f649'; +} + +.bi-piggy-bank::before { + content: '\f64a'; +} + +.bi-pin-map-fill::before { + content: '\f64b'; +} + +.bi-pin-map::before { + content: '\f64c'; +} + +.bi-plus-lg::before { + content: '\f64d'; +} + +.bi-question-lg::before { + content: '\f64e'; +} + +.bi-recycle::before { + content: '\f64f'; +} + +.bi-reddit::before { + content: '\f650'; +} + +.bi-safe-fill::before { + content: '\f651'; +} + +.bi-safe2-fill::before { + content: '\f652'; +} + +.bi-safe2::before { + content: '\f653'; +} + +.bi-sd-card-fill::before { + content: '\f654'; +} + +.bi-sd-card::before { + content: '\f655'; +} + +.bi-skype::before { + content: '\f656'; +} + +.bi-slash-lg::before { + content: '\f657'; +} + +.bi-translate::before { + content: '\f658'; +} + +.bi-x-lg::before { + content: '\f659'; +} + +.bi-safe::before { + content: '\f65a'; +} diff --git a/src/assets/css/bootstrap.css b/src/assets/css/bootstrap.css new file mode 100644 index 0000000..4a94237 --- /dev/null +++ b/src/assets/css/bootstrap.css @@ -0,0 +1,11887 @@ + + +@charset "UTF-8"; +/*! + * Bootstrap v5.1.3 (https://getbootstrap.com/) + * Copyright 2011-2021 The Bootstrap Authors + * Copyright 2011-2021 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */ +:root { + --bs-blue: #0d6efd; + --bs-indigo: #6610f2; + --bs-purple: #6f42c1; + --bs-pink: #d63384; + --bs-red: #dc3545; + --bs-orange: #fd7e14; + --bs-yellow: #ffc107; + --bs-green: #198754; + --bs-teal: #20c997; + --bs-cyan: #0dcaf0; + --bs-white: #fff; + --bs-gray: #6c757d; + --bs-gray-dark: #343a40; + --bs-gray-100: #f8f9fa; + --bs-gray-200: #e9ecef; + --bs-gray-300: #dee2e6; + --bs-gray-400: #ced4da; + --bs-gray-500: #adb5bd; + --bs-gray-600: #6c757d; + --bs-gray-700: #495057; + --bs-gray-800: #343a40; + --bs-gray-900: #212529; + --bs-primary: #0d6efd; + --bs-secondary: #6c757d; + --bs-success: #198754; + --bs-info: #0dcaf0; + --bs-warning: #ffc107; + --bs-danger: #dc3545; + --bs-light: #f8f9fa; + --bs-dark: #212529; + --bs-primary-rgb: 13, 110, 253; + --bs-secondary-rgb: 108, 117, 125; + --bs-success-rgb: 25, 135, 84; + --bs-info-rgb: 13, 202, 240; + --bs-warning-rgb: 255, 193, 7; + --bs-danger-rgb: 220, 53, 69; + --bs-light-rgb: 248, 249, 250; + --bs-dark-rgb: 33, 37, 41; + --bs-white-rgb: 255, 255, 255; + --bs-black-rgb: 0, 0, 0; + --bs-body-color-rgb: 33, 37, 41; + --bs-body-bg-rgb: 255, 255, 255; + --bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + --bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; + --bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0)); + --bs-body-font-family: var(--bs-font-sans-serif); + --bs-body-font-size: 1rem; + --bs-body-font-weight: 400; + --bs-body-line-height: 1.5; + --bs-body-color: #212529; + --bs-body-bg: #fff; +} + +*, +*::before, +*::after { + box-sizing: border-box; +} + +@media (prefers-reduced-motion: no-preference) { + :root { + scroll-behavior: smooth; + } +} + +body { + margin: 0; + font-family: var(--bs-body-font-family); + font-size: var(--bs-body-font-size); + font-weight: var(--bs-body-font-weight); + line-height: var(--bs-body-line-height); + color: var(--bs-body-color); + text-align: var(--bs-body-text-align); + background-color: var(--bs-body-bg); + -webkit-text-size-adjust: 100%; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} + +hr { + margin: 1rem 0; + color: inherit; + background-color: currentColor; + border: 0; + opacity: 0.25; +} + +hr:not([size]) { + height: 1px; +} + +h6, .h6, h5, .h5, h4, .h4, h3, .h3, h2, .h2, h1, .h1 { + margin-top: 0; + margin-bottom: 0.5rem; + font-weight: 500; + line-height: 1.2; +} + +h1, .h1 { + font-size: calc(1.375rem + 1.5vw); +} + +@media (min-width: 1200px) { + h1, .h1 { + font-size: 2.5rem; + } +} + +h2, .h2 { + font-size: calc(1.325rem + 0.9vw); +} + +@media (min-width: 1200px) { + h2, .h2 { + font-size: 2rem; + } +} + +h3, .h3 { + font-size: calc(1.3rem + 0.6vw); +} + +@media (min-width: 1200px) { + h3, .h3 { + font-size: 1.75rem; + } +} + +h4, .h4 { + font-size: calc(1.275rem + 0.3vw); +} + +@media (min-width: 1200px) { + h4, .h4 { + font-size: 1.5rem; + } +} + +h5, .h5 { + font-size: 1.25rem; +} + +h6, .h6 { + font-size: 1rem; +} + +p { + margin-top: 0; + margin-bottom: 1rem; +} + +abbr[title], +abbr[data-bs-original-title] { + -webkit-text-decoration: underline dotted; + text-decoration: underline dotted; + cursor: help; + -webkit-text-decoration-skip-ink: none; + text-decoration-skip-ink: none; +} + +address { + margin-bottom: 1rem; + font-style: normal; + line-height: inherit; +} + +ol, +ul { + padding-left: 2rem; +} + +ol, +ul, +dl { + margin-top: 0; + margin-bottom: 1rem; +} + +ol ol, +ul ul, +ol ul, +ul ol { + margin-bottom: 0; +} + +dt { + font-weight: 700; +} + +dd { + margin-bottom: 0.5rem; + margin-left: 0; +} + +blockquote { + margin: 0 0 1rem; +} + +b, +strong { + font-weight: bolder; +} + +small, .small { + font-size: 0.875em; +} + +mark, .mark { + padding: 0.2em; + background-color: #fcf8e3; +} + +sub, +sup { + position: relative; + font-size: 0.75em; + line-height: 0; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +a { + color: #0d6efd; + text-decoration: underline; +} + +a:hover { + color: #0a58ca; +} + +a:not([href]):not([class]), a:not([href]):not([class]):hover { + color: inherit; + text-decoration: none; +} + +pre, +code, +kbd, +samp { + font-family: var(--bs-font-monospace); + font-size: 1em; + direction: ltr /* rtl:ignore */; + unicode-bidi: bidi-override; +} + +pre { + display: block; + margin-top: 0; + margin-bottom: 1rem; + overflow: auto; + font-size: 0.875em; +} + +pre code { + font-size: inherit; + color: inherit; + word-break: normal; +} + +code { + font-size: 0.875em; + color: #d63384; + word-wrap: break-word; +} + +a > code { + color: inherit; +} + +kbd { + padding: 0.2rem 0.4rem; + font-size: 0.875em; + color: #fff; + background-color: #212529; + border-radius: 0.2rem; +} + +kbd kbd { + padding: 0; + font-size: 1em; + font-weight: 700; +} + +figure { + margin: 0 0 1rem; +} + +img, +svg { + vertical-align: middle; +} + +table { + caption-side: bottom; + border-collapse: collapse; +} + +caption { + padding-top: 0.5rem; + padding-bottom: 0.5rem; + color: #6c757d; + text-align: left; +} + +th { + text-align: inherit; + text-align: -webkit-match-parent; +} + +thead, +tbody, +tfoot, +tr, +td, +th { + border-color: inherit; + border-style: solid; + border-width: 0; +} + +label { + display: inline-block; +} + +button { + border-radius: 0; +} + +button:focus:not(:focus-visible) { + outline: 0; +} + +input, +button, +select, +optgroup, +textarea { + margin: 0; + font-family: inherit; + font-size: inherit; + line-height: inherit; +} + +button, +select { + text-transform: none; +} + +[role=button] { + cursor: pointer; +} + +select { + word-wrap: normal; +} + +select:disabled { + opacity: 1; +} + +[list]::-webkit-calendar-picker-indicator { + display: none; +} + +button, +[type=button], +[type=reset], +[type=submit] { + -webkit-appearance: button; +} + +button:not(:disabled), +[type=button]:not(:disabled), +[type=reset]:not(:disabled), +[type=submit]:not(:disabled) { + cursor: pointer; +} + +::-moz-focus-inner { + padding: 0; + border-style: none; +} + +textarea { + resize: vertical; +} + +fieldset { + min-width: 0; + padding: 0; + margin: 0; + border: 0; +} + +legend { + float: left; + width: 100%; + padding: 0; + margin-bottom: 0.5rem; + font-size: calc(1.275rem + 0.3vw); + line-height: inherit; +} + +@media (min-width: 1200px) { + legend { + font-size: 1.5rem; + } +} + +legend + * { + clear: left; +} + +::-webkit-datetime-edit-fields-wrapper, +::-webkit-datetime-edit-text, +::-webkit-datetime-edit-minute, +::-webkit-datetime-edit-hour-field, +::-webkit-datetime-edit-day-field, +::-webkit-datetime-edit-month-field, +::-webkit-datetime-edit-year-field { + padding: 0; +} + +::-webkit-inner-spin-button { + height: auto; +} + +[type=search] { + outline-offset: -2px; + -webkit-appearance: textfield; +} + +/* rtl:raw: +[type="tel"], +[type="url"], +[type="email"], +[type="number"] { + direction: ltr; +} +*/ +::-webkit-search-decoration { + -webkit-appearance: none; +} + +::-webkit-color-swatch-wrapper { + padding: 0; +} + +::-webkit-file-upload-button { + font: inherit; +} + +::file-selector-button { + font: inherit; +} + +::-webkit-file-upload-button { + font: inherit; + -webkit-appearance: button; +} + +output { + display: inline-block; +} + +iframe { + border: 0; +} + +summary { + display: list-item; + cursor: pointer; +} + +progress { + vertical-align: baseline; +} + +[hidden] { + display: none !important; +} + +.lead { + font-size: 1.25rem; + font-weight: 300; +} + +.display-1 { + font-size: calc(1.625rem + 4.5vw); + font-weight: 300; + line-height: 1.2; +} + +@media (min-width: 1200px) { + .display-1 { + font-size: 5rem; + } +} + +.display-2 { + font-size: calc(1.575rem + 3.9vw); + font-weight: 300; + line-height: 1.2; +} + +@media (min-width: 1200px) { + .display-2 { + font-size: 4.5rem; + } +} + +.display-3 { + font-size: calc(1.525rem + 3.3vw); + font-weight: 300; + line-height: 1.2; +} + +@media (min-width: 1200px) { + .display-3 { + font-size: 4rem; + } +} + +.display-4 { + font-size: calc(1.475rem + 2.7vw); + font-weight: 300; + line-height: 1.2; +} + +@media (min-width: 1200px) { + .display-4 { + font-size: 3.5rem; + } +} + +.display-5 { + font-size: calc(1.425rem + 2.1vw); + font-weight: 300; + line-height: 1.2; +} + +@media (min-width: 1200px) { + .display-5 { + font-size: 3rem; + } +} + +.display-6 { + font-size: calc(1.375rem + 1.5vw); + font-weight: 300; + line-height: 1.2; +} + +@media (min-width: 1200px) { + .display-6 { + font-size: 2.5rem; + } +} + +.list-unstyled { + padding-left: 0; + list-style: none; +} + +.list-inline { + padding-left: 0; + list-style: none; +} + +.list-inline-item { + display: inline-block; +} + +.list-inline-item:not(:last-child) { + margin-right: 0.5rem; +} + +.initialism { + font-size: 0.875em; + text-transform: uppercase; +} + +.blockquote { + margin-bottom: 1rem; + font-size: 1.25rem; +} + +.blockquote > :last-child { + margin-bottom: 0; +} + +.blockquote-footer { + margin-top: -1rem; + margin-bottom: 1rem; + font-size: 0.875em; + color: #6c757d; +} + +.blockquote-footer::before { + content: "— "; +} + +.img-fluid { + max-width: 100%; + height: auto; +} + +.img-thumbnail { + padding: 0.25rem; + background-color: #fff; + border: 1px solid #dee2e6; + border-radius: 0.25rem; + max-width: 100%; + height: auto; +} + +.figure { + display: inline-block; +} + +.figure-img { + margin-bottom: 0.5rem; + line-height: 1; +} + +.figure-caption { + font-size: 0.875em; + color: #6c757d; +} + +.container, +.container-fluid, +.container-xxl, +.container-xl, +.container-lg, +.container-md, +.container-sm { + width: 100%; + padding-right: var(--bs-gutter-x, 0.75rem); + padding-left: var(--bs-gutter-x, 0.75rem); + margin-right: auto; + margin-left: auto; +} + +@media (min-width: 576px) { + .container-sm, .container { + max-width: 540px; + } +} + +@media (min-width: 768px) { + .container-md, .container-sm, .container { + max-width: 720px; + } +} + +@media (min-width: 992px) { + .container-lg, .container-md, .container-sm, .container { + max-width: 960px; + } +} + +@media (min-width: 1200px) { + .container-xl, .container-lg, .container-md, .container-sm, .container { + max-width: 1140px; + } +} + +@media (min-width: 1400px) { + .container-xxl, .container-xl, .container-lg, .container-md, .container-sm, .container { + max-width: 1320px; + } +} + +.row { + --bs-gutter-x: 1.5rem; + --bs-gutter-y: 0; + display: flex; + flex-wrap: wrap; + margin-top: calc(-1 * var(--bs-gutter-y)); + margin-right: calc(-0.5 * var(--bs-gutter-x)); + margin-left: calc(-0.5 * var(--bs-gutter-x)); +} + +.row > * { + flex-shrink: 0; + width: 100%; + max-width: 100%; + padding-right: calc(var(--bs-gutter-x) * 0.5); + padding-left: calc(var(--bs-gutter-x) * 0.5); + margin-top: var(--bs-gutter-y); +} + +.col { + flex: 1 0 0%; +} + +.row-cols-auto > * { + flex: 0 0 auto; + width: auto; +} + +.row-cols-1 > * { + flex: 0 0 auto; + width: 100%; +} + +.row-cols-2 > * { + flex: 0 0 auto; + width: 50%; +} + +.row-cols-3 > * { + flex: 0 0 auto; + width: 33.3333333333%; +} + +.row-cols-4 > * { + flex: 0 0 auto; + width: 25%; +} + +.row-cols-5 > * { + flex: 0 0 auto; + width: 20%; +} + +.row-cols-6 > * { + flex: 0 0 auto; + width: 16.6666666667%; +} + +.col-auto { + flex: 0 0 auto; + width: auto; +} + +.col-1 { + flex: 0 0 auto; + width: 8.33333333%; +} + +.col-2 { + flex: 0 0 auto; + width: 16.66666667%; +} + +.col-3 { + flex: 0 0 auto; + width: 25%; +} + +.col-4 { + flex: 0 0 auto; + width: 33.33333333%; +} + +.col-5 { + flex: 0 0 auto; + width: 41.66666667%; +} + +.col-6 { + flex: 0 0 auto; + width: 50%; +} + +.col-7 { + flex: 0 0 auto; + width: 58.33333333%; +} + +.col-8 { + flex: 0 0 auto; + width: 66.66666667%; +} + +.col-9 { + flex: 0 0 auto; + width: 75%; +} + +.col-10 { + flex: 0 0 auto; + width: 83.33333333%; +} + +.col-11 { + flex: 0 0 auto; + width: 91.66666667%; +} + +.col-12 { + flex: 0 0 auto; + width: 100%; +} + +.offset-1 { + margin-left: 8.33333333%; +} + +.offset-2 { + margin-left: 16.66666667%; +} + +.offset-3 { + margin-left: 25%; +} + +.offset-4 { + margin-left: 33.33333333%; +} + +.offset-5 { + margin-left: 41.66666667%; +} + +.offset-6 { + margin-left: 50%; +} + +.offset-7 { + margin-left: 58.33333333%; +} + +.offset-8 { + margin-left: 66.66666667%; +} + +.offset-9 { + margin-left: 75%; +} + +.offset-10 { + margin-left: 83.33333333%; +} + +.offset-11 { + margin-left: 91.66666667%; +} + +.g-0, +.gx-0 { + --bs-gutter-x: 0; +} + +.g-0, +.gy-0 { + --bs-gutter-y: 0; +} + +.g-1, +.gx-1 { + --bs-gutter-x: 0.25rem; +} + +.g-1, +.gy-1 { + --bs-gutter-y: 0.25rem; +} + +.g-2, +.gx-2 { + --bs-gutter-x: 0.5rem; +} + +.g-2, +.gy-2 { + --bs-gutter-y: 0.5rem; +} + +.g-3, +.gx-3 { + --bs-gutter-x: 1rem; +} + +.g-3, +.gy-3 { + --bs-gutter-y: 1rem; +} + +.g-4, +.gx-4 { + --bs-gutter-x: 1.5rem; +} + +.g-4, +.gy-4 { + --bs-gutter-y: 1.5rem; +} + +.g-5, +.gx-5 { + --bs-gutter-x: 3rem; +} + +.g-5, +.gy-5 { + --bs-gutter-y: 3rem; +} + +@media (min-width: 576px) { + .col-sm { + flex: 1 0 0%; + } + + .row-cols-sm-auto > * { + flex: 0 0 auto; + width: auto; + } + + .row-cols-sm-1 > * { + flex: 0 0 auto; + width: 100%; + } + + .row-cols-sm-2 > * { + flex: 0 0 auto; + width: 50%; + } + + .row-cols-sm-3 > * { + flex: 0 0 auto; + width: 33.3333333333%; + } + + .row-cols-sm-4 > * { + flex: 0 0 auto; + width: 25%; + } + + .row-cols-sm-5 > * { + flex: 0 0 auto; + width: 20%; + } + + .row-cols-sm-6 > * { + flex: 0 0 auto; + width: 16.6666666667%; + } + + .col-sm-auto { + flex: 0 0 auto; + width: auto; + } + + .col-sm-1 { + flex: 0 0 auto; + width: 8.33333333%; + } + + .col-sm-2 { + flex: 0 0 auto; + width: 16.66666667%; + } + + .col-sm-3 { + flex: 0 0 auto; + width: 25%; + } + + .col-sm-4 { + flex: 0 0 auto; + width: 33.33333333%; + } + + .col-sm-5 { + flex: 0 0 auto; + width: 41.66666667%; + } + + .col-sm-6 { + flex: 0 0 auto; + width: 50%; + } + + .col-sm-7 { + flex: 0 0 auto; + width: 58.33333333%; + } + + .col-sm-8 { + flex: 0 0 auto; + width: 66.66666667%; + } + + .col-sm-9 { + flex: 0 0 auto; + width: 75%; + } + + .col-sm-10 { + flex: 0 0 auto; + width: 83.33333333%; + } + + .col-sm-11 { + flex: 0 0 auto; + width: 91.66666667%; + } + + .col-sm-12 { + flex: 0 0 auto; + width: 100%; + } + + .offset-sm-0 { + margin-left: 0; + } + + .offset-sm-1 { + margin-left: 8.33333333%; + } + + .offset-sm-2 { + margin-left: 16.66666667%; + } + + .offset-sm-3 { + margin-left: 25%; + } + + .offset-sm-4 { + margin-left: 33.33333333%; + } + + .offset-sm-5 { + margin-left: 41.66666667%; + } + + .offset-sm-6 { + margin-left: 50%; + } + + .offset-sm-7 { + margin-left: 58.33333333%; + } + + .offset-sm-8 { + margin-left: 66.66666667%; + } + + .offset-sm-9 { + margin-left: 75%; + } + + .offset-sm-10 { + margin-left: 83.33333333%; + } + + .offset-sm-11 { + margin-left: 91.66666667%; + } + + .g-sm-0, + .gx-sm-0 { + --bs-gutter-x: 0; + } + + .g-sm-0, + .gy-sm-0 { + --bs-gutter-y: 0; + } + + .g-sm-1, + .gx-sm-1 { + --bs-gutter-x: 0.25rem; + } + + .g-sm-1, + .gy-sm-1 { + --bs-gutter-y: 0.25rem; + } + + .g-sm-2, + .gx-sm-2 { + --bs-gutter-x: 0.5rem; + } + + .g-sm-2, + .gy-sm-2 { + --bs-gutter-y: 0.5rem; + } + + .g-sm-3, + .gx-sm-3 { + --bs-gutter-x: 1rem; + } + + .g-sm-3, + .gy-sm-3 { + --bs-gutter-y: 1rem; + } + + .g-sm-4, + .gx-sm-4 { + --bs-gutter-x: 1.5rem; + } + + .g-sm-4, + .gy-sm-4 { + --bs-gutter-y: 1.5rem; + } + + .g-sm-5, + .gx-sm-5 { + --bs-gutter-x: 3rem; + } + + .g-sm-5, + .gy-sm-5 { + --bs-gutter-y: 3rem; + } +} + +@media (min-width: 768px) { + .col-md { + flex: 1 0 0%; + } + + .row-cols-md-auto > * { + flex: 0 0 auto; + width: auto; + } + + .row-cols-md-1 > * { + flex: 0 0 auto; + width: 100%; + } + + .row-cols-md-2 > * { + flex: 0 0 auto; + width: 50%; + } + + .row-cols-md-3 > * { + flex: 0 0 auto; + width: 33.3333333333%; + } + + .row-cols-md-4 > * { + flex: 0 0 auto; + width: 25%; + } + + .row-cols-md-5 > * { + flex: 0 0 auto; + width: 20%; + } + + .row-cols-md-6 > * { + flex: 0 0 auto; + width: 16.6666666667%; + } + + .col-md-auto { + flex: 0 0 auto; + width: auto; + } + + .col-md-1 { + flex: 0 0 auto; + width: 8.33333333%; + } + + .col-md-2 { + flex: 0 0 auto; + width: 16.66666667%; + } + + .col-md-3 { + flex: 0 0 auto; + width: 25%; + } + + .col-md-4 { + flex: 0 0 auto; + width: 33.33333333%; + } + + .col-md-5 { + flex: 0 0 auto; + width: 41.66666667%; + } + + .col-md-6 { + flex: 0 0 auto; + width: 50%; + } + + .col-md-7 { + flex: 0 0 auto; + width: 58.33333333%; + } + + .col-md-8 { + flex: 0 0 auto; + width: 66.66666667%; + } + + .col-md-9 { + flex: 0 0 auto; + width: 75%; + } + + .col-md-10 { + flex: 0 0 auto; + width: 83.33333333%; + } + + .col-md-11 { + flex: 0 0 auto; + width: 91.66666667%; + } + + .col-md-12 { + flex: 0 0 auto; + width: 100%; + } + + .offset-md-0 { + margin-left: 0; + } + + .offset-md-1 { + margin-left: 8.33333333%; + } + + .offset-md-2 { + margin-left: 16.66666667%; + } + + .offset-md-3 { + margin-left: 25%; + } + + .offset-md-4 { + margin-left: 33.33333333%; + } + + .offset-md-5 { + margin-left: 41.66666667%; + } + + .offset-md-6 { + margin-left: 50%; + } + + .offset-md-7 { + margin-left: 58.33333333%; + } + + .offset-md-8 { + margin-left: 66.66666667%; + } + + .offset-md-9 { + margin-left: 75%; + } + + .offset-md-10 { + margin-left: 83.33333333%; + } + + .offset-md-11 { + margin-left: 91.66666667%; + } + + .g-md-0, + .gx-md-0 { + --bs-gutter-x: 0; + } + + .g-md-0, + .gy-md-0 { + --bs-gutter-y: 0; + } + + .g-md-1, + .gx-md-1 { + --bs-gutter-x: 0.25rem; + } + + .g-md-1, + .gy-md-1 { + --bs-gutter-y: 0.25rem; + } + + .g-md-2, + .gx-md-2 { + --bs-gutter-x: 0.5rem; + } + + .g-md-2, + .gy-md-2 { + --bs-gutter-y: 0.5rem; + } + + .g-md-3, + .gx-md-3 { + --bs-gutter-x: 1rem; + } + + .g-md-3, + .gy-md-3 { + --bs-gutter-y: 1rem; + } + + .g-md-4, + .gx-md-4 { + --bs-gutter-x: 1.5rem; + } + + .g-md-4, + .gy-md-4 { + --bs-gutter-y: 1.5rem; + } + + .g-md-5, + .gx-md-5 { + --bs-gutter-x: 3rem; + } + + .g-md-5, + .gy-md-5 { + --bs-gutter-y: 3rem; + } +} + +@media (min-width: 992px) { + .col-lg { + flex: 1 0 0%; + } + + .row-cols-lg-auto > * { + flex: 0 0 auto; + width: auto; + } + + .row-cols-lg-1 > * { + flex: 0 0 auto; + width: 100%; + } + + .row-cols-lg-2 > * { + flex: 0 0 auto; + width: 50%; + } + + .row-cols-lg-3 > * { + flex: 0 0 auto; + width: 33.3333333333%; + } + + .row-cols-lg-4 > * { + flex: 0 0 auto; + width: 25%; + } + + .row-cols-lg-5 > * { + flex: 0 0 auto; + width: 20%; + } + + .row-cols-lg-6 > * { + flex: 0 0 auto; + width: 16.6666666667%; + } + + .col-lg-auto { + flex: 0 0 auto; + width: auto; + } + + .col-lg-1 { + flex: 0 0 auto; + width: 8.33333333%; + } + + .col-lg-2 { + flex: 0 0 auto; + width: 16.66666667%; + } + + .col-lg-3 { + flex: 0 0 auto; + width: 25%; + } + + .col-lg-4 { + flex: 0 0 auto; + width: 33.33333333%; + } + + .col-lg-5 { + flex: 0 0 auto; + width: 41.66666667%; + } + + .col-lg-6 { + flex: 0 0 auto; + width: 50%; + } + + .col-lg-7 { + flex: 0 0 auto; + width: 58.33333333%; + } + + .col-lg-8 { + flex: 0 0 auto; + width: 66.66666667%; + } + + .col-lg-9 { + flex: 0 0 auto; + width: 75%; + } + + .col-lg-10 { + flex: 0 0 auto; + width: 83.33333333%; + } + + .col-lg-11 { + flex: 0 0 auto; + width: 91.66666667%; + } + + .col-lg-12 { + flex: 0 0 auto; + width: 100%; + } + + .offset-lg-0 { + margin-left: 0; + } + + .offset-lg-1 { + margin-left: 8.33333333%; + } + + .offset-lg-2 { + margin-left: 16.66666667%; + } + + .offset-lg-3 { + margin-left: 25%; + } + + .offset-lg-4 { + margin-left: 33.33333333%; + } + + .offset-lg-5 { + margin-left: 41.66666667%; + } + + .offset-lg-6 { + margin-left: 50%; + } + + .offset-lg-7 { + margin-left: 58.33333333%; + } + + .offset-lg-8 { + margin-left: 66.66666667%; + } + + .offset-lg-9 { + margin-left: 75%; + } + + .offset-lg-10 { + margin-left: 83.33333333%; + } + + .offset-lg-11 { + margin-left: 91.66666667%; + } + + .g-lg-0, + .gx-lg-0 { + --bs-gutter-x: 0; + } + + .g-lg-0, + .gy-lg-0 { + --bs-gutter-y: 0; + } + + .g-lg-1, + .gx-lg-1 { + --bs-gutter-x: 0.25rem; + } + + .g-lg-1, + .gy-lg-1 { + --bs-gutter-y: 0.25rem; + } + + .g-lg-2, + .gx-lg-2 { + --bs-gutter-x: 0.5rem; + } + + .g-lg-2, + .gy-lg-2 { + --bs-gutter-y: 0.5rem; + } + + .g-lg-3, + .gx-lg-3 { + --bs-gutter-x: 1rem; + } + + .g-lg-3, + .gy-lg-3 { + --bs-gutter-y: 1rem; + } + + .g-lg-4, + .gx-lg-4 { + --bs-gutter-x: 1.5rem; + } + + .g-lg-4, + .gy-lg-4 { + --bs-gutter-y: 1.5rem; + } + + .g-lg-5, + .gx-lg-5 { + --bs-gutter-x: 3rem; + } + + .g-lg-5, + .gy-lg-5 { + --bs-gutter-y: 3rem; + } +} + +@media (min-width: 1200px) { + .col-xl { + flex: 1 0 0%; + } + + .row-cols-xl-auto > * { + flex: 0 0 auto; + width: auto; + } + + .row-cols-xl-1 > * { + flex: 0 0 auto; + width: 100%; + } + + .row-cols-xl-2 > * { + flex: 0 0 auto; + width: 50%; + } + + .row-cols-xl-3 > * { + flex: 0 0 auto; + width: 33.3333333333%; + } + + .row-cols-xl-4 > * { + flex: 0 0 auto; + width: 25%; + } + + .row-cols-xl-5 > * { + flex: 0 0 auto; + width: 20%; + } + + .row-cols-xl-6 > * { + flex: 0 0 auto; + width: 16.6666666667%; + } + + .col-xl-auto { + flex: 0 0 auto; + width: auto; + } + + .col-xl-1 { + flex: 0 0 auto; + width: 8.33333333%; + } + + .col-xl-2 { + flex: 0 0 auto; + width: 16.66666667%; + } + + .col-xl-3 { + flex: 0 0 auto; + width: 25%; + } + + .col-xl-4 { + flex: 0 0 auto; + width: 33.33333333%; + } + + .col-xl-5 { + flex: 0 0 auto; + width: 41.66666667%; + } + + .col-xl-6 { + flex: 0 0 auto; + width: 50%; + } + + .col-xl-7 { + flex: 0 0 auto; + width: 58.33333333%; + } + + .col-xl-8 { + flex: 0 0 auto; + width: 66.66666667%; + } + + .col-xl-9 { + flex: 0 0 auto; + width: 75%; + } + + .col-xl-10 { + flex: 0 0 auto; + width: 83.33333333%; + } + + .col-xl-11 { + flex: 0 0 auto; + width: 91.66666667%; + } + + .col-xl-12 { + flex: 0 0 auto; + width: 100%; + } + + .offset-xl-0 { + margin-left: 0; + } + + .offset-xl-1 { + margin-left: 8.33333333%; + } + + .offset-xl-2 { + margin-left: 16.66666667%; + } + + .offset-xl-3 { + margin-left: 25%; + } + + .offset-xl-4 { + margin-left: 33.33333333%; + } + + .offset-xl-5 { + margin-left: 41.66666667%; + } + + .offset-xl-6 { + margin-left: 50%; + } + + .offset-xl-7 { + margin-left: 58.33333333%; + } + + .offset-xl-8 { + margin-left: 66.66666667%; + } + + .offset-xl-9 { + margin-left: 75%; + } + + .offset-xl-10 { + margin-left: 83.33333333%; + } + + .offset-xl-11 { + margin-left: 91.66666667%; + } + + .g-xl-0, + .gx-xl-0 { + --bs-gutter-x: 0; + } + + .g-xl-0, + .gy-xl-0 { + --bs-gutter-y: 0; + } + + .g-xl-1, + .gx-xl-1 { + --bs-gutter-x: 0.25rem; + } + + .g-xl-1, + .gy-xl-1 { + --bs-gutter-y: 0.25rem; + } + + .g-xl-2, + .gx-xl-2 { + --bs-gutter-x: 0.5rem; + } + + .g-xl-2, + .gy-xl-2 { + --bs-gutter-y: 0.5rem; + } + + .g-xl-3, + .gx-xl-3 { + --bs-gutter-x: 1rem; + } + + .g-xl-3, + .gy-xl-3 { + --bs-gutter-y: 1rem; + } + + .g-xl-4, + .gx-xl-4 { + --bs-gutter-x: 1.5rem; + } + + .g-xl-4, + .gy-xl-4 { + --bs-gutter-y: 1.5rem; + } + + .g-xl-5, + .gx-xl-5 { + --bs-gutter-x: 3rem; + } + + .g-xl-5, + .gy-xl-5 { + --bs-gutter-y: 3rem; + } +} + +@media (min-width: 1400px) { + .col-xxl { + flex: 1 0 0%; + } + + .row-cols-xxl-auto > * { + flex: 0 0 auto; + width: auto; + } + + .row-cols-xxl-1 > * { + flex: 0 0 auto; + width: 100%; + } + + .row-cols-xxl-2 > * { + flex: 0 0 auto; + width: 50%; + } + + .row-cols-xxl-3 > * { + flex: 0 0 auto; + width: 33.3333333333%; + } + + .row-cols-xxl-4 > * { + flex: 0 0 auto; + width: 25%; + } + + .row-cols-xxl-5 > * { + flex: 0 0 auto; + width: 20%; + } + + .row-cols-xxl-6 > * { + flex: 0 0 auto; + width: 16.6666666667%; + } + + .col-xxl-auto { + flex: 0 0 auto; + width: auto; + } + + .col-xxl-1 { + flex: 0 0 auto; + width: 8.33333333%; + } + + .col-xxl-2 { + flex: 0 0 auto; + width: 16.66666667%; + } + + .col-xxl-3 { + flex: 0 0 auto; + width: 25%; + } + + .col-xxl-4 { + flex: 0 0 auto; + width: 33.33333333%; + } + + .col-xxl-5 { + flex: 0 0 auto; + width: 41.66666667%; + } + + .col-xxl-6 { + flex: 0 0 auto; + width: 50%; + } + + .col-xxl-7 { + flex: 0 0 auto; + width: 58.33333333%; + } + + .col-xxl-8 { + flex: 0 0 auto; + width: 66.66666667%; + } + + .col-xxl-9 { + flex: 0 0 auto; + width: 75%; + } + + .col-xxl-10 { + flex: 0 0 auto; + width: 83.33333333%; + } + + .col-xxl-11 { + flex: 0 0 auto; + width: 91.66666667%; + } + + .col-xxl-12 { + flex: 0 0 auto; + width: 100%; + } + + .offset-xxl-0 { + margin-left: 0; + } + + .offset-xxl-1 { + margin-left: 8.33333333%; + } + + .offset-xxl-2 { + margin-left: 16.66666667%; + } + + .offset-xxl-3 { + margin-left: 25%; + } + + .offset-xxl-4 { + margin-left: 33.33333333%; + } + + .offset-xxl-5 { + margin-left: 41.66666667%; + } + + .offset-xxl-6 { + margin-left: 50%; + } + + .offset-xxl-7 { + margin-left: 58.33333333%; + } + + .offset-xxl-8 { + margin-left: 66.66666667%; + } + + .offset-xxl-9 { + margin-left: 75%; + } + + .offset-xxl-10 { + margin-left: 83.33333333%; + } + + .offset-xxl-11 { + margin-left: 91.66666667%; + } + + .g-xxl-0, + .gx-xxl-0 { + --bs-gutter-x: 0; + } + + .g-xxl-0, + .gy-xxl-0 { + --bs-gutter-y: 0; + } + + .g-xxl-1, + .gx-xxl-1 { + --bs-gutter-x: 0.25rem; + } + + .g-xxl-1, + .gy-xxl-1 { + --bs-gutter-y: 0.25rem; + } + + .g-xxl-2, + .gx-xxl-2 { + --bs-gutter-x: 0.5rem; + } + + .g-xxl-2, + .gy-xxl-2 { + --bs-gutter-y: 0.5rem; + } + + .g-xxl-3, + .gx-xxl-3 { + --bs-gutter-x: 1rem; + } + + .g-xxl-3, + .gy-xxl-3 { + --bs-gutter-y: 1rem; + } + + .g-xxl-4, + .gx-xxl-4 { + --bs-gutter-x: 1.5rem; + } + + .g-xxl-4, + .gy-xxl-4 { + --bs-gutter-y: 1.5rem; + } + + .g-xxl-5, + .gx-xxl-5 { + --bs-gutter-x: 3rem; + } + + .g-xxl-5, + .gy-xxl-5 { + --bs-gutter-y: 3rem; + } +} + +.table { + --bs-table-bg: transparent; + --bs-table-accent-bg: transparent; + --bs-table-striped-color: #212529; + --bs-table-striped-bg: rgba(0, 0, 0, 0.05); + --bs-table-active-color: #212529; + --bs-table-active-bg: rgba(0, 0, 0, 0.1); + --bs-table-hover-color: #212529; + --bs-table-hover-bg: rgba(0, 0, 0, 0.075); + width: 100%; + margin-bottom: 1rem; + color: #212529; + vertical-align: top; + border-color: #dee2e6; +} + +.table > :not(caption) > * > * { + padding: 0.5rem 0.5rem; + background-color: var(--bs-table-bg); + border-bottom-width: 1px; + box-shadow: inset 0 0 0 9999px var(--bs-table-accent-bg); +} + +.table > tbody { + vertical-align: inherit; +} + +.table > thead { + vertical-align: bottom; +} + +.table > :not(:first-child) { + border-top: 2px solid currentColor; +} + +.caption-top { + caption-side: top; +} + +.table-sm > :not(caption) > * > * { + padding: 0.25rem 0.25rem; +} + +.table-bordered > :not(caption) > * { + border-width: 1px 0; +} + +.table-bordered > :not(caption) > * > * { + border-width: 0 1px; +} + +.table-borderless > :not(caption) > * > * { + border-bottom-width: 0; +} + +.table-borderless > :not(:first-child) { + border-top-width: 0; +} + +.table-striped > tbody > tr:nth-of-type(odd) > * { + --bs-table-accent-bg: var(--bs-table-striped-bg); + color: var(--bs-table-striped-color); +} + +.table-active { + --bs-table-accent-bg: var(--bs-table-active-bg); + color: var(--bs-table-active-color); +} + +.table-hover > tbody > tr:hover > * { + --bs-table-accent-bg: var(--bs-table-hover-bg); + color: var(--bs-table-hover-color); +} + +.table-primary { + --bs-table-bg: #cfe2ff; + --bs-table-striped-bg: #c5d7f2; + --bs-table-striped-color: #000; + --bs-table-active-bg: #bacbe6; + --bs-table-active-color: #000; + --bs-table-hover-bg: #bfd1ec; + --bs-table-hover-color: #000; + color: #000; + border-color: #bacbe6; +} + +.table-secondary { + --bs-table-bg: #e2e3e5; + --bs-table-striped-bg: #d7d8da; + --bs-table-striped-color: #000; + --bs-table-active-bg: #cbccce; + --bs-table-active-color: #000; + --bs-table-hover-bg: #d1d2d4; + --bs-table-hover-color: #000; + color: #000; + border-color: #cbccce; +} + +.table-success { + --bs-table-bg: #d1e7dd; + --bs-table-striped-bg: #c7dbd2; + --bs-table-striped-color: #000; + --bs-table-active-bg: #bcd0c7; + --bs-table-active-color: #000; + --bs-table-hover-bg: #c1d6cc; + --bs-table-hover-color: #000; + color: #000; + border-color: #bcd0c7; +} + +.table-info { + --bs-table-bg: #cff4fc; + --bs-table-striped-bg: #c5e8ef; + --bs-table-striped-color: #000; + --bs-table-active-bg: #badce3; + --bs-table-active-color: #000; + --bs-table-hover-bg: #bfe2e9; + --bs-table-hover-color: #000; + color: #000; + border-color: #badce3; +} + +.table-warning { + --bs-table-bg: #fff3cd; + --bs-table-striped-bg: #f2e7c3; + --bs-table-striped-color: #000; + --bs-table-active-bg: #e6dbb9; + --bs-table-active-color: #000; + --bs-table-hover-bg: #ece1be; + --bs-table-hover-color: #000; + color: #000; + border-color: #e6dbb9; +} + +.table-danger { + --bs-table-bg: #f8d7da; + --bs-table-striped-bg: #eccccf; + --bs-table-striped-color: #000; + --bs-table-active-bg: #dfc2c4; + --bs-table-active-color: #000; + --bs-table-hover-bg: #e5c7ca; + --bs-table-hover-color: #000; + color: #000; + border-color: #dfc2c4; +} + +.table-light { + --bs-table-bg: #f8f9fa; + --bs-table-striped-bg: #ecedee; + --bs-table-striped-color: #000; + --bs-table-active-bg: #dfe0e1; + --bs-table-active-color: #000; + --bs-table-hover-bg: #e5e6e7; + --bs-table-hover-color: #000; + color: #000; + border-color: #dfe0e1; +} + +.table-dark { + --bs-table-bg: #212529; + --bs-table-striped-bg: #2c3034; + --bs-table-striped-color: #fff; + --bs-table-active-bg: #373b3e; + --bs-table-active-color: #fff; + --bs-table-hover-bg: #323539; + --bs-table-hover-color: #fff; + color: #fff; + border-color: #373b3e; +} + +.table-responsive { + overflow-x: auto; + -webkit-overflow-scrolling: touch; +} + +@media (max-width: 575.98px) { + .table-responsive-sm { + overflow-x: auto; + -webkit-overflow-scrolling: touch; + } +} + +@media (max-width: 767.98px) { + .table-responsive-md { + overflow-x: auto; + -webkit-overflow-scrolling: touch; + } +} + +@media (max-width: 991.98px) { + .table-responsive-lg { + overflow-x: auto; + -webkit-overflow-scrolling: touch; + } +} + +@media (max-width: 1199.98px) { + .table-responsive-xl { + overflow-x: auto; + -webkit-overflow-scrolling: touch; + } +} + +@media (max-width: 1399.98px) { + .table-responsive-xxl { + overflow-x: auto; + -webkit-overflow-scrolling: touch; + } +} + +.form-label { + margin-bottom: 0.5rem; +} + +.col-form-label { + padding-top: calc(0.375rem + 1px); + padding-bottom: calc(0.375rem + 1px); + margin-bottom: 0; + font-size: inherit; + line-height: 1.5; +} + +.col-form-label-lg { + padding-top: calc(0.5rem + 1px); + padding-bottom: calc(0.5rem + 1px); + font-size: 1.25rem; +} + +.col-form-label-sm { + padding-top: calc(0.25rem + 1px); + padding-bottom: calc(0.25rem + 1px); + font-size: 0.875rem; +} + +.form-text { + margin-top: 0.25rem; + font-size: 0.875em; + color: #6c757d; +} + +.form-control { + display: block; + width: 100%; + padding: 0.375rem 0.75rem; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: #212529; + background-color: #fff; + background-clip: padding-box; + border: 1px solid #ced4da; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + border-radius: 0.25rem; + transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} + +@media (prefers-reduced-motion: reduce) { + .form-control { + transition: none; + } +} + +.form-control[type=file] { + overflow: hidden; +} + +.form-control[type=file]:not(:disabled):not([readonly]) { + cursor: pointer; +} + +.form-control:focus { + color: #212529; + background-color: #fff; + border-color: #86b7fe; + outline: 0; + box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); +} + +.form-control::-webkit-date-and-time-value { + height: 1.5em; +} + +.form-control::-moz-placeholder { + color: #6c757d; + opacity: 1; +} + +.form-control::placeholder { + color: #6c757d; + opacity: 1; +} + +.form-control:disabled, .form-control[readonly] { + background-color: #e9ecef; + opacity: 1; +} + +.form-control::-webkit-file-upload-button { + padding: 0.375rem 0.75rem; + margin: -0.375rem -0.75rem; + -webkit-margin-end: 0.75rem; + margin-inline-end: 0.75rem; + color: #212529; + background-color: #e9ecef; + pointer-events: none; + border-color: inherit; + border-style: solid; + border-width: 0; + border-inline-end-width: 1px; + border-radius: 0; + -webkit-transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} + +.form-control::file-selector-button { + padding: 0.375rem 0.75rem; + margin: -0.375rem -0.75rem; + -webkit-margin-end: 0.75rem; + margin-inline-end: 0.75rem; + color: #212529; + background-color: #e9ecef; + pointer-events: none; + border-color: inherit; + border-style: solid; + border-width: 0; + border-inline-end-width: 1px; + border-radius: 0; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} + +@media (prefers-reduced-motion: reduce) { + .form-control::-webkit-file-upload-button { + -webkit-transition: none; + transition: none; + } + + .form-control::file-selector-button { + transition: none; + } +} + +.form-control:hover:not(:disabled):not([readonly])::-webkit-file-upload-button { + background-color: #dde0e3; +} + +.form-control:hover:not(:disabled):not([readonly])::file-selector-button { + background-color: #dde0e3; +} + +.form-control::-webkit-file-upload-button { + padding: 0.375rem 0.75rem; + margin: -0.375rem -0.75rem; + -webkit-margin-end: 0.75rem; + margin-inline-end: 0.75rem; + color: #212529; + background-color: #e9ecef; + pointer-events: none; + border-color: inherit; + border-style: solid; + border-width: 0; + border-inline-end-width: 1px; + border-radius: 0; + -webkit-transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} + +@media (prefers-reduced-motion: reduce) { + .form-control::-webkit-file-upload-button { + -webkit-transition: none; + transition: none; + } +} + +.form-control:hover:not(:disabled):not([readonly])::-webkit-file-upload-button { + background-color: #dde0e3; +} + +.form-control-plaintext { + display: block; + width: 100%; + padding: 0.375rem 0; + margin-bottom: 0; + line-height: 1.5; + color: #212529; + background-color: transparent; + border: solid transparent; + border-width: 1px 0; +} + +.form-control-plaintext.form-control-sm, .form-control-plaintext.form-control-lg { + padding-right: 0; + padding-left: 0; +} + +.form-control-sm { + min-height: calc(1.5em + 0.5rem + 2px); + padding: 0.25rem 0.5rem; + font-size: 0.875rem; + border-radius: 0.2rem; +} + +.form-control-sm::-webkit-file-upload-button { + padding: 0.25rem 0.5rem; + margin: -0.25rem -0.5rem; + -webkit-margin-end: 0.5rem; + margin-inline-end: 0.5rem; +} + +.form-control-sm::file-selector-button { + padding: 0.25rem 0.5rem; + margin: -0.25rem -0.5rem; + -webkit-margin-end: 0.5rem; + margin-inline-end: 0.5rem; +} + +.form-control-sm::-webkit-file-upload-button { + padding: 0.25rem 0.5rem; + margin: -0.25rem -0.5rem; + -webkit-margin-end: 0.5rem; + margin-inline-end: 0.5rem; +} + +.form-control-lg { + min-height: calc(1.5em + 1rem + 2px); + padding: 0.5rem 1rem; + font-size: 1.25rem; + border-radius: 0.3rem; +} + +.form-control-lg::-webkit-file-upload-button { + padding: 0.5rem 1rem; + margin: -0.5rem -1rem; + -webkit-margin-end: 1rem; + margin-inline-end: 1rem; +} + +.form-control-lg::file-selector-button { + padding: 0.5rem 1rem; + margin: -0.5rem -1rem; + -webkit-margin-end: 1rem; + margin-inline-end: 1rem; +} + +.form-control-lg::-webkit-file-upload-button { + padding: 0.5rem 1rem; + margin: -0.5rem -1rem; + -webkit-margin-end: 1rem; + margin-inline-end: 1rem; +} + +textarea.form-control { + min-height: calc(1.5em + 0.75rem + 2px); +} + +textarea.form-control-sm { + min-height: calc(1.5em + 0.5rem + 2px); +} + +textarea.form-control-lg { + min-height: calc(1.5em + 1rem + 2px); +} + +.form-control-color { + width: 3rem; + height: auto; + padding: 0.375rem; +} + +.form-control-color:not(:disabled):not([readonly]) { + cursor: pointer; +} + +.form-control-color::-moz-color-swatch { + height: 1.5em; + border-radius: 0.25rem; +} + +.form-control-color::-webkit-color-swatch { + height: 1.5em; + border-radius: 0.25rem; +} + +.form-select { + display: block; + width: 100%; + padding: 0.375rem 2.25rem 0.375rem 0.75rem; + -moz-padding-start: calc(0.75rem - 3px); + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: #212529; + background-color: #fff; + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e"); + background-repeat: no-repeat; + background-position: right 0.75rem center; + background-size: 16px 12px; + border: 1px solid #ced4da; + border-radius: 0.25rem; + transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; +} + +@media (prefers-reduced-motion: reduce) { + .form-select { + transition: none; + } +} + +.form-select:focus { + border-color: #86b7fe; + outline: 0; + box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); +} + +.form-select[multiple], .form-select[size]:not([size="1"]) { + padding-right: 0.75rem; + background-image: none; +} + +.form-select:disabled { + background-color: #e9ecef; +} + +.form-select:-moz-focusring { + color: transparent; + text-shadow: 0 0 0 #212529; +} + +.form-select-sm { + padding-top: 0.25rem; + padding-bottom: 0.25rem; + padding-left: 0.5rem; + font-size: 0.875rem; + border-radius: 0.2rem; +} + +.form-select-lg { + padding-top: 0.5rem; + padding-bottom: 0.5rem; + padding-left: 1rem; + font-size: 1.25rem; + border-radius: 0.3rem; +} + +.form-check { + display: block; + min-height: 1.5rem; + padding-left: 1.5em; + margin-bottom: 0.125rem; +} + +.form-check .form-check-input { + float: left; + margin-left: -1.5em; +} + +.form-check-input { + width: 1em; + height: 1em; + margin-top: 0.25em; + vertical-align: top; + background-color: #fff; + background-repeat: no-repeat; + background-position: center; + background-size: contain; + border: 1px solid rgba(0, 0, 0, 0.25); + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + -webkit-print-color-adjust: exact; + color-adjust: exact; +} + +.form-check-input[type=checkbox] { + border-radius: 0.25em; +} + +.form-check-input[type=radio] { + border-radius: 50%; +} + +.form-check-input:active { + filter: brightness(90%); +} + +.form-check-input:focus { + border-color: #86b7fe; + outline: 0; + box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); +} + +.form-check-input:checked { + background-color: #0d6efd; + border-color: #0d6efd; +} + +.form-check-input:checked[type=checkbox] { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10l3 3l6-6'/%3e%3c/svg%3e"); +} + +.form-check-input:checked[type=radio] { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='%23fff'/%3e%3c/svg%3e"); +} + +.form-check-input[type=checkbox]:indeterminate { + background-color: #0d6efd; + border-color: #0d6efd; + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/%3e%3c/svg%3e"); +} + +.form-check-input:disabled { + pointer-events: none; + filter: none; + opacity: 0.5; +} + +.form-check-input[disabled] ~ .form-check-label, .form-check-input:disabled ~ .form-check-label { + opacity: 0.5; +} + +.form-switch { + padding-left: 2.5em; +} + +.form-switch .form-check-input { + width: 2em; + margin-left: -2.5em; + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%280, 0, 0, 0.25%29'/%3e%3c/svg%3e"); + background-position: left center; + border-radius: 2em; + transition: background-position 0.15s ease-in-out; +} + +@media (prefers-reduced-motion: reduce) { + .form-switch .form-check-input { + transition: none; + } +} + +.form-switch .form-check-input:focus { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%2386b7fe'/%3e%3c/svg%3e"); +} + +.form-switch .form-check-input:checked { + background-position: right center; + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e"); +} + +.form-check-inline { + display: inline-block; + margin-right: 1rem; +} + +.btn-check { + position: absolute; + clip: rect(0, 0, 0, 0); + pointer-events: none; +} + +.btn-check[disabled] + .btn, .btn-check:disabled + .btn { + pointer-events: none; + filter: none; + opacity: 0.65; +} + +.form-range { + width: 100%; + height: 1.5rem; + padding: 0; + background-color: transparent; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; +} + +.form-range:focus { + outline: 0; +} + +.form-range:focus::-webkit-slider-thumb { + box-shadow: 0 0 0 1px #fff, 0 0 0 0.25rem rgba(13, 110, 253, 0.25); +} + +.form-range:focus::-moz-range-thumb { + box-shadow: 0 0 0 1px #fff, 0 0 0 0.25rem rgba(13, 110, 253, 0.25); +} + +.form-range::-moz-focus-outer { + border: 0; +} + +.form-range::-webkit-slider-thumb { + width: 1rem; + height: 1rem; + margin-top: -0.25rem; + background-color: #0d6efd; + border: 0; + border-radius: 1rem; + -webkit-transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + -webkit-appearance: none; + appearance: none; +} + +@media (prefers-reduced-motion: reduce) { + .form-range::-webkit-slider-thumb { + -webkit-transition: none; + transition: none; + } +} + +.form-range::-webkit-slider-thumb:active { + background-color: #b6d4fe; +} + +.form-range::-webkit-slider-runnable-track { + width: 100%; + height: 0.5rem; + color: transparent; + cursor: pointer; + background-color: #dee2e6; + border-color: transparent; + border-radius: 1rem; +} + +.form-range::-moz-range-thumb { + width: 1rem; + height: 1rem; + background-color: #0d6efd; + border: 0; + border-radius: 1rem; + -moz-transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + -moz-appearance: none; + appearance: none; +} + +@media (prefers-reduced-motion: reduce) { + .form-range::-moz-range-thumb { + -moz-transition: none; + transition: none; + } +} + +.form-range::-moz-range-thumb:active { + background-color: #b6d4fe; +} + +.form-range::-moz-range-track { + width: 100%; + height: 0.5rem; + color: transparent; + cursor: pointer; + background-color: #dee2e6; + border-color: transparent; + border-radius: 1rem; +} + +.form-range:disabled { + pointer-events: none; +} + +.form-range:disabled::-webkit-slider-thumb { + background-color: #adb5bd; +} + +.form-range:disabled::-moz-range-thumb { + background-color: #adb5bd; +} + +.form-floating { + position: relative; +} + +.form-floating > .form-control, +.form-floating > .form-select { + height: calc(3.5rem + 2px); + line-height: 1.25; +} + +.form-floating > label { + position: absolute; + top: 0; + left: 0; + height: 100%; + padding: 1rem 0.75rem; + pointer-events: none; + border: 1px solid transparent; + transform-origin: 0 0; + transition: opacity 0.1s ease-in-out, transform 0.1s ease-in-out; +} + +@media (prefers-reduced-motion: reduce) { + .form-floating > label { + transition: none; + } +} + +.form-floating > .form-control { + padding: 1rem 0.75rem; +} + +.form-floating > .form-control::-moz-placeholder { + color: transparent; +} + +.form-floating > .form-control::placeholder { + color: transparent; +} + +.form-floating > .form-control:not(:-moz-placeholder-shown) { + padding-top: 1.625rem; + padding-bottom: 0.625rem; +} + +.form-floating > .form-control:focus, .form-floating > .form-control:not(:placeholder-shown) { + padding-top: 1.625rem; + padding-bottom: 0.625rem; +} + +.form-floating > .form-control:-webkit-autofill { + padding-top: 1.625rem; + padding-bottom: 0.625rem; +} + +.form-floating > .form-select { + padding-top: 1.625rem; + padding-bottom: 0.625rem; +} + +.form-floating > .form-control:not(:-moz-placeholder-shown) ~ label { + opacity: 0.65; + transform: scale(0.85) translateY(-0.5rem) translateX(0.15rem); +} + +.form-floating > .form-control:focus ~ label, +.form-floating > .form-control:not(:placeholder-shown) ~ label, +.form-floating > .form-select ~ label { + opacity: 0.65; + transform: scale(0.85) translateY(-0.5rem) translateX(0.15rem); +} + +.form-floating > .form-control:-webkit-autofill ~ label { + opacity: 0.65; + transform: scale(0.85) translateY(-0.5rem) translateX(0.15rem); +} + +.input-group { + position: relative; + display: flex; + flex-wrap: wrap; + align-items: stretch; + width: 100%; +} + +.input-group > .form-control, +.input-group > .form-select { + position: relative; + flex: 1 1 auto; + width: 1%; + min-width: 0; +} + +.input-group > .form-control:focus, +.input-group > .form-select:focus { + z-index: 3; +} + +.input-group .btn { + position: relative; + z-index: 2; +} + +.input-group .btn:focus { + z-index: 3; +} + +.input-group-text { + display: flex; + align-items: center; + padding: 0.375rem 0.75rem; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: #212529; + text-align: center; + white-space: nowrap; + background-color: #e9ecef; + border: 1px solid #ced4da; + border-radius: 0.25rem; +} + +.input-group-lg > .form-control, +.input-group-lg > .form-select, +.input-group-lg > .input-group-text, +.input-group-lg > .btn { + padding: 0.5rem 1rem; + font-size: 1.25rem; + border-radius: 0.3rem; +} + +.input-group-sm > .form-control, +.input-group-sm > .form-select, +.input-group-sm > .input-group-text, +.input-group-sm > .btn { + padding: 0.25rem 0.5rem; + font-size: 0.875rem; + border-radius: 0.2rem; +} + +.input-group-lg > .form-select, +.input-group-sm > .form-select { + padding-right: 3rem; +} + +.input-group:not(.has-validation) > :not(:last-child):not(.dropdown-toggle):not(.dropdown-menu), +.input-group:not(.has-validation) > .dropdown-toggle:nth-last-child(n+3) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.input-group.has-validation > :nth-last-child(n+3):not(.dropdown-toggle):not(.dropdown-menu), +.input-group.has-validation > .dropdown-toggle:nth-last-child(n+4) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.input-group > :not(:first-child):not(.dropdown-menu):not(.valid-tooltip):not(.valid-feedback):not(.invalid-tooltip):not(.invalid-feedback) { + margin-left: -1px; + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +.valid-feedback { + display: none; + width: 100%; + margin-top: 0.25rem; + font-size: 0.875em; + color: #198754; +} + +.valid-tooltip { + position: absolute; + top: 100%; + z-index: 5; + display: none; + max-width: 100%; + padding: 0.25rem 0.5rem; + margin-top: 0.1rem; + font-size: 0.875rem; + color: #fff; + background-color: rgba(25, 135, 84, 0.9); + border-radius: 0.25rem; +} + +.was-validated :valid ~ .valid-feedback, +.was-validated :valid ~ .valid-tooltip, +.is-valid ~ .valid-feedback, +.is-valid ~ .valid-tooltip { + display: block; +} + +.was-validated .form-control:valid, .form-control.is-valid { + border-color: #198754; + padding-right: calc(1.5em + 0.75rem); + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e"); + background-repeat: no-repeat; + background-position: right calc(0.375em + 0.1875rem) center; + background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); +} + +.was-validated .form-control:valid:focus, .form-control.is-valid:focus { + border-color: #198754; + box-shadow: 0 0 0 0.25rem rgba(25, 135, 84, 0.25); +} + +.was-validated textarea.form-control:valid, textarea.form-control.is-valid { + padding-right: calc(1.5em + 0.75rem); + background-position: top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem); +} + +.was-validated .form-select:valid, .form-select.is-valid { + border-color: #198754; +} + +.was-validated .form-select:valid:not([multiple]):not([size]), .was-validated .form-select:valid:not([multiple])[size="1"], .form-select.is-valid:not([multiple]):not([size]), .form-select.is-valid:not([multiple])[size="1"] { + padding-right: 4.125rem; + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e"), url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e"); + background-position: right 0.75rem center, center right 2.25rem; + background-size: 16px 12px, calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); +} + +.was-validated .form-select:valid:focus, .form-select.is-valid:focus { + border-color: #198754; + box-shadow: 0 0 0 0.25rem rgba(25, 135, 84, 0.25); +} + +.was-validated .form-check-input:valid, .form-check-input.is-valid { + border-color: #198754; +} + +.was-validated .form-check-input:valid:checked, .form-check-input.is-valid:checked { + background-color: #198754; +} + +.was-validated .form-check-input:valid:focus, .form-check-input.is-valid:focus { + box-shadow: 0 0 0 0.25rem rgba(25, 135, 84, 0.25); +} + +.was-validated .form-check-input:valid ~ .form-check-label, .form-check-input.is-valid ~ .form-check-label { + color: #198754; +} + +.form-check-inline .form-check-input ~ .valid-feedback { + margin-left: 0.5em; +} + +.was-validated .input-group .form-control:valid, .input-group .form-control.is-valid, +.was-validated .input-group .form-select:valid, +.input-group .form-select.is-valid { + z-index: 1; +} + +.was-validated .input-group .form-control:valid:focus, .input-group .form-control.is-valid:focus, +.was-validated .input-group .form-select:valid:focus, +.input-group .form-select.is-valid:focus { + z-index: 3; +} + +.invalid-feedback { + display: none; + width: 100%; + margin-top: 0.25rem; + font-size: 0.875em; + color: #dc3545; +} + +.invalid-tooltip { + position: absolute; + top: 100%; + z-index: 5; + display: none; + max-width: 100%; + padding: 0.25rem 0.5rem; + margin-top: 0.1rem; + font-size: 0.875rem; + color: #fff; + background-color: rgba(220, 53, 69, 0.9); + border-radius: 0.25rem; +} + +.was-validated :invalid ~ .invalid-feedback, +.was-validated :invalid ~ .invalid-tooltip, +.is-invalid ~ .invalid-feedback, +.is-invalid ~ .invalid-tooltip { + display: block; +} + +.was-validated .form-control:invalid, .form-control.is-invalid { + border-color: #dc3545; + padding-right: calc(1.5em + 0.75rem); + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e"); + background-repeat: no-repeat; + background-position: right calc(0.375em + 0.1875rem) center; + background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); +} + +.was-validated .form-control:invalid:focus, .form-control.is-invalid:focus { + border-color: #dc3545; + box-shadow: 0 0 0 0.25rem rgba(220, 53, 69, 0.25); +} + +.was-validated textarea.form-control:invalid, textarea.form-control.is-invalid { + padding-right: calc(1.5em + 0.75rem); + background-position: top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem); +} + +.was-validated .form-select:invalid, .form-select.is-invalid { + border-color: #dc3545; +} + +.was-validated .form-select:invalid:not([multiple]):not([size]), .was-validated .form-select:invalid:not([multiple])[size="1"], .form-select.is-invalid:not([multiple]):not([size]), .form-select.is-invalid:not([multiple])[size="1"] { + padding-right: 4.125rem; + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e"), url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e"); + background-position: right 0.75rem center, center right 2.25rem; + background-size: 16px 12px, calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); +} + +.was-validated .form-select:invalid:focus, .form-select.is-invalid:focus { + border-color: #dc3545; + box-shadow: 0 0 0 0.25rem rgba(220, 53, 69, 0.25); +} + +.was-validated .form-check-input:invalid, .form-check-input.is-invalid { + border-color: #dc3545; +} + +.was-validated .form-check-input:invalid:checked, .form-check-input.is-invalid:checked { + background-color: #dc3545; +} + +.was-validated .form-check-input:invalid:focus, .form-check-input.is-invalid:focus { + box-shadow: 0 0 0 0.25rem rgba(220, 53, 69, 0.25); +} + +.was-validated .form-check-input:invalid ~ .form-check-label, .form-check-input.is-invalid ~ .form-check-label { + color: #dc3545; +} + +.form-check-inline .form-check-input ~ .invalid-feedback { + margin-left: 0.5em; +} + +.was-validated .input-group .form-control:invalid, .input-group .form-control.is-invalid, +.was-validated .input-group .form-select:invalid, +.input-group .form-select.is-invalid { + z-index: 2; +} + +.was-validated .input-group .form-control:invalid:focus, .input-group .form-control.is-invalid:focus, +.was-validated .input-group .form-select:invalid:focus, +.input-group .form-select.is-invalid:focus { + z-index: 3; +} + +.btn { + display: inline-block; + font-weight: 400; + line-height: 1.5; + color: #212529; + text-align: center; + text-decoration: none; + vertical-align: middle; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + background-color: transparent; + border: 1px solid transparent; + padding: 0.375rem 0.75rem; + font-size: 1rem; + border-radius: 0.25rem; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} + +@media (prefers-reduced-motion: reduce) { + .btn { + transition: none; + } +} + +.btn:hover { + color: #212529; +} + +.btn-check:focus + .btn, .btn:focus { + outline: 0; + box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); +} + +.btn:disabled, .btn.disabled, fieldset:disabled .btn { + pointer-events: none; + opacity: 0.65; +} + +.btn-primary { + color: #fff; + background-color: #0d6efd; + border-color: #0d6efd; +} + +.btn-primary:hover { + color: #fff; + background-color: #0b5ed7; + border-color: #0a58ca; +} + +.btn-check:focus + .btn-primary, .btn-primary:focus { + color: #fff; + background-color: #0b5ed7; + border-color: #0a58ca; + box-shadow: 0 0 0 0.25rem rgba(49, 132, 253, 0.5); +} + +.btn-check:checked + .btn-primary, .btn-check:active + .btn-primary, .btn-primary:active, .btn-primary.active, .show > .btn-primary.dropdown-toggle { + color: #fff; + background-color: #0a58ca; + border-color: #0a53be; +} + +.btn-check:checked + .btn-primary:focus, .btn-check:active + .btn-primary:focus, .btn-primary:active:focus, .btn-primary.active:focus, .show > .btn-primary.dropdown-toggle:focus { + box-shadow: 0 0 0 0.25rem rgba(49, 132, 253, 0.5); +} + +.btn-primary:disabled, .btn-primary.disabled { + color: #fff; + background-color: #0d6efd; + border-color: #0d6efd; +} + +.btn-secondary { + color: #fff; + background-color: #6c757d; + border-color: #6c757d; +} + +.btn-secondary:hover { + color: #fff; + background-color: #5c636a; + border-color: #565e64; +} + +.btn-check:focus + .btn-secondary, .btn-secondary:focus { + color: #fff; + background-color: #5c636a; + border-color: #565e64; + box-shadow: 0 0 0 0.25rem rgba(130, 138, 145, 0.5); +} + +.btn-check:checked + .btn-secondary, .btn-check:active + .btn-secondary, .btn-secondary:active, .btn-secondary.active, .show > .btn-secondary.dropdown-toggle { + color: #fff; + background-color: #565e64; + border-color: #51585e; +} + +.btn-check:checked + .btn-secondary:focus, .btn-check:active + .btn-secondary:focus, .btn-secondary:active:focus, .btn-secondary.active:focus, .show > .btn-secondary.dropdown-toggle:focus { + box-shadow: 0 0 0 0.25rem rgba(130, 138, 145, 0.5); +} + +.btn-secondary:disabled, .btn-secondary.disabled { + color: #fff; + background-color: #6c757d; + border-color: #6c757d; +} + +.btn-success { + color: #fff; + background-color: #198754; + border-color: #198754; +} + +.btn-success:hover { + color: #fff; + background-color: #157347; + border-color: #146c43; +} + +.btn-check:focus + .btn-success, .btn-success:focus { + color: #fff; + background-color: #157347; + border-color: #146c43; + box-shadow: 0 0 0 0.25rem rgba(60, 153, 110, 0.5); +} + +.btn-check:checked + .btn-success, .btn-check:active + .btn-success, .btn-success:active, .btn-success.active, .show > .btn-success.dropdown-toggle { + color: #fff; + background-color: #146c43; + border-color: #13653f; +} + +.btn-check:checked + .btn-success:focus, .btn-check:active + .btn-success:focus, .btn-success:active:focus, .btn-success.active:focus, .show > .btn-success.dropdown-toggle:focus { + box-shadow: 0 0 0 0.25rem rgba(60, 153, 110, 0.5); +} + +.btn-success:disabled, .btn-success.disabled { + color: #fff; + background-color: #198754; + border-color: #198754; +} + +.btn-info { + color: #000; + background-color: #0dcaf0; + border-color: #0dcaf0; +} + +.btn-info:hover { + color: #000; + background-color: #31d2f2; + border-color: #25cff2; +} + +.btn-check:focus + .btn-info, .btn-info:focus { + color: #000; + background-color: #31d2f2; + border-color: #25cff2; + box-shadow: 0 0 0 0.25rem rgba(11, 172, 204, 0.5); +} + +.btn-check:checked + .btn-info, .btn-check:active + .btn-info, .btn-info:active, .btn-info.active, .show > .btn-info.dropdown-toggle { + color: #000; + background-color: #3dd5f3; + border-color: #25cff2; +} + +.btn-check:checked + .btn-info:focus, .btn-check:active + .btn-info:focus, .btn-info:active:focus, .btn-info.active:focus, .show > .btn-info.dropdown-toggle:focus { + box-shadow: 0 0 0 0.25rem rgba(11, 172, 204, 0.5); +} + +.btn-info:disabled, .btn-info.disabled { + color: #000; + background-color: #0dcaf0; + border-color: #0dcaf0; +} + +.btn-warning { + color: #000; + background-color: #ffc107; + border-color: #ffc107; +} + +.btn-warning:hover { + color: #000; + background-color: #ffca2c; + border-color: #ffc720; +} + +.btn-check:focus + .btn-warning, .btn-warning:focus { + color: #000; + background-color: #ffca2c; + border-color: #ffc720; + box-shadow: 0 0 0 0.25rem rgba(217, 164, 6, 0.5); +} + +.btn-check:checked + .btn-warning, .btn-check:active + .btn-warning, .btn-warning:active, .btn-warning.active, .show > .btn-warning.dropdown-toggle { + color: #000; + background-color: #ffcd39; + border-color: #ffc720; +} + +.btn-check:checked + .btn-warning:focus, .btn-check:active + .btn-warning:focus, .btn-warning:active:focus, .btn-warning.active:focus, .show > .btn-warning.dropdown-toggle:focus { + box-shadow: 0 0 0 0.25rem rgba(217, 164, 6, 0.5); +} + +.btn-warning:disabled, .btn-warning.disabled { + color: #000; + background-color: #ffc107; + border-color: #ffc107; +} + +.btn-danger { + color: #fff; + background-color: #dc3545; + border-color: #dc3545; +} + +.btn-danger:hover { + color: #fff; + background-color: #bb2d3b; + border-color: #b02a37; +} + +.btn-check:focus + .btn-danger, .btn-danger:focus { + color: #fff; + background-color: #bb2d3b; + border-color: #b02a37; + box-shadow: 0 0 0 0.25rem rgba(225, 83, 97, 0.5); +} + +.btn-check:checked + .btn-danger, .btn-check:active + .btn-danger, .btn-danger:active, .btn-danger.active, .show > .btn-danger.dropdown-toggle { + color: #fff; + background-color: #b02a37; + border-color: #a52834; +} + +.btn-check:checked + .btn-danger:focus, .btn-check:active + .btn-danger:focus, .btn-danger:active:focus, .btn-danger.active:focus, .show > .btn-danger.dropdown-toggle:focus { + box-shadow: 0 0 0 0.25rem rgba(225, 83, 97, 0.5); +} + +.btn-danger:disabled, .btn-danger.disabled { + color: #fff; + background-color: #dc3545; + border-color: #dc3545; +} + +.btn-light { + color: #000; + background-color: #f8f9fa; + border-color: #f8f9fa; +} + +.btn-light:hover { + color: #000; + background-color: #f9fafb; + border-color: #f9fafb; +} + +.btn-check:focus + .btn-light, .btn-light:focus { + color: #000; + background-color: #f9fafb; + border-color: #f9fafb; + box-shadow: 0 0 0 0.25rem rgba(211, 212, 213, 0.5); +} + +.btn-check:checked + .btn-light, .btn-check:active + .btn-light, .btn-light:active, .btn-light.active, .show > .btn-light.dropdown-toggle { + color: #000; + background-color: #f9fafb; + border-color: #f9fafb; +} + +.btn-check:checked + .btn-light:focus, .btn-check:active + .btn-light:focus, .btn-light:active:focus, .btn-light.active:focus, .show > .btn-light.dropdown-toggle:focus { + box-shadow: 0 0 0 0.25rem rgba(211, 212, 213, 0.5); +} + +.btn-light:disabled, .btn-light.disabled { + color: #000; + background-color: #f8f9fa; + border-color: #f8f9fa; +} + +.btn-dark { + color: #fff; + background-color: #212529; + border-color: #212529; +} + +.btn-dark:hover { + color: #fff; + background-color: #1c1f23; + border-color: #1a1e21; +} + +.btn-check:focus + .btn-dark, .btn-dark:focus { + color: #fff; + background-color: #1c1f23; + border-color: #1a1e21; + box-shadow: 0 0 0 0.25rem rgba(66, 70, 73, 0.5); +} + +.btn-check:checked + .btn-dark, .btn-check:active + .btn-dark, .btn-dark:active, .btn-dark.active, .show > .btn-dark.dropdown-toggle { + color: #fff; + background-color: #1a1e21; + border-color: #191c1f; +} + +.btn-check:checked + .btn-dark:focus, .btn-check:active + .btn-dark:focus, .btn-dark:active:focus, .btn-dark.active:focus, .show > .btn-dark.dropdown-toggle:focus { + box-shadow: 0 0 0 0.25rem rgba(66, 70, 73, 0.5); +} + +.btn-dark:disabled, .btn-dark.disabled { + color: #fff; + background-color: #212529; + border-color: #212529; +} + +.btn-outline-primary { + color: #0d6efd; + border-color: #0d6efd; +} + +.btn-outline-primary:hover { + color: #fff; + background-color: #0d6efd; + border-color: #0d6efd; +} + +.btn-check:focus + .btn-outline-primary, .btn-outline-primary:focus { + box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.5); +} + +.btn-check:checked + .btn-outline-primary, .btn-check:active + .btn-outline-primary, .btn-outline-primary:active, .btn-outline-primary.active, .btn-outline-primary.dropdown-toggle.show { + color: #fff; + background-color: #0d6efd; + border-color: #0d6efd; +} + +.btn-check:checked + .btn-outline-primary:focus, .btn-check:active + .btn-outline-primary:focus, .btn-outline-primary:active:focus, .btn-outline-primary.active:focus, .btn-outline-primary.dropdown-toggle.show:focus { + box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.5); +} + +.btn-outline-primary:disabled, .btn-outline-primary.disabled { + color: #0d6efd; + background-color: transparent; +} + +.btn-outline-secondary { + color: #6c757d; + border-color: #6c757d; +} + +.btn-outline-secondary:hover { + color: #fff; + background-color: #6c757d; + border-color: #6c757d; +} + +.btn-check:focus + .btn-outline-secondary, .btn-outline-secondary:focus { + box-shadow: 0 0 0 0.25rem rgba(108, 117, 125, 0.5); +} + +.btn-check:checked + .btn-outline-secondary, .btn-check:active + .btn-outline-secondary, .btn-outline-secondary:active, .btn-outline-secondary.active, .btn-outline-secondary.dropdown-toggle.show { + color: #fff; + background-color: #6c757d; + border-color: #6c757d; +} + +.btn-check:checked + .btn-outline-secondary:focus, .btn-check:active + .btn-outline-secondary:focus, .btn-outline-secondary:active:focus, .btn-outline-secondary.active:focus, .btn-outline-secondary.dropdown-toggle.show:focus { + box-shadow: 0 0 0 0.25rem rgba(108, 117, 125, 0.5); +} + +.btn-outline-secondary:disabled, .btn-outline-secondary.disabled { + color: #6c757d; + background-color: transparent; +} + +.btn-outline-success { + color: #198754; + border-color: #198754; +} + +.btn-outline-success:hover { + color: #fff; + background-color: #198754; + border-color: #198754; +} + +.btn-check:focus + .btn-outline-success, .btn-outline-success:focus { + box-shadow: 0 0 0 0.25rem rgba(25, 135, 84, 0.5); +} + +.btn-check:checked + .btn-outline-success, .btn-check:active + .btn-outline-success, .btn-outline-success:active, .btn-outline-success.active, .btn-outline-success.dropdown-toggle.show { + color: #fff; + background-color: #198754; + border-color: #198754; +} + +.btn-check:checked + .btn-outline-success:focus, .btn-check:active + .btn-outline-success:focus, .btn-outline-success:active:focus, .btn-outline-success.active:focus, .btn-outline-success.dropdown-toggle.show:focus { + box-shadow: 0 0 0 0.25rem rgba(25, 135, 84, 0.5); +} + +.btn-outline-success:disabled, .btn-outline-success.disabled { + color: #198754; + background-color: transparent; +} + +.btn-outline-info { + color: #0dcaf0; + border-color: #0dcaf0; +} + +.btn-outline-info:hover { + color: #000; + background-color: #0dcaf0; + border-color: #0dcaf0; +} + +.btn-check:focus + .btn-outline-info, .btn-outline-info:focus { + box-shadow: 0 0 0 0.25rem rgba(13, 202, 240, 0.5); +} + +.btn-check:checked + .btn-outline-info, .btn-check:active + .btn-outline-info, .btn-outline-info:active, .btn-outline-info.active, .btn-outline-info.dropdown-toggle.show { + color: #000; + background-color: #0dcaf0; + border-color: #0dcaf0; +} + +.btn-check:checked + .btn-outline-info:focus, .btn-check:active + .btn-outline-info:focus, .btn-outline-info:active:focus, .btn-outline-info.active:focus, .btn-outline-info.dropdown-toggle.show:focus { + box-shadow: 0 0 0 0.25rem rgba(13, 202, 240, 0.5); +} + +.btn-outline-info:disabled, .btn-outline-info.disabled { + color: #0dcaf0; + background-color: transparent; +} + +.btn-outline-warning { + color: #ffc107; + border-color: #ffc107; +} + +.btn-outline-warning:hover { + color: #000; + background-color: #ffc107; + border-color: #ffc107; +} + +.btn-check:focus + .btn-outline-warning, .btn-outline-warning:focus { + box-shadow: 0 0 0 0.25rem rgba(255, 193, 7, 0.5); +} + +.btn-check:checked + .btn-outline-warning, .btn-check:active + .btn-outline-warning, .btn-outline-warning:active, .btn-outline-warning.active, .btn-outline-warning.dropdown-toggle.show { + color: #000; + background-color: #ffc107; + border-color: #ffc107; +} + +.btn-check:checked + .btn-outline-warning:focus, .btn-check:active + .btn-outline-warning:focus, .btn-outline-warning:active:focus, .btn-outline-warning.active:focus, .btn-outline-warning.dropdown-toggle.show:focus { + box-shadow: 0 0 0 0.25rem rgba(255, 193, 7, 0.5); +} + +.btn-outline-warning:disabled, .btn-outline-warning.disabled { + color: #ffc107; + background-color: transparent; +} + +.btn-outline-danger { + color: #dc3545; + border-color: #dc3545; +} + +.btn-outline-danger:hover { + color: #fff; + background-color: #dc3545; + border-color: #dc3545; +} + +.btn-check:focus + .btn-outline-danger, .btn-outline-danger:focus { + box-shadow: 0 0 0 0.25rem rgba(220, 53, 69, 0.5); +} + +.btn-check:checked + .btn-outline-danger, .btn-check:active + .btn-outline-danger, .btn-outline-danger:active, .btn-outline-danger.active, .btn-outline-danger.dropdown-toggle.show { + color: #fff; + background-color: #dc3545; + border-color: #dc3545; +} + +.btn-check:checked + .btn-outline-danger:focus, .btn-check:active + .btn-outline-danger:focus, .btn-outline-danger:active:focus, .btn-outline-danger.active:focus, .btn-outline-danger.dropdown-toggle.show:focus { + box-shadow: 0 0 0 0.25rem rgba(220, 53, 69, 0.5); +} + +.btn-outline-danger:disabled, .btn-outline-danger.disabled { + color: #dc3545; + background-color: transparent; +} + +.btn-outline-light { + color: #f8f9fa; + border-color: #f8f9fa; +} + +.btn-outline-light:hover { + color: #000; + background-color: #f8f9fa; + border-color: #f8f9fa; +} + +.btn-check:focus + .btn-outline-light, .btn-outline-light:focus { + box-shadow: 0 0 0 0.25rem rgba(248, 249, 250, 0.5); +} + +.btn-check:checked + .btn-outline-light, .btn-check:active + .btn-outline-light, .btn-outline-light:active, .btn-outline-light.active, .btn-outline-light.dropdown-toggle.show { + color: #000; + background-color: #f8f9fa; + border-color: #f8f9fa; +} + +.btn-check:checked + .btn-outline-light:focus, .btn-check:active + .btn-outline-light:focus, .btn-outline-light:active:focus, .btn-outline-light.active:focus, .btn-outline-light.dropdown-toggle.show:focus { + box-shadow: 0 0 0 0.25rem rgba(248, 249, 250, 0.5); +} + +.btn-outline-light:disabled, .btn-outline-light.disabled { + color: #f8f9fa; + background-color: transparent; +} + +.btn-outline-dark { + color: #212529; + border-color: #212529; +} + +.btn-outline-dark:hover { + color: #fff; + background-color: #212529; + border-color: #212529; +} + +.btn-check:focus + .btn-outline-dark, .btn-outline-dark:focus { + box-shadow: 0 0 0 0.25rem rgba(33, 37, 41, 0.5); +} + +.btn-check:checked + .btn-outline-dark, .btn-check:active + .btn-outline-dark, .btn-outline-dark:active, .btn-outline-dark.active, .btn-outline-dark.dropdown-toggle.show { + color: #fff; + background-color: #212529; + border-color: #212529; +} + +.btn-check:checked + .btn-outline-dark:focus, .btn-check:active + .btn-outline-dark:focus, .btn-outline-dark:active:focus, .btn-outline-dark.active:focus, .btn-outline-dark.dropdown-toggle.show:focus { + box-shadow: 0 0 0 0.25rem rgba(33, 37, 41, 0.5); +} + +.btn-outline-dark:disabled, .btn-outline-dark.disabled { + color: #212529; + background-color: transparent; +} + +.btn-link { + font-weight: 400; + color: #0d6efd; + text-decoration: underline; +} + +.btn-link:hover { + color: #0a58ca; +} + +.btn-link:disabled, .btn-link.disabled { + color: #6c757d; +} + +.btn-lg, .btn-group-lg > .btn { + padding: 0.5rem 1rem; + font-size: 1.25rem; + border-radius: 0.3rem; +} + +.btn-sm, .btn-group-sm > .btn { + padding: 0.25rem 0.5rem; + font-size: 0.875rem; + border-radius: 0.2rem; +} + +.fade { + transition: opacity 0.15s linear; +} + +@media (prefers-reduced-motion: reduce) { + .fade { + transition: none; + } +} + +.fade:not(.show) { + opacity: 0; +} + +.collapse:not(.show) { + display: none; +} + +.collapsing { + height: 0; + overflow: hidden; + transition: height 0.35s ease; +} + +@media (prefers-reduced-motion: reduce) { + .collapsing { + transition: none; + } +} + +.collapsing.collapse-horizontal { + width: 0; + height: auto; + transition: width 0.35s ease; +} + +@media (prefers-reduced-motion: reduce) { + .collapsing.collapse-horizontal { + transition: none; + } +} + +.dropup, +.dropend, +.dropdown, +.dropstart { + position: relative; +} + +.dropdown-toggle { + white-space: nowrap; +} + +.dropdown-toggle::after { + display: inline-block; + margin-left: 0.255em; + vertical-align: 0.255em; + content: ""; + border-top: 0.3em solid; + border-right: 0.3em solid transparent; + border-bottom: 0; + border-left: 0.3em solid transparent; +} + +.dropdown-toggle:empty::after { + margin-left: 0; +} + +.dropdown-menu { + position: absolute; + z-index: 1000; + display: none; + min-width: 10rem; + padding: 0.5rem 0; + margin: 0; + font-size: 1rem; + color: #212529; + text-align: left; + list-style: none; + background-color: #fff; + background-clip: padding-box; + border: 1px solid rgba(0, 0, 0, 0.15); + border-radius: 0.25rem; +} + +.dropdown-menu[data-bs-popper] { + top: 100%; + left: 0; + margin-top: 0.125rem; +} + +.dropdown-menu-start { + --bs-position: start; +} + +.dropdown-menu-start[data-bs-popper] { + right: auto; + left: 0; +} + +.dropdown-menu-end { + --bs-position: end; +} + +.dropdown-menu-end[data-bs-popper] { + right: 0; + left: auto; +} + +@media (min-width: 576px) { + .dropdown-menu-sm-start { + --bs-position: start; + } + + .dropdown-menu-sm-start[data-bs-popper] { + right: auto; + left: 0; + } + + .dropdown-menu-sm-end { + --bs-position: end; + } + + .dropdown-menu-sm-end[data-bs-popper] { + right: 0; + left: auto; + } +} + +@media (min-width: 768px) { + .dropdown-menu-md-start { + --bs-position: start; + } + + .dropdown-menu-md-start[data-bs-popper] { + right: auto; + left: 0; + } + + .dropdown-menu-md-end { + --bs-position: end; + } + + .dropdown-menu-md-end[data-bs-popper] { + right: 0; + left: auto; + } +} + +@media (min-width: 992px) { + .dropdown-menu-lg-start { + --bs-position: start; + } + + .dropdown-menu-lg-start[data-bs-popper] { + right: auto; + left: 0; + } + + .dropdown-menu-lg-end { + --bs-position: end; + } + + .dropdown-menu-lg-end[data-bs-popper] { + right: 0; + left: auto; + } +} + +@media (min-width: 1200px) { + .dropdown-menu-xl-start { + --bs-position: start; + } + + .dropdown-menu-xl-start[data-bs-popper] { + right: auto; + left: 0; + } + + .dropdown-menu-xl-end { + --bs-position: end; + } + + .dropdown-menu-xl-end[data-bs-popper] { + right: 0; + left: auto; + } +} + +@media (min-width: 1400px) { + .dropdown-menu-xxl-start { + --bs-position: start; + } + + .dropdown-menu-xxl-start[data-bs-popper] { + right: auto; + left: 0; + } + + .dropdown-menu-xxl-end { + --bs-position: end; + } + + .dropdown-menu-xxl-end[data-bs-popper] { + right: 0; + left: auto; + } +} + +.dropup .dropdown-menu[data-bs-popper] { + top: auto; + bottom: 100%; + margin-top: 0; + margin-bottom: 0.125rem; +} + +.dropup .dropdown-toggle::after { + display: inline-block; + margin-left: 0.255em; + vertical-align: 0.255em; + content: ""; + border-top: 0; + border-right: 0.3em solid transparent; + border-bottom: 0.3em solid; + border-left: 0.3em solid transparent; +} + +.dropup .dropdown-toggle:empty::after { + margin-left: 0; +} + +.dropend .dropdown-menu[data-bs-popper] { + top: 0; + right: auto; + left: 100%; + margin-top: 0; + margin-left: 0.125rem; +} + +.dropend .dropdown-toggle::after { + display: inline-block; + margin-left: 0.255em; + vertical-align: 0.255em; + content: ""; + border-top: 0.3em solid transparent; + border-right: 0; + border-bottom: 0.3em solid transparent; + border-left: 0.3em solid; +} + +.dropend .dropdown-toggle:empty::after { + margin-left: 0; +} + +.dropend .dropdown-toggle::after { + vertical-align: 0; +} + +.dropstart .dropdown-menu[data-bs-popper] { + top: 0; + right: 100%; + left: auto; + margin-top: 0; + margin-right: 0.125rem; +} + +.dropstart .dropdown-toggle::after { + display: inline-block; + margin-left: 0.255em; + vertical-align: 0.255em; + content: ""; +} + +.dropstart .dropdown-toggle::after { + display: none; +} + +.dropstart .dropdown-toggle::before { + display: inline-block; + margin-right: 0.255em; + vertical-align: 0.255em; + content: ""; + border-top: 0.3em solid transparent; + border-right: 0.3em solid; + border-bottom: 0.3em solid transparent; +} + +.dropstart .dropdown-toggle:empty::after { + margin-left: 0; +} + +.dropstart .dropdown-toggle::before { + vertical-align: 0; +} + +.dropdown-divider { + height: 0; + margin: 0.5rem 0; + overflow: hidden; + border-top: 1px solid rgba(0, 0, 0, 0.15); +} + +.dropdown-item { + display: block; + width: 100%; + padding: 0.25rem 1rem; + clear: both; + font-weight: 400; + color: #212529; + text-align: inherit; + text-decoration: none; + white-space: nowrap; + background-color: transparent; + border: 0; +} + +.dropdown-item:hover, .dropdown-item:focus { + color: #1e2125; + background-color: #e9ecef; +} + +.dropdown-item.active, .dropdown-item:active { + color: #fff; + text-decoration: none; + background-color: #0d6efd; +} + +.dropdown-item.disabled, .dropdown-item:disabled { + color: #adb5bd; + pointer-events: none; + background-color: transparent; +} + +.dropdown-menu.show { + display: block; +} + +.dropdown-header { + display: block; + padding: 0.5rem 1rem; + margin-bottom: 0; + font-size: 0.875rem; + color: #6c757d; + white-space: nowrap; +} + +.dropdown-item-text { + display: block; + padding: 0.25rem 1rem; + color: #212529; +} + +.dropdown-menu-dark { + color: #dee2e6; + background-color: #343a40; + border-color: rgba(0, 0, 0, 0.15); +} + +.dropdown-menu-dark .dropdown-item { + color: #dee2e6; +} + +.dropdown-menu-dark .dropdown-item:hover, .dropdown-menu-dark .dropdown-item:focus { + color: #fff; + background-color: rgba(255, 255, 255, 0.15); +} + +.dropdown-menu-dark .dropdown-item.active, .dropdown-menu-dark .dropdown-item:active { + color: #fff; + background-color: #0d6efd; +} + +.dropdown-menu-dark .dropdown-item.disabled, .dropdown-menu-dark .dropdown-item:disabled { + color: #adb5bd; +} + +.dropdown-menu-dark .dropdown-divider { + border-color: rgba(0, 0, 0, 0.15); +} + +.dropdown-menu-dark .dropdown-item-text { + color: #dee2e6; +} + +.dropdown-menu-dark .dropdown-header { + color: #adb5bd; +} + +.btn-group, +.btn-group-vertical { + position: relative; + display: inline-flex; + vertical-align: middle; +} + +.btn-group > .btn, +.btn-group-vertical > .btn { + position: relative; + flex: 1 1 auto; +} + +.btn-group > .btn-check:checked + .btn, +.btn-group > .btn-check:focus + .btn, +.btn-group > .btn:hover, +.btn-group > .btn:focus, +.btn-group > .btn:active, +.btn-group > .btn.active, +.btn-group-vertical > .btn-check:checked + .btn, +.btn-group-vertical > .btn-check:focus + .btn, +.btn-group-vertical > .btn:hover, +.btn-group-vertical > .btn:focus, +.btn-group-vertical > .btn:active, +.btn-group-vertical > .btn.active { + z-index: 1; +} + +.btn-toolbar { + display: flex; + flex-wrap: wrap; + justify-content: flex-start; +} + +.btn-toolbar .input-group { + width: auto; +} + +.btn-group > .btn:not(:first-child), +.btn-group > .btn-group:not(:first-child) { + margin-left: -1px; +} + +.btn-group > .btn:not(:last-child):not(.dropdown-toggle), +.btn-group > .btn-group:not(:last-child) > .btn { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.btn-group > .btn:nth-child(n+3), +.btn-group > :not(.btn-check) + .btn, +.btn-group > .btn-group:not(:first-child) > .btn { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +.dropdown-toggle-split { + padding-right: 0.5625rem; + padding-left: 0.5625rem; +} + +.dropdown-toggle-split::after, .dropup .dropdown-toggle-split::after, .dropend .dropdown-toggle-split::after { + margin-left: 0; +} + +.dropstart .dropdown-toggle-split::before { + margin-right: 0; +} + +.btn-sm + .dropdown-toggle-split, .btn-group-sm > .btn + .dropdown-toggle-split { + padding-right: 0.375rem; + padding-left: 0.375rem; +} + +.btn-lg + .dropdown-toggle-split, .btn-group-lg > .btn + .dropdown-toggle-split { + padding-right: 0.75rem; + padding-left: 0.75rem; +} + +.btn-group-vertical { + flex-direction: column; + align-items: flex-start; + justify-content: center; +} + +.btn-group-vertical > .btn, +.btn-group-vertical > .btn-group { + width: 100%; +} + +.btn-group-vertical > .btn:not(:first-child), +.btn-group-vertical > .btn-group:not(:first-child) { + margin-top: -1px; +} + +.btn-group-vertical > .btn:not(:last-child):not(.dropdown-toggle), +.btn-group-vertical > .btn-group:not(:last-child) > .btn { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} + +.btn-group-vertical > .btn ~ .btn, +.btn-group-vertical > .btn-group:not(:first-child) > .btn { + border-top-left-radius: 0; + border-top-right-radius: 0; +} + +.nav { + display: flex; + flex-wrap: wrap; + padding-left: 0; + margin-bottom: 0; + list-style: none; +} + +.nav-link { + display: block; + padding: 0.5rem 1rem; + color: #0d6efd; + text-decoration: none; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out; +} + +@media (prefers-reduced-motion: reduce) { + .nav-link { + transition: none; + } +} + +.nav-link:hover, .nav-link:focus { + color: #0a58ca; +} + +.nav-link.disabled { + color: #6c757d; + pointer-events: none; + cursor: default; +} + +.nav-tabs { + border-bottom: 1px solid #dee2e6; +} + +.nav-tabs .nav-link { + margin-bottom: -1px; + background: none; + border: 1px solid transparent; + border-top-left-radius: 0.25rem; + border-top-right-radius: 0.25rem; +} + +.nav-tabs .nav-link:hover, .nav-tabs .nav-link:focus { + border-color: #e9ecef #e9ecef #dee2e6; + isolation: isolate; +} + +.nav-tabs .nav-link.disabled { + color: #6c757d; + background-color: transparent; + border-color: transparent; +} + +.nav-tabs .nav-link.active, +.nav-tabs .nav-item.show .nav-link { + color: #495057; + background-color: #fff; + border-color: #dee2e6 #dee2e6 #fff; +} + +.nav-tabs .dropdown-menu { + margin-top: -1px; + border-top-left-radius: 0; + border-top-right-radius: 0; +} + +.nav-pills .nav-link { + background: none; + border: 0; + border-radius: 0.25rem; +} + +.nav-pills .nav-link.active, +.nav-pills .show > .nav-link { + color: #fff; + background-color: #0d6efd; +} + +.nav-fill > .nav-link, +.nav-fill .nav-item { + flex: 1 1 auto; + text-align: center; +} + +.nav-justified > .nav-link, +.nav-justified .nav-item { + flex-basis: 0; + flex-grow: 1; + text-align: center; +} + +.nav-fill .nav-item .nav-link, +.nav-justified .nav-item .nav-link { + width: 100%; +} + +.tab-content > .tab-pane { + display: none; +} + +.tab-content > .active { + display: block; +} + +.navbar { + position: relative; + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: space-between; + padding-top: 0.5rem; + padding-bottom: 0.5rem; +} + +.navbar > .container, +.navbar > .container-fluid, +.navbar > .container-sm, +.navbar > .container-md, +.navbar > .container-lg, +.navbar > .container-xl, +.navbar > .container-xxl { + display: flex; + flex-wrap: inherit; + align-items: center; + justify-content: space-between; +} + +.navbar-brand { + padding-top: 0.3125rem; + padding-bottom: 0.3125rem; + margin-right: 1rem; + font-size: 1.25rem; + text-decoration: none; + white-space: nowrap; +} + +.navbar-nav { + display: flex; + flex-direction: column; + padding-left: 0; + margin-bottom: 0; + list-style: none; +} + +.navbar-nav .nav-link { + padding-right: 0; + padding-left: 0; +} + +.navbar-nav .dropdown-menu { + position: static; +} + +.navbar-text { + padding-top: 0.5rem; + padding-bottom: 0.5rem; +} + +.navbar-collapse { + flex-basis: 100%; + flex-grow: 1; + align-items: center; +} + +.navbar-toggler { + padding: 0.25rem 0.75rem; + font-size: 1.25rem; + line-height: 1; + background-color: transparent; + border: 1px solid transparent; + border-radius: 0.25rem; + transition: box-shadow 0.15s ease-in-out; +} + +@media (prefers-reduced-motion: reduce) { + .navbar-toggler { + transition: none; + } +} + +.navbar-toggler:hover { + text-decoration: none; +} + +.navbar-toggler:focus { + text-decoration: none; + outline: 0; + box-shadow: 0 0 0 0.25rem; +} + +.navbar-toggler-icon { + display: inline-block; + width: 1.5em; + height: 1.5em; + vertical-align: middle; + background-repeat: no-repeat; + background-position: center; + background-size: 100%; +} + +.navbar-nav-scroll { + max-height: var(--bs-scroll-height, 75vh); + overflow-y: auto; +} + +@media (min-width: 576px) { + .navbar-expand-sm { + flex-wrap: nowrap; + justify-content: flex-start; + } + + .navbar-expand-sm .navbar-nav { + flex-direction: row; + } + + .navbar-expand-sm .navbar-nav .dropdown-menu { + position: absolute; + } + + .navbar-expand-sm .navbar-nav .nav-link { + padding-right: 0.5rem; + padding-left: 0.5rem; + } + + .navbar-expand-sm .navbar-nav-scroll { + overflow: visible; + } + + .navbar-expand-sm .navbar-collapse { + display: flex !important; + flex-basis: auto; + } + + .navbar-expand-sm .navbar-toggler { + display: none; + } + + .navbar-expand-sm .offcanvas-header { + display: none; + } + + .navbar-expand-sm .offcanvas { + position: inherit; + bottom: 0; + z-index: 1000; + flex-grow: 1; + visibility: visible !important; + background-color: transparent; + border-right: 0; + border-left: 0; + transition: none; + transform: none; + } + + .navbar-expand-sm .offcanvas-top, + .navbar-expand-sm .offcanvas-bottom { + height: auto; + border-top: 0; + border-bottom: 0; + } + + .navbar-expand-sm .offcanvas-body { + display: flex; + flex-grow: 0; + padding: 0; + overflow-y: visible; + } +} + +@media (min-width: 768px) { + .navbar-expand-md { + flex-wrap: nowrap; + justify-content: flex-start; + } + + .navbar-expand-md .navbar-nav { + flex-direction: row; + } + + .navbar-expand-md .navbar-nav .dropdown-menu { + position: absolute; + } + + .navbar-expand-md .navbar-nav .nav-link { + padding-right: 0.5rem; + padding-left: 0.5rem; + } + + .navbar-expand-md .navbar-nav-scroll { + overflow: visible; + } + + .navbar-expand-md .navbar-collapse { + display: flex !important; + flex-basis: auto; + } + + .navbar-expand-md .navbar-toggler { + display: none; + } + + .navbar-expand-md .offcanvas-header { + display: none; + } + + .navbar-expand-md .offcanvas { + position: inherit; + bottom: 0; + z-index: 1000; + flex-grow: 1; + visibility: visible !important; + background-color: transparent; + border-right: 0; + border-left: 0; + transition: none; + transform: none; + } + + .navbar-expand-md .offcanvas-top, + .navbar-expand-md .offcanvas-bottom { + height: auto; + border-top: 0; + border-bottom: 0; + } + + .navbar-expand-md .offcanvas-body { + display: flex; + flex-grow: 0; + padding: 0; + overflow-y: visible; + } +} + +@media (min-width: 992px) { + .navbar-expand-lg { + flex-wrap: nowrap; + justify-content: flex-start; + } + + .navbar-expand-lg .navbar-nav { + flex-direction: row; + } + + .navbar-expand-lg .navbar-nav .dropdown-menu { + position: absolute; + } + + .navbar-expand-lg .navbar-nav .nav-link { + padding-right: 0.5rem; + padding-left: 0.5rem; + } + + .navbar-expand-lg .navbar-nav-scroll { + overflow: visible; + } + + .navbar-expand-lg .navbar-collapse { + display: flex !important; + flex-basis: auto; + } + + .navbar-expand-lg .navbar-toggler { + display: none; + } + + .navbar-expand-lg .offcanvas-header { + display: none; + } + + .navbar-expand-lg .offcanvas { + position: inherit; + bottom: 0; + z-index: 1000; + flex-grow: 1; + visibility: visible !important; + background-color: transparent; + border-right: 0; + border-left: 0; + transition: none; + transform: none; + } + + .navbar-expand-lg .offcanvas-top, + .navbar-expand-lg .offcanvas-bottom { + height: auto; + border-top: 0; + border-bottom: 0; + } + + .navbar-expand-lg .offcanvas-body { + display: flex; + flex-grow: 0; + padding: 0; + overflow-y: visible; + } +} + +@media (min-width: 1200px) { + .navbar-expand-xl { + flex-wrap: nowrap; + justify-content: flex-start; + } + + .navbar-expand-xl .navbar-nav { + flex-direction: row; + } + + .navbar-expand-xl .navbar-nav .dropdown-menu { + position: absolute; + } + + .navbar-expand-xl .navbar-nav .nav-link { + padding-right: 0.5rem; + padding-left: 0.5rem; + } + + .navbar-expand-xl .navbar-nav-scroll { + overflow: visible; + } + + .navbar-expand-xl .navbar-collapse { + display: flex !important; + flex-basis: auto; + } + + .navbar-expand-xl .navbar-toggler { + display: none; + } + + .navbar-expand-xl .offcanvas-header { + display: none; + } + + .navbar-expand-xl .offcanvas { + position: inherit; + bottom: 0; + z-index: 1000; + flex-grow: 1; + visibility: visible !important; + background-color: transparent; + border-right: 0; + border-left: 0; + transition: none; + transform: none; + } + + .navbar-expand-xl .offcanvas-top, + .navbar-expand-xl .offcanvas-bottom { + height: auto; + border-top: 0; + border-bottom: 0; + } + + .navbar-expand-xl .offcanvas-body { + display: flex; + flex-grow: 0; + padding: 0; + overflow-y: visible; + } +} + +@media (min-width: 1400px) { + .navbar-expand-xxl { + flex-wrap: nowrap; + justify-content: flex-start; + } + + .navbar-expand-xxl .navbar-nav { + flex-direction: row; + } + + .navbar-expand-xxl .navbar-nav .dropdown-menu { + position: absolute; + } + + .navbar-expand-xxl .navbar-nav .nav-link { + padding-right: 0.5rem; + padding-left: 0.5rem; + } + + .navbar-expand-xxl .navbar-nav-scroll { + overflow: visible; + } + + .navbar-expand-xxl .navbar-collapse { + display: flex !important; + flex-basis: auto; + } + + .navbar-expand-xxl .navbar-toggler { + display: none; + } + + .navbar-expand-xxl .offcanvas-header { + display: none; + } + + .navbar-expand-xxl .offcanvas { + position: inherit; + bottom: 0; + z-index: 1000; + flex-grow: 1; + visibility: visible !important; + background-color: transparent; + border-right: 0; + border-left: 0; + transition: none; + transform: none; + } + + .navbar-expand-xxl .offcanvas-top, + .navbar-expand-xxl .offcanvas-bottom { + height: auto; + border-top: 0; + border-bottom: 0; + } + + .navbar-expand-xxl .offcanvas-body { + display: flex; + flex-grow: 0; + padding: 0; + overflow-y: visible; + } +} + +.navbar-expand { + flex-wrap: nowrap; + justify-content: flex-start; +} + +.navbar-expand .navbar-nav { + flex-direction: row; +} + +.navbar-expand .navbar-nav .dropdown-menu { + position: absolute; +} + +.navbar-expand .navbar-nav .nav-link { + padding-right: 0.5rem; + padding-left: 0.5rem; +} + +.navbar-expand .navbar-nav-scroll { + overflow: visible; +} + +.navbar-expand .navbar-collapse { + display: flex !important; + flex-basis: auto; +} + +.navbar-expand .navbar-toggler { + display: none; +} + +.navbar-expand .offcanvas-header { + display: none; +} + +.navbar-expand .offcanvas { + position: inherit; + bottom: 0; + z-index: 1000; + flex-grow: 1; + visibility: visible !important; + background-color: transparent; + border-right: 0; + border-left: 0; + transition: none; + transform: none; +} + +.navbar-expand .offcanvas-top, +.navbar-expand .offcanvas-bottom { + height: auto; + border-top: 0; + border-bottom: 0; +} + +.navbar-expand .offcanvas-body { + display: flex; + flex-grow: 0; + padding: 0; + overflow-y: visible; +} + +.navbar-light .navbar-brand { + color: rgba(0, 0, 0, 0.9); +} + +.navbar-light .navbar-brand:hover, .navbar-light .navbar-brand:focus { + color: rgba(0, 0, 0, 0.9); +} + +.navbar-light .navbar-nav .nav-link { + color: rgba(0, 0, 0, 0.55); +} + +.navbar-light .navbar-nav .nav-link:hover, .navbar-light .navbar-nav .nav-link:focus { + color: rgba(0, 0, 0, 0.7); +} + +.navbar-light .navbar-nav .nav-link.disabled { + color: rgba(0, 0, 0, 0.3); +} + +.navbar-light .navbar-nav .show > .nav-link, +.navbar-light .navbar-nav .nav-link.active { + color: rgba(0, 0, 0, 0.9); +} + +.navbar-light .navbar-toggler { + color: rgba(0, 0, 0, 0.55); + border-color: rgba(0, 0, 0, 0.1); +} + +.navbar-light .navbar-toggler-icon { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%280, 0, 0, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"); +} + +.navbar-light .navbar-text { + color: rgba(0, 0, 0, 0.55); +} + +.navbar-light .navbar-text a, +.navbar-light .navbar-text a:hover, +.navbar-light .navbar-text a:focus { + color: rgba(0, 0, 0, 0.9); +} + +.navbar-dark .navbar-brand { + color: #fff; +} + +.navbar-dark .navbar-brand:hover, .navbar-dark .navbar-brand:focus { + color: #fff; +} + +.navbar-dark .navbar-nav .nav-link { + color: rgba(255, 255, 255, 0.55); +} + +.navbar-dark .navbar-nav .nav-link:hover, .navbar-dark .navbar-nav .nav-link:focus { + color: rgba(255, 255, 255, 0.75); +} + +.navbar-dark .navbar-nav .nav-link.disabled { + color: rgba(255, 255, 255, 0.25); +} + +.navbar-dark .navbar-nav .show > .nav-link, +.navbar-dark .navbar-nav .nav-link.active { + color: #fff; +} + +.navbar-dark .navbar-toggler { + color: rgba(255, 255, 255, 0.55); + border-color: rgba(255, 255, 255, 0.1); +} + +.navbar-dark .navbar-toggler-icon { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"); +} + +.navbar-dark .navbar-text { + color: rgba(255, 255, 255, 0.55); +} + +.navbar-dark .navbar-text a, +.navbar-dark .navbar-text a:hover, +.navbar-dark .navbar-text a:focus { + color: #fff; +} + +.card { + position: relative; + display: flex; + flex-direction: column; + min-width: 0; + word-wrap: break-word; + background-color: #fff; + background-clip: border-box; + border: 1px solid rgba(0, 0, 0, 0.125); + border-radius: 0.25rem; +} + +.card > hr { + margin-right: 0; + margin-left: 0; +} + +.card > .list-group { + border-top: inherit; + border-bottom: inherit; +} + +.card > .list-group:first-child { + border-top-width: 0; + border-top-left-radius: calc(0.25rem - 1px); + border-top-right-radius: calc(0.25rem - 1px); +} + +.card > .list-group:last-child { + border-bottom-width: 0; + border-bottom-right-radius: calc(0.25rem - 1px); + border-bottom-left-radius: calc(0.25rem - 1px); +} + +.card > .card-header + .list-group, +.card > .list-group + .card-footer { + border-top: 0; +} + +.card-body { + flex: 1 1 auto; + padding: 1rem 1rem; +} + +.card-title { + margin-bottom: 0.5rem; +} + +.card-subtitle { + margin-top: -0.25rem; + margin-bottom: 0; +} + +.card-text:last-child { + margin-bottom: 0; +} + +.card-link + .card-link { + margin-left: 1rem; +} + +.card-header { + padding: 0.5rem 1rem; + margin-bottom: 0; + background-color: rgba(0, 0, 0, 0.03); + border-bottom: 1px solid rgba(0, 0, 0, 0.125); +} + +.card-header:first-child { + border-radius: calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0; +} + +.card-footer { + padding: 0.5rem 1rem; + background-color: rgba(0, 0, 0, 0.03); + border-top: 1px solid rgba(0, 0, 0, 0.125); +} + +.card-footer:last-child { + border-radius: 0 0 calc(0.25rem - 1px) calc(0.25rem - 1px); +} + +.card-header-tabs { + margin-right: -0.5rem; + margin-bottom: -0.5rem; + margin-left: -0.5rem; + border-bottom: 0; +} + +.card-header-pills { + margin-right: -0.5rem; + margin-left: -0.5rem; +} + +.card-img-overlay { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + padding: 1rem; + border-radius: calc(0.25rem - 1px); +} + +.card-img, +.card-img-top, +.card-img-bottom { + width: 100%; +} + +.card-img, +.card-img-top { + border-top-left-radius: calc(0.25rem - 1px); + border-top-right-radius: calc(0.25rem - 1px); +} + +.card-img, +.card-img-bottom { + border-bottom-right-radius: calc(0.25rem - 1px); + border-bottom-left-radius: calc(0.25rem - 1px); +} + +.card-group > .card { + margin-bottom: 0.75rem; +} + +@media (min-width: 576px) { + .card-group { + display: flex; + flex-flow: row wrap; + } + + .card-group > .card { + flex: 1 0 0%; + margin-bottom: 0; + } + + .card-group > .card + .card { + margin-left: 0; + border-left: 0; + } + + .card-group > .card:not(:last-child) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + } + + .card-group > .card:not(:last-child) .card-img-top, + .card-group > .card:not(:last-child) .card-header { + border-top-right-radius: 0; + } + + .card-group > .card:not(:last-child) .card-img-bottom, + .card-group > .card:not(:last-child) .card-footer { + border-bottom-right-radius: 0; + } + + .card-group > .card:not(:first-child) { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + } + + .card-group > .card:not(:first-child) .card-img-top, + .card-group > .card:not(:first-child) .card-header { + border-top-left-radius: 0; + } + + .card-group > .card:not(:first-child) .card-img-bottom, + .card-group > .card:not(:first-child) .card-footer { + border-bottom-left-radius: 0; + } +} + +.accordion-button { + position: relative; + display: flex; + align-items: center; + width: 100%; + padding: 1rem 1.25rem; + font-size: 1rem; + color: #212529; + text-align: left; + background-color: #fff; + border: 0; + border-radius: 0; + overflow-anchor: none; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, border-radius 0.15s ease; +} + +@media (prefers-reduced-motion: reduce) { + .accordion-button { + transition: none; + } +} + +.accordion-button:not(.collapsed) { + color: #0c63e4; + background-color: #e7f1ff; + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.125); +} + +.accordion-button:not(.collapsed)::after { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%230c63e4'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); + transform: rotate(-180deg); +} + +.accordion-button::after { + flex-shrink: 0; + width: 1.25rem; + height: 1.25rem; + margin-left: auto; + content: ""; + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23212529'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); + background-repeat: no-repeat; + background-size: 1.25rem; + transition: transform 0.2s ease-in-out; +} + +@media (prefers-reduced-motion: reduce) { + .accordion-button::after { + transition: none; + } +} + +.accordion-button:hover { + z-index: 2; +} + +.accordion-button:focus { + z-index: 3; + border-color: #86b7fe; + outline: 0; + box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); +} + +.accordion-header { + margin-bottom: 0; +} + +.accordion-item { + background-color: #fff; + border: 1px solid rgba(0, 0, 0, 0.125); +} + +.accordion-item:first-of-type { + border-top-left-radius: 0.25rem; + border-top-right-radius: 0.25rem; +} + +.accordion-item:first-of-type .accordion-button { + border-top-left-radius: calc(0.25rem - 1px); + border-top-right-radius: calc(0.25rem - 1px); +} + +.accordion-item:not(:first-of-type) { + border-top: 0; +} + +.accordion-item:last-of-type { + border-bottom-right-radius: 0.25rem; + border-bottom-left-radius: 0.25rem; +} + +.accordion-item:last-of-type .accordion-button.collapsed { + border-bottom-right-radius: calc(0.25rem - 1px); + border-bottom-left-radius: calc(0.25rem - 1px); +} + +.accordion-item:last-of-type .accordion-collapse { + border-bottom-right-radius: 0.25rem; + border-bottom-left-radius: 0.25rem; +} + +.accordion-body { + padding: 1rem 1.25rem; +} + +.accordion-flush .accordion-collapse { + border-width: 0; +} + +.accordion-flush .accordion-item { + border-right: 0; + border-left: 0; + border-radius: 0; +} + +.accordion-flush .accordion-item:first-child { + border-top: 0; +} + +.accordion-flush .accordion-item:last-child { + border-bottom: 0; +} + +.accordion-flush .accordion-item .accordion-button { + border-radius: 0; +} + +.breadcrumb { + display: flex; + flex-wrap: wrap; + padding: 0 0; + margin-bottom: 1rem; + list-style: none; +} + +.breadcrumb-item + .breadcrumb-item { + padding-left: 0.5rem; +} + +.breadcrumb-item + .breadcrumb-item::before { + float: left; + padding-right: 0.5rem; + color: #6c757d; + content: var(--bs-breadcrumb-divider, "/") /* rtl: var(--bs-breadcrumb-divider, "/") */; +} + +.breadcrumb-item.active { + color: #6c757d; +} + +.pagination { + display: flex; + padding-left: 0; + list-style: none; +} + +.page-link { + position: relative; + display: block; + color: #0d6efd; + text-decoration: none; + background-color: #fff; + border: 1px solid #dee2e6; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} + +@media (prefers-reduced-motion: reduce) { + .page-link { + transition: none; + } +} + +.page-link:hover { + z-index: 2; + color: #0a58ca; + background-color: #e9ecef; + border-color: #dee2e6; +} + +.page-link:focus { + z-index: 3; + color: #0a58ca; + background-color: #e9ecef; + outline: 0; + box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); +} + +.page-item:not(:first-child) .page-link { + margin-left: -1px; +} + +.page-item.active .page-link { + z-index: 3; + color: #fff; + background-color: #0d6efd; + border-color: #0d6efd; +} + +.page-item.disabled .page-link { + color: #6c757d; + pointer-events: none; + background-color: #fff; + border-color: #dee2e6; +} + +.page-link { + padding: 0.375rem 0.75rem; +} + +.page-item:first-child .page-link { + border-top-left-radius: 0.25rem; + border-bottom-left-radius: 0.25rem; +} + +.page-item:last-child .page-link { + border-top-right-radius: 0.25rem; + border-bottom-right-radius: 0.25rem; +} + +.pagination-lg .page-link { + padding: 0.75rem 1.5rem; + font-size: 1.25rem; +} + +.pagination-lg .page-item:first-child .page-link { + border-top-left-radius: 0.3rem; + border-bottom-left-radius: 0.3rem; +} + +.pagination-lg .page-item:last-child .page-link { + border-top-right-radius: 0.3rem; + border-bottom-right-radius: 0.3rem; +} + +.pagination-sm .page-link { + padding: 0.25rem 0.5rem; + font-size: 0.875rem; +} + +.pagination-sm .page-item:first-child .page-link { + border-top-left-radius: 0.2rem; + border-bottom-left-radius: 0.2rem; +} + +.pagination-sm .page-item:last-child .page-link { + border-top-right-radius: 0.2rem; + border-bottom-right-radius: 0.2rem; +} + +.badge { + display: inline-block; + padding: 0.35em 0.65em; + font-size: 0.75em; + font-weight: 700; + line-height: 1; + color: #fff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: 0.25rem; +} + +.badge:empty { + display: none; +} + +.btn .badge { + position: relative; + top: -1px; +} + +.alert { + position: relative; + padding: 1rem 1rem; + margin-bottom: 1rem; + border: 1px solid transparent; + border-radius: 0.25rem; +} + +.alert-heading { + color: inherit; +} + +.alert-link { + font-weight: 700; +} + +.alert-dismissible { + padding-right: 3rem; +} + +.alert-dismissible .btn-close { + position: absolute; + top: 0; + right: 0; + z-index: 2; + padding: 1.25rem 1rem; +} + +.alert-primary { + color: #084298; + background-color: #cfe2ff; + border-color: #b6d4fe; +} + +.alert-primary .alert-link { + color: #06357a; +} + +.alert-secondary { + color: #41464b; + background-color: #e2e3e5; + border-color: #d3d6d8; +} + +.alert-secondary .alert-link { + color: #34383c; +} + +.alert-success { + color: #0f5132; + background-color: #d1e7dd; + border-color: #badbcc; +} + +.alert-success .alert-link { + color: #0c4128; +} + +.alert-info { + color: #055160; + background-color: #cff4fc; + border-color: #b6effb; +} + +.alert-info .alert-link { + color: #04414d; +} + +.alert-warning { + color: #664d03; + background-color: #fff3cd; + border-color: #ffecb5; +} + +.alert-warning .alert-link { + color: #523e02; +} + +.alert-danger { + color: #842029; + background-color: #f8d7da; + border-color: #f5c2c7; +} + +.alert-danger .alert-link { + color: #6a1a21; +} + +.alert-light { + color: #636464; + background-color: #fefefe; + border-color: #fdfdfe; +} + +.alert-light .alert-link { + color: #4f5050; +} + +.alert-dark { + color: #141619; + background-color: #d3d3d4; + border-color: #bcbebf; +} + +.alert-dark .alert-link { + color: #101214; +} + +@-webkit-keyframes progress-bar-stripes { + 0% { + background-position-x: 1rem; + } +} + +@keyframes progress-bar-stripes { + 0% { + background-position-x: 1rem; + } +} + +.progress { + display: flex; + height: 1rem; + overflow: hidden; + font-size: 0.75rem; + background-color: #e9ecef; + border-radius: 0.25rem; +} + +.progress-bar { + display: flex; + flex-direction: column; + justify-content: center; + overflow: hidden; + color: #fff; + text-align: center; + white-space: nowrap; + background-color: #0d6efd; + transition: width 0.6s ease; +} + +@media (prefers-reduced-motion: reduce) { + .progress-bar { + transition: none; + } +} + +.progress-bar-striped { + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-size: 1rem 1rem; +} + +.progress-bar-animated { + -webkit-animation: 1s linear infinite progress-bar-stripes; + animation: 1s linear infinite progress-bar-stripes; +} + +@media (prefers-reduced-motion: reduce) { + .progress-bar-animated { + -webkit-animation: none; + animation: none; + } +} + +.list-group { + display: flex; + flex-direction: column; + padding-left: 0; + margin-bottom: 0; + border-radius: 0.25rem; +} + +.list-group-numbered { + list-style-type: none; + counter-reset: section; +} + +.list-group-numbered > li::before { + content: counters(section, ".") ". "; + counter-increment: section; +} + +.list-group-item-action { + width: 100%; + color: #495057; + text-align: inherit; +} + +.list-group-item-action:hover, .list-group-item-action:focus { + z-index: 1; + color: #495057; + text-decoration: none; + background-color: #f8f9fa; +} + +.list-group-item-action:active { + color: #212529; + background-color: #e9ecef; +} + +.list-group-item { + position: relative; + display: block; + padding: 0.5rem 1rem; + color: #212529; + text-decoration: none; + background-color: #fff; + border: 1px solid rgba(0, 0, 0, 0.125); +} + +.list-group-item:first-child { + border-top-left-radius: inherit; + border-top-right-radius: inherit; +} + +.list-group-item:last-child { + border-bottom-right-radius: inherit; + border-bottom-left-radius: inherit; +} + +.list-group-item.disabled, .list-group-item:disabled { + color: #6c757d; + pointer-events: none; + background-color: #fff; +} + +.list-group-item.active { + z-index: 2; + color: #fff; + background-color: #0d6efd; + border-color: #0d6efd; +} + +.list-group-item + .list-group-item { + border-top-width: 0; +} + +.list-group-item + .list-group-item.active { + margin-top: -1px; + border-top-width: 1px; +} + +.list-group-horizontal { + flex-direction: row; +} + +.list-group-horizontal > .list-group-item:first-child { + border-bottom-left-radius: 0.25rem; + border-top-right-radius: 0; +} + +.list-group-horizontal > .list-group-item:last-child { + border-top-right-radius: 0.25rem; + border-bottom-left-radius: 0; +} + +.list-group-horizontal > .list-group-item.active { + margin-top: 0; +} + +.list-group-horizontal > .list-group-item + .list-group-item { + border-top-width: 1px; + border-left-width: 0; +} + +.list-group-horizontal > .list-group-item + .list-group-item.active { + margin-left: -1px; + border-left-width: 1px; +} + +@media (min-width: 576px) { + .list-group-horizontal-sm { + flex-direction: row; + } + + .list-group-horizontal-sm > .list-group-item:first-child { + border-bottom-left-radius: 0.25rem; + border-top-right-radius: 0; + } + + .list-group-horizontal-sm > .list-group-item:last-child { + border-top-right-radius: 0.25rem; + border-bottom-left-radius: 0; + } + + .list-group-horizontal-sm > .list-group-item.active { + margin-top: 0; + } + + .list-group-horizontal-sm > .list-group-item + .list-group-item { + border-top-width: 1px; + border-left-width: 0; + } + + .list-group-horizontal-sm > .list-group-item + .list-group-item.active { + margin-left: -1px; + border-left-width: 1px; + } +} + +@media (min-width: 768px) { + .list-group-horizontal-md { + flex-direction: row; + } + + .list-group-horizontal-md > .list-group-item:first-child { + border-bottom-left-radius: 0.25rem; + border-top-right-radius: 0; + } + + .list-group-horizontal-md > .list-group-item:last-child { + border-top-right-radius: 0.25rem; + border-bottom-left-radius: 0; + } + + .list-group-horizontal-md > .list-group-item.active { + margin-top: 0; + } + + .list-group-horizontal-md > .list-group-item + .list-group-item { + border-top-width: 1px; + border-left-width: 0; + } + + .list-group-horizontal-md > .list-group-item + .list-group-item.active { + margin-left: -1px; + border-left-width: 1px; + } +} + +@media (min-width: 992px) { + .list-group-horizontal-lg { + flex-direction: row; + } + + .list-group-horizontal-lg > .list-group-item:first-child { + border-bottom-left-radius: 0.25rem; + border-top-right-radius: 0; + } + + .list-group-horizontal-lg > .list-group-item:last-child { + border-top-right-radius: 0.25rem; + border-bottom-left-radius: 0; + } + + .list-group-horizontal-lg > .list-group-item.active { + margin-top: 0; + } + + .list-group-horizontal-lg > .list-group-item + .list-group-item { + border-top-width: 1px; + border-left-width: 0; + } + + .list-group-horizontal-lg > .list-group-item + .list-group-item.active { + margin-left: -1px; + border-left-width: 1px; + } +} + +@media (min-width: 1200px) { + .list-group-horizontal-xl { + flex-direction: row; + } + + .list-group-horizontal-xl > .list-group-item:first-child { + border-bottom-left-radius: 0.25rem; + border-top-right-radius: 0; + } + + .list-group-horizontal-xl > .list-group-item:last-child { + border-top-right-radius: 0.25rem; + border-bottom-left-radius: 0; + } + + .list-group-horizontal-xl > .list-group-item.active { + margin-top: 0; + } + + .list-group-horizontal-xl > .list-group-item + .list-group-item { + border-top-width: 1px; + border-left-width: 0; + } + + .list-group-horizontal-xl > .list-group-item + .list-group-item.active { + margin-left: -1px; + border-left-width: 1px; + } +} + +@media (min-width: 1400px) { + .list-group-horizontal-xxl { + flex-direction: row; + } + + .list-group-horizontal-xxl > .list-group-item:first-child { + border-bottom-left-radius: 0.25rem; + border-top-right-radius: 0; + } + + .list-group-horizontal-xxl > .list-group-item:last-child { + border-top-right-radius: 0.25rem; + border-bottom-left-radius: 0; + } + + .list-group-horizontal-xxl > .list-group-item.active { + margin-top: 0; + } + + .list-group-horizontal-xxl > .list-group-item + .list-group-item { + border-top-width: 1px; + border-left-width: 0; + } + + .list-group-horizontal-xxl > .list-group-item + .list-group-item.active { + margin-left: -1px; + border-left-width: 1px; + } +} + +.list-group-flush { + border-radius: 0; +} + +.list-group-flush > .list-group-item { + border-width: 0 0 1px; +} + +.list-group-flush > .list-group-item:last-child { + border-bottom-width: 0; +} + +.list-group-item-primary { + color: #084298; + background-color: #cfe2ff; +} + +.list-group-item-primary.list-group-item-action:hover, .list-group-item-primary.list-group-item-action:focus { + color: #084298; + background-color: #bacbe6; +} + +.list-group-item-primary.list-group-item-action.active { + color: #fff; + background-color: #084298; + border-color: #084298; +} + +.list-group-item-secondary { + color: #41464b; + background-color: #e2e3e5; +} + +.list-group-item-secondary.list-group-item-action:hover, .list-group-item-secondary.list-group-item-action:focus { + color: #41464b; + background-color: #cbccce; +} + +.list-group-item-secondary.list-group-item-action.active { + color: #fff; + background-color: #41464b; + border-color: #41464b; +} + +.list-group-item-success { + color: #0f5132; + background-color: #d1e7dd; +} + +.list-group-item-success.list-group-item-action:hover, .list-group-item-success.list-group-item-action:focus { + color: #0f5132; + background-color: #bcd0c7; +} + +.list-group-item-success.list-group-item-action.active { + color: #fff; + background-color: #0f5132; + border-color: #0f5132; +} + +.list-group-item-info { + color: #055160; + background-color: #cff4fc; +} + +.list-group-item-info.list-group-item-action:hover, .list-group-item-info.list-group-item-action:focus { + color: #055160; + background-color: #badce3; +} + +.list-group-item-info.list-group-item-action.active { + color: #fff; + background-color: #055160; + border-color: #055160; +} + +.list-group-item-warning { + color: #664d03; + background-color: #fff3cd; +} + +.list-group-item-warning.list-group-item-action:hover, .list-group-item-warning.list-group-item-action:focus { + color: #664d03; + background-color: #e6dbb9; +} + +.list-group-item-warning.list-group-item-action.active { + color: #fff; + background-color: #664d03; + border-color: #664d03; +} + +.list-group-item-danger { + color: #842029; + background-color: #f8d7da; +} + +.list-group-item-danger.list-group-item-action:hover, .list-group-item-danger.list-group-item-action:focus { + color: #842029; + background-color: #dfc2c4; +} + +.list-group-item-danger.list-group-item-action.active { + color: #fff; + background-color: #842029; + border-color: #842029; +} + +.list-group-item-light { + color: #636464; + background-color: #fefefe; +} + +.list-group-item-light.list-group-item-action:hover, .list-group-item-light.list-group-item-action:focus { + color: #636464; + background-color: #e5e5e5; +} + +.list-group-item-light.list-group-item-action.active { + color: #fff; + background-color: #636464; + border-color: #636464; +} + +.list-group-item-dark { + color: #141619; + background-color: #d3d3d4; +} + +.list-group-item-dark.list-group-item-action:hover, .list-group-item-dark.list-group-item-action:focus { + color: #141619; + background-color: #bebebf; +} + +.list-group-item-dark.list-group-item-action.active { + color: #fff; + background-color: #141619; + border-color: #141619; +} + +.btn-close { + box-sizing: content-box; + width: 1em; + height: 1em; + padding: 0.25em 0.25em; + color: #000; + background: transparent url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23000'%3e%3cpath d='M.293.293a1 1 0 011.414 0L8 6.586 14.293.293a1 1 0 111.414 1.414L9.414 8l6.293 6.293a1 1 0 01-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 01-1.414-1.414L6.586 8 .293 1.707a1 1 0 010-1.414z'/%3e%3c/svg%3e") center/1em auto no-repeat; + border: 0; + border-radius: 0.25rem; + opacity: 0.5; +} + +.btn-close:hover { + color: #000; + text-decoration: none; + opacity: 0.75; +} + +.btn-close:focus { + outline: 0; + box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); + opacity: 1; +} + +.btn-close:disabled, .btn-close.disabled { + pointer-events: none; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + opacity: 0.25; +} + +.btn-close-white { + filter: invert(1) grayscale(100%) brightness(200%); +} + +.toast { + width: 350px; + max-width: 100%; + font-size: 0.875rem; + pointer-events: auto; + background-color: rgba(255, 255, 255, 0.85); + background-clip: padding-box; + border: 1px solid rgba(0, 0, 0, 0.1); + box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15); + border-radius: 0.25rem; +} + +.toast.showing { + opacity: 0; +} + +.toast:not(.show) { + display: none; +} + +.toast-container { + width: -webkit-max-content; + width: -moz-max-content; + width: max-content; + max-width: 100%; + pointer-events: none; +} + +.toast-container > :not(:last-child) { + margin-bottom: 0.75rem; +} + +.toast-header { + display: flex; + align-items: center; + padding: 0.5rem 0.75rem; + color: #6c757d; + background-color: rgba(255, 255, 255, 0.85); + background-clip: padding-box; + border-bottom: 1px solid rgba(0, 0, 0, 0.05); + border-top-left-radius: calc(0.25rem - 1px); + border-top-right-radius: calc(0.25rem - 1px); +} + +.toast-header .btn-close { + margin-right: -0.375rem; + margin-left: 0.75rem; +} + +.toast-body { + padding: 0.75rem; + word-wrap: break-word; +} + +.modal { + position: fixed; + top: 0; + left: 0; + z-index: 1055; + display: none; + width: 100%; + height: 100%; + overflow-x: hidden; + overflow-y: auto; + outline: 0; +} + +.modal-dialog { + position: relative; + width: auto; + margin: 0.5rem; + pointer-events: none; +} + +.modal.fade .modal-dialog { + transition: transform 0.3s ease-out; + transform: translate(0, -50px); +} + +@media (prefers-reduced-motion: reduce) { + .modal.fade .modal-dialog { + transition: none; + } +} + +.modal.show .modal-dialog { + transform: none; +} + +.modal.modal-static .modal-dialog { + transform: scale(1.02); +} + +.modal-dialog-scrollable { + height: calc(100% - 1rem); +} + +.modal-dialog-scrollable .modal-content { + max-height: 100%; + overflow: hidden; +} + +.modal-dialog-scrollable .modal-body { + overflow-y: auto; +} + +.modal-dialog-centered { + display: flex; + align-items: center; + min-height: calc(100% - 1rem); +} + +.modal-content { + position: relative; + display: flex; + flex-direction: column; + width: 100%; + pointer-events: auto; + background-color: #fff; + background-clip: padding-box; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 0.3rem; + outline: 0; +} + +.modal-backdrop { + position: fixed; + top: 0; + left: 0; + z-index: 1050; + width: 100vw; + height: 100vh; + background-color: #000; +} + +.modal-backdrop.fade { + opacity: 0; +} + +.modal-backdrop.show { + opacity: 0.5; +} + +.modal-header { + display: flex; + flex-shrink: 0; + align-items: center; + justify-content: space-between; + padding: 1rem 1rem; + border-bottom: 1px solid #dee2e6; + border-top-left-radius: calc(0.3rem - 1px); + border-top-right-radius: calc(0.3rem - 1px); +} + +.modal-header .btn-close { + padding: 0.5rem 0.5rem; + margin: -0.5rem -0.5rem -0.5rem auto; +} + +.modal-title { + margin-bottom: 0; + line-height: 1.5; +} + +.modal-body { + position: relative; + flex: 1 1 auto; + padding: 1rem; +} + +.modal-footer { + display: flex; + flex-wrap: wrap; + flex-shrink: 0; + align-items: center; + justify-content: flex-end; + padding: 0.75rem; + border-top: 1px solid #dee2e6; + border-bottom-right-radius: calc(0.3rem - 1px); + border-bottom-left-radius: calc(0.3rem - 1px); +} + +.modal-footer > * { + margin: 0.25rem; +} + +@media (min-width: 576px) { + .modal-dialog { + max-width: 500px; + margin: 1.75rem auto; + } + + .modal-dialog-scrollable { + height: calc(100% - 3.5rem); + } + + .modal-dialog-centered { + min-height: calc(100% - 3.5rem); + } + + .modal-sm { + max-width: 300px; + } +} + +@media (min-width: 992px) { + .modal-lg, + .modal-xl { + max-width: 800px; + } +} + +@media (min-width: 1200px) { + .modal-xl { + max-width: 1140px; + } +} + +.modal-fullscreen { + width: 100vw; + max-width: none; + height: 100%; + margin: 0; +} + +.modal-fullscreen .modal-content { + height: 100%; + border: 0; + border-radius: 0; +} + +.modal-fullscreen .modal-header { + border-radius: 0; +} + +.modal-fullscreen .modal-body { + overflow-y: auto; +} + +.modal-fullscreen .modal-footer { + border-radius: 0; +} + +@media (max-width: 575.98px) { + .modal-fullscreen-sm-down { + width: 100vw; + max-width: none; + height: 100%; + margin: 0; + } + + .modal-fullscreen-sm-down .modal-content { + height: 100%; + border: 0; + border-radius: 0; + } + + .modal-fullscreen-sm-down .modal-header { + border-radius: 0; + } + + .modal-fullscreen-sm-down .modal-body { + overflow-y: auto; + } + + .modal-fullscreen-sm-down .modal-footer { + border-radius: 0; + } +} + +@media (max-width: 767.98px) { + .modal-fullscreen-md-down { + width: 100vw; + max-width: none; + height: 100%; + margin: 0; + } + + .modal-fullscreen-md-down .modal-content { + height: 100%; + border: 0; + border-radius: 0; + } + + .modal-fullscreen-md-down .modal-header { + border-radius: 0; + } + + .modal-fullscreen-md-down .modal-body { + overflow-y: auto; + } + + .modal-fullscreen-md-down .modal-footer { + border-radius: 0; + } +} + +@media (max-width: 991.98px) { + .modal-fullscreen-lg-down { + width: 100vw; + max-width: none; + height: 100%; + margin: 0; + } + + .modal-fullscreen-lg-down .modal-content { + height: 100%; + border: 0; + border-radius: 0; + } + + .modal-fullscreen-lg-down .modal-header { + border-radius: 0; + } + + .modal-fullscreen-lg-down .modal-body { + overflow-y: auto; + } + + .modal-fullscreen-lg-down .modal-footer { + border-radius: 0; + } +} + +@media (max-width: 1199.98px) { + .modal-fullscreen-xl-down { + width: 100vw; + max-width: none; + height: 100%; + margin: 0; + } + + .modal-fullscreen-xl-down .modal-content { + height: 100%; + border: 0; + border-radius: 0; + } + + .modal-fullscreen-xl-down .modal-header { + border-radius: 0; + } + + .modal-fullscreen-xl-down .modal-body { + overflow-y: auto; + } + + .modal-fullscreen-xl-down .modal-footer { + border-radius: 0; + } +} + +@media (max-width: 1399.98px) { + .modal-fullscreen-xxl-down { + width: 100vw; + max-width: none; + height: 100%; + margin: 0; + } + + .modal-fullscreen-xxl-down .modal-content { + height: 100%; + border: 0; + border-radius: 0; + } + + .modal-fullscreen-xxl-down .modal-header { + border-radius: 0; + } + + .modal-fullscreen-xxl-down .modal-body { + overflow-y: auto; + } + + .modal-fullscreen-xxl-down .modal-footer { + border-radius: 0; + } +} + +.tooltip { + position: absolute; + z-index: 1080; + display: block; + margin: 0; + font-family: var(--bs-font-sans-serif); + font-style: normal; + font-weight: 400; + line-height: 1.5; + text-align: left; + text-align: start; + text-decoration: none; + text-shadow: none; + text-transform: none; + letter-spacing: normal; + word-break: normal; + word-spacing: normal; + white-space: normal; + line-break: auto; + font-size: 0.875rem; + word-wrap: break-word; + opacity: 0; +} + +.tooltip.show { + opacity: 0.9; +} + +.tooltip .tooltip-arrow { + position: absolute; + display: block; + width: 0.8rem; + height: 0.4rem; +} + +.tooltip .tooltip-arrow::before { + position: absolute; + content: ""; + border-color: transparent; + border-style: solid; +} + +.bs-tooltip-top, .bs-tooltip-auto[data-popper-placement^=top] { + padding: 0.4rem 0; +} + +.bs-tooltip-top .tooltip-arrow, .bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow { + bottom: 0; +} + +.bs-tooltip-top .tooltip-arrow::before, .bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow::before { + top: -1px; + border-width: 0.4rem 0.4rem 0; + border-top-color: #000; +} + +.bs-tooltip-end, .bs-tooltip-auto[data-popper-placement^=right] { + padding: 0 0.4rem; +} + +.bs-tooltip-end .tooltip-arrow, .bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow { + left: 0; + width: 0.4rem; + height: 0.8rem; +} + +.bs-tooltip-end .tooltip-arrow::before, .bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow::before { + right: -1px; + border-width: 0.4rem 0.4rem 0.4rem 0; + border-right-color: #000; +} + +.bs-tooltip-bottom, .bs-tooltip-auto[data-popper-placement^=bottom] { + padding: 0.4rem 0; +} + +.bs-tooltip-bottom .tooltip-arrow, .bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow { + top: 0; +} + +.bs-tooltip-bottom .tooltip-arrow::before, .bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow::before { + bottom: -1px; + border-width: 0 0.4rem 0.4rem; + border-bottom-color: #000; +} + +.bs-tooltip-start, .bs-tooltip-auto[data-popper-placement^=left] { + padding: 0 0.4rem; +} + +.bs-tooltip-start .tooltip-arrow, .bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow { + right: 0; + width: 0.4rem; + height: 0.8rem; +} + +.bs-tooltip-start .tooltip-arrow::before, .bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow::before { + left: -1px; + border-width: 0.4rem 0 0.4rem 0.4rem; + border-left-color: #000; +} + +.tooltip-inner { + max-width: 200px; + padding: 0.25rem 0.5rem; + color: #fff; + text-align: center; + background-color: #000; + border-radius: 0.25rem; +} + +.popover { + position: absolute; + top: 0; + left: 0 /* rtl:ignore */; + z-index: 1070; + display: block; + max-width: 276px; + font-family: var(--bs-font-sans-serif); + font-style: normal; + font-weight: 400; + line-height: 1.5; + text-align: left; + text-align: start; + text-decoration: none; + text-shadow: none; + text-transform: none; + letter-spacing: normal; + word-break: normal; + word-spacing: normal; + white-space: normal; + line-break: auto; + font-size: 0.875rem; + word-wrap: break-word; + background-color: #fff; + background-clip: padding-box; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 0.3rem; +} + +.popover .popover-arrow { + position: absolute; + display: block; + width: 1rem; + height: 0.5rem; +} + +.popover .popover-arrow::before, .popover .popover-arrow::after { + position: absolute; + display: block; + content: ""; + border-color: transparent; + border-style: solid; +} + +.bs-popover-top > .popover-arrow, .bs-popover-auto[data-popper-placement^=top] > .popover-arrow { + bottom: calc(-0.5rem - 1px); +} + +.bs-popover-top > .popover-arrow::before, .bs-popover-auto[data-popper-placement^=top] > .popover-arrow::before { + bottom: 0; + border-width: 0.5rem 0.5rem 0; + border-top-color: rgba(0, 0, 0, 0.25); +} + +.bs-popover-top > .popover-arrow::after, .bs-popover-auto[data-popper-placement^=top] > .popover-arrow::after { + bottom: 1px; + border-width: 0.5rem 0.5rem 0; + border-top-color: #fff; +} + +.bs-popover-end > .popover-arrow, .bs-popover-auto[data-popper-placement^=right] > .popover-arrow { + left: calc(-0.5rem - 1px); + width: 0.5rem; + height: 1rem; +} + +.bs-popover-end > .popover-arrow::before, .bs-popover-auto[data-popper-placement^=right] > .popover-arrow::before { + left: 0; + border-width: 0.5rem 0.5rem 0.5rem 0; + border-right-color: rgba(0, 0, 0, 0.25); +} + +.bs-popover-end > .popover-arrow::after, .bs-popover-auto[data-popper-placement^=right] > .popover-arrow::after { + left: 1px; + border-width: 0.5rem 0.5rem 0.5rem 0; + border-right-color: #fff; +} + +.bs-popover-bottom > .popover-arrow, .bs-popover-auto[data-popper-placement^=bottom] > .popover-arrow { + top: calc(-0.5rem - 1px); +} + +.bs-popover-bottom > .popover-arrow::before, .bs-popover-auto[data-popper-placement^=bottom] > .popover-arrow::before { + top: 0; + border-width: 0 0.5rem 0.5rem 0.5rem; + border-bottom-color: rgba(0, 0, 0, 0.25); +} + +.bs-popover-bottom > .popover-arrow::after, .bs-popover-auto[data-popper-placement^=bottom] > .popover-arrow::after { + top: 1px; + border-width: 0 0.5rem 0.5rem 0.5rem; + border-bottom-color: #fff; +} + +.bs-popover-bottom .popover-header::before, .bs-popover-auto[data-popper-placement^=bottom] .popover-header::before { + position: absolute; + top: 0; + left: 50%; + display: block; + width: 1rem; + margin-left: -0.5rem; + content: ""; + border-bottom: 1px solid #f0f0f0; +} + +.bs-popover-start > .popover-arrow, .bs-popover-auto[data-popper-placement^=left] > .popover-arrow { + right: calc(-0.5rem - 1px); + width: 0.5rem; + height: 1rem; +} + +.bs-popover-start > .popover-arrow::before, .bs-popover-auto[data-popper-placement^=left] > .popover-arrow::before { + right: 0; + border-width: 0.5rem 0 0.5rem 0.5rem; + border-left-color: rgba(0, 0, 0, 0.25); +} + +.bs-popover-start > .popover-arrow::after, .bs-popover-auto[data-popper-placement^=left] > .popover-arrow::after { + right: 1px; + border-width: 0.5rem 0 0.5rem 0.5rem; + border-left-color: #fff; +} + +.popover-header { + padding: 0.5rem 1rem; + margin-bottom: 0; + font-size: 1rem; + background-color: #f0f0f0; + border-bottom: 1px solid rgba(0, 0, 0, 0.2); + border-top-left-radius: calc(0.3rem - 1px); + border-top-right-radius: calc(0.3rem - 1px); +} + +.popover-header:empty { + display: none; +} + +.popover-body { + padding: 1rem 1rem; + color: #212529; +} + +.carousel { + position: relative; +} + +.carousel.pointer-event { + touch-action: pan-y; +} + +.carousel-inner { + position: relative; + width: 100%; + overflow: hidden; +} + +.carousel-inner::after { + display: block; + clear: both; + content: ""; +} + +.carousel-item { + position: relative; + display: none; + float: left; + width: 100%; + margin-right: -100%; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + transition: transform 0.6s ease-in-out; +} + +@media (prefers-reduced-motion: reduce) { + .carousel-item { + transition: none; + } +} + +.carousel-item.active, +.carousel-item-next, +.carousel-item-prev { + display: block; +} + +/* rtl:begin:ignore */ +.carousel-item-next:not(.carousel-item-start), +.active.carousel-item-end { + transform: translateX(100%); +} + +.carousel-item-prev:not(.carousel-item-end), +.active.carousel-item-start { + transform: translateX(-100%); +} + +/* rtl:end:ignore */ +.carousel-fade .carousel-item { + opacity: 0; + transition-property: opacity; + transform: none; +} + +.carousel-fade .carousel-item.active, +.carousel-fade .carousel-item-next.carousel-item-start, +.carousel-fade .carousel-item-prev.carousel-item-end { + z-index: 1; + opacity: 1; +} + +.carousel-fade .active.carousel-item-start, +.carousel-fade .active.carousel-item-end { + z-index: 0; + opacity: 0; + transition: opacity 0s 0.6s; +} + +@media (prefers-reduced-motion: reduce) { + .carousel-fade .active.carousel-item-start, + .carousel-fade .active.carousel-item-end { + transition: none; + } +} + +.carousel-control-prev, +.carousel-control-next { + position: absolute; + top: 0; + bottom: 0; + z-index: 1; + display: flex; + align-items: center; + justify-content: center; + width: 15%; + padding: 0; + color: #fff; + text-align: center; + background: none; + border: 0; + opacity: 0.5; + transition: opacity 0.15s ease; +} + +@media (prefers-reduced-motion: reduce) { + .carousel-control-prev, + .carousel-control-next { + transition: none; + } +} + +.carousel-control-prev:hover, .carousel-control-prev:focus, +.carousel-control-next:hover, +.carousel-control-next:focus { + color: #fff; + text-decoration: none; + outline: 0; + opacity: 0.9; +} + +.carousel-control-prev { + left: 0; +} + +.carousel-control-next { + right: 0; +} + +.carousel-control-prev-icon, +.carousel-control-next-icon { + display: inline-block; + width: 2rem; + height: 2rem; + background-repeat: no-repeat; + background-position: 50%; + background-size: 100% 100%; +} + +/* rtl:options: { + "autoRename": true, + "stringMap":[ { + "name" : "prev-next", + "search" : "prev", + "replace" : "next" + } ] +} */ +.carousel-control-prev-icon { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e"); +} + +.carousel-control-next-icon { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); +} + +.carousel-indicators { + position: absolute; + right: 0; + bottom: 0; + left: 0; + z-index: 2; + display: flex; + justify-content: center; + padding: 0; + margin-right: 15%; + margin-bottom: 1rem; + margin-left: 15%; + list-style: none; +} + +.carousel-indicators [data-bs-target] { + box-sizing: content-box; + flex: 0 1 auto; + width: 30px; + height: 3px; + padding: 0; + margin-right: 3px; + margin-left: 3px; + text-indent: -999px; + cursor: pointer; + background-color: #fff; + background-clip: padding-box; + border: 0; + border-top: 10px solid transparent; + border-bottom: 10px solid transparent; + opacity: 0.5; + transition: opacity 0.6s ease; +} + +@media (prefers-reduced-motion: reduce) { + .carousel-indicators [data-bs-target] { + transition: none; + } +} + +.carousel-indicators .active { + opacity: 1; +} + +.carousel-caption { + position: absolute; + right: 15%; + bottom: 1.25rem; + left: 15%; + padding-top: 1.25rem; + padding-bottom: 1.25rem; + color: #fff; + text-align: center; +} + +.carousel-dark .carousel-control-prev-icon, +.carousel-dark .carousel-control-next-icon { + filter: invert(1) grayscale(100); +} + +.carousel-dark .carousel-indicators [data-bs-target] { + background-color: #000; +} + +.carousel-dark .carousel-caption { + color: #000; +} + +@-webkit-keyframes spinner-border { + to { + transform: rotate(360deg) /* rtl:ignore */; + } +} + +@keyframes spinner-border { + to { + transform: rotate(360deg) /* rtl:ignore */; + } +} + +.spinner-border { + display: inline-block; + width: 2rem; + height: 2rem; + vertical-align: -0.125em; + border: 0.25em solid currentColor; + border-right-color: transparent; + border-radius: 50%; + -webkit-animation: 0.75s linear infinite spinner-border; + animation: 0.75s linear infinite spinner-border; +} + +.spinner-border-sm { + width: 1rem; + height: 1rem; + border-width: 0.2em; +} + +@-webkit-keyframes spinner-grow { + 0% { + transform: scale(0); + } + 50% { + opacity: 1; + transform: none; + } +} + +@keyframes spinner-grow { + 0% { + transform: scale(0); + } + 50% { + opacity: 1; + transform: none; + } +} + +.spinner-grow { + display: inline-block; + width: 2rem; + height: 2rem; + vertical-align: -0.125em; + background-color: currentColor; + border-radius: 50%; + opacity: 0; + -webkit-animation: 0.75s linear infinite spinner-grow; + animation: 0.75s linear infinite spinner-grow; +} + +.spinner-grow-sm { + width: 1rem; + height: 1rem; +} + +@media (prefers-reduced-motion: reduce) { + .spinner-border, + .spinner-grow { + -webkit-animation-duration: 1.5s; + animation-duration: 1.5s; + } +} + +.offcanvas { + position: fixed; + bottom: 0; + z-index: 1045; + display: flex; + flex-direction: column; + max-width: 100%; + visibility: hidden; + background-color: #fff; + background-clip: padding-box; + outline: 0; + transition: transform 0.3s ease-in-out; +} + +@media (prefers-reduced-motion: reduce) { + .offcanvas { + transition: none; + } +} + +.offcanvas-backdrop { + position: fixed; + top: 0; + left: 0; + z-index: 1040; + width: 100vw; + height: 100vh; + background-color: #000; +} + +.offcanvas-backdrop.fade { + opacity: 0; +} + +.offcanvas-backdrop.show { + opacity: 0.5; +} + +.offcanvas-header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 1rem 1rem; +} + +.offcanvas-header .btn-close { + padding: 0.5rem 0.5rem; + margin-top: -0.5rem; + margin-right: -0.5rem; + margin-bottom: -0.5rem; +} + +.offcanvas-title { + margin-bottom: 0; + line-height: 1.5; +} + +.offcanvas-body { + flex-grow: 1; + padding: 1rem 1rem; + overflow-y: auto; +} + +.offcanvas-start { + top: 0; + left: 0; + width: 400px; + border-right: 1px solid rgba(0, 0, 0, 0.2); + transform: translateX(-100%); +} + +.offcanvas-end { + top: 0; + right: 0; + width: 400px; + border-left: 1px solid rgba(0, 0, 0, 0.2); + transform: translateX(100%); +} + +.offcanvas-top { + top: 0; + right: 0; + left: 0; + height: 30vh; + max-height: 100%; + border-bottom: 1px solid rgba(0, 0, 0, 0.2); + transform: translateY(-100%); +} + +.offcanvas-bottom { + right: 0; + left: 0; + height: 30vh; + max-height: 100%; + border-top: 1px solid rgba(0, 0, 0, 0.2); + transform: translateY(100%); +} + +.offcanvas.show { + transform: none; +} + +.placeholder { + display: inline-block; + min-height: 1em; + vertical-align: middle; + cursor: wait; + background-color: currentColor; + opacity: 0.5; +} + +.placeholder.btn::before { + display: inline-block; + content: ""; +} + +.placeholder-xs { + min-height: 0.6em; +} + +.placeholder-sm { + min-height: 0.8em; +} + +.placeholder-lg { + min-height: 1.2em; +} + +.placeholder-glow .placeholder { + -webkit-animation: placeholder-glow 2s ease-in-out infinite; + animation: placeholder-glow 2s ease-in-out infinite; +} + +@-webkit-keyframes placeholder-glow { + 50% { + opacity: 0.2; + } +} + +@keyframes placeholder-glow { + 50% { + opacity: 0.2; + } +} + +.placeholder-wave { + -webkit-mask-image: linear-gradient(130deg, #000 55%, rgba(0, 0, 0, 0.8) 75%, #000 95%); + mask-image: linear-gradient(130deg, #000 55%, rgba(0, 0, 0, 0.8) 75%, #000 95%); + -webkit-mask-size: 200% 100%; + mask-size: 200% 100%; + -webkit-animation: placeholder-wave 2s linear infinite; + animation: placeholder-wave 2s linear infinite; +} + +@-webkit-keyframes placeholder-wave { + 100% { + -webkit-mask-position: -200% 0%; + mask-position: -200% 0%; + } +} + +@keyframes placeholder-wave { + 100% { + -webkit-mask-position: -200% 0%; + mask-position: -200% 0%; + } +} + +.clearfix::after { + display: block; + clear: both; + content: ""; +} + +.link-primary { + color: #0d6efd; +} + +.link-primary:hover, .link-primary:focus { + color: #0a58ca; +} + +.link-secondary { + color: #6c757d; +} + +.link-secondary:hover, .link-secondary:focus { + color: #565e64; +} + +.link-success { + color: #198754; +} + +.link-success:hover, .link-success:focus { + color: #146c43; +} + +.link-info { + color: #0dcaf0; +} + +.link-info:hover, .link-info:focus { + color: #3dd5f3; +} + +.link-warning { + color: #ffc107; +} + +.link-warning:hover, .link-warning:focus { + color: #ffcd39; +} + +.link-danger { + color: #dc3545; +} + +.link-danger:hover, .link-danger:focus { + color: #b02a37; +} + +.link-light { + color: #f8f9fa; +} + +.link-light:hover, .link-light:focus { + color: #f9fafb; +} + +.link-dark { + color: #212529; +} + +.link-dark:hover, .link-dark:focus { + color: #1a1e21; +} + +.ratio { + position: relative; + width: 100%; +} + +.ratio::before { + display: block; + padding-top: var(--bs-aspect-ratio); + content: ""; +} + +.ratio > * { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; +} + +.ratio-1x1 { + --bs-aspect-ratio: 100%; +} + +.ratio-4x3 { + --bs-aspect-ratio: 75%; +} + +.ratio-16x9 { + --bs-aspect-ratio: 56.25%; +} + +.ratio-21x9 { + --bs-aspect-ratio: 42.8571428571%; +} + +.fixed-top { + position: fixed; + top: 0; + right: 0; + left: 0; + z-index: 1030; +} + +.fixed-bottom { + position: fixed; + right: 0; + bottom: 0; + left: 0; + z-index: 1030; +} + +.sticky-top { + position: -webkit-sticky; + position: sticky; + top: 0; + z-index: 1020; +} + +@media (min-width: 576px) { + .sticky-sm-top { + position: -webkit-sticky; + position: sticky; + top: 0; + z-index: 1020; + } +} + +@media (min-width: 768px) { + .sticky-md-top { + position: -webkit-sticky; + position: sticky; + top: 0; + z-index: 1020; + } +} + +@media (min-width: 992px) { + .sticky-lg-top { + position: -webkit-sticky; + position: sticky; + top: 0; + z-index: 1020; + } +} + +@media (min-width: 1200px) { + .sticky-xl-top { + position: -webkit-sticky; + position: sticky; + top: 0; + z-index: 1020; + } +} + +@media (min-width: 1400px) { + .sticky-xxl-top { + position: -webkit-sticky; + position: sticky; + top: 0; + z-index: 1020; + } +} + +.hstack { + display: flex; + flex-direction: row; + align-items: center; + align-self: stretch; +} + +.vstack { + display: flex; + flex: 1 1 auto; + flex-direction: column; + align-self: stretch; +} + +.visually-hidden, +.visually-hidden-focusable:not(:focus):not(:focus-within) { + position: absolute !important; + width: 1px !important; + height: 1px !important; + padding: 0 !important; + margin: -1px !important; + overflow: hidden !important; + clip: rect(0, 0, 0, 0) !important; + white-space: nowrap !important; + border: 0 !important; +} + +.stretched-link::after { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1; + content: ""; +} + +.text-truncate { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.vr { + display: inline-block; + align-self: stretch; + width: 1px; + min-height: 1em; + background-color: currentColor; + opacity: 0.25; +} + +.align-baseline { + vertical-align: baseline !important; +} + +.align-top { + vertical-align: top !important; +} + +.align-middle { + vertical-align: middle !important; +} + +.align-bottom { + vertical-align: bottom !important; +} + +.align-text-bottom { + vertical-align: text-bottom !important; +} + +.align-text-top { + vertical-align: text-top !important; +} + +.float-start { + float: left !important; +} + +.float-end { + float: right !important; +} + +.float-none { + float: none !important; +} + +.opacity-0 { + opacity: 0 !important; +} + +.opacity-25 { + opacity: 0.25 !important; +} + +.opacity-50 { + opacity: 0.5 !important; +} + +.opacity-75 { + opacity: 0.75 !important; +} + +.opacity-100 { + opacity: 1 !important; +} + +.overflow-auto { + overflow: auto !important; +} + +.overflow-hidden { + overflow: hidden !important; +} + +.overflow-visible { + overflow: visible !important; +} + +.overflow-scroll { + overflow: scroll !important; +} + +.d-inline { + display: inline !important; +} + +.d-inline-block { + display: inline-block !important; +} + +.d-block { + display: block !important; +} + +.d-grid { + display: grid !important; +} + +.d-table { + display: table !important; +} + +.d-table-row { + display: table-row !important; +} + +.d-table-cell { + display: table-cell !important; +} + +.d-flex { + display: flex !important; +} + +.d-inline-flex { + display: inline-flex !important; +} + +.d-none { + display: none !important; +} + +.shadow { + box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important; +} + +.shadow-sm { + box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075) !important; +} + +.shadow-lg { + box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.175) !important; +} + +.shadow-none { + box-shadow: none !important; +} + +.position-static { + position: static !important; +} + +.position-relative { + position: relative !important; +} + +.position-absolute { + position: absolute !important; +} + +.position-fixed { + position: fixed !important; +} + +.position-sticky { + position: -webkit-sticky !important; + position: sticky !important; +} + +.top-0 { + top: 0 !important; +} + +.top-50 { + top: 50% !important; +} + +.top-100 { + top: 100% !important; +} + +.bottom-0 { + bottom: 0 !important; +} + +.bottom-50 { + bottom: 50% !important; +} + +.bottom-100 { + bottom: 100% !important; +} + +.start-0 { + left: 0 !important; +} + +.start-50 { + left: 50% !important; +} + +.start-100 { + left: 100% !important; +} + +.end-0 { + right: 0 !important; +} + +.end-50 { + right: 50% !important; +} + +.end-100 { + right: 100% !important; +} + +.translate-middle { + transform: translate(-50%, -50%) !important; +} + +.translate-middle-x { + transform: translateX(-50%) !important; +} + +.translate-middle-y { + transform: translateY(-50%) !important; +} + +.border { + border: 1px solid #dee2e6 !important; +} + +.border-0 { + border: 0 !important; +} + +.border-top { + border-top: 1px solid #dee2e6 !important; +} + +.border-top-0 { + border-top: 0 !important; +} + +.border-end { + border-right: 1px solid #dee2e6 !important; +} + +.border-end-0 { + border-right: 0 !important; +} + +.border-bottom { + border-bottom: 1px solid #dee2e6 !important; +} + +.border-bottom-0 { + border-bottom: 0 !important; +} + +.border-start { + border-left: 1px solid #dee2e6 !important; +} + +.border-start-0 { + border-left: 0 !important; +} + +.border-primary { + border-color: #0d6efd !important; +} + +.border-secondary { + border-color: #6c757d !important; +} + +.border-success { + border-color: #198754 !important; +} + +.border-info { + border-color: #0dcaf0 !important; +} + +.border-warning { + border-color: #ffc107 !important; +} + +.border-danger { + border-color: #dc3545 !important; +} + +.border-light { + border-color: #f8f9fa !important; +} + +.border-dark { + border-color: #212529 !important; +} + +.border-white { + border-color: #fff !important; +} + +.border-1 { + border-width: 1px !important; +} + +.border-2 { + border-width: 2px !important; +} + +.border-3 { + border-width: 3px !important; +} + +.border-4 { + border-width: 4px !important; +} + +.border-5 { + border-width: 5px !important; +} + +.w-25 { + width: 25% !important; +} + +.w-50 { + width: 50% !important; +} + +.w-75 { + width: 75% !important; +} + +.w-100 { + width: 100% !important; +} + +.w-auto { + width: auto !important; +} + +.mw-100 { + max-width: 100% !important; +} + +.vw-100 { + width: 100vw !important; +} + +.min-vw-100 { + min-width: 100vw !important; +} + +.h-25 { + height: 25% !important; +} + +.h-50 { + height: 50% !important; +} + +.h-75 { + height: 75% !important; +} + +.h-100 { + height: 100% !important; +} + +.h-auto { + height: auto !important; +} + +.mh-100 { + max-height: 100% !important; +} + +.vh-100 { + height: 100vh !important; +} + +.min-vh-100 { + min-height: 100vh !important; +} + +.flex-fill { + flex: 1 1 auto !important; +} + +.flex-row { + flex-direction: row !important; +} + +.flex-column { + flex-direction: column !important; +} + +.flex-row-reverse { + flex-direction: row-reverse !important; +} + +.flex-column-reverse { + flex-direction: column-reverse !important; +} + +.flex-grow-0 { + flex-grow: 0 !important; +} + +.flex-grow-1 { + flex-grow: 1 !important; +} + +.flex-shrink-0 { + flex-shrink: 0 !important; +} + +.flex-shrink-1 { + flex-shrink: 1 !important; +} + +.flex-wrap { + flex-wrap: wrap !important; +} + +.flex-nowrap { + flex-wrap: nowrap !important; +} + +.flex-wrap-reverse { + flex-wrap: wrap-reverse !important; +} + +.gap-0 { + gap: 0 !important; +} + +.gap-1 { + gap: 0.25rem !important; +} + +.gap-2 { + gap: 0.5rem !important; +} + +.gap-3 { + gap: 1rem !important; +} + +.gap-4 { + gap: 1.5rem !important; +} + +.gap-5 { + gap: 3rem !important; +} + +.justify-content-start { + justify-content: flex-start !important; +} + +.justify-content-end { + justify-content: flex-end !important; +} + +.justify-content-center { + justify-content: center !important; +} + +.justify-content-between { + justify-content: space-between !important; +} + +.justify-content-around { + justify-content: space-around !important; +} + +.justify-content-evenly { + justify-content: space-evenly !important; +} + +.align-items-start { + align-items: flex-start !important; +} + +.align-items-end { + align-items: flex-end !important; +} + +.align-items-center { + align-items: center !important; +} + +.align-items-baseline { + align-items: baseline !important; +} + +.align-items-stretch { + align-items: stretch !important; +} + +.align-content-start { + align-content: flex-start !important; +} + +.align-content-end { + align-content: flex-end !important; +} + +.align-content-center { + align-content: center !important; +} + +.align-content-between { + align-content: space-between !important; +} + +.align-content-around { + align-content: space-around !important; +} + +.align-content-stretch { + align-content: stretch !important; +} + +.align-self-auto { + align-self: auto !important; +} + +.align-self-start { + align-self: flex-start !important; +} + +.align-self-end { + align-self: flex-end !important; +} + +.align-self-center { + align-self: center !important; +} + +.align-self-baseline { + align-self: baseline !important; +} + +.align-self-stretch { + align-self: stretch !important; +} + +.order-first { + order: -1 !important; +} + +.order-0 { + order: 0 !important; +} + +.order-1 { + order: 1 !important; +} + +.order-2 { + order: 2 !important; +} + +.order-3 { + order: 3 !important; +} + +.order-4 { + order: 4 !important; +} + +.order-5 { + order: 5 !important; +} + +.order-last { + order: 6 !important; +} + +.m-0 { + margin: 0 !important; +} + +.m-1 { + margin: 0.25rem !important; +} + +.m-2 { + margin: 0.5rem !important; +} + +.m-3 { + margin: 1rem !important; +} + +.m-4 { + margin: 1.5rem !important; +} + +.m-5 { + margin: 3rem !important; +} + +.m-auto { + margin: auto !important; +} + +.mx-0 { + margin-right: 0 !important; + margin-left: 0 !important; +} + +.mx-1 { + margin-right: 0.25rem !important; + margin-left: 0.25rem !important; +} + +.mx-2 { + margin-right: 0.5rem !important; + margin-left: 0.5rem !important; +} + +.mx-3 { + margin-right: 1rem !important; + margin-left: 1rem !important; +} + +.mx-4 { + margin-right: 1.5rem !important; + margin-left: 1.5rem !important; +} + +.mx-5 { + margin-right: 3rem !important; + margin-left: 3rem !important; +} + +.mx-auto { + margin-right: auto !important; + margin-left: auto !important; +} + +.my-0 { + margin-top: 0 !important; + margin-bottom: 0 !important; +} + +.my-1 { + margin-top: 0.25rem !important; + margin-bottom: 0.25rem !important; +} + +.my-2 { + margin-top: 0.5rem !important; + margin-bottom: 0.5rem !important; +} + +.my-3 { + margin-top: 1rem !important; + margin-bottom: 1rem !important; +} + +.my-4 { + margin-top: 1.5rem !important; + margin-bottom: 1.5rem !important; +} + +.my-5 { + margin-top: 3rem !important; + margin-bottom: 3rem !important; +} + +.my-auto { + margin-top: auto !important; + margin-bottom: auto !important; +} + +.mt-0 { + margin-top: 0 !important; +} + +.mt-1 { + margin-top: 0.25rem !important; +} + +.mt-2 { + margin-top: 0.5rem !important; +} + +.mt-3 { + margin-top: 1rem !important; +} + +.mt-4 { + margin-top: 1.5rem !important; +} + +.mt-5 { + margin-top: 3rem !important; +} + +.mt-auto { + margin-top: auto !important; +} + +.me-0 { + margin-right: 0 !important; +} + +.me-1 { + margin-right: 0.25rem !important; +} + +.me-2 { + margin-right: 0.5rem !important; +} + +.me-3 { + margin-right: 1rem !important; +} + +.me-4 { + margin-right: 1.5rem !important; +} + +.me-5 { + margin-right: 3rem !important; +} + +.me-auto { + margin-right: auto !important; +} + +.mb-0 { + margin-bottom: 0 !important; +} + +.mb-1 { + margin-bottom: 0.25rem !important; +} + +.mb-2 { + margin-bottom: 0.5rem !important; +} + +.mb-3 { + margin-bottom: 1rem !important; +} + +.mb-4 { + margin-bottom: 1.5rem !important; +} + +.mb-5 { + margin-bottom: 3rem !important; +} + +.mb-auto { + margin-bottom: auto !important; +} + +.ms-0 { + margin-left: 0 !important; +} + +.ms-1 { + margin-left: 0.25rem !important; +} + +.ms-2 { + margin-left: 0.5rem !important; +} + +.ms-3 { + margin-left: 1rem !important; +} + +.ms-4 { + margin-left: 1.5rem !important; +} + +.ms-5 { + margin-left: 3rem !important; +} + +.ms-auto { + margin-left: auto !important; +} + +.p-0 { + padding: 0 !important; +} + +.p-1 { + padding: 0.25rem !important; +} + +.p-2 { + padding: 0.5rem !important; +} + +.p-3 { + padding: 1rem !important; +} + +.p-4 { + padding: 1.5rem !important; +} + +.p-5 { + padding: 3rem !important; +} + +.px-0 { + padding-right: 0 !important; + padding-left: 0 !important; +} + +.px-1 { + padding-right: 0.25rem !important; + padding-left: 0.25rem !important; +} + +.px-2 { + padding-right: 0.5rem !important; + padding-left: 0.5rem !important; +} + +.px-3 { + padding-right: 1rem !important; + padding-left: 1rem !important; +} + +.px-4 { + padding-right: 1.5rem !important; + padding-left: 1.5rem !important; +} + +.px-5 { + padding-right: 3rem !important; + padding-left: 3rem !important; +} + +.py-0 { + padding-top: 0 !important; + padding-bottom: 0 !important; +} + +.py-1 { + padding-top: 0.25rem !important; + padding-bottom: 0.25rem !important; +} + +.py-2 { + padding-top: 0.5rem !important; + padding-bottom: 0.5rem !important; +} + +.py-3 { + padding-top: 1rem !important; + padding-bottom: 1rem !important; +} + +.py-4 { + padding-top: 1.5rem !important; + padding-bottom: 1.5rem !important; +} + +.py-5 { + padding-top: 3rem !important; + padding-bottom: 3rem !important; +} + +.pt-0 { + padding-top: 0 !important; +} + +.pt-1 { + padding-top: 0.25rem !important; +} + +.pt-2 { + padding-top: 0.5rem !important; +} + +.pt-3 { + padding-top: 1rem !important; +} + +.pt-4 { + padding-top: 1.5rem !important; +} + +.pt-5 { + padding-top: 3rem !important; +} + +.pe-0 { + padding-right: 0 !important; +} + +.pe-1 { + padding-right: 0.25rem !important; +} + +.pe-2 { + padding-right: 0.5rem !important; +} + +.pe-3 { + padding-right: 1rem !important; +} + +.pe-4 { + padding-right: 1.5rem !important; +} + +.pe-5 { + padding-right: 3rem !important; +} + +.pb-0 { + padding-bottom: 0 !important; +} + +.pb-1 { + padding-bottom: 0.25rem !important; +} + +.pb-2 { + padding-bottom: 0.5rem !important; +} + +.pb-3 { + padding-bottom: 1rem !important; +} + +.pb-4 { + padding-bottom: 1.5rem !important; +} + +.pb-5 { + padding-bottom: 3rem !important; +} + +.ps-0 { + padding-left: 0 !important; +} + +.ps-1 { + padding-left: 0.25rem !important; +} + +.ps-2 { + padding-left: 0.5rem !important; +} + +.ps-3 { + padding-left: 1rem !important; +} + +.ps-4 { + padding-left: 1.5rem !important; +} + +.ps-5 { + padding-left: 3rem !important; +} + +.font-monospace { + font-family: var(--bs-font-monospace) !important; +} + +.fs-1 { + font-size: calc(1.375rem + 1.5vw) !important; +} + +.fs-2 { + font-size: calc(1.325rem + 0.9vw) !important; +} + +.fs-3 { + font-size: calc(1.3rem + 0.6vw) !important; +} + +.fs-4 { + font-size: calc(1.275rem + 0.3vw) !important; +} + +.fs-5 { + font-size: 1.25rem !important; +} + +.fs-6 { + font-size: 1rem !important; +} + +.fst-italic { + font-style: italic !important; +} + +.fst-normal { + font-style: normal !important; +} + +.fw-light { + font-weight: 300 !important; +} + +.fw-lighter { + font-weight: lighter !important; +} + +.fw-normal { + font-weight: 400 !important; +} + +.fw-bold { + font-weight: 700 !important; +} + +.fw-bolder { + font-weight: bolder !important; +} + +.lh-1 { + line-height: 1 !important; +} + +.lh-sm { + line-height: 1.25 !important; +} + +.lh-base { + line-height: 1.5 !important; +} + +.lh-lg { + line-height: 2 !important; +} + +.text-start { + text-align: left !important; +} + +.text-end { + text-align: right !important; +} + +.text-center { + text-align: center !important; +} + +.text-decoration-none { + text-decoration: none !important; +} + +.text-decoration-underline { + text-decoration: underline !important; +} + +.text-decoration-line-through { + text-decoration: line-through !important; +} + +.text-lowercase { + text-transform: lowercase !important; +} + +.text-uppercase { + text-transform: uppercase !important; +} + +.text-capitalize { + text-transform: capitalize !important; +} + +.text-wrap { + white-space: normal !important; +} + +.text-nowrap { + white-space: nowrap !important; +} + +/* rtl:begin:remove */ +.text-break { + word-wrap: break-word !important; + word-break: break-word !important; +} + +/* rtl:end:remove */ +.text-primary { + --bs-text-opacity: 1; + color: rgba(var(--bs-primary-rgb), var(--bs-text-opacity)) !important; +} + +.text-secondary { + --bs-text-opacity: 1; + color: rgba(var(--bs-secondary-rgb), var(--bs-text-opacity)) !important; +} + +.text-success { + --bs-text-opacity: 1; + color: rgba(var(--bs-success-rgb), var(--bs-text-opacity)) !important; +} + +.text-info { + --bs-text-opacity: 1; + color: rgba(var(--bs-info-rgb), var(--bs-text-opacity)) !important; +} + +.text-warning { + --bs-text-opacity: 1; + color: rgba(var(--bs-warning-rgb), var(--bs-text-opacity)) !important; +} + +.text-danger { + --bs-text-opacity: 1; + color: rgba(var(--bs-danger-rgb), var(--bs-text-opacity)) !important; +} + +.text-light { + --bs-text-opacity: 1; + color: rgba(var(--bs-light-rgb), var(--bs-text-opacity)) !important; +} + +.text-dark { + --bs-text-opacity: 1; + color: rgba(var(--bs-dark-rgb), var(--bs-text-opacity)) !important; +} + +.text-black { + --bs-text-opacity: 1; + color: rgba(var(--bs-black-rgb), var(--bs-text-opacity)) !important; +} + +.text-white { + --bs-text-opacity: 1; + color: rgba(var(--bs-white-rgb), var(--bs-text-opacity)) !important; +} + +.text-body { + --bs-text-opacity: 1; + color: rgba(var(--bs-body-color-rgb), var(--bs-text-opacity)) !important; +} + +.text-muted { + --bs-text-opacity: 1; + color: #6c757d !important; +} + +.text-black-50 { + --bs-text-opacity: 1; + color: rgba(0, 0, 0, 0.5) !important; +} + +.text-white-50 { + --bs-text-opacity: 1; + color: rgba(255, 255, 255, 0.5) !important; +} + +.text-reset { + --bs-text-opacity: 1; + color: inherit !important; +} + +.text-opacity-25 { + --bs-text-opacity: 0.25; +} + +.text-opacity-50 { + --bs-text-opacity: 0.5; +} + +.text-opacity-75 { + --bs-text-opacity: 0.75; +} + +.text-opacity-100 { + --bs-text-opacity: 1; +} + +.bg-primary { + --bs-bg-opacity: 1; + background-color: rgba(var(--bs-primary-rgb), var(--bs-bg-opacity)) !important; +} + +.bg-secondary { + --bs-bg-opacity: 1; + background-color: rgba(var(--bs-secondary-rgb), var(--bs-bg-opacity)) !important; +} + +.bg-success { + --bs-bg-opacity: 1; + background-color: rgba(var(--bs-success-rgb), var(--bs-bg-opacity)) !important; +} + +.bg-info { + --bs-bg-opacity: 1; + background-color: rgba(var(--bs-info-rgb), var(--bs-bg-opacity)) !important; +} + +.bg-warning { + --bs-bg-opacity: 1; + background-color: rgba(var(--bs-warning-rgb), var(--bs-bg-opacity)) !important; +} + +.bg-danger { + --bs-bg-opacity: 1; + background-color: rgba(var(--bs-danger-rgb), var(--bs-bg-opacity)) !important; +} + +.bg-light { + --bs-bg-opacity: 1; + background-color: rgba(var(--bs-light-rgb), var(--bs-bg-opacity)) !important; +} + +.bg-dark { + --bs-bg-opacity: 1; + background-color: rgba(var(--bs-dark-rgb), var(--bs-bg-opacity)) !important; +} + +.bg-black { + --bs-bg-opacity: 1; + background-color: rgba(var(--bs-black-rgb), var(--bs-bg-opacity)) !important; +} + +.bg-white { + --bs-bg-opacity: 1; + background-color: rgba(var(--bs-white-rgb), var(--bs-bg-opacity)) !important; +} + +.bg-body { + --bs-bg-opacity: 1; + background-color: rgba(var(--bs-body-bg-rgb), var(--bs-bg-opacity)) !important; +} + +.bg-transparent { + --bs-bg-opacity: 1; + background-color: transparent !important; +} + +.bg-opacity-10 { + --bs-bg-opacity: 0.1; +} + +.bg-opacity-25 { + --bs-bg-opacity: 0.25; +} + +.bg-opacity-50 { + --bs-bg-opacity: 0.5; +} + +.bg-opacity-75 { + --bs-bg-opacity: 0.75; +} + +.bg-opacity-100 { + --bs-bg-opacity: 1; +} + +.bg-gradient { + background-image: var(--bs-gradient) !important; +} + +.user-select-all { + -webkit-user-select: all !important; + -moz-user-select: all !important; + user-select: all !important; +} + +.user-select-auto { + -webkit-user-select: auto !important; + -moz-user-select: auto !important; + user-select: auto !important; +} + +.user-select-none { + -webkit-user-select: none !important; + -moz-user-select: none !important; + user-select: none !important; +} + +.pe-none { + pointer-events: none !important; +} + +.pe-auto { + pointer-events: auto !important; +} + +.rounded { + border-radius: 0.25rem !important; +} + +.rounded-0 { + border-radius: 0 !important; +} + +.rounded-1 { + border-radius: 0.2rem !important; +} + +.rounded-2 { + border-radius: 0.25rem !important; +} + +.rounded-3 { + border-radius: 0.3rem !important; +} + +.rounded-circle { + border-radius: 50% !important; +} + +.rounded-pill { + border-radius: 50rem !important; +} + +.rounded-top { + border-top-left-radius: 0.25rem !important; + border-top-right-radius: 0.25rem !important; +} + +.rounded-end { + border-top-right-radius: 0.25rem !important; + border-bottom-right-radius: 0.25rem !important; +} + +.rounded-bottom { + border-bottom-right-radius: 0.25rem !important; + border-bottom-left-radius: 0.25rem !important; +} + +.rounded-start { + border-bottom-left-radius: 0.25rem !important; + border-top-left-radius: 0.25rem !important; +} + +.visible { + visibility: visible !important; +} + +.invisible { + visibility: hidden !important; +} + +@media (min-width: 576px) { + .float-sm-start { + float: left !important; + } + + .float-sm-end { + float: right !important; + } + + .float-sm-none { + float: none !important; + } + + .d-sm-inline { + display: inline !important; + } + + .d-sm-inline-block { + display: inline-block !important; + } + + .d-sm-block { + display: block !important; + } + + .d-sm-grid { + display: grid !important; + } + + .d-sm-table { + display: table !important; + } + + .d-sm-table-row { + display: table-row !important; + } + + .d-sm-table-cell { + display: table-cell !important; + } + + .d-sm-flex { + display: flex !important; + } + + .d-sm-inline-flex { + display: inline-flex !important; + } + + .d-sm-none { + display: none !important; + } + + .flex-sm-fill { + flex: 1 1 auto !important; + } + + .flex-sm-row { + flex-direction: row !important; + } + + .flex-sm-column { + flex-direction: column !important; + } + + .flex-sm-row-reverse { + flex-direction: row-reverse !important; + } + + .flex-sm-column-reverse { + flex-direction: column-reverse !important; + } + + .flex-sm-grow-0 { + flex-grow: 0 !important; + } + + .flex-sm-grow-1 { + flex-grow: 1 !important; + } + + .flex-sm-shrink-0 { + flex-shrink: 0 !important; + } + + .flex-sm-shrink-1 { + flex-shrink: 1 !important; + } + + .flex-sm-wrap { + flex-wrap: wrap !important; + } + + .flex-sm-nowrap { + flex-wrap: nowrap !important; + } + + .flex-sm-wrap-reverse { + flex-wrap: wrap-reverse !important; + } + + .gap-sm-0 { + gap: 0 !important; + } + + .gap-sm-1 { + gap: 0.25rem !important; + } + + .gap-sm-2 { + gap: 0.5rem !important; + } + + .gap-sm-3 { + gap: 1rem !important; + } + + .gap-sm-4 { + gap: 1.5rem !important; + } + + .gap-sm-5 { + gap: 3rem !important; + } + + .justify-content-sm-start { + justify-content: flex-start !important; + } + + .justify-content-sm-end { + justify-content: flex-end !important; + } + + .justify-content-sm-center { + justify-content: center !important; + } + + .justify-content-sm-between { + justify-content: space-between !important; + } + + .justify-content-sm-around { + justify-content: space-around !important; + } + + .justify-content-sm-evenly { + justify-content: space-evenly !important; + } + + .align-items-sm-start { + align-items: flex-start !important; + } + + .align-items-sm-end { + align-items: flex-end !important; + } + + .align-items-sm-center { + align-items: center !important; + } + + .align-items-sm-baseline { + align-items: baseline !important; + } + + .align-items-sm-stretch { + align-items: stretch !important; + } + + .align-content-sm-start { + align-content: flex-start !important; + } + + .align-content-sm-end { + align-content: flex-end !important; + } + + .align-content-sm-center { + align-content: center !important; + } + + .align-content-sm-between { + align-content: space-between !important; + } + + .align-content-sm-around { + align-content: space-around !important; + } + + .align-content-sm-stretch { + align-content: stretch !important; + } + + .align-self-sm-auto { + align-self: auto !important; + } + + .align-self-sm-start { + align-self: flex-start !important; + } + + .align-self-sm-end { + align-self: flex-end !important; + } + + .align-self-sm-center { + align-self: center !important; + } + + .align-self-sm-baseline { + align-self: baseline !important; + } + + .align-self-sm-stretch { + align-self: stretch !important; + } + + .order-sm-first { + order: -1 !important; + } + + .order-sm-0 { + order: 0 !important; + } + + .order-sm-1 { + order: 1 !important; + } + + .order-sm-2 { + order: 2 !important; + } + + .order-sm-3 { + order: 3 !important; + } + + .order-sm-4 { + order: 4 !important; + } + + .order-sm-5 { + order: 5 !important; + } + + .order-sm-last { + order: 6 !important; + } + + .m-sm-0 { + margin: 0 !important; + } + + .m-sm-1 { + margin: 0.25rem !important; + } + + .m-sm-2 { + margin: 0.5rem !important; + } + + .m-sm-3 { + margin: 1rem !important; + } + + .m-sm-4 { + margin: 1.5rem !important; + } + + .m-sm-5 { + margin: 3rem !important; + } + + .m-sm-auto { + margin: auto !important; + } + + .mx-sm-0 { + margin-right: 0 !important; + margin-left: 0 !important; + } + + .mx-sm-1 { + margin-right: 0.25rem !important; + margin-left: 0.25rem !important; + } + + .mx-sm-2 { + margin-right: 0.5rem !important; + margin-left: 0.5rem !important; + } + + .mx-sm-3 { + margin-right: 1rem !important; + margin-left: 1rem !important; + } + + .mx-sm-4 { + margin-right: 1.5rem !important; + margin-left: 1.5rem !important; + } + + .mx-sm-5 { + margin-right: 3rem !important; + margin-left: 3rem !important; + } + + .mx-sm-auto { + margin-right: auto !important; + margin-left: auto !important; + } + + .my-sm-0 { + margin-top: 0 !important; + margin-bottom: 0 !important; + } + + .my-sm-1 { + margin-top: 0.25rem !important; + margin-bottom: 0.25rem !important; + } + + .my-sm-2 { + margin-top: 0.5rem !important; + margin-bottom: 0.5rem !important; + } + + .my-sm-3 { + margin-top: 1rem !important; + margin-bottom: 1rem !important; + } + + .my-sm-4 { + margin-top: 1.5rem !important; + margin-bottom: 1.5rem !important; + } + + .my-sm-5 { + margin-top: 3rem !important; + margin-bottom: 3rem !important; + } + + .my-sm-auto { + margin-top: auto !important; + margin-bottom: auto !important; + } + + .mt-sm-0 { + margin-top: 0 !important; + } + + .mt-sm-1 { + margin-top: 0.25rem !important; + } + + .mt-sm-2 { + margin-top: 0.5rem !important; + } + + .mt-sm-3 { + margin-top: 1rem !important; + } + + .mt-sm-4 { + margin-top: 1.5rem !important; + } + + .mt-sm-5 { + margin-top: 3rem !important; + } + + .mt-sm-auto { + margin-top: auto !important; + } + + .me-sm-0 { + margin-right: 0 !important; + } + + .me-sm-1 { + margin-right: 0.25rem !important; + } + + .me-sm-2 { + margin-right: 0.5rem !important; + } + + .me-sm-3 { + margin-right: 1rem !important; + } + + .me-sm-4 { + margin-right: 1.5rem !important; + } + + .me-sm-5 { + margin-right: 3rem !important; + } + + .me-sm-auto { + margin-right: auto !important; + } + + .mb-sm-0 { + margin-bottom: 0 !important; + } + + .mb-sm-1 { + margin-bottom: 0.25rem !important; + } + + .mb-sm-2 { + margin-bottom: 0.5rem !important; + } + + .mb-sm-3 { + margin-bottom: 1rem !important; + } + + .mb-sm-4 { + margin-bottom: 1.5rem !important; + } + + .mb-sm-5 { + margin-bottom: 3rem !important; + } + + .mb-sm-auto { + margin-bottom: auto !important; + } + + .ms-sm-0 { + margin-left: 0 !important; + } + + .ms-sm-1 { + margin-left: 0.25rem !important; + } + + .ms-sm-2 { + margin-left: 0.5rem !important; + } + + .ms-sm-3 { + margin-left: 1rem !important; + } + + .ms-sm-4 { + margin-left: 1.5rem !important; + } + + .ms-sm-5 { + margin-left: 3rem !important; + } + + .ms-sm-auto { + margin-left: auto !important; + } + + .p-sm-0 { + padding: 0 !important; + } + + .p-sm-1 { + padding: 0.25rem !important; + } + + .p-sm-2 { + padding: 0.5rem !important; + } + + .p-sm-3 { + padding: 1rem !important; + } + + .p-sm-4 { + padding: 1.5rem !important; + } + + .p-sm-5 { + padding: 3rem !important; + } + + .px-sm-0 { + padding-right: 0 !important; + padding-left: 0 !important; + } + + .px-sm-1 { + padding-right: 0.25rem !important; + padding-left: 0.25rem !important; + } + + .px-sm-2 { + padding-right: 0.5rem !important; + padding-left: 0.5rem !important; + } + + .px-sm-3 { + padding-right: 1rem !important; + padding-left: 1rem !important; + } + + .px-sm-4 { + padding-right: 1.5rem !important; + padding-left: 1.5rem !important; + } + + .px-sm-5 { + padding-right: 3rem !important; + padding-left: 3rem !important; + } + + .py-sm-0 { + padding-top: 0 !important; + padding-bottom: 0 !important; + } + + .py-sm-1 { + padding-top: 0.25rem !important; + padding-bottom: 0.25rem !important; + } + + .py-sm-2 { + padding-top: 0.5rem !important; + padding-bottom: 0.5rem !important; + } + + .py-sm-3 { + padding-top: 1rem !important; + padding-bottom: 1rem !important; + } + + .py-sm-4 { + padding-top: 1.5rem !important; + padding-bottom: 1.5rem !important; + } + + .py-sm-5 { + padding-top: 3rem !important; + padding-bottom: 3rem !important; + } + + .pt-sm-0 { + padding-top: 0 !important; + } + + .pt-sm-1 { + padding-top: 0.25rem !important; + } + + .pt-sm-2 { + padding-top: 0.5rem !important; + } + + .pt-sm-3 { + padding-top: 1rem !important; + } + + .pt-sm-4 { + padding-top: 1.5rem !important; + } + + .pt-sm-5 { + padding-top: 3rem !important; + } + + .pe-sm-0 { + padding-right: 0 !important; + } + + .pe-sm-1 { + padding-right: 0.25rem !important; + } + + .pe-sm-2 { + padding-right: 0.5rem !important; + } + + .pe-sm-3 { + padding-right: 1rem !important; + } + + .pe-sm-4 { + padding-right: 1.5rem !important; + } + + .pe-sm-5 { + padding-right: 3rem !important; + } + + .pb-sm-0 { + padding-bottom: 0 !important; + } + + .pb-sm-1 { + padding-bottom: 0.25rem !important; + } + + .pb-sm-2 { + padding-bottom: 0.5rem !important; + } + + .pb-sm-3 { + padding-bottom: 1rem !important; + } + + .pb-sm-4 { + padding-bottom: 1.5rem !important; + } + + .pb-sm-5 { + padding-bottom: 3rem !important; + } + + .ps-sm-0 { + padding-left: 0 !important; + } + + .ps-sm-1 { + padding-left: 0.25rem !important; + } + + .ps-sm-2 { + padding-left: 0.5rem !important; + } + + .ps-sm-3 { + padding-left: 1rem !important; + } + + .ps-sm-4 { + padding-left: 1.5rem !important; + } + + .ps-sm-5 { + padding-left: 3rem !important; + } + + .text-sm-start { + text-align: left !important; + } + + .text-sm-end { + text-align: right !important; + } + + .text-sm-center { + text-align: center !important; + } +} + +@media (min-width: 768px) { + .float-md-start { + float: left !important; + } + + .float-md-end { + float: right !important; + } + + .float-md-none { + float: none !important; + } + + .d-md-inline { + display: inline !important; + } + + .d-md-inline-block { + display: inline-block !important; + } + + .d-md-block { + display: block !important; + } + + .d-md-grid { + display: grid !important; + } + + .d-md-table { + display: table !important; + } + + .d-md-table-row { + display: table-row !important; + } + + .d-md-table-cell { + display: table-cell !important; + } + + .d-md-flex { + display: flex !important; + } + + .d-md-inline-flex { + display: inline-flex !important; + } + + .d-md-none { + display: none !important; + } + + .flex-md-fill { + flex: 1 1 auto !important; + } + + .flex-md-row { + flex-direction: row !important; + } + + .flex-md-column { + flex-direction: column !important; + } + + .flex-md-row-reverse { + flex-direction: row-reverse !important; + } + + .flex-md-column-reverse { + flex-direction: column-reverse !important; + } + + .flex-md-grow-0 { + flex-grow: 0 !important; + } + + .flex-md-grow-1 { + flex-grow: 1 !important; + } + + .flex-md-shrink-0 { + flex-shrink: 0 !important; + } + + .flex-md-shrink-1 { + flex-shrink: 1 !important; + } + + .flex-md-wrap { + flex-wrap: wrap !important; + } + + .flex-md-nowrap { + flex-wrap: nowrap !important; + } + + .flex-md-wrap-reverse { + flex-wrap: wrap-reverse !important; + } + + .gap-md-0 { + gap: 0 !important; + } + + .gap-md-1 { + gap: 0.25rem !important; + } + + .gap-md-2 { + gap: 0.5rem !important; + } + + .gap-md-3 { + gap: 1rem !important; + } + + .gap-md-4 { + gap: 1.5rem !important; + } + + .gap-md-5 { + gap: 3rem !important; + } + + .justify-content-md-start { + justify-content: flex-start !important; + } + + .justify-content-md-end { + justify-content: flex-end !important; + } + + .justify-content-md-center { + justify-content: center !important; + } + + .justify-content-md-between { + justify-content: space-between !important; + } + + .justify-content-md-around { + justify-content: space-around !important; + } + + .justify-content-md-evenly { + justify-content: space-evenly !important; + } + + .align-items-md-start { + align-items: flex-start !important; + } + + .align-items-md-end { + align-items: flex-end !important; + } + + .align-items-md-center { + align-items: center !important; + } + + .align-items-md-baseline { + align-items: baseline !important; + } + + .align-items-md-stretch { + align-items: stretch !important; + } + + .align-content-md-start { + align-content: flex-start !important; + } + + .align-content-md-end { + align-content: flex-end !important; + } + + .align-content-md-center { + align-content: center !important; + } + + .align-content-md-between { + align-content: space-between !important; + } + + .align-content-md-around { + align-content: space-around !important; + } + + .align-content-md-stretch { + align-content: stretch !important; + } + + .align-self-md-auto { + align-self: auto !important; + } + + .align-self-md-start { + align-self: flex-start !important; + } + + .align-self-md-end { + align-self: flex-end !important; + } + + .align-self-md-center { + align-self: center !important; + } + + .align-self-md-baseline { + align-self: baseline !important; + } + + .align-self-md-stretch { + align-self: stretch !important; + } + + .order-md-first { + order: -1 !important; + } + + .order-md-0 { + order: 0 !important; + } + + .order-md-1 { + order: 1 !important; + } + + .order-md-2 { + order: 2 !important; + } + + .order-md-3 { + order: 3 !important; + } + + .order-md-4 { + order: 4 !important; + } + + .order-md-5 { + order: 5 !important; + } + + .order-md-last { + order: 6 !important; + } + + .m-md-0 { + margin: 0 !important; + } + + .m-md-1 { + margin: 0.25rem !important; + } + + .m-md-2 { + margin: 0.5rem !important; + } + + .m-md-3 { + margin: 1rem !important; + } + + .m-md-4 { + margin: 1.5rem !important; + } + + .m-md-5 { + margin: 3rem !important; + } + + .m-md-auto { + margin: auto !important; + } + + .mx-md-0 { + margin-right: 0 !important; + margin-left: 0 !important; + } + + .mx-md-1 { + margin-right: 0.25rem !important; + margin-left: 0.25rem !important; + } + + .mx-md-2 { + margin-right: 0.5rem !important; + margin-left: 0.5rem !important; + } + + .mx-md-3 { + margin-right: 1rem !important; + margin-left: 1rem !important; + } + + .mx-md-4 { + margin-right: 1.5rem !important; + margin-left: 1.5rem !important; + } + + .mx-md-5 { + margin-right: 3rem !important; + margin-left: 3rem !important; + } + + .mx-md-auto { + margin-right: auto !important; + margin-left: auto !important; + } + + .my-md-0 { + margin-top: 0 !important; + margin-bottom: 0 !important; + } + + .my-md-1 { + margin-top: 0.25rem !important; + margin-bottom: 0.25rem !important; + } + + .my-md-2 { + margin-top: 0.5rem !important; + margin-bottom: 0.5rem !important; + } + + .my-md-3 { + margin-top: 1rem !important; + margin-bottom: 1rem !important; + } + + .my-md-4 { + margin-top: 1.5rem !important; + margin-bottom: 1.5rem !important; + } + + .my-md-5 { + margin-top: 3rem !important; + margin-bottom: 3rem !important; + } + + .my-md-auto { + margin-top: auto !important; + margin-bottom: auto !important; + } + + .mt-md-0 { + margin-top: 0 !important; + } + + .mt-md-1 { + margin-top: 0.25rem !important; + } + + .mt-md-2 { + margin-top: 0.5rem !important; + } + + .mt-md-3 { + margin-top: 1rem !important; + } + + .mt-md-4 { + margin-top: 1.5rem !important; + } + + .mt-md-5 { + margin-top: 3rem !important; + } + + .mt-md-auto { + margin-top: auto !important; + } + + .me-md-0 { + margin-right: 0 !important; + } + + .me-md-1 { + margin-right: 0.25rem !important; + } + + .me-md-2 { + margin-right: 0.5rem !important; + } + + .me-md-3 { + margin-right: 1rem !important; + } + + .me-md-4 { + margin-right: 1.5rem !important; + } + + .me-md-5 { + margin-right: 3rem !important; + } + + .me-md-auto { + margin-right: auto !important; + } + + .mb-md-0 { + margin-bottom: 0 !important; + } + + .mb-md-1 { + margin-bottom: 0.25rem !important; + } + + .mb-md-2 { + margin-bottom: 0.5rem !important; + } + + .mb-md-3 { + margin-bottom: 1rem !important; + } + + .mb-md-4 { + margin-bottom: 1.5rem !important; + } + + .mb-md-5 { + margin-bottom: 3rem !important; + } + + .mb-md-auto { + margin-bottom: auto !important; + } + + .ms-md-0 { + margin-left: 0 !important; + } + + .ms-md-1 { + margin-left: 0.25rem !important; + } + + .ms-md-2 { + margin-left: 0.5rem !important; + } + + .ms-md-3 { + margin-left: 1rem !important; + } + + .ms-md-4 { + margin-left: 1.5rem !important; + } + + .ms-md-5 { + margin-left: 3rem !important; + } + + .ms-md-auto { + margin-left: auto !important; + } + + .p-md-0 { + padding: 0 !important; + } + + .p-md-1 { + padding: 0.25rem !important; + } + + .p-md-2 { + padding: 0.5rem !important; + } + + .p-md-3 { + padding: 1rem !important; + } + + .p-md-4 { + padding: 1.5rem !important; + } + + .p-md-5 { + padding: 3rem !important; + } + + .px-md-0 { + padding-right: 0 !important; + padding-left: 0 !important; + } + + .px-md-1 { + padding-right: 0.25rem !important; + padding-left: 0.25rem !important; + } + + .px-md-2 { + padding-right: 0.5rem !important; + padding-left: 0.5rem !important; + } + + .px-md-3 { + padding-right: 1rem !important; + padding-left: 1rem !important; + } + + .px-md-4 { + padding-right: 1.5rem !important; + padding-left: 1.5rem !important; + } + + .px-md-5 { + padding-right: 3rem !important; + padding-left: 3rem !important; + } + + .py-md-0 { + padding-top: 0 !important; + padding-bottom: 0 !important; + } + + .py-md-1 { + padding-top: 0.25rem !important; + padding-bottom: 0.25rem !important; + } + + .py-md-2 { + padding-top: 0.5rem !important; + padding-bottom: 0.5rem !important; + } + + .py-md-3 { + padding-top: 1rem !important; + padding-bottom: 1rem !important; + } + + .py-md-4 { + padding-top: 1.5rem !important; + padding-bottom: 1.5rem !important; + } + + .py-md-5 { + padding-top: 3rem !important; + padding-bottom: 3rem !important; + } + + .pt-md-0 { + padding-top: 0 !important; + } + + .pt-md-1 { + padding-top: 0.25rem !important; + } + + .pt-md-2 { + padding-top: 0.5rem !important; + } + + .pt-md-3 { + padding-top: 1rem !important; + } + + .pt-md-4 { + padding-top: 1.5rem !important; + } + + .pt-md-5 { + padding-top: 3rem !important; + } + + .pe-md-0 { + padding-right: 0 !important; + } + + .pe-md-1 { + padding-right: 0.25rem !important; + } + + .pe-md-2 { + padding-right: 0.5rem !important; + } + + .pe-md-3 { + padding-right: 1rem !important; + } + + .pe-md-4 { + padding-right: 1.5rem !important; + } + + .pe-md-5 { + padding-right: 3rem !important; + } + + .pb-md-0 { + padding-bottom: 0 !important; + } + + .pb-md-1 { + padding-bottom: 0.25rem !important; + } + + .pb-md-2 { + padding-bottom: 0.5rem !important; + } + + .pb-md-3 { + padding-bottom: 1rem !important; + } + + .pb-md-4 { + padding-bottom: 1.5rem !important; + } + + .pb-md-5 { + padding-bottom: 3rem !important; + } + + .ps-md-0 { + padding-left: 0 !important; + } + + .ps-md-1 { + padding-left: 0.25rem !important; + } + + .ps-md-2 { + padding-left: 0.5rem !important; + } + + .ps-md-3 { + padding-left: 1rem !important; + } + + .ps-md-4 { + padding-left: 1.5rem !important; + } + + .ps-md-5 { + padding-left: 3rem !important; + } + + .text-md-start { + text-align: left !important; + } + + .text-md-end { + text-align: right !important; + } + + .text-md-center { + text-align: center !important; + } +} + +@media (min-width: 992px) { + .float-lg-start { + float: left !important; + } + + .float-lg-end { + float: right !important; + } + + .float-lg-none { + float: none !important; + } + + .d-lg-inline { + display: inline !important; + } + + .d-lg-inline-block { + display: inline-block !important; + } + + .d-lg-block { + display: block !important; + } + + .d-lg-grid { + display: grid !important; + } + + .d-lg-table { + display: table !important; + } + + .d-lg-table-row { + display: table-row !important; + } + + .d-lg-table-cell { + display: table-cell !important; + } + + .d-lg-flex { + display: flex !important; + } + + .d-lg-inline-flex { + display: inline-flex !important; + } + + .d-lg-none { + display: none !important; + } + + .flex-lg-fill { + flex: 1 1 auto !important; + } + + .flex-lg-row { + flex-direction: row !important; + } + + .flex-lg-column { + flex-direction: column !important; + } + + .flex-lg-row-reverse { + flex-direction: row-reverse !important; + } + + .flex-lg-column-reverse { + flex-direction: column-reverse !important; + } + + .flex-lg-grow-0 { + flex-grow: 0 !important; + } + + .flex-lg-grow-1 { + flex-grow: 1 !important; + } + + .flex-lg-shrink-0 { + flex-shrink: 0 !important; + } + + .flex-lg-shrink-1 { + flex-shrink: 1 !important; + } + + .flex-lg-wrap { + flex-wrap: wrap !important; + } + + .flex-lg-nowrap { + flex-wrap: nowrap !important; + } + + .flex-lg-wrap-reverse { + flex-wrap: wrap-reverse !important; + } + + .gap-lg-0 { + gap: 0 !important; + } + + .gap-lg-1 { + gap: 0.25rem !important; + } + + .gap-lg-2 { + gap: 0.5rem !important; + } + + .gap-lg-3 { + gap: 1rem !important; + } + + .gap-lg-4 { + gap: 1.5rem !important; + } + + .gap-lg-5 { + gap: 3rem !important; + } + + .justify-content-lg-start { + justify-content: flex-start !important; + } + + .justify-content-lg-end { + justify-content: flex-end !important; + } + + .justify-content-lg-center { + justify-content: center !important; + } + + .justify-content-lg-between { + justify-content: space-between !important; + } + + .justify-content-lg-around { + justify-content: space-around !important; + } + + .justify-content-lg-evenly { + justify-content: space-evenly !important; + } + + .align-items-lg-start { + align-items: flex-start !important; + } + + .align-items-lg-end { + align-items: flex-end !important; + } + + .align-items-lg-center { + align-items: center !important; + } + + .align-items-lg-baseline { + align-items: baseline !important; + } + + .align-items-lg-stretch { + align-items: stretch !important; + } + + .align-content-lg-start { + align-content: flex-start !important; + } + + .align-content-lg-end { + align-content: flex-end !important; + } + + .align-content-lg-center { + align-content: center !important; + } + + .align-content-lg-between { + align-content: space-between !important; + } + + .align-content-lg-around { + align-content: space-around !important; + } + + .align-content-lg-stretch { + align-content: stretch !important; + } + + .align-self-lg-auto { + align-self: auto !important; + } + + .align-self-lg-start { + align-self: flex-start !important; + } + + .align-self-lg-end { + align-self: flex-end !important; + } + + .align-self-lg-center { + align-self: center !important; + } + + .align-self-lg-baseline { + align-self: baseline !important; + } + + .align-self-lg-stretch { + align-self: stretch !important; + } + + .order-lg-first { + order: -1 !important; + } + + .order-lg-0 { + order: 0 !important; + } + + .order-lg-1 { + order: 1 !important; + } + + .order-lg-2 { + order: 2 !important; + } + + .order-lg-3 { + order: 3 !important; + } + + .order-lg-4 { + order: 4 !important; + } + + .order-lg-5 { + order: 5 !important; + } + + .order-lg-last { + order: 6 !important; + } + + .m-lg-0 { + margin: 0 !important; + } + + .m-lg-1 { + margin: 0.25rem !important; + } + + .m-lg-2 { + margin: 0.5rem !important; + } + + .m-lg-3 { + margin: 1rem !important; + } + + .m-lg-4 { + margin: 1.5rem !important; + } + + .m-lg-5 { + margin: 3rem !important; + } + + .m-lg-auto { + margin: auto !important; + } + + .mx-lg-0 { + margin-right: 0 !important; + margin-left: 0 !important; + } + + .mx-lg-1 { + margin-right: 0.25rem !important; + margin-left: 0.25rem !important; + } + + .mx-lg-2 { + margin-right: 0.5rem !important; + margin-left: 0.5rem !important; + } + + .mx-lg-3 { + margin-right: 1rem !important; + margin-left: 1rem !important; + } + + .mx-lg-4 { + margin-right: 1.5rem !important; + margin-left: 1.5rem !important; + } + + .mx-lg-5 { + margin-right: 3rem !important; + margin-left: 3rem !important; + } + + .mx-lg-auto { + margin-right: auto !important; + margin-left: auto !important; + } + + .my-lg-0 { + margin-top: 0 !important; + margin-bottom: 0 !important; + } + + .my-lg-1 { + margin-top: 0.25rem !important; + margin-bottom: 0.25rem !important; + } + + .my-lg-2 { + margin-top: 0.5rem !important; + margin-bottom: 0.5rem !important; + } + + .my-lg-3 { + margin-top: 1rem !important; + margin-bottom: 1rem !important; + } + + .my-lg-4 { + margin-top: 1.5rem !important; + margin-bottom: 1.5rem !important; + } + + .my-lg-5 { + margin-top: 3rem !important; + margin-bottom: 3rem !important; + } + + .my-lg-auto { + margin-top: auto !important; + margin-bottom: auto !important; + } + + .mt-lg-0 { + margin-top: 0 !important; + } + + .mt-lg-1 { + margin-top: 0.25rem !important; + } + + .mt-lg-2 { + margin-top: 0.5rem !important; + } + + .mt-lg-3 { + margin-top: 1rem !important; + } + + .mt-lg-4 { + margin-top: 1.5rem !important; + } + + .mt-lg-5 { + margin-top: 3rem !important; + } + + .mt-lg-auto { + margin-top: auto !important; + } + + .me-lg-0 { + margin-right: 0 !important; + } + + .me-lg-1 { + margin-right: 0.25rem !important; + } + + .me-lg-2 { + margin-right: 0.5rem !important; + } + + .me-lg-3 { + margin-right: 1rem !important; + } + + .me-lg-4 { + margin-right: 1.5rem !important; + } + + .me-lg-5 { + margin-right: 3rem !important; + } + + .me-lg-auto { + margin-right: auto !important; + } + + .mb-lg-0 { + margin-bottom: 0 !important; + } + + .mb-lg-1 { + margin-bottom: 0.25rem !important; + } + + .mb-lg-2 { + margin-bottom: 0.5rem !important; + } + + .mb-lg-3 { + margin-bottom: 1rem !important; + } + + .mb-lg-4 { + margin-bottom: 1.5rem !important; + } + + .mb-lg-5 { + margin-bottom: 3rem !important; + } + + .mb-lg-auto { + margin-bottom: auto !important; + } + + .ms-lg-0 { + margin-left: 0 !important; + } + + .ms-lg-1 { + margin-left: 0.25rem !important; + } + + .ms-lg-2 { + margin-left: 0.5rem !important; + } + + .ms-lg-3 { + margin-left: 1rem !important; + } + + .ms-lg-4 { + margin-left: 1.5rem !important; + } + + .ms-lg-5 { + margin-left: 3rem !important; + } + + .ms-lg-auto { + margin-left: auto !important; + } + + .p-lg-0 { + padding: 0 !important; + } + + .p-lg-1 { + padding: 0.25rem !important; + } + + .p-lg-2 { + padding: 0.5rem !important; + } + + .p-lg-3 { + padding: 1rem !important; + } + + .p-lg-4 { + padding: 1.5rem !important; + } + + .p-lg-5 { + padding: 3rem !important; + } + + .px-lg-0 { + padding-right: 0 !important; + padding-left: 0 !important; + } + + .px-lg-1 { + padding-right: 0.25rem !important; + padding-left: 0.25rem !important; + } + + .px-lg-2 { + padding-right: 0.5rem !important; + padding-left: 0.5rem !important; + } + + .px-lg-3 { + padding-right: 1rem !important; + padding-left: 1rem !important; + } + + .px-lg-4 { + padding-right: 1.5rem !important; + padding-left: 1.5rem !important; + } + + .px-lg-5 { + padding-right: 3rem !important; + padding-left: 3rem !important; + } + + .py-lg-0 { + padding-top: 0 !important; + padding-bottom: 0 !important; + } + + .py-lg-1 { + padding-top: 0.25rem !important; + padding-bottom: 0.25rem !important; + } + + .py-lg-2 { + padding-top: 0.5rem !important; + padding-bottom: 0.5rem !important; + } + + .py-lg-3 { + padding-top: 1rem !important; + padding-bottom: 1rem !important; + } + + .py-lg-4 { + padding-top: 1.5rem !important; + padding-bottom: 1.5rem !important; + } + + .py-lg-5 { + padding-top: 3rem !important; + padding-bottom: 3rem !important; + } + + .pt-lg-0 { + padding-top: 0 !important; + } + + .pt-lg-1 { + padding-top: 0.25rem !important; + } + + .pt-lg-2 { + padding-top: 0.5rem !important; + } + + .pt-lg-3 { + padding-top: 1rem !important; + } + + .pt-lg-4 { + padding-top: 1.5rem !important; + } + + .pt-lg-5 { + padding-top: 3rem !important; + } + + .pe-lg-0 { + padding-right: 0 !important; + } + + .pe-lg-1 { + padding-right: 0.25rem !important; + } + + .pe-lg-2 { + padding-right: 0.5rem !important; + } + + .pe-lg-3 { + padding-right: 1rem !important; + } + + .pe-lg-4 { + padding-right: 1.5rem !important; + } + + .pe-lg-5 { + padding-right: 3rem !important; + } + + .pb-lg-0 { + padding-bottom: 0 !important; + } + + .pb-lg-1 { + padding-bottom: 0.25rem !important; + } + + .pb-lg-2 { + padding-bottom: 0.5rem !important; + } + + .pb-lg-3 { + padding-bottom: 1rem !important; + } + + .pb-lg-4 { + padding-bottom: 1.5rem !important; + } + + .pb-lg-5 { + padding-bottom: 3rem !important; + } + + .ps-lg-0 { + padding-left: 0 !important; + } + + .ps-lg-1 { + padding-left: 0.25rem !important; + } + + .ps-lg-2 { + padding-left: 0.5rem !important; + } + + .ps-lg-3 { + padding-left: 1rem !important; + } + + .ps-lg-4 { + padding-left: 1.5rem !important; + } + + .ps-lg-5 { + padding-left: 3rem !important; + } + + .text-lg-start { + text-align: left !important; + } + + .text-lg-end { + text-align: right !important; + } + + .text-lg-center { + text-align: center !important; + } +} + +@media (min-width: 1200px) { + .float-xl-start { + float: left !important; + } + + .float-xl-end { + float: right !important; + } + + .float-xl-none { + float: none !important; + } + + .d-xl-inline { + display: inline !important; + } + + .d-xl-inline-block { + display: inline-block !important; + } + + .d-xl-block { + display: block !important; + } + + .d-xl-grid { + display: grid !important; + } + + .d-xl-table { + display: table !important; + } + + .d-xl-table-row { + display: table-row !important; + } + + .d-xl-table-cell { + display: table-cell !important; + } + + .d-xl-flex { + display: flex !important; + } + + .d-xl-inline-flex { + display: inline-flex !important; + } + + .d-xl-none { + display: none !important; + } + + .flex-xl-fill { + flex: 1 1 auto !important; + } + + .flex-xl-row { + flex-direction: row !important; + } + + .flex-xl-column { + flex-direction: column !important; + } + + .flex-xl-row-reverse { + flex-direction: row-reverse !important; + } + + .flex-xl-column-reverse { + flex-direction: column-reverse !important; + } + + .flex-xl-grow-0 { + flex-grow: 0 !important; + } + + .flex-xl-grow-1 { + flex-grow: 1 !important; + } + + .flex-xl-shrink-0 { + flex-shrink: 0 !important; + } + + .flex-xl-shrink-1 { + flex-shrink: 1 !important; + } + + .flex-xl-wrap { + flex-wrap: wrap !important; + } + + .flex-xl-nowrap { + flex-wrap: nowrap !important; + } + + .flex-xl-wrap-reverse { + flex-wrap: wrap-reverse !important; + } + + .gap-xl-0 { + gap: 0 !important; + } + + .gap-xl-1 { + gap: 0.25rem !important; + } + + .gap-xl-2 { + gap: 0.5rem !important; + } + + .gap-xl-3 { + gap: 1rem !important; + } + + .gap-xl-4 { + gap: 1.5rem !important; + } + + .gap-xl-5 { + gap: 3rem !important; + } + + .justify-content-xl-start { + justify-content: flex-start !important; + } + + .justify-content-xl-end { + justify-content: flex-end !important; + } + + .justify-content-xl-center { + justify-content: center !important; + } + + .justify-content-xl-between { + justify-content: space-between !important; + } + + .justify-content-xl-around { + justify-content: space-around !important; + } + + .justify-content-xl-evenly { + justify-content: space-evenly !important; + } + + .align-items-xl-start { + align-items: flex-start !important; + } + + .align-items-xl-end { + align-items: flex-end !important; + } + + .align-items-xl-center { + align-items: center !important; + } + + .align-items-xl-baseline { + align-items: baseline !important; + } + + .align-items-xl-stretch { + align-items: stretch !important; + } + + .align-content-xl-start { + align-content: flex-start !important; + } + + .align-content-xl-end { + align-content: flex-end !important; + } + + .align-content-xl-center { + align-content: center !important; + } + + .align-content-xl-between { + align-content: space-between !important; + } + + .align-content-xl-around { + align-content: space-around !important; + } + + .align-content-xl-stretch { + align-content: stretch !important; + } + + .align-self-xl-auto { + align-self: auto !important; + } + + .align-self-xl-start { + align-self: flex-start !important; + } + + .align-self-xl-end { + align-self: flex-end !important; + } + + .align-self-xl-center { + align-self: center !important; + } + + .align-self-xl-baseline { + align-self: baseline !important; + } + + .align-self-xl-stretch { + align-self: stretch !important; + } + + .order-xl-first { + order: -1 !important; + } + + .order-xl-0 { + order: 0 !important; + } + + .order-xl-1 { + order: 1 !important; + } + + .order-xl-2 { + order: 2 !important; + } + + .order-xl-3 { + order: 3 !important; + } + + .order-xl-4 { + order: 4 !important; + } + + .order-xl-5 { + order: 5 !important; + } + + .order-xl-last { + order: 6 !important; + } + + .m-xl-0 { + margin: 0 !important; + } + + .m-xl-1 { + margin: 0.25rem !important; + } + + .m-xl-2 { + margin: 0.5rem !important; + } + + .m-xl-3 { + margin: 1rem !important; + } + + .m-xl-4 { + margin: 1.5rem !important; + } + + .m-xl-5 { + margin: 3rem !important; + } + + .m-xl-auto { + margin: auto !important; + } + + .mx-xl-0 { + margin-right: 0 !important; + margin-left: 0 !important; + } + + .mx-xl-1 { + margin-right: 0.25rem !important; + margin-left: 0.25rem !important; + } + + .mx-xl-2 { + margin-right: 0.5rem !important; + margin-left: 0.5rem !important; + } + + .mx-xl-3 { + margin-right: 1rem !important; + margin-left: 1rem !important; + } + + .mx-xl-4 { + margin-right: 1.5rem !important; + margin-left: 1.5rem !important; + } + + .mx-xl-5 { + margin-right: 3rem !important; + margin-left: 3rem !important; + } + + .mx-xl-auto { + margin-right: auto !important; + margin-left: auto !important; + } + + .my-xl-0 { + margin-top: 0 !important; + margin-bottom: 0 !important; + } + + .my-xl-1 { + margin-top: 0.25rem !important; + margin-bottom: 0.25rem !important; + } + + .my-xl-2 { + margin-top: 0.5rem !important; + margin-bottom: 0.5rem !important; + } + + .my-xl-3 { + margin-top: 1rem !important; + margin-bottom: 1rem !important; + } + + .my-xl-4 { + margin-top: 1.5rem !important; + margin-bottom: 1.5rem !important; + } + + .my-xl-5 { + margin-top: 3rem !important; + margin-bottom: 3rem !important; + } + + .my-xl-auto { + margin-top: auto !important; + margin-bottom: auto !important; + } + + .mt-xl-0 { + margin-top: 0 !important; + } + + .mt-xl-1 { + margin-top: 0.25rem !important; + } + + .mt-xl-2 { + margin-top: 0.5rem !important; + } + + .mt-xl-3 { + margin-top: 1rem !important; + } + + .mt-xl-4 { + margin-top: 1.5rem !important; + } + + .mt-xl-5 { + margin-top: 3rem !important; + } + + .mt-xl-auto { + margin-top: auto !important; + } + + .me-xl-0 { + margin-right: 0 !important; + } + + .me-xl-1 { + margin-right: 0.25rem !important; + } + + .me-xl-2 { + margin-right: 0.5rem !important; + } + + .me-xl-3 { + margin-right: 1rem !important; + } + + .me-xl-4 { + margin-right: 1.5rem !important; + } + + .me-xl-5 { + margin-right: 3rem !important; + } + + .me-xl-auto { + margin-right: auto !important; + } + + .mb-xl-0 { + margin-bottom: 0 !important; + } + + .mb-xl-1 { + margin-bottom: 0.25rem !important; + } + + .mb-xl-2 { + margin-bottom: 0.5rem !important; + } + + .mb-xl-3 { + margin-bottom: 1rem !important; + } + + .mb-xl-4 { + margin-bottom: 1.5rem !important; + } + + .mb-xl-5 { + margin-bottom: 3rem !important; + } + + .mb-xl-auto { + margin-bottom: auto !important; + } + + .ms-xl-0 { + margin-left: 0 !important; + } + + .ms-xl-1 { + margin-left: 0.25rem !important; + } + + .ms-xl-2 { + margin-left: 0.5rem !important; + } + + .ms-xl-3 { + margin-left: 1rem !important; + } + + .ms-xl-4 { + margin-left: 1.5rem !important; + } + + .ms-xl-5 { + margin-left: 3rem !important; + } + + .ms-xl-auto { + margin-left: auto !important; + } + + .p-xl-0 { + padding: 0 !important; + } + + .p-xl-1 { + padding: 0.25rem !important; + } + + .p-xl-2 { + padding: 0.5rem !important; + } + + .p-xl-3 { + padding: 1rem !important; + } + + .p-xl-4 { + padding: 1.5rem !important; + } + + .p-xl-5 { + padding: 3rem !important; + } + + .px-xl-0 { + padding-right: 0 !important; + padding-left: 0 !important; + } + + .px-xl-1 { + padding-right: 0.25rem !important; + padding-left: 0.25rem !important; + } + + .px-xl-2 { + padding-right: 0.5rem !important; + padding-left: 0.5rem !important; + } + + .px-xl-3 { + padding-right: 1rem !important; + padding-left: 1rem !important; + } + + .px-xl-4 { + padding-right: 1.5rem !important; + padding-left: 1.5rem !important; + } + + .px-xl-5 { + padding-right: 3rem !important; + padding-left: 3rem !important; + } + + .py-xl-0 { + padding-top: 0 !important; + padding-bottom: 0 !important; + } + + .py-xl-1 { + padding-top: 0.25rem !important; + padding-bottom: 0.25rem !important; + } + + .py-xl-2 { + padding-top: 0.5rem !important; + padding-bottom: 0.5rem !important; + } + + .py-xl-3 { + padding-top: 1rem !important; + padding-bottom: 1rem !important; + } + + .py-xl-4 { + padding-top: 1.5rem !important; + padding-bottom: 1.5rem !important; + } + + .py-xl-5 { + padding-top: 3rem !important; + padding-bottom: 3rem !important; + } + + .pt-xl-0 { + padding-top: 0 !important; + } + + .pt-xl-1 { + padding-top: 0.25rem !important; + } + + .pt-xl-2 { + padding-top: 0.5rem !important; + } + + .pt-xl-3 { + padding-top: 1rem !important; + } + + .pt-xl-4 { + padding-top: 1.5rem !important; + } + + .pt-xl-5 { + padding-top: 3rem !important; + } + + .pe-xl-0 { + padding-right: 0 !important; + } + + .pe-xl-1 { + padding-right: 0.25rem !important; + } + + .pe-xl-2 { + padding-right: 0.5rem !important; + } + + .pe-xl-3 { + padding-right: 1rem !important; + } + + .pe-xl-4 { + padding-right: 1.5rem !important; + } + + .pe-xl-5 { + padding-right: 3rem !important; + } + + .pb-xl-0 { + padding-bottom: 0 !important; + } + + .pb-xl-1 { + padding-bottom: 0.25rem !important; + } + + .pb-xl-2 { + padding-bottom: 0.5rem !important; + } + + .pb-xl-3 { + padding-bottom: 1rem !important; + } + + .pb-xl-4 { + padding-bottom: 1.5rem !important; + } + + .pb-xl-5 { + padding-bottom: 3rem !important; + } + + .ps-xl-0 { + padding-left: 0 !important; + } + + .ps-xl-1 { + padding-left: 0.25rem !important; + } + + .ps-xl-2 { + padding-left: 0.5rem !important; + } + + .ps-xl-3 { + padding-left: 1rem !important; + } + + .ps-xl-4 { + padding-left: 1.5rem !important; + } + + .ps-xl-5 { + padding-left: 3rem !important; + } + + .text-xl-start { + text-align: left !important; + } + + .text-xl-end { + text-align: right !important; + } + + .text-xl-center { + text-align: center !important; + } +} + +@media (min-width: 1400px) { + .float-xxl-start { + float: left !important; + } + + .float-xxl-end { + float: right !important; + } + + .float-xxl-none { + float: none !important; + } + + .d-xxl-inline { + display: inline !important; + } + + .d-xxl-inline-block { + display: inline-block !important; + } + + .d-xxl-block { + display: block !important; + } + + .d-xxl-grid { + display: grid !important; + } + + .d-xxl-table { + display: table !important; + } + + .d-xxl-table-row { + display: table-row !important; + } + + .d-xxl-table-cell { + display: table-cell !important; + } + + .d-xxl-flex { + display: flex !important; + } + + .d-xxl-inline-flex { + display: inline-flex !important; + } + + .d-xxl-none { + display: none !important; + } + + .flex-xxl-fill { + flex: 1 1 auto !important; + } + + .flex-xxl-row { + flex-direction: row !important; + } + + .flex-xxl-column { + flex-direction: column !important; + } + + .flex-xxl-row-reverse { + flex-direction: row-reverse !important; + } + + .flex-xxl-column-reverse { + flex-direction: column-reverse !important; + } + + .flex-xxl-grow-0 { + flex-grow: 0 !important; + } + + .flex-xxl-grow-1 { + flex-grow: 1 !important; + } + + .flex-xxl-shrink-0 { + flex-shrink: 0 !important; + } + + .flex-xxl-shrink-1 { + flex-shrink: 1 !important; + } + + .flex-xxl-wrap { + flex-wrap: wrap !important; + } + + .flex-xxl-nowrap { + flex-wrap: nowrap !important; + } + + .flex-xxl-wrap-reverse { + flex-wrap: wrap-reverse !important; + } + + .gap-xxl-0 { + gap: 0 !important; + } + + .gap-xxl-1 { + gap: 0.25rem !important; + } + + .gap-xxl-2 { + gap: 0.5rem !important; + } + + .gap-xxl-3 { + gap: 1rem !important; + } + + .gap-xxl-4 { + gap: 1.5rem !important; + } + + .gap-xxl-5 { + gap: 3rem !important; + } + + .justify-content-xxl-start { + justify-content: flex-start !important; + } + + .justify-content-xxl-end { + justify-content: flex-end !important; + } + + .justify-content-xxl-center { + justify-content: center !important; + } + + .justify-content-xxl-between { + justify-content: space-between !important; + } + + .justify-content-xxl-around { + justify-content: space-around !important; + } + + .justify-content-xxl-evenly { + justify-content: space-evenly !important; + } + + .align-items-xxl-start { + align-items: flex-start !important; + } + + .align-items-xxl-end { + align-items: flex-end !important; + } + + .align-items-xxl-center { + align-items: center !important; + } + + .align-items-xxl-baseline { + align-items: baseline !important; + } + + .align-items-xxl-stretch { + align-items: stretch !important; + } + + .align-content-xxl-start { + align-content: flex-start !important; + } + + .align-content-xxl-end { + align-content: flex-end !important; + } + + .align-content-xxl-center { + align-content: center !important; + } + + .align-content-xxl-between { + align-content: space-between !important; + } + + .align-content-xxl-around { + align-content: space-around !important; + } + + .align-content-xxl-stretch { + align-content: stretch !important; + } + + .align-self-xxl-auto { + align-self: auto !important; + } + + .align-self-xxl-start { + align-self: flex-start !important; + } + + .align-self-xxl-end { + align-self: flex-end !important; + } + + .align-self-xxl-center { + align-self: center !important; + } + + .align-self-xxl-baseline { + align-self: baseline !important; + } + + .align-self-xxl-stretch { + align-self: stretch !important; + } + + .order-xxl-first { + order: -1 !important; + } + + .order-xxl-0 { + order: 0 !important; + } + + .order-xxl-1 { + order: 1 !important; + } + + .order-xxl-2 { + order: 2 !important; + } + + .order-xxl-3 { + order: 3 !important; + } + + .order-xxl-4 { + order: 4 !important; + } + + .order-xxl-5 { + order: 5 !important; + } + + .order-xxl-last { + order: 6 !important; + } + + .m-xxl-0 { + margin: 0 !important; + } + + .m-xxl-1 { + margin: 0.25rem !important; + } + + .m-xxl-2 { + margin: 0.5rem !important; + } + + .m-xxl-3 { + margin: 1rem !important; + } + + .m-xxl-4 { + margin: 1.5rem !important; + } + + .m-xxl-5 { + margin: 3rem !important; + } + + .m-xxl-auto { + margin: auto !important; + } + + .mx-xxl-0 { + margin-right: 0 !important; + margin-left: 0 !important; + } + + .mx-xxl-1 { + margin-right: 0.25rem !important; + margin-left: 0.25rem !important; + } + + .mx-xxl-2 { + margin-right: 0.5rem !important; + margin-left: 0.5rem !important; + } + + .mx-xxl-3 { + margin-right: 1rem !important; + margin-left: 1rem !important; + } + + .mx-xxl-4 { + margin-right: 1.5rem !important; + margin-left: 1.5rem !important; + } + + .mx-xxl-5 { + margin-right: 3rem !important; + margin-left: 3rem !important; + } + + .mx-xxl-auto { + margin-right: auto !important; + margin-left: auto !important; + } + + .my-xxl-0 { + margin-top: 0 !important; + margin-bottom: 0 !important; + } + + .my-xxl-1 { + margin-top: 0.25rem !important; + margin-bottom: 0.25rem !important; + } + + .my-xxl-2 { + margin-top: 0.5rem !important; + margin-bottom: 0.5rem !important; + } + + .my-xxl-3 { + margin-top: 1rem !important; + margin-bottom: 1rem !important; + } + + .my-xxl-4 { + margin-top: 1.5rem !important; + margin-bottom: 1.5rem !important; + } + + .my-xxl-5 { + margin-top: 3rem !important; + margin-bottom: 3rem !important; + } + + .my-xxl-auto { + margin-top: auto !important; + margin-bottom: auto !important; + } + + .mt-xxl-0 { + margin-top: 0 !important; + } + + .mt-xxl-1 { + margin-top: 0.25rem !important; + } + + .mt-xxl-2 { + margin-top: 0.5rem !important; + } + + .mt-xxl-3 { + margin-top: 1rem !important; + } + + .mt-xxl-4 { + margin-top: 1.5rem !important; + } + + .mt-xxl-5 { + margin-top: 3rem !important; + } + + .mt-xxl-auto { + margin-top: auto !important; + } + + .me-xxl-0 { + margin-right: 0 !important; + } + + .me-xxl-1 { + margin-right: 0.25rem !important; + } + + .me-xxl-2 { + margin-right: 0.5rem !important; + } + + .me-xxl-3 { + margin-right: 1rem !important; + } + + .me-xxl-4 { + margin-right: 1.5rem !important; + } + + .me-xxl-5 { + margin-right: 3rem !important; + } + + .me-xxl-auto { + margin-right: auto !important; + } + + .mb-xxl-0 { + margin-bottom: 0 !important; + } + + .mb-xxl-1 { + margin-bottom: 0.25rem !important; + } + + .mb-xxl-2 { + margin-bottom: 0.5rem !important; + } + + .mb-xxl-3 { + margin-bottom: 1rem !important; + } + + .mb-xxl-4 { + margin-bottom: 1.5rem !important; + } + + .mb-xxl-5 { + margin-bottom: 3rem !important; + } + + .mb-xxl-auto { + margin-bottom: auto !important; + } + + .ms-xxl-0 { + margin-left: 0 !important; + } + + .ms-xxl-1 { + margin-left: 0.25rem !important; + } + + .ms-xxl-2 { + margin-left: 0.5rem !important; + } + + .ms-xxl-3 { + margin-left: 1rem !important; + } + + .ms-xxl-4 { + margin-left: 1.5rem !important; + } + + .ms-xxl-5 { + margin-left: 3rem !important; + } + + .ms-xxl-auto { + margin-left: auto !important; + } + + .p-xxl-0 { + padding: 0 !important; + } + + .p-xxl-1 { + padding: 0.25rem !important; + } + + .p-xxl-2 { + padding: 0.5rem !important; + } + + .p-xxl-3 { + padding: 1rem !important; + } + + .p-xxl-4 { + padding: 1.5rem !important; + } + + .p-xxl-5 { + padding: 3rem !important; + } + + .px-xxl-0 { + padding-right: 0 !important; + padding-left: 0 !important; + } + + .px-xxl-1 { + padding-right: 0.25rem !important; + padding-left: 0.25rem !important; + } + + .px-xxl-2 { + padding-right: 0.5rem !important; + padding-left: 0.5rem !important; + } + + .px-xxl-3 { + padding-right: 1rem !important; + padding-left: 1rem !important; + } + + .px-xxl-4 { + padding-right: 1.5rem !important; + padding-left: 1.5rem !important; + } + + .px-xxl-5 { + padding-right: 3rem !important; + padding-left: 3rem !important; + } + + .py-xxl-0 { + padding-top: 0 !important; + padding-bottom: 0 !important; + } + + .py-xxl-1 { + padding-top: 0.25rem !important; + padding-bottom: 0.25rem !important; + } + + .py-xxl-2 { + padding-top: 0.5rem !important; + padding-bottom: 0.5rem !important; + } + + .py-xxl-3 { + padding-top: 1rem !important; + padding-bottom: 1rem !important; + } + + .py-xxl-4 { + padding-top: 1.5rem !important; + padding-bottom: 1.5rem !important; + } + + .py-xxl-5 { + padding-top: 3rem !important; + padding-bottom: 3rem !important; + } + + .pt-xxl-0 { + padding-top: 0 !important; + } + + .pt-xxl-1 { + padding-top: 0.25rem !important; + } + + .pt-xxl-2 { + padding-top: 0.5rem !important; + } + + .pt-xxl-3 { + padding-top: 1rem !important; + } + + .pt-xxl-4 { + padding-top: 1.5rem !important; + } + + .pt-xxl-5 { + padding-top: 3rem !important; + } + + .pe-xxl-0 { + padding-right: 0 !important; + } + + .pe-xxl-1 { + padding-right: 0.25rem !important; + } + + .pe-xxl-2 { + padding-right: 0.5rem !important; + } + + .pe-xxl-3 { + padding-right: 1rem !important; + } + + .pe-xxl-4 { + padding-right: 1.5rem !important; + } + + .pe-xxl-5 { + padding-right: 3rem !important; + } + + .pb-xxl-0 { + padding-bottom: 0 !important; + } + + .pb-xxl-1 { + padding-bottom: 0.25rem !important; + } + + .pb-xxl-2 { + padding-bottom: 0.5rem !important; + } + + .pb-xxl-3 { + padding-bottom: 1rem !important; + } + + .pb-xxl-4 { + padding-bottom: 1.5rem !important; + } + + .pb-xxl-5 { + padding-bottom: 3rem !important; + } + + .ps-xxl-0 { + padding-left: 0 !important; + } + + .ps-xxl-1 { + padding-left: 0.25rem !important; + } + + .ps-xxl-2 { + padding-left: 0.5rem !important; + } + + .ps-xxl-3 { + padding-left: 1rem !important; + } + + .ps-xxl-4 { + padding-left: 1.5rem !important; + } + + .ps-xxl-5 { + padding-left: 3rem !important; + } + + .text-xxl-start { + text-align: left !important; + } + + .text-xxl-end { + text-align: right !important; + } + + .text-xxl-center { + text-align: center !important; + } +} + +@media (min-width: 1200px) { + .fs-1 { + font-size: 2.5rem !important; + } + + .fs-2 { + font-size: 2rem !important; + } + + .fs-3 { + font-size: 1.75rem !important; + } + + .fs-4 { + font-size: 1.5rem !important; + } +} + +@media print { + .d-print-inline { + display: inline !important; + } + + .d-print-inline-block { + display: inline-block !important; + } + + .d-print-block { + display: block !important; + } + + .d-print-grid { + display: grid !important; + } + + .d-print-table { + display: table !important; + } + + .d-print-table-row { + display: table-row !important; + } + + .d-print-table-cell { + display: table-cell !important; + } + + .d-print-flex { + display: flex !important; + } + + .d-print-inline-flex { + display: inline-flex !important; + } + + .d-print-none { + display: none !important; + } +} + +/*# sourceMappingURL=bootstrap.css.map */ diff --git a/src/assets/css/onap-styles.css b/src/assets/css/onap-styles.css new file mode 100644 index 0000000..272eded --- /dev/null +++ b/src/assets/css/onap-styles.css @@ -0,0 +1,10755 @@ + + +:root { + --blue: #07819b; + --indigo: #6610f2; + --purple: #6f42c1; + --pink: #e83e8c; + --red: #dc3545; + --orange: #fd7e14; + --yellow: #ffc107; + --green: #28a745; + --teal: #20c997; + --cyan: #17a2b8; + --white: #fff; + --gray: #313032; + --gray-dark: #343a40; + --primary: #07819b; + --secondary: #313032; + --success: #28a745; + --info: #17a2b8; + --warning: #ffc107; + --danger: #dc3545; + --light: #f8f9fa; + --dark: #343a40; + --breakpoint-xs: 0; + --breakpoint-sm: 576px; + --breakpoint-md: 768px; + --breakpoint-lg: 992px; + --breakpoint-xl: 1200px; + --font-family-sans-serif: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', + sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + --font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace; +} + +*, +*::before, +*::after { + box-sizing: border-box; +} + +html { + font-family: sans-serif; + line-height: 1.15; + -webkit-text-size-adjust: 100%; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} + +article, +aside, +figcaption, +figure, +footer, +header, +hgroup, +main, +nav, +section { + display: block; +} + +body { + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, + 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: #212529; + text-align: left; + background-color: #fff; +} + +[tabindex='-1']:focus:not(:focus-visible) { + outline: 0 !important; +} + +hr { + box-sizing: content-box; + height: 0; + overflow: visible; +} + +h1, +h2, +h3, +h4, +h5, +h6 { + margin-top: 0; + margin-bottom: 0.5rem; +} + +p { + margin-top: 0; + margin-bottom: 1rem; +} + +abbr[title], +abbr[data-original-title] { + text-decoration: underline; + text-decoration: underline dotted; + cursor: help; + border-bottom: 0; + text-decoration-skip-ink: none; +} + +address { + margin-bottom: 1rem; + font-style: normal; + line-height: inherit; +} + +ol, +ul, +dl { + margin-top: 0; + margin-bottom: 1rem; +} + +ol ol, +ul ul, +ol ul, +ul ol { + margin-bottom: 0; +} + +dt { + font-weight: 700; +} + +dd { + margin-bottom: 0.5rem; + margin-left: 0; +} + +blockquote { + margin: 0 0 1rem; +} + +b, +strong { + font-weight: bolder; +} + +small { + font-size: 80%; +} + +sub, +sup { + position: relative; + font-size: 75%; + line-height: 0; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +a { + color: #07819b; + text-decoration: none; + background-color: transparent; +} + +a:hover { + color: #044452; + text-decoration: underline; +} + +a:not([href]) { + color: inherit; + text-decoration: none; +} + +a:not([href]):hover { + color: inherit; + text-decoration: none; +} + +pre, +code, +kbd, +samp { + font-family: SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace; + font-size: 1em; +} + +pre { + margin-top: 0; + margin-bottom: 1rem; + overflow: auto; + -ms-overflow-style: scrollbar; +} + +figure { + margin: 0 0 1rem; +} + +img { + vertical-align: middle; + border-style: none; +} + +svg { + overflow: hidden; + vertical-align: middle; +} + +table { + border-collapse: collapse; +} + +caption { + padding-top: 0.75rem; + padding-bottom: 0.75rem; + color: #313032; + text-align: left; + caption-side: bottom; +} + +th { + text-align: inherit; +} + +label { + display: inline-block; + margin-bottom: 0.5rem; +} + +button { + border-radius: 0; +} + +button:focus { + outline: 1px dotted; + outline: 5px auto -webkit-focus-ring-color; +} + +input, +button, +select, +optgroup, +textarea { + margin: 0; + font-family: inherit; + font-size: inherit; + line-height: inherit; +} + +button, +input { + overflow: visible; +} + +button, +select { + text-transform: none; +} + +[role='button'] { + cursor: pointer; +} + +select { + word-wrap: normal; +} + +button, +[type='button'], +[type='reset'], +[type='submit'] { + -webkit-appearance: button; +} + +button:not(:disabled), +[type='button']:not(:disabled), +[type='reset']:not(:disabled), +[type='submit']:not(:disabled) { + cursor: pointer; +} + +button::-moz-focus-inner, +[type='button']::-moz-focus-inner, +[type='reset']::-moz-focus-inner, +[type='submit']::-moz-focus-inner { + padding: 0; + border-style: none; +} + +input[type='radio'], +input[type='checkbox'] { + box-sizing: border-box; + padding: 0; +} + +textarea { + overflow: auto; + resize: vertical; +} + +fieldset { + min-width: 0; + padding: 0; + margin: 0; + border: 0; +} + +legend { + display: block; + width: 100%; + max-width: 100%; + padding: 0; + margin-bottom: 0.5rem; + font-size: 1.5rem; + line-height: inherit; + color: inherit; + white-space: normal; +} + +progress { + vertical-align: baseline; +} + +[type='number']::-webkit-inner-spin-button, +[type='number']::-webkit-outer-spin-button { + height: auto; +} + +[type='search'] { + outline-offset: -2px; + -webkit-appearance: none; +} + +[type='search']::-webkit-search-decoration { + -webkit-appearance: none; +} + +::-webkit-file-upload-button { + font: inherit; + -webkit-appearance: button; +} + +output { + display: inline-block; +} + +summary { + display: list-item; + cursor: pointer; +} + +template { + display: none; +} + +[hidden] { + display: none !important; +} + +h1, +h2, +h3, +h4, +h5, +h6, +.h1, +.h2, +.h3, +.h4, +.h5, +.h6 { + margin-bottom: 0.5rem; + font-weight: 500; + line-height: 1.2; +} + +h1, +.h1 { + font-size: 2.5rem; +} + +h2, +.h2 { + font-size: 2rem; +} + +h3, +.h3 { + font-size: 1.75rem; +} + +h4, +.h4 { + font-size: 1.5rem; +} + +h5, +.h5 { + font-size: 1.25rem; +} + +h6, +.h6 { + font-size: 1rem; +} + +.lead { + font-size: 1.25rem; + font-weight: 300; +} + +.display-1 { + font-size: 6rem; + font-weight: 300; + line-height: 1.2; +} + +.display-2 { + font-size: 5.5rem; + font-weight: 300; + line-height: 1.2; +} + +.display-3 { + font-size: 4.5rem; + font-weight: 300; + line-height: 1.2; +} + +.display-4 { + font-size: 3.5rem; + font-weight: 300; + line-height: 1.2; +} + +hr { + margin-top: 1rem; + margin-bottom: 1rem; + border: 0; + border-top: 1px solid rgba(0, 0, 0, 0.1); +} + +small, +.small { + font-size: 80%; + font-weight: 400; +} + +mark, +.mark { + padding: 0.2em; + background-color: #fcf8e3; +} + +.list-unstyled { + padding-left: 0; + list-style: none; +} + +.list-inline { + padding-left: 0; + list-style: none; +} + +.list-inline-item { + display: inline-block; +} + +.list-inline-item:not(:last-child) { + margin-right: 0.5rem; +} + +.initialism { + font-size: 90%; + text-transform: uppercase; +} + +.blockquote { + margin-bottom: 1rem; + font-size: 1.25rem; +} + +.blockquote-footer { + display: block; + font-size: 80%; + color: #313032; +} + +.blockquote-footer::before { + content: '\2014\00A0'; +} + +.img-fluid { + max-width: 100%; + height: auto; +} + +.img-thumbnail { + padding: 0.25rem; + background-color: #fff; + border: 1px solid #dee2e6; + border-radius: 0.25rem; + max-width: 100%; + height: auto; +} + +.figure { + display: inline-block; +} + +.figure-img { + margin-bottom: 0.5rem; + line-height: 1; +} + +.figure-caption { + font-size: 90%; + color: #313032; +} + +code { + font-size: 87.5%; + color: #e83e8c; + word-wrap: break-word; +} + +a > code { + color: inherit; +} + +kbd { + padding: 0.2rem 0.4rem; + font-size: 87.5%; + color: #fff; + background-color: #212529; + border-radius: 0.2rem; +} + +kbd kbd { + padding: 0; + font-size: 100%; + font-weight: 700; +} + +pre { + display: block; + font-size: 87.5%; + color: #212529; +} + +pre code { + font-size: inherit; + color: inherit; + word-break: normal; +} + +.pre-scrollable { + max-height: 340px; + overflow-y: scroll; +} + +.container { + width: 100%; + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; +} + +@media (min-width: 576px) { + .container { + max-width: 540px; + } +} + +@media (min-width: 768px) { + .container { + max-width: 720px; + } +} + +@media (min-width: 992px) { + .container { + max-width: 960px; + } +} + +@media (min-width: 1200px) { + .container { + max-width: 1140px; + } +} + +.container-fluid, +.container-sm, +.container-md, +.container-lg, +.container-xl { + width: 100%; + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; +} + +@media (min-width: 576px) { + .container, + .container-sm { + max-width: 540px; + } +} + +@media (min-width: 768px) { + .container, + .container-sm, + .container-md { + max-width: 720px; + } +} + +@media (min-width: 992px) { + .container, + .container-sm, + .container-md, + .container-lg { + max-width: 960px; + } +} + +@media (min-width: 1200px) { + .container, + .container-sm, + .container-md, + .container-lg, + .container-xl { + max-width: 1140px; + } +} + +.row { + display: flex; + flex-wrap: wrap; + margin-right: -15px; + margin-left: -15px; +} + +.no-gutters { + margin-right: 0; + margin-left: 0; +} + +.no-gutters > .col, +.no-gutters > [class*='col-'] { + padding-right: 0; + padding-left: 0; +} + +.col-1, +.col-2, +.col-3, +.col-4, +.col-5, +.col-6, +.col-7, +.col-8, +.col-9, +.col-10, +.col-11, +.col-12, +.col, +.col-auto, +.col-sm-1, +.col-sm-2, +.col-sm-3, +.col-sm-4, +.col-sm-5, +.col-sm-6, +.col-sm-7, +.col-sm-8, +.col-sm-9, +.col-sm-10, +.col-sm-11, +.col-sm-12, +.col-sm, +.col-sm-auto, +.col-md-1, +.col-md-2, +.col-md-3, +.col-md-4, +.col-md-5, +.col-md-6, +.col-md-7, +.col-md-8, +.col-md-9, +.col-md-10, +.col-md-11, +.col-md-12, +.col-md, +.col-md-auto, +.col-lg-1, +.col-lg-2, +.col-lg-3, +.col-lg-4, +.col-lg-5, +.col-lg-6, +.col-lg-7, +.col-lg-8, +.col-lg-9, +.col-lg-10, +.col-lg-11, +.col-lg-12, +.col-lg, +.col-lg-auto, +.col-xl-1, +.col-xl-2, +.col-xl-3, +.col-xl-4, +.col-xl-5, +.col-xl-6, +.col-xl-7, +.col-xl-8, +.col-xl-9, +.col-xl-10, +.col-xl-11, +.col-xl-12, +.col-xl, +.col-xl-auto { + position: relative; + width: 100%; + padding-right: 15px; + padding-left: 15px; +} + +.col { + flex-basis: 0; + flex-grow: 1; + min-width: 0; + max-width: 100%; +} + +.row-cols-1 > * { + flex: 0 0 100%; + max-width: 100%; +} + +.row-cols-2 > * { + flex: 0 0 50%; + max-width: 50%; +} + +.row-cols-3 > * { + flex: 0 0 33.33333%; + max-width: 33.33333%; +} + +.row-cols-4 > * { + flex: 0 0 25%; + max-width: 25%; +} + +.row-cols-5 > * { + flex: 0 0 20%; + max-width: 20%; +} + +.row-cols-6 > * { + flex: 0 0 16.66667%; + max-width: 16.66667%; +} + +.col-auto { + flex: 0 0 auto; + width: auto; + max-width: 100%; +} + +.col-1 { + flex: 0 0 8.33333%; + max-width: 8.33333%; +} + +.col-2 { + flex: 0 0 16.66667%; + max-width: 16.66667%; +} + +.col-3 { + flex: 0 0 25%; + max-width: 25%; +} + +.col-4 { + flex: 0 0 33.33333%; + max-width: 33.33333%; +} + +.col-5 { + flex: 0 0 41.66667%; + max-width: 41.66667%; +} + +.col-6 { + flex: 0 0 50%; + max-width: 50%; +} + +.col-7 { + flex: 0 0 58.33333%; + max-width: 58.33333%; +} + +.col-8 { + flex: 0 0 66.66667%; + max-width: 66.66667%; +} + +.col-9 { + flex: 0 0 75%; + max-width: 75%; +} + +.col-10 { + flex: 0 0 83.33333%; + max-width: 83.33333%; +} + +.col-11 { + flex: 0 0 91.66667%; + max-width: 91.66667%; +} + +.col-12 { + flex: 0 0 100%; + max-width: 100%; +} + +.order-first { + order: -1; +} + +.order-last { + order: 13; +} + +.order-0 { + order: 0; +} + +.order-1 { + order: 1; +} + +.order-2 { + order: 2; +} + +.order-3 { + order: 3; +} + +.order-4 { + order: 4; +} + +.order-5 { + order: 5; +} + +.order-6 { + order: 6; +} + +.order-7 { + order: 7; +} + +.order-8 { + order: 8; +} + +.order-9 { + order: 9; +} + +.order-10 { + order: 10; +} + +.order-11 { + order: 11; +} + +.order-12 { + order: 12; +} + +.offset-1 { + margin-left: 8.33333%; +} + +.offset-2 { + margin-left: 16.66667%; +} + +.offset-3 { + margin-left: 25%; +} + +.offset-4 { + margin-left: 33.33333%; +} + +.offset-5 { + margin-left: 41.66667%; +} + +.offset-6 { + margin-left: 50%; +} + +.offset-7 { + margin-left: 58.33333%; +} + +.offset-8 { + margin-left: 66.66667%; +} + +.offset-9 { + margin-left: 75%; +} + +.offset-10 { + margin-left: 83.33333%; +} + +.offset-11 { + margin-left: 91.66667%; +} + +@media (min-width: 576px) { + .col-sm { + flex-basis: 0; + flex-grow: 1; + min-width: 0; + max-width: 100%; + } + + .row-cols-sm-1 > * { + flex: 0 0 100%; + max-width: 100%; + } + + .row-cols-sm-2 > * { + flex: 0 0 50%; + max-width: 50%; + } + + .row-cols-sm-3 > * { + flex: 0 0 33.33333%; + max-width: 33.33333%; + } + + .row-cols-sm-4 > * { + flex: 0 0 25%; + max-width: 25%; + } + + .row-cols-sm-5 > * { + flex: 0 0 20%; + max-width: 20%; + } + + .row-cols-sm-6 > * { + flex: 0 0 16.66667%; + max-width: 16.66667%; + } + + .col-sm-auto { + flex: 0 0 auto; + width: auto; + max-width: 100%; + } + + .col-sm-1 { + flex: 0 0 8.33333%; + max-width: 8.33333%; + } + + .col-sm-2 { + flex: 0 0 16.66667%; + max-width: 16.66667%; + } + + .col-sm-3 { + flex: 0 0 25%; + max-width: 25%; + } + + .col-sm-4 { + flex: 0 0 33.33333%; + max-width: 33.33333%; + } + + .col-sm-5 { + flex: 0 0 41.66667%; + max-width: 41.66667%; + } + + .col-sm-6 { + flex: 0 0 50%; + max-width: 50%; + } + + .col-sm-7 { + flex: 0 0 58.33333%; + max-width: 58.33333%; + } + + .col-sm-8 { + flex: 0 0 66.66667%; + max-width: 66.66667%; + } + + .col-sm-9 { + flex: 0 0 75%; + max-width: 75%; + } + + .col-sm-10 { + flex: 0 0 83.33333%; + max-width: 83.33333%; + } + + .col-sm-11 { + flex: 0 0 91.66667%; + max-width: 91.66667%; + } + + .col-sm-12 { + flex: 0 0 100%; + max-width: 100%; + } + + .order-sm-first { + order: -1; + } + + .order-sm-last { + order: 13; + } + + .order-sm-0 { + order: 0; + } + + .order-sm-1 { + order: 1; + } + + .order-sm-2 { + order: 2; + } + + .order-sm-3 { + order: 3; + } + + .order-sm-4 { + order: 4; + } + + .order-sm-5 { + order: 5; + } + + .order-sm-6 { + order: 6; + } + + .order-sm-7 { + order: 7; + } + + .order-sm-8 { + order: 8; + } + + .order-sm-9 { + order: 9; + } + + .order-sm-10 { + order: 10; + } + + .order-sm-11 { + order: 11; + } + + .order-sm-12 { + order: 12; + } + + .offset-sm-0 { + margin-left: 0; + } + + .offset-sm-1 { + margin-left: 8.33333%; + } + + .offset-sm-2 { + margin-left: 16.66667%; + } + + .offset-sm-3 { + margin-left: 25%; + } + + .offset-sm-4 { + margin-left: 33.33333%; + } + + .offset-sm-5 { + margin-left: 41.66667%; + } + + .offset-sm-6 { + margin-left: 50%; + } + + .offset-sm-7 { + margin-left: 58.33333%; + } + + .offset-sm-8 { + margin-left: 66.66667%; + } + + .offset-sm-9 { + margin-left: 75%; + } + + .offset-sm-10 { + margin-left: 83.33333%; + } + + .offset-sm-11 { + margin-left: 91.66667%; + } +} + +@media (min-width: 768px) { + .col-md { + flex-basis: 0; + flex-grow: 1; + min-width: 0; + max-width: 100%; + } + + .row-cols-md-1 > * { + flex: 0 0 100%; + max-width: 100%; + } + + .row-cols-md-2 > * { + flex: 0 0 50%; + max-width: 50%; + } + + .row-cols-md-3 > * { + flex: 0 0 33.33333%; + max-width: 33.33333%; + } + + .row-cols-md-4 > * { + flex: 0 0 25%; + max-width: 25%; + } + + .row-cols-md-5 > * { + flex: 0 0 20%; + max-width: 20%; + } + + .row-cols-md-6 > * { + flex: 0 0 16.66667%; + max-width: 16.66667%; + } + + .col-md-auto { + flex: 0 0 auto; + width: auto; + max-width: 100%; + } + + .col-md-1 { + flex: 0 0 8.33333%; + max-width: 8.33333%; + } + + .col-md-2 { + flex: 0 0 16.66667%; + max-width: 16.66667%; + } + + .col-md-3 { + flex: 0 0 25%; + max-width: 25%; + } + + .col-md-4 { + flex: 0 0 33.33333%; + max-width: 33.33333%; + } + + .col-md-5 { + flex: 0 0 41.66667%; + max-width: 41.66667%; + } + + .col-md-6 { + flex: 0 0 50%; + max-width: 50%; + } + + .col-md-7 { + flex: 0 0 58.33333%; + max-width: 58.33333%; + } + + .col-md-8 { + flex: 0 0 66.66667%; + max-width: 66.66667%; + } + + .col-md-9 { + flex: 0 0 75%; + max-width: 75%; + } + + .col-md-10 { + flex: 0 0 83.33333%; + max-width: 83.33333%; + } + + .col-md-11 { + flex: 0 0 91.66667%; + max-width: 91.66667%; + } + + .col-md-12 { + flex: 0 0 100%; + max-width: 100%; + } + + .order-md-first { + order: -1; + } + + .order-md-last { + order: 13; + } + + .order-md-0 { + order: 0; + } + + .order-md-1 { + order: 1; + } + + .order-md-2 { + order: 2; + } + + .order-md-3 { + order: 3; + } + + .order-md-4 { + order: 4; + } + + .order-md-5 { + order: 5; + } + + .order-md-6 { + order: 6; + } + + .order-md-7 { + order: 7; + } + + .order-md-8 { + order: 8; + } + + .order-md-9 { + order: 9; + } + + .order-md-10 { + order: 10; + } + + .order-md-11 { + order: 11; + } + + .order-md-12 { + order: 12; + } + + .offset-md-0 { + margin-left: 0; + } + + .offset-md-1 { + margin-left: 8.33333%; + } + + .offset-md-2 { + margin-left: 16.66667%; + } + + .offset-md-3 { + margin-left: 25%; + } + + .offset-md-4 { + margin-left: 33.33333%; + } + + .offset-md-5 { + margin-left: 41.66667%; + } + + .offset-md-6 { + margin-left: 50%; + } + + .offset-md-7 { + margin-left: 58.33333%; + } + + .offset-md-8 { + margin-left: 66.66667%; + } + + .offset-md-9 { + margin-left: 75%; + } + + .offset-md-10 { + margin-left: 83.33333%; + } + + .offset-md-11 { + margin-left: 91.66667%; + } +} + +@media (min-width: 992px) { + .col-lg { + flex-basis: 0; + flex-grow: 1; + min-width: 0; + max-width: 100%; + } + + .row-cols-lg-1 > * { + flex: 0 0 100%; + max-width: 100%; + } + + .row-cols-lg-2 > * { + flex: 0 0 50%; + max-width: 50%; + } + + .row-cols-lg-3 > * { + flex: 0 0 33.33333%; + max-width: 33.33333%; + } + + .row-cols-lg-4 > * { + flex: 0 0 25%; + max-width: 25%; + } + + .row-cols-lg-5 > * { + flex: 0 0 20%; + max-width: 20%; + } + + .row-cols-lg-6 > * { + flex: 0 0 16.66667%; + max-width: 16.66667%; + } + + .col-lg-auto { + flex: 0 0 auto; + width: auto; + max-width: 100%; + } + + .col-lg-1 { + flex: 0 0 8.33333%; + max-width: 8.33333%; + } + + .col-lg-2 { + flex: 0 0 16.66667%; + max-width: 16.66667%; + } + + .col-lg-3 { + flex: 0 0 25%; + max-width: 25%; + } + + .col-lg-4 { + flex: 0 0 33.33333%; + max-width: 33.33333%; + } + + .col-lg-5 { + flex: 0 0 41.66667%; + max-width: 41.66667%; + } + + .col-lg-6 { + flex: 0 0 50%; + max-width: 50%; + } + + .col-lg-7 { + flex: 0 0 58.33333%; + max-width: 58.33333%; + } + + .col-lg-8 { + flex: 0 0 66.66667%; + max-width: 66.66667%; + } + + .col-lg-9 { + flex: 0 0 75%; + max-width: 75%; + } + + .col-lg-10 { + flex: 0 0 83.33333%; + max-width: 83.33333%; + } + + .col-lg-11 { + flex: 0 0 91.66667%; + max-width: 91.66667%; + } + + .col-lg-12 { + flex: 0 0 100%; + max-width: 100%; + } + + .order-lg-first { + order: -1; + } + + .order-lg-last { + order: 13; + } + + .order-lg-0 { + order: 0; + } + + .order-lg-1 { + order: 1; + } + + .order-lg-2 { + order: 2; + } + + .order-lg-3 { + order: 3; + } + + .order-lg-4 { + order: 4; + } + + .order-lg-5 { + order: 5; + } + + .order-lg-6 { + order: 6; + } + + .order-lg-7 { + order: 7; + } + + .order-lg-8 { + order: 8; + } + + .order-lg-9 { + order: 9; + } + + .order-lg-10 { + order: 10; + } + + .order-lg-11 { + order: 11; + } + + .order-lg-12 { + order: 12; + } + + .offset-lg-0 { + margin-left: 0; + } + + .offset-lg-1 { + margin-left: 8.33333%; + } + + .offset-lg-2 { + margin-left: 16.66667%; + } + + .offset-lg-3 { + margin-left: 25%; + } + + .offset-lg-4 { + margin-left: 33.33333%; + } + + .offset-lg-5 { + margin-left: 41.66667%; + } + + .offset-lg-6 { + margin-left: 50%; + } + + .offset-lg-7 { + margin-left: 58.33333%; + } + + .offset-lg-8 { + margin-left: 66.66667%; + } + + .offset-lg-9 { + margin-left: 75%; + } + + .offset-lg-10 { + margin-left: 83.33333%; + } + + .offset-lg-11 { + margin-left: 91.66667%; + } +} + +@media (min-width: 1200px) { + .col-xl { + flex-basis: 0; + flex-grow: 1; + min-width: 0; + max-width: 100%; + } + + .row-cols-xl-1 > * { + flex: 0 0 100%; + max-width: 100%; + } + + .row-cols-xl-2 > * { + flex: 0 0 50%; + max-width: 50%; + } + + .row-cols-xl-3 > * { + flex: 0 0 33.33333%; + max-width: 33.33333%; + } + + .row-cols-xl-4 > * { + flex: 0 0 25%; + max-width: 25%; + } + + .row-cols-xl-5 > * { + flex: 0 0 20%; + max-width: 20%; + } + + .row-cols-xl-6 > * { + flex: 0 0 16.66667%; + max-width: 16.66667%; + } + + .col-xl-auto { + flex: 0 0 auto; + width: auto; + max-width: 100%; + } + + .col-xl-1 { + flex: 0 0 8.33333%; + max-width: 8.33333%; + } + + .col-xl-2 { + flex: 0 0 16.66667%; + max-width: 16.66667%; + } + + .col-xl-3 { + flex: 0 0 25%; + max-width: 25%; + } + + .col-xl-4 { + flex: 0 0 33.33333%; + max-width: 33.33333%; + } + + .col-xl-5 { + flex: 0 0 41.66667%; + max-width: 41.66667%; + } + + .col-xl-6 { + flex: 0 0 50%; + max-width: 50%; + } + + .col-xl-7 { + flex: 0 0 58.33333%; + max-width: 58.33333%; + } + + .col-xl-8 { + flex: 0 0 66.66667%; + max-width: 66.66667%; + } + + .col-xl-9 { + flex: 0 0 75%; + max-width: 75%; + } + + .col-xl-10 { + flex: 0 0 83.33333%; + max-width: 83.33333%; + } + + .col-xl-11 { + flex: 0 0 91.66667%; + max-width: 91.66667%; + } + + .col-xl-12 { + flex: 0 0 100%; + max-width: 100%; + } + + .order-xl-first { + order: -1; + } + + .order-xl-last { + order: 13; + } + + .order-xl-0 { + order: 0; + } + + .order-xl-1 { + order: 1; + } + + .order-xl-2 { + order: 2; + } + + .order-xl-3 { + order: 3; + } + + .order-xl-4 { + order: 4; + } + + .order-xl-5 { + order: 5; + } + + .order-xl-6 { + order: 6; + } + + .order-xl-7 { + order: 7; + } + + .order-xl-8 { + order: 8; + } + + .order-xl-9 { + order: 9; + } + + .order-xl-10 { + order: 10; + } + + .order-xl-11 { + order: 11; + } + + .order-xl-12 { + order: 12; + } + + .offset-xl-0 { + margin-left: 0; + } + + .offset-xl-1 { + margin-left: 8.33333%; + } + + .offset-xl-2 { + margin-left: 16.66667%; + } + + .offset-xl-3 { + margin-left: 25%; + } + + .offset-xl-4 { + margin-left: 33.33333%; + } + + .offset-xl-5 { + margin-left: 41.66667%; + } + + .offset-xl-6 { + margin-left: 50%; + } + + .offset-xl-7 { + margin-left: 58.33333%; + } + + .offset-xl-8 { + margin-left: 66.66667%; + } + + .offset-xl-9 { + margin-left: 75%; + } + + .offset-xl-10 { + margin-left: 83.33333%; + } + + .offset-xl-11 { + margin-left: 91.66667%; + } +} + +.table { + width: 100%; + margin-bottom: 1rem; + color: #212529; +} + +.table th, +.table td { + padding: 0.75rem; + vertical-align: top; + border-top: 1px solid #dee2e6; +} + +.table thead th { + vertical-align: bottom; + border-bottom: 2px solid #dee2e6; +} + +.table tbody + tbody { + border-top: 2px solid #dee2e6; +} + +.table-sm th, +.table-sm td { + padding: 0.3rem; +} + +.table-bordered { + border: 1px solid #dee2e6; +} + +.table-bordered th, +.table-bordered td { + border: 1px solid #dee2e6; +} + +.table-bordered thead th, +.table-bordered thead td { + border-bottom-width: 2px; +} + +.table-borderless th, +.table-borderless td, +.table-borderless thead th, +.table-borderless tbody + tbody { + border: 0; +} + +.table-striped tbody tr:nth-of-type(odd) { + background-color: rgba(0, 0, 0, 0.05); +} + +.table-hover tbody tr:hover { + color: #212529; + background-color: rgba(0, 0, 0, 0.075); +} + +.table-primary, +.table-primary > th, +.table-primary > td { + background-color: #badce3; +} + +.table-primary th, +.table-primary td, +.table-primary thead th, +.table-primary tbody + tbody { + border-color: #7ebdcb; +} + +.table-hover .table-primary:hover { + background-color: #a8d3dc; +} + +.table-hover .table-primary:hover > td, +.table-hover .table-primary:hover > th { + background-color: #a8d3dc; +} + +.table-secondary, +.table-secondary > th, +.table-secondary > td { + background-color: #c5c5c6; +} + +.table-secondary th, +.table-secondary td, +.table-secondary thead th, +.table-secondary tbody + tbody { + border-color: #949394; +} + +.table-hover .table-secondary:hover { + background-color: #b8b8b9; +} + +.table-hover .table-secondary:hover > td, +.table-hover .table-secondary:hover > th { + background-color: #b8b8b9; +} + +.table-success, +.table-success > th, +.table-success > td { + background-color: #c3e6cb; +} + +.table-success th, +.table-success td, +.table-success thead th, +.table-success tbody + tbody { + border-color: #8fd19e; +} + +.table-hover .table-success:hover { + background-color: #b1dfbb; +} + +.table-hover .table-success:hover > td, +.table-hover .table-success:hover > th { + background-color: #b1dfbb; +} + +.table-info, +.table-info > th, +.table-info > td { + background-color: #bee5eb; +} + +.table-info th, +.table-info td, +.table-info thead th, +.table-info tbody + tbody { + border-color: #86cfda; +} + +.table-hover .table-info:hover { + background-color: #abdde5; +} + +.table-hover .table-info:hover > td, +.table-hover .table-info:hover > th { + background-color: #abdde5; +} + +.table-warning, +.table-warning > th, +.table-warning > td { + background-color: #ffeeba; +} + +.table-warning th, +.table-warning td, +.table-warning thead th, +.table-warning tbody + tbody { + border-color: #ffdf7e; +} + +.table-hover .table-warning:hover { + background-color: #ffe8a1; +} + +.table-hover .table-warning:hover > td, +.table-hover .table-warning:hover > th { + background-color: #ffe8a1; +} + +.table-danger, +.table-danger > th, +.table-danger > td { + background-color: #f5c6cb; +} + +.table-danger th, +.table-danger td, +.table-danger thead th, +.table-danger tbody + tbody { + border-color: #ed969e; +} + +.table-hover .table-danger:hover { + background-color: #f1b0b7; +} + +.table-hover .table-danger:hover > td, +.table-hover .table-danger:hover > th { + background-color: #f1b0b7; +} + +.table-light, +.table-light > th, +.table-light > td { + background-color: #fdfdfe; +} + +.table-light th, +.table-light td, +.table-light thead th, +.table-light tbody + tbody { + border-color: #fbfcfc; +} + +.table-hover .table-light:hover { + background-color: #ececf6; +} + +.table-hover .table-light:hover > td, +.table-hover .table-light:hover > th { + background-color: #ececf6; +} + +.table-dark, +.table-dark > th, +.table-dark > td { + background-color: #c6c8ca; +} + +.table-dark th, +.table-dark td, +.table-dark thead th, +.table-dark tbody + tbody { + border-color: #95999c; +} + +.table-hover .table-dark:hover { + background-color: #b9bbbe; +} + +.table-hover .table-dark:hover > td, +.table-hover .table-dark:hover > th { + background-color: #b9bbbe; +} + +.table-active, +.table-active > th, +.table-active > td { + background-color: rgba(0, 0, 0, 0.075); +} + +.table-hover .table-active:hover { + background-color: rgba(0, 0, 0, 0.075); +} + +.table-hover .table-active:hover > td, +.table-hover .table-active:hover > th { + background-color: rgba(0, 0, 0, 0.075); +} + +.table .thead-dark th { + color: #fff; + background-color: #343a40; + border-color: #454d55; +} + +.table .thead-light th { + color: #495057; + background-color: #e9ecef; + border-color: #dee2e6; +} + +.table-dark { + color: #fff; + background-color: #343a40; +} + +.table-dark th, +.table-dark td, +.table-dark thead th { + border-color: #454d55; +} + +.table-dark.table-bordered { + border: 0; +} + +.table-dark.table-striped tbody tr:nth-of-type(odd) { + background-color: rgba(255, 255, 255, 0.05); +} + +.table-dark.table-hover tbody tr:hover { + color: #fff; + background-color: rgba(255, 255, 255, 0.075); +} + +@media (max-width: 575.98px) { + .table-responsive-sm { + display: block; + width: 100%; + overflow-x: auto; + -webkit-overflow-scrolling: touch; + } + + .table-responsive-sm > .table-bordered { + border: 0; + } +} + +@media (max-width: 767.98px) { + .table-responsive-md { + display: block; + width: 100%; + overflow-x: auto; + -webkit-overflow-scrolling: touch; + } + + .table-responsive-md > .table-bordered { + border: 0; + } +} + +@media (max-width: 991.98px) { + .table-responsive-lg { + display: block; + width: 100%; + overflow-x: auto; + -webkit-overflow-scrolling: touch; + } + + .table-responsive-lg > .table-bordered { + border: 0; + } +} + +@media (max-width: 1199.98px) { + .table-responsive-xl { + display: block; + width: 100%; + overflow-x: auto; + -webkit-overflow-scrolling: touch; + } + + .table-responsive-xl > .table-bordered { + border: 0; + } +} + +.table-responsive { + display: block; + width: 100%; + overflow-x: auto; + -webkit-overflow-scrolling: touch; +} + +.table-responsive > .table-bordered { + border: 0; +} + +.form-control { + display: block; + width: 100%; + height: calc(1.5em + 0.75rem + 2px); + padding: 0.375rem 0.75rem; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: #495057; + background-color: #fff; + background-clip: padding-box; + border: 1px solid #ced4da; + border-radius: 0.25rem; + transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} + +.form-control::-ms-expand { + background-color: transparent; + border: 0; +} + +.form-control:-moz-focusring { + color: transparent; + text-shadow: 0 0 0 #495057; +} + +.form-control:focus { + color: #495057; + background-color: #fff; + border-color: #2cd2f5; + outline: 0; + box-shadow: 0 0 0 0.2rem rgba(7, 129, 155, 0.25); +} + +.form-control::placeholder { + color: #313032; + opacity: 1; +} + +.form-control:disabled, +.form-control[readonly] { + background-color: #e9ecef; + opacity: 1; +} + +input[type='date'].form-control, +input[type='time'].form-control, +input[type='datetime-local'].form-control, +input[type='month'].form-control { + appearance: none; +} + +select.form-control:focus::-ms-value { + color: #495057; + background-color: #fff; +} + +.form-control-file, +.form-control-range { + display: block; + width: 100%; +} + +.col-form-label { + padding-top: calc(0.375rem + 1px); + padding-bottom: calc(0.375rem + 1px); + margin-bottom: 0; + font-size: inherit; + line-height: 1.5; +} + +.col-form-label-lg { + padding-top: calc(0.5rem + 1px); + padding-bottom: calc(0.5rem + 1px); + font-size: 1.25rem; + line-height: 1.5; +} + +.col-form-label-sm { + padding-top: calc(0.25rem + 1px); + padding-bottom: calc(0.25rem + 1px); + font-size: 0.875rem; + line-height: 1.5; +} + +.form-control-plaintext { + display: block; + width: 100%; + padding: 0.375rem 0; + margin-bottom: 0; + font-size: 1rem; + line-height: 1.5; + color: #212529; + background-color: transparent; + border: solid transparent; + border-width: 1px 0; +} + +.form-control-plaintext.form-control-sm, +.form-control-plaintext.form-control-lg { + padding-right: 0; + padding-left: 0; +} + +.form-control-sm { + height: calc(1.5em + 0.5rem + 2px); + padding: 0.25rem 0.5rem; + font-size: 0.875rem; + line-height: 1.5; + border-radius: 0.2rem; +} + +.form-control-lg { + height: calc(1.5em + 1rem + 2px); + padding: 0.5rem 1rem; + font-size: 1.25rem; + line-height: 1.5; + border-radius: 0.3rem; +} + +select.form-control[size], +select.form-control[multiple] { + height: auto; +} + +textarea.form-control { + height: auto; +} + +.form-group { + margin-bottom: 1rem; +} + +.form-text { + display: block; + margin-top: 0.25rem; +} + +.form-row { + display: flex; + flex-wrap: wrap; + margin-right: -5px; + margin-left: -5px; +} + +.form-row > .col, +.form-row > [class*='col-'] { + padding-right: 5px; + padding-left: 5px; +} + +.form-check { + position: relative; + display: block; + padding-left: 1.25rem; +} + +.form-check-input { + position: absolute; + margin-top: 0.3rem; + margin-left: -1.25rem; +} + +.form-check-input[disabled] ~ .form-check-label, +.form-check-input:disabled ~ .form-check-label { + color: #313032; +} + +.form-check-label { + margin-bottom: 0; +} + +.form-check-inline { + display: inline-flex; + align-items: center; + padding-left: 0; + margin-right: 0.75rem; +} + +.form-check-inline .form-check-input { + position: static; + margin-top: 0; + margin-right: 0.3125rem; + margin-left: 0; +} + +.valid-feedback { + display: none; + width: 100%; + margin-top: 0.25rem; + font-size: 80%; + color: #28a745; +} + +.valid-tooltip { + position: absolute; + top: 100%; + z-index: 5; + display: none; + max-width: 100%; + padding: 0.25rem 0.5rem; + margin-top: 0.1rem; + font-size: 0.875rem; + line-height: 1.5; + color: #fff; + background-color: rgba(40, 167, 69, 0.9); + border-radius: 0.25rem; +} + +.was-validated :valid ~ .valid-feedback, +.was-validated :valid ~ .valid-tooltip, +.is-valid ~ .valid-feedback, +.is-valid ~ .valid-tooltip { + display: block; +} + +.was-validated .form-control:valid, +.form-control.is-valid { + border-color: #28a745; + padding-right: calc(1.5em + 0.75rem); + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e"); + background-repeat: no-repeat; + background-position: right calc(0.375em + 0.1875rem) center; + background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); +} + +.was-validated .form-control:valid:focus, +.form-control.is-valid:focus { + border-color: #28a745; + box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25); +} + +.was-validated textarea.form-control:valid, +textarea.form-control.is-valid { + padding-right: calc(1.5em + 0.75rem); + background-position: top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem); +} + +.was-validated .custom-select:valid, +.custom-select.is-valid { + border-color: #28a745; + padding-right: calc(0.75em + 2.3125rem); + background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right 0.75rem center/8px 10px, + url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e") #fff no-repeat center right 1.75rem / calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); +} + +.was-validated .custom-select:valid:focus, +.custom-select.is-valid:focus { + border-color: #28a745; + box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25); +} + +.was-validated .form-check-input:valid ~ .form-check-label, +.form-check-input.is-valid ~ .form-check-label { + color: #28a745; +} + +.was-validated .form-check-input:valid ~ .valid-feedback, +.was-validated .form-check-input:valid ~ .valid-tooltip, +.form-check-input.is-valid ~ .valid-feedback, +.form-check-input.is-valid ~ .valid-tooltip { + display: block; +} + +.was-validated .custom-control-input:valid ~ .custom-control-label, +.custom-control-input.is-valid ~ .custom-control-label { + color: #28a745; +} + +.was-validated .custom-control-input:valid ~ .custom-control-label::before, +.custom-control-input.is-valid ~ .custom-control-label::before { + border-color: #28a745; +} + +.was-validated .custom-control-input:valid:checked ~ .custom-control-label::before, +.custom-control-input.is-valid:checked ~ .custom-control-label::before { + border-color: #34ce57; + background-color: #34ce57; +} + +.was-validated .custom-control-input:valid:focus ~ .custom-control-label::before, +.custom-control-input.is-valid:focus ~ .custom-control-label::before { + box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25); +} + +.was-validated .custom-control-input:valid:focus:not(:checked) ~ .custom-control-label::before, +.custom-control-input.is-valid:focus:not(:checked) ~ .custom-control-label::before { + border-color: #28a745; +} + +.was-validated .custom-file-input:valid ~ .custom-file-label, +.custom-file-input.is-valid ~ .custom-file-label { + border-color: #28a745; +} + +.was-validated .custom-file-input:valid:focus ~ .custom-file-label, +.custom-file-input.is-valid:focus ~ .custom-file-label { + border-color: #28a745; + box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25); +} + +.invalid-feedback { + display: none; + width: 100%; + margin-top: 0.25rem; + font-size: 80%; + color: #dc3545; +} + +.invalid-tooltip { + position: absolute; + top: 100%; + z-index: 5; + display: none; + max-width: 100%; + padding: 0.25rem 0.5rem; + margin-top: 0.1rem; + font-size: 0.875rem; + line-height: 1.5; + color: #fff; + background-color: rgba(220, 53, 69, 0.9); + border-radius: 0.25rem; +} + +.was-validated :invalid ~ .invalid-feedback, +.was-validated :invalid ~ .invalid-tooltip, +.is-invalid ~ .invalid-feedback, +.is-invalid ~ .invalid-tooltip { + display: block; +} + +.was-validated .form-control:invalid, +.form-control.is-invalid { + border-color: #dc3545; + padding-right: calc(1.5em + 0.75rem); + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e"); + background-repeat: no-repeat; + background-position: right calc(0.375em + 0.1875rem) center; + background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); +} + +.was-validated .form-control:invalid:focus, +.form-control.is-invalid:focus { + border-color: #dc3545; + box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25); +} + +.was-validated textarea.form-control:invalid, +textarea.form-control.is-invalid { + padding-right: calc(1.5em + 0.75rem); + background-position: top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem); +} + +.was-validated .custom-select:invalid, +.custom-select.is-invalid { + border-color: #dc3545; + padding-right: calc(0.75em + 2.3125rem); + background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right 0.75rem center/8px 10px, + url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e") #fff no-repeat center right 1.75rem / calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); +} + +.was-validated .custom-select:invalid:focus, +.custom-select.is-invalid:focus { + border-color: #dc3545; + box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25); +} + +.was-validated .form-check-input:invalid ~ .form-check-label, +.form-check-input.is-invalid ~ .form-check-label { + color: #dc3545; +} + +.was-validated .form-check-input:invalid ~ .invalid-feedback, +.was-validated .form-check-input:invalid ~ .invalid-tooltip, +.form-check-input.is-invalid ~ .invalid-feedback, +.form-check-input.is-invalid ~ .invalid-tooltip { + display: block; +} + +.was-validated .custom-control-input:invalid ~ .custom-control-label, +.custom-control-input.is-invalid ~ .custom-control-label { + color: #dc3545; +} + +.was-validated .custom-control-input:invalid ~ .custom-control-label::before, +.custom-control-input.is-invalid ~ .custom-control-label::before { + border-color: #dc3545; +} + +.was-validated .custom-control-input:invalid:checked ~ .custom-control-label::before, +.custom-control-input.is-invalid:checked ~ .custom-control-label::before { + border-color: #e4606d; + background-color: #e4606d; +} + +.was-validated .custom-control-input:invalid:focus ~ .custom-control-label::before, +.custom-control-input.is-invalid:focus ~ .custom-control-label::before { + box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25); +} + +.was-validated .custom-control-input:invalid:focus:not(:checked) ~ .custom-control-label::before, +.custom-control-input.is-invalid:focus:not(:checked) ~ .custom-control-label::before { + border-color: #dc3545; +} + +.was-validated .custom-file-input:invalid ~ .custom-file-label, +.custom-file-input.is-invalid ~ .custom-file-label { + border-color: #dc3545; +} + +.was-validated .custom-file-input:invalid:focus ~ .custom-file-label, +.custom-file-input.is-invalid:focus ~ .custom-file-label { + border-color: #dc3545; + box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25); +} + +.form-inline { + display: flex; + flex-flow: row wrap; + align-items: center; +} + +.form-inline .form-check { + width: 100%; +} + +@media (min-width: 576px) { + .form-inline label { + display: flex; + align-items: center; + justify-content: center; + margin-bottom: 0; + } + + .form-inline .form-group { + display: flex; + flex: 0 0 auto; + flex-flow: row wrap; + align-items: center; + margin-bottom: 0; + } + + .form-inline .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + + .form-inline .form-control-plaintext { + display: inline-block; + } + + .form-inline .input-group, + .form-inline .custom-select { + width: auto; + } + + .form-inline .form-check { + display: flex; + align-items: center; + justify-content: center; + width: auto; + padding-left: 0; + } + + .form-inline .form-check-input { + position: relative; + flex-shrink: 0; + margin-top: 0; + margin-right: 0.25rem; + margin-left: 0; + } + + .form-inline .custom-control { + align-items: center; + justify-content: center; + } + + .form-inline .custom-control-label { + margin-bottom: 0; + } +} + +.btn { + display: inline-block; + font-weight: 400; + color: #212529; + text-align: center; + vertical-align: middle; + user-select: none; + background-color: transparent; + border: 1px solid transparent; + padding: 0.375rem 0.75rem; + font-size: 1rem; + line-height: 1.5; + border-radius: 0.25rem; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, + box-shadow 0.15s ease-in-out; +} + +.btn:hover { + color: #212529; + text-decoration: none; +} + +.btn:focus, +.btn.focus { + outline: 0; + box-shadow: 0 0 0 0.2rem rgba(7, 129, 155, 0.25); +} + +.btn.disabled, +.btn:disabled { + opacity: 0.65; +} + +.btn:not(:disabled):not(.disabled) { + cursor: pointer; +} + +a.btn.disabled, +fieldset:disabled a.btn { + pointer-events: none; +} + +.btn-primary { + color: #fff; + background-color: #07819b; + border-color: #07819b; +} + +.btn-primary:hover { + color: #fff; + background-color: #056376; + border-color: #05586a; +} + +.btn-primary:focus, +.btn-primary.focus { + color: #fff; + background-color: #056376; + border-color: #05586a; + box-shadow: 0 0 0 0.2rem rgba(44, 148, 170, 0.5); +} + +.btn-primary.disabled, +.btn-primary:disabled { + color: #fff; + background-color: #07819b; + border-color: #07819b; +} + +.btn-primary:not(:disabled):not(.disabled):active, +.btn-primary:not(:disabled):not(.disabled).active, +.show > .btn-primary.dropdown-toggle { + color: #fff; + background-color: #05586a; + border-color: #044e5e; +} + +.btn-primary:not(:disabled):not(.disabled):active:focus, +.btn-primary:not(:disabled):not(.disabled).active:focus, +.show > .btn-primary.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(44, 148, 170, 0.5); +} + +.btn-secondary { + color: #fff; + background-color: #313032; + border-color: #313032; +} + +.btn-secondary:hover { + color: #fff; + background-color: #1e1d1e; + border-color: #181718; +} + +.btn-secondary:focus, +.btn-secondary.focus { + color: #fff; + background-color: #1e1d1e; + border-color: #181718; + box-shadow: 0 0 0 0.2rem rgba(80, 79, 81, 0.5); +} + +.btn-secondary.disabled, +.btn-secondary:disabled { + color: #fff; + background-color: #313032; + border-color: #313032; +} + +.btn-secondary:not(:disabled):not(.disabled):active, +.btn-secondary:not(:disabled):not(.disabled).active, +.show > .btn-secondary.dropdown-toggle { + color: #fff; + background-color: #181718; + border-color: #111111; +} + +.btn-secondary:not(:disabled):not(.disabled):active:focus, +.btn-secondary:not(:disabled):not(.disabled).active:focus, +.show > .btn-secondary.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(80, 79, 81, 0.5); +} + +.btn-success { + color: #fff; + background-color: #28a745; + border-color: #28a745; +} + +.btn-success:hover { + color: #fff; + background-color: #218838; + border-color: #1e7e34; +} + +.btn-success:focus, +.btn-success.focus { + color: #fff; + background-color: #218838; + border-color: #1e7e34; + box-shadow: 0 0 0 0.2rem rgba(72, 180, 97, 0.5); +} + +.btn-success.disabled, +.btn-success:disabled { + color: #fff; + background-color: #28a745; + border-color: #28a745; +} + +.btn-success:not(:disabled):not(.disabled):active, +.btn-success:not(:disabled):not(.disabled).active, +.show > .btn-success.dropdown-toggle { + color: #fff; + background-color: #1e7e34; + border-color: #1c7430; +} + +.btn-success:not(:disabled):not(.disabled):active:focus, +.btn-success:not(:disabled):not(.disabled).active:focus, +.show > .btn-success.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(72, 180, 97, 0.5); +} + +.btn-info { + color: #fff; + background-color: #17a2b8; + border-color: #17a2b8; +} + +.btn-info:hover { + color: #fff; + background-color: #138496; + border-color: #117a8b; +} + +.btn-info:focus, +.btn-info.focus { + color: #fff; + background-color: #138496; + border-color: #117a8b; + box-shadow: 0 0 0 0.2rem rgba(58, 176, 195, 0.5); +} + +.btn-info.disabled, +.btn-info:disabled { + color: #fff; + background-color: #17a2b8; + border-color: #17a2b8; +} + +.btn-info:not(:disabled):not(.disabled):active, +.btn-info:not(:disabled):not(.disabled).active, +.show > .btn-info.dropdown-toggle { + color: #fff; + background-color: #117a8b; + border-color: #10707f; +} + +.btn-info:not(:disabled):not(.disabled):active:focus, +.btn-info:not(:disabled):not(.disabled).active:focus, +.show > .btn-info.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(58, 176, 195, 0.5); +} + +.btn-warning { + color: #212529; + background-color: #ffc107; + border-color: #ffc107; +} + +.btn-warning:hover { + color: #212529; + background-color: #e0a800; + border-color: #d39e00; +} + +.btn-warning:focus, +.btn-warning.focus { + color: #212529; + background-color: #e0a800; + border-color: #d39e00; + box-shadow: 0 0 0 0.2rem rgba(222, 170, 12, 0.5); +} + +.btn-warning.disabled, +.btn-warning:disabled { + color: #212529; + background-color: #ffc107; + border-color: #ffc107; +} + +.btn-warning:not(:disabled):not(.disabled):active, +.btn-warning:not(:disabled):not(.disabled).active, +.show > .btn-warning.dropdown-toggle { + color: #212529; + background-color: #d39e00; + border-color: #c69500; +} + +.btn-warning:not(:disabled):not(.disabled):active:focus, +.btn-warning:not(:disabled):not(.disabled).active:focus, +.show > .btn-warning.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(222, 170, 12, 0.5); +} + +.btn-danger { + color: #fff; + background-color: #dc3545; + border-color: #dc3545; +} + +.btn-danger:hover { + color: #fff; + background-color: #c82333; + border-color: #bd2130; +} + +.btn-danger:focus, +.btn-danger.focus { + color: #fff; + background-color: #c82333; + border-color: #bd2130; + box-shadow: 0 0 0 0.2rem rgba(225, 83, 97, 0.5); +} + +.btn-danger.disabled, +.btn-danger:disabled { + color: #fff; + background-color: #dc3545; + border-color: #dc3545; +} + +.btn-danger:not(:disabled):not(.disabled):active, +.btn-danger:not(:disabled):not(.disabled).active, +.show > .btn-danger.dropdown-toggle { + color: #fff; + background-color: #bd2130; + border-color: #b21f2d; +} + +.btn-danger:not(:disabled):not(.disabled):active:focus, +.btn-danger:not(:disabled):not(.disabled).active:focus, +.show > .btn-danger.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(225, 83, 97, 0.5); +} + +.btn-light { + color: #212529; + background-color: #f8f9fa; + border-color: #f8f9fa; +} + +.btn-light:hover { + color: #212529; + background-color: #e2e6ea; + border-color: #dae0e5; +} + +.btn-light:focus, +.btn-light.focus { + color: #212529; + background-color: #e2e6ea; + border-color: #dae0e5; + box-shadow: 0 0 0 0.2rem rgba(216, 217, 219, 0.5); +} + +.btn-light.disabled, +.btn-light:disabled { + color: #212529; + background-color: #f8f9fa; + border-color: #f8f9fa; +} + +.btn-light:not(:disabled):not(.disabled):active, +.btn-light:not(:disabled):not(.disabled).active, +.show > .btn-light.dropdown-toggle { + color: #212529; + background-color: #dae0e5; + border-color: #d3d9df; +} + +.btn-light:not(:disabled):not(.disabled):active:focus, +.btn-light:not(:disabled):not(.disabled).active:focus, +.show > .btn-light.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(216, 217, 219, 0.5); +} + +.btn-dark { + color: #fff; + background-color: #343a40; + border-color: #343a40; +} + +.btn-dark:hover { + color: #fff; + background-color: #23272b; + border-color: #1d2124; +} + +.btn-dark:focus, +.btn-dark.focus { + color: #fff; + background-color: #23272b; + border-color: #1d2124; + box-shadow: 0 0 0 0.2rem rgba(82, 88, 93, 0.5); +} + +.btn-dark.disabled, +.btn-dark:disabled { + color: #fff; + background-color: #343a40; + border-color: #343a40; +} + +.btn-dark:not(:disabled):not(.disabled):active, +.btn-dark:not(:disabled):not(.disabled).active, +.show > .btn-dark.dropdown-toggle { + color: #fff; + background-color: #1d2124; + border-color: #171a1d; +} + +.btn-dark:not(:disabled):not(.disabled):active:focus, +.btn-dark:not(:disabled):not(.disabled).active:focus, +.show > .btn-dark.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(82, 88, 93, 0.5); +} + +.btn-outline-primary { + color: #07819b; + border-color: #07819b; +} + +.btn-outline-primary:hover { + color: #fff; + background-color: #07819b; + border-color: #07819b; +} + +.btn-outline-primary:focus, +.btn-outline-primary.focus { + box-shadow: 0 0 0 0.2rem rgba(7, 129, 155, 0.5); +} + +.btn-outline-primary.disabled, +.btn-outline-primary:disabled { + color: #07819b; + background-color: transparent; +} + +.btn-outline-primary:not(:disabled):not(.disabled):active, +.btn-outline-primary:not(:disabled):not(.disabled).active, +.show > .btn-outline-primary.dropdown-toggle { + color: #fff; + background-color: #07819b; + border-color: #07819b; +} + +.btn-outline-primary:not(:disabled):not(.disabled):active:focus, +.btn-outline-primary:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-primary.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(7, 129, 155, 0.5); +} + +.btn-outline-secondary { + color: #313032; + border-color: #313032; +} + +.btn-outline-secondary:hover { + color: #fff; + background-color: #313032; + border-color: #313032; +} + +.btn-outline-secondary:focus, +.btn-outline-secondary.focus { + box-shadow: 0 0 0 0.2rem rgba(49, 48, 50, 0.5); +} + +.btn-outline-secondary.disabled, +.btn-outline-secondary:disabled { + color: #313032; + background-color: transparent; +} + +.btn-outline-secondary:not(:disabled):not(.disabled):active, +.btn-outline-secondary:not(:disabled):not(.disabled).active, +.show > .btn-outline-secondary.dropdown-toggle { + color: #fff; + background-color: #313032; + border-color: #313032; +} + +.btn-outline-secondary:not(:disabled):not(.disabled):active:focus, +.btn-outline-secondary:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-secondary.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(49, 48, 50, 0.5); +} + +.btn-outline-success { + color: #28a745; + border-color: #28a745; +} + +.btn-outline-success:hover { + color: #fff; + background-color: #28a745; + border-color: #28a745; +} + +.btn-outline-success:focus, +.btn-outline-success.focus { + box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); +} + +.btn-outline-success.disabled, +.btn-outline-success:disabled { + color: #28a745; + background-color: transparent; +} + +.btn-outline-success:not(:disabled):not(.disabled):active, +.btn-outline-success:not(:disabled):not(.disabled).active, +.show > .btn-outline-success.dropdown-toggle { + color: #fff; + background-color: #28a745; + border-color: #28a745; +} + +.btn-outline-success:not(:disabled):not(.disabled):active:focus, +.btn-outline-success:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-success.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); +} + +.btn-outline-info { + color: #17a2b8; + border-color: #17a2b8; +} + +.btn-outline-info:hover { + color: #fff; + background-color: #17a2b8; + border-color: #17a2b8; +} + +.btn-outline-info:focus, +.btn-outline-info.focus { + box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); +} + +.btn-outline-info.disabled, +.btn-outline-info:disabled { + color: #17a2b8; + background-color: transparent; +} + +.btn-outline-info:not(:disabled):not(.disabled):active, +.btn-outline-info:not(:disabled):not(.disabled).active, +.show > .btn-outline-info.dropdown-toggle { + color: #fff; + background-color: #17a2b8; + border-color: #17a2b8; +} + +.btn-outline-info:not(:disabled):not(.disabled):active:focus, +.btn-outline-info:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-info.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); +} + +.btn-outline-warning { + color: #ffc107; + border-color: #ffc107; +} + +.btn-outline-warning:hover { + color: #212529; + background-color: #ffc107; + border-color: #ffc107; +} + +.btn-outline-warning:focus, +.btn-outline-warning.focus { + box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); +} + +.btn-outline-warning.disabled, +.btn-outline-warning:disabled { + color: #ffc107; + background-color: transparent; +} + +.btn-outline-warning:not(:disabled):not(.disabled):active, +.btn-outline-warning:not(:disabled):not(.disabled).active, +.show > .btn-outline-warning.dropdown-toggle { + color: #212529; + background-color: #ffc107; + border-color: #ffc107; +} + +.btn-outline-warning:not(:disabled):not(.disabled):active:focus, +.btn-outline-warning:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-warning.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); +} + +.btn-outline-danger { + color: #dc3545; + border-color: #dc3545; +} + +.btn-outline-danger:hover { + color: #fff; + background-color: #dc3545; + border-color: #dc3545; +} + +.btn-outline-danger:focus, +.btn-outline-danger.focus { + box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); +} + +.btn-outline-danger.disabled, +.btn-outline-danger:disabled { + color: #dc3545; + background-color: transparent; +} + +.btn-outline-danger:not(:disabled):not(.disabled):active, +.btn-outline-danger:not(:disabled):not(.disabled).active, +.show > .btn-outline-danger.dropdown-toggle { + color: #fff; + background-color: #dc3545; + border-color: #dc3545; +} + +.btn-outline-danger:not(:disabled):not(.disabled):active:focus, +.btn-outline-danger:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-danger.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); +} + +.btn-outline-light { + color: #f8f9fa; + border-color: #f8f9fa; +} + +.btn-outline-light:hover { + color: #212529; + background-color: #f8f9fa; + border-color: #f8f9fa; +} + +.btn-outline-light:focus, +.btn-outline-light.focus { + box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); +} + +.btn-outline-light.disabled, +.btn-outline-light:disabled { + color: #f8f9fa; + background-color: transparent; +} + +.btn-outline-light:not(:disabled):not(.disabled):active, +.btn-outline-light:not(:disabled):not(.disabled).active, +.show > .btn-outline-light.dropdown-toggle { + color: #212529; + background-color: #f8f9fa; + border-color: #f8f9fa; +} + +.btn-outline-light:not(:disabled):not(.disabled):active:focus, +.btn-outline-light:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-light.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); +} + +.btn-outline-dark { + color: #343a40; + border-color: #343a40; +} + +.btn-outline-dark:hover { + color: #fff; + background-color: #343a40; + border-color: #343a40; +} + +.btn-outline-dark:focus, +.btn-outline-dark.focus { + box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); +} + +.btn-outline-dark.disabled, +.btn-outline-dark:disabled { + color: #343a40; + background-color: transparent; +} + +.btn-outline-dark:not(:disabled):not(.disabled):active, +.btn-outline-dark:not(:disabled):not(.disabled).active, +.show > .btn-outline-dark.dropdown-toggle { + color: #fff; + background-color: #343a40; + border-color: #343a40; +} + +.btn-outline-dark:not(:disabled):not(.disabled):active:focus, +.btn-outline-dark:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-dark.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); +} + +.btn-link { + font-weight: 400; + color: #07819b; + text-decoration: none; +} + +.btn-link:hover { + color: #044452; + text-decoration: underline; +} + +.btn-link:focus, +.btn-link.focus { + text-decoration: underline; +} + +.btn-link:disabled, +.btn-link.disabled { + color: #313032; + pointer-events: none; +} + +.btn-lg, +.btn-group-lg > .btn { + padding: 0.5rem 1rem; + font-size: 1.25rem; + line-height: 1.5; + border-radius: 0.3rem; +} + +.btn-sm, +.btn-group-sm > .btn { + padding: 0.25rem 0.5rem; + font-size: 0.875rem; + line-height: 1.5; + border-radius: 0.2rem; +} + +.btn-block { + display: block; + width: 100%; +} + +.btn-block + .btn-block { + margin-top: 0.5rem; +} + +input[type='submit'].btn-block, +input[type='reset'].btn-block, +input[type='button'].btn-block { + width: 100%; +} + +.fade { + transition: opacity 0.15s linear; +} + +.fade:not(.show) { + opacity: 0; +} + +.collapse:not(.show) { + display: none; +} + +.collapsing { + position: relative; + height: 0; + overflow: hidden; + transition: height 0.35s ease; +} + +.dropup, +.dropright, +.dropdown, +.dropleft { + position: relative; +} + +.dropdown-toggle { + white-space: nowrap; +} + +.dropdown-toggle::after { + display: inline-block; + margin-left: 0.255em; + vertical-align: 0.255em; + content: ''; + border-top: 0.3em solid; + border-right: 0.3em solid transparent; + border-bottom: 0; + border-left: 0.3em solid transparent; +} + +.dropdown-toggle:empty::after { + margin-left: 0; +} + +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 10rem; + padding: 0.5rem 0; + margin: 0.125rem 0 0; + font-size: 1rem; + color: #212529; + text-align: left; + list-style: none; + background-color: #fff; + background-clip: padding-box; + border: 1px solid rgba(0, 0, 0, 0.15); + border-radius: 0.25rem; +} + +.dropdown-menu-left { + right: auto; + left: 0; +} + +.dropdown-menu-right { + right: 0; + left: auto; +} + +@media (min-width: 576px) { + .dropdown-menu-sm-left { + right: auto; + left: 0; + } + + .dropdown-menu-sm-right { + right: 0; + left: auto; + } +} + +@media (min-width: 768px) { + .dropdown-menu-md-left { + right: auto; + left: 0; + } + + .dropdown-menu-md-right { + right: 0; + left: auto; + } +} + +@media (min-width: 992px) { + .dropdown-menu-lg-left { + right: auto; + left: 0; + } + + .dropdown-menu-lg-right { + right: 0; + left: auto; + } +} + +@media (min-width: 1200px) { + .dropdown-menu-xl-left { + right: auto; + left: 0; + } + + .dropdown-menu-xl-right { + right: 0; + left: auto; + } +} + +.dropup .dropdown-menu { + top: auto; + bottom: 100%; + margin-top: 0; + margin-bottom: 0.125rem; +} + +.dropup .dropdown-toggle::after { + display: inline-block; + margin-left: 0.255em; + vertical-align: 0.255em; + content: ''; + border-top: 0; + border-right: 0.3em solid transparent; + border-bottom: 0.3em solid; + border-left: 0.3em solid transparent; +} + +.dropup .dropdown-toggle:empty::after { + margin-left: 0; +} + +.dropright .dropdown-menu { + top: 0; + right: auto; + left: 100%; + margin-top: 0; + margin-left: 0.125rem; +} + +.dropright .dropdown-toggle::after { + display: inline-block; + margin-left: 0.255em; + vertical-align: 0.255em; + content: ''; + border-top: 0.3em solid transparent; + border-right: 0; + border-bottom: 0.3em solid transparent; + border-left: 0.3em solid; +} + +.dropright .dropdown-toggle:empty::after { + margin-left: 0; +} + +.dropright .dropdown-toggle::after { + vertical-align: 0; +} + +.dropleft .dropdown-menu { + top: 0; + right: 100%; + left: auto; + margin-top: 0; + margin-right: 0.125rem; +} + +.dropleft .dropdown-toggle::after { + display: inline-block; + margin-left: 0.255em; + vertical-align: 0.255em; + content: ''; +} + +.dropleft .dropdown-toggle::after { + display: none; +} + +.dropleft .dropdown-toggle::before { + display: inline-block; + margin-right: 0.255em; + vertical-align: 0.255em; + content: ''; + border-top: 0.3em solid transparent; + border-right: 0.3em solid; + border-bottom: 0.3em solid transparent; +} + +.dropleft .dropdown-toggle:empty::after { + margin-left: 0; +} + +.dropleft .dropdown-toggle::before { + vertical-align: 0; +} + +.dropdown-menu[x-placement^='top'], +.dropdown-menu[x-placement^='right'], +.dropdown-menu[x-placement^='bottom'], +.dropdown-menu[x-placement^='left'] { + right: auto; + bottom: auto; +} + +.dropdown-divider { + height: 0; + margin: 0.5rem 0; + overflow: hidden; + border-top: 1px solid #e9ecef; +} + +.dropdown-item { + display: block; + width: 100%; + padding: 0.25rem 1.5rem; + clear: both; + font-weight: 400; + color: #212529; + text-align: inherit; + white-space: nowrap; + background-color: transparent; + border: 0; +} + +.dropdown-item:hover, +.dropdown-item:focus { + color: #16181b; + text-decoration: none; + background-color: #f8f9fa; +} + +.dropdown-item.active, +.dropdown-item:active { + color: #fff; + text-decoration: none; + background-color: #07819b; +} + +.dropdown-item.disabled, +.dropdown-item:disabled { + color: #313032; + pointer-events: none; + background-color: transparent; +} + +.dropdown-menu.show { + display: block; +} + +.dropdown-header { + display: block; + padding: 0.5rem 1.5rem; + margin-bottom: 0; + font-size: 0.875rem; + color: #313032; + white-space: nowrap; +} + +.dropdown-item-text { + display: block; + padding: 0.25rem 1.5rem; + color: #212529; +} + +.btn-group, +.btn-group-vertical { + position: relative; + display: inline-flex; + vertical-align: middle; +} + +.btn-group > .btn, +.btn-group-vertical > .btn { + position: relative; + flex: 1 1 auto; +} + +.btn-group > .btn:hover, +.btn-group-vertical > .btn:hover { + z-index: 1; +} + +.btn-group > .btn:focus, +.btn-group > .btn:active, +.btn-group > .btn.active, +.btn-group-vertical > .btn:focus, +.btn-group-vertical > .btn:active, +.btn-group-vertical > .btn.active { + z-index: 1; +} + +.btn-toolbar { + display: flex; + flex-wrap: wrap; + justify-content: flex-start; +} + +.btn-toolbar .input-group { + width: auto; +} + +.btn-group > .btn:not(:first-child), +.btn-group > .btn-group:not(:first-child) { + margin-left: -1px; +} + +.btn-group > .btn:not(:last-child):not(.dropdown-toggle), +.btn-group > .btn-group:not(:last-child) > .btn { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.btn-group > .btn:not(:first-child), +.btn-group > .btn-group:not(:first-child) > .btn { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +.dropdown-toggle-split { + padding-right: 0.5625rem; + padding-left: 0.5625rem; +} + +.dropdown-toggle-split::after, +.dropup .dropdown-toggle-split::after, +.dropright .dropdown-toggle-split::after { + margin-left: 0; +} + +.dropleft .dropdown-toggle-split::before { + margin-right: 0; +} + +.btn-sm + .dropdown-toggle-split, +.btn-group-sm > .btn + .dropdown-toggle-split { + padding-right: 0.375rem; + padding-left: 0.375rem; +} + +.btn-lg + .dropdown-toggle-split, +.btn-group-lg > .btn + .dropdown-toggle-split { + padding-right: 0.75rem; + padding-left: 0.75rem; +} + +.btn-group-vertical { + flex-direction: column; + align-items: flex-start; + justify-content: center; +} + +.btn-group-vertical > .btn, +.btn-group-vertical > .btn-group { + width: 100%; +} + +.btn-group-vertical > .btn:not(:first-child), +.btn-group-vertical > .btn-group:not(:first-child) { + margin-top: -1px; +} + +.btn-group-vertical > .btn:not(:last-child):not(.dropdown-toggle), +.btn-group-vertical > .btn-group:not(:last-child) > .btn { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} + +.btn-group-vertical > .btn:not(:first-child), +.btn-group-vertical > .btn-group:not(:first-child) > .btn { + border-top-left-radius: 0; + border-top-right-radius: 0; +} + +.btn-group-toggle > .btn, +.btn-group-toggle > .btn-group > .btn { + margin-bottom: 0; +} + +.btn-group-toggle > .btn input[type='radio'], +.btn-group-toggle > .btn input[type='checkbox'], +.btn-group-toggle > .btn-group > .btn input[type='radio'], +.btn-group-toggle > .btn-group > .btn input[type='checkbox'] { + position: absolute; + clip: rect(0, 0, 0, 0); + pointer-events: none; +} + +.input-group { + position: relative; + display: flex; + flex-wrap: wrap; + align-items: stretch; + width: 100%; +} + +.input-group > .form-control, +.input-group > .form-control-plaintext, +.input-group > .custom-select, +.input-group > .custom-file { + position: relative; + flex: 1 1 auto; + width: 1%; + min-width: 0; + margin-bottom: 0; +} + +.input-group > .form-control + .form-control, +.input-group > .form-control + .custom-select, +.input-group > .form-control + .custom-file, +.input-group > .form-control-plaintext + .form-control, +.input-group > .form-control-plaintext + .custom-select, +.input-group > .form-control-plaintext + .custom-file, +.input-group > .custom-select + .form-control, +.input-group > .custom-select + .custom-select, +.input-group > .custom-select + .custom-file, +.input-group > .custom-file + .form-control, +.input-group > .custom-file + .custom-select, +.input-group > .custom-file + .custom-file { + margin-left: -1px; +} + +.input-group > .form-control:focus, +.input-group > .custom-select:focus, +.input-group > .custom-file .custom-file-input:focus ~ .custom-file-label { + z-index: 3; +} + +.input-group > .custom-file .custom-file-input:focus { + z-index: 4; +} + +.input-group > .form-control:not(:last-child), +.input-group > .custom-select:not(:last-child) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.input-group > .form-control:not(:first-child), +.input-group > .custom-select:not(:first-child) { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +.input-group > .custom-file { + display: flex; + align-items: center; +} + +.input-group > .custom-file:not(:last-child) .custom-file-label, +.input-group > .custom-file:not(:last-child) .custom-file-label::after { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.input-group > .custom-file:not(:first-child) .custom-file-label { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +.input-group-prepend, +.input-group-append { + display: flex; +} + +.input-group-prepend .btn, +.input-group-append .btn { + position: relative; + z-index: 2; +} + +.input-group-prepend .btn:focus, +.input-group-append .btn:focus { + z-index: 3; +} + +.input-group-prepend .btn + .btn, +.input-group-prepend .btn + .input-group-text, +.input-group-prepend .input-group-text + .input-group-text, +.input-group-prepend .input-group-text + .btn, +.input-group-append .btn + .btn, +.input-group-append .btn + .input-group-text, +.input-group-append .input-group-text + .input-group-text, +.input-group-append .input-group-text + .btn { + margin-left: -1px; +} + +.input-group-prepend { + margin-right: -1px; +} + +.input-group-append { + margin-left: -1px; +} + +.input-group-text { + display: flex; + align-items: center; + padding: 0.375rem 0.75rem; + margin-bottom: 0; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: #495057; + text-align: center; + white-space: nowrap; + background-color: #e9ecef; + border: 1px solid #ced4da; + border-radius: 0.25rem; +} + +.input-group-text input[type='radio'], +.input-group-text input[type='checkbox'] { + margin-top: 0; +} + +.input-group-lg > .form-control:not(textarea), +.input-group-lg > .custom-select { + height: calc(1.5em + 1rem + 2px); +} + +.input-group-lg > .form-control, +.input-group-lg > .custom-select, +.input-group-lg > .input-group-prepend > .input-group-text, +.input-group-lg > .input-group-append > .input-group-text, +.input-group-lg > .input-group-prepend > .btn, +.input-group-lg > .input-group-append > .btn { + padding: 0.5rem 1rem; + font-size: 1.25rem; + line-height: 1.5; + border-radius: 0.3rem; +} + +.input-group-sm > .form-control:not(textarea), +.input-group-sm > .custom-select { + height: calc(1.5em + 0.5rem + 2px); +} + +.input-group-sm > .form-control, +.input-group-sm > .custom-select, +.input-group-sm > .input-group-prepend > .input-group-text, +.input-group-sm > .input-group-append > .input-group-text, +.input-group-sm > .input-group-prepend > .btn, +.input-group-sm > .input-group-append > .btn { + padding: 0.25rem 0.5rem; + font-size: 0.875rem; + line-height: 1.5; + border-radius: 0.2rem; +} + +.input-group-lg > .custom-select, +.input-group-sm > .custom-select { + padding-right: 1.75rem; +} + +.input-group > .input-group-prepend > .btn, +.input-group > .input-group-prepend > .input-group-text, +.input-group > .input-group-append:not(:last-child) > .btn, +.input-group > .input-group-append:not(:last-child) > .input-group-text, +.input-group > .input-group-append:last-child > .btn:not(:last-child):not(.dropdown-toggle), +.input-group > .input-group-append:last-child > .input-group-text:not(:last-child) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.input-group > .input-group-append > .btn, +.input-group > .input-group-append > .input-group-text, +.input-group > .input-group-prepend:not(:first-child) > .btn, +.input-group > .input-group-prepend:not(:first-child) > .input-group-text, +.input-group > .input-group-prepend:first-child > .btn:not(:first-child), +.input-group > .input-group-prepend:first-child > .input-group-text:not(:first-child) { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +.custom-control { + position: relative; + display: block; + min-height: 1.5rem; + padding-left: 1.5rem; +} + +.custom-control-inline { + display: inline-flex; + margin-right: 1rem; +} + +.custom-control-input { + position: absolute; + left: 0; + z-index: -1; + width: 1rem; + height: 1.25rem; + opacity: 0; +} + +.custom-control-input:checked ~ .custom-control-label::before { + color: #fff; + border-color: #07819b; + background-color: #07819b; +} + +.custom-control-input:focus ~ .custom-control-label::before { + box-shadow: 0 0 0 0.2rem rgba(7, 129, 155, 0.25); +} + +.custom-control-input:focus:not(:checked) ~ .custom-control-label::before { + border-color: #2cd2f5; +} + +.custom-control-input:not(:disabled):active ~ .custom-control-label::before { + color: #fff; + background-color: #5ddcf8; + border-color: #5ddcf8; +} + +.custom-control-input[disabled] ~ .custom-control-label, +.custom-control-input:disabled ~ .custom-control-label { + color: #313032; +} + +.custom-control-input[disabled] ~ .custom-control-label::before, +.custom-control-input:disabled ~ .custom-control-label::before { + background-color: #e9ecef; +} + +.custom-control-label { + position: relative; + margin-bottom: 0; + vertical-align: top; +} + +.custom-control-label::before { + position: absolute; + top: 0.25rem; + left: -1.5rem; + display: block; + width: 1rem; + height: 1rem; + pointer-events: none; + content: ''; + background-color: #fff; + border: #adb5bd solid 1px; +} + +.custom-control-label::after { + position: absolute; + top: 0.25rem; + left: -1.5rem; + display: block; + width: 1rem; + height: 1rem; + content: ''; + background: no-repeat 50% / 50% 50%; +} + +.custom-checkbox .custom-control-label::before { + border-radius: 0.25rem; +} + +.custom-checkbox .custom-control-input:checked ~ .custom-control-label::after { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26l2.974 2.99L8 2.193z'/%3e%3c/svg%3e"); +} + +.custom-checkbox .custom-control-input:indeterminate ~ .custom-control-label::before { + border-color: #07819b; + background-color: #07819b; +} + +.custom-checkbox .custom-control-input:indeterminate ~ .custom-control-label::after { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='4' viewBox='0 0 4 4'%3e%3cpath stroke='%23fff' d='M0 2h4'/%3e%3c/svg%3e"); +} + +.custom-checkbox .custom-control-input:disabled:checked ~ .custom-control-label::before { + background-color: rgba(7, 129, 155, 0.5); +} + +.custom-checkbox .custom-control-input:disabled:indeterminate ~ .custom-control-label::before { + background-color: rgba(7, 129, 155, 0.5); +} + +.custom-radio .custom-control-label::before { + border-radius: 50%; +} + +.custom-radio .custom-control-input:checked ~ .custom-control-label::after { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e"); +} + +.custom-radio .custom-control-input:disabled:checked ~ .custom-control-label::before { + background-color: rgba(7, 129, 155, 0.5); +} + +.custom-switch { + padding-left: 2.25rem; +} + +.custom-switch .custom-control-label::before { + left: -2.25rem; + width: 1.75rem; + pointer-events: all; + border-radius: 0.5rem; +} + +.custom-switch .custom-control-label::after { + top: calc(0.25rem + 2px); + left: calc(-2.25rem + 2px); + width: calc(1rem - 4px); + height: calc(1rem - 4px); + background-color: #adb5bd; + border-radius: 0.5rem; + transition: transform 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, + box-shadow 0.15s ease-in-out; +} + +.custom-switch .custom-control-input:checked ~ .custom-control-label::after { + background-color: #fff; + transform: translateX(0.75rem); +} + +.custom-switch .custom-control-input:disabled:checked ~ .custom-control-label::before { + background-color: rgba(7, 129, 155, 0.5); +} + +.custom-select { + display: inline-block; + width: 100%; + height: calc(1.5em + 0.75rem + 2px); + padding: 0.375rem 1.75rem 0.375rem 0.75rem; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: #495057; + vertical-align: middle; + background: #fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right 0.75rem center/8px 10px; + border: 1px solid #ced4da; + border-radius: 0.25rem; + appearance: none; +} + +.custom-select:focus { + border-color: #2cd2f5; + outline: 0; + box-shadow: 0 0 0 0.2rem rgba(7, 129, 155, 0.25); +} + +.custom-select:focus::-ms-value { + color: #495057; + background-color: #fff; +} + +.custom-select[multiple], +.custom-select[size]:not([size='1']) { + height: auto; + padding-right: 0.75rem; + background-image: none; +} + +.custom-select:disabled { + color: #313032; + background-color: #e9ecef; +} + +.custom-select::-ms-expand { + display: none; +} + +.custom-select:-moz-focusring { + color: transparent; + text-shadow: 0 0 0 #495057; +} + +.custom-select-sm { + height: calc(1.5em + 0.5rem + 2px); + padding-top: 0.25rem; + padding-bottom: 0.25rem; + padding-left: 0.5rem; + font-size: 0.875rem; +} + +.custom-select-lg { + height: calc(1.5em + 1rem + 2px); + padding-top: 0.5rem; + padding-bottom: 0.5rem; + padding-left: 1rem; + font-size: 1.25rem; +} + +.custom-file { + position: relative; + display: inline-block; + width: 100%; + height: calc(1.5em + 0.75rem + 2px); + margin-bottom: 0; +} + +.custom-file-input { + position: relative; + z-index: 2; + width: 100%; + height: calc(1.5em + 0.75rem + 2px); + margin: 0; + opacity: 0; +} + +.custom-file-input:focus ~ .custom-file-label { + border-color: #2cd2f5; + box-shadow: 0 0 0 0.2rem rgba(7, 129, 155, 0.25); +} + +.custom-file-input[disabled] ~ .custom-file-label, +.custom-file-input:disabled ~ .custom-file-label { + background-color: #e9ecef; +} + +.custom-file-input:lang(en) ~ .custom-file-label::after { + content: 'Browse'; +} + +.custom-file-input ~ .custom-file-label[data-browse]::after { + content: attr(data-browse); +} + +.custom-file-label { + position: absolute; + top: 0; + right: 0; + left: 0; + z-index: 1; + height: calc(1.5em + 0.75rem + 2px); + padding: 0.375rem 0.75rem; + font-weight: 400; + line-height: 1.5; + color: #495057; + background-color: #fff; + border: 1px solid #ced4da; + border-radius: 0.25rem; +} + +.custom-file-label::after { + position: absolute; + top: 0; + right: 0; + bottom: 0; + z-index: 3; + display: block; + height: calc(1.5em + 0.75rem); + padding: 0.375rem 0.75rem; + line-height: 1.5; + color: #495057; + content: 'Browse'; + background-color: #e9ecef; + border-left: inherit; + border-radius: 0 0.25rem 0.25rem 0; +} + +.custom-range { + width: 100%; + height: 1.4rem; + padding: 0; + background-color: transparent; + appearance: none; +} + +.custom-range:focus { + outline: none; +} + +.custom-range:focus::-webkit-slider-thumb { + box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(7, 129, 155, 0.25); +} + +.custom-range:focus::-moz-range-thumb { + box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(7, 129, 155, 0.25); +} + +.custom-range:focus::-ms-thumb { + box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(7, 129, 155, 0.25); +} + +.custom-range::-moz-focus-outer { + border: 0; +} + +.custom-range::-webkit-slider-thumb { + width: 1rem; + height: 1rem; + margin-top: -0.25rem; + background-color: #07819b; + border: 0; + border-radius: 1rem; + transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + appearance: none; +} + +.custom-range::-webkit-slider-thumb:active { + background-color: #5ddcf8; +} + +.custom-range::-webkit-slider-runnable-track { + width: 100%; + height: 0.5rem; + color: transparent; + cursor: pointer; + background-color: #dee2e6; + border-color: transparent; + border-radius: 1rem; +} + +.custom-range::-moz-range-thumb { + width: 1rem; + height: 1rem; + background-color: #07819b; + border: 0; + border-radius: 1rem; + transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + appearance: none; +} + +.custom-range::-moz-range-thumb:active { + background-color: #5ddcf8; +} + +.custom-range::-moz-range-track { + width: 100%; + height: 0.5rem; + color: transparent; + cursor: pointer; + background-color: #dee2e6; + border-color: transparent; + border-radius: 1rem; +} + +.custom-range::-ms-thumb { + width: 1rem; + height: 1rem; + margin-top: 0; + margin-right: 0.2rem; + margin-left: 0.2rem; + background-color: #07819b; + border: 0; + border-radius: 1rem; + transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + appearance: none; +} + +.custom-range::-ms-thumb:active { + background-color: #5ddcf8; +} + +.custom-range::-ms-track { + width: 100%; + height: 0.5rem; + color: transparent; + cursor: pointer; + background-color: transparent; + border-color: transparent; + border-width: 0.5rem; +} + +.custom-range::-ms-fill-lower { + background-color: #dee2e6; + border-radius: 1rem; +} + +.custom-range::-ms-fill-upper { + margin-right: 15px; + background-color: #dee2e6; + border-radius: 1rem; +} + +.custom-range:disabled::-webkit-slider-thumb { + background-color: #adb5bd; +} + +.custom-range:disabled::-webkit-slider-runnable-track { + cursor: default; +} + +.custom-range:disabled::-moz-range-thumb { + background-color: #adb5bd; +} + +.custom-range:disabled::-moz-range-track { + cursor: default; +} + +.custom-range:disabled::-ms-thumb { + background-color: #adb5bd; +} + +.custom-control-label::before, +.custom-file-label, +.custom-select { + transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} + +.nav { + display: flex; + flex-wrap: wrap; + padding-left: 0; + margin-bottom: 0; + list-style: none; +} + +.nav-link { + display: block; + padding: 0.5rem 1rem; +} + +.nav-link:hover, +.nav-link:focus { + text-decoration: none; +} + +.nav-link.disabled { + color: #313032; + pointer-events: none; + cursor: default; +} + +.nav-tabs { + border-bottom: 1px solid #dee2e6; +} + +.nav-tabs .nav-item { + margin-bottom: -1px; +} + +.nav-tabs .nav-link { + border: 1px solid transparent; + border-top-left-radius: 0.25rem; + border-top-right-radius: 0.25rem; +} + +.nav-tabs .nav-link:hover, +.nav-tabs .nav-link:focus { + border-color: #e9ecef #e9ecef #dee2e6; +} + +.nav-tabs .nav-link.disabled { + color: #313032; + background-color: transparent; + border-color: transparent; +} + +.nav-tabs .nav-link.active, +.nav-tabs .nav-item.show .nav-link { + color: #495057; + background-color: #fff; + border-color: #dee2e6 #dee2e6 #fff; +} + +.nav-tabs .dropdown-menu { + margin-top: -1px; + border-top-left-radius: 0; + border-top-right-radius: 0; +} + +.nav-pills .nav-link { + border-radius: 0.25rem; +} + +.nav-pills .nav-link.active, +.nav-pills .show > .nav-link { + color: #fff; + background-color: #07819b; +} + +.nav-fill .nav-item { + flex: 1 1 auto; + text-align: center; +} + +.nav-justified .nav-item { + flex-basis: 0; + flex-grow: 1; + text-align: center; +} + +.tab-content > .tab-pane { + display: none; +} + +.tab-content > .active { + display: block; +} + +.navbar { + position: relative; + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: space-between; + padding: 0.5rem 1rem; +} + +.navbar .container, +.navbar .container-fluid, +.navbar .container-sm, +.navbar .container-md, +.navbar .container-lg, +.navbar .container-xl { + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: space-between; +} + +.navbar-brand { + display: inline-block; + padding-top: 0.3125rem; + padding-bottom: 0.3125rem; + margin-right: 1rem; + font-size: 1.25rem; + line-height: inherit; + white-space: nowrap; +} + +.navbar-brand:hover, +.navbar-brand:focus { + text-decoration: none; +} + +.navbar-nav { + display: flex; + flex-direction: column; + padding-left: 0; + margin-bottom: 0; + list-style: none; +} + +.navbar-nav .nav-link { + padding-right: 0; + padding-left: 0; +} + +.navbar-nav .dropdown-menu { + position: static; + float: none; +} + +.navbar-text { + display: inline-block; + padding-top: 0.5rem; + padding-bottom: 0.5rem; +} + +.navbar-collapse { + flex-basis: 100%; + flex-grow: 1; + align-items: center; +} + +.navbar-toggler { + padding: 0.25rem 0.75rem; + font-size: 1.25rem; + line-height: 1; + background-color: transparent; + border: 1px solid transparent; + border-radius: 0.25rem; +} + +.navbar-toggler:hover, +.navbar-toggler:focus { + text-decoration: none; +} + +.navbar-toggler-icon { + display: inline-block; + width: 1.5em; + height: 1.5em; + vertical-align: middle; + content: ''; + background: no-repeat center center; + background-size: 100% 100%; +} + +@media (max-width: 575.98px) { + .navbar-expand-sm > .container, + .navbar-expand-sm > .container-fluid, + .navbar-expand-sm > .container-sm, + .navbar-expand-sm > .container-md, + .navbar-expand-sm > .container-lg, + .navbar-expand-sm > .container-xl { + padding-right: 0; + padding-left: 0; + } +} + +@media (min-width: 576px) { + .navbar-expand-sm { + flex-flow: row nowrap; + justify-content: flex-start; + } + + .navbar-expand-sm .navbar-nav { + flex-direction: row; + } + + .navbar-expand-sm .navbar-nav .dropdown-menu { + position: absolute; + } + + .navbar-expand-sm .navbar-nav .nav-link { + padding-right: 0.5rem; + padding-left: 0.5rem; + } + + .navbar-expand-sm > .container, + .navbar-expand-sm > .container-fluid, + .navbar-expand-sm > .container-sm, + .navbar-expand-sm > .container-md, + .navbar-expand-sm > .container-lg, + .navbar-expand-sm > .container-xl { + flex-wrap: nowrap; + } + + .navbar-expand-sm .navbar-collapse { + display: flex !important; + flex-basis: auto; + } + + .navbar-expand-sm .navbar-toggler { + display: none; + } +} + +@media (max-width: 767.98px) { + .navbar-expand-md > .container, + .navbar-expand-md > .container-fluid, + .navbar-expand-md > .container-sm, + .navbar-expand-md > .container-md, + .navbar-expand-md > .container-lg, + .navbar-expand-md > .container-xl { + padding-right: 0; + padding-left: 0; + } +} + +@media (min-width: 768px) { + .navbar-expand-md { + flex-flow: row nowrap; + justify-content: flex-start; + } + + .navbar-expand-md .navbar-nav { + flex-direction: row; + } + + .navbar-expand-md .navbar-nav .dropdown-menu { + position: absolute; + } + + .navbar-expand-md .navbar-nav .nav-link { + padding-right: 0.5rem; + padding-left: 0.5rem; + } + + .navbar-expand-md > .container, + .navbar-expand-md > .container-fluid, + .navbar-expand-md > .container-sm, + .navbar-expand-md > .container-md, + .navbar-expand-md > .container-lg, + .navbar-expand-md > .container-xl { + flex-wrap: nowrap; + } + + .navbar-expand-md .navbar-collapse { + display: flex !important; + flex-basis: auto; + } + + .navbar-expand-md .navbar-toggler { + display: none; + } +} + +@media (max-width: 991.98px) { + .navbar-expand-lg > .container, + .navbar-expand-lg > .container-fluid, + .navbar-expand-lg > .container-sm, + .navbar-expand-lg > .container-md, + .navbar-expand-lg > .container-lg, + .navbar-expand-lg > .container-xl { + padding-right: 0; + padding-left: 0; + } +} + +@media (min-width: 992px) { + .navbar-expand-lg { + flex-flow: row nowrap; + justify-content: flex-start; + } + + .navbar-expand-lg .navbar-nav { + flex-direction: row; + } + + .navbar-expand-lg .navbar-nav .dropdown-menu { + position: absolute; + } + + .navbar-expand-lg .navbar-nav .nav-link { + padding-right: 0.5rem; + padding-left: 0.5rem; + } + + .navbar-expand-lg > .container, + .navbar-expand-lg > .container-fluid, + .navbar-expand-lg > .container-sm, + .navbar-expand-lg > .container-md, + .navbar-expand-lg > .container-lg, + .navbar-expand-lg > .container-xl { + flex-wrap: nowrap; + } + + .navbar-expand-lg .navbar-collapse { + display: flex !important; + flex-basis: auto; + } + + .navbar-expand-lg .navbar-toggler { + display: none; + } +} + +@media (max-width: 1199.98px) { + .navbar-expand-xl > .container, + .navbar-expand-xl > .container-fluid, + .navbar-expand-xl > .container-sm, + .navbar-expand-xl > .container-md, + .navbar-expand-xl > .container-lg, + .navbar-expand-xl > .container-xl { + padding-right: 0; + padding-left: 0; + } +} + +@media (min-width: 1200px) { + .navbar-expand-xl { + flex-flow: row nowrap; + justify-content: flex-start; + } + + .navbar-expand-xl .navbar-nav { + flex-direction: row; + } + + .navbar-expand-xl .navbar-nav .dropdown-menu { + position: absolute; + } + + .navbar-expand-xl .navbar-nav .nav-link { + padding-right: 0.5rem; + padding-left: 0.5rem; + } + + .navbar-expand-xl > .container, + .navbar-expand-xl > .container-fluid, + .navbar-expand-xl > .container-sm, + .navbar-expand-xl > .container-md, + .navbar-expand-xl > .container-lg, + .navbar-expand-xl > .container-xl { + flex-wrap: nowrap; + } + + .navbar-expand-xl .navbar-collapse { + display: flex !important; + flex-basis: auto; + } + + .navbar-expand-xl .navbar-toggler { + display: none; + } +} + +.navbar-expand { + flex-flow: row nowrap; + justify-content: flex-start; +} + +.navbar-expand > .container, +.navbar-expand > .container-fluid, +.navbar-expand > .container-sm, +.navbar-expand > .container-md, +.navbar-expand > .container-lg, +.navbar-expand > .container-xl { + padding-right: 0; + padding-left: 0; +} + +.navbar-expand .navbar-nav { + flex-direction: row; +} + +.navbar-expand .navbar-nav .dropdown-menu { + position: absolute; +} + +.navbar-expand .navbar-nav .nav-link { + padding-right: 0.5rem; + padding-left: 0.5rem; +} + +.navbar-expand > .container, +.navbar-expand > .container-fluid, +.navbar-expand > .container-sm, +.navbar-expand > .container-md, +.navbar-expand > .container-lg, +.navbar-expand > .container-xl { + flex-wrap: nowrap; +} + +.navbar-expand .navbar-collapse { + display: flex !important; + flex-basis: auto; +} + +.navbar-expand .navbar-toggler { + display: none; +} + +.navbar-light .navbar-brand { + color: rgba(0, 0, 0, 0.9); +} + +.navbar-light .navbar-brand:hover, +.navbar-light .navbar-brand:focus { + color: rgba(0, 0, 0, 0.9); +} + +.navbar-light .navbar-nav .nav-link { + color: rgba(0, 0, 0, 0.5); +} + +.navbar-light .navbar-nav .nav-link:hover, +.navbar-light .navbar-nav .nav-link:focus { + color: rgba(0, 0, 0, 0.7); +} + +.navbar-light .navbar-nav .nav-link.disabled { + color: rgba(0, 0, 0, 0.3); +} + +.navbar-light .navbar-nav .show > .nav-link, +.navbar-light .navbar-nav .active > .nav-link, +.navbar-light .navbar-nav .nav-link.show, +.navbar-light .navbar-nav .nav-link.active { + color: rgba(0, 0, 0, 0.9); +} + +.navbar-light .navbar-toggler { + color: rgba(0, 0, 0, 0.5); + border-color: rgba(0, 0, 0, 0.1); +} + +.navbar-light .navbar-toggler-icon { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%280, 0, 0, 0.5%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"); +} + +.navbar-light .navbar-text { + color: rgba(0, 0, 0, 0.5); +} + +.navbar-light .navbar-text a { + color: rgba(0, 0, 0, 0.9); +} + +.navbar-light .navbar-text a:hover, +.navbar-light .navbar-text a:focus { + color: rgba(0, 0, 0, 0.9); +} + +.navbar-dark .navbar-brand { + color: #fff; +} + +.navbar-dark .navbar-brand:hover, +.navbar-dark .navbar-brand:focus { + color: #fff; +} + +.navbar-dark .navbar-nav .nav-link { + color: rgba(255, 255, 255, 0.5); +} + +.navbar-dark .navbar-nav .nav-link:hover, +.navbar-dark .navbar-nav .nav-link:focus { + color: rgba(255, 255, 255, 0.75); +} + +.navbar-dark .navbar-nav .nav-link.disabled { + color: rgba(255, 255, 255, 0.25); +} + +.navbar-dark .navbar-nav .show > .nav-link, +.navbar-dark .navbar-nav .active > .nav-link, +.navbar-dark .navbar-nav .nav-link.show, +.navbar-dark .navbar-nav .nav-link.active { + color: #fff; +} + +.navbar-dark .navbar-toggler { + color: rgba(255, 255, 255, 0.5); + border-color: rgba(255, 255, 255, 0.1); +} + +.navbar-dark .navbar-toggler-icon { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.5%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"); +} + +.navbar-dark .navbar-text { + color: rgba(255, 255, 255, 0.5); +} + +.navbar-dark .navbar-text a { + color: #fff; +} + +.navbar-dark .navbar-text a:hover, +.navbar-dark .navbar-text a:focus { + color: #fff; +} + +.card { + position: relative; + display: flex; + flex-direction: column; + min-width: 0; + word-wrap: break-word; + background-color: #fff; + background-clip: border-box; + border: 1px solid rgba(0, 0, 0, 0.125); + border-radius: 0.25rem; +} + +.card > hr { + margin-right: 0; + margin-left: 0; +} + +.card > .list-group { + border-top: inherit; + border-bottom: inherit; +} + +.card > .list-group:first-child { + border-top-width: 0; + border-top-left-radius: calc(0.25rem - 1px); + border-top-right-radius: calc(0.25rem - 1px); +} + +.card > .list-group:last-child { + border-bottom-width: 0; + border-bottom-right-radius: calc(0.25rem - 1px); + border-bottom-left-radius: calc(0.25rem - 1px); +} + +.card-body { + flex: 1 1 auto; + min-height: 1px; + padding: 1.25rem; +} + +.card-title { + margin-bottom: 0.75rem; +} + +.card-subtitle { + margin-top: -0.375rem; + margin-bottom: 0; +} + +.card-text:last-child { + margin-bottom: 0; +} + +.card-link:hover { + text-decoration: none; +} + +.card-link + .card-link { + margin-left: 1.25rem; +} + +.card-header { + padding: 0.75rem 1.25rem; + margin-bottom: 0; + background-color: rgba(0, 0, 0, 0.03); + border-bottom: 1px solid rgba(0, 0, 0, 0.125); +} + +.card-header:first-child { + border-radius: calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0; +} + +.card-header + .list-group .list-group-item:first-child { + border-top: 0; +} + +.card-footer { + padding: 0.75rem 1.25rem; + background-color: rgba(0, 0, 0, 0.03); + border-top: 1px solid rgba(0, 0, 0, 0.125); +} + +.card-footer:last-child { + border-radius: 0 0 calc(0.25rem - 1px) calc(0.25rem - 1px); +} + +.card-header-tabs { + margin-right: -0.625rem; + margin-bottom: -0.75rem; + margin-left: -0.625rem; + border-bottom: 0; +} + +.card-header-pills { + margin-right: -0.625rem; + margin-left: -0.625rem; +} + +.card-img-overlay { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + padding: 1.25rem; +} + +.card-img, +.card-img-top, +.card-img-bottom { + flex-shrink: 0; + width: 100%; +} + +.card-img, +.card-img-top { + border-top-left-radius: calc(0.25rem - 1px); + border-top-right-radius: calc(0.25rem - 1px); +} + +.card-img, +.card-img-bottom { + border-bottom-right-radius: calc(0.25rem - 1px); + border-bottom-left-radius: calc(0.25rem - 1px); +} + +.card-deck .card { + margin-bottom: 15px; +} + +@media (min-width: 576px) { + .card-deck { + display: flex; + flex-flow: row wrap; + margin-right: -15px; + margin-left: -15px; + } + + .card-deck .card { + flex: 1 0 0%; + margin-right: 15px; + margin-bottom: 0; + margin-left: 15px; + } +} + +.card-group > .card { + margin-bottom: 15px; +} + +@media (min-width: 576px) { + .card-group { + display: flex; + flex-flow: row wrap; + } + + .card-group > .card { + flex: 1 0 0%; + margin-bottom: 0; + } + + .card-group > .card + .card { + margin-left: 0; + border-left: 0; + } + + .card-group > .card:not(:last-child) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + } + + .card-group > .card:not(:last-child) .card-img-top, + .card-group > .card:not(:last-child) .card-header { + border-top-right-radius: 0; + } + + .card-group > .card:not(:last-child) .card-img-bottom, + .card-group > .card:not(:last-child) .card-footer { + border-bottom-right-radius: 0; + } + + .card-group > .card:not(:first-child) { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + } + + .card-group > .card:not(:first-child) .card-img-top, + .card-group > .card:not(:first-child) .card-header { + border-top-left-radius: 0; + } + + .card-group > .card:not(:first-child) .card-img-bottom, + .card-group > .card:not(:first-child) .card-footer { + border-bottom-left-radius: 0; + } +} + +.card-columns .card { + margin-bottom: 0.75rem; +} + +@media (min-width: 576px) { + .card-columns { + column-count: 3; + column-gap: 1.25rem; + orphans: 1; + widows: 1; + } + + .card-columns .card { + display: inline-block; + width: 100%; + } +} + +.accordion > .card { + overflow: visible; +} + +.accordion > .card:not(:last-of-type) { + border-bottom: 0; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} + +.accordion > .card:not(:first-of-type) { + border-top-left-radius: 0; + border-top-right-radius: 0; +} + +.accordion > .card > .card-header { + border-radius: 0; + margin-bottom: -1px; +} + +.breadcrumb { + display: flex; + flex-wrap: wrap; + padding: 0.75rem 1rem; + margin-bottom: 1rem; + list-style: none; + background-color: #e9ecef; + border-radius: 0.25rem; +} + +.breadcrumb-item { + display: flex; +} + +.breadcrumb-item + .breadcrumb-item { + padding-left: 0.5rem; +} + +.breadcrumb-item + .breadcrumb-item::before { + display: inline-block; + padding-right: 0.5rem; + color: #313032; + content: '/'; +} + +.breadcrumb-item + .breadcrumb-item:hover::before { + text-decoration: underline; +} + +.breadcrumb-item + .breadcrumb-item:hover::before { + text-decoration: none; +} + +.breadcrumb-item.active { + color: #313032; +} + +.pagination { + display: flex; + padding-left: 0; + list-style: none; + border-radius: 0.25rem; +} + +.page-link { + position: relative; + display: block; + padding: 0.5rem 0.75rem; + margin-left: -1px; + line-height: 1.25; + color: #07819b; + background-color: #fff; + border: 1px solid #dee2e6; +} + +.page-link:hover { + z-index: 2; + color: #044452; + text-decoration: none; + background-color: #e9ecef; + border-color: #dee2e6; +} + +.page-link:focus { + z-index: 3; + outline: 0; + box-shadow: 0 0 0 0.2rem rgba(7, 129, 155, 0.25); +} + +.page-item:first-child .page-link { + margin-left: 0; + border-top-left-radius: 0.25rem; + border-bottom-left-radius: 0.25rem; +} + +.page-item:last-child .page-link { + border-top-right-radius: 0.25rem; + border-bottom-right-radius: 0.25rem; +} + +.page-item.active .page-link { + z-index: 3; + color: #fff; + background-color: #07819b; + border-color: #07819b; +} + +.page-item.disabled .page-link { + color: #313032; + pointer-events: none; + cursor: auto; + background-color: #fff; + border-color: #dee2e6; +} + +.pagination-lg .page-link { + padding: 0.75rem 1.5rem; + font-size: 1.25rem; + line-height: 1.5; +} + +.pagination-lg .page-item:first-child .page-link { + border-top-left-radius: 0.3rem; + border-bottom-left-radius: 0.3rem; +} + +.pagination-lg .page-item:last-child .page-link { + border-top-right-radius: 0.3rem; + border-bottom-right-radius: 0.3rem; +} + +.pagination-sm .page-link { + padding: 0.25rem 0.5rem; + font-size: 0.875rem; + line-height: 1.5; +} + +.pagination-sm .page-item:first-child .page-link { + border-top-left-radius: 0.2rem; + border-bottom-left-radius: 0.2rem; +} + +.pagination-sm .page-item:last-child .page-link { + border-top-right-radius: 0.2rem; + border-bottom-right-radius: 0.2rem; +} + +.badge { + display: inline-block; + padding: 0.25em 0.4em; + font-size: 75%; + font-weight: 700; + line-height: 1; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: 0.25rem; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, + box-shadow 0.15s ease-in-out; +} + +a.badge:hover, +a.badge:focus { + text-decoration: none; +} + +.badge:empty { + display: none; +} + +.btn .badge { + position: relative; + top: -1px; +} + +.badge-pill { + padding-right: 0.6em; + padding-left: 0.6em; + border-radius: 10rem; +} + +.badge-primary { + color: #fff; + background-color: #07819b; +} + +a.badge-primary:hover, +a.badge-primary:focus { + color: #fff; + background-color: #05586a; +} + +a.badge-primary:focus, +a.badge-primary.focus { + outline: 0; + box-shadow: 0 0 0 0.2rem rgba(7, 129, 155, 0.5); +} + +.badge-secondary { + color: #fff; + background-color: #313032; +} + +a.badge-secondary:hover, +a.badge-secondary:focus { + color: #fff; + background-color: #181718; +} + +a.badge-secondary:focus, +a.badge-secondary.focus { + outline: 0; + box-shadow: 0 0 0 0.2rem rgba(49, 48, 50, 0.5); +} + +.badge-success { + color: #fff; + background-color: #28a745; +} + +a.badge-success:hover, +a.badge-success:focus { + color: #fff; + background-color: #1e7e34; +} + +a.badge-success:focus, +a.badge-success.focus { + outline: 0; + box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); +} + +.badge-info { + color: #fff; + background-color: #17a2b8; +} + +a.badge-info:hover, +a.badge-info:focus { + color: #fff; + background-color: #117a8b; +} + +a.badge-info:focus, +a.badge-info.focus { + outline: 0; + box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); +} + +.badge-warning { + color: #212529; + background-color: #ffc107; +} + +a.badge-warning:hover, +a.badge-warning:focus { + color: #212529; + background-color: #d39e00; +} + +a.badge-warning:focus, +a.badge-warning.focus { + outline: 0; + box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); +} + +.badge-danger { + color: #fff; + background-color: #dc3545; +} + +a.badge-danger:hover, +a.badge-danger:focus { + color: #fff; + background-color: #bd2130; +} + +a.badge-danger:focus, +a.badge-danger.focus { + outline: 0; + box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); +} + +.badge-light { + color: #212529; + background-color: #f8f9fa; +} + +a.badge-light:hover, +a.badge-light:focus { + color: #212529; + background-color: #dae0e5; +} + +a.badge-light:focus, +a.badge-light.focus { + outline: 0; + box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); +} + +.badge-dark { + color: #fff; + background-color: #343a40; +} + +a.badge-dark:hover, +a.badge-dark:focus { + color: #fff; + background-color: #1d2124; +} + +a.badge-dark:focus, +a.badge-dark.focus { + outline: 0; + box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); +} + +.jumbotron { + padding: 2rem 1rem; + margin-bottom: 2rem; + background-color: #e9ecef; + border-radius: 0.3rem; +} + +@media (min-width: 576px) { + .jumbotron { + padding: 4rem 2rem; + } +} + +.jumbotron-fluid { + padding-right: 0; + padding-left: 0; + border-radius: 0; +} + +.alert { + position: relative; + padding: 0.75rem 1.25rem; + margin-bottom: 1rem; + border: 1px solid transparent; + border-radius: 0.25rem; +} + +.alert-heading { + color: inherit; +} + +.alert-link { + font-weight: 700; +} + +.alert-dismissible { + padding-right: 4rem; +} + +.alert-dismissible .close { + position: absolute; + top: 0; + right: 0; + padding: 0.75rem 1.25rem; + color: inherit; +} + +.alert-primary { + color: #044351; + background-color: #cde6eb; + border-color: #badce3; +} + +.alert-primary hr { + border-top-color: #a8d3dc; +} + +.alert-primary .alert-link { + color: #021b20; +} + +.alert-secondary { + color: #19191a; + background-color: #d6d6d6; + border-color: #c5c5c6; +} + +.alert-secondary hr { + border-top-color: #b8b8b9; +} + +.alert-secondary .alert-link { + color: black; +} + +.alert-success { + color: #155724; + background-color: #d4edda; + border-color: #c3e6cb; +} + +.alert-success hr { + border-top-color: #b1dfbb; +} + +.alert-success .alert-link { + color: #0b2e13; +} + +.alert-info { + color: #0c5460; + background-color: #d1ecf1; + border-color: #bee5eb; +} + +.alert-info hr { + border-top-color: #abdde5; +} + +.alert-info .alert-link { + color: #062c33; +} + +.alert-warning { + color: #856404; + background-color: #fff3cd; + border-color: #ffeeba; +} + +.alert-warning hr { + border-top-color: #ffe8a1; +} + +.alert-warning .alert-link { + color: #533f03; +} + +.alert-danger { + color: #721c24; + background-color: #f8d7da; + border-color: #f5c6cb; +} + +.alert-danger hr { + border-top-color: #f1b0b7; +} + +.alert-danger .alert-link { + color: #491217; +} + +.alert-light { + color: #818182; + background-color: #fefefe; + border-color: #fdfdfe; +} + +.alert-light hr { + border-top-color: #ececf6; +} + +.alert-light .alert-link { + color: #686868; +} + +.alert-dark { + color: #1b1e21; + background-color: #d6d8d9; + border-color: #c6c8ca; +} + +.alert-dark hr { + border-top-color: #b9bbbe; +} + +.alert-dark .alert-link { + color: #040505; +} + +@keyframes progress-bar-stripes { + from { + background-position: 1rem 0; + } + to { + background-position: 0 0; + } +} + +.progress { + display: flex; + height: 1rem; + overflow: hidden; + line-height: 0; + font-size: 0.75rem; + background-color: #e9ecef; + border-radius: 0.25rem; +} + +.progress-bar { + display: flex; + flex-direction: column; + justify-content: center; + overflow: hidden; + color: #fff; + text-align: center; + white-space: nowrap; + background-color: #07819b; + transition: width 0.6s ease; +} + +.progress-bar-striped { + background-image: linear-gradient( + 45deg, + rgba(255, 255, 255, 0.15) 25%, + transparent 25%, + transparent 50%, + rgba(255, 255, 255, 0.15) 50%, + rgba(255, 255, 255, 0.15) 75%, + transparent 75%, + transparent + ); + background-size: 1rem 1rem; +} + +.progress-bar-animated { + animation: progress-bar-stripes 1s linear infinite; +} + +.media { + display: flex; + align-items: flex-start; +} + +.media-body { + flex: 1; +} + +.list-group { + display: flex; + flex-direction: column; + padding-left: 0; + margin-bottom: 0; + border-radius: 0.25rem; +} + +.list-group-item-action { + width: 100%; + color: #495057; + text-align: inherit; +} + +.list-group-item-action:hover, +.list-group-item-action:focus { + z-index: 1; + color: #495057; + text-decoration: none; + background-color: #f8f9fa; +} + +.list-group-item-action:active { + color: #212529; + background-color: #e9ecef; +} + +.list-group-item { + position: relative; + display: block; + padding: 0.75rem 1.25rem; + background-color: #fff; + border: 1px solid rgba(0, 0, 0, 0.125); +} + +.list-group-item:first-child { + border-top-left-radius: inherit; + border-top-right-radius: inherit; +} + +.list-group-item:last-child { + border-bottom-right-radius: inherit; + border-bottom-left-radius: inherit; +} + +.list-group-item.disabled, +.list-group-item:disabled { + color: #313032; + pointer-events: none; + background-color: #fff; +} + +.list-group-item.active { + z-index: 2; + color: #fff; + background-color: #07819b; + border-color: #07819b; +} + +.list-group-item + .list-group-item { + border-top-width: 0; +} + +.list-group-item + .list-group-item.active { + margin-top: -1px; + border-top-width: 1px; +} + +.list-group-horizontal { + flex-direction: row; +} + +.list-group-horizontal > .list-group-item:first-child { + border-bottom-left-radius: 0.25rem; + border-top-right-radius: 0; +} + +.list-group-horizontal > .list-group-item:last-child { + border-top-right-radius: 0.25rem; + border-bottom-left-radius: 0; +} + +.list-group-horizontal > .list-group-item.active { + margin-top: 0; +} + +.list-group-horizontal > .list-group-item + .list-group-item { + border-top-width: 1px; + border-left-width: 0; +} + +.list-group-horizontal > .list-group-item + .list-group-item.active { + margin-left: -1px; + border-left-width: 1px; +} + +@media (min-width: 576px) { + .list-group-horizontal-sm { + flex-direction: row; + } + + .list-group-horizontal-sm > .list-group-item:first-child { + border-bottom-left-radius: 0.25rem; + border-top-right-radius: 0; + } + + .list-group-horizontal-sm > .list-group-item:last-child { + border-top-right-radius: 0.25rem; + border-bottom-left-radius: 0; + } + + .list-group-horizontal-sm > .list-group-item.active { + margin-top: 0; + } + + .list-group-horizontal-sm > .list-group-item + .list-group-item { + border-top-width: 1px; + border-left-width: 0; + } + + .list-group-horizontal-sm > .list-group-item + .list-group-item.active { + margin-left: -1px; + border-left-width: 1px; + } +} + +@media (min-width: 768px) { + .list-group-horizontal-md { + flex-direction: row; + } + + .list-group-horizontal-md > .list-group-item:first-child { + border-bottom-left-radius: 0.25rem; + border-top-right-radius: 0; + } + + .list-group-horizontal-md > .list-group-item:last-child { + border-top-right-radius: 0.25rem; + border-bottom-left-radius: 0; + } + + .list-group-horizontal-md > .list-group-item.active { + margin-top: 0; + } + + .list-group-horizontal-md > .list-group-item + .list-group-item { + border-top-width: 1px; + border-left-width: 0; + } + + .list-group-horizontal-md > .list-group-item + .list-group-item.active { + margin-left: -1px; + border-left-width: 1px; + } +} + +@media (min-width: 992px) { + .list-group-horizontal-lg { + flex-direction: row; + } + + .list-group-horizontal-lg > .list-group-item:first-child { + border-bottom-left-radius: 0.25rem; + border-top-right-radius: 0; + } + + .list-group-horizontal-lg > .list-group-item:last-child { + border-top-right-radius: 0.25rem; + border-bottom-left-radius: 0; + } + + .list-group-horizontal-lg > .list-group-item.active { + margin-top: 0; + } + + .list-group-horizontal-lg > .list-group-item + .list-group-item { + border-top-width: 1px; + border-left-width: 0; + } + + .list-group-horizontal-lg > .list-group-item + .list-group-item.active { + margin-left: -1px; + border-left-width: 1px; + } +} + +@media (min-width: 1200px) { + .list-group-horizontal-xl { + flex-direction: row; + } + + .list-group-horizontal-xl > .list-group-item:first-child { + border-bottom-left-radius: 0.25rem; + border-top-right-radius: 0; + } + + .list-group-horizontal-xl > .list-group-item:last-child { + border-top-right-radius: 0.25rem; + border-bottom-left-radius: 0; + } + + .list-group-horizontal-xl > .list-group-item.active { + margin-top: 0; + } + + .list-group-horizontal-xl > .list-group-item + .list-group-item { + border-top-width: 1px; + border-left-width: 0; + } + + .list-group-horizontal-xl > .list-group-item + .list-group-item.active { + margin-left: -1px; + border-left-width: 1px; + } +} + +.list-group-flush { + border-radius: 0; +} + +.list-group-flush > .list-group-item { + border-width: 0 0 1px; +} + +.list-group-flush > .list-group-item:last-child { + border-bottom-width: 0; +} + +.list-group-item-primary { + color: #044351; + background-color: #badce3; +} + +.list-group-item-primary.list-group-item-action:hover, +.list-group-item-primary.list-group-item-action:focus { + color: #044351; + background-color: #a8d3dc; +} + +.list-group-item-primary.list-group-item-action.active { + color: #fff; + background-color: #044351; + border-color: #044351; +} + +.list-group-item-secondary { + color: #19191a; + background-color: #c5c5c6; +} + +.list-group-item-secondary.list-group-item-action:hover, +.list-group-item-secondary.list-group-item-action:focus { + color: #19191a; + background-color: #b8b8b9; +} + +.list-group-item-secondary.list-group-item-action.active { + color: #fff; + background-color: #19191a; + border-color: #19191a; +} + +.list-group-item-success { + color: #155724; + background-color: #c3e6cb; +} + +.list-group-item-success.list-group-item-action:hover, +.list-group-item-success.list-group-item-action:focus { + color: #155724; + background-color: #b1dfbb; +} + +.list-group-item-success.list-group-item-action.active { + color: #fff; + background-color: #155724; + border-color: #155724; +} + +.list-group-item-info { + color: #0c5460; + background-color: #bee5eb; +} + +.list-group-item-info.list-group-item-action:hover, +.list-group-item-info.list-group-item-action:focus { + color: #0c5460; + background-color: #abdde5; +} + +.list-group-item-info.list-group-item-action.active { + color: #fff; + background-color: #0c5460; + border-color: #0c5460; +} + +.list-group-item-warning { + color: #856404; + background-color: #ffeeba; +} + +.list-group-item-warning.list-group-item-action:hover, +.list-group-item-warning.list-group-item-action:focus { + color: #856404; + background-color: #ffe8a1; +} + +.list-group-item-warning.list-group-item-action.active { + color: #fff; + background-color: #856404; + border-color: #856404; +} + +.list-group-item-danger { + color: #721c24; + background-color: #f5c6cb; +} + +.list-group-item-danger.list-group-item-action:hover, +.list-group-item-danger.list-group-item-action:focus { + color: #721c24; + background-color: #f1b0b7; +} + +.list-group-item-danger.list-group-item-action.active { + color: #fff; + background-color: #721c24; + border-color: #721c24; +} + +.list-group-item-light { + color: #818182; + background-color: #fdfdfe; +} + +.list-group-item-light.list-group-item-action:hover, +.list-group-item-light.list-group-item-action:focus { + color: #818182; + background-color: #ececf6; +} + +.list-group-item-light.list-group-item-action.active { + color: #fff; + background-color: #818182; + border-color: #818182; +} + +.list-group-item-dark { + color: #1b1e21; + background-color: #c6c8ca; +} + +.list-group-item-dark.list-group-item-action:hover, +.list-group-item-dark.list-group-item-action:focus { + color: #1b1e21; + background-color: #b9bbbe; +} + +.list-group-item-dark.list-group-item-action.active { + color: #fff; + background-color: #1b1e21; + border-color: #1b1e21; +} + +.close { + float: right; + font-size: 1.5rem; + font-weight: 700; + line-height: 1; + color: #000; + text-shadow: 0 1px 0 #fff; + opacity: 0.5; +} + +.close:hover { + color: #000; + text-decoration: none; +} + +.close:not(:disabled):not(.disabled):hover, +.close:not(:disabled):not(.disabled):focus { + opacity: 0.75; +} + +button.close { + padding: 0; + background-color: transparent; + border: 0; +} + +a.close.disabled { + pointer-events: none; +} + +.toast { + max-width: 350px; + overflow: hidden; + font-size: 0.875rem; + background-color: rgba(255, 255, 255, 0.85); + background-clip: padding-box; + border: 1px solid rgba(0, 0, 0, 0.1); + box-shadow: 0 0.25rem 0.75rem rgba(0, 0, 0, 0.1); + backdrop-filter: blur(10px); + opacity: 0; + border-radius: 0.25rem; +} + +.toast:not(:last-child) { + margin-bottom: 0.75rem; +} + +.toast.showing { + opacity: 1; +} + +.toast.show { + display: block; + opacity: 1; +} + +.toast.hide { + display: none; +} + +.toast-header { + display: flex; + align-items: center; + padding: 0.25rem 0.75rem; + color: #313032; + background-color: rgba(255, 255, 255, 0.85); + background-clip: padding-box; + border-bottom: 1px solid rgba(0, 0, 0, 0.05); +} + +.toast-body { + padding: 0.75rem; +} + +.modal-open { + overflow: hidden; +} + +.modal-open .modal { + overflow-x: hidden; + overflow-y: auto; +} + +.modal { + position: fixed; + top: 0; + left: 0; + z-index: 1050; + display: none; + width: 100%; + height: 100%; + overflow: hidden; + outline: 0; +} + +.modal-dialog { + position: relative; + width: auto; + margin: 0.5rem; + pointer-events: none; +} + +.modal.fade .modal-dialog { + transition: transform 0.3s ease-out; + transform: translate(0, -50px); +} + +.modal.show .modal-dialog { + transform: none; +} + +.modal.modal-static .modal-dialog { + transform: scale(1.02); +} + +.modal-dialog-scrollable { + display: flex; + max-height: calc(100% - 1rem); +} + +.modal-dialog-scrollable .modal-content { + max-height: calc(100vh - 1rem); + overflow: hidden; +} + +.modal-dialog-scrollable .modal-header, +.modal-dialog-scrollable .modal-footer { + flex-shrink: 0; +} + +.modal-dialog-scrollable .modal-body { + overflow-y: auto; +} + +.modal-dialog-centered { + display: flex; + align-items: center; + min-height: calc(100% - 1rem); +} + +.modal-dialog-centered::before { + display: block; + height: calc(100vh - 1rem); + height: min-content; + content: ''; +} + +.modal-dialog-centered.modal-dialog-scrollable { + flex-direction: column; + justify-content: center; + height: 100%; +} + +.modal-dialog-centered.modal-dialog-scrollable .modal-content { + max-height: none; +} + +.modal-dialog-centered.modal-dialog-scrollable::before { + content: none; +} + +.modal-content { + position: relative; + display: flex; + flex-direction: column; + width: 100%; + pointer-events: auto; + background-color: #fff; + background-clip: padding-box; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 0.3rem; + outline: 0; +} + +.modal-backdrop { + position: fixed; + top: 0; + left: 0; + z-index: 1040; + width: 100vw; + height: 100vh; + background-color: #000; +} + +.modal-backdrop.fade { + opacity: 0; +} + +.modal-backdrop.show { + opacity: 0.5; +} + +.modal-header { + display: flex; + align-items: flex-start; + justify-content: space-between; + padding: 1rem 1rem; + border-bottom: 1px solid #dee2e6; + border-top-left-radius: calc(0.3rem - 1px); + border-top-right-radius: calc(0.3rem - 1px); +} + +.modal-header .close { + padding: 1rem 1rem; + margin: -1rem -1rem -1rem auto; +} + +.modal-title { + margin-bottom: 0; + line-height: 1.5; +} + +.modal-body { + position: relative; + flex: 1 1 auto; + padding: 1rem; +} + +.modal-footer { + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: flex-end; + padding: 0.75rem; + border-top: 1px solid #dee2e6; + border-bottom-right-radius: calc(0.3rem - 1px); + border-bottom-left-radius: calc(0.3rem - 1px); +} + +.modal-footer > * { + margin: 0.25rem; +} + +.modal-scrollbar-measure { + position: absolute; + top: -9999px; + width: 50px; + height: 50px; + overflow: scroll; +} + +@media (min-width: 576px) { + .modal-dialog { + max-width: 500px; + margin: 1.75rem auto; + } + + .modal-dialog-scrollable { + max-height: calc(100% - 3.5rem); + } + + .modal-dialog-scrollable .modal-content { + max-height: calc(100vh - 3.5rem); + } + + .modal-dialog-centered { + min-height: calc(100% - 3.5rem); + } + + .modal-dialog-centered::before { + height: calc(100vh - 3.5rem); + height: min-content; + } + + .modal-sm { + max-width: 300px; + } +} + +@media (min-width: 992px) { + .modal-lg, + .modal-xl { + max-width: 800px; + } +} + +@media (min-width: 1200px) { + .modal-xl { + max-width: 1140px; + } +} + +.tooltip { + position: absolute; + z-index: 1070; + display: block; + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, + 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + font-style: normal; + font-weight: 400; + line-height: 1.5; + text-align: left; + text-align: start; + text-decoration: none; + text-shadow: none; + text-transform: none; + letter-spacing: normal; + word-break: normal; + word-spacing: normal; + white-space: normal; + line-break: auto; + font-size: 0.875rem; + word-wrap: break-word; + opacity: 0; +} + +.tooltip.show { + opacity: 0.9; +} + +.tooltip .arrow { + position: absolute; + display: block; + width: 0.8rem; + height: 0.4rem; +} + +.tooltip .arrow::before { + position: absolute; + content: ''; + border-color: transparent; + border-style: solid; +} + +.bs-tooltip-top, +.bs-tooltip-auto[x-placement^='top'] { + padding: 0.4rem 0; +} + +.bs-tooltip-top .arrow, +.bs-tooltip-auto[x-placement^='top'] .arrow { + bottom: 0; +} + +.bs-tooltip-top .arrow::before, +.bs-tooltip-auto[x-placement^='top'] .arrow::before { + top: 0; + border-width: 0.4rem 0.4rem 0; + border-top-color: #000; +} + +.bs-tooltip-right, +.bs-tooltip-auto[x-placement^='right'] { + padding: 0 0.4rem; +} + +.bs-tooltip-right .arrow, +.bs-tooltip-auto[x-placement^='right'] .arrow { + left: 0; + width: 0.4rem; + height: 0.8rem; +} + +.bs-tooltip-right .arrow::before, +.bs-tooltip-auto[x-placement^='right'] .arrow::before { + right: 0; + border-width: 0.4rem 0.4rem 0.4rem 0; + border-right-color: #000; +} + +.bs-tooltip-bottom, +.bs-tooltip-auto[x-placement^='bottom'] { + padding: 0.4rem 0; +} + +.bs-tooltip-bottom .arrow, +.bs-tooltip-auto[x-placement^='bottom'] .arrow { + top: 0; +} + +.bs-tooltip-bottom .arrow::before, +.bs-tooltip-auto[x-placement^='bottom'] .arrow::before { + bottom: 0; + border-width: 0 0.4rem 0.4rem; + border-bottom-color: #000; +} + +.bs-tooltip-left, +.bs-tooltip-auto[x-placement^='left'] { + padding: 0 0.4rem; +} + +.bs-tooltip-left .arrow, +.bs-tooltip-auto[x-placement^='left'] .arrow { + right: 0; + width: 0.4rem; + height: 0.8rem; +} + +.bs-tooltip-left .arrow::before, +.bs-tooltip-auto[x-placement^='left'] .arrow::before { + left: 0; + border-width: 0.4rem 0 0.4rem 0.4rem; + border-left-color: #000; +} + +.tooltip-inner { + max-width: 200px; + padding: 0.25rem 0.5rem; + color: #fff; + text-align: center; + background-color: #000; + border-radius: 0.25rem; +} + +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1060; + display: block; + max-width: 276px; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, + 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + font-style: normal; + font-weight: 400; + line-height: 1.5; + text-align: left; + text-align: start; + text-decoration: none; + text-shadow: none; + text-transform: none; + letter-spacing: normal; + word-break: normal; + word-spacing: normal; + white-space: normal; + line-break: auto; + font-size: 0.875rem; + word-wrap: break-word; + background-color: #fff; + background-clip: padding-box; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 0.3rem; +} + +.popover .arrow { + position: absolute; + display: block; + width: 1rem; + height: 0.5rem; + margin: 0 0.3rem; +} + +.popover .arrow::before, +.popover .arrow::after { + position: absolute; + display: block; + content: ''; + border-color: transparent; + border-style: solid; +} + +.bs-popover-top, +.bs-popover-auto[x-placement^='top'] { + margin-bottom: 0.5rem; +} + +.bs-popover-top > .arrow, +.bs-popover-auto[x-placement^='top'] > .arrow { + bottom: calc(-0.5rem - 1px); +} + +.bs-popover-top > .arrow::before, +.bs-popover-auto[x-placement^='top'] > .arrow::before { + bottom: 0; + border-width: 0.5rem 0.5rem 0; + border-top-color: rgba(0, 0, 0, 0.25); +} + +.bs-popover-top > .arrow::after, +.bs-popover-auto[x-placement^='top'] > .arrow::after { + bottom: 1px; + border-width: 0.5rem 0.5rem 0; + border-top-color: #fff; +} + +.bs-popover-right, +.bs-popover-auto[x-placement^='right'] { + margin-left: 0.5rem; +} + +.bs-popover-right > .arrow, +.bs-popover-auto[x-placement^='right'] > .arrow { + left: calc(-0.5rem - 1px); + width: 0.5rem; + height: 1rem; + margin: 0.3rem 0; +} + +.bs-popover-right > .arrow::before, +.bs-popover-auto[x-placement^='right'] > .arrow::before { + left: 0; + border-width: 0.5rem 0.5rem 0.5rem 0; + border-right-color: rgba(0, 0, 0, 0.25); +} + +.bs-popover-right > .arrow::after, +.bs-popover-auto[x-placement^='right'] > .arrow::after { + left: 1px; + border-width: 0.5rem 0.5rem 0.5rem 0; + border-right-color: #fff; +} + +.bs-popover-bottom, +.bs-popover-auto[x-placement^='bottom'] { + margin-top: 0.5rem; +} + +.bs-popover-bottom > .arrow, +.bs-popover-auto[x-placement^='bottom'] > .arrow { + top: calc(-0.5rem - 1px); +} + +.bs-popover-bottom > .arrow::before, +.bs-popover-auto[x-placement^='bottom'] > .arrow::before { + top: 0; + border-width: 0 0.5rem 0.5rem 0.5rem; + border-bottom-color: rgba(0, 0, 0, 0.25); +} + +.bs-popover-bottom > .arrow::after, +.bs-popover-auto[x-placement^='bottom'] > .arrow::after { + top: 1px; + border-width: 0 0.5rem 0.5rem 0.5rem; + border-bottom-color: #fff; +} + +.bs-popover-bottom .popover-header::before, +.bs-popover-auto[x-placement^='bottom'] .popover-header::before { + position: absolute; + top: 0; + left: 50%; + display: block; + width: 1rem; + margin-left: -0.5rem; + content: ''; + border-bottom: 1px solid #f7f7f7; +} + +.bs-popover-left, +.bs-popover-auto[x-placement^='left'] { + margin-right: 0.5rem; +} + +.bs-popover-left > .arrow, +.bs-popover-auto[x-placement^='left'] > .arrow { + right: calc(-0.5rem - 1px); + width: 0.5rem; + height: 1rem; + margin: 0.3rem 0; +} + +.bs-popover-left > .arrow::before, +.bs-popover-auto[x-placement^='left'] > .arrow::before { + right: 0; + border-width: 0.5rem 0 0.5rem 0.5rem; + border-left-color: rgba(0, 0, 0, 0.25); +} + +.bs-popover-left > .arrow::after, +.bs-popover-auto[x-placement^='left'] > .arrow::after { + right: 1px; + border-width: 0.5rem 0 0.5rem 0.5rem; + border-left-color: #fff; +} + +.popover-header { + padding: 0.5rem 0.75rem; + margin-bottom: 0; + font-size: 1rem; + background-color: #f7f7f7; + border-bottom: 1px solid #ebebeb; + border-top-left-radius: calc(0.3rem - 1px); + border-top-right-radius: calc(0.3rem - 1px); +} + +.popover-header:empty { + display: none; +} + +.popover-body { + padding: 0.5rem 0.75rem; + color: #212529; +} + +.carousel { + position: relative; +} + +.carousel.pointer-event { + touch-action: pan-y; +} + +.carousel-inner { + position: relative; + width: 100%; + overflow: hidden; +} + +.carousel-inner::after { + display: block; + clear: both; + content: ''; +} + +.carousel-item { + position: relative; + display: none; + float: left; + width: 100%; + margin-right: -100%; + backface-visibility: hidden; + transition: transform 0.6s ease-in-out; +} + +.carousel-item.active, +.carousel-item-next, +.carousel-item-prev { + display: block; +} + +.carousel-item-next:not(.carousel-item-left), +.active.carousel-item-right { + transform: translateX(100%); +} + +.carousel-item-prev:not(.carousel-item-right), +.active.carousel-item-left { + transform: translateX(-100%); +} + +.carousel-fade .carousel-item { + opacity: 0; + transition-property: opacity; + transform: none; +} + +.carousel-fade .carousel-item.active, +.carousel-fade .carousel-item-next.carousel-item-left, +.carousel-fade .carousel-item-prev.carousel-item-right { + z-index: 1; + opacity: 1; +} + +.carousel-fade .active.carousel-item-left, +.carousel-fade .active.carousel-item-right { + z-index: 0; + opacity: 0; + transition: opacity 0s 0.6s; +} + +.carousel-control-prev, +.carousel-control-next { + position: absolute; + top: 0; + bottom: 0; + z-index: 1; + display: flex; + align-items: center; + justify-content: center; + width: 15%; + color: #fff; + text-align: center; + opacity: 0.5; + transition: opacity 0.15s ease; +} + +.carousel-control-prev:hover, +.carousel-control-prev:focus, +.carousel-control-next:hover, +.carousel-control-next:focus { + color: #fff; + text-decoration: none; + outline: 0; + opacity: 0.9; +} + +.carousel-control-prev { + left: 0; +} + +.carousel-control-next { + right: 0; +} + +.carousel-control-prev-icon, +.carousel-control-next-icon { + display: inline-block; + width: 20px; + height: 20px; + background: no-repeat 50% / 100% 100%; +} + +.carousel-control-prev-icon { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath d='M5.25 0l-4 4 4 4 1.5-1.5L4.25 4l2.5-2.5L5.25 0z'/%3e%3c/svg%3e"); +} + +.carousel-control-next-icon { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath d='M2.75 0l-1.5 1.5L3.75 4l-2.5 2.5L2.75 8l4-4-4-4z'/%3e%3c/svg%3e"); +} + +.carousel-indicators { + position: absolute; + right: 0; + bottom: 0; + left: 0; + z-index: 15; + display: flex; + justify-content: center; + padding-left: 0; + margin-right: 15%; + margin-left: 15%; + list-style: none; +} + +.carousel-indicators li { + box-sizing: content-box; + flex: 0 1 auto; + width: 30px; + height: 3px; + margin-right: 3px; + margin-left: 3px; + text-indent: -999px; + cursor: pointer; + background-color: #fff; + background-clip: padding-box; + border-top: 10px solid transparent; + border-bottom: 10px solid transparent; + opacity: 0.5; + transition: opacity 0.6s ease; +} + +.carousel-indicators .active { + opacity: 1; +} + +.carousel-caption { + position: absolute; + right: 15%; + bottom: 20px; + left: 15%; + z-index: 10; + padding-top: 20px; + padding-bottom: 20px; + color: #fff; + text-align: center; +} + +@keyframes spinner-border { + to { + transform: rotate(360deg); + } +} + +.spinner-border { + display: inline-block; + width: 2rem; + height: 2rem; + vertical-align: text-bottom; + border: 0.25em solid currentColor; + border-right-color: transparent; + border-radius: 50%; + animation: spinner-border 0.75s linear infinite; +} + +.spinner-border-sm { + width: 1rem; + height: 1rem; + border-width: 0.2em; +} + +@keyframes spinner-grow { + 0% { + transform: scale(0); + } + 50% { + opacity: 1; + transform: none; + } +} + +.spinner-grow { + display: inline-block; + width: 2rem; + height: 2rem; + vertical-align: text-bottom; + background-color: currentColor; + border-radius: 50%; + opacity: 0; + animation: spinner-grow 0.75s linear infinite; +} + +.spinner-grow-sm { + width: 1rem; + height: 1rem; +} + +.align-baseline { + vertical-align: baseline !important; +} + +.align-top { + vertical-align: top !important; +} + +.align-middle { + vertical-align: middle !important; +} + +.align-bottom { + vertical-align: bottom !important; +} + +.align-text-bottom { + vertical-align: text-bottom !important; +} + +.align-text-top { + vertical-align: text-top !important; +} + +.bg-primary { + background-color: #07819b !important; +} + +a.bg-primary:hover, +a.bg-primary:focus, +button.bg-primary:hover, +button.bg-primary:focus { + background-color: #05586a !important; +} + +.bg-secondary { + background-color: #313032 !important; +} + +a.bg-secondary:hover, +a.bg-secondary:focus, +button.bg-secondary:hover, +button.bg-secondary:focus { + background-color: #181718 !important; +} + +.bg-success { + background-color: #28a745 !important; +} + +a.bg-success:hover, +a.bg-success:focus, +button.bg-success:hover, +button.bg-success:focus { + background-color: #1e7e34 !important; +} + +.bg-info { + background-color: #17a2b8 !important; +} + +a.bg-info:hover, +a.bg-info:focus, +button.bg-info:hover, +button.bg-info:focus { + background-color: #117a8b !important; +} + +.bg-warning { + background-color: #ffc107 !important; +} + +a.bg-warning:hover, +a.bg-warning:focus, +button.bg-warning:hover, +button.bg-warning:focus { + background-color: #d39e00 !important; +} + +.bg-danger { + background-color: #dc3545 !important; +} + +a.bg-danger:hover, +a.bg-danger:focus, +button.bg-danger:hover, +button.bg-danger:focus { + background-color: #bd2130 !important; +} + +.bg-light { + background-color: #f8f9fa !important; +} + +a.bg-light:hover, +a.bg-light:focus, +button.bg-light:hover, +button.bg-light:focus { + background-color: #dae0e5 !important; +} + +.bg-dark { + background-color: #343a40 !important; +} + +a.bg-dark:hover, +a.bg-dark:focus, +button.bg-dark:hover, +button.bg-dark:focus { + background-color: #1d2124 !important; +} + +.bg-white { + background-color: #fff !important; +} + +.bg-transparent { + background-color: transparent !important; +} + +.border { + border: 1px solid #dee2e6 !important; +} + +.border-top { + border-top: 1px solid #dee2e6 !important; +} + +.border-right { + border-right: 1px solid #dee2e6 !important; +} + +.border-bottom { + border-bottom: 1px solid #dee2e6 !important; +} + +.border-left { + border-left: 1px solid #dee2e6 !important; +} + +.border-0 { + border: 0 !important; +} + +.border-top-0 { + border-top: 0 !important; +} + +.border-right-0 { + border-right: 0 !important; +} + +.border-bottom-0 { + border-bottom: 0 !important; +} + +.border-left-0 { + border-left: 0 !important; +} + +.border-primary { + border-color: #07819b !important; +} + +.border-secondary { + border-color: #313032 !important; +} + +.border-success { + border-color: #28a745 !important; +} + +.border-info { + border-color: #17a2b8 !important; +} + +.border-warning { + border-color: #ffc107 !important; +} + +.border-danger { + border-color: #dc3545 !important; +} + +.border-light { + border-color: #f8f9fa !important; +} + +.border-dark { + border-color: #343a40 !important; +} + +.border-white { + border-color: #fff !important; +} + +.rounded-sm { + border-radius: 0.2rem !important; +} + +.rounded { + border-radius: 0.25rem !important; +} + +.rounded-top { + border-top-left-radius: 0.25rem !important; + border-top-right-radius: 0.25rem !important; +} + +.rounded-right { + border-top-right-radius: 0.25rem !important; + border-bottom-right-radius: 0.25rem !important; +} + +.rounded-bottom { + border-bottom-right-radius: 0.25rem !important; + border-bottom-left-radius: 0.25rem !important; +} + +.rounded-left { + border-top-left-radius: 0.25rem !important; + border-bottom-left-radius: 0.25rem !important; +} + +.rounded-lg { + border-radius: 0.3rem !important; +} + +.rounded-circle { + border-radius: 50% !important; +} + +.rounded-pill { + border-radius: 50rem !important; +} + +.rounded-0 { + border-radius: 0 !important; +} + +.clearfix::after { + display: block; + clear: both; + content: ''; +} + +.d-none { + display: none !important; +} + +.d-inline { + display: inline !important; +} + +.d-inline-block { + display: inline-block !important; +} + +.d-block { + display: block !important; +} + +.d-table { + display: table !important; +} + +.d-table-row { + display: table-row !important; +} + +.d-table-cell { + display: table-cell !important; +} + +.d-flex { + display: flex !important; +} + +.d-inline-flex { + display: inline-flex !important; +} + +@media (min-width: 576px) { + .d-sm-none { + display: none !important; + } + + .d-sm-inline { + display: inline !important; + } + + .d-sm-inline-block { + display: inline-block !important; + } + + .d-sm-block { + display: block !important; + } + + .d-sm-table { + display: table !important; + } + + .d-sm-table-row { + display: table-row !important; + } + + .d-sm-table-cell { + display: table-cell !important; + } + + .d-sm-flex { + display: flex !important; + } + + .d-sm-inline-flex { + display: inline-flex !important; + } +} + +@media (min-width: 768px) { + .d-md-none { + display: none !important; + } + + .d-md-inline { + display: inline !important; + } + + .d-md-inline-block { + display: inline-block !important; + } + + .d-md-block { + display: block !important; + } + + .d-md-table { + display: table !important; + } + + .d-md-table-row { + display: table-row !important; + } + + .d-md-table-cell { + display: table-cell !important; + } + + .d-md-flex { + display: flex !important; + } + + .d-md-inline-flex { + display: inline-flex !important; + } +} + +@media (min-width: 992px) { + .d-lg-none { + display: none !important; + } + + .d-lg-inline { + display: inline !important; + } + + .d-lg-inline-block { + display: inline-block !important; + } + + .d-lg-block { + display: block !important; + } + + .d-lg-table { + display: table !important; + } + + .d-lg-table-row { + display: table-row !important; + } + + .d-lg-table-cell { + display: table-cell !important; + } + + .d-lg-flex { + display: flex !important; + } + + .d-lg-inline-flex { + display: inline-flex !important; + } +} + +@media (min-width: 1200px) { + .d-xl-none { + display: none !important; + } + + .d-xl-inline { + display: inline !important; + } + + .d-xl-inline-block { + display: inline-block !important; + } + + .d-xl-block { + display: block !important; + } + + .d-xl-table { + display: table !important; + } + + .d-xl-table-row { + display: table-row !important; + } + + .d-xl-table-cell { + display: table-cell !important; + } + + .d-xl-flex { + display: flex !important; + } + + .d-xl-inline-flex { + display: inline-flex !important; + } +} + +@media print { + .d-print-none { + display: none !important; + } + + .d-print-inline { + display: inline !important; + } + + .d-print-inline-block { + display: inline-block !important; + } + + .d-print-block { + display: block !important; + } + + .d-print-table { + display: table !important; + } + + .d-print-table-row { + display: table-row !important; + } + + .d-print-table-cell { + display: table-cell !important; + } + + .d-print-flex { + display: flex !important; + } + + .d-print-inline-flex { + display: inline-flex !important; + } +} + +.embed-responsive { + position: relative; + display: block; + width: 100%; + padding: 0; + overflow: hidden; +} + +.embed-responsive::before { + display: block; + content: ''; +} + +.embed-responsive .embed-responsive-item, +.embed-responsive iframe, +.embed-responsive embed, +.embed-responsive object, +.embed-responsive video { + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 100%; + height: 100%; + border: 0; +} + +.embed-responsive-21by9::before { + padding-top: 42.85714%; +} + +.embed-responsive-16by9::before { + padding-top: 56.25%; +} + +.embed-responsive-4by3::before { + padding-top: 75%; +} + +.embed-responsive-1by1::before { + padding-top: 100%; +} + +.flex-row { + flex-direction: row !important; +} + +.flex-column { + flex-direction: column !important; +} + +.flex-row-reverse { + flex-direction: row-reverse !important; +} + +.flex-column-reverse { + flex-direction: column-reverse !important; +} + +.flex-wrap { + flex-wrap: wrap !important; +} + +.flex-nowrap { + flex-wrap: nowrap !important; +} + +.flex-wrap-reverse { + flex-wrap: wrap-reverse !important; +} + +.flex-fill { + flex: 1 1 auto !important; +} + +.flex-grow-0 { + flex-grow: 0 !important; +} + +.flex-grow-1 { + flex-grow: 1 !important; +} + +.flex-shrink-0 { + flex-shrink: 0 !important; +} + +.flex-shrink-1 { + flex-shrink: 1 !important; +} + +.justify-content-start { + justify-content: flex-start !important; +} + +.justify-content-end { + justify-content: flex-end !important; +} + +.justify-content-center { + justify-content: center !important; +} + +.justify-content-between { + justify-content: space-between !important; +} + +.justify-content-around { + justify-content: space-around !important; +} + +.align-items-start { + align-items: flex-start !important; +} + +.align-items-end { + align-items: flex-end !important; +} + +.align-items-center { + align-items: center !important; +} + +.align-items-baseline { + align-items: baseline !important; +} + +.align-items-stretch { + align-items: stretch !important; +} + +.align-content-start { + align-content: flex-start !important; +} + +.align-content-end { + align-content: flex-end !important; +} + +.align-content-center { + align-content: center !important; +} + +.align-content-between { + align-content: space-between !important; +} + +.align-content-around { + align-content: space-around !important; +} + +.align-content-stretch { + align-content: stretch !important; +} + +.align-self-auto { + align-self: auto !important; +} + +.align-self-start { + align-self: flex-start !important; +} + +.align-self-end { + align-self: flex-end !important; +} + +.align-self-center { + align-self: center !important; +} + +.align-self-baseline { + align-self: baseline !important; +} + +.align-self-stretch { + align-self: stretch !important; +} + +@media (min-width: 576px) { + .flex-sm-row { + flex-direction: row !important; + } + + .flex-sm-column { + flex-direction: column !important; + } + + .flex-sm-row-reverse { + flex-direction: row-reverse !important; + } + + .flex-sm-column-reverse { + flex-direction: column-reverse !important; + } + + .flex-sm-wrap { + flex-wrap: wrap !important; + } + + .flex-sm-nowrap { + flex-wrap: nowrap !important; + } + + .flex-sm-wrap-reverse { + flex-wrap: wrap-reverse !important; + } + + .flex-sm-fill { + flex: 1 1 auto !important; + } + + .flex-sm-grow-0 { + flex-grow: 0 !important; + } + + .flex-sm-grow-1 { + flex-grow: 1 !important; + } + + .flex-sm-shrink-0 { + flex-shrink: 0 !important; + } + + .flex-sm-shrink-1 { + flex-shrink: 1 !important; + } + + .justify-content-sm-start { + justify-content: flex-start !important; + } + + .justify-content-sm-end { + justify-content: flex-end !important; + } + + .justify-content-sm-center { + justify-content: center !important; + } + + .justify-content-sm-between { + justify-content: space-between !important; + } + + .justify-content-sm-around { + justify-content: space-around !important; + } + + .align-items-sm-start { + align-items: flex-start !important; + } + + .align-items-sm-end { + align-items: flex-end !important; + } + + .align-items-sm-center { + align-items: center !important; + } + + .align-items-sm-baseline { + align-items: baseline !important; + } + + .align-items-sm-stretch { + align-items: stretch !important; + } + + .align-content-sm-start { + align-content: flex-start !important; + } + + .align-content-sm-end { + align-content: flex-end !important; + } + + .align-content-sm-center { + align-content: center !important; + } + + .align-content-sm-between { + align-content: space-between !important; + } + + .align-content-sm-around { + align-content: space-around !important; + } + + .align-content-sm-stretch { + align-content: stretch !important; + } + + .align-self-sm-auto { + align-self: auto !important; + } + + .align-self-sm-start { + align-self: flex-start !important; + } + + .align-self-sm-end { + align-self: flex-end !important; + } + + .align-self-sm-center { + align-self: center !important; + } + + .align-self-sm-baseline { + align-self: baseline !important; + } + + .align-self-sm-stretch { + align-self: stretch !important; + } +} + +@media (min-width: 768px) { + .flex-md-row { + flex-direction: row !important; + } + + .flex-md-column { + flex-direction: column !important; + } + + .flex-md-row-reverse { + flex-direction: row-reverse !important; + } + + .flex-md-column-reverse { + flex-direction: column-reverse !important; + } + + .flex-md-wrap { + flex-wrap: wrap !important; + } + + .flex-md-nowrap { + flex-wrap: nowrap !important; + } + + .flex-md-wrap-reverse { + flex-wrap: wrap-reverse !important; + } + + .flex-md-fill { + flex: 1 1 auto !important; + } + + .flex-md-grow-0 { + flex-grow: 0 !important; + } + + .flex-md-grow-1 { + flex-grow: 1 !important; + } + + .flex-md-shrink-0 { + flex-shrink: 0 !important; + } + + .flex-md-shrink-1 { + flex-shrink: 1 !important; + } + + .justify-content-md-start { + justify-content: flex-start !important; + } + + .justify-content-md-end { + justify-content: flex-end !important; + } + + .justify-content-md-center { + justify-content: center !important; + } + + .justify-content-md-between { + justify-content: space-between !important; + } + + .justify-content-md-around { + justify-content: space-around !important; + } + + .align-items-md-start { + align-items: flex-start !important; + } + + .align-items-md-end { + align-items: flex-end !important; + } + + .align-items-md-center { + align-items: center !important; + } + + .align-items-md-baseline { + align-items: baseline !important; + } + + .align-items-md-stretch { + align-items: stretch !important; + } + + .align-content-md-start { + align-content: flex-start !important; + } + + .align-content-md-end { + align-content: flex-end !important; + } + + .align-content-md-center { + align-content: center !important; + } + + .align-content-md-between { + align-content: space-between !important; + } + + .align-content-md-around { + align-content: space-around !important; + } + + .align-content-md-stretch { + align-content: stretch !important; + } + + .align-self-md-auto { + align-self: auto !important; + } + + .align-self-md-start { + align-self: flex-start !important; + } + + .align-self-md-end { + align-self: flex-end !important; + } + + .align-self-md-center { + align-self: center !important; + } + + .align-self-md-baseline { + align-self: baseline !important; + } + + .align-self-md-stretch { + align-self: stretch !important; + } +} + +@media (min-width: 992px) { + .flex-lg-row { + flex-direction: row !important; + } + + .flex-lg-column { + flex-direction: column !important; + } + + .flex-lg-row-reverse { + flex-direction: row-reverse !important; + } + + .flex-lg-column-reverse { + flex-direction: column-reverse !important; + } + + .flex-lg-wrap { + flex-wrap: wrap !important; + } + + .flex-lg-nowrap { + flex-wrap: nowrap !important; + } + + .flex-lg-wrap-reverse { + flex-wrap: wrap-reverse !important; + } + + .flex-lg-fill { + flex: 1 1 auto !important; + } + + .flex-lg-grow-0 { + flex-grow: 0 !important; + } + + .flex-lg-grow-1 { + flex-grow: 1 !important; + } + + .flex-lg-shrink-0 { + flex-shrink: 0 !important; + } + + .flex-lg-shrink-1 { + flex-shrink: 1 !important; + } + + .justify-content-lg-start { + justify-content: flex-start !important; + } + + .justify-content-lg-end { + justify-content: flex-end !important; + } + + .justify-content-lg-center { + justify-content: center !important; + } + + .justify-content-lg-between { + justify-content: space-between !important; + } + + .justify-content-lg-around { + justify-content: space-around !important; + } + + .align-items-lg-start { + align-items: flex-start !important; + } + + .align-items-lg-end { + align-items: flex-end !important; + } + + .align-items-lg-center { + align-items: center !important; + } + + .align-items-lg-baseline { + align-items: baseline !important; + } + + .align-items-lg-stretch { + align-items: stretch !important; + } + + .align-content-lg-start { + align-content: flex-start !important; + } + + .align-content-lg-end { + align-content: flex-end !important; + } + + .align-content-lg-center { + align-content: center !important; + } + + .align-content-lg-between { + align-content: space-between !important; + } + + .align-content-lg-around { + align-content: space-around !important; + } + + .align-content-lg-stretch { + align-content: stretch !important; + } + + .align-self-lg-auto { + align-self: auto !important; + } + + .align-self-lg-start { + align-self: flex-start !important; + } + + .align-self-lg-end { + align-self: flex-end !important; + } + + .align-self-lg-center { + align-self: center !important; + } + + .align-self-lg-baseline { + align-self: baseline !important; + } + + .align-self-lg-stretch { + align-self: stretch !important; + } +} + +@media (min-width: 1200px) { + .flex-xl-row { + flex-direction: row !important; + } + + .flex-xl-column { + flex-direction: column !important; + } + + .flex-xl-row-reverse { + flex-direction: row-reverse !important; + } + + .flex-xl-column-reverse { + flex-direction: column-reverse !important; + } + + .flex-xl-wrap { + flex-wrap: wrap !important; + } + + .flex-xl-nowrap { + flex-wrap: nowrap !important; + } + + .flex-xl-wrap-reverse { + flex-wrap: wrap-reverse !important; + } + + .flex-xl-fill { + flex: 1 1 auto !important; + } + + .flex-xl-grow-0 { + flex-grow: 0 !important; + } + + .flex-xl-grow-1 { + flex-grow: 1 !important; + } + + .flex-xl-shrink-0 { + flex-shrink: 0 !important; + } + + .flex-xl-shrink-1 { + flex-shrink: 1 !important; + } + + .justify-content-xl-start { + justify-content: flex-start !important; + } + + .justify-content-xl-end { + justify-content: flex-end !important; + } + + .justify-content-xl-center { + justify-content: center !important; + } + + .justify-content-xl-between { + justify-content: space-between !important; + } + + .justify-content-xl-around { + justify-content: space-around !important; + } + + .align-items-xl-start { + align-items: flex-start !important; + } + + .align-items-xl-end { + align-items: flex-end !important; + } + + .align-items-xl-center { + align-items: center !important; + } + + .align-items-xl-baseline { + align-items: baseline !important; + } + + .align-items-xl-stretch { + align-items: stretch !important; + } + + .align-content-xl-start { + align-content: flex-start !important; + } + + .align-content-xl-end { + align-content: flex-end !important; + } + + .align-content-xl-center { + align-content: center !important; + } + + .align-content-xl-between { + align-content: space-between !important; + } + + .align-content-xl-around { + align-content: space-around !important; + } + + .align-content-xl-stretch { + align-content: stretch !important; + } + + .align-self-xl-auto { + align-self: auto !important; + } + + .align-self-xl-start { + align-self: flex-start !important; + } + + .align-self-xl-end { + align-self: flex-end !important; + } + + .align-self-xl-center { + align-self: center !important; + } + + .align-self-xl-baseline { + align-self: baseline !important; + } + + .align-self-xl-stretch { + align-self: stretch !important; + } +} + +.float-left { + float: left !important; +} + +.float-right { + float: right !important; +} + +.float-none { + float: none !important; +} + +@media (min-width: 576px) { + .float-sm-left { + float: left !important; + } + + .float-sm-right { + float: right !important; + } + + .float-sm-none { + float: none !important; + } +} + +@media (min-width: 768px) { + .float-md-left { + float: left !important; + } + + .float-md-right { + float: right !important; + } + + .float-md-none { + float: none !important; + } +} + +@media (min-width: 992px) { + .float-lg-left { + float: left !important; + } + + .float-lg-right { + float: right !important; + } + + .float-lg-none { + float: none !important; + } +} + +@media (min-width: 1200px) { + .float-xl-left { + float: left !important; + } + + .float-xl-right { + float: right !important; + } + + .float-xl-none { + float: none !important; + } +} + +.user-select-all { + user-select: all !important; +} + +.user-select-auto { + user-select: auto !important; +} + +.user-select-none { + user-select: none !important; +} + +.overflow-auto { + overflow: auto !important; +} + +.overflow-hidden { + overflow: hidden !important; +} + +.position-static { + position: static !important; +} + +.position-relative { + position: relative !important; +} + +.position-absolute { + position: absolute !important; +} + +.position-fixed { + position: fixed !important; +} + +.position-sticky { + position: sticky !important; +} + +.fixed-top { + position: fixed; + top: 0; + right: 0; + left: 0; + z-index: 1030; +} + +.fixed-bottom { + position: fixed; + right: 0; + bottom: 0; + left: 0; + z-index: 1030; +} + +@supports (position: sticky) { + .sticky-top { + position: sticky; + top: 0; + z-index: 1020; + } +} + +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; +} + +.sr-only-focusable:active, +.sr-only-focusable:focus { + position: static; + width: auto; + height: auto; + overflow: visible; + clip: auto; + white-space: normal; +} + +.shadow-sm { + box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075) !important; +} + +.shadow { + box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important; +} + +.shadow-lg { + box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.175) !important; +} + +.shadow-none { + box-shadow: none !important; +} + +.w-25 { + width: 25% !important; +} + +.w-50 { + width: 50% !important; +} + +.w-75 { + width: 75% !important; +} + +.w-100 { + width: 100% !important; +} + +.w-auto { + width: auto !important; +} + +.h-25 { + height: 25% !important; +} + +.h-50 { + height: 50% !important; +} + +.h-75 { + height: 75% !important; +} + +.h-100 { + height: 100% !important; +} + +.h-auto { + height: auto !important; +} + +.mw-100 { + max-width: 100% !important; +} + +.mh-100 { + max-height: 100% !important; +} + +.min-vw-100 { + min-width: 100vw !important; +} + +.min-vh-100 { + min-height: 100vh !important; +} + +.vw-100 { + width: 100vw !important; +} + +.vh-100 { + height: 100vh !important; +} + +.m-0 { + margin: 0 !important; +} + +.mt-0, +.my-0 { + margin-top: 0 !important; +} + +.mr-0, +.mx-0 { + margin-right: 0 !important; +} + +.mb-0, +.my-0 { + margin-bottom: 0 !important; +} + +.ml-0, +.mx-0 { + margin-left: 0 !important; +} + +.m-1 { + margin: 0.25rem !important; +} + +.mt-1, +.my-1 { + margin-top: 0.25rem !important; +} + +.mr-1, +.mx-1 { + margin-right: 0.25rem !important; +} + +.mb-1, +.my-1 { + margin-bottom: 0.25rem !important; +} + +.ml-1, +.mx-1 { + margin-left: 0.25rem !important; +} + +.m-2 { + margin: 0.5rem !important; +} + +.mt-2, +.my-2 { + margin-top: 0.5rem !important; +} + +.mr-2, +.mx-2 { + margin-right: 0.5rem !important; +} + +.mb-2, +.my-2 { + margin-bottom: 0.5rem !important; +} + +.ml-2, +.mx-2 { + margin-left: 0.5rem !important; +} + +.m-3 { + margin: 1rem !important; +} + +.mt-3, +.my-3 { + margin-top: 1rem !important; +} + +.mr-3, +.mx-3 { + margin-right: 1rem !important; +} + +.mb-3, +.my-3 { + margin-bottom: 1rem !important; +} + +.ml-3, +.mx-3 { + margin-left: 1rem !important; +} + +.m-4 { + margin: 1.5rem !important; +} + +.mt-4, +.my-4 { + margin-top: 1.5rem !important; +} + +.mr-4, +.mx-4 { + margin-right: 1.5rem !important; +} + +.mb-4, +.my-4 { + margin-bottom: 1.5rem !important; +} + +.ml-4, +.mx-4 { + margin-left: 1.5rem !important; +} + +.m-5 { + margin: 3rem !important; +} + +.mt-5, +.my-5 { + margin-top: 3rem !important; +} + +.mr-5, +.mx-5 { + margin-right: 3rem !important; +} + +.mb-5, +.my-5 { + margin-bottom: 3rem !important; +} + +.ml-5, +.mx-5 { + margin-left: 3rem !important; +} + +.p-0 { + padding: 0 !important; +} + +.pt-0, +.py-0 { + padding-top: 0 !important; +} + +.pr-0, +.px-0 { + padding-right: 0 !important; +} + +.pb-0, +.py-0 { + padding-bottom: 0 !important; +} + +.pl-0, +.px-0 { + padding-left: 0 !important; +} + +.p-1 { + padding: 0.25rem !important; +} + +.pt-1, +.py-1 { + padding-top: 0.25rem !important; +} + +.pr-1, +.px-1 { + padding-right: 0.25rem !important; +} + +.pb-1, +.py-1 { + padding-bottom: 0.25rem !important; +} + +.pl-1, +.px-1 { + padding-left: 0.25rem !important; +} + +.p-2 { + padding: 0.5rem !important; +} + +.pt-2, +.py-2 { + padding-top: 0.5rem !important; +} + +.pr-2, +.px-2 { + padding-right: 0.5rem !important; +} + +.pb-2, +.py-2 { + padding-bottom: 0.5rem !important; +} + +.pl-2, +.px-2 { + padding-left: 0.5rem !important; +} + +.p-3 { + padding: 1rem !important; +} + +.pt-3, +.py-3 { + padding-top: 1rem !important; +} + +.pr-3, +.px-3 { + padding-right: 1rem !important; +} + +.pb-3, +.py-3 { + padding-bottom: 1rem !important; +} + +.pl-3, +.px-3 { + padding-left: 1rem !important; +} + +.p-4 { + padding: 1.5rem !important; +} + +.pt-4, +.py-4 { + padding-top: 1.5rem !important; +} + +.pr-4, +.px-4 { + padding-right: 1.5rem !important; +} + +.pb-4, +.py-4 { + padding-bottom: 1.5rem !important; +} + +.pl-4, +.px-4 { + padding-left: 1.5rem !important; +} + +.p-5 { + padding: 3rem !important; +} + +.pt-5, +.py-5 { + padding-top: 3rem !important; +} + +.pr-5, +.px-5 { + padding-right: 3rem !important; +} + +.pb-5, +.py-5 { + padding-bottom: 3rem !important; +} + +.pl-5, +.px-5 { + padding-left: 3rem !important; +} + +.m-n1 { + margin: -0.25rem !important; +} + +.mt-n1, +.my-n1 { + margin-top: -0.25rem !important; +} + +.mr-n1, +.mx-n1 { + margin-right: -0.25rem !important; +} + +.mb-n1, +.my-n1 { + margin-bottom: -0.25rem !important; +} + +.ml-n1, +.mx-n1 { + margin-left: -0.25rem !important; +} + +.m-n2 { + margin: -0.5rem !important; +} + +.mt-n2, +.my-n2 { + margin-top: -0.5rem !important; +} + +.mr-n2, +.mx-n2 { + margin-right: -0.5rem !important; +} + +.mb-n2, +.my-n2 { + margin-bottom: -0.5rem !important; +} + +.ml-n2, +.mx-n2 { + margin-left: -0.5rem !important; +} + +.m-n3 { + margin: -1rem !important; +} + +.mt-n3, +.my-n3 { + margin-top: -1rem !important; +} + +.mr-n3, +.mx-n3 { + margin-right: -1rem !important; +} + +.mb-n3, +.my-n3 { + margin-bottom: -1rem !important; +} + +.ml-n3, +.mx-n3 { + margin-left: -1rem !important; +} + +.m-n4 { + margin: -1.5rem !important; +} + +.mt-n4, +.my-n4 { + margin-top: -1.5rem !important; +} + +.mr-n4, +.mx-n4 { + margin-right: -1.5rem !important; +} + +.mb-n4, +.my-n4 { + margin-bottom: -1.5rem !important; +} + +.ml-n4, +.mx-n4 { + margin-left: -1.5rem !important; +} + +.m-n5 { + margin: -3rem !important; +} + +.mt-n5, +.my-n5 { + margin-top: -3rem !important; +} + +.mr-n5, +.mx-n5 { + margin-right: -3rem !important; +} + +.mb-n5, +.my-n5 { + margin-bottom: -3rem !important; +} + +.ml-n5, +.mx-n5 { + margin-left: -3rem !important; +} + +.m-auto { + margin: auto !important; +} + +.mt-auto, +.my-auto { + margin-top: auto !important; +} + +.mr-auto, +.mx-auto { + margin-right: auto !important; +} + +.mb-auto, +.my-auto { + margin-bottom: auto !important; +} + +.ml-auto, +.mx-auto { + margin-left: auto !important; +} + +@media (min-width: 576px) { + .m-sm-0 { + margin: 0 !important; + } + + .mt-sm-0, + .my-sm-0 { + margin-top: 0 !important; + } + + .mr-sm-0, + .mx-sm-0 { + margin-right: 0 !important; + } + + .mb-sm-0, + .my-sm-0 { + margin-bottom: 0 !important; + } + + .ml-sm-0, + .mx-sm-0 { + margin-left: 0 !important; + } + + .m-sm-1 { + margin: 0.25rem !important; + } + + .mt-sm-1, + .my-sm-1 { + margin-top: 0.25rem !important; + } + + .mr-sm-1, + .mx-sm-1 { + margin-right: 0.25rem !important; + } + + .mb-sm-1, + .my-sm-1 { + margin-bottom: 0.25rem !important; + } + + .ml-sm-1, + .mx-sm-1 { + margin-left: 0.25rem !important; + } + + .m-sm-2 { + margin: 0.5rem !important; + } + + .mt-sm-2, + .my-sm-2 { + margin-top: 0.5rem !important; + } + + .mr-sm-2, + .mx-sm-2 { + margin-right: 0.5rem !important; + } + + .mb-sm-2, + .my-sm-2 { + margin-bottom: 0.5rem !important; + } + + .ml-sm-2, + .mx-sm-2 { + margin-left: 0.5rem !important; + } + + .m-sm-3 { + margin: 1rem !important; + } + + .mt-sm-3, + .my-sm-3 { + margin-top: 1rem !important; + } + + .mr-sm-3, + .mx-sm-3 { + margin-right: 1rem !important; + } + + .mb-sm-3, + .my-sm-3 { + margin-bottom: 1rem !important; + } + + .ml-sm-3, + .mx-sm-3 { + margin-left: 1rem !important; + } + + .m-sm-4 { + margin: 1.5rem !important; + } + + .mt-sm-4, + .my-sm-4 { + margin-top: 1.5rem !important; + } + + .mr-sm-4, + .mx-sm-4 { + margin-right: 1.5rem !important; + } + + .mb-sm-4, + .my-sm-4 { + margin-bottom: 1.5rem !important; + } + + .ml-sm-4, + .mx-sm-4 { + margin-left: 1.5rem !important; + } + + .m-sm-5 { + margin: 3rem !important; + } + + .mt-sm-5, + .my-sm-5 { + margin-top: 3rem !important; + } + + .mr-sm-5, + .mx-sm-5 { + margin-right: 3rem !important; + } + + .mb-sm-5, + .my-sm-5 { + margin-bottom: 3rem !important; + } + + .ml-sm-5, + .mx-sm-5 { + margin-left: 3rem !important; + } + + .p-sm-0 { + padding: 0 !important; + } + + .pt-sm-0, + .py-sm-0 { + padding-top: 0 !important; + } + + .pr-sm-0, + .px-sm-0 { + padding-right: 0 !important; + } + + .pb-sm-0, + .py-sm-0 { + padding-bottom: 0 !important; + } + + .pl-sm-0, + .px-sm-0 { + padding-left: 0 !important; + } + + .p-sm-1 { + padding: 0.25rem !important; + } + + .pt-sm-1, + .py-sm-1 { + padding-top: 0.25rem !important; + } + + .pr-sm-1, + .px-sm-1 { + padding-right: 0.25rem !important; + } + + .pb-sm-1, + .py-sm-1 { + padding-bottom: 0.25rem !important; + } + + .pl-sm-1, + .px-sm-1 { + padding-left: 0.25rem !important; + } + + .p-sm-2 { + padding: 0.5rem !important; + } + + .pt-sm-2, + .py-sm-2 { + padding-top: 0.5rem !important; + } + + .pr-sm-2, + .px-sm-2 { + padding-right: 0.5rem !important; + } + + .pb-sm-2, + .py-sm-2 { + padding-bottom: 0.5rem !important; + } + + .pl-sm-2, + .px-sm-2 { + padding-left: 0.5rem !important; + } + + .p-sm-3 { + padding: 1rem !important; + } + + .pt-sm-3, + .py-sm-3 { + padding-top: 1rem !important; + } + + .pr-sm-3, + .px-sm-3 { + padding-right: 1rem !important; + } + + .pb-sm-3, + .py-sm-3 { + padding-bottom: 1rem !important; + } + + .pl-sm-3, + .px-sm-3 { + padding-left: 1rem !important; + } + + .p-sm-4 { + padding: 1.5rem !important; + } + + .pt-sm-4, + .py-sm-4 { + padding-top: 1.5rem !important; + } + + .pr-sm-4, + .px-sm-4 { + padding-right: 1.5rem !important; + } + + .pb-sm-4, + .py-sm-4 { + padding-bottom: 1.5rem !important; + } + + .pl-sm-4, + .px-sm-4 { + padding-left: 1.5rem !important; + } + + .p-sm-5 { + padding: 3rem !important; + } + + .pt-sm-5, + .py-sm-5 { + padding-top: 3rem !important; + } + + .pr-sm-5, + .px-sm-5 { + padding-right: 3rem !important; + } + + .pb-sm-5, + .py-sm-5 { + padding-bottom: 3rem !important; + } + + .pl-sm-5, + .px-sm-5 { + padding-left: 3rem !important; + } + + .m-sm-n1 { + margin: -0.25rem !important; + } + + .mt-sm-n1, + .my-sm-n1 { + margin-top: -0.25rem !important; + } + + .mr-sm-n1, + .mx-sm-n1 { + margin-right: -0.25rem !important; + } + + .mb-sm-n1, + .my-sm-n1 { + margin-bottom: -0.25rem !important; + } + + .ml-sm-n1, + .mx-sm-n1 { + margin-left: -0.25rem !important; + } + + .m-sm-n2 { + margin: -0.5rem !important; + } + + .mt-sm-n2, + .my-sm-n2 { + margin-top: -0.5rem !important; + } + + .mr-sm-n2, + .mx-sm-n2 { + margin-right: -0.5rem !important; + } + + .mb-sm-n2, + .my-sm-n2 { + margin-bottom: -0.5rem !important; + } + + .ml-sm-n2, + .mx-sm-n2 { + margin-left: -0.5rem !important; + } + + .m-sm-n3 { + margin: -1rem !important; + } + + .mt-sm-n3, + .my-sm-n3 { + margin-top: -1rem !important; + } + + .mr-sm-n3, + .mx-sm-n3 { + margin-right: -1rem !important; + } + + .mb-sm-n3, + .my-sm-n3 { + margin-bottom: -1rem !important; + } + + .ml-sm-n3, + .mx-sm-n3 { + margin-left: -1rem !important; + } + + .m-sm-n4 { + margin: -1.5rem !important; + } + + .mt-sm-n4, + .my-sm-n4 { + margin-top: -1.5rem !important; + } + + .mr-sm-n4, + .mx-sm-n4 { + margin-right: -1.5rem !important; + } + + .mb-sm-n4, + .my-sm-n4 { + margin-bottom: -1.5rem !important; + } + + .ml-sm-n4, + .mx-sm-n4 { + margin-left: -1.5rem !important; + } + + .m-sm-n5 { + margin: -3rem !important; + } + + .mt-sm-n5, + .my-sm-n5 { + margin-top: -3rem !important; + } + + .mr-sm-n5, + .mx-sm-n5 { + margin-right: -3rem !important; + } + + .mb-sm-n5, + .my-sm-n5 { + margin-bottom: -3rem !important; + } + + .ml-sm-n5, + .mx-sm-n5 { + margin-left: -3rem !important; + } + + .m-sm-auto { + margin: auto !important; + } + + .mt-sm-auto, + .my-sm-auto { + margin-top: auto !important; + } + + .mr-sm-auto, + .mx-sm-auto { + margin-right: auto !important; + } + + .mb-sm-auto, + .my-sm-auto { + margin-bottom: auto !important; + } + + .ml-sm-auto, + .mx-sm-auto { + margin-left: auto !important; + } +} + +@media (min-width: 768px) { + .m-md-0 { + margin: 0 !important; + } + + .mt-md-0, + .my-md-0 { + margin-top: 0 !important; + } + + .mr-md-0, + .mx-md-0 { + margin-right: 0 !important; + } + + .mb-md-0, + .my-md-0 { + margin-bottom: 0 !important; + } + + .ml-md-0, + .mx-md-0 { + margin-left: 0 !important; + } + + .m-md-1 { + margin: 0.25rem !important; + } + + .mt-md-1, + .my-md-1 { + margin-top: 0.25rem !important; + } + + .mr-md-1, + .mx-md-1 { + margin-right: 0.25rem !important; + } + + .mb-md-1, + .my-md-1 { + margin-bottom: 0.25rem !important; + } + + .ml-md-1, + .mx-md-1 { + margin-left: 0.25rem !important; + } + + .m-md-2 { + margin: 0.5rem !important; + } + + .mt-md-2, + .my-md-2 { + margin-top: 0.5rem !important; + } + + .mr-md-2, + .mx-md-2 { + margin-right: 0.5rem !important; + } + + .mb-md-2, + .my-md-2 { + margin-bottom: 0.5rem !important; + } + + .ml-md-2, + .mx-md-2 { + margin-left: 0.5rem !important; + } + + .m-md-3 { + margin: 1rem !important; + } + + .mt-md-3, + .my-md-3 { + margin-top: 1rem !important; + } + + .mr-md-3, + .mx-md-3 { + margin-right: 1rem !important; + } + + .mb-md-3, + .my-md-3 { + margin-bottom: 1rem !important; + } + + .ml-md-3, + .mx-md-3 { + margin-left: 1rem !important; + } + + .m-md-4 { + margin: 1.5rem !important; + } + + .mt-md-4, + .my-md-4 { + margin-top: 1.5rem !important; + } + + .mr-md-4, + .mx-md-4 { + margin-right: 1.5rem !important; + } + + .mb-md-4, + .my-md-4 { + margin-bottom: 1.5rem !important; + } + + .ml-md-4, + .mx-md-4 { + margin-left: 1.5rem !important; + } + + .m-md-5 { + margin: 3rem !important; + } + + .mt-md-5, + .my-md-5 { + margin-top: 3rem !important; + } + + .mr-md-5, + .mx-md-5 { + margin-right: 3rem !important; + } + + .mb-md-5, + .my-md-5 { + margin-bottom: 3rem !important; + } + + .ml-md-5, + .mx-md-5 { + margin-left: 3rem !important; + } + + .p-md-0 { + padding: 0 !important; + } + + .pt-md-0, + .py-md-0 { + padding-top: 0 !important; + } + + .pr-md-0, + .px-md-0 { + padding-right: 0 !important; + } + + .pb-md-0, + .py-md-0 { + padding-bottom: 0 !important; + } + + .pl-md-0, + .px-md-0 { + padding-left: 0 !important; + } + + .p-md-1 { + padding: 0.25rem !important; + } + + .pt-md-1, + .py-md-1 { + padding-top: 0.25rem !important; + } + + .pr-md-1, + .px-md-1 { + padding-right: 0.25rem !important; + } + + .pb-md-1, + .py-md-1 { + padding-bottom: 0.25rem !important; + } + + .pl-md-1, + .px-md-1 { + padding-left: 0.25rem !important; + } + + .p-md-2 { + padding: 0.5rem !important; + } + + .pt-md-2, + .py-md-2 { + padding-top: 0.5rem !important; + } + + .pr-md-2, + .px-md-2 { + padding-right: 0.5rem !important; + } + + .pb-md-2, + .py-md-2 { + padding-bottom: 0.5rem !important; + } + + .pl-md-2, + .px-md-2 { + padding-left: 0.5rem !important; + } + + .p-md-3 { + padding: 1rem !important; + } + + .pt-md-3, + .py-md-3 { + padding-top: 1rem !important; + } + + .pr-md-3, + .px-md-3 { + padding-right: 1rem !important; + } + + .pb-md-3, + .py-md-3 { + padding-bottom: 1rem !important; + } + + .pl-md-3, + .px-md-3 { + padding-left: 1rem !important; + } + + .p-md-4 { + padding: 1.5rem !important; + } + + .pt-md-4, + .py-md-4 { + padding-top: 1.5rem !important; + } + + .pr-md-4, + .px-md-4 { + padding-right: 1.5rem !important; + } + + .pb-md-4, + .py-md-4 { + padding-bottom: 1.5rem !important; + } + + .pl-md-4, + .px-md-4 { + padding-left: 1.5rem !important; + } + + .p-md-5 { + padding: 3rem !important; + } + + .pt-md-5, + .py-md-5 { + padding-top: 3rem !important; + } + + .pr-md-5, + .px-md-5 { + padding-right: 3rem !important; + } + + .pb-md-5, + .py-md-5 { + padding-bottom: 3rem !important; + } + + .pl-md-5, + .px-md-5 { + padding-left: 3rem !important; + } + + .m-md-n1 { + margin: -0.25rem !important; + } + + .mt-md-n1, + .my-md-n1 { + margin-top: -0.25rem !important; + } + + .mr-md-n1, + .mx-md-n1 { + margin-right: -0.25rem !important; + } + + .mb-md-n1, + .my-md-n1 { + margin-bottom: -0.25rem !important; + } + + .ml-md-n1, + .mx-md-n1 { + margin-left: -0.25rem !important; + } + + .m-md-n2 { + margin: -0.5rem !important; + } + + .mt-md-n2, + .my-md-n2 { + margin-top: -0.5rem !important; + } + + .mr-md-n2, + .mx-md-n2 { + margin-right: -0.5rem !important; + } + + .mb-md-n2, + .my-md-n2 { + margin-bottom: -0.5rem !important; + } + + .ml-md-n2, + .mx-md-n2 { + margin-left: -0.5rem !important; + } + + .m-md-n3 { + margin: -1rem !important; + } + + .mt-md-n3, + .my-md-n3 { + margin-top: -1rem !important; + } + + .mr-md-n3, + .mx-md-n3 { + margin-right: -1rem !important; + } + + .mb-md-n3, + .my-md-n3 { + margin-bottom: -1rem !important; + } + + .ml-md-n3, + .mx-md-n3 { + margin-left: -1rem !important; + } + + .m-md-n4 { + margin: -1.5rem !important; + } + + .mt-md-n4, + .my-md-n4 { + margin-top: -1.5rem !important; + } + + .mr-md-n4, + .mx-md-n4 { + margin-right: -1.5rem !important; + } + + .mb-md-n4, + .my-md-n4 { + margin-bottom: -1.5rem !important; + } + + .ml-md-n4, + .mx-md-n4 { + margin-left: -1.5rem !important; + } + + .m-md-n5 { + margin: -3rem !important; + } + + .mt-md-n5, + .my-md-n5 { + margin-top: -3rem !important; + } + + .mr-md-n5, + .mx-md-n5 { + margin-right: -3rem !important; + } + + .mb-md-n5, + .my-md-n5 { + margin-bottom: -3rem !important; + } + + .ml-md-n5, + .mx-md-n5 { + margin-left: -3rem !important; + } + + .m-md-auto { + margin: auto !important; + } + + .mt-md-auto, + .my-md-auto { + margin-top: auto !important; + } + + .mr-md-auto, + .mx-md-auto { + margin-right: auto !important; + } + + .mb-md-auto, + .my-md-auto { + margin-bottom: auto !important; + } + + .ml-md-auto, + .mx-md-auto { + margin-left: auto !important; + } +} + +@media (min-width: 992px) { + .m-lg-0 { + margin: 0 !important; + } + + .mt-lg-0, + .my-lg-0 { + margin-top: 0 !important; + } + + .mr-lg-0, + .mx-lg-0 { + margin-right: 0 !important; + } + + .mb-lg-0, + .my-lg-0 { + margin-bottom: 0 !important; + } + + .ml-lg-0, + .mx-lg-0 { + margin-left: 0 !important; + } + + .m-lg-1 { + margin: 0.25rem !important; + } + + .mt-lg-1, + .my-lg-1 { + margin-top: 0.25rem !important; + } + + .mr-lg-1, + .mx-lg-1 { + margin-right: 0.25rem !important; + } + + .mb-lg-1, + .my-lg-1 { + margin-bottom: 0.25rem !important; + } + + .ml-lg-1, + .mx-lg-1 { + margin-left: 0.25rem !important; + } + + .m-lg-2 { + margin: 0.5rem !important; + } + + .mt-lg-2, + .my-lg-2 { + margin-top: 0.5rem !important; + } + + .mr-lg-2, + .mx-lg-2 { + margin-right: 0.5rem !important; + } + + .mb-lg-2, + .my-lg-2 { + margin-bottom: 0.5rem !important; + } + + .ml-lg-2, + .mx-lg-2 { + margin-left: 0.5rem !important; + } + + .m-lg-3 { + margin: 1rem !important; + } + + .mt-lg-3, + .my-lg-3 { + margin-top: 1rem !important; + } + + .mr-lg-3, + .mx-lg-3 { + margin-right: 1rem !important; + } + + .mb-lg-3, + .my-lg-3 { + margin-bottom: 1rem !important; + } + + .ml-lg-3, + .mx-lg-3 { + margin-left: 1rem !important; + } + + .m-lg-4 { + margin: 1.5rem !important; + } + + .mt-lg-4, + .my-lg-4 { + margin-top: 1.5rem !important; + } + + .mr-lg-4, + .mx-lg-4 { + margin-right: 1.5rem !important; + } + + .mb-lg-4, + .my-lg-4 { + margin-bottom: 1.5rem !important; + } + + .ml-lg-4, + .mx-lg-4 { + margin-left: 1.5rem !important; + } + + .m-lg-5 { + margin: 3rem !important; + } + + .mt-lg-5, + .my-lg-5 { + margin-top: 3rem !important; + } + + .mr-lg-5, + .mx-lg-5 { + margin-right: 3rem !important; + } + + .mb-lg-5, + .my-lg-5 { + margin-bottom: 3rem !important; + } + + .ml-lg-5, + .mx-lg-5 { + margin-left: 3rem !important; + } + + .p-lg-0 { + padding: 0 !important; + } + + .pt-lg-0, + .py-lg-0 { + padding-top: 0 !important; + } + + .pr-lg-0, + .px-lg-0 { + padding-right: 0 !important; + } + + .pb-lg-0, + .py-lg-0 { + padding-bottom: 0 !important; + } + + .pl-lg-0, + .px-lg-0 { + padding-left: 0 !important; + } + + .p-lg-1 { + padding: 0.25rem !important; + } + + .pt-lg-1, + .py-lg-1 { + padding-top: 0.25rem !important; + } + + .pr-lg-1, + .px-lg-1 { + padding-right: 0.25rem !important; + } + + .pb-lg-1, + .py-lg-1 { + padding-bottom: 0.25rem !important; + } + + .pl-lg-1, + .px-lg-1 { + padding-left: 0.25rem !important; + } + + .p-lg-2 { + padding: 0.5rem !important; + } + + .pt-lg-2, + .py-lg-2 { + padding-top: 0.5rem !important; + } + + .pr-lg-2, + .px-lg-2 { + padding-right: 0.5rem !important; + } + + .pb-lg-2, + .py-lg-2 { + padding-bottom: 0.5rem !important; + } + + .pl-lg-2, + .px-lg-2 { + padding-left: 0.5rem !important; + } + + .p-lg-3 { + padding: 1rem !important; + } + + .pt-lg-3, + .py-lg-3 { + padding-top: 1rem !important; + } + + .pr-lg-3, + .px-lg-3 { + padding-right: 1rem !important; + } + + .pb-lg-3, + .py-lg-3 { + padding-bottom: 1rem !important; + } + + .pl-lg-3, + .px-lg-3 { + padding-left: 1rem !important; + } + + .p-lg-4 { + padding: 1.5rem !important; + } + + .pt-lg-4, + .py-lg-4 { + padding-top: 1.5rem !important; + } + + .pr-lg-4, + .px-lg-4 { + padding-right: 1.5rem !important; + } + + .pb-lg-4, + .py-lg-4 { + padding-bottom: 1.5rem !important; + } + + .pl-lg-4, + .px-lg-4 { + padding-left: 1.5rem !important; + } + + .p-lg-5 { + padding: 3rem !important; + } + + .pt-lg-5, + .py-lg-5 { + padding-top: 3rem !important; + } + + .pr-lg-5, + .px-lg-5 { + padding-right: 3rem !important; + } + + .pb-lg-5, + .py-lg-5 { + padding-bottom: 3rem !important; + } + + .pl-lg-5, + .px-lg-5 { + padding-left: 3rem !important; + } + + .m-lg-n1 { + margin: -0.25rem !important; + } + + .mt-lg-n1, + .my-lg-n1 { + margin-top: -0.25rem !important; + } + + .mr-lg-n1, + .mx-lg-n1 { + margin-right: -0.25rem !important; + } + + .mb-lg-n1, + .my-lg-n1 { + margin-bottom: -0.25rem !important; + } + + .ml-lg-n1, + .mx-lg-n1 { + margin-left: -0.25rem !important; + } + + .m-lg-n2 { + margin: -0.5rem !important; + } + + .mt-lg-n2, + .my-lg-n2 { + margin-top: -0.5rem !important; + } + + .mr-lg-n2, + .mx-lg-n2 { + margin-right: -0.5rem !important; + } + + .mb-lg-n2, + .my-lg-n2 { + margin-bottom: -0.5rem !important; + } + + .ml-lg-n2, + .mx-lg-n2 { + margin-left: -0.5rem !important; + } + + .m-lg-n3 { + margin: -1rem !important; + } + + .mt-lg-n3, + .my-lg-n3 { + margin-top: -1rem !important; + } + + .mr-lg-n3, + .mx-lg-n3 { + margin-right: -1rem !important; + } + + .mb-lg-n3, + .my-lg-n3 { + margin-bottom: -1rem !important; + } + + .ml-lg-n3, + .mx-lg-n3 { + margin-left: -1rem !important; + } + + .m-lg-n4 { + margin: -1.5rem !important; + } + + .mt-lg-n4, + .my-lg-n4 { + margin-top: -1.5rem !important; + } + + .mr-lg-n4, + .mx-lg-n4 { + margin-right: -1.5rem !important; + } + + .mb-lg-n4, + .my-lg-n4 { + margin-bottom: -1.5rem !important; + } + + .ml-lg-n4, + .mx-lg-n4 { + margin-left: -1.5rem !important; + } + + .m-lg-n5 { + margin: -3rem !important; + } + + .mt-lg-n5, + .my-lg-n5 { + margin-top: -3rem !important; + } + + .mr-lg-n5, + .mx-lg-n5 { + margin-right: -3rem !important; + } + + .mb-lg-n5, + .my-lg-n5 { + margin-bottom: -3rem !important; + } + + .ml-lg-n5, + .mx-lg-n5 { + margin-left: -3rem !important; + } + + .m-lg-auto { + margin: auto !important; + } + + .mt-lg-auto, + .my-lg-auto { + margin-top: auto !important; + } + + .mr-lg-auto, + .mx-lg-auto { + margin-right: auto !important; + } + + .mb-lg-auto, + .my-lg-auto { + margin-bottom: auto !important; + } + + .ml-lg-auto, + .mx-lg-auto { + margin-left: auto !important; + } +} + +@media (min-width: 1200px) { + .m-xl-0 { + margin: 0 !important; + } + + .mt-xl-0, + .my-xl-0 { + margin-top: 0 !important; + } + + .mr-xl-0, + .mx-xl-0 { + margin-right: 0 !important; + } + + .mb-xl-0, + .my-xl-0 { + margin-bottom: 0 !important; + } + + .ml-xl-0, + .mx-xl-0 { + margin-left: 0 !important; + } + + .m-xl-1 { + margin: 0.25rem !important; + } + + .mt-xl-1, + .my-xl-1 { + margin-top: 0.25rem !important; + } + + .mr-xl-1, + .mx-xl-1 { + margin-right: 0.25rem !important; + } + + .mb-xl-1, + .my-xl-1 { + margin-bottom: 0.25rem !important; + } + + .ml-xl-1, + .mx-xl-1 { + margin-left: 0.25rem !important; + } + + .m-xl-2 { + margin: 0.5rem !important; + } + + .mt-xl-2, + .my-xl-2 { + margin-top: 0.5rem !important; + } + + .mr-xl-2, + .mx-xl-2 { + margin-right: 0.5rem !important; + } + + .mb-xl-2, + .my-xl-2 { + margin-bottom: 0.5rem !important; + } + + .ml-xl-2, + .mx-xl-2 { + margin-left: 0.5rem !important; + } + + .m-xl-3 { + margin: 1rem !important; + } + + .mt-xl-3, + .my-xl-3 { + margin-top: 1rem !important; + } + + .mr-xl-3, + .mx-xl-3 { + margin-right: 1rem !important; + } + + .mb-xl-3, + .my-xl-3 { + margin-bottom: 1rem !important; + } + + .ml-xl-3, + .mx-xl-3 { + margin-left: 1rem !important; + } + + .m-xl-4 { + margin: 1.5rem !important; + } + + .mt-xl-4, + .my-xl-4 { + margin-top: 1.5rem !important; + } + + .mr-xl-4, + .mx-xl-4 { + margin-right: 1.5rem !important; + } + + .mb-xl-4, + .my-xl-4 { + margin-bottom: 1.5rem !important; + } + + .ml-xl-4, + .mx-xl-4 { + margin-left: 1.5rem !important; + } + + .m-xl-5 { + margin: 3rem !important; + } + + .mt-xl-5, + .my-xl-5 { + margin-top: 3rem !important; + } + + .mr-xl-5, + .mx-xl-5 { + margin-right: 3rem !important; + } + + .mb-xl-5, + .my-xl-5 { + margin-bottom: 3rem !important; + } + + .ml-xl-5, + .mx-xl-5 { + margin-left: 3rem !important; + } + + .p-xl-0 { + padding: 0 !important; + } + + .pt-xl-0, + .py-xl-0 { + padding-top: 0 !important; + } + + .pr-xl-0, + .px-xl-0 { + padding-right: 0 !important; + } + + .pb-xl-0, + .py-xl-0 { + padding-bottom: 0 !important; + } + + .pl-xl-0, + .px-xl-0 { + padding-left: 0 !important; + } + + .p-xl-1 { + padding: 0.25rem !important; + } + + .pt-xl-1, + .py-xl-1 { + padding-top: 0.25rem !important; + } + + .pr-xl-1, + .px-xl-1 { + padding-right: 0.25rem !important; + } + + .pb-xl-1, + .py-xl-1 { + padding-bottom: 0.25rem !important; + } + + .pl-xl-1, + .px-xl-1 { + padding-left: 0.25rem !important; + } + + .p-xl-2 { + padding: 0.5rem !important; + } + + .pt-xl-2, + .py-xl-2 { + padding-top: 0.5rem !important; + } + + .pr-xl-2, + .px-xl-2 { + padding-right: 0.5rem !important; + } + + .pb-xl-2, + .py-xl-2 { + padding-bottom: 0.5rem !important; + } + + .pl-xl-2, + .px-xl-2 { + padding-left: 0.5rem !important; + } + + .p-xl-3 { + padding: 1rem !important; + } + + .pt-xl-3, + .py-xl-3 { + padding-top: 1rem !important; + } + + .pr-xl-3, + .px-xl-3 { + padding-right: 1rem !important; + } + + .pb-xl-3, + .py-xl-3 { + padding-bottom: 1rem !important; + } + + .pl-xl-3, + .px-xl-3 { + padding-left: 1rem !important; + } + + .p-xl-4 { + padding: 1.5rem !important; + } + + .pt-xl-4, + .py-xl-4 { + padding-top: 1.5rem !important; + } + + .pr-xl-4, + .px-xl-4 { + padding-right: 1.5rem !important; + } + + .pb-xl-4, + .py-xl-4 { + padding-bottom: 1.5rem !important; + } + + .pl-xl-4, + .px-xl-4 { + padding-left: 1.5rem !important; + } + + .p-xl-5 { + padding: 3rem !important; + } + + .pt-xl-5, + .py-xl-5 { + padding-top: 3rem !important; + } + + .pr-xl-5, + .px-xl-5 { + padding-right: 3rem !important; + } + + .pb-xl-5, + .py-xl-5 { + padding-bottom: 3rem !important; + } + + .pl-xl-5, + .px-xl-5 { + padding-left: 3rem !important; + } + + .m-xl-n1 { + margin: -0.25rem !important; + } + + .mt-xl-n1, + .my-xl-n1 { + margin-top: -0.25rem !important; + } + + .mr-xl-n1, + .mx-xl-n1 { + margin-right: -0.25rem !important; + } + + .mb-xl-n1, + .my-xl-n1 { + margin-bottom: -0.25rem !important; + } + + .ml-xl-n1, + .mx-xl-n1 { + margin-left: -0.25rem !important; + } + + .m-xl-n2 { + margin: -0.5rem !important; + } + + .mt-xl-n2, + .my-xl-n2 { + margin-top: -0.5rem !important; + } + + .mr-xl-n2, + .mx-xl-n2 { + margin-right: -0.5rem !important; + } + + .mb-xl-n2, + .my-xl-n2 { + margin-bottom: -0.5rem !important; + } + + .ml-xl-n2, + .mx-xl-n2 { + margin-left: -0.5rem !important; + } + + .m-xl-n3 { + margin: -1rem !important; + } + + .mt-xl-n3, + .my-xl-n3 { + margin-top: -1rem !important; + } + + .mr-xl-n3, + .mx-xl-n3 { + margin-right: -1rem !important; + } + + .mb-xl-n3, + .my-xl-n3 { + margin-bottom: -1rem !important; + } + + .ml-xl-n3, + .mx-xl-n3 { + margin-left: -1rem !important; + } + + .m-xl-n4 { + margin: -1.5rem !important; + } + + .mt-xl-n4, + .my-xl-n4 { + margin-top: -1.5rem !important; + } + + .mr-xl-n4, + .mx-xl-n4 { + margin-right: -1.5rem !important; + } + + .mb-xl-n4, + .my-xl-n4 { + margin-bottom: -1.5rem !important; + } + + .ml-xl-n4, + .mx-xl-n4 { + margin-left: -1.5rem !important; + } + + .m-xl-n5 { + margin: -3rem !important; + } + + .mt-xl-n5, + .my-xl-n5 { + margin-top: -3rem !important; + } + + .mr-xl-n5, + .mx-xl-n5 { + margin-right: -3rem !important; + } + + .mb-xl-n5, + .my-xl-n5 { + margin-bottom: -3rem !important; + } + + .ml-xl-n5, + .mx-xl-n5 { + margin-left: -3rem !important; + } + + .m-xl-auto { + margin: auto !important; + } + + .mt-xl-auto, + .my-xl-auto { + margin-top: auto !important; + } + + .mr-xl-auto, + .mx-xl-auto { + margin-right: auto !important; + } + + .mb-xl-auto, + .my-xl-auto { + margin-bottom: auto !important; + } + + .ml-xl-auto, + .mx-xl-auto { + margin-left: auto !important; + } +} + +.stretched-link::after { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1; + pointer-events: auto; + content: ''; + background-color: rgba(0, 0, 0, 0); +} + +.text-monospace { + font-family: SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace !important; +} + +.text-justify { + text-align: justify !important; +} + +.text-wrap { + white-space: normal !important; +} + +.text-nowrap { + white-space: nowrap !important; +} + +.text-truncate { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.text-left { + text-align: left !important; +} + +.text-right { + text-align: right !important; +} + +.text-center { + text-align: center !important; +} + +@media (min-width: 576px) { + .text-sm-left { + text-align: left !important; + } + + .text-sm-right { + text-align: right !important; + } + + .text-sm-center { + text-align: center !important; + } +} + +@media (min-width: 768px) { + .text-md-left { + text-align: left !important; + } + + .text-md-right { + text-align: right !important; + } + + .text-md-center { + text-align: center !important; + } +} + +@media (min-width: 992px) { + .text-lg-left { + text-align: left !important; + } + + .text-lg-right { + text-align: right !important; + } + + .text-lg-center { + text-align: center !important; + } +} + +@media (min-width: 1200px) { + .text-xl-left { + text-align: left !important; + } + + .text-xl-right { + text-align: right !important; + } + + .text-xl-center { + text-align: center !important; + } +} + +.text-lowercase { + text-transform: lowercase !important; +} + +.text-uppercase { + text-transform: uppercase !important; +} + +.text-capitalize { + text-transform: capitalize !important; +} + +.font-weight-light { + font-weight: 300 !important; +} + +.font-weight-lighter { + font-weight: lighter !important; +} + +.font-weight-normal { + font-weight: 400 !important; +} + +.font-weight-bold { + font-weight: 700 !important; +} + +.font-weight-bolder { + font-weight: bolder !important; +} + +.font-italic { + font-style: italic !important; +} + +.text-white { + color: #fff !important; +} + +.text-primary { + color: #07819b !important; +} + +a.text-primary:hover, +a.text-primary:focus { + color: #044452 !important; +} + +.text-secondary { + color: #313032 !important; +} + +a.text-secondary:hover, +a.text-secondary:focus { + color: #0b0b0b !important; +} + +.text-success { + color: #28a745 !important; +} + +a.text-success:hover, +a.text-success:focus { + color: #19692c !important; +} + +.text-info { + color: #17a2b8 !important; +} + +a.text-info:hover, +a.text-info:focus { + color: #0f6674 !important; +} + +.text-warning { + color: #ffc107 !important; +} + +a.text-warning:hover, +a.text-warning:focus { + color: #ba8b00 !important; +} + +.text-danger { + color: #dc3545 !important; +} + +a.text-danger:hover, +a.text-danger:focus { + color: #a71d2a !important; +} + +.text-light { + color: #f8f9fa !important; +} + +a.text-light:hover, +a.text-light:focus { + color: #cbd3da !important; +} + +.text-dark { + color: #343a40 !important; +} + +a.text-dark:hover, +a.text-dark:focus { + color: #121416 !important; +} + +.text-body { + color: #212529 !important; +} + +.text-muted { + color: #313032 !important; +} + +.text-black-50 { + color: rgba(0, 0, 0, 0.5) !important; +} + +.text-white-50 { + color: rgba(255, 255, 255, 0.5) !important; +} + +.text-hide { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} + +.text-decoration-none { + text-decoration: none !important; +} + +.text-break { + word-wrap: break-word !important; +} + +.text-reset { + color: inherit !important; +} + +.visible { + visibility: visible !important; +} + +.invisible { + visibility: hidden !important; +} + +@media print { + *, + *::before, + *::after { + text-shadow: none !important; + box-shadow: none !important; + } + + a:not(.btn) { + text-decoration: underline; + } + + abbr[title]::after { + content: ' (' attr(title) ')'; + } + + pre { + white-space: pre-wrap !important; + } + + pre, + blockquote { + border: 1px solid #adb5bd; + page-break-inside: avoid; + } + + thead { + display: table-header-group; + } + + tr, + img { + page-break-inside: avoid; + } + + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + + h2, + h3 { + page-break-after: avoid; + } + + @page { + size: a3; + } + + body { + min-width: 992px !important; + } + + .container { + min-width: 992px !important; + } + + .navbar { + display: none; + } + + .badge { + border: 1px solid #000; + } + + .table { + border-collapse: collapse !important; + } + + .table td, + .table th { + background-color: #fff !important; + } + + .table-bordered th, + .table-bordered td { + border: 1px solid #dee2e6 !important; + } + + .table-dark { + color: inherit; + } + + .table-dark th, + .table-dark td, + .table-dark thead th, + .table-dark tbody + tbody { + border-color: #dee2e6; + } + + .table .thead-dark th { + color: inherit; + border-color: #dee2e6; + } +} + +/** + * Styles for specific components of the portal + */ +.fixed-bottom { + background-color: #313032; +} diff --git a/src/assets/fonts/bootstrap-icons.woff b/src/assets/fonts/bootstrap-icons.woff Binary files differnew file mode 100644 index 0000000..8cd8946 --- /dev/null +++ b/src/assets/fonts/bootstrap-icons.woff diff --git a/src/assets/fonts/bootstrap-icons.woff2 b/src/assets/fonts/bootstrap-icons.woff2 Binary files differnew file mode 100644 index 0000000..3e587fd --- /dev/null +++ b/src/assets/fonts/bootstrap-icons.woff2 diff --git a/src/assets/i18n/de.json b/src/assets/i18n/de.json new file mode 100644 index 0000000..1b06ded --- /dev/null +++ b/src/assets/i18n/de.json @@ -0,0 +1,355 @@ +{ + "common": { + "loading": "Lädt...", + "required": "Erforderlich", + "buttons": { + "cancel": "Abbrechen", + "clear": "Clear", + "close": "Schließen", + "collapse": "Einklappen", + "delete": "Löschen", + "notPossibleDelete": "Es ist nicht möglich, den eigenen Account zu löschen.", + "edit": "Bearbeiten", + "expand": "Ausklappen", + "filter": "Filtern", + "info": "Info", + "next": "Weiter", + "previous": "Zurück", + "refresh": "Refresh", + "rightClick": "Öffne das Kontextmenü", + "save": "Speichern", + "search": "Suchen", + "set": "Speichern", + "reset": "Reset", + "submit": "Senden", + "openSupportLink": "Support link ausklappen", + "closeSupportLink": "Support link einklappen" + }, + "dateFilter": { + "startDate": "Startdatum auswählen", + "endDate": "Enddatum auswählen" + }, + "filters": { + "filterBy": "Filtern nach {{value}}", + "noResults": "Keine Daten verfügbar.", + "noResultsForCustomer": "Keine Daten für den Kunden verfügbar: {{customerId}}", + "noOptions": "Keine Aktion möglich.", + "searchHint": "Suchbegriffe eingeben", + "showCategories": "Menü zum filtern nach Kategorien anzeigen", + "noFilterResults": "Keine Übereinstimmung mit den angegebenen Filterkriterien." + }, + "no": "Nein", + "pagination": { + "itemsPerPage": "{{value}} Einträge pro Seite", + "totalCount": "Gesamtanzahl: {{value}}", + "selectItemsPerPage": "Wähle Anzahl der Elemente pro Seite" + }, + "sorting": { + "ascending:": "Aufsteigend sortiert", + "descending": "Absteigend sortiert", + "none": "Keine Sortierung" + }, + "select": { + "description": "Selektier die Anzahl der Items pro Seite", + "itemsPerPage": "{{value}} Einträge pro Seite", + "openOptions": "Optionen öffnen", + "closeOptions": "Optionen schließen", + "selectOption": "Option auswählen" + }, + "hint": "Hinweis", + "warning": "Warnung", + "yes": "Ja", + "messages": { + "badRequest": "Bad request: Der Server kann ihre Anfrage nicht verarbeiten.", + "unauthorized": "Sie sind nicht authorisiert. Bitte loggen sie sich ein.", + "forbidden": "Sie haben keine oder nur unzureichende Berechtigungen.", + "notFound": "Die angeforderten Ressourcen konnten nicht gefunden werden.", + "conflict": "Ihre Anfrage steht im Konflikt zu einer anderen Anfrage.", + "internalServerError": "Internal Server Error: Bitte kontaktieren Sie den Support.", + "badGateway": "Überprüfen Sie ihre Proxy-Einstellungen.", + "serviceUnavailable": "Der Service ist zur Zeit nicht verfügbar. Bitte kontaktieren Sie die System-Administratoren.", + "checkRequest": "Überprüfen Sie den Request.", + "actionUnsuccessful": "Die Aktion konnte nicht durchgeführt werden, bitte probieren Sie es erneut.", + "contactSupport": "Bitte, kontaktieren Sie das Support Team.", + "timeout": "Ressource ist nicht erreichbar.", + "keycloakAccessTokenNotValid": "Die Gültigkeit Ihres Zugangstokens ist aufgrund von Verbindungsproblemen abgelaufen. Bitte laden sie erneut die Seite. Falls das Problem weiterhin besteht, wenden Sie sich an den Support." + }, + "systems": { + "AAI": "AAI", + "CDS": "CDS", + "KUBERNETES": "Kubernetes", + "KEYCLOAK": "Keycloak", + "PORTAL_SERVICE": "Portal Service", + "SDC": "SDC", + "SO": "SO", + "SO_CATALOG": "SO Catalog", + "PORTAL_HISTORY": "Portal History", + "PORTAL_PREFS": "Portal Preferences" + }, + "block": { + "userAdministration": { + "create": "Beim Anlegen des Benutzerkontos ist ein Fehler aufgetreten!", + "edit": "Beim Bearbeiten des Benutzerkontos ist ein Fehler aufgetreten!", + "list": "Die Benutzerlist kann wegen eines Fehlers nicht angezeigt werden!", + "delete": "Der Benutzer kann wegen eines Fehlers nicht gelöscht werden!", + "helpUserNameExists": "Versuchen Sie bitte den Benutzer mit einer anderen Benutzername anzulegen.", + "helpUserEmailExists": "Versuchen Sie bitte den Benutzer mit einer anderen E-mail Adresse anzulegen." + }, + "defaultMessage": "Systemfehler aufgetreten!", + "logging": "Warnung, Logging ist fehlgeschlagen! Keine weitere Aktion notwendig! ", + "dashboard": "Systemfehler, Anzeigen des Dashboard nicht möglich!", + "appStarter": "Systemfehler, Anzeigen der Applikationen nicht möglich!", + "authorization": "Fehler bei der Autorisierung!", + "loadPreferences": "Beim Laden der Benutzereinstellungen ist ein Fehler aufgetreten!", + "savePreferences": "Beim Speichern der Benutzereinstellungen ist ein Fehler aufgetreten!", + "saveAction": "Beim Speichern der letzten Benutzeraktion ist ein Fehler aufgetreten!", + "loadAction": "Beim Laden der letzten Benutzeraktion ist ein Fehler aufgetreten!", + "timeout": "Timeout ist nach {{value}} Sekunden aufgetreten!" + }, + "alert": { + "contactSupport": { + "part1": "Für Hilfe kontaktieren Sie bitte unseren ", + "part2": " und geben Sie alle Informationen einschließlich dieser ID an:" + }, + "errorReporter": "Fehlermeldung von \"{{system}}\" System:", + "support": "Support" + }, + "noPermissions": { + "noPermissions": "Sie haben nicht genügend Berechtigungen um diese Seite zu sehen!", + "support": "Wenn Sie glauben, dies ist ein Fehler, kontaktieren Sie bitte den Support." + }, + "form": { + "feedback": { + "emailWrongFormat": "Falsches Email Format", + "invalidCharacters": "Ungültige Zeichen", + "invalidConfirmationPassword": "Passworte stimmen nicht überein", + "required": "Darf nicht leer sein", + "whiteSpaceNotAllowed": "Leerzeichen sind nicht erlaubt", + "specialCharactersNotAllowed": "Sonderzeichen sind nicht erlaubt." + } + } + }, + "appStarter": { + "groups": { + "admin": "Admin", + "developer": "Developer", + "operator": "Operator" + }, + "title": "App Starter", + "tiles": { + "tooltips": { + "enum": { + "1": "SDC ist das visuelle Modellierungs- und Designtool von ONAP. Es erstellt interne Metadaten, die Assets beschreiben, die von allen ONAP-Komponenten verwendet werden, sowohl zur Entwurfszeit als auch zur Laufzeit.", + "2": "VID bietet eine gut strukturierte Organisation von Infrastrukturbereitstellung, Instanziierung und Change Management, die von Operations verwendet werden, um Orchestrierungen und Change Management abzuleiten.", + "3": "Das ONAP Policy Framework legt die Architektur des Frameworks dar und zeigt die APIs, die anderen Komponenten bereitgestellt werden, die mit dem Framework zusammenarbeiten.", + "4": "Der ONAP Service Orchestrator bietet die höchste Ebene der Service-Orchestrierung in der ONAP-Architektur.", + "5": "CLAMP ist eine Plattform zum Entwerfen und Verwalten sogenannter Control Loops. Es wird verwendet, um geschlossene Schleifen (Closed Loops) zu entwerfen, diese mit spezifischen Parametern für einen bestimmten Netzwerkdienst zu konfigurieren und sie dann in Betrieb und außer Betrieb zu nehmen.", + "6": "Kibana Dashboard zur Visualisierung der von Control Loops ausgelösten Ereignisse (wird auch in ONAP für die Alarmvisualisierung verwendet).", + "7": "Die CDS Designer Benutzeroberfläche ist ein Framework zur Automatisierung der Auflösung von Ressourcen für die Instanziierung und aller Konfigurationsbereitstellung, wie z. B. die Konfiguration von Day0, Day1 oder Day2.", + "8": "CDT ermöglicht das Self-Service-Onboarding von VNFs durch das Erstellen von Templates und anderen Artefakten. Dies kann zum Beispiel für den Configure-Befehl im APPC verwendet werden um Konfigurationen nach der Instanziierung anzupassen.", + "9": "Das Holmes-Projekt bietet Alarmkorrelation und -analyse für Telekommunikations-Cloudinfrastruktur und -Dienste, einschließlich Hosts, Vims, VNFs und NSs.", + "10": "AAI ist eine Komponente der ONAP-Laufzeit (Echtzeitansichten von Ressourcen, Services, Produkten, Kundenabonnements und deren Beziehungen).", + "11": "DCAE ist der Obername für eine Reihe von Komponenten, die gemeinsam die Rolle der Datenerfassung, Analyse und Ereignisgenerierung für ONAP erfüllen. Die Architektur von DCAE zielt auf eine flexible, steckbare, Micros-Service-orientierte, modellbasierte Komponentenbereitstellung und Servicezusammensetzung ab. DCAE unterstützt auch Sammel- und Analysevorgänge an mehreren Standorten, die für große ONAP-Bereitstellungen unerlässlich sind.", + "12": "SDNC DG soll eine Ausführungsumgebung für schnell geschriebene und hochgradig angepasste Serviceabläufe bereitstellen.", + "13": "Das OpenDaylight Project ist ein kollaboratives Open-Source-Projekt, das von der Linux Foundation gehostet wird. Das Projekt dient als Plattform für Software-Defined Networking (SDN) zur offenen, zentralisierten Überwachung von Netzwerkgeräten." + } + } + } + }, + "dashboard": { + "apps": { + "userLastAction": { + "filter": { + "label": "Letzte Aktivitäten filtern nach: ", + "type": { + "ALL": "Alle meine Aktivitäten", + "SEARCH": "Meine Suchen", + "ACTION": "Meine Handlungen" + }, + "interval": { + "1H": "Letzte 1 Stunde", + "4H": "Letzten 4 Stunden", + "1D": "Letzten 1 Tage", + "ALL": "Alle" + } + }, + "actionType": { + "SEARCH": "Suche", + "VIEW": "Ansehen", + "EDIT": "Bearbeiten", + "DEPLOY": "Deploy", + "DELETE": "Löschen", + "CREATE": "Erstellen", + "CLEAR": "Clear", + "ACK": "Acknowledge", + "UNACK": "Unacknowledge" + }, + "entityType": { + "ALARM": "Alarm", + "USERADMINISTRATION": "Benutzeradministration", + "SERVICEMODEL": "Servicemodell", + "SERVICEINSTANCE": "Serviceinstanz", + "TOPOLOGY": "Topologie" + }, + "tooltip": { + "again": "wieder", + "statusOf": "Status von", + "noAction": "Vorerst keine Aktion.", + "repeatAction": "Letzte Aktion wiederholen", + "viewAction": "Letzte Aktion anzeigen", + "deployment": "deployment" + }, + "modal": { + "deploymentStatus": "Deployment Status", + "state": "State", + "progress": "Progress", + "flowStatus": "Flow Status", + "rollbackStatus": "Rollback Status", + "retryStatus": "Retry Status", + "taskInformation": "Task Information" + } + }, + "KPI_GRAPH_TILE": "KPI Grafen", + "ALARM_COUNT_TILE": "Anzahl Alarme", + "USER_LAST_ACTION_TILE": "Letzte Benutzeraktionen" + }, + "showSettings": "Konfigurieren Sie, welche Anwendungen im Dashboard sichtbar sein sollen", + "selectApplications": "Bitte wählen Sie Anwendungen aus, die Sie im Dashboard sehen möchten", + "tooltips": { + "settings": "Dashboard-Einstellungen anzeigen" + } + }, + "layout": { + "header": { + "header": "Kopfleiste/Header", + "skipToMainContentLink": "Zum Hauptinhalt springen", + "button": { + "account": "Kontoeinstellungen", + "closeFullscreen": "Vollbildmodus schließen", + "logout": "Abmelden", + "openFullscreen": "Vollbildmodus öffnen", + "useraccount": "Mein Account" + }, + "info": { + "mail": "Email:", + "name": "Name:" + }, + "logo": { + "onap": "ONAP Logo" + }, + "sidebarToggler": "Öffne/schliesse Seitenmenü", + "shortcuts": { + "details": "Informationen zu den Tastaturkürzeln", + "home": "Home (Kopfbereich)", + "main": "Setzt den Fokus auf den Inhaltsanteil der Seite", + "search": "Setz den Fokus auf das Suchfeld, wenn auf Seite vorhanden", + "menu": "Setzt Fokus auf das Hauptmenü links", + "heading": "Tastaturkurzbefehle", + "helpText": "Tastaturkurzbefehle werden vom Portal unterstützt. Die Mechanismen variieren zwischen den Browsern:", + "helpBrowser1": "<b>ALT</b> gedrückt halten und die <b>Taste</b> drücken für <b>Google Chrome, Microsoft, Safari</b>", + "helpBrowser2": "<b>ALT</b> und <b>Umschalten</b> gedrückt halten und die <b>Taste</b> drücken für <b>Firefox</b>", + "helpBroswer3": "<b>MACINTOSH Safari: CTRL</b> Taste gedrückt halten und die <b>Taste</b> drücken" + } + }, + "main": { + "alerts": "Alarmmeldungen", + "mainContent": "Hauptinhalt", + "breadcrumb": "Breadcrumb/Brotkrumen" + }, + "sidebar": "Seitenleiste", + "menu": { + "mainMenu": "Hauptmenü", + "menuItems": "Menü Items", + "items": { + "cellSiteMap": "Mobilfunk-Karte", + "home": "Home", + "appStarter": "App Starter", + "dashboard": "Dashboard", + "options": "Optionen", + "userAdministration": "Benutzerverwaltung", + "users": "Benutzer", + "userSettings": "Benutzereinstellungen" + } + } + }, + "modal": { + "error": { + "accessDenied": "Keine Berechtigung!", + "details": "Details:" + } + }, + "userAdministration": { + "buttons": { + "createUser": "Benutzer anlegen", + "editUser": "Benutzer bearbeiten" + }, + "fields": { + "access": "Zugang", + "actions": "Aktionen", + "assignedRoles": "Zugewiesene Rollen", + "attributes": "Eigenschaften", + "confirmPassword": "Passwort bestätigen", + "createdAt": "Angelegt am", + "disableableCredentialTypes": "Berechtigungsnachweise deaktivieren", + "email": "Email", + "emailVerified": "Email geprüft", + "enabled": "Aktiviert", + "firstName": "Vorname", + "id": "ID", + "key": "Schlüssel", + "lastName": "Nachname", + "password": "Passwort", + "requiredActions": "Erforderliche Aktionen", + "temporaryPassword": "Temporäres Passwort", + "userName": "Benutzer", + "value": "Wert" + }, + "form": { + "headings": { + "setNewPassword": "Neues Passwort setzen", + "setRoles": { + "assigned": "Zugewiesen", + "available": "Verfügbar", + "title": "Rollen zuweisen" + }, + "setUserData": "Benutzerdaten einstellen" + }, + "title": { + "changePassword": "Passwort ändern", + "changePasswordTooltip": "Um Ihr Passwort zu ändern, loggen Sie sich bitte aus und benutzen Sie den Link \"Passwort vergessen?\".", + "create": "Benutzer anlegen", + "edit": "Benutzer bearbeiten", + "roles": "Rollen" + } + }, + "list": { + "modal": { + "delete": { + "title": "Lösche Benutzer", + "text": "Möchtest Du den Benutzer: {{userName}} wirklich löschen?" + } + }, + "tableCaption": "Benutzertabelle", + "title": "Benutzerverwaltung" + }, + "messages": { + "success": { + "created": "Benutzer erfolgreich angelegt.", + "deleted": "Benutzer erfolgreich gelöscht.", + "setPassword": "Password erfolgreich geändert.", + "updated": "Benutzer erfolgreich aktualisiert." + } + }, + "warnings": { + "userDeleted": { + "header": "Benutzer existiert nicht mehr", + "message": "Eine Bearbeitung des Benutzers ist nicht möglich. Benutzer wurde bereits gelöscht." + } + } + }, + "pageNotFound": { + "text": "Die gesuchte Seite konnte nicht gefunden werden.", + "button": "Zurück zur Hauptseite", + "imgAltText": "Bild einer fragenden Frau" + } +} diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json new file mode 100644 index 0000000..350137d --- /dev/null +++ b/src/assets/i18n/en.json @@ -0,0 +1,351 @@ +{ + "common": { + "loading": "Loading...", + "required": "Required", + "buttons": { + "cancel": "Cancel", + "clear": "Clear", + "close": "Close", + "collapse": "Collapse", + "delete": "Delete", + "notPossibleDelete": "It is not possible to delete your own account.", + "edit": "Edit", + "expand": "Expand", + "filter": "Filter", + "info": "Info", + "next": "Next", + "previous": "Previous", + "refresh": "Refresh", + "rightClick": "Open the right-click context menu", + "save": "Save", + "search": "Search", + "set": "Set", + "reset": "Reset", + "submit": "Submit", + "openSupportLink": "Expand support link", + "closeSupportLink": "Collapse support link" + }, + "dateFilter": { + "startDate": "Select start date", + "endDate": "Select end date" + }, + "filters": { + "filterBy": "Filter by {{value}}", + "noResults": "No data available.", + "noResultsForCustomer": "No data available for customer: {{customerId}}", + "noOptions": "No action possible.", + "searchHint": "Enter Search Terms", + "showCategories": "Show menu to filter by categories", + "noFilterResults": "No match to the given filter criteria." + }, + "no": "No", + "pagination": { + "itemsPerPage": "{{value}} items per page", + "totalCount": "Total Count: {{value}}", + "selectItemsPerPage": "Select items per page" + }, + "yes": "Yes", + "sorting": { + "ascending": "Sorted Ascending", + "descending": "Sorted Descending", + "none": "No Sorting" + }, + "select": { + "description": "Select number of items per page", + "itemsPerPage": "{{value}} items per page", + "openOptions": "Open Options", + "closeOptions": "Close Options", + "selectOption": "Select Option" + }, + "hint": "Hint", + "warning": "Warning", + "messages": { + "badRequest": "Bad request: The server cannot process your request.", + "unauthorized": "You are not authorized. Please log in first.", + "forbidden": "You have no or limited permissions.", + "notFound": "Requested information not found.", + "conflict": "Your request has a conflict with resource.", + "internalServerError": "Internal Server Error: Please contact the support team.", + "badGateway": "Check your proxy settings.", + "serviceUnavailable": "Please, contact server administrators team.", + "checkRequest": "Check your requests.", + "actionUnsuccessful": "Action unsuccessful, try again later.", + "contactSupport": "Please, contact our support team.", + "timeout": "Resource is not reachable.", + "keycloakAccessTokenNotValid": "Your access token validity expired due to connection issues. Please try to reload a page and in case issue persists, contact support" + }, + "systems": { + "AAI": "AAI", + "CDS": "CDS", + "KUBERNETES": "Kubernetes", + "KEYCLOAK": "Keycloak", + "PORTAL_SERVICE": "Portal Service", + "SDC": "SDC", + "SO": "SO", + "SO_CATALOG": "SO Catalog", + "PORTAL_HISTORY": "Portal History", + "PORTAL_PREFS": "Portal Preferences" + }, + "block": { + "userAdministration": { + "create": "Error while creating user account!", + "edit": "Error, changing user account failed!", + "list": "System error, not able to display user accounts!", + "delete": "Error while trying to delete user account!", + "helpUserNameExists": "Please, try to create user with different username.", + "helpUserEmailExists": "Please, try to create user with different email address." + }, + "defaultMessage": "A System error occurred!", + "logging": "Warning, internal logging failed! No further action required! ", + "dashboard": "System error while trying to load data for displaying tiles on the dashboard!", + "appStarter": "System error while trying to display app starter!", + "authorization": "Error during authorization!", + "loadPreferences": "System error while trying to load user preferences!", + "savePreferences": "System error while trying to save user preferences!", + "saveAction": "System error while trying to save user action!", + "loadAction": "System error while trying to load user actions!", + "timeout": "Timeout has occurred after {{value}} seconds!" + }, + "alert": { + "contactSupport": { + "part1": "For help please contact our ", + "part2": " and provide all information including this ID:" + }, + "errorReporter": "Error reported by \"{{system}}\" system:", + "support": "Support" + }, + "noPermissions": { + "noPermissions": "You don't have enough permissions for viewing this page!", + "support": "If you think this is an error, please contact the support." + }, + "form": { + "feedback": { + "emailWrongFormat": "Wrong email format", + "invalidCharacters": "Invalid character", + "invalidConfirmationPassword": "Password and Confirm Password are not matching", + "required": "Cannot be empty", + "whiteSpaceNotAllowed": "White and empty spaces are not allowed", + "specialCharactersNotAllowed": "Special characters are not allowed." + } + } + }, + "appStarter": { + "groups": { + "admin": "Admin", + "developer": "Developer", + "operator": "Operator" + }, + "title": "App Starter", + "tiles": { + "tooltips": { + "enum": { + "1": "SDC is the ONAP visual modeling and design tool. It creates internal metadata that describes assets used by all ONAP components, both at design time and run time.", + "2": "VID provides a well-structured organization of infrastructure deployment, instantiation and change-management operations used by Operations to derive orchestrations and change-management.", + "3": "ONAP Policy Framework lays out the architecture of the framework and shows the APIs provided to other components that interwork with the framework.", + "4": "The ONAP Service Orchestrator provides the highest level of service orchestration in the ONAP architecture.", + "5": "CLAMP is a platform for designing and managing control loops. It is used to design a closed loop, configure it with specific parameters for a particular network service, then deploying and undeploying it.", + "6": "Kibana Dashboard to visualize the events, triggered by control loops (used also in ONAP for Alarm Visualization).", + "7": "CDS Designer UI is a framework to automate the resolution of resources for instantiation and any config provisioning operation, such as day0, day1, or day2 configuration.", + "8": "CDT enables self-service onboarding of VNF's by creating templates and other artifacts. This may for instance be used in APPC's Configure command for applying a post-instantiation configuration.", + "9": "Holmes project provides alarm correlation and analysis for Telecom cloud infrastructure and services, including hosts, vims, VNFs and NSs.", + "10": "AAI is a component of ONAP runtime (Real-time views of Resources, Services, Products, Customer Subscriptions and their relationships).", + "11": "DCAE is the umbrella name for a number of components collectively fulfilling the role of Data Collection, Analytics, and Events generation for ONAP. The architecture of DCAE targets flexible, plug-able, micros-service oriented, model based component deployment and service composition. DCAE also support multi-site collection and analytics operations which are essential for large ONAP deployments.", + "12": "SDNC DG is to provide an execution environment for quickly written and highly customized service flows.", + "13": "The OpenDaylight Project is a collaborative open-source project hosted by The Linux Foundation. The project serves as a platform for software-defined networking (SDN) for open, centralized, network device monitoring." + } + } + } + }, + "dashboard": { + "apps": { + "userLastAction": { + "filter": { + "label": "Filter the last actions by: ", + "type": { + "ALL": "All my activities", + "SEARCH": "My searches", + "ACTION": "My activities" + }, + "interval": { + "1H": "Last 1 hour", + "4H": "Last 4 hours", + "1D": "Last 1 day", + "ALL": "All" + } + }, + "actionType": { + "SEARCH": "Search", + "VIEW": "View", + "EDIT": "Edit", + "DEPLOY": "Deploy", + "DELETE": "Delete", + "CREATE": "Create", + "CLEAR": "Clear", + "ACK": "Acknowledge", + "UNACK": "Unacknowledge" + }, + "entityType": { + "ALARM": "alarm", + "USERADMINISTRATION": "user", + "SERVICEMODEL": "service model", + "SERVICEINSTANCE": "service instance", + "TOPOLOGY": "topology" + }, + "tooltip": { + "again": "again", + "statusOf": "status of", + "noAction": "No action for now.", + "repeatAction": "Repeat last action", + "viewAction": "View last action", + "deployment": "deployment" + }, + "modal": { + "deploymentStatus": "Deployment Status", + "state": "State", + "progress": "Progress", + "flowStatus": "Flow Status", + "rollbackStatus": "Rollback Status", + "retryStatus": "Retry Status", + "taskInformation": "Task Information" + } + }, + "USER_LAST_ACTION_TILE": "Last user actions" + }, + "showSettings": "Configure which applications should be visible on dashboard", + "selectApplications": "Please select applications, that you would like to see in dashboard", + "tooltips": { + "settings": "Show dashboard settings" + } + }, + "layout": { + "header": { + "header": "Header", + "skipToMainContentLink": "Skip to Main Content", + "button": { + "account": "Account settings", + "closeFullscreen": "Close Fullscreen", + "logout": "Logout", + "openFullscreen": "Open Fullscreen", + "useraccount": "My Account" + }, + "info": { + "mail": "Email:", + "name": "Name:" + }, + "logo": { + "onap": "ONAP Logo" + }, + "sidebarToggler": "Toggle sidemenu", + "shortcuts": { + "details": "Details about keyboard shortcuts", + "home": "Home (top bar)", + "main": "Set focus to main content", + "search": "Set focus on search field if available on page", + "menu": "Set focus to main menu at the left", + "heading": "Keyboard Shortcuts", + "helpText": "Shortcut keys are supported by the portal, the mechanism differs across browsers:", + "helpBrowser1": "Hold down <b>ALT</b> and press key for <b>Google Chrome, Microsoft, Safari</b>", + "helpBrowser2": "Hold down <b>ALT + shift</b> and press the <b>key</b> for <b>Firefox</b>", + "helpBrowser3": "<b>MACINTOSH Safari:</b> hold down <b>CTRL</b> and press the <b>key</b>." + } + }, + "main": { + "alerts": "Alerts", + "mainContent": "Main Content", + "breadcrumb": "Breadcrumb" + }, + "sidebar": "Sidebar", + "menu": { + "mainMenu": "Main Menu", + "menuItems": "Menu Items", + "items": { + "home": "Home", + "appStarter": "App Starter", + "dashboard": "Dashboard", + "options": "Options", + "userAdministration": "User Administration", + "users": "Users", + "userSettings": "User Settings" + } + } + }, + "modal": { + "error": { + "accessDenied": "Access denied!", + "details": "Details:" + } + }, + "userAdministration": { + "buttons": { + "createUser": "Create User", + "editUser": "Edit User" + }, + "fields": { + "access": "Access", + "actions": "Actions", + "assignedRoles": "Assigned Roles", + "attributes": "Attributes", + "confirmPassword": "Confirm Password", + "createdAt": "Created At", + "email": "Email", + "emailVerified": "Email Verified", + "enabled": "Enabled", + "firstName": "First Name", + "id": "ID", + "key": "Key", + "lastName": "Last Name", + "password": "Password", + "requiredActions": "Required Actions", + "temporaryPassword": "Temporary Password", + "userName": "Username", + "value": "Value" + }, + "form": { + "headings": { + "setNewPassword": "Set New Password", + "setRoles": { + "assigned": "Assigned", + "available": "Available", + "title": "Set Roles" + }, + "setUserData": "Set User Data" + }, + "title": { + "changePassword": "Change Password", + "changePasswordTooltip": "To change your password, please log out and use the \"Forgot your password?\" link.", + "create": "Create User", + "edit": "Edit User", + "roles": "Roles" + } + }, + "list": { + "modal": { + "delete": { + "title": "Delete User", + "text": "Are you sure, that you want to delete user: {{userName}} ?" + } + }, + "tableCaption": "List of users", + "title": "User Administration" + }, + "messages": { + "success": { + "created": "User successfully created.", + "deleted": "User successfully deleted.", + "setPassword": "Password was successfully changed.", + "updated": "User successfully updated." + }, + "warnings": { + "userDeleted": { + "header": "User does not exist anymore", + "message": "Edit the user is not possible. User was already deleted." + } + } + } + }, + "pageNotFound": { + "text": "The page that you are looking for could not be found.", + "button": "Back to Main page", + "imgAltText": "Image of wondering woman" + } +} diff --git a/src/assets/images/icons/Asterisk.svg b/src/assets/images/icons/Asterisk.svg new file mode 100644 index 0000000..5480eea --- /dev/null +++ b/src/assets/images/icons/Asterisk.svg @@ -0,0 +1,5 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="32.275" height="30.469"> + <path + d="M0 14.355l2.246-6.933c5.176 1.823 8.936 3.402 11.28 4.736-.62-5.892-.945-9.944-.977-12.158h7.08c-.098 3.223-.472 7.26-1.123 12.11 3.353-1.693 7.194-3.256 11.523-4.688l2.246 6.933c-4.134 1.368-8.186 2.28-12.158 2.735 1.986 1.725 4.785 4.801 8.399 9.228l-5.86 4.15c-1.888-2.57-4.118-6.07-6.69-10.497-2.408 4.59-4.524 8.089-6.347 10.498l-5.762-4.15c3.776-4.656 6.478-7.732 8.106-9.23-4.2-.813-8.187-1.724-11.963-2.734" + font-size="100" font-family="arial" fill="red" /> +</svg>
\ No newline at end of file diff --git a/src/assets/images/icons/arrows-fullscreen-dark.svg b/src/assets/images/icons/arrows-fullscreen-dark.svg new file mode 100644 index 0000000..0e7ae36 --- /dev/null +++ b/src/assets/images/icons/arrows-fullscreen-dark.svg @@ -0,0 +1,3 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="18" height="20" fill="currentColor" class="bi bi-arrows-fullscreen" viewBox="0 0 16 16"> + <path fill-rule="evenodd" d="M5.828 10.172a.5.5 0 0 0-.707 0l-4.096 4.096V11.5a.5.5 0 0 0-1 0v3.975a.5.5 0 0 0 .5.5H4.5a.5.5 0 0 0 0-1H1.732l4.096-4.096a.5.5 0 0 0 0-.707zm4.344 0a.5.5 0 0 1 .707 0l4.096 4.096V11.5a.5.5 0 1 1 1 0v3.975a.5.5 0 0 1-.5.5H11.5a.5.5 0 0 1 0-1h2.768l-4.096-4.096a.5.5 0 0 1 0-.707zm0-4.344a.5.5 0 0 0 .707 0l4.096-4.096V4.5a.5.5 0 1 0 1 0V.525a.5.5 0 0 0-.5-.5H11.5a.5.5 0 0 0 0 1h2.768l-4.096 4.096a.5.5 0 0 0 0 .707zm-4.344 0a.5.5 0 0 1-.707 0L1.025 1.732V4.5a.5.5 0 0 1-1 0V.525a.5.5 0 0 1 .5-.5H4.5a.5.5 0 0 1 0 1H1.732l4.096 4.096a.5.5 0 0 1 0 .707z"/> +</svg> diff --git a/src/assets/images/icons/brush_graphical.svg b/src/assets/images/icons/brush_graphical.svg new file mode 100644 index 0000000..973e8c3 --- /dev/null +++ b/src/assets/images/icons/brush_graphical.svg @@ -0,0 +1,15 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="64.001" height="64"> + <path fill="none" d="M0 0H64.001V64H0z"/> + <linearGradient id="a" gradientUnits="userSpaceOnUse" x1="196.4878" y1="-51.1158" x2="213.9881" y2="-68.6161" gradientTransform="scale(-1.05 1.05) rotate(-45 216.3452 261.4473)"> + <stop offset="0" stop-color="#948983"/> + <stop offset="1" stop-color="#b9ada7"/> + </linearGradient> + <path fill="url(#a)" d="M18.537,31.208L37.329,50c-5.729,5.265-12.071,7.192-15.474,7.192c-1.095,0-2.756-0.21-3.588-1.101 l-16.01-16.01c-0.611-0.611-0.211-1.638,0.651-1.702C8.604,37.951,14.18,35.564,18.537,31.208z"/> + <linearGradient id="b" gradientUnits="userSpaceOnUse" x1="21.4183" y1="48.4644" x2="21.4183" y2="4.3958" gradientTransform="matrix(-1 0 0 1 64.003 0)"> + <stop offset="0" stop-color="#1063ad"/> + <stop offset="1" stop-color="#529ad6"/> + </linearGradient> + <path fill="url(#b)" d="M23.132,26.612l18.794,18.794l0.828-0.829c1.089-1.111,1.246-2.795,0.562-4.271 c-1.004-2.24-2.78-5.832-0.383-8.23c0.226-0.225,16.369-14.21,16.632-14.473l0.688-0.688c2.314-2.314,2.375-6.019,0.197-8.415 c0,0-0.161-0.182-0.196-0.218l0,0c-0.035-0.035-0.218-0.197-0.218-0.197c-2.396-2.178-6.101-2.117-8.415,0.197l-0.688,0.688 C50.67,9.235,36.686,25.378,36.461,25.604c-2.397,2.397-5.99,0.621-8.23-0.382c-1.476-0.683-3.16-0.527-4.271,0.562L23.132,26.612 z M54.504,10.589c0.952-0.952,2.494-0.952,3.446,0s0.952,2.494,0,3.446s-2.494,0.952-3.446,0 C53.552,13.083,53.552,11.54,54.504,10.589z"/> + <path opacity=".7" fill="#948983" d="M18.537,31.208L37.329,50c-0.818,0.752-1.648,1.428-2.481,2.048L16.113,33.312 C16.952,32.666,17.768,31.976,18.537,31.208z"/> + <path transform="rotate(-135 30.2303 38.3063)" fill="#DADAE2" d="M16.942 35.057H43.518V41.555H16.942z"/> +</svg> diff --git a/src/assets/images/icons/caret-down-fill-dark.svg b/src/assets/images/icons/caret-down-fill-dark.svg new file mode 100644 index 0000000..5ef3724 --- /dev/null +++ b/src/assets/images/icons/caret-down-fill-dark.svg @@ -0,0 +1,3 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="21" height="22" fill="currentColor" class="bi bi-caret-down-fill" viewBox="0 0 16 16"> + <path d="M7.247 11.14 2.451 5.658C1.885 5.013 2.345 4 3.204 4h9.592a1 1 0 0 1 .753 1.659l-4.796 5.48a1 1 0 0 1-1.506 0z"/> +</svg> diff --git a/src/assets/images/icons/crane_graphical.svg b/src/assets/images/icons/crane_graphical.svg new file mode 100644 index 0000000..242517e --- /dev/null +++ b/src/assets/images/icons/crane_graphical.svg @@ -0,0 +1,11 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="64.001" height="64"> + <path fill="none" stroke="#6C6C6C" stroke-width="3" stroke-linecap="round" stroke-miterlimit="10" d="M48.41,25.586 c0,2.809,2.277,5.087,5.087,5.087c2.809,0,5.087-2.277,5.087-5.087c0-2.809-2.277-5.087-5.087-5.087V9.001"/> + <linearGradient id="a" gradientUnits="userSpaceOnUse" x1="33.4962" y1="31.1591" x2="33.4962" y2="-19.8768"> + <stop offset="0" stop-color="#a6a6ae"/> + <stop offset="1" stop-color="#dadae2"/> + </linearGradient> + <path fill="url(#a)" d="M61.856,7.462c-0.16,0.375-0.466,0.67-0.848,0.814L21.361,23.327L18.033,9.412L58.74,1.96 c0.69-0.128,1.375,0.243,1.65,0.887l1.466,3.438C62.016,6.661,62.016,7.086,61.856,7.462z M5.016,23.537v31.462h12.982V23.537 H5.016z"/> + <path fill="#A6A6AE" d="M3.528,26.021h17.74c0.453,0,0.882-0.205,1.167-0.558c0.285-0.352,0.395-0.814,0.3-1.257L19.297,8.186 C19.149,7.494,18.538,7,17.83,7H3.528c-0.829,0-1.5,0.672-1.5,1.5v16.021C2.028,25.35,2.7,26.021,3.528,26.021z"/> + <path fill="#808083" d="M33.486,52.989H3.519c-0.829,0-1.5,0.672-1.5,1.5V62h32.966v-7.51 C34.986,53.661,34.314,52.989,33.486,52.989z"/> + <path opacity=".7" fill="#808083" d="M5.016 26.021H17.997999999999998V28.021H5.016z"/> +</svg> diff --git a/src/assets/images/icons/delete-icon.svg b/src/assets/images/icons/delete-icon.svg new file mode 100644 index 0000000..8a8901a --- /dev/null +++ b/src/assets/images/icons/delete-icon.svg @@ -0,0 +1,7 @@ +<svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-trash" fill="currentColor" + xmlns="http://www.w3.org/2000/svg"> + <path + d="M5.5 5.5A.5.5 0 0 1 6 6v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm2.5 0a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm3 .5a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0V6z"></path> + <path fill-rule="evenodd" + d="M14.5 3a1 1 0 0 1-1 1H13v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V4h-.5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1H6a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1h3.5a1 1 0 0 1 1 1v1zM4.118 4L4 4.059V13a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4.059L11.882 4H4.118zM2.5 3V2h11v1h-11z"></path> +</svg> diff --git a/src/assets/images/icons/edit_graphical.svg b/src/assets/images/icons/edit_graphical.svg new file mode 100644 index 0000000..14b0fd1 --- /dev/null +++ b/src/assets/images/icons/edit_graphical.svg @@ -0,0 +1,14 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="64.001" height="64"> + <path fill="none" d="M0 0H64.001V64H0z"/> + <linearGradient id="a" gradientUnits="userSpaceOnUse" x1="-166.8658" y1="1526.6628" x2="-213.6318" y2="1573.4288" gradientTransform="scale(1 -1) rotate(-45 -1982.2689 489.3917)"> + <stop offset="0" stop-color="#218076"/> + <stop offset="1" stop-color="#1bada2"/> + </linearGradient> + <path fill="url(#a)" d="M7.426,45.7l43-43c0.8-0.8,2.1-0.8,2.8,0l8.5,8.5c0.8,0.8,0.8,2.1,0,2.8l-43,43L7.426,45.7z"/> + <path fill="#B9ADA7" d="M7.426,45.7l-4.9,14c0,0-0.1,0.399-0.1,0.6s0,0.4,0.1,0.601c0.1,0.199,0.2,0.399,0.4,0.6 c0.2,0.2,0.4,0.3,0.6,0.4c0.2,0.1,0.4,0.1,0.6,0.1c0.2,0,0.6-0.1,0.6-0.1l14-4.9L7.426,45.7z"/> + <linearGradient id="b" gradientUnits="userSpaceOnUse" x1="2.4185" y1="58.2998" x2="9.8484" y2="58.2998"> + <stop offset="0" stop-color="#4c4c4c"/> + <stop offset="1" stop-color="#7a7a7a"/> + </linearGradient> + <path fill="url(#b)" d="M2.542,59.679c-0.082,0.203-0.123,0.42-0.123,0.636c0,0.217,0.041,0.434,0.123,0.637 c0.083,0.204,0.207,0.396,0.373,0.561c0.165,0.165,0.356,0.289,0.559,0.372c0.204,0.082,0.421,0.124,0.637,0.124 c0.217,0,0.433-0.042,0.637-0.124l5.086-1.773l-5.518-5.519L2.542,59.679z"/> +</svg> diff --git a/src/assets/images/icons/eraser_graphical.svg b/src/assets/images/icons/eraser_graphical.svg new file mode 100644 index 0000000..cbf4a9e --- /dev/null +++ b/src/assets/images/icons/eraser_graphical.svg @@ -0,0 +1,7 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="64.001" height="64"> + <path fill="none" d="M0 0H64.001V64H0z"/> + <path fill="#F05C51" d="M22.001,60c-1.1,0-2.636-0.636-3.414-1.414L2.915,42.914c-0.778-0.778-0.778-2.051,0-2.828L36.587,6.414 c0.778-0.778,2.051-0.778,2.828,0l20.172,20.172c0.778,0.778,0.778,2.051,0,2.828L30.415,58.586 C29.637,59.364,28.101,60,27.001,60H22.001z"/> + <path opacity=".6" fill="#D52B1E" d="M32.001,57l-1.586,1.586C29.637,59.364,28.101,60,27.001,60h-5 c-1.1,0-2.636-0.636-3.414-1.414L2.915,42.914c-0.778-0.778-0.778-2.051,0-2.828L9.001,34L32.001,57z"/> + <path fill="#427CAC" d="M49.001,40l12.086-12.086c0.778-0.778,0.778-2.051,0-2.828L40.915,4.914c-0.778-0.778-2.051-0.778-2.828,0 L26.001,17L49.001,40z"/> + <path fill="#EDEDED" d="M6.001,37l-1.5,1.5l21.5,21.5h1c0.498,0,1.084-0.135,1.65-0.35L6.001,37z"/> +</svg> diff --git a/src/assets/images/icons/install_graphical.svg b/src/assets/images/icons/install_graphical.svg new file mode 100644 index 0000000..b8b4fb6 --- /dev/null +++ b/src/assets/images/icons/install_graphical.svg @@ -0,0 +1,15 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="64.001" height="64"> + <style> + </style> + <path fill="none" d="M0 0H64.001V64H0z" id="Asset"/> + <g id="Icons"> + <linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="32.0149" y1="37.2887" x2="32.0149" y2="62.0548"> + <stop offset="0" stop-color="#ededed"/> + <stop offset="1" stop-color="#d0d0d0"/> + </linearGradient> + <path d="M58.015,44c0-1.1-0.9-2-2-2H8.015c-1.1,0-2,0.9-2,2v16.001c0,1.1,0.9,2,2,2h48.001c1.1,0,2-0.9,2-2V44z" fill="url(#SVGID_1_)"/> + <circle cx="49.002" cy="52.001" r="3" fill="#7ba84a"/> + <path d="M58.015,60.047c0,1.075-0.9,1.954-2,1.954H8.015c-1.1,0-2-0.88-2-1.955l0,0 C6.015,60.029,58.015,60.029,58.015,60.047L58.015,60.047z" opacity=".15"/> + <path d="M46.005,35h-10V6c0-2.209-1.791-4-4-4s-4,1.791-4,4v29h-10l14,14L46.005,35z" fill="#31c3f7"/> + </g> +</svg> diff --git a/src/assets/images/icons/list-dark.svg b/src/assets/images/icons/list-dark.svg new file mode 100644 index 0000000..9191e81 --- /dev/null +++ b/src/assets/images/icons/list-dark.svg @@ -0,0 +1,3 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="24" height="25" fill="currentColor" class="bi bi-list" viewBox="0 0 16 16"> + <path fill-rule="evenodd" d="M2.5 12a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5z"/> +</svg> diff --git a/src/assets/images/icons/person-fill-dark.svg b/src/assets/images/icons/person-fill-dark.svg new file mode 100644 index 0000000..aa6b09d --- /dev/null +++ b/src/assets/images/icons/person-fill-dark.svg @@ -0,0 +1,3 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="21" height="22" fill="currentColor" class="bi bi-person-fill" viewBox="0 0 16 16"> + <path d="M3 14s-1 0-1-1 1-4 6-4 6 3 6 4-1 1-1 1H3zm5-6a3 3 0 1 0 0-6 3 3 0 0 0 0 6z"/> +</svg> diff --git a/src/assets/images/icons/question-circle.svg b/src/assets/images/icons/question-circle.svg new file mode 100644 index 0000000..a7cf7d4 --- /dev/null +++ b/src/assets/images/icons/question-circle.svg @@ -0,0 +1,4 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="18" height="21" fill="currentColor" class="bi bi-question-circle" viewBox="0 0 16 16"> + <path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z"/> + <path d="M5.255 5.786a.237.237 0 0 0 .241.247h.825c.138 0 .248-.113.266-.25.09-.656.54-1.134 1.342-1.134.686 0 1.314.343 1.314 1.168 0 .635-.374.927-.965 1.371-.673.489-1.206 1.06-1.168 1.987l.003.217a.25.25 0 0 0 .25.246h.811a.25.25 0 0 0 .25-.25v-.105c0-.718.273-.927 1.01-1.486.609-.463 1.244-.977 1.244-2.056 0-1.511-1.276-2.241-2.673-2.241-1.267 0-2.655.59-2.75 2.286zm1.557 5.763c0 .533.425.927 1.01.927.609 0 1.028-.394 1.028-.927 0-.552-.42-.94-1.029-.94-.584 0-1.009.388-1.009.94z"/> +</svg> diff --git a/src/assets/images/icons/search_graphical.svg b/src/assets/images/icons/search_graphical.svg new file mode 100644 index 0000000..89d2d6b --- /dev/null +++ b/src/assets/images/icons/search_graphical.svg @@ -0,0 +1,16 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="64.001" height="64"> + <path fill="none" d="M0 0H64.001V64H0z"/> + <linearGradient id="a" gradientUnits="userSpaceOnUse" x1="16.1731" y1="59.9902" x2="16.1731" y2="31.6028"> + <stop offset="0" stop-color="#4c4c4c"/> + <stop offset="1" stop-color="#7a7a7a"/> + </linearGradient> + <path fill="url(#a)" d="M8.025,59.99c-1.024,0-2.047-0.391-2.829-1.172c-1.562-1.562-1.562-4.095,0-5.656l16.295-16.295 c1.563-1.562,4.095-1.562,5.657,0c1.562,1.562,1.562,4.095,0,5.656L10.854,58.818C10.073,59.6,9.049,59.99,8.025,59.99z"/> + <path opacity=".4" fill="#4B4B4B" d="M21.492,36.867l-5.001,5c1.624,2.148,3.461,4.084,5.717,5.597l4.94-4.941 c1.562-1.562,1.562-4.095,0-5.656C25.587,35.306,23.055,35.305,21.492,36.867z"/> + <path fill="#D4EEFC" d="M37.017,4c-12.7,0-23,10.3-23,23c0,5,1.6,9.7,4.3,13.4c1.5,2,3.2,3.8,5.3,5.199 c3.8,2.801,8.4,4.4,13.4,4.4c12.699,0,23-10.3,23-23S49.716,4,37.017,4z"/> + <path fill="#317CB3" d="M37.017,9.6c10.199,0,18.5,8.101,19,18.2c0-0.3,0-0.5,0-0.8c0-10.5-8.5-19-19-19s-19,8.5-19,19 c0,0.3,0,0.5,0,0.8C18.517,17.7,26.816,9.6,37.017,9.6z" opacity=".25"/> + <linearGradient id="b" gradientUnits="userSpaceOnUse" x1="12.0718" y1="-1489.1914" x2="12.0718" y2="-1442.2994" gradientTransform="matrix(1 0 0 -1 24.9448 -1439.1914)"> + <stop offset="0" stop-color="#a6a6ae"/> + <stop offset="1" stop-color="#dadae2"/> + </linearGradient> + <path fill="url(#b)" d="M37.017,8c10.5,0,19,8.5,19,19s-8.5,19-19,19c-4,0-7.8-1.2-11.101-3.6 c-1.699-1.2-3.1-2.7-4.3-4.301c-2.399-3.3-3.6-7.1-3.6-11.1C18.017,16.5,26.517,8,37.017,8 M37.017,4c-12.7,0-23,10.3-23,23 c0,5,1.6,9.7,4.3,13.4c1.5,2,3.2,3.8,5.3,5.199c3.8,2.801,8.4,4.4,13.4,4.4c12.699,0,23-10.3,23-23S49.716,4,37.017,4L37.017,4z"/> +</svg> diff --git a/src/assets/images/icons/standing-woman.svg b/src/assets/images/icons/standing-woman.svg new file mode 100644 index 0000000..dd87137 --- /dev/null +++ b/src/assets/images/icons/standing-woman.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 53.6726 140.4517"><defs><style>.cls-1{isolation:isolate;}.cls-2{fill:#875a5a;}.cls-3{opacity:0.4;}.cls-3,.cls-5{mix-blend-mode:multiply;}.cls-4{fill:#efc3bd;}.cls-5{opacity:0.6;}.cls-6{fill:#d89891;}.cls-7{fill:#c67f79;}.cls-8{fill:#fbb03b;}.cls-9{fill:#363a46;}.cls-10{fill:#0a1045;}</style></defs><g class="cls-1"><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-2" d="M18.6217,6.3614A3.7477,3.7477,0,0,0,15.9363,0,9.2124,9.2124,0,0,0,12.72.68c-6.9959,2.6674.1452,18.5721.9794,22.0812L15.2856,12.2a8.9483,8.9483,0,0,1,2.4283-4.9037Z"/><g class="cls-3"><path d="M9.9764,9.97c.9013,5.1042,3.2072,10.6508,3.6593,12.5538L15.2215,11.963A8.9479,8.9479,0,0,1,17.55,7.1651l-1.5425-.4639S14.3527,5.266,12.9925,7.8329A5.2355,5.2355,0,0,1,9.9764,9.97Z"/></g><path class="cls-2" d="M15.74,14.7375c2.5945,6.7088,8.5439,3.0426,8.5439,3.0426l6.0725-8.5842.3231-.4571s.9249-1.3612-1.0017-4.0582c-.0148-.0207-.03-.0413-.0453-.062C27.6784,1.9719,22.9544,1.2223,20.2781,2.37,17.5812,3.5252,12.605,6.629,15.74,14.7375Z"/><polygon class="cls-4" points="19.965 14.514 19.347 23.754 19.965 37.372 26.93 37.372 27.928 24.546 26.536 23.754 25.346 14.589 19.965 14.514"/><g class="cls-5"><path class="cls-6" d="M20.9735,14.5278s-1.6261,6.0528,5.2259,6.6337l-.8532-6.5722Z"/></g><path class="cls-4" d="M19.9643,15.0855a4.4222,4.4222,0,0,0,2.5315,3.7637c2.432.9889,4.4384,2.1512,5.7061,1.6755s2.8654-6.1839,2.7-6.8153a10.5665,10.5665,0,0,1,0-3.4268l.0089-.0413a4.7336,4.7336,0,0,0,.0935-.6107c.0759-1.0087-.3181-2.4793-3.5282-4.8433,0,0,.0394.5408-.9644,1.3268s-5.3869,4.3005-5.4391,6.504c0,0-.6344-2.7108-2.4822-1.97S17.3255,14.61,19.9643,15.0855Z"/><ellipse cx="25.8379" cy="11.9603" rx="0.344" ry="0.6117"/><path class="cls-2" d="M24.1091,10.8287a2.7662,2.7662,0,0,1,1.4991-.75,4.7276,4.7276,0,0,1,1.4669-.0379l-.0056-.0282a.8974.8974,0,0,0-.8924-.7263l-.0311.0006a2.5546,2.5546,0,0,0-2.171,1.3308.1443.1443,0,0,0,.1341.2114Z"/><path class="cls-2" d="M28.8953,10.0571a4.7487,4.7487,0,0,1,1.4677.0384,2.67,2.67,0,0,1,.5477.1458,4.7336,4.7336,0,0,0,.0935-.6107,2.4844,2.4844,0,0,0-1.179-.3271c-.0109,0-.0217,0-.0315-.0009a.8992.8992,0,0,0-.8924.7269Z"/><path class="cls-7" d="M28.3879,15.2015l-.0129-.1966a1.4953,1.4953,0,0,0,1.1186-.3957.4278.4278,0,0,0,.103-.2885l-.6472-1.2073.1736-.0932.6663,1.253a.6044.6044,0,0,1-.1362.4518A1.7,1.7,0,0,1,28.3879,15.2015Z"/><path class="cls-7" d="M29.38,16.4694H27.0751A1.5666,1.5666,0,0,0,29.38,16.4694Z"/><path class="cls-2" d="M20.9735,6.5373v6.0805l1.7031-2.2912a5.5054,5.5054,0,0,0,1.0126-1.7887l.47.8323h1.1318L26.36,7.3224,27.048,9.37h.4029l.6678-2.8033.43,2.8033h1.2155l.4087-1.6952.8727,1.5209.3231-.4571s.4124-2.9526-1.0017-4.0582a4.8741,4.8741,0,0,0-2.6438-.4757C24.4929,4.2049,20.9735,6.5373,20.9735,6.5373Z"/><ellipse cx="30.0487" cy="11.9774" rx="0.344" ry="0.6117"/><path class="cls-8" d="M9.5837,42.0825l3.8135,15.9853h17.75l3.09-16.9732s1.3948-2.1641,1.251-6.4449c-.1291-3.8267,3.0281-6.9385-2.022-8.285-2.4556-.655-6.9432-3.609-6.9432-3.609H19.3346s-7.2023,2.9953-9.5052,3.609C4.78,27.7112,9.5837,42.0825,9.5837,42.0825Z"/><g class="cls-3"><path d="M14.4613,36.0278c5,15.23-1.9415,19.0447-1.9415,19.0447L8.68,38.9333S13.6866,33.6683,14.4613,36.0278Z"/></g><path class="cls-4" d="M26.45,22.6972A2.6066,2.6066,0,0,1,23.9756,26.38c-1.9515,0-4.641-1.6247-4.641-3.7188Z"/><path class="cls-9" d="M53.6693,140.4517a2.3285,2.3285,0,0,0-1.9354-2.3338c-2.1061-.6262-4.7814-.6831-6.0337-5.6922H39.6664l.3143,1.547a9.4594,9.4594,0,0,1-.0293,3.862,10.3279,10.3279,0,0,0-.285,2.617Z"/><path class="cls-9" d="M.0033,140.4517a2.3285,2.3285,0,0,1,1.9354-2.3338c2.1061-.6262,4.4-.2277,4.8054-5.6922h6.0338l.0333,2.3542a6.2545,6.2545,0,0,0,.4059,2.1267,9.9353,9.9353,0,0,1,.789,3.5451Z"/><path class="cls-10" d="M13.3972,58.0678S9.4405,65.7018,9.0223,72.633s-4.3351,61.3654-4.3351,61.3654h8.7835L23.44,78.8448l7.7074-20.777Z"/><path class="cls-10" d="M31.1472,58.0678s3.4862,11.6571,4.2277,14.4672c1.9849,7.5217,12.16,61.4634,12.16,61.4634H38.7514L22.5468,79.0392l-9.15-20.9714Z"/><path class="cls-8" d="M14.6133,36.7853a12.13,12.13,0,0,0-1.3366-6.9718c-1.0556-1.9911-2.529-3.8539-4.16-3.2092-3.2135,1.27-2.9953,3.9558-3.2043,9.6492S5.7416,49.694,7.1853,51.3312a3.5008,3.5008,0,0,0,6.0207-1.6879C13.4317,47.8,14.18,40.842,14.6133,36.7853Z"/><g class="cls-3"><path d="M27.6424,67.7272s2.886,23.3546,1.1082,32.3528L23.1791,81.6817l-.6323-2.6425Z"/></g><path class="cls-8" d="M38.4915,43.6064c.1375-4.8328-.0208-15.68-3.8178-16.82,0,0-4.0672.6077-3.8241,5.9062a106.0064,106.0064,0,0,0,.7322,10.8068,4.2384,4.2384,0,0,0,3.5866,3.3328A3.2807,3.2807,0,0,0,38.4915,43.6064Z"/><path class="cls-4" d="M32.2635,40.384,27.4821,40.23l-2.0379,2.16s-10.62,1.8463-14.11,2.2095a5.1033,5.1033,0,0,0-2.969,1.343,4.0946,4.0946,0,0,0-1.1286,4.4577,2.7891,2.7891,0,0,0,2.9729,1.949c2.2048-.2526,16.6034-6.924,16.6034-6.924l.351.0695a2.263,2.263,0,0,0,1.8507-.452l2.6177-1.1175Z"/><g class="cls-5"><polygon class="cls-6" points="27.482 40.23 31.632 43.926 32.264 40.384 27.482 40.23"/></g><path class="cls-4" d="M26.8085,20.5929l3.1633-1.5161,3.8208,3.5371,2.1336,4.8119,2.5966,16.571a3.7856,3.7856,0,0,1-1.5645,2.9824c-1.7856,1.0122-3.8239.8991-5.1776-2.0406-.3481-.756.6728-18.9251.6728-18.9251h0a2.7483,2.7483,0,0,1-2.4479-2.1011l-.349-1.5759-2.2727.0332Z"/><g class="cls-5"><polygon class="cls-6" points="29.657 22.337 29.972 19.077 26.808 20.593 27.384 22.37 29.657 22.337"/></g></g></g></g></svg>
\ No newline at end of file diff --git a/src/assets/images/icons/thumbs-down_graphical.svg b/src/assets/images/icons/thumbs-down_graphical.svg new file mode 100644 index 0000000..20504e0 --- /dev/null +++ b/src/assets/images/icons/thumbs-down_graphical.svg @@ -0,0 +1,8 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="64.001" height="64"> + <path fill="none" d="M0 0H64.001V64H0z"/> + <path fill="#FFD7A5" d="M12.375,33.829l11.883,4.913c0,0-1.543,2.56-4.077,6.824c-4.603,7.746-1.827,11.873,1.584,12.436 l5.718-9.249L43.926,36h14.072l0.029-21.001L43.911,15c0,0-3.626-1.499-8.25-3.218c-8.421-3.13-12.55-2.982-14.632-2.33 c-1.363,0.427-1.481,2.259-1.481,2.259l4.006,7.961L12.375,33.829z"/> + <path fill="#FFD7A5" d="M28.536,11.766l-5.367-2.207c-1.688-0.685-3.617,0.124-4.303,1.809c-0.685,1.69,0.123,3.616,1.811,4.305 l-3.705-1.515c-1.695-0.668-3.607,0.169-4.272,1.867c-0.67,1.695,0.169,3.609,1.862,4.271l-2.711-1.112 c-1.688-0.685-3.613,0.132-4.295,1.821c-0.688,1.686,0.131,3.611,1.822,4.294l0.598,0.246c-1.717-0.718-3.693,0.093-4.408,1.814 c-0.715,1.717,0.094,3.69,1.814,4.406l8.156,3.347c1.719,0.715,3.691-0.097,4.406-1.815c0.714-1.717-0.095-3.688-1.813-4.406 l2.43,0.997c1.688,0.68,3.609-0.132,4.293-1.819c0.686-1.69-0.131-3.611-1.82-4.296l1.469,0.603 c1.697,0.664,3.609-0.169,4.277-1.867c0.664-1.696-0.168-3.61-1.865-4.275l-0.866-0.355c1.684,0.684,3.609-0.127,4.296-1.813 C31.03,14.38,30.224,12.452,28.536,11.766z"/> + <path opacity=".4" fill="#D48936" d="M28.536,11.766l-1.928-0.793c1.288,0.867,1.839,2.611,1.236,4.091 c-0.657,1.613-2.446,2.41-4.075,1.878l1.518,0.623l-0.254-0.104c1.269,0.86,1.824,2.572,1.247,4.046 c-0.642,1.633-2.434,2.452-4.08,1.922l2.303,0.945c1.697,0.664,3.609-0.169,4.277-1.867c0.664-1.696-0.168-3.61-1.865-4.275 l-0.866-0.355c1.684,0.684,3.609-0.127,4.296-1.813C31.03,14.38,30.224,12.452,28.536,11.766z M23.034,23.771l-1.907-0.782 c1.277,0.869,1.827,2.6,1.227,4.078c-0.655,1.617-2.445,2.414-4.078,1.882l2.285,0.938c1.688,0.68,3.609-0.132,4.293-1.819 C25.54,26.377,24.724,24.456,23.034,23.771z M18.128,28.888l-2.375-0.974c1.701,0.726,2.402,2.673,1.691,4.382 c-0.682,1.639-2.507,2.437-4.167,1.887l2.26,0.928c1.719,0.715,3.691-0.097,4.406-1.815 C20.659,31.578,19.849,29.604,18.128,28.888z"/> + <path opacity=".25" fill="#D48936" d="M18.817 27.448L7.634 22.859c-.098-.039-.182-.097-.273-.144.165 1.119.891 2.127 2.018 2.582l8.899 3.651c1.633.532 3.423-.265 4.078-1.882.063-.156.1-.315.139-.473C21.59 27.591 20.136 27.979 18.817 27.448zM13.796 32.672l-8.158-3.347c-.1-.042-.185-.101-.279-.15.176 1.117.9 2.122 2.023 2.589l5.896 2.419c1.659.55 3.485-.248 4.167-1.887.069-.165.111-.333.152-.501C16.667 32.836 15.156 33.238 13.796 32.672zM22.761 21.935l-9.939-4.078c-.108-.042-.202-.103-.303-.154.166 1.132.905 2.147 2.045 2.593l7.637 3.133c1.646.529 3.438-.289 4.08-1.922.056-.142.086-.287.121-.431C25.507 22.06 24.072 22.449 22.761 21.935zM24.302 15.436l-5.367-2.203c-.094-.038-.175-.094-.264-.14.166 1.116.886 2.121 2.006 2.578l3.094 1.27c1.629.532 3.417-.265 4.075-1.878.064-.158.103-.32.142-.481C27.082 15.584 25.622 15.975 24.302 15.436zM34.438 25.045l.938-.347-.694-1.876-.938.348c-9.602 3.551-11.199 12.576-11.447 14.754l1.944.806.01-.243C24.256 38.39 24.772 28.62 34.438 25.045z"/> + <path opacity=".3" fill="#D48936" d="M27.482,48.753L43.926,36h14.072l0.003-2H43.222l-17.26,13.409 c0,0-3.994,6.594-5.108,10.339c0.296,0.111,0.599,0.203,0.911,0.254L27.482,48.753z"/> +</svg> diff --git a/src/assets/images/icons/thumbs-up_graphical.svg b/src/assets/images/icons/thumbs-up_graphical.svg new file mode 100644 index 0000000..d0cde66 --- /dev/null +++ b/src/assets/images/icons/thumbs-up_graphical.svg @@ -0,0 +1,7 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="64.001" height="64"> + <path fill="none" d="M0 0H64.001V64H0z"/> + <path fill="#FFD7A5" d="M56.619,31.145l-1.13-0.463l0.002-0.001l-15.715-6.448c0,0,1.512-2.535,4.046-6.8 c4.603-7.746,1.827-11.873-1.584-12.436l-5.718,9.249L20.077,27H6.001v21.001L20.092,48c0,0,3.626,1.497,8.25,3.216 c8.421,3.13,12.625,2.88,14.707,2.228c0.031-0.01,0.052-0.028,0.081-0.039c0.876-0.296,1.628-0.942,2.003-1.864 c0.688-1.69-0.123-3.616-1.811-4.305l-1.141-0.469l-0.002-0.004l4.848,1.987c1.697,0.668,3.609-0.169,4.273-1.867 c0.668-1.695-0.17-3.61-1.865-4.271l-5.469-2.244l0.001,0l8.181,3.357c1.688,0.685,3.615-0.132,4.297-1.821 c0.686-1.687-0.131-3.611-1.822-4.294l-4.957-2.034l0,0l4.359,1.788c1.715,0.718,3.691-0.093,4.408-1.813 C59.148,33.834,58.338,31.86,56.619,31.145z"/> + <path opacity=".4" fill="#D48936" d="M35.221,40.401c-0.664,1.696,0.166,3.61,1.865,4.275l2.257,0.925 c-1.539-0.746-2.255-2.584-1.623-4.2c0.64-1.633,2.433-2.451,4.078-1.923l-2.302-0.945C37.801,37.87,35.887,38.703,35.221,40.401z M39.354,45.607l-1.399-0.574c-1.686-0.688-3.611,0.124-4.299,1.812c-0.686,1.684,0.119,3.611,1.807,4.298l2.475,1.017 c-1.684-0.688-2.466-2.633-1.782-4.315c0.605-1.485,2.177-2.305,3.694-2.012l-0.284-0.116 C39.49,45.687,39.426,45.642,39.354,45.607z M39.145,34.841c-0.684,1.69,0.133,3.611,1.822,4.296l0.838,0.344 c0.063,0.021,0.128,0.029,0.191,0.053l1.021,0.419c-1.379-0.826-1.993-2.579-1.373-4.112c0.657-1.617,2.446-2.414,4.079-1.882 l-2.285-0.937C41.752,32.342,39.83,33.153,39.145,34.841z M50.723,28.726l-2.262-0.928c-1.717-0.715-3.689,0.097-4.406,1.814 c-0.713,1.718,0.096,3.691,1.818,4.408l2.509,1.029c-1.635-0.767-2.521-2.766-1.827-4.437 C47.239,28.973,49.065,28.175,50.723,28.726z"/> + <path opacity=".25" fill="#D48936" d="M48.382,35.05l-0.111-0.045c0,0,0,0,0,0l5.754,2.36c1.229,0.514,2.585,0.234,3.522-0.594 c-0.144-0.039-0.289-0.072-0.43-0.131l-8.152-3.344c-1.366-0.569-2.136-1.931-2.045-3.328c-0.141,0.198-0.267,0.41-0.365,0.645 C45.861,32.284,46.747,34.282,48.382,35.05z M38.557,50.418c-1.339-0.545-2.101-1.872-2.024-3.237 c-0.145,0.205-0.278,0.422-0.376,0.664c-0.684,1.68,0.097,3.622,1.776,4.312l2.907,1.195c1.21,0.488,2.537,0.199,3.446-0.621 c-0.121-0.034-0.243-0.058-0.362-0.106L38.557,50.418z M44.059,38.412c-1.343-0.544-2.112-1.871-2.034-3.242 c-0.147,0.206-0.28,0.425-0.38,0.67c-0.606,1.499-0.028,3.202,1.286,4.049c0.141,0.084,0.281,0.168,0.437,0.232l8.78,3.603 c1.21,0.491,2.537,0.2,3.446-0.622c-0.118-0.033-0.237-0.056-0.353-0.103L44.059,38.412z M40.178,43.952 c-1.36-0.533-2.142-1.869-2.066-3.251c-0.153,0.215-0.29,0.443-0.391,0.701c-0.609,1.556,0.04,3.306,1.46,4.101 c0.097,0.051,0.188,0.111,0.292,0.153l7.555,3.096c1.206,0.475,2.512,0.179,3.41-0.635c-0.106-0.03-0.212-0.048-0.317-0.089 L40.178,43.952z"/> + <path opacity=".3" fill="#D48936" d="M40.832,53.35l-4.666-1.918c-1.886-0.367-4.225-1.012-7.127-2.091 c-4.627-1.72-8.256-3.058-8.256-3.058L20.448,46L6.001,46.001v2L20.092,48c0,0,3.626,1.497,8.25,3.216 c8.421,3.13,12.625,2.88,14.707,2.228c0.037-0.012,0.065-0.031,0.1-0.045C42.419,53.651,41.602,53.662,40.832,53.35z M44.897,6.419c0.536,2.042-0.01,5.727-2.544,9.991c-2.521,4.242-3.252,5.453-3.256,5.46l-1.298,2.167l-0.018,0.017 c0.323,6.105-3.419,11.696-9.313,13.915l-0.936,0.352l0.705,1.872l0.935-0.353c6.617-2.49,10.844-8.731,10.61-15.591l-0.018-0.002 c0.05-0.083,1.567-2.621,4.059-6.815C47.076,11.955,46.636,8.296,44.897,6.419z"/> +</svg> diff --git a/src/assets/images/icons/triangular-warning-sign.svg b/src/assets/images/icons/triangular-warning-sign.svg new file mode 100644 index 0000000..82ebf5c --- /dev/null +++ b/src/assets/images/icons/triangular-warning-sign.svg @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg version='1.1' id='Capa_1' xmlns='http://www.w3.org/2000/svg' x='0px' y='0px' + width='458.096px' height='458.096px' viewBox='0 0 458.096 458.096' + style='enable-background:new 0 0 458.096 458.096;' + xml:space='preserve'> +<g> + <path stroke="#a60000" fill="#a60000" d="M454.106,396.635L247.33,38.496c-3.783-6.555-10.775-10.592-18.344-10.592c-7.566,0-14.561,4.037-18.344,10.592 + L2.837,398.414c-3.783,6.555-3.783,14.629,0,21.184c3.783,6.556,10.778,10.593,18.344,10.593h415.613c0.041,0,0.088,0.006,0.118,0 + c11.709,0,21.184-9.481,21.184-21.185C458.096,404.384,456.612,400.116,454.106,396.635z M57.872,387.822L228.986,91.456 + L400.1,387.828H57.872V387.822z M218.054,163.009h21.982c1.803,0,3.534,0.727,4.8,2.021c1.259,1.3,1.938,3.044,1.892,4.855 + l-4.416,138.673c-0.095,3.641-3.073,6.537-6.703,6.537h-13.125c-3.635,0-6.614-2.902-6.7-6.537l-4.418-138.673 + c-0.047-1.812,0.636-3.555,1.895-4.855C214.52,163.736,216.251,163.009,218.054,163.009z M246.449,333.502v25.104 + c0,3.699-2.997,6.696-6.703,6.696h-21.394c-3.706,0-6.7-2.997-6.7-6.696v-25.104c0-3.7,2.994-6.703,6.7-6.703h21.394 + C243.452,326.793,246.449,329.802,246.449,333.502z"/> +</g> +</svg> diff --git a/src/assets/images/icons/visible_graphical.svg b/src/assets/images/icons/visible_graphical.svg new file mode 100644 index 0000000..6875a28 --- /dev/null +++ b/src/assets/images/icons/visible_graphical.svg @@ -0,0 +1,18 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="64.001" height="64"> + <path fill="none" d="M0 0H64.001V64H0z"/> + <linearGradient id="a" gradientUnits="userSpaceOnUse" x1="32" y1="54.6846" x2="32" y2="15.9954"> + <stop offset="0" stop-color="#e9e4e2"/> + <stop offset=".6626" stop-color="#f5f3f2"/> + </linearGradient> + <path fill="url(#a)" d="M32,16.5c-11.962,0-22.851,6.319-28.5,15.528C9.149,41.237,20.038,47.556,32,47.556 c11.963,0,22.851-6.318,28.5-15.527C54.851,22.819,43.963,16.5,32,16.5z"/> + <linearGradient id="b" gradientUnits="userSpaceOnUse" x1="32" y1="55.8553" x2="32" y2="15.9035"> + <stop offset="0" stop-color="#317cb3"/> + <stop offset="1" stop-color="#53baf2"/> + </linearGradient> + <path fill="url(#b)" d="M17.612,31.904c0-7.947,6.443-14.384,14.388-14.384c7.945,0,14.388,6.437,14.388,14.384 c0,7.95-6.442,14.388-14.388,14.388C24.056,46.292,17.612,39.854,17.612,31.904z"/> + <path fill="#235482" d="M25.204,31.904c0-3.752,3.044-6.793,6.796-6.793c3.753,0,6.796,3.041,6.796,6.793 c0,3.756-3.043,6.796-6.796,6.796C28.248,38.7,25.204,35.66,25.204,31.904z"/> + <path fill="#FFF" d="M24.096,27.278c0-1.809,1.468-3.276,3.278-3.276c1.812,0,3.277,1.468,3.277,3.276 c0,1.814-1.466,3.277-3.277,3.277C25.563,30.556,24.096,29.092,24.096,27.278z" opacity=".4"/> + <path fill="#C7BDB9" d="M32,48.556c-12.049,0-23.296-6.133-29.353-16.005l-0.321-0.522l0.321-0.522 C8.704,21.633,19.951,15.5,32,15.5c12.049,0,23.296,6.133,29.353,16.006l0.321,0.522l-0.321,0.522 C55.296,42.423,44.049,48.556,32,48.556z M4.681,32.028C10.378,40.872,21.028,46.556,32,46.556s21.622-5.684,27.319-14.527 C53.622,23.183,42.972,17.5,32,17.5S10.378,23.183,4.681,32.028z"/> + <path opacity=".12" d="M34.486,15.545c-0.825-0.046-1.653-0.072-2.486-0.072s-1.661,0.026-2.486,0.072 C18.336,16.312,8.353,22.187,3,30.496c0.48,0.746,1.011,1.464,1.563,2.168c0.322-0.164,0.617-0.393,0.851-0.699 C10.76,24.983,21.195,20.473,32,20.473s21.24,4.511,26.585,11.492c0.234,0.307,0.527,0.537,0.849,0.702 c0.553-0.706,1.084-1.425,1.565-2.171C55.647,22.187,45.664,16.312,34.486,15.545z"/> + <path fill="#99999C" d="M60.501,33.528c-0.504,0-0.997-0.254-1.28-0.716C53.701,23.815,43.016,18,32,18 S10.299,23.815,4.779,32.812c-0.434,0.707-1.358,0.927-2.063,0.494c-0.707-0.433-0.928-1.356-0.495-2.062 C8.368,21.225,19.779,15,32,15s23.632,6.225,29.779,16.244c0.433,0.706,0.212,1.63-0.495,2.062 C61.04,33.457,60.769,33.528,60.501,33.528z"/> +</svg> diff --git a/src/assets/images/onap-logo.png b/src/assets/images/onap-logo.png Binary files differnew file mode 100644 index 0000000..41c41cc --- /dev/null +++ b/src/assets/images/onap-logo.png diff --git a/src/assets/images/tiles/cds.svg b/src/assets/images/tiles/cds.svg new file mode 100644 index 0000000..fe9a6fe --- /dev/null +++ b/src/assets/images/tiles/cds.svg @@ -0,0 +1,220 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc='http://purl.org/dc/elements/1.1/'
+ xmlns:cc='http://creativecommons.org/ns#'
+ xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'
+ xmlns='http://www.w3.org/2000/svg'
+ xmlns:xlink='http://www.w3.org/1999/xlink'
+ xmlns:sodipodi='http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd'
+ xmlns:inkscape='http://www.inkscape.org/namespaces/inkscape'
+ width='512'
+ height='512'
+ viewBox='0 0 512 512'
+ version='1.1'
+ id='svg50'
+ sodipodi:docname='cds_512.svg'
+ inkscape:version='1.0.1 (3bc2e813f5, 2020-09-07)'>
+ <metadata
+ id="metadata54">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1920"
+ inkscape:window-height="1001"
+ id="namedview52"
+ showgrid="false"
+ inkscape:zoom="0.8203125"
+ inkscape:cx="-201.60994"
+ inkscape:cy="210.23007"
+ inkscape:window-x="4791"
+ inkscape:window-y="-9"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg50"
+ inkscape:document-rotation="0" />
+ <!-- Generator: Sketch 59.1 (86144) - https://sketch.com -->
+ <title
+ id="title2">logo</title>
+ <desc
+ id="desc4">Created with Sketch.</desc>
+ <defs
+ id="defs10">
+ <polygon
+ id="path-1"
+ points="14.228769,9.2028846 0.065307692,9.2028846 0.065307692,0.30846154 14.228769,0.30846154 " />
+ <polygon
+ id="path-3"
+ points="14.824538,9.1926154 0,9.1926154 0,0.14338461 14.824538,0.14338461 " />
+ <polygon
+ id="path-5"
+ points="7.4436154,8.5450385 0,8.5450385 0,0.029269231 7.4436154,0.029269231 " />
+ <polygon
+ id="path-7"
+ points="14.824538,9.3957692 0,9.3957692 0,0.34653846 14.824538,0.34653846 " />
+ </defs>
+ <g
+ id="g938">
+ <rect
+ style="opacity:1;fill:#ffffff;stroke-width:0.295893"
+ id="rect868"
+ width="512"
+ height="512"
+ x="0"
+ y="0" />
+ <g
+ id="Symbols"
+ stroke="none"
+ stroke-width="1"
+ fill="none"
+ fill-rule="evenodd"
+ transform="matrix(17.195545,0,0,17.195545,0,18.563919)">
+ <g
+ id="Side-Nav"
+ transform="translate(-10,-16)">
+ <g
+ id="logo---icon">
+ <g
+ id="g45">
+ <g
+ id="logo"
+ transform="translate(10,16)">
+ <polygon
+ id="Fill-1"
+ fill="#312f31"
+ points="0.00015384615,18.160692 14.824385,27.307615 29.775154,17.719154 29.775154,9.4553077 14.824385,0.30838461 0.00015384615,9.6445385 " />
+ <g
+ id="Group-26">
+ <g
+ id="Group-4"
+ transform="translate(7.692308)">
+ <mask
+ id="mask-2"
+ fill="#ffffff">
+ <use
+ xlink:href="#path-1"
+ id="use13"
+ x="0"
+ y="0"
+ width="100%"
+ height="100%" />
+ </mask>
+ <g
+ id="Clip-3" />
+ <path
+ d="M 7.1322308,0.30826923 0.06530769,4.7586538 7.1322308,9.2028846 C 9.4976154,7.6855769 11.863385,6.1675 14.228769,4.6501923 11.863385,3.2025 9.4976154,1.7555769 7.1322308,0.30826923"
+ id="Fill-2"
+ fill="#5dbdba"
+ mask="url(#mask-2)" />
+ </g>
+ <path
+ d="m 29.774961,9.4552692 c -2.618076,-1.6015384 -5.235769,-3.2034615 -7.853846,-4.805 -2.365384,1.5173077 -4.731154,3.035 -7.096538,4.5526923 l 7.475,4.6049995 z"
+ id="Fill-5"
+ fill="#17a1a1" />
+ <g
+ id="Group-9"
+ transform="translate(0,4.615385)">
+ <mask
+ id="mask-4"
+ fill="#ffffff">
+ <use
+ xlink:href="#path-3"
+ id="use20"
+ x="0"
+ y="0"
+ width="100%"
+ height="100%" />
+ </mask>
+ <g
+ id="Clip-8" />
+ <polygon
+ id="Fill-7"
+ fill="#17a1a1"
+ mask="url(#mask-4)"
+ points="7.7576154,0.14338461 -7.6923077e-05,5.0291539 7.4437692,9.1926154 14.824538,4.5876154 " />
+ </g>
+ <polygon
+ id="Fill-10"
+ fill="#08809a"
+ points="29.774961,17.719115 29.143423,18.124115 22.299577,13.807961 29.774961,9.4552692 " />
+ <polygon
+ id="Fill-12"
+ fill="#08809a"
+ points="7.4437692,13.808269 14.824538,18.602115 22.299923,13.808269 14.824538,9.2028846 " />
+ <polygon
+ id="Fill-14"
+ fill="#0f699d"
+ points="22.299731,13.808 14.824731,18.602231 21.763577,22.857615 29.143577,18.124154 " />
+ <g
+ id="Group-18"
+ transform="translate(0,9.615385)">
+ <mask
+ id="mask-6"
+ fill="#ffffff">
+ <use
+ xlink:href="#path-5"
+ id="use29"
+ x="0"
+ y="0"
+ width="100%"
+ height="100%" />
+ </mask>
+ <g
+ id="Clip-17" />
+ <polygon
+ id="Fill-16"
+ fill="#08809a"
+ mask="url(#mask-6)"
+ points="-0.00023076923,8.5450385 7.4436154,4.1927308 -0.00023076923,0.029269231 " />
+ </g>
+ <g
+ id="Group-21"
+ transform="translate(0,13.461538)">
+ <mask
+ id="mask-8"
+ fill="#ffffff">
+ <use
+ xlink:href="#path-7"
+ id="use35"
+ x="0"
+ y="0"
+ width="100%"
+ height="100%" />
+ </mask>
+ <g
+ id="Clip-20" />
+ <polygon
+ id="Fill-19"
+ fill="#0f699d"
+ mask="url(#mask-8)"
+ points="14.824538,5.1407692 7.4437692,0.34653846 -7.6923077e-05,4.6992308 7.6118461,9.3957692 " />
+ </g>
+ <polygon
+ id="Fill-22"
+ fill="#1b3d6e"
+ points="14.824538,18.602462 7.6118461,22.857461 14.824538,27.307461 21.763385,22.857461 " />
+ <path
+ d="m 10.958115,20.1415 c -0.820384,0 -1.5015381,-0.07269 -2.0438458,-0.218077 -0.5430769,-0.145385 -0.9765384,-0.387308 -1.3003846,-0.725 -0.3242308,-0.337308 -0.5561538,-0.790385 -0.695,-1.359231 C 6.7804231,17.269961 6.7108077,16.561885 6.7108077,15.715346 v -4.803461 c 0,-0.846539 0.069615,-1.5546158 0.2080769,-2.1238465 0.1388462,-0.5684616 0.3707692,-1.0253846 0.695,-1.3692308 C 7.9377308,7.0745769 8.3711923,6.8330385 8.9142692,6.6941923 9.4565769,6.5553461 10.137731,6.4857308 10.958115,6.4857308 h 7.661539 c 0.503077,0 0.942692,0.069615 1.32,0.2084615 0.376923,0.1388462 0.697692,0.3111538 0.962307,0.5161539 0.265,0.2053846 0.476924,0.4234615 0.635385,0.6549999 0.158846,0.2319231 0.278077,0.4400001 0.357692,0.6250001 L 20.187731,10.237269 C 20.0685,9.9726539 19.876577,9.7311154 19.612346,9.5126539 c -0.265,-0.2184616 -0.655,-0.3273077 -1.171154,-0.3273077 h -7.463077 c -0.595384,0 -1.0123073,0.1257692 -1.2503842,0.376923 C 9.4896539,9.8138077 9.3704231,10.263808 9.3704231,10.911885 v 4.823077 c 0,0.291538 0.02,0.542692 0.059231,0.754615 0.04,0.211538 0.1157693,0.390384 0.2284616,0.535384 0.1123077,0.14577 0.2746154,0.255385 0.4865383,0.327693 0.211538,0.07269 0.489231,0.108846 0.833461,0.108846 h 7.562308 c 0.529231,0 0.919231,-0.108846 1.171154,-0.326923 0.251154,-0.218462 0.436538,-0.46 0.555384,-0.724615 l 1.707308,1.726538 c -0.07923,0.185769 -0.198461,0.394615 -0.357308,0.625385 -0.158846,0.231923 -0.370769,0.45 -0.635,0.655 -0.265,0.205384 -0.585769,0.377307 -0.962692,0.516153 -0.377308,0.138847 -0.817308,0.208462 -1.320384,0.208462 z"
+ id="Fill-24"
+ fill="#fefefe" />
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/src/assets/images/tiles/dcae-mod.svg b/src/assets/images/tiles/dcae-mod.svg new file mode 100644 index 0000000..90efc07 --- /dev/null +++ b/src/assets/images/tiles/dcae-mod.svg @@ -0,0 +1,279 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + version="1.1" + id="svg226" + width="512" + height="512" + viewBox="0 0 512 512" + sodipodi:docname="dcae-mod1.svg" + inkscape:version="1.1.1 (c3084ef, 2021-09-22)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs230" /> + <sodipodi:namedview + id="namedview228" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:zoom="1.4511719" + inkscape:cx="256" + inkscape:cy="256" + inkscape:window-width="1312" + inkscape:window-height="969" + inkscape:window-x="0" + inkscape:window-y="25" + inkscape:window-maximized="0" + inkscape:current-layer="g232" /> + <g + inkscape:groupmode="layer" + inkscape:label="Image" + id="g232"> + <image + width="512" + height="512" + preserveAspectRatio="none" + xlink:href="data:image/png;base64,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 +" + id="image234" /> + </g> +</svg> diff --git a/src/assets/images/tiles/kibana.svg b/src/assets/images/tiles/kibana.svg new file mode 100644 index 0000000..072f2a6 --- /dev/null +++ b/src/assets/images/tiles/kibana.svg @@ -0,0 +1,84 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc='http://purl.org/dc/elements/1.1/'
+ xmlns:cc='http://creativecommons.org/ns#'
+ xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'
+ xmlns='http://www.w3.org/2000/svg'
+ xmlns:sodipodi='http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd'
+ xmlns:inkscape='http://www.inkscape.org/namespaces/inkscape'
+ width='512'
+ height='512'
+ viewBox='0 0 512 512'
+ version='1.1'
+ id='svg12'
+ sodipodi:docname='kibana.svg'
+ inkscape:version='1.0.1 (3bc2e813f5, 2020-09-07)'>
+ <metadata
+ id="metadata18">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs16" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="2400"
+ inkscape:window-height="1271"
+ id="namedview14"
+ showgrid="false"
+ inkscape:zoom="0.50754247"
+ inkscape:cx="-761.90676"
+ inkscape:cy="175.8502"
+ inkscape:window-x="2391"
+ inkscape:window-y="-9"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg12" />
+ <!-- Generator: Sketch 63.1 (92452) - https://sketch.com -->
+ <title
+ id="title2">kibana-logo-color-64px</title>
+ <desc
+ id="desc4">Created with Sketch.</desc>
+ <g
+ id="kibana-logo-color-64px"
+ stroke="none"
+ stroke-width="1"
+ fill="none"
+ fill-rule="evenodd"
+ transform="scale(8)">
+ <rect
+ id="bounding-box"
+ x="0"
+ y="0"
+ width="64"
+ height="64" />
+ <g
+ id="group"
+ transform="translate(11,4.9999)">
+ <path
+ d="M 0,20.25 V 48.581 L 20.137,25.392 C 14.149,22.13 7.299,20.25 0,20.25"
+ id="Fill-1"
+ fill="#343741" />
+ <path
+ d="m 0,0 v 20.25 c 7.299,0 14.149,1.88 20.137,5.142 L 42.188,0 Z"
+ id="Fill-3"
+ fill="#f04e98" />
+ <path
+ d="m 24.4434,28.0591 -20.668,23.801 -1.859,2.14 h 39.425 c -2.163,-10.658 -8.349,-19.851 -16.898,-25.941"
+ id="Fill-6"
+ fill="#00bfb3" />
+ </g>
+ </g>
+</svg>
diff --git a/src/assets/images/tiles/onap.svg b/src/assets/images/tiles/onap.svg new file mode 100644 index 0000000..f76048b --- /dev/null +++ b/src/assets/images/tiles/onap.svg @@ -0,0 +1,157 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc='http://purl.org/dc/elements/1.1/'
+ xmlns:cc='http://creativecommons.org/ns#'
+ xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'
+ xmlns='http://www.w3.org/2000/svg'
+ xmlns:sodipodi='http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd'
+ xmlns:inkscape='http://www.inkscape.org/namespaces/inkscape'
+ width='135.46666mm'
+ height='135.46667mm'
+ viewBox='0 0 135.46666 135.46667'
+ version='1.1'
+ id='svg8'
+ inkscape:version='1.0.1 (3bc2e813f5, 2020-09-07)'
+ sodipodi:docname='onap_512.svg'>
+ <defs
+ id="defs2" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1"
+ inkscape:cx="254.99999"
+ inkscape:cy="382.49625"
+ inkscape:document-units="mm"
+ inkscape:current-layer="layer1"
+ inkscape:document-rotation="0"
+ showgrid="false"
+ showguides="true"
+ inkscape:guide-bbox="true"
+ inkscape:window-width="1920"
+ inkscape:window-height="1001"
+ inkscape:window-x="4791"
+ inkscape:window-y="-9"
+ inkscape:window-maximized="1" />
+ <metadata
+ id="metadata5">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-38.364587,-46.964534)">
+ <g
+ id="g891">
+ <rect
+ style="fill:none;stroke-width:0.0828541"
+ id="rect931"
+ width="135.46645"
+ height="135.46667"
+ x="38.364693"
+ y="46.964535" />
+ <g
+ id="g929"
+ transform="matrix(0.71408631,0,0,0.71408744,30.33485,32.793562)">
+ <g
+ id="g909">
+ <path
+ style="fill:#252728;fill-opacity:1;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 11.386385,144.42823 -0.0093,53.56829 h 85.539418 z"
+ id="path7778" />
+ <path
+ style="fill:#252728;fill-opacity:1;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 200.80945,144.42823 0.009,53.56829 h -85.53941 z"
+ id="path7780" />
+ <path
+ style="fill:#252728;fill-opacity:1;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 200.80975,84.967496 0.009,-53.568284 h -85.53942 z"
+ id="path7782" />
+ <path
+ style="fill:#252728;fill-opacity:1;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 11.386085,84.967506 -0.009,-53.568294 h 85.539416 z"
+ id="path7784" />
+ </g>
+ <g
+ id="g918"
+ transform="translate(11.377085,34.307641)">
+ <path
+ id="path7720"
+ style="opacity:1;fill:#1f3d7c;fill-opacity:1;stroke:none;stroke-width:1.48358;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
+ d="M 96.13733,150.99858 58.341783,127.44042 c 8.715431,-10.97674 22.069544,-18.22157 37.795545,-23.55817 18.664302,6.41492 28.816872,14.84742 37.795552,23.55817 z"
+ sodipodi:nodetypes="ccccc" />
+ <g
+ id="g7923"
+ transform="translate(9.5787166e-5,5.9572513e-5)">
+ <path
+ id="path7722"
+ style="opacity:0.999;fill:#0081a4;fill-opacity:1;stroke:none;stroke-width:5.60724;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 77.654297,214.54883 -12.035156,7.50195 V 385.12305 L 77.654297,392.625 C 134.38081,367.89947 180.88136,337.61289 220.50391,303.58594 178.10009,266.29585 130.2023,237.02747 77.654297,214.54883 Z"
+ transform="scale(0.26458333)"
+ sodipodi:nodetypes="cccccc" />
+ <path
+ id="path7724"
+ style="opacity:0.999;fill:#0081a4;fill-opacity:1;stroke:none;stroke-width:2.8;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
+ transform="matrix(0.6711242,0,0,0.41831531,31.023878,52.065734)"
+ d="M 97.021318,123.86938 C 70.596563,109.56205 54.910314,88.989236 40.704548,67.552614 57.969944,45.682337 76.496459,26.404851 97.021315,11.235844 121.08206,26.256569 139.1231,45.547538 153.33809,67.552611 138.87483,91.09219 119.569,109.27412 97.021318,123.86938 Z"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ id="path7726"
+ style="opacity:0.999;fill:#0081a4;fill-opacity:1;stroke:none;stroke-width:5.60724;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 649.05273,214.54883 c -50.75146,26.54411 -102.16252,52.42863 -142.84961,89.03711 37.05592,34.81884 82.35689,65.62536 142.84961,89.03906 l 12.03516,-7.50195 V 222.05078 Z"
+ transform="scale(0.26458333)"
+ sodipodi:nodetypes="cccccc" />
+ </g>
+ <g
+ id="g7746"
+ style="opacity:1;fill:#00b0aa;fill-opacity:1"
+ transform="translate(144.72404,-78.959013)">
+ <path
+ id="path7733"
+ style="opacity:0.999;fill:#00b0aa;fill-opacity:1;stroke:none;stroke-width:2.8;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
+ transform="matrix(0.6711242,0,0,0.41831531,-151.49571,107.46658)"
+ d="M 97.021318,123.86938 40.704548,67.552614 97.021315,11.235844 C 117.7448,26.909858 136.47987,45.741167 153.33809,67.552611 Z"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ id="path7735"
+ style="opacity:1;fill:#00b0aa;fill-opacity:1;stroke:none;stroke-width:2.8;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
+ transform="matrix(0.6711242,0,0,0.41831531,-75.904619,107.46658)"
+ d="M 97.021318,123.86938 40.704548,67.552614 c 15.71848,-22.033132 35.252803,-39.99164 56.316767,-56.31677 l 56.316775,56.316767 z"
+ sodipodi:nodetypes="ccccc" />
+ </g>
+ <path
+ id="path7748"
+ style="opacity:1;fill:#69c7b9;fill-opacity:1;stroke:none;stroke-width:1.48358;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
+ d="M 96.13723,56.765859 58.341683,33.207694 96.137228,9.6495269 133.93278,33.207693 Z" />
+ <g
+ id="g7754"
+ style="opacity:1;fill:#006fa0;fill-opacity:1"
+ transform="translate(144.72414,-31.842621)">
+ <path
+ id="path7750"
+ style="opacity:0.999;fill:#006fa0;fill-opacity:1;stroke:none;stroke-width:2.8;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
+ transform="matrix(0.6711242,0,0,0.41831531,-151.49571,107.46658)"
+ d="M 97.021318,123.86938 40.704548,67.552614 97.021315,11.235844 153.33809,67.552611 Z" />
+ <path
+ id="path7752"
+ style="opacity:0.999;fill:#006fa0;fill-opacity:1;stroke:none;stroke-width:2.8;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
+ transform="matrix(0.6711242,0,0,0.41831531,-75.904619,107.46658)"
+ d="M 97.021318,123.86938 40.704548,67.552614 97.021315,11.235844 153.33809,67.552611 Z" />
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/src/assets/images/tiles/sdc.svg b/src/assets/images/tiles/sdc.svg new file mode 100644 index 0000000..04cefab --- /dev/null +++ b/src/assets/images/tiles/sdc.svg @@ -0,0 +1,96 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc='http://purl.org/dc/elements/1.1/'
+ xmlns:cc='http://creativecommons.org/ns#'
+ xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'
+ xmlns='http://www.w3.org/2000/svg'
+ xmlns:xlink='http://www.w3.org/1999/xlink'
+ xmlns:sodipodi='http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd'
+ xmlns:inkscape='http://www.inkscape.org/namespaces/inkscape'
+ width='135.46666mm'
+ height='135.46666mm'
+ viewBox='0 0 135.46666 135.46666'
+ version='1.1'
+ id='svg1715'
+ inkscape:version='1.0.1 (3bc2e813f5, 2020-09-07)'
+ sodipodi:docname='sdc_512.svg'>
+ <defs
+ id="defs1709">
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient851"
+ id="linearGradient1672"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.3911867,0,0,2.3661441,-145.87097,-204.18732)"
+ x1="95.654984"
+ y1="137.89748"
+ x2="114.46542"
+ y2="148.75768" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient851">
+ <stop
+ style="stop-color:#1ae5d9;stop-opacity:1"
+ offset="0"
+ id="stop847" />
+ <stop
+ style="stop-color:#4b7cc9;stop-opacity:1"
+ offset="1"
+ id="stop849" />
+ </linearGradient>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4"
+ inkscape:cx="240.19182"
+ inkscape:cy="200.15801"
+ inkscape:document-units="mm"
+ inkscape:current-layer="layer1"
+ inkscape:document-rotation="0"
+ showgrid="false"
+ inkscape:window-width="2400"
+ inkscape:window-height="1271"
+ inkscape:window-x="2391"
+ inkscape:window-y="-9"
+ inkscape:window-maximized="1" />
+ <metadata
+ id="metadata1712">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-37.266669,-80.76667)">
+ <rect
+ style="fill:#ffffff;stroke-width:0.1"
+ id="rect843"
+ width="47.247025"
+ height="19.654762"
+ x="81.376488"
+ y="167.51221" />
+ <path
+ id="rect1648"
+ style="fill:#2c333c;fill-opacity:1;stroke-width:0.1"
+ d="M 37.266668,80.76667 V 216.23333 H 172.73333 V 80.76667 Z m 68.051142,28.80444 c 0.008,-5e-5 0.0169,-5e-5 0.0253,0 0.37568,0.0253 0.737,0.1074 1.05627,0.27957 6.74476,4.33831 13.55385,8.09768 20.38635,11.64632 0.62356,0.39304 1.00213,1.10293 1.05161,1.81229 -0.45264,7.75818 -0.1237,15.51637 0,23.27455 -0.0243,0.71973 -0.51981,1.29816 -1.05161,1.81178 -7.06313,3.50751 -13.75925,7.52884 -20.38633,11.64683 -0.61604,0.2797 -1.4333,0.32478 -2.10323,0 -6.529496,-4.03003 -13.080116,-8.04832 -20.386356,-11.64683 -0.59609,-0.38772 -0.952697,-1.09256 -1.051615,-1.81178 0.194219,-7.80674 0.483868,-15.63733 0,-23.27455 0.05981,-0.71636 0.509685,-1.38156 1.051615,-1.81229 7.14441,-3.53315 13.856931,-7.49819 20.386356,-11.64632 0.31868,-0.16359 0.68515,-0.22987 1.02164,-0.27957 z m -0.032,2.06396 c -0.57462,0.003 -1.13829,0.15742 -1.63401,0.44803 -6.525104,3.41263 -12.716996,7.06327 -18.618539,10.9213 v 0.0129 c 6.670706,4.06704 13.326132,8.15445 20.256129,11.87576 7.09558,-3.8726 13.8416,-7.83842 20.26904,-11.88919 v -0.0134 c -6.04188,-3.7501 -11.96787,-7.58298 -18.60506,-10.90786 -0.49577,-0.29043 -1.05944,-0.4448 -1.63401,-0.44752 -0.0112,-6e-5 -0.0224,-6e-5 -0.0336,0 z m -20.552234,13.25139 -0.01188,0.006 c -0.166708,6.83653 -0.301451,13.68584 -0.03049,20.69744 -0.0013,0.89912 0.479559,1.72992 1.259872,2.17661 6.005006,3.92556 12.15492,7.27149 18.336352,10.49135 l 0.0124,-0.006 c 0.14844,-7.28293 0.3112,-14.56586 0.0263,-21.84879 -6.185763,-4.13466 -12.784737,-7.91514 -19.592554,-11.51661 z m 41.228494,0 c -6.65595,3.66352 -13.15809,7.54237 -19.59209,11.51661 -0.28213,7.39937 -0.1253,14.62315 0.0269,21.84879 l 0.0109,0.006 c 6.11212,-3.40849 12.22423,-6.59129 18.33635,-10.49135 1.07293,-0.3839 1.39195,-1.24945 1.26039,-2.17661 0.53235,-7.13183 -0.004,-13.80574 -0.0305,-20.69796 z m -35.28626,45.13471 c 0.980549,0 1.880378,0.0937 2.698544,0.28112 0.818166,0.18737 1.542193,0.41819 2.172994,0.69298 v 2.19211 h -0.130741 c -0.530874,-0.44968 -1.23045,-0.82112 -2.09858,-1.11466 -0.861886,-0.29978 -1.745917,-0.44958 -2.651519,-0.44958 -0.99304,0 -1.792486,0.20584 -2.398303,0.61805 -0.599572,0.41221 -0.89917,0.94313 -0.89917,1.59267 0,0.58083 0.149799,1.03686 0.449585,1.36787 0.299786,0.33102 0.827656,0.58425 1.583365,0.75913 0.399716,0.0874 0.967832,0.19341 1.704805,0.31833 0.736976,0.12491 1.361654,0.2528 1.87379,0.38395 1.036754,0.27481 1.817349,0.69007 2.341975,1.24592 0.524624,0.55585 0.787032,1.33339 0.787032,2.33267 0,0.54336 -0.127894,1.08092 -0.383955,1.61179 -0.249822,0.53088 -0.602927,0.98027 -1.058852,1.34876 -0.499642,0.39971 -1.083559,0.71205 -1.75183,0.93689 -0.662027,0.22484 -1.461479,0.33745 -2.398302,0.33745 -1.005533,0 -1.910956,-0.0938 -2.716631,-0.28112 -0.79943,-0.18737 -1.614673,-0.46557 -2.445329,-0.83406 v -2.32337 h 0.131257 c 0.705747,0.58708 1.520989,1.04004 2.445329,1.35857 0.924341,0.31852 1.792574,0.47801 2.604492,0.47801 1.149181,0 2.041861,-0.21553 2.678907,-0.64647 0.643292,-0.43095 0.965316,-1.0057 0.965316,-1.72393 0,-0.61831 -0.153374,-1.07433 -0.459404,-1.36787 -0.299786,-0.29355 -0.758867,-0.5213 -1.377177,-0.68368 -0.468416,-0.12492 -0.977429,-0.22783 -1.527038,-0.30903 -0.543361,-0.0812 -1.120648,-0.18463 -1.732711,-0.30954 -1.236617,-0.26231 -2.154782,-0.70865 -2.754355,-1.33945 -0.593325,-0.63705 -0.890384,-1.46452 -0.890384,-2.48254 0,-1.16792 0.493734,-2.12379 1.480529,-2.86701 0.986796,-0.74947 2.238693,-1.12396 3.756361,-1.12396 z m 29.23852,0 c 0.74947,0 1.49592,0.0907 2.23914,0.27182 0.74947,0.18112 1.57999,0.49957 2.49184,0.9555 v 2.20141 h -0.14004 c -0.7682,-0.64329 -1.53045,-1.11154 -2.28617,-1.40508 -0.7557,-0.29354 -1.56432,-0.44028 -2.4262,-0.44028 -0.70575,0 -1.34318,0.11514 -1.91152,0.34623 -0.5621,0.22484 -1.06448,0.57794 -1.50791,1.05885 -0.43095,0.46841 -0.76826,1.06149 -1.01183,1.77973 -0.23733,0.712 -0.35605,1.53641 -0.35605,2.47324 0,0.98055 0.13094,1.82381 0.39326,2.52956 0.26856,0.70575 0.61249,1.28049 1.03094,1.72393 0.43719,0.46216 0.94621,0.80558 1.52704,1.03042 0.58708,0.2186 1.20513,0.32815 1.85467,0.32815 0.89311,0 1.73026,-0.15337 2.51096,-0.45941 0.78068,-0.30602 1.51134,-0.76511 2.19211,-1.37717 h 0.13074 v 2.17351 c -0.3435,0.14989 -0.65533,0.29052 -0.93637,0.42168 -0.27481,0.13116 -0.63708,0.26873 -1.08676,0.41238 -0.38098,0.11866 -0.79625,0.21852 -1.24592,0.29972 -0.44343,0.0874 -0.93411,0.13126 -1.47123,0.13126 -1.01178,0 -1.933,-0.14064 -2.76365,-0.42168 -0.82442,-0.28729 -1.54233,-0.73415 -2.15439,-1.33997 -0.59958,-0.59333 -1.06834,-1.3459 -1.4056,-2.25775 -0.33726,-0.9181 -0.50592,-1.983 -0.50592,-3.19463 0,-1.14918 0.16255,-2.17638 0.48731,-3.08198 0.32478,-0.90561 0.79303,-1.6704 1.40509,-2.29495 0.59332,-0.60582 1.3087,-1.06847 2.1456,-1.387 0.84315,-0.31852 1.7766,-0.47749 2.80086,-0.47749 z m -20.825598,0.2527 h 3.485058 c 1.36153,0 2.44224,0.0999 3.24166,0.29972 0.80568,0.19361 1.4864,0.46265 2.04226,0.80615 0.94932,0.59333 1.68915,1.38308 2.22002,2.36988 0.53087,0.9868 0.79633,2.15769 0.79633,3.51297 0,1.26785 -0.27769,2.41734 -0.83354,3.44785 -0.54961,1.03051 -1.28384,1.82996 -2.20194,2.3983 -0.63704,0.39347 -1.34884,0.67779 -2.13578,0.85266 -0.78069,0.17488 -1.81095,0.262 -3.09128,0.262 h -3.522788 z m 1.855188,1.59266 v 10.76421 h 1.74253 c 0.89311,0 1.67064,-0.0652 2.33267,-0.19638 0.66827,-0.13115 1.28021,-0.37522 1.83606,-0.73122 0.69326,-0.44343 1.21145,-1.02735 1.55495,-1.75183 0.34975,-0.72448 0.52451,-1.62991 0.52451,-2.71663 0,-1.09297 -0.19004,-2.01419 -0.57102,-2.76365 -0.38098,-0.74947 -0.94962,-1.3395 -1.70532,-1.77044 -0.54961,-0.31228 -1.13352,-0.5278 -1.75184,-0.64647 -0.6183,-0.12491 -1.35813,-0.18759 -2.22001,-0.18759 z"
+ sodipodi:nodetypes="ccccccccccccccccccccccccccccsccccccccccccccccccscccccscsscscsscccsccccsscscccccscssccccsscccscccssccccccscccssccscsccsscccsccccscccssccsc" />
+ <path
+ id="path1670"
+ style="opacity:1;fill:url(#linearGradient1672);fill-opacity:1;stroke-width:3.09223;stroke-linecap:round"
+ d="m 105.34297,109.57121 c -0.36729,7.7e-4 -0.72808,0.097 -1.04701,0.27913 L 83.909519,121.4971 c -0.650209,0.37155 -1.051463,1.06302 -1.05142,1.8119 v 23.27462 c -5.1e-5,0.74888 0.401205,1.44037 1.05142,1.81192 l 20.386441,11.64676 c 0.65163,0.37228 1.45154,0.37228 2.10317,0 l 20.38641,-11.64676 c 0.65034,-0.37147 1.05173,-1.06297 1.05174,-1.81192 V 123.309 c -2e-5,-0.74894 -0.40141,-1.44044 -1.05174,-1.8119 l -20.38641,-11.64676 c -0.32162,-0.18371 -0.68577,-0.27995 -1.05616,-0.27913 z m -0.0571,2.06355 c 0.0111,-6e-5 0.0223,-6e-5 0.0334,0 0.57458,0.003 1.13822,0.15739 1.63392,0.44795 l 18.60497,10.90786 v 0.0132 l -20.26905,11.8892 -20.255751,-11.87561 v -0.0132 l 18.618581,-10.92118 c 0.49567,-0.29067 1.05931,-0.44529 1.63391,-0.44825 z m -20.552611,13.2517 19.592831,11.51667 -0.0266,21.84884 -0.0119,0.006 -18.336511,-10.49126 c -0.780478,-0.44664 -1.261492,-1.27753 -1.26017,-2.17677 l 0.0307,-20.69748 z m 41.228501,0 0.0119,0.006 0.0307,20.69748 c 10e-4,0.8993 -0.47988,1.7302 -1.26047,2.17677 l -18.33649,10.49126 -0.0107,-0.006 -0.0268,-21.84884 z"
+ sodipodi:nodetypes="ccccccccccccccccccccccccccccccccccccccccc" />
+ </g>
+</svg>
diff --git a/src/assets/images/tiles/sdnc-dg.svg b/src/assets/images/tiles/sdnc-dg.svg new file mode 100644 index 0000000..6b93a58 --- /dev/null +++ b/src/assets/images/tiles/sdnc-dg.svg @@ -0,0 +1,534 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + version="1.1" + id="svg387" + width="1200" + height="1200" + viewBox="0 0 1200 1200" + sodipodi:docname="onap_lighty.jpg.svg" + inkscape:version="1.1.1 (c3084ef, 2021-09-22)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs391" /> + <sodipodi:namedview + id="namedview389" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:zoom="0.59916667" + inkscape:cx="630.04172" + inkscape:cy="469.81919" + inkscape:window-width="1306" + inkscape:window-height="969" + inkscape:window-x="0" + inkscape:window-y="25" + inkscape:window-maximized="0" + inkscape:current-layer="g393" /> + <g + inkscape:groupmode="layer" + inkscape:label="Image" + id="g393"> + <image + width="1200" + height="1200" + preserveAspectRatio="none" + xlink:href="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAoHCAkIBgoJCAkMCwoMDxoRDw4ODx8WGBMaJSEnJiQh +JCMpLjsyKSw4LCMkM0Y0OD0/QkNCKDFITUhATTtBQj//2wBDAQsMDA8NDx4RER4/KiQqPz8/Pz8/ +Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz//wgARCASwBLADAREA +AhEBAxEB/8QAHAABAAICAwEAAAAAAAAAAAAAAAECBgcEBQgD/8QAGgEBAQEAAwEAAAAAAAAAAAAA +AAECBAUGA//aAAwDAQACEAMQAAAA3MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +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 +HEMXOGdiZMcgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgpi9L1PYdR1nO4PG5Nda5nM43ddlwO87Prrak +gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4HB5GJ ++W7ricfk11a6tdWNWu9cnk8fNfQ+f7HlcYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAQcLg/fDfG9/wDPO671XVrq11Y1a71XVt9cbA9L5jncjjyAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACmbhXiO/4nE5Eb +tdarq11a6satd6rq11ez5/Bz/wBD5qQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAdP0/MxbyPdV1qN2utV1a6tdWNWu9V1a6tfo2X6fyPK+vyAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFZeLxvrEvJ5Hy+m8gAAADE/Id +x1XUc+urG7XWq6tdWurGrXeq6tdWurn/AKTy3bcriAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAADjcf6Y90HadT1PO+OPpGrFvYdhxMk77qe05/EAAAgwvw3fcPhciu +tRu11qurXVrqxq13qurXVrq536LzXdczgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAACDrOr5eKeU7r5/P6V0i2NWLYtrq9/3XVZV3/TWoACIwzw/e8LhcmutRu11qur +XVrqxq13qurXVrq536LzXdczgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAADgcD74f4zv6ZsXVdItjVi2La6saZJ3nT5R3nUgADGPK9t0vR9jXVjdrrVdWurXVjVrvVd +WurXVzv0Xme65nBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEERh +fh+/4nC5EaRdV0i2NWLYtrqxU/SbE9h5X7fXEgA6vq+ViXju9rbG7XWq6tdWurGrXeq6tdWurnfo +vM91zOCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIOt6zk4l4vvY +1YqLqukWxqxbFtdWKjVzH0vn+77LgSACuWHeM73r+By43a61XVrq11Y1a71XVrq11e+7Pq827vz8 +gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEHQed7LH/NdpGrFRdV0 +i2NWLYtrqxUauT9/0uS9x1UgAg4vF+uHeN7/AI/y+tdarq11a6satd6rq11a6sb1kna9NmPbdFIA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIMX8j2/UdNz41YqLqukWx +qxbFtdWKjVyPvOoynu+nkAAHF4/0xrznb9T1nOpd11a6satd6rq11a6tdajVyTtOmzLtuhsAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQY55jtOj8/wBlGrFRdV0i2NWL +YtrqxUauR931GU9508gAAA+Pz3weHya5vH+f0+31x8s7x/rez6nic+urXWo1a71z+Tw+35fBiotq +cn6fHtvvwe3+3DsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACI6nqOZi3 +kO6jViouq6RbGrFsW11YqNXK/Q9HkPbdZIAAAAAAKxiHS95jfW9xW6jVrvVdWurTSlVqmlLOf9uL +sXsfNdv9eJIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIPn8tYR4P0Hy+X +1jSLqukWxqxbFtdWKjVyPvOnynu+okAAAAAAEAw3pe9xvre5jVrvVdWurTSlVqmlLKVbedq9n5Lu +PrxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0fRdhjXlu3jSLqukWxqx +bFtdWKjV+n2xnnqfM83kfEAAAAAAAVl190Hpuq4vYV3qurXVppSq1TSllKpp2H24m4Oz8jKSAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACIxvzXa9F0PZRdV0i2NWLYtrqxUas +W8nlfDOPS+c5n3+MgAAAAAAgxjre2w/p/Q13qurXVppSq1TSllKppWtndj5XJfv18gAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6nquZ0fSdj1/C5Pzx9I1Yti2urFRqxq1t5 +PI+Ga+i892XK4wAAAAAAgxvru0wzpvR13qurXVppSq1TSllKppWss5XTbI53ngAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKxXOgIjqeu52Jef7v5Z+katbYtbcvk8e2pxPn +94urfTPb8vgZJ2PU9lyOJIAAIMb67tMM6b0dd6rq11aaUqtU0pZSqaVrtvvwdu9j5OQAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAddw+ThPmfQ/DH2rbFsatajVi2LY1Y +tjTJey6bM+16CSQAQY113a4b03oq71XVrq00pVappSylU0rXe8jrdrdh5eQAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQdfxOTgvmPSfLP0i2NWtRqxbFsasWxq1rKOz6 +TM+z6GQAQdFwewwXo/T13qurXVppSq1TSllKppWsv5fS7E5vn5AAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABjfUdpifRd7FsatajVi2LY1YtjVrUbbM73x/Y/bjACDi/ +L66y837Gt3Xdrq00pVappSylU0rW2ez8h3X14kgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAA6jg8zBvM+ki6jVrUasWxbGrFsatajVyXsOlzjtPPgAQa/wCi9P03E7Gu +9V1aaUqtU0pZSqaZByOs2j2PmJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AOJx/t1/C5Py+f0v9c9jzOJy+R8ZAAAB0/A5uD+a9JFsatajVi2LY1YtjVrUavM5HF2h3nj5AAOF +8vvrnovV8bHIrq00pVappSylc/7cXavZ+T5evmAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAOJxvri/mu56vrubXdrrUatdXsew4eWd50nYcrjSAADHeq7LEeg7+LY1a1GrFsWxq +xbGrWo1ft9fjtbv/ABcgAEHE+X2wbqfSdNx+xppSq1TSlmRcvq8/5/neVr5yAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDr+v5GH+Q77553XWq7tdajVru11X0maeg893nP4AAA +x/q+xw/z/oItjVrUasWxbGrFsatajV+/2+G1e+8ZIAABB1PH5uP8Ts+Hj7xXP+3FyDldb2n14kgA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4/H+mE+H9B8sfWurXVru11qNWu7 +XVrqz9M7E9P5Xmfb4yADreJysB8t6aLqNWtRqxbFsasWxq1qNXvOb1ewe38yAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMZ8v2vSdF2Vdarq11a7tdajVru11a6tdXJ +e46bLu36WQAVl175X0/C4/KjVrUasWxbGrFsatajV7vm9XsLt/MgAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACCuLgvgfQ/P5/WutV1a6td2utRq13a6tdWur2fO4OwPQ ++akAEHR9b2GF+f8ARRbWo1Yti2NWLY1a1Grb6Y2V3fkew+vGkAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAEHE4f1wvwvoIuq61XVrq13a61GrXdrq11a6v1+/z2d6fyE0 +ABBiXSd1jfU9xW2NWLYtjVi2NWtRqxbyPtx9i9x5TsfrxwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAABB13W8nEfFd7GrXWq6tdWu7XWo1a7tdWurXV+n3+Wz/AE/kZoAA +QdB1vZYt1HdcP48iNWLY1YtjVrUasW1rk/bj7D7fy3Z/XiyAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAACDjcX6YT4P0MXVdarq11a7tdajVru11a6tdX6/f57O9P5CaAAA +FY63jcvr+PyoXk/X4zXC+XIw/re++U+kW1qtTrPdcrr73FFiuZ9Phzvpx++5HXdhv4AAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARlg/hfQcfjfeurXWq6td2utRq13a6tdWu +r9fv8tnen8jNAAAAAACDrfhytd9L6v4Z+1arVarVarZWq1FRqZjyulzvndD9EAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHQ+f7HHPNdvXVrq11a7tdajVru11a6tdWftnZ3p +vIfXeQAAAAAAB1nw5WuOm9Z8c/WtVqtVqtlarUVWqmWcvp9jc7zsgAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAHzxcN8b3vC4PLrq11a7tdajVru11a6tdWutd12PW5z3fnbWS +AAAAAACDHeJ2eBdR6itVqtVqtlarUVWqla2n2XlMh+3AkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAEHw+G8S8n3nX8Ll1tru11qNWu7XVrq11a61Gr3fY9ZnPc+dvYAAAAAAI +Pjnepug9tVqtVqtVsrVaiq1UrXeffrtsdj5aQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAVjrOt5fU9bzuJ8Pv8cfSNWurxs/Xi/P711a61GrXWu05vAzHteh53148kA+msWA +AABB8871J0HtqtVqtVqtlarUVWqlanXz3f2vi/rcgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAVjF+o7jFeo7yurGrXVrrVd2urSqaUPp9Pn33K63MOZ0nbfXigACD553q +ToPbVarVarVbK1WoqtVK1Wtxdn47tfpxgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAABBjPV9tiHT9/FtdWutV3a6tKppSq1SxvOxex8zk/I62QAQfPO9SdD7as1Wq1Wq2V +qtRVaqVqtm5+08Z2G/iAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +MS6nusV6rvK6tdaru11aVTSlVqllNGs7Y7TyPcfTigAUl1P0XtPhj7VqtVqtlarUVWqla5H0+G6u +z8bewAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfPOtY+a9h8M/Wu +tV3a6tKppSq1SymlK7/kdbtPsfLyACDW/T+q6bjdjWq1Wq2VqtRVaqVrMOZ0uxOZ5+QAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARGsPNew42PvXWq7tdWlU0pVapZTS +lV1N1dr4vla+UgAx7i9jr7qPU1trVarZWq1FVqp9vp8tw9n4/l6+UgAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiNYea9hxsfeutV3a6tKppSq1SymlKrW0uy8pkX24E +gAgwjru/xPgd5Wq1WytVqKrVtY2h2Plu/wDtwQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAABEaw817DjY+9daru11aVTSlVqllNKVWtodj5XJPv18gAEGLcLt8K6/wBB +xp9K2VqtRXZ/bh7E5/nO3+vEkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAEGtfO+s4Pw5ddaru11aVTSlVqllNKVWts9n5Du/rxJAABB8s76Dj9j1Hx5vEz9uw+vF7v +7cDuvvwbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgwPovR9H +w+0rrVd2urSqaUqtUsppSr/T5br7Txn0uZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAABB0XC7DBOj9PXWq7tdWlU0pVapZTSlZtzeiz3mdEAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIKy686H1HVfDsK6tdWlU0 +pVapZTTsPrxNtdp5L7XIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAA4vz+mBdN6fqfhz66tKppSq1SztPvwtmdl5fmb+UgAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgrLjfB7bGOH3HV/HmU0odh9uJlXN6fKu +X1H0sAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +HwzviY+3K38vvr5yAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +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 +sY+cmPOYU64s1Uon/hsP/9k= +" + id="image395" /> + </g> +</svg> diff --git a/src/assets/images/tiles/sdnc-odl.svg b/src/assets/images/tiles/sdnc-odl.svg new file mode 100644 index 0000000..6b93a58 --- /dev/null +++ b/src/assets/images/tiles/sdnc-odl.svg @@ -0,0 +1,534 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + version="1.1" + id="svg387" + width="1200" + height="1200" + viewBox="0 0 1200 1200" + sodipodi:docname="onap_lighty.jpg.svg" + inkscape:version="1.1.1 (c3084ef, 2021-09-22)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs391" /> + <sodipodi:namedview + id="namedview389" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:zoom="0.59916667" + inkscape:cx="630.04172" + inkscape:cy="469.81919" + inkscape:window-width="1306" + inkscape:window-height="969" + inkscape:window-x="0" + inkscape:window-y="25" + inkscape:window-maximized="0" + inkscape:current-layer="g393" /> + <g + inkscape:groupmode="layer" + inkscape:label="Image" + id="g393"> + <image + width="1200" + height="1200" + preserveAspectRatio="none" + xlink:href="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAoHCAkIBgoJCAkMCwoMDxoRDw4ODx8WGBMaJSEnJiQh +JCMpLjsyKSw4LCMkM0Y0OD0/QkNCKDFITUhATTtBQj//2wBDAQsMDA8NDx4RER4/KiQqPz8/Pz8/ +Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz//wgARCASwBLADAREA +AhEBAxEB/8QAHAABAAICAwEAAAAAAAAAAAAAAAECBgcEBQgD/8QAGgEBAQEAAwEAAAAAAAAAAAAA +AAECBAUGA//aAAwDAQACEAMQAAAA3MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +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 +HEMXOGdiZMcgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgpi9L1PYdR1nO4PG5Nda5nM43ddlwO87Prrak +gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4HB5GJ ++W7ricfk11a6tdWNWu9cnk8fNfQ+f7HlcYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAQcLg/fDfG9/wDPO671XVrq11Y1a71XVt9cbA9L5jncjjyAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACmbhXiO/4nE5Eb +tdarq11a6satd6rq11ez5/Bz/wBD5qQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAdP0/MxbyPdV1qN2utV1a6tdWNWu9V1a6tfo2X6fyPK+vyAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFZeLxvrEvJ5Hy+m8gAAADE/Id +x1XUc+urG7XWq6tdWurGrXeq6tdWurn/AKTy3bcriAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAADjcf6Y90HadT1PO+OPpGrFvYdhxMk77qe05/EAAAgwvw3fcPhciu +tRu11qurXVrqxq13qurXVrq536LzXdczgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAACDrOr5eKeU7r5/P6V0i2NWLYtrq9/3XVZV3/TWoACIwzw/e8LhcmutRu11qur +XVrqxq13qurXVrq536LzXdczgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAADgcD74f4zv6ZsXVdItjVi2La6saZJ3nT5R3nUgADGPK9t0vR9jXVjdrrVdWurXVjVrvVd +WurXVzv0Xme65nBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEERh +fh+/4nC5EaRdV0i2NWLYtrqxU/SbE9h5X7fXEgA6vq+ViXju9rbG7XWq6tdWurGrXeq6tdWurnfo +vM91zOCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIOt6zk4l4vvY +1YqLqukWxqxbFtdWKjVzH0vn+77LgSACuWHeM73r+By43a61XVrq11Y1a71XVrq11e+7Pq827vz8 +gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEHQed7LH/NdpGrFRdV0 +i2NWLYtrqxUauT9/0uS9x1UgAg4vF+uHeN7/AI/y+tdarq11a6satd6rq11a6sb1kna9NmPbdFIA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIMX8j2/UdNz41YqLqukWx +qxbFtdWKjVyPvOoynu+nkAAHF4/0xrznb9T1nOpd11a6satd6rq11a6tdajVyTtOmzLtuhsAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQY55jtOj8/wBlGrFRdV0i2NWL +YtrqxUauR931GU9508gAAA+Pz3weHya5vH+f0+31x8s7x/rez6nic+urXWo1a71z+Tw+35fBiotq +cn6fHtvvwe3+3DsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACI6nqOZi3 +kO6jViouq6RbGrFsW11YqNXK/Q9HkPbdZIAAAAAAKxiHS95jfW9xW6jVrvVdWurTSlVqmlLOf9uL +sXsfNdv9eJIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIPn8tYR4P0Hy+X +1jSLqukWxqxbFtdWKjVyPvOnynu+okAAAAAAEAw3pe9xvre5jVrvVdWurTSlVqmlLKVbedq9n5Lu +PrxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0fRdhjXlu3jSLqukWxqx +bFtdWKjV+n2xnnqfM83kfEAAAAAAAVl190Hpuq4vYV3qurXVppSq1TSllKpp2H24m4Oz8jKSAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACIxvzXa9F0PZRdV0i2NWLYtrqxUas +W8nlfDOPS+c5n3+MgAAAAAAgxjre2w/p/Q13qurXVppSq1TSllKppWtndj5XJfv18gAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6nquZ0fSdj1/C5Pzx9I1Yti2urFRqxq1t5 +PI+Ga+i892XK4wAAAAAAgxvru0wzpvR13qurXVppSq1TSllKppWss5XTbI53ngAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKxXOgIjqeu52Jef7v5Z+katbYtbcvk8e2pxPn +94urfTPb8vgZJ2PU9lyOJIAAIMb67tMM6b0dd6rq11aaUqtU0pZSqaVrtvvwdu9j5OQAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAddw+ThPmfQ/DH2rbFsatajVi2LY1Y +tjTJey6bM+16CSQAQY113a4b03oq71XVrq00pVappSylU0rXe8jrdrdh5eQAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQdfxOTgvmPSfLP0i2NWtRqxbFsasWxq1rKOz6 +TM+z6GQAQdFwewwXo/T13qurXVppSq1TSllKppWsv5fS7E5vn5AAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABjfUdpifRd7FsatajVi2LY1YtjVrUbbM73x/Y/bjACDi/ +L66y837Gt3Xdrq00pVappSylU0rW2ez8h3X14kgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAA6jg8zBvM+ki6jVrUasWxbGrFsatajVyXsOlzjtPPgAQa/wCi9P03E7Gu +9V1aaUqtU0pZSqaZByOs2j2PmJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AOJx/t1/C5Py+f0v9c9jzOJy+R8ZAAAB0/A5uD+a9JFsatajVi2LY1YtjVrUavM5HF2h3nj5AAOF +8vvrnovV8bHIrq00pVappSylc/7cXavZ+T5evmAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAOJxvri/mu56vrubXdrrUatdXsew4eWd50nYcrjSAADHeq7LEeg7+LY1a1GrFsWxq +xbGrWo1ft9fjtbv/ABcgAEHE+X2wbqfSdNx+xppSq1TSlmRcvq8/5/neVr5yAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDr+v5GH+Q77553XWq7tdajVru11X0maeg893nP4AAA +x/q+xw/z/oItjVrUasWxbGrFsatajV+/2+G1e+8ZIAABB1PH5uP8Ts+Hj7xXP+3FyDldb2n14kgA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4/H+mE+H9B8sfWurXVru11qNWu7 +XVrqz9M7E9P5Xmfb4yADreJysB8t6aLqNWtRqxbFsasWxq1qNXvOb1ewe38yAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMZ8v2vSdF2Vdarq11a7tdajVru11a6tdXJ +e46bLu36WQAVl175X0/C4/KjVrUasWxbGrFsatajV7vm9XsLt/MgAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACCuLgvgfQ/P5/WutV1a6td2utRq13a6tdWur2fO4OwPQ ++akAEHR9b2GF+f8ARRbWo1Yti2NWLY1a1Grb6Y2V3fkew+vGkAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAEHE4f1wvwvoIuq61XVrq13a61GrXdrq11a6v1+/z2d6fyE0 +ABBiXSd1jfU9xW2NWLYtjVi2NWtRqxbyPtx9i9x5TsfrxwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAABB13W8nEfFd7GrXWq6tdWu7XWo1a7tdWurXV+n3+Wz/AE/kZoAA +QdB1vZYt1HdcP48iNWLY1YtjVrUasW1rk/bj7D7fy3Z/XiyAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAACDjcX6YT4P0MXVdarq11a7tdajVru11a6tdX6/f57O9P5CaAAA +FY63jcvr+PyoXk/X4zXC+XIw/re++U+kW1qtTrPdcrr73FFiuZ9Phzvpx++5HXdhv4AAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARlg/hfQcfjfeurXWq6td2utRq13a6tdWu +r9fv8tnen8jNAAAAAACDrfhytd9L6v4Z+1arVarVarZWq1FRqZjyulzvndD9EAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHQ+f7HHPNdvXVrq11a7tdajVru11a6tdWftnZ3p +vIfXeQAAAAAAB1nw5WuOm9Z8c/WtVqtVqtlarUVWqmWcvp9jc7zsgAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAHzxcN8b3vC4PLrq11a7tdajVru11a6tdWutd12PW5z3fnbWS +AAAAAACDHeJ2eBdR6itVqtVqtlarUVWqla2n2XlMh+3AkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAEHw+G8S8n3nX8Ll1tru11qNWu7XVrq11a61Gr3fY9ZnPc+dvYAAAAAAI +Pjnepug9tVqtVqtVsrVaiq1UrXeffrtsdj5aQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAVjrOt5fU9bzuJ8Pv8cfSNWurxs/Xi/P711a61GrXWu05vAzHteh53148kA+msWA +AABB8871J0HtqtVqtVqtlarUVWqlanXz3f2vi/rcgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAVjF+o7jFeo7yurGrXVrrVd2urSqaUPp9Pn33K63MOZ0nbfXigACD553q +ToPbVarVarVbK1WoqtVK1Wtxdn47tfpxgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAABBjPV9tiHT9/FtdWutV3a6tKppSq1SxvOxex8zk/I62QAQfPO9SdD7as1Wq1Wq2V +qtRVaqVqtm5+08Z2G/iAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +MS6nusV6rvK6tdaru11aVTSlVqllNGs7Y7TyPcfTigAUl1P0XtPhj7VqtVqtlarUVWqla5H0+G6u +z8bewAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfPOtY+a9h8M/Wu +tV3a6tKppSq1SymlK7/kdbtPsfLyACDW/T+q6bjdjWq1Wq2VqtRVaqVrMOZ0uxOZ5+QAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARGsPNew42PvXWq7tdWlU0pVapZTS +lV1N1dr4vla+UgAx7i9jr7qPU1trVarZWq1FVqp9vp8tw9n4/l6+UgAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiNYea9hxsfeutV3a6tKppSq1SymlKrW0uy8pkX24E +gAgwjru/xPgd5Wq1WytVqKrVtY2h2Plu/wDtwQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAABEaw817DjY+9daru11aVTSlVqllNKVWtodj5XJPv18gAEGLcLt8K6/wBB +xp9K2VqtRXZ/bh7E5/nO3+vEkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAEGtfO+s4Pw5ddaru11aVTSlVqllNKVWts9n5Du/rxJAABB8s76Dj9j1Hx5vEz9uw+vF7v +7cDuvvwbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgwPovR9H +w+0rrVd2urSqaUqtUsppSr/T5br7Txn0uZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAABB0XC7DBOj9PXWq7tdWlU0pVapZTSlZtzeiz3mdEAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIKy686H1HVfDsK6tdWlU0 +pVapZTTsPrxNtdp5L7XIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAA4vz+mBdN6fqfhz66tKppSq1SztPvwtmdl5fmb+UgAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgrLjfB7bGOH3HV/HmU0odh9uJlXN6fKu +X1H0sAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +HwzviY+3K38vvr5yAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +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 +sY+cmPOYU64s1Uon/hsP/9k= +" + id="image395" /> + </g> +</svg> diff --git a/src/assets/js/bootstrap.min.js b/src/assets/js/bootstrap.min.js new file mode 100644 index 0000000..633c722 --- /dev/null +++ b/src/assets/js/bootstrap.min.js @@ -0,0 +1,1345 @@ +/*! + * Bootstrap v3.3.1 (http://getbootstrap.com) + * Copyright 2011-2014 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ +if ('undefined' == typeof jQuery) throw new Error("Bootstrap's JavaScript requires jQuery"); ++(function (a) { + var b = a.fn.jquery.split(' ')[0].split('.'); + if ((b[0] < 2 && b[1] < 9) || (1 == b[0] && 9 == b[1] && b[2] < 1)) + throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher"); +})(jQuery), + +(function (a) { + 'use strict'; + function b() { + var a = document.createElement('bootstrap'), + b = { + WebkitTransition: 'webkitTransitionEnd', + MozTransition: 'transitionend', + OTransition: 'oTransitionEnd otransitionend', + transition: 'transitionend', + }; + for (var c in b) if (void 0 !== a.style[c]) return { end: b[c] }; + return !1; + } + (a.fn.emulateTransitionEnd = function (b) { + var c = !1, + d = this; + a(this).one('bsTransitionEnd', function () { + c = !0; + }); + var e = function () { + c || a(d).trigger(a.support.transition.end); + }; + return setTimeout(e, b), this; + }), + a(function () { + (a.support.transition = b()), + a.support.transition && + (a.event.special.bsTransitionEnd = { + bindType: a.support.transition.end, + delegateType: a.support.transition.end, + handle: function (b) { + return a(b.target).is(this) ? b.handleObj.handler.apply(this, arguments) : void 0; + }, + }); + }); + })(jQuery), + +(function (a) { + 'use strict'; + function b(b) { + return this.each(function () { + var c = a(this), + e = c.data('bs.alert'); + e || c.data('bs.alert', (e = new d(this))), 'string' == typeof b && e[b].call(c); + }); + } + var c = '[data-dismiss="alert"]', + d = function (b) { + a(b).on('click', c, this.close); + }; + (d.VERSION = '3.3.1'), + (d.TRANSITION_DURATION = 150), + (d.prototype.close = function (b) { + function c() { + g.detach().trigger('closed.bs.alert').remove(); + } + var e = a(this), + f = e.attr('data-target'); + f || ((f = e.attr('href')), (f = f && f.replace(/.*(?=#[^\s]*$)/, ''))); + var g = a(f); + b && b.preventDefault(), + g.length || (g = e.closest('.alert')), + g.trigger((b = a.Event('close.bs.alert'))), + b.isDefaultPrevented() || + (g.removeClass('in'), + a.support.transition && g.hasClass('fade') + ? g.one('bsTransitionEnd', c).emulateTransitionEnd(d.TRANSITION_DURATION) + : c()); + }); + var e = a.fn.alert; + (a.fn.alert = b), + (a.fn.alert.Constructor = d), + (a.fn.alert.noConflict = function () { + return (a.fn.alert = e), this; + }), + a(document).on('click.bs.alert.data-api', c, d.prototype.close); + })(jQuery), + +(function (a) { + 'use strict'; + function b(b) { + return this.each(function () { + var d = a(this), + e = d.data('bs.button'), + f = 'object' == typeof b && b; + e || d.data('bs.button', (e = new c(this, f))), 'toggle' == b ? e.toggle() : b && e.setState(b); + }); + } + var c = function (b, d) { + (this.$element = a(b)), (this.options = a.extend({}, c.DEFAULTS, d)), (this.isLoading = !1); + }; + (c.VERSION = '3.3.1'), + (c.DEFAULTS = { loadingText: 'loading...' }), + (c.prototype.setState = function (b) { + var c = 'disabled', + d = this.$element, + e = d.is('input') ? 'val' : 'html', + f = d.data(); + (b += 'Text'), + null == f.resetText && d.data('resetText', d[e]()), + setTimeout( + a.proxy(function () { + d[e](null == f[b] ? this.options[b] : f[b]), + 'loadingText' == b + ? ((this.isLoading = !0), d.addClass(c).attr(c, c)) + : this.isLoading && ((this.isLoading = !1), d.removeClass(c).removeAttr(c)); + }, this), + 0, + ); + }), + (c.prototype.toggle = function () { + var a = !0, + b = this.$element.closest('[data-toggle="buttons"]'); + if (b.length) { + var c = this.$element.find('input'); + 'radio' == c.prop('type') && + (c.prop('checked') && this.$element.hasClass('active') + ? (a = !1) + : b.find('.active').removeClass('active')), + a && c.prop('checked', !this.$element.hasClass('active')).trigger('change'); + } else this.$element.attr('aria-pressed', !this.$element.hasClass('active')); + a && this.$element.toggleClass('active'); + }); + var d = a.fn.button; + (a.fn.button = b), + (a.fn.button.Constructor = c), + (a.fn.button.noConflict = function () { + return (a.fn.button = d), this; + }), + a(document) + .on('click.bs.button.data-api', '[data-toggle^="button"]', function (c) { + var d = a(c.target); + d.hasClass('btn') || (d = d.closest('.btn')), b.call(d, 'toggle'), c.preventDefault(); + }) + .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (b) { + a(b.target) + .closest('.btn') + .toggleClass('focus', /^focus(in)?$/.test(b.type)); + }); + })(jQuery), + +(function (a) { + 'use strict'; + function b(b) { + return this.each(function () { + var d = a(this), + e = d.data('bs.carousel'), + f = a.extend({}, c.DEFAULTS, d.data(), 'object' == typeof b && b), + g = 'string' == typeof b ? b : f.slide; + e || d.data('bs.carousel', (e = new c(this, f))), + 'number' == typeof b ? e.to(b) : g ? e[g]() : f.interval && e.pause().cycle(); + }); + } + var c = function (b, c) { + (this.$element = a(b)), + (this.$indicators = this.$element.find('.carousel-indicators')), + (this.options = c), + (this.paused = this.sliding = this.interval = this.$active = this.$items = null), + this.options.keyboard && this.$element.on('keydown.bs.carousel', a.proxy(this.keydown, this)), + 'hover' == this.options.pause && + !('ontouchstart' in document.documentElement) && + this.$element + .on('mouseenter.bs.carousel', a.proxy(this.pause, this)) + .on('mouseleave.bs.carousel', a.proxy(this.cycle, this)); + }; + (c.VERSION = '3.3.1'), + (c.TRANSITION_DURATION = 600), + (c.DEFAULTS = { interval: 5e3, pause: 'hover', wrap: !0, keyboard: !0 }), + (c.prototype.keydown = function (a) { + if (!/input|textarea/i.test(a.target.tagName)) { + switch (a.which) { + case 37: + this.prev(); + break; + case 39: + this.next(); + break; + default: + return; + } + a.preventDefault(); + } + }), + (c.prototype.cycle = function (b) { + return ( + b || (this.paused = !1), + this.interval && clearInterval(this.interval), + this.options.interval && + !this.paused && + (this.interval = setInterval(a.proxy(this.next, this), this.options.interval)), + this + ); + }), + (c.prototype.getItemIndex = function (a) { + return (this.$items = a.parent().children('.item')), this.$items.index(a || this.$active); + }), + (c.prototype.getItemForDirection = function (a, b) { + var c = 'prev' == a ? -1 : 1, + d = this.getItemIndex(b), + e = (d + c) % this.$items.length; + return this.$items.eq(e); + }), + (c.prototype.to = function (a) { + var b = this, + c = this.getItemIndex((this.$active = this.$element.find('.item.active'))); + return a > this.$items.length - 1 || 0 > a + ? void 0 + : this.sliding + ? this.$element.one('slid.bs.carousel', function () { + b.to(a); + }) + : c == a + ? this.pause().cycle() + : this.slide(a > c ? 'next' : 'prev', this.$items.eq(a)); + }), + (c.prototype.pause = function (b) { + return ( + b || (this.paused = !0), + this.$element.find('.next, .prev').length && + a.support.transition && + (this.$element.trigger(a.support.transition.end), this.cycle(!0)), + (this.interval = clearInterval(this.interval)), + this + ); + }), + (c.prototype.next = function () { + return this.sliding ? void 0 : this.slide('next'); + }), + (c.prototype.prev = function () { + return this.sliding ? void 0 : this.slide('prev'); + }), + (c.prototype.slide = function (b, d) { + var e = this.$element.find('.item.active'), + f = d || this.getItemForDirection(b, e), + g = this.interval, + h = 'next' == b ? 'left' : 'right', + i = 'next' == b ? 'first' : 'last', + j = this; + if (!f.length) { + if (!this.options.wrap) return; + f = this.$element.find('.item')[i](); + } + if (f.hasClass('active')) return (this.sliding = !1); + var k = f[0], + l = a.Event('slide.bs.carousel', { relatedTarget: k, direction: h }); + if ((this.$element.trigger(l), !l.isDefaultPrevented())) { + if (((this.sliding = !0), g && this.pause(), this.$indicators.length)) { + this.$indicators.find('.active').removeClass('active'); + var m = a(this.$indicators.children()[this.getItemIndex(f)]); + m && m.addClass('active'); + } + var n = a.Event('slid.bs.carousel', { relatedTarget: k, direction: h }); + return ( + a.support.transition && this.$element.hasClass('slide') + ? (f.addClass(b), + f[0].offsetWidth, + e.addClass(h), + f.addClass(h), + e + .one('bsTransitionEnd', function () { + f.removeClass([b, h].join(' ')).addClass('active'), + e.removeClass(['active', h].join(' ')), + (j.sliding = !1), + setTimeout(function () { + j.$element.trigger(n); + }, 0); + }) + .emulateTransitionEnd(c.TRANSITION_DURATION)) + : (e.removeClass('active'), f.addClass('active'), (this.sliding = !1), this.$element.trigger(n)), + g && this.cycle(), + this + ); + } + }); + var d = a.fn.carousel; + (a.fn.carousel = b), + (a.fn.carousel.Constructor = c), + (a.fn.carousel.noConflict = function () { + return (a.fn.carousel = d), this; + }); + var e = function (c) { + var d, + e = a(this), + f = a(e.attr('data-target') || ((d = e.attr('href')) && d.replace(/.*(?=#[^\s]+$)/, ''))); + if (f.hasClass('carousel')) { + var g = a.extend({}, f.data(), e.data()), + h = e.attr('data-slide-to'); + h && (g.interval = !1), b.call(f, g), h && f.data('bs.carousel').to(h), c.preventDefault(); + } + }; + a(document) + .on('click.bs.carousel.data-api', '[data-slide]', e) + .on('click.bs.carousel.data-api', '[data-slide-to]', e), + a(window).on('load', function () { + a('[data-ride="carousel"]').each(function () { + var c = a(this); + b.call(c, c.data()); + }); + }); + })(jQuery), + +(function (a) { + 'use strict'; + function b(b) { + var c, + d = b.attr('data-target') || ((c = b.attr('href')) && c.replace(/.*(?=#[^\s]+$)/, '')); + return a(d); + } + function c(b) { + return this.each(function () { + var c = a(this), + e = c.data('bs.collapse'), + f = a.extend({}, d.DEFAULTS, c.data(), 'object' == typeof b && b); + !e && f.toggle && 'show' == b && (f.toggle = !1), + e || c.data('bs.collapse', (e = new d(this, f))), + 'string' == typeof b && e[b](); + }); + } + var d = function (b, c) { + (this.$element = a(b)), + (this.options = a.extend({}, d.DEFAULTS, c)), + (this.$trigger = a(this.options.trigger).filter('[href="#' + b.id + '"], [data-target="#' + b.id + '"]')), + (this.transitioning = null), + this.options.parent + ? (this.$parent = this.getParent()) + : this.addAriaAndCollapsedClass(this.$element, this.$trigger), + this.options.toggle && this.toggle(); + }; + (d.VERSION = '3.3.1'), + (d.TRANSITION_DURATION = 350), + (d.DEFAULTS = { toggle: !0, trigger: '[data-toggle="collapse"]' }), + (d.prototype.dimension = function () { + var a = this.$element.hasClass('width'); + return a ? 'width' : 'height'; + }), + (d.prototype.show = function () { + if (!this.transitioning && !this.$element.hasClass('in')) { + var b, + e = this.$parent && this.$parent.find('> .panel').children('.in, .collapsing'); + if (!(e && e.length && ((b = e.data('bs.collapse')), b && b.transitioning))) { + var f = a.Event('show.bs.collapse'); + if ((this.$element.trigger(f), !f.isDefaultPrevented())) { + e && e.length && (c.call(e, 'hide'), b || e.data('bs.collapse', null)); + var g = this.dimension(); + this.$element.removeClass('collapse').addClass('collapsing')[g](0).attr('aria-expanded', !0), + this.$trigger.removeClass('collapsed').attr('aria-expanded', !0), + (this.transitioning = 1); + var h = function () { + this.$element.removeClass('collapsing').addClass('collapse in')[g](''), + (this.transitioning = 0), + this.$element.trigger('shown.bs.collapse'); + }; + if (!a.support.transition) return h.call(this); + var i = a.camelCase(['scroll', g].join('-')); + this.$element + .one('bsTransitionEnd', a.proxy(h, this)) + .emulateTransitionEnd(d.TRANSITION_DURATION) + [g](this.$element[0][i]); + } + } + } + }), + (d.prototype.hide = function () { + if (!this.transitioning && this.$element.hasClass('in')) { + var b = a.Event('hide.bs.collapse'); + if ((this.$element.trigger(b), !b.isDefaultPrevented())) { + var c = this.dimension(); + this.$element[c](this.$element[c]())[0].offsetHeight, + this.$element.addClass('collapsing').removeClass('collapse in').attr('aria-expanded', !1), + this.$trigger.addClass('collapsed').attr('aria-expanded', !1), + (this.transitioning = 1); + var e = function () { + (this.transitioning = 0), + this.$element.removeClass('collapsing').addClass('collapse').trigger('hidden.bs.collapse'); + }; + return a.support.transition + ? void this.$element[c](0) + .one('bsTransitionEnd', a.proxy(e, this)) + .emulateTransitionEnd(d.TRANSITION_DURATION) + : e.call(this); + } + } + }), + (d.prototype.toggle = function () { + this[this.$element.hasClass('in') ? 'hide' : 'show'](); + }), + (d.prototype.getParent = function () { + return a(this.options.parent) + .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]') + .each( + a.proxy(function (c, d) { + var e = a(d); + this.addAriaAndCollapsedClass(b(e), e); + }, this), + ) + .end(); + }), + (d.prototype.addAriaAndCollapsedClass = function (a, b) { + var c = a.hasClass('in'); + a.attr('aria-expanded', c), b.toggleClass('collapsed', !c).attr('aria-expanded', c); + }); + var e = a.fn.collapse; + (a.fn.collapse = c), + (a.fn.collapse.Constructor = d), + (a.fn.collapse.noConflict = function () { + return (a.fn.collapse = e), this; + }), + a(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (d) { + var e = a(this); + e.attr('data-target') || d.preventDefault(); + var f = b(e), + g = f.data('bs.collapse'), + h = g ? 'toggle' : a.extend({}, e.data(), { trigger: this }); + c.call(f, h); + }); + })(jQuery), + +(function (a) { + 'use strict'; + function b(b) { + (b && 3 === b.which) || + (a(e).remove(), + a(f).each(function () { + var d = a(this), + e = c(d), + f = { relatedTarget: this }; + e.hasClass('open') && + (e.trigger((b = a.Event('hide.bs.dropdown', f))), + b.isDefaultPrevented() || + (d.attr('aria-expanded', 'false'), e.removeClass('open').trigger('hidden.bs.dropdown', f))); + })); + } + function c(b) { + var c = b.attr('data-target'); + c || ((c = b.attr('href')), (c = c && /#[A-Za-z]/.test(c) && c.replace(/.*(?=#[^\s]*$)/, ''))); + var d = c && a(c); + return d && d.length ? d : b.parent(); + } + function d(b) { + return this.each(function () { + var c = a(this), + d = c.data('bs.dropdown'); + d || c.data('bs.dropdown', (d = new g(this))), 'string' == typeof b && d[b].call(c); + }); + } + var e = '.dropdown-backdrop', + f = '[data-toggle="dropdown"]', + g = function (b) { + a(b).on('click.bs.dropdown', this.toggle); + }; + (g.VERSION = '3.3.1'), + (g.prototype.toggle = function (d) { + var e = a(this); + if (!e.is('.disabled, :disabled')) { + var f = c(e), + g = f.hasClass('open'); + if ((b(), !g)) { + 'ontouchstart' in document.documentElement && + !f.closest('.navbar-nav').length && + a('<div class="dropdown-backdrop"/>').insertAfter(a(this)).on('click', b); + var h = { relatedTarget: this }; + if ((f.trigger((d = a.Event('show.bs.dropdown', h))), d.isDefaultPrevented())) return; + e.trigger('focus').attr('aria-expanded', 'true'), f.toggleClass('open').trigger('shown.bs.dropdown', h); + } + return !1; + } + }), + (g.prototype.keydown = function (b) { + if (/(38|40|27|32)/.test(b.which) && !/input|textarea/i.test(b.target.tagName)) { + var d = a(this); + if ((b.preventDefault(), b.stopPropagation(), !d.is('.disabled, :disabled'))) { + var e = c(d), + g = e.hasClass('open'); + if ((!g && 27 != b.which) || (g && 27 == b.which)) + return 27 == b.which && e.find(f).trigger('focus'), d.trigger('click'); + var h = ' li:not(.divider):visible a', + i = e.find('[role="menu"]' + h + ', [role="listbox"]' + h); + if (i.length) { + var j = i.index(b.target); + 38 == b.which && j > 0 && j--, + 40 == b.which && j < i.length - 1 && j++, + ~j || (j = 0), + i.eq(j).trigger('focus'); + } + } + } + }); + var h = a.fn.dropdown; + (a.fn.dropdown = d), + (a.fn.dropdown.Constructor = g), + (a.fn.dropdown.noConflict = function () { + return (a.fn.dropdown = h), this; + }), + a(document) + .on('click.bs.dropdown.data-api', b) + .on('click.bs.dropdown.data-api', '.dropdown form', function (a) { + a.stopPropagation(); + }) + .on('click.bs.dropdown.data-api', f, g.prototype.toggle) + .on('keydown.bs.dropdown.data-api', f, g.prototype.keydown) + .on('keydown.bs.dropdown.data-api', '[role="menu"]', g.prototype.keydown) + .on('keydown.bs.dropdown.data-api', '[role="listbox"]', g.prototype.keydown); + })(jQuery), + +(function (a) { + 'use strict'; + function b(b, d) { + return this.each(function () { + var e = a(this), + f = e.data('bs.modal'), + g = a.extend({}, c.DEFAULTS, e.data(), 'object' == typeof b && b); + f || e.data('bs.modal', (f = new c(this, g))), 'string' == typeof b ? f[b](d) : g.show && f.show(d); + }); + } + var c = function (b, c) { + (this.options = c), + (this.$body = a(document.body)), + (this.$element = a(b)), + (this.$backdrop = this.isShown = null), + (this.scrollbarWidth = 0), + this.options.remote && + this.$element.find('.modal-content').load( + this.options.remote, + a.proxy(function () { + this.$element.trigger('loaded.bs.modal'); + }, this), + ); + }; + (c.VERSION = '3.3.1'), + (c.TRANSITION_DURATION = 300), + (c.BACKDROP_TRANSITION_DURATION = 150), + (c.DEFAULTS = { backdrop: !0, keyboard: !0, show: !0 }), + (c.prototype.toggle = function (a) { + return this.isShown ? this.hide() : this.show(a); + }), + (c.prototype.show = function (b) { + var d = this, + e = a.Event('show.bs.modal', { relatedTarget: b }); + this.$element.trigger(e), + this.isShown || + e.isDefaultPrevented() || + ((this.isShown = !0), + this.checkScrollbar(), + this.setScrollbar(), + this.$body.addClass('modal-open'), + this.escape(), + this.resize(), + this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', a.proxy(this.hide, this)), + this.backdrop(function () { + var e = a.support.transition && d.$element.hasClass('fade'); + d.$element.parent().length || d.$element.appendTo(d.$body), + d.$element.show().scrollTop(0), + d.options.backdrop && d.adjustBackdrop(), + d.adjustDialog(), + e && d.$element[0].offsetWidth, + d.$element.addClass('in').attr('aria-hidden', !1), + d.enforceFocus(); + var f = a.Event('shown.bs.modal', { relatedTarget: b }); + e + ? d.$element + .find('.modal-dialog') + .one('bsTransitionEnd', function () { + d.$element.trigger('focus').trigger(f); + }) + .emulateTransitionEnd(c.TRANSITION_DURATION) + : d.$element.trigger('focus').trigger(f); + })); + }), + (c.prototype.hide = function (b) { + b && b.preventDefault(), + (b = a.Event('hide.bs.modal')), + this.$element.trigger(b), + this.isShown && + !b.isDefaultPrevented() && + ((this.isShown = !1), + this.escape(), + this.resize(), + a(document).off('focusin.bs.modal'), + this.$element.removeClass('in').attr('aria-hidden', !0).off('click.dismiss.bs.modal'), + a.support.transition && this.$element.hasClass('fade') + ? this.$element + .one('bsTransitionEnd', a.proxy(this.hideModal, this)) + .emulateTransitionEnd(c.TRANSITION_DURATION) + : this.hideModal()); + }), + (c.prototype.enforceFocus = function () { + a(document) + .off('focusin.bs.modal') + .on( + 'focusin.bs.modal', + a.proxy(function (a) { + this.$element[0] === a.target || this.$element.has(a.target).length || this.$element.trigger('focus'); + }, this), + ); + }), + (c.prototype.escape = function () { + this.isShown && this.options.keyboard + ? this.$element.on( + 'keydown.dismiss.bs.modal', + a.proxy(function (a) { + 27 == a.which && this.hide(); + }, this), + ) + : this.isShown || this.$element.off('keydown.dismiss.bs.modal'); + }), + (c.prototype.resize = function () { + this.isShown + ? a(window).on('resize.bs.modal', a.proxy(this.handleUpdate, this)) + : a(window).off('resize.bs.modal'); + }), + (c.prototype.hideModal = function () { + var a = this; + this.$element.hide(), + this.backdrop(function () { + a.$body.removeClass('modal-open'), + a.resetAdjustments(), + a.resetScrollbar(), + a.$element.trigger('hidden.bs.modal'); + }); + }), + (c.prototype.removeBackdrop = function () { + this.$backdrop && this.$backdrop.remove(), (this.$backdrop = null); + }), + (c.prototype.backdrop = function (b) { + var d = this, + e = this.$element.hasClass('fade') ? 'fade' : ''; + if (this.isShown && this.options.backdrop) { + var f = a.support.transition && e; + if ( + ((this.$backdrop = a('<div class="modal-backdrop ' + e + '" />') + .prependTo(this.$element) + .on( + 'click.dismiss.bs.modal', + a.proxy(function (a) { + a.target === a.currentTarget && + ('static' == this.options.backdrop + ? this.$element[0].focus.call(this.$element[0]) + : this.hide.call(this)); + }, this), + )), + f && this.$backdrop[0].offsetWidth, + this.$backdrop.addClass('in'), + !b) + ) + return; + f ? this.$backdrop.one('bsTransitionEnd', b).emulateTransitionEnd(c.BACKDROP_TRANSITION_DURATION) : b(); + } else if (!this.isShown && this.$backdrop) { + this.$backdrop.removeClass('in'); + var g = function () { + d.removeBackdrop(), b && b(); + }; + a.support.transition && this.$element.hasClass('fade') + ? this.$backdrop.one('bsTransitionEnd', g).emulateTransitionEnd(c.BACKDROP_TRANSITION_DURATION) + : g(); + } else b && b(); + }), + (c.prototype.handleUpdate = function () { + this.options.backdrop && this.adjustBackdrop(), this.adjustDialog(); + }), + (c.prototype.adjustBackdrop = function () { + this.$backdrop.css('height', 0).css('height', this.$element[0].scrollHeight); + }), + (c.prototype.adjustDialog = function () { + var a = this.$element[0].scrollHeight > document.documentElement.clientHeight; + this.$element.css({ + paddingLeft: !this.bodyIsOverflowing && a ? this.scrollbarWidth : '', + paddingRight: this.bodyIsOverflowing && !a ? this.scrollbarWidth : '', + }); + }), + (c.prototype.resetAdjustments = function () { + this.$element.css({ paddingLeft: '', paddingRight: '' }); + }), + (c.prototype.checkScrollbar = function () { + (this.bodyIsOverflowing = document.body.scrollHeight > document.documentElement.clientHeight), + (this.scrollbarWidth = this.measureScrollbar()); + }), + (c.prototype.setScrollbar = function () { + var a = parseInt(this.$body.css('padding-right') || 0, 10); + this.bodyIsOverflowing && this.$body.css('padding-right', a + this.scrollbarWidth); + }), + (c.prototype.resetScrollbar = function () { + this.$body.css('padding-right', ''); + }), + (c.prototype.measureScrollbar = function () { + var a = document.createElement('div'); + (a.className = 'modal-scrollbar-measure'), this.$body.append(a); + var b = a.offsetWidth - a.clientWidth; + return this.$body[0].removeChild(a), b; + }); + var d = a.fn.modal; + (a.fn.modal = b), + (a.fn.modal.Constructor = c), + (a.fn.modal.noConflict = function () { + return (a.fn.modal = d), this; + }), + a(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (c) { + var d = a(this), + e = d.attr('href'), + f = a(d.attr('data-target') || (e && e.replace(/.*(?=#[^\s]+$)/, ''))), + g = f.data('bs.modal') ? 'toggle' : a.extend({ remote: !/#/.test(e) && e }, f.data(), d.data()); + d.is('a') && c.preventDefault(), + f.one('show.bs.modal', function (a) { + a.isDefaultPrevented() || + f.one('hidden.bs.modal', function () { + d.is(':visible') && d.trigger('focus'); + }); + }), + b.call(f, g, this); + }); + })(jQuery), + +(function (a) { + 'use strict'; + function b(b) { + return this.each(function () { + var d = a(this), + e = d.data('bs.tooltip'), + f = 'object' == typeof b && b, + g = f && f.selector; + (e || 'destroy' != b) && + (g + ? (e || d.data('bs.tooltip', (e = {})), e[g] || (e[g] = new c(this, f))) + : e || d.data('bs.tooltip', (e = new c(this, f))), + 'string' == typeof b && e[b]()); + }); + } + var c = function (a, b) { + (this.type = this.options = this.enabled = this.timeout = this.hoverState = this.$element = null), + this.init('tooltip', a, b); + }; + (c.VERSION = '3.3.1'), + (c.TRANSITION_DURATION = 150), + (c.DEFAULTS = { + animation: !0, + placement: 'top', + selector: !1, + template: + '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>', + trigger: 'hover focus', + title: '', + delay: 0, + html: !1, + container: !1, + viewport: { selector: 'body', padding: 0 }, + }), + (c.prototype.init = function (b, c, d) { + (this.enabled = !0), + (this.type = b), + (this.$element = a(c)), + (this.options = this.getOptions(d)), + (this.$viewport = this.options.viewport && a(this.options.viewport.selector || this.options.viewport)); + for (var e = this.options.trigger.split(' '), f = e.length; f--; ) { + var g = e[f]; + if ('click' == g) this.$element.on('click.' + this.type, this.options.selector, a.proxy(this.toggle, this)); + else if ('manual' != g) { + var h = 'hover' == g ? 'mouseenter' : 'focusin', + i = 'hover' == g ? 'mouseleave' : 'focusout'; + this.$element.on(h + '.' + this.type, this.options.selector, a.proxy(this.enter, this)), + this.$element.on(i + '.' + this.type, this.options.selector, a.proxy(this.leave, this)); + } + } + this.options.selector + ? (this._options = a.extend({}, this.options, { trigger: 'manual', selector: '' })) + : this.fixTitle(); + }), + (c.prototype.getDefaults = function () { + return c.DEFAULTS; + }), + (c.prototype.getOptions = function (b) { + return ( + (b = a.extend({}, this.getDefaults(), this.$element.data(), b)), + b.delay && 'number' == typeof b.delay && (b.delay = { show: b.delay, hide: b.delay }), + b + ); + }), + (c.prototype.getDelegateOptions = function () { + var b = {}, + c = this.getDefaults(); + return ( + this._options && + a.each(this._options, function (a, d) { + c[a] != d && (b[a] = d); + }), + b + ); + }), + (c.prototype.enter = function (b) { + var c = b instanceof this.constructor ? b : a(b.currentTarget).data('bs.' + this.type); + return c && c.$tip && c.$tip.is(':visible') + ? void (c.hoverState = 'in') + : (c || + ((c = new this.constructor(b.currentTarget, this.getDelegateOptions())), + a(b.currentTarget).data('bs.' + this.type, c)), + clearTimeout(c.timeout), + (c.hoverState = 'in'), + c.options.delay && c.options.delay.show + ? void (c.timeout = setTimeout(function () { + 'in' == c.hoverState && c.show(); + }, c.options.delay.show)) + : c.show()); + }), + (c.prototype.leave = function (b) { + var c = b instanceof this.constructor ? b : a(b.currentTarget).data('bs.' + this.type); + return ( + c || + ((c = new this.constructor(b.currentTarget, this.getDelegateOptions())), + a(b.currentTarget).data('bs.' + this.type, c)), + clearTimeout(c.timeout), + (c.hoverState = 'out'), + c.options.delay && c.options.delay.hide + ? void (c.timeout = setTimeout(function () { + 'out' == c.hoverState && c.hide(); + }, c.options.delay.hide)) + : c.hide() + ); + }), + (c.prototype.show = function () { + var b = a.Event('show.bs.' + this.type); + if (this.hasContent() && this.enabled) { + this.$element.trigger(b); + var d = a.contains(this.$element[0].ownerDocument.documentElement, this.$element[0]); + if (b.isDefaultPrevented() || !d) return; + var e = this, + f = this.tip(), + g = this.getUID(this.type); + this.setContent(), + f.attr('id', g), + this.$element.attr('aria-describedby', g), + this.options.animation && f.addClass('fade'); + var h = + 'function' == typeof this.options.placement + ? this.options.placement.call(this, f[0], this.$element[0]) + : this.options.placement, + i = /\s?auto?\s?/i, + j = i.test(h); + j && (h = h.replace(i, '') || 'top'), + f + .detach() + .css({ top: 0, left: 0, display: 'block' }) + .addClass(h) + .data('bs.' + this.type, this), + this.options.container ? f.appendTo(this.options.container) : f.insertAfter(this.$element); + var k = this.getPosition(), + l = f[0].offsetWidth, + m = f[0].offsetHeight; + if (j) { + var n = h, + o = this.options.container ? a(this.options.container) : this.$element.parent(), + p = this.getPosition(o); + (h = + 'bottom' == h && k.bottom + m > p.bottom + ? 'top' + : 'top' == h && k.top - m < p.top + ? 'bottom' + : 'right' == h && k.right + l > p.width + ? 'left' + : 'left' == h && k.left - l < p.left + ? 'right' + : h), + f.removeClass(n).addClass(h); + } + var q = this.getCalculatedOffset(h, k, l, m); + this.applyPlacement(q, h); + var r = function () { + var a = e.hoverState; + e.$element.trigger('shown.bs.' + e.type), (e.hoverState = null), 'out' == a && e.leave(e); + }; + a.support.transition && this.$tip.hasClass('fade') + ? f.one('bsTransitionEnd', r).emulateTransitionEnd(c.TRANSITION_DURATION) + : r(); + } + }), + (c.prototype.applyPlacement = function (b, c) { + var d = this.tip(), + e = d[0].offsetWidth, + f = d[0].offsetHeight, + g = parseInt(d.css('margin-top'), 10), + h = parseInt(d.css('margin-left'), 10); + isNaN(g) && (g = 0), + isNaN(h) && (h = 0), + (b.top = b.top + g), + (b.left = b.left + h), + a.offset.setOffset( + d[0], + a.extend( + { + using: function (a) { + d.css({ top: Math.round(a.top), left: Math.round(a.left) }); + }, + }, + b, + ), + 0, + ), + d.addClass('in'); + var i = d[0].offsetWidth, + j = d[0].offsetHeight; + 'top' == c && j != f && (b.top = b.top + f - j); + var k = this.getViewportAdjustedDelta(c, b, i, j); + k.left ? (b.left += k.left) : (b.top += k.top); + var l = /top|bottom/.test(c), + m = l ? 2 * k.left - e + i : 2 * k.top - f + j, + n = l ? 'offsetWidth' : 'offsetHeight'; + d.offset(b), this.replaceArrow(m, d[0][n], l); + }), + (c.prototype.replaceArrow = function (a, b, c) { + this.arrow() + .css(c ? 'left' : 'top', 50 * (1 - a / b) + '%') + .css(c ? 'top' : 'left', ''); + }), + (c.prototype.setContent = function () { + var a = this.tip(), + b = this.getTitle(); + a.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](b), + a.removeClass('fade in top bottom left right'); + }), + (c.prototype.hide = function (b) { + function d() { + 'in' != e.hoverState && f.detach(), + e.$element.removeAttr('aria-describedby').trigger('hidden.bs.' + e.type), + b && b(); + } + var e = this, + f = this.tip(), + g = a.Event('hide.bs.' + this.type); + return ( + this.$element.trigger(g), + g.isDefaultPrevented() + ? void 0 + : (f.removeClass('in'), + a.support.transition && this.$tip.hasClass('fade') + ? f.one('bsTransitionEnd', d).emulateTransitionEnd(c.TRANSITION_DURATION) + : d(), + (this.hoverState = null), + this) + ); + }), + (c.prototype.fixTitle = function () { + var a = this.$element; + (a.attr('title') || 'string' != typeof a.attr('data-original-title')) && + a.attr('data-original-title', a.attr('title') || '').attr('title', ''); + }), + (c.prototype.hasContent = function () { + return this.getTitle(); + }), + (c.prototype.getPosition = function (b) { + b = b || this.$element; + var c = b[0], + d = 'BODY' == c.tagName, + e = c.getBoundingClientRect(); + null == e.width && (e = a.extend({}, e, { width: e.right - e.left, height: e.bottom - e.top })); + var f = d ? { top: 0, left: 0 } : b.offset(), + g = { scroll: d ? document.documentElement.scrollTop || document.body.scrollTop : b.scrollTop() }, + h = d ? { width: a(window).width(), height: a(window).height() } : null; + return a.extend({}, e, g, h, f); + }), + (c.prototype.getCalculatedOffset = function (a, b, c, d) { + return 'bottom' == a + ? { top: b.top + b.height, left: b.left + b.width / 2 - c / 2 } + : 'top' == a + ? { top: b.top - d, left: b.left + b.width / 2 - c / 2 } + : 'left' == a + ? { top: b.top + b.height / 2 - d / 2, left: b.left - c } + : { top: b.top + b.height / 2 - d / 2, left: b.left + b.width }; + }), + (c.prototype.getViewportAdjustedDelta = function (a, b, c, d) { + var e = { top: 0, left: 0 }; + if (!this.$viewport) return e; + var f = (this.options.viewport && this.options.viewport.padding) || 0, + g = this.getPosition(this.$viewport); + if (/right|left/.test(a)) { + var h = b.top - f - g.scroll, + i = b.top + f - g.scroll + d; + h < g.top ? (e.top = g.top - h) : i > g.top + g.height && (e.top = g.top + g.height - i); + } else { + var j = b.left - f, + k = b.left + f + c; + j < g.left ? (e.left = g.left - j) : k > g.width && (e.left = g.left + g.width - k); + } + return e; + }), + (c.prototype.getTitle = function () { + var a, + b = this.$element, + c = this.options; + return (a = b.attr('data-original-title') || ('function' == typeof c.title ? c.title.call(b[0]) : c.title)); + }), + (c.prototype.getUID = function (a) { + do a += ~~(1e6 * Math.random()); + while (document.getElementById(a)); + return a; + }), + (c.prototype.tip = function () { + return (this.$tip = this.$tip || a(this.options.template)); + }), + (c.prototype.arrow = function () { + return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')); + }), + (c.prototype.enable = function () { + this.enabled = !0; + }), + (c.prototype.disable = function () { + this.enabled = !1; + }), + (c.prototype.toggleEnabled = function () { + this.enabled = !this.enabled; + }), + (c.prototype.toggle = function (b) { + var c = this; + b && + ((c = a(b.currentTarget).data('bs.' + this.type)), + c || + ((c = new this.constructor(b.currentTarget, this.getDelegateOptions())), + a(b.currentTarget).data('bs.' + this.type, c))), + c.tip().hasClass('in') ? c.leave(c) : c.enter(c); + }), + (c.prototype.destroy = function () { + var a = this; + clearTimeout(this.timeout), + this.hide(function () { + a.$element.off('.' + a.type).removeData('bs.' + a.type); + }); + }); + var d = a.fn.tooltip; + (a.fn.tooltip = b), + (a.fn.tooltip.Constructor = c), + (a.fn.tooltip.noConflict = function () { + return (a.fn.tooltip = d), this; + }); + })(jQuery), + +(function (a) { + 'use strict'; + function b(b) { + return this.each(function () { + var d = a(this), + e = d.data('bs.popover'), + f = 'object' == typeof b && b, + g = f && f.selector; + (e || 'destroy' != b) && + (g + ? (e || d.data('bs.popover', (e = {})), e[g] || (e[g] = new c(this, f))) + : e || d.data('bs.popover', (e = new c(this, f))), + 'string' == typeof b && e[b]()); + }); + } + var c = function (a, b) { + this.init('popover', a, b); + }; + if (!a.fn.tooltip) throw new Error('Popover requires tooltip.js'); + (c.VERSION = '3.3.1'), + (c.DEFAULTS = a.extend({}, a.fn.tooltip.Constructor.DEFAULTS, { + placement: 'right', + trigger: 'click', + content: '', + template: + '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>', + })), + (c.prototype = a.extend({}, a.fn.tooltip.Constructor.prototype)), + (c.prototype.constructor = c), + (c.prototype.getDefaults = function () { + return c.DEFAULTS; + }), + (c.prototype.setContent = function () { + var a = this.tip(), + b = this.getTitle(), + c = this.getContent(); + a.find('.popover-title')[this.options.html ? 'html' : 'text'](b), + a + .find('.popover-content') + .children() + .detach() + .end() + [this.options.html ? ('string' == typeof c ? 'html' : 'append') : 'text'](c), + a.removeClass('fade top bottom left right in'), + a.find('.popover-title').html() || a.find('.popover-title').hide(); + }), + (c.prototype.hasContent = function () { + return this.getTitle() || this.getContent(); + }), + (c.prototype.getContent = function () { + var a = this.$element, + b = this.options; + return a.attr('data-content') || ('function' == typeof b.content ? b.content.call(a[0]) : b.content); + }), + (c.prototype.arrow = function () { + return (this.$arrow = this.$arrow || this.tip().find('.arrow')); + }), + (c.prototype.tip = function () { + return this.$tip || (this.$tip = a(this.options.template)), this.$tip; + }); + var d = a.fn.popover; + (a.fn.popover = b), + (a.fn.popover.Constructor = c), + (a.fn.popover.noConflict = function () { + return (a.fn.popover = d), this; + }); + })(jQuery), + +(function (a) { + 'use strict'; + function b(c, d) { + var e = a.proxy(this.process, this); + (this.$body = a('body')), + (this.$scrollElement = a(a(c).is('body') ? window : c)), + (this.options = a.extend({}, b.DEFAULTS, d)), + (this.selector = (this.options.target || '') + ' .nav li > a'), + (this.offsets = []), + (this.targets = []), + (this.activeTarget = null), + (this.scrollHeight = 0), + this.$scrollElement.on('scroll.bs.scrollspy', e), + this.refresh(), + this.process(); + } + function c(c) { + return this.each(function () { + var d = a(this), + e = d.data('bs.scrollspy'), + f = 'object' == typeof c && c; + e || d.data('bs.scrollspy', (e = new b(this, f))), 'string' == typeof c && e[c](); + }); + } + (b.VERSION = '3.3.1'), + (b.DEFAULTS = { offset: 10 }), + (b.prototype.getScrollHeight = function () { + return ( + this.$scrollElement[0].scrollHeight || + Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight) + ); + }), + (b.prototype.refresh = function () { + var b = 'offset', + c = 0; + a.isWindow(this.$scrollElement[0]) || ((b = 'position'), (c = this.$scrollElement.scrollTop())), + (this.offsets = []), + (this.targets = []), + (this.scrollHeight = this.getScrollHeight()); + var d = this; + this.$body + .find(this.selector) + .map(function () { + var d = a(this), + e = d.data('target') || d.attr('href'), + f = /^#./.test(e) && a(e); + return (f && f.length && f.is(':visible') && [[f[b]().top + c, e]]) || null; + }) + .sort(function (a, b) { + return a[0] - b[0]; + }) + .each(function () { + d.offsets.push(this[0]), d.targets.push(this[1]); + }); + }), + (b.prototype.process = function () { + var a, + b = this.$scrollElement.scrollTop() + this.options.offset, + c = this.getScrollHeight(), + d = this.options.offset + c - this.$scrollElement.height(), + e = this.offsets, + f = this.targets, + g = this.activeTarget; + if ((this.scrollHeight != c && this.refresh(), b >= d)) return g != (a = f[f.length - 1]) && this.activate(a); + if (g && b < e[0]) return (this.activeTarget = null), this.clear(); + for (a = e.length; a--; ) g != f[a] && b >= e[a] && (!e[a + 1] || b <= e[a + 1]) && this.activate(f[a]); + }), + (b.prototype.activate = function (b) { + (this.activeTarget = b), this.clear(); + var c = this.selector + '[data-target="' + b + '"],' + this.selector + '[href="' + b + '"]', + d = a(c).parents('li').addClass('active'); + d.parent('.dropdown-menu').length && (d = d.closest('li.dropdown').addClass('active')), + d.trigger('activate.bs.scrollspy'); + }), + (b.prototype.clear = function () { + a(this.selector).parentsUntil(this.options.target, '.active').removeClass('active'); + }); + var d = a.fn.scrollspy; + (a.fn.scrollspy = c), + (a.fn.scrollspy.Constructor = b), + (a.fn.scrollspy.noConflict = function () { + return (a.fn.scrollspy = d), this; + }), + a(window).on('load.bs.scrollspy.data-api', function () { + a('[data-spy="scroll"]').each(function () { + var b = a(this); + c.call(b, b.data()); + }); + }); + })(jQuery), + +(function (a) { + 'use strict'; + function b(b) { + return this.each(function () { + var d = a(this), + e = d.data('bs.tab'); + e || d.data('bs.tab', (e = new c(this))), 'string' == typeof b && e[b](); + }); + } + var c = function (b) { + this.element = a(b); + }; + (c.VERSION = '3.3.1'), + (c.TRANSITION_DURATION = 150), + (c.prototype.show = function () { + var b = this.element, + c = b.closest('ul:not(.dropdown-menu)'), + d = b.data('target'); + if ( + (d || ((d = b.attr('href')), (d = d && d.replace(/.*(?=#[^\s]*$)/, ''))), !b.parent('li').hasClass('active')) + ) { + var e = c.find('.active:last a'), + f = a.Event('hide.bs.tab', { relatedTarget: b[0] }), + g = a.Event('show.bs.tab', { relatedTarget: e[0] }); + if ((e.trigger(f), b.trigger(g), !g.isDefaultPrevented() && !f.isDefaultPrevented())) { + var h = a(d); + this.activate(b.closest('li'), c), + this.activate(h, h.parent(), function () { + e.trigger({ type: 'hidden.bs.tab', relatedTarget: b[0] }), + b.trigger({ type: 'shown.bs.tab', relatedTarget: e[0] }); + }); + } + } + }), + (c.prototype.activate = function (b, d, e) { + function f() { + g + .removeClass('active') + .find('> .dropdown-menu > .active') + .removeClass('active') + .end() + .find('[data-toggle="tab"]') + .attr('aria-expanded', !1), + b.addClass('active').find('[data-toggle="tab"]').attr('aria-expanded', !0), + h ? (b[0].offsetWidth, b.addClass('in')) : b.removeClass('fade'), + b.parent('.dropdown-menu') && + b.closest('li.dropdown').addClass('active').end().find('[data-toggle="tab"]').attr('aria-expanded', !0), + e && e(); + } + var g = d.find('> .active'), + h = e && a.support.transition && ((g.length && g.hasClass('fade')) || !!d.find('> .fade').length); + g.length && h ? g.one('bsTransitionEnd', f).emulateTransitionEnd(c.TRANSITION_DURATION) : f(), + g.removeClass('in'); + }); + var d = a.fn.tab; + (a.fn.tab = b), + (a.fn.tab.Constructor = c), + (a.fn.tab.noConflict = function () { + return (a.fn.tab = d), this; + }); + var e = function (c) { + c.preventDefault(), b.call(a(this), 'show'); + }; + a(document) + .on('click.bs.tab.data-api', '[data-toggle="tab"]', e) + .on('click.bs.tab.data-api', '[data-toggle="pill"]', e); + })(jQuery), + +(function (a) { + 'use strict'; + function b(b) { + return this.each(function () { + var d = a(this), + e = d.data('bs.affix'), + f = 'object' == typeof b && b; + e || d.data('bs.affix', (e = new c(this, f))), 'string' == typeof b && e[b](); + }); + } + var c = function (b, d) { + (this.options = a.extend({}, c.DEFAULTS, d)), + (this.$target = a(this.options.target) + .on('scroll.bs.affix.data-api', a.proxy(this.checkPosition, this)) + .on('click.bs.affix.data-api', a.proxy(this.checkPositionWithEventLoop, this))), + (this.$element = a(b)), + (this.affixed = this.unpin = this.pinnedOffset = null), + this.checkPosition(); + }; + (c.VERSION = '3.3.1'), + (c.RESET = 'affix affix-top affix-bottom'), + (c.DEFAULTS = { offset: 0, target: window }), + (c.prototype.getState = function (a, b, c, d) { + var e = this.$target.scrollTop(), + f = this.$element.offset(), + g = this.$target.height(); + if (null != c && 'top' == this.affixed) return c > e ? 'top' : !1; + if ('bottom' == this.affixed) + return null != c ? (e + this.unpin <= f.top ? !1 : 'bottom') : a - d >= e + g ? !1 : 'bottom'; + var h = null == this.affixed, + i = h ? e : f.top, + j = h ? g : b; + return null != c && c >= i ? 'top' : null != d && i + j >= a - d ? 'bottom' : !1; + }), + (c.prototype.getPinnedOffset = function () { + if (this.pinnedOffset) return this.pinnedOffset; + this.$element.removeClass(c.RESET).addClass('affix'); + var a = this.$target.scrollTop(), + b = this.$element.offset(); + return (this.pinnedOffset = b.top - a); + }), + (c.prototype.checkPositionWithEventLoop = function () { + setTimeout(a.proxy(this.checkPosition, this), 1); + }), + (c.prototype.checkPosition = function () { + if (this.$element.is(':visible')) { + var b = this.$element.height(), + d = this.options.offset, + e = d.top, + f = d.bottom, + g = a('body').height(); + 'object' != typeof d && (f = e = d), + 'function' == typeof e && (e = d.top(this.$element)), + 'function' == typeof f && (f = d.bottom(this.$element)); + var h = this.getState(g, b, e, f); + if (this.affixed != h) { + null != this.unpin && this.$element.css('top', ''); + var i = 'affix' + (h ? '-' + h : ''), + j = a.Event(i + '.bs.affix'); + if ((this.$element.trigger(j), j.isDefaultPrevented())) return; + (this.affixed = h), + (this.unpin = 'bottom' == h ? this.getPinnedOffset() : null), + this.$element + .removeClass(c.RESET) + .addClass(i) + .trigger(i.replace('affix', 'affixed') + '.bs.affix'); + } + 'bottom' == h && this.$element.offset({ top: g - b - f }); + } + }); + var d = a.fn.affix; + (a.fn.affix = b), + (a.fn.affix.Constructor = c), + (a.fn.affix.noConflict = function () { + return (a.fn.affix = d), this; + }), + a(window).on('load', function () { + a('[data-spy="affix"]').each(function () { + var c = a(this), + d = c.data(); + (d.offset = d.offset || {}), + null != d.offsetBottom && (d.offset.bottom = d.offsetBottom), + null != d.offsetTop && (d.offset.top = d.offsetTop), + b.call(c, d); + }); + }); + })(jQuery); diff --git a/src/assets/js/jquery-2.1.3.min.js b/src/assets/js/jquery-2.1.3.min.js new file mode 100644 index 0000000..6c27cc7 --- /dev/null +++ b/src/assets/js/jquery-2.1.3.min.js @@ -0,0 +1,4462 @@ +/*! jQuery v2.1.3 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */ +!(function (a, b) { + 'object' == typeof module && 'object' == typeof module.exports + ? (module.exports = a.document + ? b(a, !0) + : function (a) { + if (!a.document) throw new Error('jQuery requires a window with a document'); + return b(a); + }) + : b(a); +})('undefined' != typeof window ? window : this, function (a, b) { + var c = [], + d = c.slice, + e = c.concat, + f = c.push, + g = c.indexOf, + h = {}, + i = h.toString, + j = h.hasOwnProperty, + k = {}, + l = a.document, + m = '2.1.3', + n = function (a, b) { + return new n.fn.init(a, b); + }, + o = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, + p = /^-ms-/, + q = /-([\da-z])/gi, + r = function (a, b) { + return b.toUpperCase(); + }; + (n.fn = n.prototype = + { + jquery: m, + constructor: n, + selector: '', + length: 0, + toArray: function () { + return d.call(this); + }, + get: function (a) { + return null != a ? (0 > a ? this[a + this.length] : this[a]) : d.call(this); + }, + pushStack: function (a) { + var b = n.merge(this.constructor(), a); + return (b.prevObject = this), (b.context = this.context), b; + }, + each: function (a, b) { + return n.each(this, a, b); + }, + map: function (a) { + return this.pushStack( + n.map(this, function (b, c) { + return a.call(b, c, b); + }), + ); + }, + slice: function () { + return this.pushStack(d.apply(this, arguments)); + }, + first: function () { + return this.eq(0); + }, + last: function () { + return this.eq(-1); + }, + eq: function (a) { + var b = this.length, + c = +a + (0 > a ? b : 0); + return this.pushStack(c >= 0 && b > c ? [this[c]] : []); + }, + end: function () { + return this.prevObject || this.constructor(null); + }, + push: f, + sort: c.sort, + splice: c.splice, + }), + (n.extend = n.fn.extend = + function () { + var a, + b, + c, + d, + e, + f, + g = arguments[0] || {}, + h = 1, + i = arguments.length, + j = !1; + for ( + 'boolean' == typeof g && ((j = g), (g = arguments[h] || {}), h++), + 'object' == typeof g || n.isFunction(g) || (g = {}), + h === i && ((g = this), h--); + i > h; + h++ + ) + if (null != (a = arguments[h])) + for (b in a) + (c = g[b]), + (d = a[b]), + g !== d && + (j && d && (n.isPlainObject(d) || (e = n.isArray(d))) + ? (e ? ((e = !1), (f = c && n.isArray(c) ? c : [])) : (f = c && n.isPlainObject(c) ? c : {}), + (g[b] = n.extend(j, f, d))) + : void 0 !== d && (g[b] = d)); + return g; + }), + n.extend({ + expando: 'jQuery' + (m + Math.random()).replace(/\D/g, ''), + isReady: !0, + error: function (a) { + throw new Error(a); + }, + noop: function () {}, + isFunction: function (a) { + return 'function' === n.type(a); + }, + isArray: Array.isArray, + isWindow: function (a) { + return null != a && a === a.window; + }, + isNumeric: function (a) { + return !n.isArray(a) && a - parseFloat(a) + 1 >= 0; + }, + isPlainObject: function (a) { + return 'object' !== n.type(a) || a.nodeType || n.isWindow(a) + ? !1 + : a.constructor && !j.call(a.constructor.prototype, 'isPrototypeOf') + ? !1 + : !0; + }, + isEmptyObject: function (a) { + var b; + for (b in a) return !1; + return !0; + }, + type: function (a) { + return null == a + ? a + '' + : 'object' == typeof a || 'function' == typeof a + ? h[i.call(a)] || 'object' + : typeof a; + }, + globalEval: function (a) { + var b, + c = eval; + (a = n.trim(a)), + a && + (1 === a.indexOf('use strict') + ? ((b = l.createElement('script')), (b.text = a), l.head.appendChild(b).parentNode.removeChild(b)) + : c(a)); + }, + camelCase: function (a) { + return a.replace(p, 'ms-').replace(q, r); + }, + nodeName: function (a, b) { + return a.nodeName && a.nodeName.toLowerCase() === b.toLowerCase(); + }, + each: function (a, b, c) { + var d, + e = 0, + f = a.length, + g = s(a); + if (c) { + if (g) { + for (; f > e; e++) if (((d = b.apply(a[e], c)), d === !1)) break; + } else for (e in a) if (((d = b.apply(a[e], c)), d === !1)) break; + } else if (g) { + for (; f > e; e++) if (((d = b.call(a[e], e, a[e])), d === !1)) break; + } else for (e in a) if (((d = b.call(a[e], e, a[e])), d === !1)) break; + return a; + }, + trim: function (a) { + return null == a ? '' : (a + '').replace(o, ''); + }, + makeArray: function (a, b) { + var c = b || []; + return null != a && (s(Object(a)) ? n.merge(c, 'string' == typeof a ? [a] : a) : f.call(c, a)), c; + }, + inArray: function (a, b, c) { + return null == b ? -1 : g.call(b, a, c); + }, + merge: function (a, b) { + for (var c = +b.length, d = 0, e = a.length; c > d; d++) a[e++] = b[d]; + return (a.length = e), a; + }, + grep: function (a, b, c) { + for (var d, e = [], f = 0, g = a.length, h = !c; g > f; f++) (d = !b(a[f], f)), d !== h && e.push(a[f]); + return e; + }, + map: function (a, b, c) { + var d, + f = 0, + g = a.length, + h = s(a), + i = []; + if (h) for (; g > f; f++) (d = b(a[f], f, c)), null != d && i.push(d); + else for (f in a) (d = b(a[f], f, c)), null != d && i.push(d); + return e.apply([], i); + }, + guid: 1, + proxy: function (a, b) { + var c, e, f; + return ( + 'string' == typeof b && ((c = a[b]), (b = a), (a = c)), + n.isFunction(a) + ? ((e = d.call(arguments, 2)), + (f = function () { + return a.apply(b || this, e.concat(d.call(arguments))); + }), + (f.guid = a.guid = a.guid || n.guid++), + f) + : void 0 + ); + }, + now: Date.now, + support: k, + }), + n.each('Boolean Number String Function Array Date RegExp Object Error'.split(' '), function (a, b) { + h['[object ' + b + ']'] = b.toLowerCase(); + }); + function s(a) { + var b = a.length, + c = n.type(a); + return 'function' === c || n.isWindow(a) + ? !1 + : 1 === a.nodeType && b + ? !0 + : 'array' === c || 0 === b || ('number' == typeof b && b > 0 && b - 1 in a); + } + var t = (function (a) { + var b, + c, + d, + e, + f, + g, + h, + i, + j, + k, + l, + m, + n, + o, + p, + q, + r, + s, + t, + u = 'sizzle' + 1 * new Date(), + v = a.document, + w = 0, + x = 0, + y = hb(), + z = hb(), + A = hb(), + B = function (a, b) { + return a === b && (l = !0), 0; + }, + C = 1 << 31, + D = {}.hasOwnProperty, + E = [], + F = E.pop, + G = E.push, + H = E.push, + I = E.slice, + J = function (a, b) { + for (var c = 0, d = a.length; d > c; c++) if (a[c] === b) return c; + return -1; + }, + K = + 'checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped', + L = '[\\x20\\t\\r\\n\\f]', + M = '(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+', + N = M.replace('w', 'w#'), + O = + '\\[' + + L + + '*(' + + M + + ')(?:' + + L + + '*([*^$|!~]?=)' + + L + + '*(?:\'((?:\\\\.|[^\\\\\'])*)\'|"((?:\\\\.|[^\\\\"])*)"|(' + + N + + '))|)' + + L + + '*\\]', + P = + ':(' + + M + + ')(?:\\(((\'((?:\\\\.|[^\\\\\'])*)\'|"((?:\\\\.|[^\\\\"])*)")|((?:\\\\.|[^\\\\()[\\]]|' + + O + + ')*)|.*)\\)|)', + Q = new RegExp(L + '+', 'g'), + R = new RegExp('^' + L + '+|((?:^|[^\\\\])(?:\\\\.)*)' + L + '+$', 'g'), + S = new RegExp('^' + L + '*,' + L + '*'), + T = new RegExp('^' + L + '*([>+~]|' + L + ')' + L + '*'), + U = new RegExp('=' + L + '*([^\\]\'"]*?)' + L + '*\\]', 'g'), + V = new RegExp(P), + W = new RegExp('^' + N + '$'), + X = { + ID: new RegExp('^#(' + M + ')'), + CLASS: new RegExp('^\\.(' + M + ')'), + TAG: new RegExp('^(' + M.replace('w', 'w*') + ')'), + ATTR: new RegExp('^' + O), + PSEUDO: new RegExp('^' + P), + CHILD: new RegExp( + '^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(' + + L + + '*(even|odd|(([+-]|)(\\d*)n|)' + + L + + '*(?:([+-]|)' + + L + + '*(\\d+)|))' + + L + + '*\\)|)', + 'i', + ), + bool: new RegExp('^(?:' + K + ')$', 'i'), + needsContext: new RegExp( + '^' + + L + + '*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(' + + L + + '*((?:-\\d)?\\d*)' + + L + + '*\\)|)(?=[^-]|$)', + 'i', + ), + }, + Y = /^(?:input|select|textarea|button)$/i, + Z = /^h\d$/i, + $ = /^[^{]+\{\s*\[native \w/, + _ = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + ab = /[+~]/, + bb = /'|\\/g, + cb = new RegExp('\\\\([\\da-f]{1,6}' + L + '?|(' + L + ')|.)', 'ig'), + db = function (a, b, c) { + var d = '0x' + b - 65536; + return d !== d || c + ? b + : 0 > d + ? String.fromCharCode(d + 65536) + : String.fromCharCode((d >> 10) | 55296, (1023 & d) | 56320); + }, + eb = function () { + m(); + }; + try { + H.apply((E = I.call(v.childNodes)), v.childNodes), E[v.childNodes.length].nodeType; + } catch (fb) { + H = { + apply: E.length + ? function (a, b) { + G.apply(a, I.call(b)); + } + : function (a, b) { + var c = a.length, + d = 0; + while ((a[c++] = b[d++])); + a.length = c - 1; + }, + }; + } + function gb(a, b, d, e) { + var f, h, j, k, l, o, r, s, w, x; + if ( + ((b ? b.ownerDocument || b : v) !== n && m(b), + (b = b || n), + (d = d || []), + (k = b.nodeType), + 'string' != typeof a || !a || (1 !== k && 9 !== k && 11 !== k)) + ) + return d; + if (!e && p) { + if (11 !== k && (f = _.exec(a))) + if ((j = f[1])) { + if (9 === k) { + if (((h = b.getElementById(j)), !h || !h.parentNode)) return d; + if (h.id === j) return d.push(h), d; + } else if (b.ownerDocument && (h = b.ownerDocument.getElementById(j)) && t(b, h) && h.id === j) + return d.push(h), d; + } else { + if (f[2]) return H.apply(d, b.getElementsByTagName(a)), d; + if ((j = f[3]) && c.getElementsByClassName) return H.apply(d, b.getElementsByClassName(j)), d; + } + if (c.qsa && (!q || !q.test(a))) { + if (((s = r = u), (w = b), (x = 1 !== k && a), 1 === k && 'object' !== b.nodeName.toLowerCase())) { + (o = g(a)), + (r = b.getAttribute('id')) ? (s = r.replace(bb, '\\$&')) : b.setAttribute('id', s), + (s = "[id='" + s + "'] "), + (l = o.length); + while (l--) o[l] = s + rb(o[l]); + (w = (ab.test(a) && pb(b.parentNode)) || b), (x = o.join(',')); + } + if (x) + try { + return H.apply(d, w.querySelectorAll(x)), d; + } catch (y) { + } finally { + r || b.removeAttribute('id'); + } + } + } + return i(a.replace(R, '$1'), b, d, e); + } + function hb() { + var a = []; + function b(c, e) { + return a.push(c + ' ') > d.cacheLength && delete b[a.shift()], (b[c + ' '] = e); + } + return b; + } + function ib(a) { + return (a[u] = !0), a; + } + function jb(a) { + var b = n.createElement('div'); + try { + return !!a(b); + } catch (c) { + return !1; + } finally { + b.parentNode && b.parentNode.removeChild(b), (b = null); + } + } + function kb(a, b) { + var c = a.split('|'), + e = a.length; + while (e--) d.attrHandle[c[e]] = b; + } + function lb(a, b) { + var c = b && a, + d = c && 1 === a.nodeType && 1 === b.nodeType && (~b.sourceIndex || C) - (~a.sourceIndex || C); + if (d) return d; + if (c) while ((c = c.nextSibling)) if (c === b) return -1; + return a ? 1 : -1; + } + function mb(a) { + return function (b) { + var c = b.nodeName.toLowerCase(); + return 'input' === c && b.type === a; + }; + } + function nb(a) { + return function (b) { + var c = b.nodeName.toLowerCase(); + return ('input' === c || 'button' === c) && b.type === a; + }; + } + function ob(a) { + return ib(function (b) { + return ( + (b = +b), + ib(function (c, d) { + var e, + f = a([], c.length, b), + g = f.length; + while (g--) c[(e = f[g])] && (c[e] = !(d[e] = c[e])); + }) + ); + }); + } + function pb(a) { + return a && 'undefined' != typeof a.getElementsByTagName && a; + } + (c = gb.support = {}), + (f = gb.isXML = + function (a) { + var b = a && (a.ownerDocument || a).documentElement; + return b ? 'HTML' !== b.nodeName : !1; + }), + (m = gb.setDocument = + function (a) { + var b, + e, + g = a ? a.ownerDocument || a : v; + return g !== n && 9 === g.nodeType && g.documentElement + ? ((n = g), + (o = g.documentElement), + (e = g.defaultView), + e && + e !== e.top && + (e.addEventListener + ? e.addEventListener('unload', eb, !1) + : e.attachEvent && e.attachEvent('onunload', eb)), + (p = !f(g)), + (c.attributes = jb(function (a) { + return (a.className = 'i'), !a.getAttribute('className'); + })), + (c.getElementsByTagName = jb(function (a) { + return a.appendChild(g.createComment('')), !a.getElementsByTagName('*').length; + })), + (c.getElementsByClassName = $.test(g.getElementsByClassName)), + (c.getById = jb(function (a) { + return (o.appendChild(a).id = u), !g.getElementsByName || !g.getElementsByName(u).length; + })), + c.getById + ? ((d.find.ID = function (a, b) { + if ('undefined' != typeof b.getElementById && p) { + var c = b.getElementById(a); + return c && c.parentNode ? [c] : []; + } + }), + (d.filter.ID = function (a) { + var b = a.replace(cb, db); + return function (a) { + return a.getAttribute('id') === b; + }; + })) + : (delete d.find.ID, + (d.filter.ID = function (a) { + var b = a.replace(cb, db); + return function (a) { + var c = 'undefined' != typeof a.getAttributeNode && a.getAttributeNode('id'); + return c && c.value === b; + }; + })), + (d.find.TAG = c.getElementsByTagName + ? function (a, b) { + return 'undefined' != typeof b.getElementsByTagName + ? b.getElementsByTagName(a) + : c.qsa + ? b.querySelectorAll(a) + : void 0; + } + : function (a, b) { + var c, + d = [], + e = 0, + f = b.getElementsByTagName(a); + if ('*' === a) { + while ((c = f[e++])) 1 === c.nodeType && d.push(c); + return d; + } + return f; + }), + (d.find.CLASS = + c.getElementsByClassName && + function (a, b) { + return p ? b.getElementsByClassName(a) : void 0; + }), + (r = []), + (q = []), + (c.qsa = $.test(g.querySelectorAll)) && + (jb(function (a) { + (o.appendChild(a).innerHTML = + "<a id='" + + u + + "'></a><select id='" + + u + + "-\f]' msallowcapture=''><option selected=''></option></select>"), + a.querySelectorAll("[msallowcapture^='']").length && q.push('[*^$]=' + L + '*(?:\'\'|"")'), + a.querySelectorAll('[selected]').length || q.push('\\[' + L + '*(?:value|' + K + ')'), + a.querySelectorAll('[id~=' + u + '-]').length || q.push('~='), + a.querySelectorAll(':checked').length || q.push(':checked'), + a.querySelectorAll('a#' + u + '+*').length || q.push('.#.+[+~]'); + }), + jb(function (a) { + var b = g.createElement('input'); + b.setAttribute('type', 'hidden'), + a.appendChild(b).setAttribute('name', 'D'), + a.querySelectorAll('[name=d]').length && q.push('name' + L + '*[*^$|!~]?='), + a.querySelectorAll(':enabled').length || q.push(':enabled', ':disabled'), + a.querySelectorAll('*,:x'), + q.push(',.*:'); + })), + (c.matchesSelector = $.test( + (s = + o.matches || + o.webkitMatchesSelector || + o.mozMatchesSelector || + o.oMatchesSelector || + o.msMatchesSelector), + )) && + jb(function (a) { + (c.disconnectedMatch = s.call(a, 'div')), s.call(a, "[s!='']:x"), r.push('!=', P); + }), + (q = q.length && new RegExp(q.join('|'))), + (r = r.length && new RegExp(r.join('|'))), + (b = $.test(o.compareDocumentPosition)), + (t = + b || $.test(o.contains) + ? function (a, b) { + var c = 9 === a.nodeType ? a.documentElement : a, + d = b && b.parentNode; + return ( + a === d || + !( + !d || + 1 !== d.nodeType || + !(c.contains ? c.contains(d) : a.compareDocumentPosition && 16 & a.compareDocumentPosition(d)) + ) + ); + } + : function (a, b) { + if (b) while ((b = b.parentNode)) if (b === a) return !0; + return !1; + }), + (B = b + ? function (a, b) { + if (a === b) return (l = !0), 0; + var d = !a.compareDocumentPosition - !b.compareDocumentPosition; + return d + ? d + : ((d = (a.ownerDocument || a) === (b.ownerDocument || b) ? a.compareDocumentPosition(b) : 1), + 1 & d || (!c.sortDetached && b.compareDocumentPosition(a) === d) + ? a === g || (a.ownerDocument === v && t(v, a)) + ? -1 + : b === g || (b.ownerDocument === v && t(v, b)) + ? 1 + : k + ? J(k, a) - J(k, b) + : 0 + : 4 & d + ? -1 + : 1); + } + : function (a, b) { + if (a === b) return (l = !0), 0; + var c, + d = 0, + e = a.parentNode, + f = b.parentNode, + h = [a], + i = [b]; + if (!e || !f) return a === g ? -1 : b === g ? 1 : e ? -1 : f ? 1 : k ? J(k, a) - J(k, b) : 0; + if (e === f) return lb(a, b); + c = a; + while ((c = c.parentNode)) h.unshift(c); + c = b; + while ((c = c.parentNode)) i.unshift(c); + while (h[d] === i[d]) d++; + return d ? lb(h[d], i[d]) : h[d] === v ? -1 : i[d] === v ? 1 : 0; + }), + g) + : n; + }), + (gb.matches = function (a, b) { + return gb(a, null, null, b); + }), + (gb.matchesSelector = function (a, b) { + if ( + ((a.ownerDocument || a) !== n && m(a), + (b = b.replace(U, "='$1']")), + !(!c.matchesSelector || !p || (r && r.test(b)) || (q && q.test(b)))) + ) + try { + var d = s.call(a, b); + if (d || c.disconnectedMatch || (a.document && 11 !== a.document.nodeType)) return d; + } catch (e) {} + return gb(b, n, null, [a]).length > 0; + }), + (gb.contains = function (a, b) { + return (a.ownerDocument || a) !== n && m(a), t(a, b); + }), + (gb.attr = function (a, b) { + (a.ownerDocument || a) !== n && m(a); + var e = d.attrHandle[b.toLowerCase()], + f = e && D.call(d.attrHandle, b.toLowerCase()) ? e(a, b, !p) : void 0; + return void 0 !== f + ? f + : c.attributes || !p + ? a.getAttribute(b) + : (f = a.getAttributeNode(b)) && f.specified + ? f.value + : null; + }), + (gb.error = function (a) { + throw new Error('Syntax error, unrecognized expression: ' + a); + }), + (gb.uniqueSort = function (a) { + var b, + d = [], + e = 0, + f = 0; + if (((l = !c.detectDuplicates), (k = !c.sortStable && a.slice(0)), a.sort(B), l)) { + while ((b = a[f++])) b === a[f] && (e = d.push(f)); + while (e--) a.splice(d[e], 1); + } + return (k = null), a; + }), + (e = gb.getText = + function (a) { + var b, + c = '', + d = 0, + f = a.nodeType; + if (f) { + if (1 === f || 9 === f || 11 === f) { + if ('string' == typeof a.textContent) return a.textContent; + for (a = a.firstChild; a; a = a.nextSibling) c += e(a); + } else if (3 === f || 4 === f) return a.nodeValue; + } else while ((b = a[d++])) c += e(b); + return c; + }), + (d = gb.selectors = + { + cacheLength: 50, + createPseudo: ib, + match: X, + attrHandle: {}, + find: {}, + relative: { + '>': { dir: 'parentNode', first: !0 }, + ' ': { dir: 'parentNode' }, + '+': { dir: 'previousSibling', first: !0 }, + '~': { dir: 'previousSibling' }, + }, + preFilter: { + ATTR: function (a) { + return ( + (a[1] = a[1].replace(cb, db)), + (a[3] = (a[3] || a[4] || a[5] || '').replace(cb, db)), + '~=' === a[2] && (a[3] = ' ' + a[3] + ' '), + a.slice(0, 4) + ); + }, + CHILD: function (a) { + return ( + (a[1] = a[1].toLowerCase()), + 'nth' === a[1].slice(0, 3) + ? (a[3] || gb.error(a[0]), + (a[4] = +(a[4] ? a[5] + (a[6] || 1) : 2 * ('even' === a[3] || 'odd' === a[3]))), + (a[5] = +(a[7] + a[8] || 'odd' === a[3]))) + : a[3] && gb.error(a[0]), + a + ); + }, + PSEUDO: function (a) { + var b, + c = !a[6] && a[2]; + return X.CHILD.test(a[0]) + ? null + : (a[3] + ? (a[2] = a[4] || a[5] || '') + : c && + V.test(c) && + (b = g(c, !0)) && + (b = c.indexOf(')', c.length - b) - c.length) && + ((a[0] = a[0].slice(0, b)), (a[2] = c.slice(0, b))), + a.slice(0, 3)); + }, + }, + filter: { + TAG: function (a) { + var b = a.replace(cb, db).toLowerCase(); + return '*' === a + ? function () { + return !0; + } + : function (a) { + return a.nodeName && a.nodeName.toLowerCase() === b; + }; + }, + CLASS: function (a) { + var b = y[a + ' ']; + return ( + b || + ((b = new RegExp('(^|' + L + ')' + a + '(' + L + '|$)')) && + y(a, function (a) { + return b.test( + ('string' == typeof a.className && a.className) || + ('undefined' != typeof a.getAttribute && a.getAttribute('class')) || + '', + ); + })) + ); + }, + ATTR: function (a, b, c) { + return function (d) { + var e = gb.attr(d, a); + return null == e + ? '!=' === b + : b + ? ((e += ''), + '=' === b + ? e === c + : '!=' === b + ? e !== c + : '^=' === b + ? c && 0 === e.indexOf(c) + : '*=' === b + ? c && e.indexOf(c) > -1 + : '$=' === b + ? c && e.slice(-c.length) === c + : '~=' === b + ? (' ' + e.replace(Q, ' ') + ' ').indexOf(c) > -1 + : '|=' === b + ? e === c || e.slice(0, c.length + 1) === c + '-' + : !1) + : !0; + }; + }, + CHILD: function (a, b, c, d, e) { + var f = 'nth' !== a.slice(0, 3), + g = 'last' !== a.slice(-4), + h = 'of-type' === b; + return 1 === d && 0 === e + ? function (a) { + return !!a.parentNode; + } + : function (b, c, i) { + var j, + k, + l, + m, + n, + o, + p = f !== g ? 'nextSibling' : 'previousSibling', + q = b.parentNode, + r = h && b.nodeName.toLowerCase(), + s = !i && !h; + if (q) { + if (f) { + while (p) { + l = b; + while ((l = l[p])) if (h ? l.nodeName.toLowerCase() === r : 1 === l.nodeType) return !1; + o = p = 'only' === a && !o && 'nextSibling'; + } + return !0; + } + if (((o = [g ? q.firstChild : q.lastChild]), g && s)) { + (k = q[u] || (q[u] = {})), + (j = k[a] || []), + (n = j[0] === w && j[1]), + (m = j[0] === w && j[2]), + (l = n && q.childNodes[n]); + while ((l = (++n && l && l[p]) || (m = n = 0) || o.pop())) + if (1 === l.nodeType && ++m && l === b) { + k[a] = [w, n, m]; + break; + } + } else if (s && (j = (b[u] || (b[u] = {}))[a]) && j[0] === w) m = j[1]; + else + while ((l = (++n && l && l[p]) || (m = n = 0) || o.pop())) + if ( + (h ? l.nodeName.toLowerCase() === r : 1 === l.nodeType) && + ++m && + (s && ((l[u] || (l[u] = {}))[a] = [w, m]), l === b) + ) + break; + return (m -= e), m === d || (m % d === 0 && m / d >= 0); + } + }; + }, + PSEUDO: function (a, b) { + var c, + e = d.pseudos[a] || d.setFilters[a.toLowerCase()] || gb.error('unsupported pseudo: ' + a); + return e[u] + ? e(b) + : e.length > 1 + ? ((c = [a, a, '', b]), + d.setFilters.hasOwnProperty(a.toLowerCase()) + ? ib(function (a, c) { + var d, + f = e(a, b), + g = f.length; + while (g--) (d = J(a, f[g])), (a[d] = !(c[d] = f[g])); + }) + : function (a) { + return e(a, 0, c); + }) + : e; + }, + }, + pseudos: { + not: ib(function (a) { + var b = [], + c = [], + d = h(a.replace(R, '$1')); + return d[u] + ? ib(function (a, b, c, e) { + var f, + g = d(a, null, e, []), + h = a.length; + while (h--) (f = g[h]) && (a[h] = !(b[h] = f)); + }) + : function (a, e, f) { + return (b[0] = a), d(b, null, f, c), (b[0] = null), !c.pop(); + }; + }), + has: ib(function (a) { + return function (b) { + return gb(a, b).length > 0; + }; + }), + contains: ib(function (a) { + return ( + (a = a.replace(cb, db)), + function (b) { + return (b.textContent || b.innerText || e(b)).indexOf(a) > -1; + } + ); + }), + lang: ib(function (a) { + return ( + W.test(a || '') || gb.error('unsupported lang: ' + a), + (a = a.replace(cb, db).toLowerCase()), + function (b) { + var c; + do + if ((c = p ? b.lang : b.getAttribute('xml:lang') || b.getAttribute('lang'))) + return (c = c.toLowerCase()), c === a || 0 === c.indexOf(a + '-'); + while ((b = b.parentNode) && 1 === b.nodeType); + return !1; + } + ); + }), + target: function (b) { + var c = a.location && a.location.hash; + return c && c.slice(1) === b.id; + }, + root: function (a) { + return a === o; + }, + focus: function (a) { + return a === n.activeElement && (!n.hasFocus || n.hasFocus()) && !!(a.type || a.href || ~a.tabIndex); + }, + enabled: function (a) { + return a.disabled === !1; + }, + disabled: function (a) { + return a.disabled === !0; + }, + checked: function (a) { + var b = a.nodeName.toLowerCase(); + return ('input' === b && !!a.checked) || ('option' === b && !!a.selected); + }, + selected: function (a) { + return a.parentNode && a.parentNode.selectedIndex, a.selected === !0; + }, + empty: function (a) { + for (a = a.firstChild; a; a = a.nextSibling) if (a.nodeType < 6) return !1; + return !0; + }, + parent: function (a) { + return !d.pseudos.empty(a); + }, + header: function (a) { + return Z.test(a.nodeName); + }, + input: function (a) { + return Y.test(a.nodeName); + }, + button: function (a) { + var b = a.nodeName.toLowerCase(); + return ('input' === b && 'button' === a.type) || 'button' === b; + }, + text: function (a) { + var b; + return ( + 'input' === a.nodeName.toLowerCase() && + 'text' === a.type && + (null == (b = a.getAttribute('type')) || 'text' === b.toLowerCase()) + ); + }, + first: ob(function () { + return [0]; + }), + last: ob(function (a, b) { + return [b - 1]; + }), + eq: ob(function (a, b, c) { + return [0 > c ? c + b : c]; + }), + even: ob(function (a, b) { + for (var c = 0; b > c; c += 2) a.push(c); + return a; + }), + odd: ob(function (a, b) { + for (var c = 1; b > c; c += 2) a.push(c); + return a; + }), + lt: ob(function (a, b, c) { + for (var d = 0 > c ? c + b : c; --d >= 0; ) a.push(d); + return a; + }), + gt: ob(function (a, b, c) { + for (var d = 0 > c ? c + b : c; ++d < b; ) a.push(d); + return a; + }), + }, + }), + (d.pseudos.nth = d.pseudos.eq); + for (b in { radio: !0, checkbox: !0, file: !0, password: !0, image: !0 }) d.pseudos[b] = mb(b); + for (b in { submit: !0, reset: !0 }) d.pseudos[b] = nb(b); + function qb() {} + (qb.prototype = d.filters = d.pseudos), + (d.setFilters = new qb()), + (g = gb.tokenize = + function (a, b) { + var c, + e, + f, + g, + h, + i, + j, + k = z[a + ' ']; + if (k) return b ? 0 : k.slice(0); + (h = a), (i = []), (j = d.preFilter); + while (h) { + (!c || (e = S.exec(h))) && (e && (h = h.slice(e[0].length) || h), i.push((f = []))), + (c = !1), + (e = T.exec(h)) && + ((c = e.shift()), f.push({ value: c, type: e[0].replace(R, ' ') }), (h = h.slice(c.length))); + for (g in d.filter) + !(e = X[g].exec(h)) || + (j[g] && !(e = j[g](e))) || + ((c = e.shift()), f.push({ value: c, type: g, matches: e }), (h = h.slice(c.length))); + if (!c) break; + } + return b ? h.length : h ? gb.error(a) : z(a, i).slice(0); + }); + function rb(a) { + for (var b = 0, c = a.length, d = ''; c > b; b++) d += a[b].value; + return d; + } + function sb(a, b, c) { + var d = b.dir, + e = c && 'parentNode' === d, + f = x++; + return b.first + ? function (b, c, f) { + while ((b = b[d])) if (1 === b.nodeType || e) return a(b, c, f); + } + : function (b, c, g) { + var h, + i, + j = [w, f]; + if (g) { + while ((b = b[d])) if ((1 === b.nodeType || e) && a(b, c, g)) return !0; + } else + while ((b = b[d])) + if (1 === b.nodeType || e) { + if (((i = b[u] || (b[u] = {})), (h = i[d]) && h[0] === w && h[1] === f)) return (j[2] = h[2]); + if (((i[d] = j), (j[2] = a(b, c, g)))) return !0; + } + }; + } + function tb(a) { + return a.length > 1 + ? function (b, c, d) { + var e = a.length; + while (e--) if (!a[e](b, c, d)) return !1; + return !0; + } + : a[0]; + } + function ub(a, b, c) { + for (var d = 0, e = b.length; e > d; d++) gb(a, b[d], c); + return c; + } + function vb(a, b, c, d, e) { + for (var f, g = [], h = 0, i = a.length, j = null != b; i > h; h++) + (f = a[h]) && (!c || c(f, d, e)) && (g.push(f), j && b.push(h)); + return g; + } + function wb(a, b, c, d, e, f) { + return ( + d && !d[u] && (d = wb(d)), + e && !e[u] && (e = wb(e, f)), + ib(function (f, g, h, i) { + var j, + k, + l, + m = [], + n = [], + o = g.length, + p = f || ub(b || '*', h.nodeType ? [h] : h, []), + q = !a || (!f && b) ? p : vb(p, m, a, h, i), + r = c ? (e || (f ? a : o || d) ? [] : g) : q; + if ((c && c(q, r, h, i), d)) { + (j = vb(r, n)), d(j, [], h, i), (k = j.length); + while (k--) (l = j[k]) && (r[n[k]] = !(q[n[k]] = l)); + } + if (f) { + if (e || a) { + if (e) { + (j = []), (k = r.length); + while (k--) (l = r[k]) && j.push((q[k] = l)); + e(null, (r = []), j, i); + } + k = r.length; + while (k--) (l = r[k]) && (j = e ? J(f, l) : m[k]) > -1 && (f[j] = !(g[j] = l)); + } + } else (r = vb(r === g ? r.splice(o, r.length) : r)), e ? e(null, g, r, i) : H.apply(g, r); + }) + ); + } + function xb(a) { + for ( + var b, + c, + e, + f = a.length, + g = d.relative[a[0].type], + h = g || d.relative[' '], + i = g ? 1 : 0, + k = sb( + function (a) { + return a === b; + }, + h, + !0, + ), + l = sb( + function (a) { + return J(b, a) > -1; + }, + h, + !0, + ), + m = [ + function (a, c, d) { + var e = (!g && (d || c !== j)) || ((b = c).nodeType ? k(a, c, d) : l(a, c, d)); + return (b = null), e; + }, + ]; + f > i; + i++ + ) + if ((c = d.relative[a[i].type])) m = [sb(tb(m), c)]; + else { + if (((c = d.filter[a[i].type].apply(null, a[i].matches)), c[u])) { + for (e = ++i; f > e; e++) if (d.relative[a[e].type]) break; + return wb( + i > 1 && tb(m), + i > 1 && rb(a.slice(0, i - 1).concat({ value: ' ' === a[i - 2].type ? '*' : '' })).replace(R, '$1'), + c, + e > i && xb(a.slice(i, e)), + f > e && xb((a = a.slice(e))), + f > e && rb(a), + ); + } + m.push(c); + } + return tb(m); + } + function yb(a, b) { + var c = b.length > 0, + e = a.length > 0, + f = function (f, g, h, i, k) { + var l, + m, + o, + p = 0, + q = '0', + r = f && [], + s = [], + t = j, + u = f || (e && d.find.TAG('*', k)), + v = (w += null == t ? 1 : Math.random() || 0.1), + x = u.length; + for (k && (j = g !== n && g); q !== x && null != (l = u[q]); q++) { + if (e && l) { + m = 0; + while ((o = a[m++])) + if (o(l, g, h)) { + i.push(l); + break; + } + k && (w = v); + } + c && ((l = !o && l) && p--, f && r.push(l)); + } + if (((p += q), c && q !== p)) { + m = 0; + while ((o = b[m++])) o(r, s, g, h); + if (f) { + if (p > 0) while (q--) r[q] || s[q] || (s[q] = F.call(i)); + s = vb(s); + } + H.apply(i, s), k && !f && s.length > 0 && p + b.length > 1 && gb.uniqueSort(i); + } + return k && ((w = v), (j = t)), r; + }; + return c ? ib(f) : f; + } + return ( + (h = gb.compile = + function (a, b) { + var c, + d = [], + e = [], + f = A[a + ' ']; + if (!f) { + b || (b = g(a)), (c = b.length); + while (c--) (f = xb(b[c])), f[u] ? d.push(f) : e.push(f); + (f = A(a, yb(e, d))), (f.selector = a); + } + return f; + }), + (i = gb.select = + function (a, b, e, f) { + var i, + j, + k, + l, + m, + n = 'function' == typeof a && a, + o = !f && g((a = n.selector || a)); + if (((e = e || []), 1 === o.length)) { + if ( + ((j = o[0] = o[0].slice(0)), + j.length > 2 && 'ID' === (k = j[0]).type && c.getById && 9 === b.nodeType && p && d.relative[j[1].type]) + ) { + if (((b = (d.find.ID(k.matches[0].replace(cb, db), b) || [])[0]), !b)) return e; + n && (b = b.parentNode), (a = a.slice(j.shift().value.length)); + } + i = X.needsContext.test(a) ? 0 : j.length; + while (i--) { + if (((k = j[i]), d.relative[(l = k.type)])) break; + if ( + (m = d.find[l]) && + (f = m(k.matches[0].replace(cb, db), (ab.test(j[0].type) && pb(b.parentNode)) || b)) + ) { + if ((j.splice(i, 1), (a = f.length && rb(j)), !a)) return H.apply(e, f), e; + break; + } + } + } + return (n || h(a, o))(f, b, !p, e, (ab.test(a) && pb(b.parentNode)) || b), e; + }), + (c.sortStable = u.split('').sort(B).join('') === u), + (c.detectDuplicates = !!l), + m(), + (c.sortDetached = jb(function (a) { + return 1 & a.compareDocumentPosition(n.createElement('div')); + })), + jb(function (a) { + return (a.innerHTML = "<a href='#'></a>"), '#' === a.firstChild.getAttribute('href'); + }) || + kb('type|href|height|width', function (a, b, c) { + return c ? void 0 : a.getAttribute(b, 'type' === b.toLowerCase() ? 1 : 2); + }), + (c.attributes && + jb(function (a) { + return ( + (a.innerHTML = '<input/>'), + a.firstChild.setAttribute('value', ''), + '' === a.firstChild.getAttribute('value') + ); + })) || + kb('value', function (a, b, c) { + return c || 'input' !== a.nodeName.toLowerCase() ? void 0 : a.defaultValue; + }), + jb(function (a) { + return null == a.getAttribute('disabled'); + }) || + kb(K, function (a, b, c) { + var d; + return c + ? void 0 + : a[b] === !0 + ? b.toLowerCase() + : (d = a.getAttributeNode(b)) && d.specified + ? d.value + : null; + }), + gb + ); + })(a); + (n.find = t), + (n.expr = t.selectors), + (n.expr[':'] = n.expr.pseudos), + (n.unique = t.uniqueSort), + (n.text = t.getText), + (n.isXMLDoc = t.isXML), + (n.contains = t.contains); + var u = n.expr.match.needsContext, + v = /^<(\w+)\s*\/?>(?:<\/\1>|)$/, + w = /^.[^:#\[\.,]*$/; + function x(a, b, c) { + if (n.isFunction(b)) + return n.grep(a, function (a, d) { + return !!b.call(a, d, a) !== c; + }); + if (b.nodeType) + return n.grep(a, function (a) { + return (a === b) !== c; + }); + if ('string' == typeof b) { + if (w.test(b)) return n.filter(b, a, c); + b = n.filter(b, a); + } + return n.grep(a, function (a) { + return g.call(b, a) >= 0 !== c; + }); + } + (n.filter = function (a, b, c) { + var d = b[0]; + return ( + c && (a = ':not(' + a + ')'), + 1 === b.length && 1 === d.nodeType + ? n.find.matchesSelector(d, a) + ? [d] + : [] + : n.find.matches( + a, + n.grep(b, function (a) { + return 1 === a.nodeType; + }), + ) + ); + }), + n.fn.extend({ + find: function (a) { + var b, + c = this.length, + d = [], + e = this; + if ('string' != typeof a) + return this.pushStack( + n(a).filter(function () { + for (b = 0; c > b; b++) if (n.contains(e[b], this)) return !0; + }), + ); + for (b = 0; c > b; b++) n.find(a, e[b], d); + return ( + (d = this.pushStack(c > 1 ? n.unique(d) : d)), (d.selector = this.selector ? this.selector + ' ' + a : a), d + ); + }, + filter: function (a) { + return this.pushStack(x(this, a || [], !1)); + }, + not: function (a) { + return this.pushStack(x(this, a || [], !0)); + }, + is: function (a) { + return !!x(this, 'string' == typeof a && u.test(a) ? n(a) : a || [], !1).length; + }, + }); + var y, + z = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/, + A = (n.fn.init = function (a, b) { + var c, d; + if (!a) return this; + if ('string' == typeof a) { + if ( + ((c = '<' === a[0] && '>' === a[a.length - 1] && a.length >= 3 ? [null, a, null] : z.exec(a)), + !c || (!c[1] && b)) + ) + return !b || b.jquery ? (b || y).find(a) : this.constructor(b).find(a); + if (c[1]) { + if ( + ((b = b instanceof n ? b[0] : b), + n.merge(this, n.parseHTML(c[1], b && b.nodeType ? b.ownerDocument || b : l, !0)), + v.test(c[1]) && n.isPlainObject(b)) + ) + for (c in b) n.isFunction(this[c]) ? this[c](b[c]) : this.attr(c, b[c]); + return this; + } + return ( + (d = l.getElementById(c[2])), + d && d.parentNode && ((this.length = 1), (this[0] = d)), + (this.context = l), + (this.selector = a), + this + ); + } + return a.nodeType + ? ((this.context = this[0] = a), (this.length = 1), this) + : n.isFunction(a) + ? 'undefined' != typeof y.ready + ? y.ready(a) + : a(n) + : (void 0 !== a.selector && ((this.selector = a.selector), (this.context = a.context)), n.makeArray(a, this)); + }); + (A.prototype = n.fn), (y = n(l)); + var B = /^(?:parents|prev(?:Until|All))/, + C = { children: !0, contents: !0, next: !0, prev: !0 }; + n.extend({ + dir: function (a, b, c) { + var d = [], + e = void 0 !== c; + while ((a = a[b]) && 9 !== a.nodeType) + if (1 === a.nodeType) { + if (e && n(a).is(c)) break; + d.push(a); + } + return d; + }, + sibling: function (a, b) { + for (var c = []; a; a = a.nextSibling) 1 === a.nodeType && a !== b && c.push(a); + return c; + }, + }), + n.fn.extend({ + has: function (a) { + var b = n(a, this), + c = b.length; + return this.filter(function () { + for (var a = 0; c > a; a++) if (n.contains(this, b[a])) return !0; + }); + }, + closest: function (a, b) { + for ( + var c, d = 0, e = this.length, f = [], g = u.test(a) || 'string' != typeof a ? n(a, b || this.context) : 0; + e > d; + d++ + ) + for (c = this[d]; c && c !== b; c = c.parentNode) + if (c.nodeType < 11 && (g ? g.index(c) > -1 : 1 === c.nodeType && n.find.matchesSelector(c, a))) { + f.push(c); + break; + } + return this.pushStack(f.length > 1 ? n.unique(f) : f); + }, + index: function (a) { + return a + ? 'string' == typeof a + ? g.call(n(a), this[0]) + : g.call(this, a.jquery ? a[0] : a) + : this[0] && this[0].parentNode + ? this.first().prevAll().length + : -1; + }, + add: function (a, b) { + return this.pushStack(n.unique(n.merge(this.get(), n(a, b)))); + }, + addBack: function (a) { + return this.add(null == a ? this.prevObject : this.prevObject.filter(a)); + }, + }); + function D(a, b) { + while ((a = a[b]) && 1 !== a.nodeType); + return a; + } + n.each( + { + parent: function (a) { + var b = a.parentNode; + return b && 11 !== b.nodeType ? b : null; + }, + parents: function (a) { + return n.dir(a, 'parentNode'); + }, + parentsUntil: function (a, b, c) { + return n.dir(a, 'parentNode', c); + }, + next: function (a) { + return D(a, 'nextSibling'); + }, + prev: function (a) { + return D(a, 'previousSibling'); + }, + nextAll: function (a) { + return n.dir(a, 'nextSibling'); + }, + prevAll: function (a) { + return n.dir(a, 'previousSibling'); + }, + nextUntil: function (a, b, c) { + return n.dir(a, 'nextSibling', c); + }, + prevUntil: function (a, b, c) { + return n.dir(a, 'previousSibling', c); + }, + siblings: function (a) { + return n.sibling((a.parentNode || {}).firstChild, a); + }, + children: function (a) { + return n.sibling(a.firstChild); + }, + contents: function (a) { + return a.contentDocument || n.merge([], a.childNodes); + }, + }, + function (a, b) { + n.fn[a] = function (c, d) { + var e = n.map(this, b, c); + return ( + 'Until' !== a.slice(-5) && (d = c), + d && 'string' == typeof d && (e = n.filter(d, e)), + this.length > 1 && (C[a] || n.unique(e), B.test(a) && e.reverse()), + this.pushStack(e) + ); + }; + }, + ); + var E = /\S+/g, + F = {}; + function G(a) { + var b = (F[a] = {}); + return ( + n.each(a.match(E) || [], function (a, c) { + b[c] = !0; + }), + b + ); + } + (n.Callbacks = function (a) { + a = 'string' == typeof a ? F[a] || G(a) : n.extend({}, a); + var b, + c, + d, + e, + f, + g, + h = [], + i = !a.once && [], + j = function (l) { + for (b = a.memory && l, c = !0, g = e || 0, e = 0, f = h.length, d = !0; h && f > g; g++) + if (h[g].apply(l[0], l[1]) === !1 && a.stopOnFalse) { + b = !1; + break; + } + (d = !1), h && (i ? i.length && j(i.shift()) : b ? (h = []) : k.disable()); + }, + k = { + add: function () { + if (h) { + var c = h.length; + !(function g(b) { + n.each(b, function (b, c) { + var d = n.type(c); + 'function' === d ? (a.unique && k.has(c)) || h.push(c) : c && c.length && 'string' !== d && g(c); + }); + })(arguments), + d ? (f = h.length) : b && ((e = c), j(b)); + } + return this; + }, + remove: function () { + return ( + h && + n.each(arguments, function (a, b) { + var c; + while ((c = n.inArray(b, h, c)) > -1) h.splice(c, 1), d && (f >= c && f--, g >= c && g--); + }), + this + ); + }, + has: function (a) { + return a ? n.inArray(a, h) > -1 : !(!h || !h.length); + }, + empty: function () { + return (h = []), (f = 0), this; + }, + disable: function () { + return (h = i = b = void 0), this; + }, + disabled: function () { + return !h; + }, + lock: function () { + return (i = void 0), b || k.disable(), this; + }, + locked: function () { + return !i; + }, + fireWith: function (a, b) { + return !h || (c && !i) || ((b = b || []), (b = [a, b.slice ? b.slice() : b]), d ? i.push(b) : j(b)), this; + }, + fire: function () { + return k.fireWith(this, arguments), this; + }, + fired: function () { + return !!c; + }, + }; + return k; + }), + n.extend({ + Deferred: function (a) { + var b = [ + ['resolve', 'done', n.Callbacks('once memory'), 'resolved'], + ['reject', 'fail', n.Callbacks('once memory'), 'rejected'], + ['notify', 'progress', n.Callbacks('memory')], + ], + c = 'pending', + d = { + state: function () { + return c; + }, + always: function () { + return e.done(arguments).fail(arguments), this; + }, + then: function () { + var a = arguments; + return n + .Deferred(function (c) { + n.each(b, function (b, f) { + var g = n.isFunction(a[b]) && a[b]; + e[f[1]](function () { + var a = g && g.apply(this, arguments); + a && n.isFunction(a.promise) + ? a.promise().done(c.resolve).fail(c.reject).progress(c.notify) + : c[f[0] + 'With'](this === d ? c.promise() : this, g ? [a] : arguments); + }); + }), + (a = null); + }) + .promise(); + }, + promise: function (a) { + return null != a ? n.extend(a, d) : d; + }, + }, + e = {}; + return ( + (d.pipe = d.then), + n.each(b, function (a, f) { + var g = f[2], + h = f[3]; + (d[f[1]] = g.add), + h && + g.add( + function () { + c = h; + }, + b[1 ^ a][2].disable, + b[2][2].lock, + ), + (e[f[0]] = function () { + return e[f[0] + 'With'](this === e ? d : this, arguments), this; + }), + (e[f[0] + 'With'] = g.fireWith); + }), + d.promise(e), + a && a.call(e, e), + e + ); + }, + when: function (a) { + var b = 0, + c = d.call(arguments), + e = c.length, + f = 1 !== e || (a && n.isFunction(a.promise)) ? e : 0, + g = 1 === f ? a : n.Deferred(), + h = function (a, b, c) { + return function (e) { + (b[a] = this), + (c[a] = arguments.length > 1 ? d.call(arguments) : e), + c === i ? g.notifyWith(b, c) : --f || g.resolveWith(b, c); + }; + }, + i, + j, + k; + if (e > 1) + for (i = new Array(e), j = new Array(e), k = new Array(e); e > b; b++) + c[b] && n.isFunction(c[b].promise) + ? c[b].promise().done(h(b, k, c)).fail(g.reject).progress(h(b, j, i)) + : --f; + return f || g.resolveWith(k, c), g.promise(); + }, + }); + var H; + (n.fn.ready = function (a) { + return n.ready.promise().done(a), this; + }), + n.extend({ + isReady: !1, + readyWait: 1, + holdReady: function (a) { + a ? n.readyWait++ : n.ready(!0); + }, + ready: function (a) { + (a === !0 ? --n.readyWait : n.isReady) || + ((n.isReady = !0), + (a !== !0 && --n.readyWait > 0) || + (H.resolveWith(l, [n]), n.fn.triggerHandler && (n(l).triggerHandler('ready'), n(l).off('ready')))); + }, + }); + function I() { + l.removeEventListener('DOMContentLoaded', I, !1), a.removeEventListener('load', I, !1), n.ready(); + } + (n.ready.promise = function (b) { + return ( + H || + ((H = n.Deferred()), + 'complete' === l.readyState + ? setTimeout(n.ready) + : (l.addEventListener('DOMContentLoaded', I, !1), a.addEventListener('load', I, !1))), + H.promise(b) + ); + }), + n.ready.promise(); + var J = (n.access = function (a, b, c, d, e, f, g) { + var h = 0, + i = a.length, + j = null == c; + if ('object' === n.type(c)) { + e = !0; + for (h in c) n.access(a, b, h, c[h], !0, f, g); + } else if ( + void 0 !== d && + ((e = !0), + n.isFunction(d) || (g = !0), + j && + (g + ? (b.call(a, d), (b = null)) + : ((j = b), + (b = function (a, b, c) { + return j.call(n(a), c); + }))), + b) + ) + for (; i > h; h++) b(a[h], c, g ? d : d.call(a[h], h, b(a[h], c))); + return e ? a : j ? b.call(a) : i ? b(a[0], c) : f; + }); + n.acceptData = function (a) { + return 1 === a.nodeType || 9 === a.nodeType || !+a.nodeType; + }; + function K() { + Object.defineProperty((this.cache = {}), 0, { + get: function () { + return {}; + }, + }), + (this.expando = n.expando + K.uid++); + } + (K.uid = 1), + (K.accepts = n.acceptData), + (K.prototype = { + key: function (a) { + if (!K.accepts(a)) return 0; + var b = {}, + c = a[this.expando]; + if (!c) { + c = K.uid++; + try { + (b[this.expando] = { value: c }), Object.defineProperties(a, b); + } catch (d) { + (b[this.expando] = c), n.extend(a, b); + } + } + return this.cache[c] || (this.cache[c] = {}), c; + }, + set: function (a, b, c) { + var d, + e = this.key(a), + f = this.cache[e]; + if ('string' == typeof b) f[b] = c; + else if (n.isEmptyObject(f)) n.extend(this.cache[e], b); + else for (d in b) f[d] = b[d]; + return f; + }, + get: function (a, b) { + var c = this.cache[this.key(a)]; + return void 0 === b ? c : c[b]; + }, + access: function (a, b, c) { + var d; + return void 0 === b || (b && 'string' == typeof b && void 0 === c) + ? ((d = this.get(a, b)), void 0 !== d ? d : this.get(a, n.camelCase(b))) + : (this.set(a, b, c), void 0 !== c ? c : b); + }, + remove: function (a, b) { + var c, + d, + e, + f = this.key(a), + g = this.cache[f]; + if (void 0 === b) this.cache[f] = {}; + else { + n.isArray(b) + ? (d = b.concat(b.map(n.camelCase))) + : ((e = n.camelCase(b)), b in g ? (d = [b, e]) : ((d = e), (d = d in g ? [d] : d.match(E) || []))), + (c = d.length); + while (c--) delete g[d[c]]; + } + }, + hasData: function (a) { + return !n.isEmptyObject(this.cache[a[this.expando]] || {}); + }, + discard: function (a) { + a[this.expando] && delete this.cache[a[this.expando]]; + }, + }); + var L = new K(), + M = new K(), + N = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + O = /([A-Z])/g; + function P(a, b, c) { + var d; + if (void 0 === c && 1 === a.nodeType) + if (((d = 'data-' + b.replace(O, '-$1').toLowerCase()), (c = a.getAttribute(d)), 'string' == typeof c)) { + try { + c = + 'true' === c + ? !0 + : 'false' === c + ? !1 + : 'null' === c + ? null + : +c + '' === c + ? +c + : N.test(c) + ? n.parseJSON(c) + : c; + } catch (e) {} + M.set(a, b, c); + } else c = void 0; + return c; + } + n.extend({ + hasData: function (a) { + return M.hasData(a) || L.hasData(a); + }, + data: function (a, b, c) { + return M.access(a, b, c); + }, + removeData: function (a, b) { + M.remove(a, b); + }, + _data: function (a, b, c) { + return L.access(a, b, c); + }, + _removeData: function (a, b) { + L.remove(a, b); + }, + }), + n.fn.extend({ + data: function (a, b) { + var c, + d, + e, + f = this[0], + g = f && f.attributes; + if (void 0 === a) { + if (this.length && ((e = M.get(f)), 1 === f.nodeType && !L.get(f, 'hasDataAttrs'))) { + c = g.length; + while (c--) + g[c] && ((d = g[c].name), 0 === d.indexOf('data-') && ((d = n.camelCase(d.slice(5))), P(f, d, e[d]))); + L.set(f, 'hasDataAttrs', !0); + } + return e; + } + return 'object' == typeof a + ? this.each(function () { + M.set(this, a); + }) + : J( + this, + function (b) { + var c, + d = n.camelCase(a); + if (f && void 0 === b) { + if (((c = M.get(f, a)), void 0 !== c)) return c; + if (((c = M.get(f, d)), void 0 !== c)) return c; + if (((c = P(f, d, void 0)), void 0 !== c)) return c; + } else + this.each(function () { + var c = M.get(this, d); + M.set(this, d, b), -1 !== a.indexOf('-') && void 0 !== c && M.set(this, a, b); + }); + }, + null, + b, + arguments.length > 1, + null, + !0, + ); + }, + removeData: function (a) { + return this.each(function () { + M.remove(this, a); + }); + }, + }), + n.extend({ + queue: function (a, b, c) { + var d; + return a + ? ((b = (b || 'fx') + 'queue'), + (d = L.get(a, b)), + c && (!d || n.isArray(c) ? (d = L.access(a, b, n.makeArray(c))) : d.push(c)), + d || []) + : void 0; + }, + dequeue: function (a, b) { + b = b || 'fx'; + var c = n.queue(a, b), + d = c.length, + e = c.shift(), + f = n._queueHooks(a, b), + g = function () { + n.dequeue(a, b); + }; + 'inprogress' === e && ((e = c.shift()), d--), + e && ('fx' === b && c.unshift('inprogress'), delete f.stop, e.call(a, g, f)), + !d && f && f.empty.fire(); + }, + _queueHooks: function (a, b) { + var c = b + 'queueHooks'; + return ( + L.get(a, c) || + L.access(a, c, { + empty: n.Callbacks('once memory').add(function () { + L.remove(a, [b + 'queue', c]); + }), + }) + ); + }, + }), + n.fn.extend({ + queue: function (a, b) { + var c = 2; + return ( + 'string' != typeof a && ((b = a), (a = 'fx'), c--), + arguments.length < c + ? n.queue(this[0], a) + : void 0 === b + ? this + : this.each(function () { + var c = n.queue(this, a, b); + n._queueHooks(this, a), 'fx' === a && 'inprogress' !== c[0] && n.dequeue(this, a); + }) + ); + }, + dequeue: function (a) { + return this.each(function () { + n.dequeue(this, a); + }); + }, + clearQueue: function (a) { + return this.queue(a || 'fx', []); + }, + promise: function (a, b) { + var c, + d = 1, + e = n.Deferred(), + f = this, + g = this.length, + h = function () { + --d || e.resolveWith(f, [f]); + }; + 'string' != typeof a && ((b = a), (a = void 0)), (a = a || 'fx'); + while (g--) (c = L.get(f[g], a + 'queueHooks')), c && c.empty && (d++, c.empty.add(h)); + return h(), e.promise(b); + }, + }); + var Q = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source, + R = ['Top', 'Right', 'Bottom', 'Left'], + S = function (a, b) { + return (a = b || a), 'none' === n.css(a, 'display') || !n.contains(a.ownerDocument, a); + }, + T = /^(?:checkbox|radio)$/i; + !(function () { + var a = l.createDocumentFragment(), + b = a.appendChild(l.createElement('div')), + c = l.createElement('input'); + c.setAttribute('type', 'radio'), + c.setAttribute('checked', 'checked'), + c.setAttribute('name', 't'), + b.appendChild(c), + (k.checkClone = b.cloneNode(!0).cloneNode(!0).lastChild.checked), + (b.innerHTML = '<textarea>x</textarea>'), + (k.noCloneChecked = !!b.cloneNode(!0).lastChild.defaultValue); + })(); + var U = 'undefined'; + k.focusinBubbles = 'onfocusin' in a; + var V = /^key/, + W = /^(?:mouse|pointer|contextmenu)|click/, + X = /^(?:focusinfocus|focusoutblur)$/, + Y = /^([^.]*)(?:\.(.+)|)$/; + function Z() { + return !0; + } + function $() { + return !1; + } + function _() { + try { + return l.activeElement; + } catch (a) {} + } + (n.event = { + global: {}, + add: function (a, b, c, d, e) { + var f, + g, + h, + i, + j, + k, + l, + m, + o, + p, + q, + r = L.get(a); + if (r) { + c.handler && ((f = c), (c = f.handler), (e = f.selector)), + c.guid || (c.guid = n.guid++), + (i = r.events) || (i = r.events = {}), + (g = r.handle) || + (g = r.handle = + function (b) { + return typeof n !== U && n.event.triggered !== b.type ? n.event.dispatch.apply(a, arguments) : void 0; + }), + (b = (b || '').match(E) || ['']), + (j = b.length); + while (j--) + (h = Y.exec(b[j]) || []), + (o = q = h[1]), + (p = (h[2] || '').split('.').sort()), + o && + ((l = n.event.special[o] || {}), + (o = (e ? l.delegateType : l.bindType) || o), + (l = n.event.special[o] || {}), + (k = n.extend( + { + type: o, + origType: q, + data: d, + handler: c, + guid: c.guid, + selector: e, + needsContext: e && n.expr.match.needsContext.test(e), + namespace: p.join('.'), + }, + f, + )), + (m = i[o]) || + ((m = i[o] = []), + (m.delegateCount = 0), + (l.setup && l.setup.call(a, d, p, g) !== !1) || (a.addEventListener && a.addEventListener(o, g, !1))), + l.add && (l.add.call(a, k), k.handler.guid || (k.handler.guid = c.guid)), + e ? m.splice(m.delegateCount++, 0, k) : m.push(k), + (n.event.global[o] = !0)); + } + }, + remove: function (a, b, c, d, e) { + var f, + g, + h, + i, + j, + k, + l, + m, + o, + p, + q, + r = L.hasData(a) && L.get(a); + if (r && (i = r.events)) { + (b = (b || '').match(E) || ['']), (j = b.length); + while (j--) + if (((h = Y.exec(b[j]) || []), (o = q = h[1]), (p = (h[2] || '').split('.').sort()), o)) { + (l = n.event.special[o] || {}), + (o = (d ? l.delegateType : l.bindType) || o), + (m = i[o] || []), + (h = h[2] && new RegExp('(^|\\.)' + p.join('\\.(?:.*\\.|)') + '(\\.|$)')), + (g = f = m.length); + while (f--) + (k = m[f]), + (!e && q !== k.origType) || + (c && c.guid !== k.guid) || + (h && !h.test(k.namespace)) || + (d && d !== k.selector && ('**' !== d || !k.selector)) || + (m.splice(f, 1), k.selector && m.delegateCount--, l.remove && l.remove.call(a, k)); + g && + !m.length && + ((l.teardown && l.teardown.call(a, p, r.handle) !== !1) || n.removeEvent(a, o, r.handle), delete i[o]); + } else for (o in i) n.event.remove(a, o + b[j], c, d, !0); + n.isEmptyObject(i) && (delete r.handle, L.remove(a, 'events')); + } + }, + trigger: function (b, c, d, e) { + var f, + g, + h, + i, + k, + m, + o, + p = [d || l], + q = j.call(b, 'type') ? b.type : b, + r = j.call(b, 'namespace') ? b.namespace.split('.') : []; + if ( + ((g = h = d = d || l), + 3 !== d.nodeType && + 8 !== d.nodeType && + !X.test(q + n.event.triggered) && + (q.indexOf('.') >= 0 && ((r = q.split('.')), (q = r.shift()), r.sort()), + (k = q.indexOf(':') < 0 && 'on' + q), + (b = b[n.expando] ? b : new n.Event(q, 'object' == typeof b && b)), + (b.isTrigger = e ? 2 : 3), + (b.namespace = r.join('.')), + (b.namespace_re = b.namespace ? new RegExp('(^|\\.)' + r.join('\\.(?:.*\\.|)') + '(\\.|$)') : null), + (b.result = void 0), + b.target || (b.target = d), + (c = null == c ? [b] : n.makeArray(c, [b])), + (o = n.event.special[q] || {}), + e || !o.trigger || o.trigger.apply(d, c) !== !1)) + ) { + if (!e && !o.noBubble && !n.isWindow(d)) { + for (i = o.delegateType || q, X.test(i + q) || (g = g.parentNode); g; g = g.parentNode) p.push(g), (h = g); + h === (d.ownerDocument || l) && p.push(h.defaultView || h.parentWindow || a); + } + f = 0; + while ((g = p[f++]) && !b.isPropagationStopped()) + (b.type = f > 1 ? i : o.bindType || q), + (m = (L.get(g, 'events') || {})[b.type] && L.get(g, 'handle')), + m && m.apply(g, c), + (m = k && g[k]), + m && m.apply && n.acceptData(g) && ((b.result = m.apply(g, c)), b.result === !1 && b.preventDefault()); + return ( + (b.type = q), + e || + b.isDefaultPrevented() || + (o._default && o._default.apply(p.pop(), c) !== !1) || + !n.acceptData(d) || + (k && + n.isFunction(d[q]) && + !n.isWindow(d) && + ((h = d[k]), + h && (d[k] = null), + (n.event.triggered = q), + d[q](), + (n.event.triggered = void 0), + h && (d[k] = h))), + b.result + ); + } + }, + dispatch: function (a) { + a = n.event.fix(a); + var b, + c, + e, + f, + g, + h = [], + i = d.call(arguments), + j = (L.get(this, 'events') || {})[a.type] || [], + k = n.event.special[a.type] || {}; + if (((i[0] = a), (a.delegateTarget = this), !k.preDispatch || k.preDispatch.call(this, a) !== !1)) { + (h = n.event.handlers.call(this, a, j)), (b = 0); + while ((f = h[b++]) && !a.isPropagationStopped()) { + (a.currentTarget = f.elem), (c = 0); + while ((g = f.handlers[c++]) && !a.isImmediatePropagationStopped()) + (!a.namespace_re || a.namespace_re.test(g.namespace)) && + ((a.handleObj = g), + (a.data = g.data), + (e = ((n.event.special[g.origType] || {}).handle || g.handler).apply(f.elem, i)), + void 0 !== e && (a.result = e) === !1 && (a.preventDefault(), a.stopPropagation())); + } + return k.postDispatch && k.postDispatch.call(this, a), a.result; + } + }, + handlers: function (a, b) { + var c, + d, + e, + f, + g = [], + h = b.delegateCount, + i = a.target; + if (h && i.nodeType && (!a.button || 'click' !== a.type)) + for (; i !== this; i = i.parentNode || this) + if (i.disabled !== !0 || 'click' !== a.type) { + for (d = [], c = 0; h > c; c++) + (f = b[c]), + (e = f.selector + ' '), + void 0 === d[e] && + (d[e] = f.needsContext ? n(e, this).index(i) >= 0 : n.find(e, this, null, [i]).length), + d[e] && d.push(f); + d.length && g.push({ elem: i, handlers: d }); + } + return h < b.length && g.push({ elem: this, handlers: b.slice(h) }), g; + }, + props: + 'altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which'.split( + ' ', + ), + fixHooks: {}, + keyHooks: { + props: 'char charCode key keyCode'.split(' '), + filter: function (a, b) { + return null == a.which && (a.which = null != b.charCode ? b.charCode : b.keyCode), a; + }, + }, + mouseHooks: { + props: 'button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement'.split(' '), + filter: function (a, b) { + var c, + d, + e, + f = b.button; + return ( + null == a.pageX && + null != b.clientX && + ((c = a.target.ownerDocument || l), + (d = c.documentElement), + (e = c.body), + (a.pageX = + b.clientX + + ((d && d.scrollLeft) || (e && e.scrollLeft) || 0) - + ((d && d.clientLeft) || (e && e.clientLeft) || 0)), + (a.pageY = + b.clientY + + ((d && d.scrollTop) || (e && e.scrollTop) || 0) - + ((d && d.clientTop) || (e && e.clientTop) || 0))), + a.which || void 0 === f || (a.which = 1 & f ? 1 : 2 & f ? 3 : 4 & f ? 2 : 0), + a + ); + }, + }, + fix: function (a) { + if (a[n.expando]) return a; + var b, + c, + d, + e = a.type, + f = a, + g = this.fixHooks[e]; + g || (this.fixHooks[e] = g = W.test(e) ? this.mouseHooks : V.test(e) ? this.keyHooks : {}), + (d = g.props ? this.props.concat(g.props) : this.props), + (a = new n.Event(f)), + (b = d.length); + while (b--) (c = d[b]), (a[c] = f[c]); + return ( + a.target || (a.target = l), + 3 === a.target.nodeType && (a.target = a.target.parentNode), + g.filter ? g.filter(a, f) : a + ); + }, + special: { + load: { noBubble: !0 }, + focus: { + trigger: function () { + return this !== _() && this.focus ? (this.focus(), !1) : void 0; + }, + delegateType: 'focusin', + }, + blur: { + trigger: function () { + return this === _() && this.blur ? (this.blur(), !1) : void 0; + }, + delegateType: 'focusout', + }, + click: { + trigger: function () { + return 'checkbox' === this.type && this.click && n.nodeName(this, 'input') ? (this.click(), !1) : void 0; + }, + _default: function (a) { + return n.nodeName(a.target, 'a'); + }, + }, + beforeunload: { + postDispatch: function (a) { + void 0 !== a.result && a.originalEvent && (a.originalEvent.returnValue = a.result); + }, + }, + }, + simulate: function (a, b, c, d) { + var e = n.extend(new n.Event(), c, { type: a, isSimulated: !0, originalEvent: {} }); + d ? n.event.trigger(e, null, b) : n.event.dispatch.call(b, e), e.isDefaultPrevented() && c.preventDefault(); + }, + }), + (n.removeEvent = function (a, b, c) { + a.removeEventListener && a.removeEventListener(b, c, !1); + }), + (n.Event = function (a, b) { + return this instanceof n.Event + ? (a && a.type + ? ((this.originalEvent = a), + (this.type = a.type), + (this.isDefaultPrevented = + a.defaultPrevented || (void 0 === a.defaultPrevented && a.returnValue === !1) ? Z : $)) + : (this.type = a), + b && n.extend(this, b), + (this.timeStamp = (a && a.timeStamp) || n.now()), + void (this[n.expando] = !0)) + : new n.Event(a, b); + }), + (n.Event.prototype = { + isDefaultPrevented: $, + isPropagationStopped: $, + isImmediatePropagationStopped: $, + preventDefault: function () { + var a = this.originalEvent; + (this.isDefaultPrevented = Z), a && a.preventDefault && a.preventDefault(); + }, + stopPropagation: function () { + var a = this.originalEvent; + (this.isPropagationStopped = Z), a && a.stopPropagation && a.stopPropagation(); + }, + stopImmediatePropagation: function () { + var a = this.originalEvent; + (this.isImmediatePropagationStopped = Z), + a && a.stopImmediatePropagation && a.stopImmediatePropagation(), + this.stopPropagation(); + }, + }), + n.each( + { mouseenter: 'mouseover', mouseleave: 'mouseout', pointerenter: 'pointerover', pointerleave: 'pointerout' }, + function (a, b) { + n.event.special[a] = { + delegateType: b, + bindType: b, + handle: function (a) { + var c, + d = this, + e = a.relatedTarget, + f = a.handleObj; + return ( + (!e || (e !== d && !n.contains(d, e))) && + ((a.type = f.origType), (c = f.handler.apply(this, arguments)), (a.type = b)), + c + ); + }, + }; + }, + ), + k.focusinBubbles || + n.each({ focus: 'focusin', blur: 'focusout' }, function (a, b) { + var c = function (a) { + n.event.simulate(b, a.target, n.event.fix(a), !0); + }; + n.event.special[b] = { + setup: function () { + var d = this.ownerDocument || this, + e = L.access(d, b); + e || d.addEventListener(a, c, !0), L.access(d, b, (e || 0) + 1); + }, + teardown: function () { + var d = this.ownerDocument || this, + e = L.access(d, b) - 1; + e ? L.access(d, b, e) : (d.removeEventListener(a, c, !0), L.remove(d, b)); + }, + }; + }), + n.fn.extend({ + on: function (a, b, c, d, e) { + var f, g; + if ('object' == typeof a) { + 'string' != typeof b && ((c = c || b), (b = void 0)); + for (g in a) this.on(g, b, c, a[g], e); + return this; + } + if ( + (null == c && null == d + ? ((d = b), (c = b = void 0)) + : null == d && ('string' == typeof b ? ((d = c), (c = void 0)) : ((d = c), (c = b), (b = void 0))), + d === !1) + ) + d = $; + else if (!d) return this; + return ( + 1 === e && + ((f = d), + (d = function (a) { + return n().off(a), f.apply(this, arguments); + }), + (d.guid = f.guid || (f.guid = n.guid++))), + this.each(function () { + n.event.add(this, a, d, c, b); + }) + ); + }, + one: function (a, b, c, d) { + return this.on(a, b, c, d, 1); + }, + off: function (a, b, c) { + var d, e; + if (a && a.preventDefault && a.handleObj) + return ( + (d = a.handleObj), + n(a.delegateTarget).off(d.namespace ? d.origType + '.' + d.namespace : d.origType, d.selector, d.handler), + this + ); + if ('object' == typeof a) { + for (e in a) this.off(e, b, a[e]); + return this; + } + return ( + (b === !1 || 'function' == typeof b) && ((c = b), (b = void 0)), + c === !1 && (c = $), + this.each(function () { + n.event.remove(this, a, c, b); + }) + ); + }, + trigger: function (a, b) { + return this.each(function () { + n.event.trigger(a, b, this); + }); + }, + triggerHandler: function (a, b) { + var c = this[0]; + return c ? n.event.trigger(a, b, c, !0) : void 0; + }, + }); + var ab = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, + bb = /<([\w:]+)/, + cb = /<|&#?\w+;/, + db = /<(?:script|style|link)/i, + eb = /checked\s*(?:[^=]|=\s*.checked.)/i, + fb = /^$|\/(?:java|ecma)script/i, + gb = /^true\/(.*)/, + hb = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g, + ib = { + option: [1, "<select multiple='multiple'>", '</select>'], + thead: [1, '<table>', '</table>'], + col: [2, '<table><colgroup>', '</colgroup></table>'], + tr: [2, '<table><tbody>', '</tbody></table>'], + td: [3, '<table><tbody><tr>', '</tr></tbody></table>'], + _default: [0, '', ''], + }; + (ib.optgroup = ib.option), (ib.tbody = ib.tfoot = ib.colgroup = ib.caption = ib.thead), (ib.th = ib.td); + function jb(a, b) { + return n.nodeName(a, 'table') && n.nodeName(11 !== b.nodeType ? b : b.firstChild, 'tr') + ? a.getElementsByTagName('tbody')[0] || a.appendChild(a.ownerDocument.createElement('tbody')) + : a; + } + function kb(a) { + return (a.type = (null !== a.getAttribute('type')) + '/' + a.type), a; + } + function lb(a) { + var b = gb.exec(a.type); + return b ? (a.type = b[1]) : a.removeAttribute('type'), a; + } + function mb(a, b) { + for (var c = 0, d = a.length; d > c; c++) L.set(a[c], 'globalEval', !b || L.get(b[c], 'globalEval')); + } + function nb(a, b) { + var c, d, e, f, g, h, i, j; + if (1 === b.nodeType) { + if (L.hasData(a) && ((f = L.access(a)), (g = L.set(b, f)), (j = f.events))) { + delete g.handle, (g.events = {}); + for (e in j) for (c = 0, d = j[e].length; d > c; c++) n.event.add(b, e, j[e][c]); + } + M.hasData(a) && ((h = M.access(a)), (i = n.extend({}, h)), M.set(b, i)); + } + } + function ob(a, b) { + var c = a.getElementsByTagName + ? a.getElementsByTagName(b || '*') + : a.querySelectorAll + ? a.querySelectorAll(b || '*') + : []; + return void 0 === b || (b && n.nodeName(a, b)) ? n.merge([a], c) : c; + } + function pb(a, b) { + var c = b.nodeName.toLowerCase(); + 'input' === c && T.test(a.type) + ? (b.checked = a.checked) + : ('input' === c || 'textarea' === c) && (b.defaultValue = a.defaultValue); + } + n.extend({ + clone: function (a, b, c) { + var d, + e, + f, + g, + h = a.cloneNode(!0), + i = n.contains(a.ownerDocument, a); + if (!(k.noCloneChecked || (1 !== a.nodeType && 11 !== a.nodeType) || n.isXMLDoc(a))) + for (g = ob(h), f = ob(a), d = 0, e = f.length; e > d; d++) pb(f[d], g[d]); + if (b) + if (c) for (f = f || ob(a), g = g || ob(h), d = 0, e = f.length; e > d; d++) nb(f[d], g[d]); + else nb(a, h); + return (g = ob(h, 'script')), g.length > 0 && mb(g, !i && ob(a, 'script')), h; + }, + buildFragment: function (a, b, c, d) { + for (var e, f, g, h, i, j, k = b.createDocumentFragment(), l = [], m = 0, o = a.length; o > m; m++) + if (((e = a[m]), e || 0 === e)) + if ('object' === n.type(e)) n.merge(l, e.nodeType ? [e] : e); + else if (cb.test(e)) { + (f = f || k.appendChild(b.createElement('div'))), + (g = (bb.exec(e) || ['', ''])[1].toLowerCase()), + (h = ib[g] || ib._default), + (f.innerHTML = h[1] + e.replace(ab, '<$1></$2>') + h[2]), + (j = h[0]); + while (j--) f = f.lastChild; + n.merge(l, f.childNodes), (f = k.firstChild), (f.textContent = ''); + } else l.push(b.createTextNode(e)); + (k.textContent = ''), (m = 0); + while ((e = l[m++])) + if ( + (!d || -1 === n.inArray(e, d)) && + ((i = n.contains(e.ownerDocument, e)), (f = ob(k.appendChild(e), 'script')), i && mb(f), c) + ) { + j = 0; + while ((e = f[j++])) fb.test(e.type || '') && c.push(e); + } + return k; + }, + cleanData: function (a) { + for (var b, c, d, e, f = n.event.special, g = 0; void 0 !== (c = a[g]); g++) { + if (n.acceptData(c) && ((e = c[L.expando]), e && (b = L.cache[e]))) { + if (b.events) for (d in b.events) f[d] ? n.event.remove(c, d) : n.removeEvent(c, d, b.handle); + L.cache[e] && delete L.cache[e]; + } + delete M.cache[c[M.expando]]; + } + }, + }), + n.fn.extend({ + text: function (a) { + return J( + this, + function (a) { + return void 0 === a + ? n.text(this) + : this.empty().each(function () { + (1 === this.nodeType || 11 === this.nodeType || 9 === this.nodeType) && (this.textContent = a); + }); + }, + null, + a, + arguments.length, + ); + }, + append: function () { + return this.domManip(arguments, function (a) { + if (1 === this.nodeType || 11 === this.nodeType || 9 === this.nodeType) { + var b = jb(this, a); + b.appendChild(a); + } + }); + }, + prepend: function () { + return this.domManip(arguments, function (a) { + if (1 === this.nodeType || 11 === this.nodeType || 9 === this.nodeType) { + var b = jb(this, a); + b.insertBefore(a, b.firstChild); + } + }); + }, + before: function () { + return this.domManip(arguments, function (a) { + this.parentNode && this.parentNode.insertBefore(a, this); + }); + }, + after: function () { + return this.domManip(arguments, function (a) { + this.parentNode && this.parentNode.insertBefore(a, this.nextSibling); + }); + }, + remove: function (a, b) { + for (var c, d = a ? n.filter(a, this) : this, e = 0; null != (c = d[e]); e++) + b || 1 !== c.nodeType || n.cleanData(ob(c)), + c.parentNode && (b && n.contains(c.ownerDocument, c) && mb(ob(c, 'script')), c.parentNode.removeChild(c)); + return this; + }, + empty: function () { + for (var a, b = 0; null != (a = this[b]); b++) + 1 === a.nodeType && (n.cleanData(ob(a, !1)), (a.textContent = '')); + return this; + }, + clone: function (a, b) { + return ( + (a = null == a ? !1 : a), + (b = null == b ? a : b), + this.map(function () { + return n.clone(this, a, b); + }) + ); + }, + html: function (a) { + return J( + this, + function (a) { + var b = this[0] || {}, + c = 0, + d = this.length; + if (void 0 === a && 1 === b.nodeType) return b.innerHTML; + if ('string' == typeof a && !db.test(a) && !ib[(bb.exec(a) || ['', ''])[1].toLowerCase()]) { + a = a.replace(ab, '<$1></$2>'); + try { + for (; d > c; c++) (b = this[c] || {}), 1 === b.nodeType && (n.cleanData(ob(b, !1)), (b.innerHTML = a)); + b = 0; + } catch (e) {} + } + b && this.empty().append(a); + }, + null, + a, + arguments.length, + ); + }, + replaceWith: function () { + var a = arguments[0]; + return ( + this.domManip(arguments, function (b) { + (a = this.parentNode), n.cleanData(ob(this)), a && a.replaceChild(b, this); + }), + a && (a.length || a.nodeType) ? this : this.remove() + ); + }, + detach: function (a) { + return this.remove(a, !0); + }, + domManip: function (a, b) { + a = e.apply([], a); + var c, + d, + f, + g, + h, + i, + j = 0, + l = this.length, + m = this, + o = l - 1, + p = a[0], + q = n.isFunction(p); + if (q || (l > 1 && 'string' == typeof p && !k.checkClone && eb.test(p))) + return this.each(function (c) { + var d = m.eq(c); + q && (a[0] = p.call(this, c, d.html())), d.domManip(a, b); + }); + if ( + l && + ((c = n.buildFragment(a, this[0].ownerDocument, !1, this)), + (d = c.firstChild), + 1 === c.childNodes.length && (c = d), + d) + ) { + for (f = n.map(ob(c, 'script'), kb), g = f.length; l > j; j++) + (h = c), j !== o && ((h = n.clone(h, !0, !0)), g && n.merge(f, ob(h, 'script'))), b.call(this[j], h, j); + if (g) + for (i = f[f.length - 1].ownerDocument, n.map(f, lb), j = 0; g > j; j++) + (h = f[j]), + fb.test(h.type || '') && + !L.access(h, 'globalEval') && + n.contains(i, h) && + (h.src ? n._evalUrl && n._evalUrl(h.src) : n.globalEval(h.textContent.replace(hb, ''))); + } + return this; + }, + }), + n.each( + { + appendTo: 'append', + prependTo: 'prepend', + insertBefore: 'before', + insertAfter: 'after', + replaceAll: 'replaceWith', + }, + function (a, b) { + n.fn[a] = function (a) { + for (var c, d = [], e = n(a), g = e.length - 1, h = 0; g >= h; h++) + (c = h === g ? this : this.clone(!0)), n(e[h])[b](c), f.apply(d, c.get()); + return this.pushStack(d); + }; + }, + ); + var qb, + rb = {}; + function sb(b, c) { + var d, + e = n(c.createElement(b)).appendTo(c.body), + f = a.getDefaultComputedStyle && (d = a.getDefaultComputedStyle(e[0])) ? d.display : n.css(e[0], 'display'); + return e.detach(), f; + } + function tb(a) { + var b = l, + c = rb[a]; + return ( + c || + ((c = sb(a, b)), + ('none' !== c && c) || + ((qb = (qb || n("<iframe frameborder='0' width='0' height='0'/>")).appendTo(b.documentElement)), + (b = qb[0].contentDocument), + b.write(), + b.close(), + (c = sb(a, b)), + qb.detach()), + (rb[a] = c)), + c + ); + } + var ub = /^margin/, + vb = new RegExp('^(' + Q + ')(?!px)[a-z%]+$', 'i'), + wb = function (b) { + return b.ownerDocument.defaultView.opener + ? b.ownerDocument.defaultView.getComputedStyle(b, null) + : a.getComputedStyle(b, null); + }; + function xb(a, b, c) { + var d, + e, + f, + g, + h = a.style; + return ( + (c = c || wb(a)), + c && (g = c.getPropertyValue(b) || c[b]), + c && + ('' !== g || n.contains(a.ownerDocument, a) || (g = n.style(a, b)), + vb.test(g) && + ub.test(b) && + ((d = h.width), + (e = h.minWidth), + (f = h.maxWidth), + (h.minWidth = h.maxWidth = h.width = g), + (g = c.width), + (h.width = d), + (h.minWidth = e), + (h.maxWidth = f))), + void 0 !== g ? g + '' : g + ); + } + function yb(a, b) { + return { + get: function () { + return a() ? void delete this.get : (this.get = b).apply(this, arguments); + }, + }; + } + !(function () { + var b, + c, + d = l.documentElement, + e = l.createElement('div'), + f = l.createElement('div'); + if (f.style) { + (f.style.backgroundClip = 'content-box'), + (f.cloneNode(!0).style.backgroundClip = ''), + (k.clearCloneStyle = 'content-box' === f.style.backgroundClip), + (e.style.cssText = 'border:0;width:0;height:0;top:0;left:-9999px;margin-top:1px;position:absolute'), + e.appendChild(f); + function g() { + (f.style.cssText = + '-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;display:block;margin-top:1%;top:1%;border:1px;padding:1px;width:4px;position:absolute'), + (f.innerHTML = ''), + d.appendChild(e); + var g = a.getComputedStyle(f, null); + (b = '1%' !== g.top), (c = '4px' === g.width), d.removeChild(e); + } + a.getComputedStyle && + n.extend(k, { + pixelPosition: function () { + return g(), b; + }, + boxSizingReliable: function () { + return null == c && g(), c; + }, + reliableMarginRight: function () { + var b, + c = f.appendChild(l.createElement('div')); + return ( + (c.style.cssText = f.style.cssText = + '-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0'), + (c.style.marginRight = c.style.width = '0'), + (f.style.width = '1px'), + d.appendChild(e), + (b = !parseFloat(a.getComputedStyle(c, null).marginRight)), + d.removeChild(e), + f.removeChild(c), + b + ); + }, + }); + } + })(), + (n.swap = function (a, b, c, d) { + var e, + f, + g = {}; + for (f in b) (g[f] = a.style[f]), (a.style[f] = b[f]); + e = c.apply(a, d || []); + for (f in b) a.style[f] = g[f]; + return e; + }); + var zb = /^(none|table(?!-c[ea]).+)/, + Ab = new RegExp('^(' + Q + ')(.*)$', 'i'), + Bb = new RegExp('^([+-])=(' + Q + ')', 'i'), + Cb = { position: 'absolute', visibility: 'hidden', display: 'block' }, + Db = { letterSpacing: '0', fontWeight: '400' }, + Eb = ['Webkit', 'O', 'Moz', 'ms']; + function Fb(a, b) { + if (b in a) return b; + var c = b[0].toUpperCase() + b.slice(1), + d = b, + e = Eb.length; + while (e--) if (((b = Eb[e] + c), b in a)) return b; + return d; + } + function Gb(a, b, c) { + var d = Ab.exec(b); + return d ? Math.max(0, d[1] - (c || 0)) + (d[2] || 'px') : b; + } + function Hb(a, b, c, d, e) { + for (var f = c === (d ? 'border' : 'content') ? 4 : 'width' === b ? 1 : 0, g = 0; 4 > f; f += 2) + 'margin' === c && (g += n.css(a, c + R[f], !0, e)), + d + ? ('content' === c && (g -= n.css(a, 'padding' + R[f], !0, e)), + 'margin' !== c && (g -= n.css(a, 'border' + R[f] + 'Width', !0, e))) + : ((g += n.css(a, 'padding' + R[f], !0, e)), + 'padding' !== c && (g += n.css(a, 'border' + R[f] + 'Width', !0, e))); + return g; + } + function Ib(a, b, c) { + var d = !0, + e = 'width' === b ? a.offsetWidth : a.offsetHeight, + f = wb(a), + g = 'border-box' === n.css(a, 'boxSizing', !1, f); + if (0 >= e || null == e) { + if (((e = xb(a, b, f)), (0 > e || null == e) && (e = a.style[b]), vb.test(e))) return e; + (d = g && (k.boxSizingReliable() || e === a.style[b])), (e = parseFloat(e) || 0); + } + return e + Hb(a, b, c || (g ? 'border' : 'content'), d, f) + 'px'; + } + function Jb(a, b) { + for (var c, d, e, f = [], g = 0, h = a.length; h > g; g++) + (d = a[g]), + d.style && + ((f[g] = L.get(d, 'olddisplay')), + (c = d.style.display), + b + ? (f[g] || 'none' !== c || (d.style.display = ''), + '' === d.style.display && S(d) && (f[g] = L.access(d, 'olddisplay', tb(d.nodeName)))) + : ((e = S(d)), ('none' === c && e) || L.set(d, 'olddisplay', e ? c : n.css(d, 'display')))); + for (g = 0; h > g; g++) + (d = a[g]), + d.style && + ((b && 'none' !== d.style.display && '' !== d.style.display) || (d.style.display = b ? f[g] || '' : 'none')); + return a; + } + n.extend({ + cssHooks: { + opacity: { + get: function (a, b) { + if (b) { + var c = xb(a, 'opacity'); + return '' === c ? '1' : c; + } + }, + }, + }, + cssNumber: { + columnCount: !0, + fillOpacity: !0, + flexGrow: !0, + flexShrink: !0, + fontWeight: !0, + lineHeight: !0, + opacity: !0, + order: !0, + orphans: !0, + widows: !0, + zIndex: !0, + zoom: !0, + }, + cssProps: { float: 'cssFloat' }, + style: function (a, b, c, d) { + if (a && 3 !== a.nodeType && 8 !== a.nodeType && a.style) { + var e, + f, + g, + h = n.camelCase(b), + i = a.style; + return ( + (b = n.cssProps[h] || (n.cssProps[h] = Fb(i, h))), + (g = n.cssHooks[b] || n.cssHooks[h]), + void 0 === c + ? g && 'get' in g && void 0 !== (e = g.get(a, !1, d)) + ? e + : i[b] + : ((f = typeof c), + 'string' === f && (e = Bb.exec(c)) && ((c = (e[1] + 1) * e[2] + parseFloat(n.css(a, b))), (f = 'number')), + null != c && + c === c && + ('number' !== f || n.cssNumber[h] || (c += 'px'), + k.clearCloneStyle || '' !== c || 0 !== b.indexOf('background') || (i[b] = 'inherit'), + (g && 'set' in g && void 0 === (c = g.set(a, c, d))) || (i[b] = c)), + void 0) + ); + } + }, + css: function (a, b, c, d) { + var e, + f, + g, + h = n.camelCase(b); + return ( + (b = n.cssProps[h] || (n.cssProps[h] = Fb(a.style, h))), + (g = n.cssHooks[b] || n.cssHooks[h]), + g && 'get' in g && (e = g.get(a, !0, c)), + void 0 === e && (e = xb(a, b, d)), + 'normal' === e && b in Db && (e = Db[b]), + '' === c || c ? ((f = parseFloat(e)), c === !0 || n.isNumeric(f) ? f || 0 : e) : e + ); + }, + }), + n.each(['height', 'width'], function (a, b) { + n.cssHooks[b] = { + get: function (a, c, d) { + return c + ? zb.test(n.css(a, 'display')) && 0 === a.offsetWidth + ? n.swap(a, Cb, function () { + return Ib(a, b, d); + }) + : Ib(a, b, d) + : void 0; + }, + set: function (a, c, d) { + var e = d && wb(a); + return Gb(a, c, d ? Hb(a, b, d, 'border-box' === n.css(a, 'boxSizing', !1, e), e) : 0); + }, + }; + }), + (n.cssHooks.marginRight = yb(k.reliableMarginRight, function (a, b) { + return b ? n.swap(a, { display: 'inline-block' }, xb, [a, 'marginRight']) : void 0; + })), + n.each({ margin: '', padding: '', border: 'Width' }, function (a, b) { + (n.cssHooks[a + b] = { + expand: function (c) { + for (var d = 0, e = {}, f = 'string' == typeof c ? c.split(' ') : [c]; 4 > d; d++) + e[a + R[d] + b] = f[d] || f[d - 2] || f[0]; + return e; + }, + }), + ub.test(a) || (n.cssHooks[a + b].set = Gb); + }), + n.fn.extend({ + css: function (a, b) { + return J( + this, + function (a, b, c) { + var d, + e, + f = {}, + g = 0; + if (n.isArray(b)) { + for (d = wb(a), e = b.length; e > g; g++) f[b[g]] = n.css(a, b[g], !1, d); + return f; + } + return void 0 !== c ? n.style(a, b, c) : n.css(a, b); + }, + a, + b, + arguments.length > 1, + ); + }, + show: function () { + return Jb(this, !0); + }, + hide: function () { + return Jb(this); + }, + toggle: function (a) { + return 'boolean' == typeof a + ? a + ? this.show() + : this.hide() + : this.each(function () { + S(this) ? n(this).show() : n(this).hide(); + }); + }, + }); + function Kb(a, b, c, d, e) { + return new Kb.prototype.init(a, b, c, d, e); + } + (n.Tween = Kb), + (Kb.prototype = { + constructor: Kb, + init: function (a, b, c, d, e, f) { + (this.elem = a), + (this.prop = c), + (this.easing = e || 'swing'), + (this.options = b), + (this.start = this.now = this.cur()), + (this.end = d), + (this.unit = f || (n.cssNumber[c] ? '' : 'px')); + }, + cur: function () { + var a = Kb.propHooks[this.prop]; + return a && a.get ? a.get(this) : Kb.propHooks._default.get(this); + }, + run: function (a) { + var b, + c = Kb.propHooks[this.prop]; + return ( + (this.pos = b = + this.options.duration + ? n.easing[this.easing](a, this.options.duration * a, 0, 1, this.options.duration) + : a), + (this.now = (this.end - this.start) * b + this.start), + this.options.step && this.options.step.call(this.elem, this.now, this), + c && c.set ? c.set(this) : Kb.propHooks._default.set(this), + this + ); + }, + }), + (Kb.prototype.init.prototype = Kb.prototype), + (Kb.propHooks = { + _default: { + get: function (a) { + var b; + return null == a.elem[a.prop] || (a.elem.style && null != a.elem.style[a.prop]) + ? ((b = n.css(a.elem, a.prop, '')), b && 'auto' !== b ? b : 0) + : a.elem[a.prop]; + }, + set: function (a) { + n.fx.step[a.prop] + ? n.fx.step[a.prop](a) + : a.elem.style && (null != a.elem.style[n.cssProps[a.prop]] || n.cssHooks[a.prop]) + ? n.style(a.elem, a.prop, a.now + a.unit) + : (a.elem[a.prop] = a.now); + }, + }, + }), + (Kb.propHooks.scrollTop = Kb.propHooks.scrollLeft = + { + set: function (a) { + a.elem.nodeType && a.elem.parentNode && (a.elem[a.prop] = a.now); + }, + }), + (n.easing = { + linear: function (a) { + return a; + }, + swing: function (a) { + return 0.5 - Math.cos(a * Math.PI) / 2; + }, + }), + (n.fx = Kb.prototype.init), + (n.fx.step = {}); + var Lb, + Mb, + Nb = /^(?:toggle|show|hide)$/, + Ob = new RegExp('^(?:([+-])=|)(' + Q + ')([a-z%]*)$', 'i'), + Pb = /queueHooks$/, + Qb = [Vb], + Rb = { + '*': [ + function (a, b) { + var c = this.createTween(a, b), + d = c.cur(), + e = Ob.exec(b), + f = (e && e[3]) || (n.cssNumber[a] ? '' : 'px'), + g = (n.cssNumber[a] || ('px' !== f && +d)) && Ob.exec(n.css(c.elem, a)), + h = 1, + i = 20; + if (g && g[3] !== f) { + (f = f || g[3]), (e = e || []), (g = +d || 1); + do (h = h || '.5'), (g /= h), n.style(c.elem, a, g + f); + while (h !== (h = c.cur() / d) && 1 !== h && --i); + } + return e && ((g = c.start = +g || +d || 0), (c.unit = f), (c.end = e[1] ? g + (e[1] + 1) * e[2] : +e[2])), c; + }, + ], + }; + function Sb() { + return ( + setTimeout(function () { + Lb = void 0; + }), + (Lb = n.now()) + ); + } + function Tb(a, b) { + var c, + d = 0, + e = { height: a }; + for (b = b ? 1 : 0; 4 > d; d += 2 - b) (c = R[d]), (e['margin' + c] = e['padding' + c] = a); + return b && (e.opacity = e.width = a), e; + } + function Ub(a, b, c) { + for (var d, e = (Rb[b] || []).concat(Rb['*']), f = 0, g = e.length; g > f; f++) + if ((d = e[f].call(c, b, a))) return d; + } + function Vb(a, b, c) { + var d, + e, + f, + g, + h, + i, + j, + k, + l = this, + m = {}, + o = a.style, + p = a.nodeType && S(a), + q = L.get(a, 'fxshow'); + c.queue || + ((h = n._queueHooks(a, 'fx')), + null == h.unqueued && + ((h.unqueued = 0), + (i = h.empty.fire), + (h.empty.fire = function () { + h.unqueued || i(); + })), + h.unqueued++, + l.always(function () { + l.always(function () { + h.unqueued--, n.queue(a, 'fx').length || h.empty.fire(); + }); + })), + 1 === a.nodeType && + ('height' in b || 'width' in b) && + ((c.overflow = [o.overflow, o.overflowX, o.overflowY]), + (j = n.css(a, 'display')), + (k = 'none' === j ? L.get(a, 'olddisplay') || tb(a.nodeName) : j), + 'inline' === k && 'none' === n.css(a, 'float') && (o.display = 'inline-block')), + c.overflow && + ((o.overflow = 'hidden'), + l.always(function () { + (o.overflow = c.overflow[0]), (o.overflowX = c.overflow[1]), (o.overflowY = c.overflow[2]); + })); + for (d in b) + if (((e = b[d]), Nb.exec(e))) { + if ((delete b[d], (f = f || 'toggle' === e), e === (p ? 'hide' : 'show'))) { + if ('show' !== e || !q || void 0 === q[d]) continue; + p = !0; + } + m[d] = (q && q[d]) || n.style(a, d); + } else j = void 0; + if (n.isEmptyObject(m)) 'inline' === ('none' === j ? tb(a.nodeName) : j) && (o.display = j); + else { + q ? 'hidden' in q && (p = q.hidden) : (q = L.access(a, 'fxshow', {})), + f && (q.hidden = !p), + p + ? n(a).show() + : l.done(function () { + n(a).hide(); + }), + l.done(function () { + var b; + L.remove(a, 'fxshow'); + for (b in m) n.style(a, b, m[b]); + }); + for (d in m) + (g = Ub(p ? q[d] : 0, d, l)), + d in q || ((q[d] = g.start), p && ((g.end = g.start), (g.start = 'width' === d || 'height' === d ? 1 : 0))); + } + } + function Wb(a, b) { + var c, d, e, f, g; + for (c in a) + if ( + ((d = n.camelCase(c)), + (e = b[d]), + (f = a[c]), + n.isArray(f) && ((e = f[1]), (f = a[c] = f[0])), + c !== d && ((a[d] = f), delete a[c]), + (g = n.cssHooks[d]), + g && 'expand' in g) + ) { + (f = g.expand(f)), delete a[d]; + for (c in f) c in a || ((a[c] = f[c]), (b[c] = e)); + } else b[d] = e; + } + function Xb(a, b, c) { + var d, + e, + f = 0, + g = Qb.length, + h = n.Deferred().always(function () { + delete i.elem; + }), + i = function () { + if (e) return !1; + for ( + var b = Lb || Sb(), + c = Math.max(0, j.startTime + j.duration - b), + d = c / j.duration || 0, + f = 1 - d, + g = 0, + i = j.tweens.length; + i > g; + g++ + ) + j.tweens[g].run(f); + return h.notifyWith(a, [j, f, c]), 1 > f && i ? c : (h.resolveWith(a, [j]), !1); + }, + j = h.promise({ + elem: a, + props: n.extend({}, b), + opts: n.extend(!0, { specialEasing: {} }, c), + originalProperties: b, + originalOptions: c, + startTime: Lb || Sb(), + duration: c.duration, + tweens: [], + createTween: function (b, c) { + var d = n.Tween(a, j.opts, b, c, j.opts.specialEasing[b] || j.opts.easing); + return j.tweens.push(d), d; + }, + stop: function (b) { + var c = 0, + d = b ? j.tweens.length : 0; + if (e) return this; + for (e = !0; d > c; c++) j.tweens[c].run(1); + return b ? h.resolveWith(a, [j, b]) : h.rejectWith(a, [j, b]), this; + }, + }), + k = j.props; + for (Wb(k, j.opts.specialEasing); g > f; f++) if ((d = Qb[f].call(j, a, k, j.opts))) return d; + return ( + n.map(k, Ub, j), + n.isFunction(j.opts.start) && j.opts.start.call(a, j), + n.fx.timer(n.extend(i, { elem: a, anim: j, queue: j.opts.queue })), + j.progress(j.opts.progress).done(j.opts.done, j.opts.complete).fail(j.opts.fail).always(j.opts.always) + ); + } + (n.Animation = n.extend(Xb, { + tweener: function (a, b) { + n.isFunction(a) ? ((b = a), (a = ['*'])) : (a = a.split(' ')); + for (var c, d = 0, e = a.length; e > d; d++) (c = a[d]), (Rb[c] = Rb[c] || []), Rb[c].unshift(b); + }, + prefilter: function (a, b) { + b ? Qb.unshift(a) : Qb.push(a); + }, + })), + (n.speed = function (a, b, c) { + var d = + a && 'object' == typeof a + ? n.extend({}, a) + : { + complete: c || (!c && b) || (n.isFunction(a) && a), + duration: a, + easing: (c && b) || (b && !n.isFunction(b) && b), + }; + return ( + (d.duration = n.fx.off + ? 0 + : 'number' == typeof d.duration + ? d.duration + : d.duration in n.fx.speeds + ? n.fx.speeds[d.duration] + : n.fx.speeds._default), + (null == d.queue || d.queue === !0) && (d.queue = 'fx'), + (d.old = d.complete), + (d.complete = function () { + n.isFunction(d.old) && d.old.call(this), d.queue && n.dequeue(this, d.queue); + }), + d + ); + }), + n.fn.extend({ + fadeTo: function (a, b, c, d) { + return this.filter(S).css('opacity', 0).show().end().animate({ opacity: b }, a, c, d); + }, + animate: function (a, b, c, d) { + var e = n.isEmptyObject(a), + f = n.speed(b, c, d), + g = function () { + var b = Xb(this, n.extend({}, a), f); + (e || L.get(this, 'finish')) && b.stop(!0); + }; + return (g.finish = g), e || f.queue === !1 ? this.each(g) : this.queue(f.queue, g); + }, + stop: function (a, b, c) { + var d = function (a) { + var b = a.stop; + delete a.stop, b(c); + }; + return ( + 'string' != typeof a && ((c = b), (b = a), (a = void 0)), + b && a !== !1 && this.queue(a || 'fx', []), + this.each(function () { + var b = !0, + e = null != a && a + 'queueHooks', + f = n.timers, + g = L.get(this); + if (e) g[e] && g[e].stop && d(g[e]); + else for (e in g) g[e] && g[e].stop && Pb.test(e) && d(g[e]); + for (e = f.length; e--; ) + f[e].elem !== this || (null != a && f[e].queue !== a) || (f[e].anim.stop(c), (b = !1), f.splice(e, 1)); + (b || !c) && n.dequeue(this, a); + }) + ); + }, + finish: function (a) { + return ( + a !== !1 && (a = a || 'fx'), + this.each(function () { + var b, + c = L.get(this), + d = c[a + 'queue'], + e = c[a + 'queueHooks'], + f = n.timers, + g = d ? d.length : 0; + for (c.finish = !0, n.queue(this, a, []), e && e.stop && e.stop.call(this, !0), b = f.length; b--; ) + f[b].elem === this && f[b].queue === a && (f[b].anim.stop(!0), f.splice(b, 1)); + for (b = 0; g > b; b++) d[b] && d[b].finish && d[b].finish.call(this); + delete c.finish; + }) + ); + }, + }), + n.each(['toggle', 'show', 'hide'], function (a, b) { + var c = n.fn[b]; + n.fn[b] = function (a, d, e) { + return null == a || 'boolean' == typeof a ? c.apply(this, arguments) : this.animate(Tb(b, !0), a, d, e); + }; + }), + n.each( + { + slideDown: Tb('show'), + slideUp: Tb('hide'), + slideToggle: Tb('toggle'), + fadeIn: { opacity: 'show' }, + fadeOut: { opacity: 'hide' }, + fadeToggle: { opacity: 'toggle' }, + }, + function (a, b) { + n.fn[a] = function (a, c, d) { + return this.animate(b, a, c, d); + }; + }, + ), + (n.timers = []), + (n.fx.tick = function () { + var a, + b = 0, + c = n.timers; + for (Lb = n.now(); b < c.length; b++) (a = c[b]), a() || c[b] !== a || c.splice(b--, 1); + c.length || n.fx.stop(), (Lb = void 0); + }), + (n.fx.timer = function (a) { + n.timers.push(a), a() ? n.fx.start() : n.timers.pop(); + }), + (n.fx.interval = 13), + (n.fx.start = function () { + Mb || (Mb = setInterval(n.fx.tick, n.fx.interval)); + }), + (n.fx.stop = function () { + clearInterval(Mb), (Mb = null); + }), + (n.fx.speeds = { slow: 600, fast: 200, _default: 400 }), + (n.fn.delay = function (a, b) { + return ( + (a = n.fx ? n.fx.speeds[a] || a : a), + (b = b || 'fx'), + this.queue(b, function (b, c) { + var d = setTimeout(b, a); + c.stop = function () { + clearTimeout(d); + }; + }) + ); + }), + (function () { + var a = l.createElement('input'), + b = l.createElement('select'), + c = b.appendChild(l.createElement('option')); + (a.type = 'checkbox'), + (k.checkOn = '' !== a.value), + (k.optSelected = c.selected), + (b.disabled = !0), + (k.optDisabled = !c.disabled), + (a = l.createElement('input')), + (a.value = 't'), + (a.type = 'radio'), + (k.radioValue = 't' === a.value); + })(); + var Yb, + Zb, + $b = n.expr.attrHandle; + n.fn.extend({ + attr: function (a, b) { + return J(this, n.attr, a, b, arguments.length > 1); + }, + removeAttr: function (a) { + return this.each(function () { + n.removeAttr(this, a); + }); + }, + }), + n.extend({ + attr: function (a, b, c) { + var d, + e, + f = a.nodeType; + if (a && 3 !== f && 8 !== f && 2 !== f) + return typeof a.getAttribute === U + ? n.prop(a, b, c) + : ((1 === f && n.isXMLDoc(a)) || + ((b = b.toLowerCase()), (d = n.attrHooks[b] || (n.expr.match.bool.test(b) ? Zb : Yb))), + void 0 === c + ? d && 'get' in d && null !== (e = d.get(a, b)) + ? e + : ((e = n.find.attr(a, b)), null == e ? void 0 : e) + : null !== c + ? d && 'set' in d && void 0 !== (e = d.set(a, c, b)) + ? e + : (a.setAttribute(b, c + ''), c) + : void n.removeAttr(a, b)); + }, + removeAttr: function (a, b) { + var c, + d, + e = 0, + f = b && b.match(E); + if (f && 1 === a.nodeType) + while ((c = f[e++])) (d = n.propFix[c] || c), n.expr.match.bool.test(c) && (a[d] = !1), a.removeAttribute(c); + }, + attrHooks: { + type: { + set: function (a, b) { + if (!k.radioValue && 'radio' === b && n.nodeName(a, 'input')) { + var c = a.value; + return a.setAttribute('type', b), c && (a.value = c), b; + } + }, + }, + }, + }), + (Zb = { + set: function (a, b, c) { + return b === !1 ? n.removeAttr(a, c) : a.setAttribute(c, c), c; + }, + }), + n.each(n.expr.match.bool.source.match(/\w+/g), function (a, b) { + var c = $b[b] || n.find.attr; + $b[b] = function (a, b, d) { + var e, f; + return d || ((f = $b[b]), ($b[b] = e), (e = null != c(a, b, d) ? b.toLowerCase() : null), ($b[b] = f)), e; + }; + }); + var _b = /^(?:input|select|textarea|button)$/i; + n.fn.extend({ + prop: function (a, b) { + return J(this, n.prop, a, b, arguments.length > 1); + }, + removeProp: function (a) { + return this.each(function () { + delete this[n.propFix[a] || a]; + }); + }, + }), + n.extend({ + propFix: { for: 'htmlFor', class: 'className' }, + prop: function (a, b, c) { + var d, + e, + f, + g = a.nodeType; + if (a && 3 !== g && 8 !== g && 2 !== g) + return ( + (f = 1 !== g || !n.isXMLDoc(a)), + f && ((b = n.propFix[b] || b), (e = n.propHooks[b])), + void 0 !== c + ? e && 'set' in e && void 0 !== (d = e.set(a, c, b)) + ? d + : (a[b] = c) + : e && 'get' in e && null !== (d = e.get(a, b)) + ? d + : a[b] + ); + }, + propHooks: { + tabIndex: { + get: function (a) { + return a.hasAttribute('tabindex') || _b.test(a.nodeName) || a.href ? a.tabIndex : -1; + }, + }, + }, + }), + k.optSelected || + (n.propHooks.selected = { + get: function (a) { + var b = a.parentNode; + return b && b.parentNode && b.parentNode.selectedIndex, null; + }, + }), + n.each( + [ + 'tabIndex', + 'readOnly', + 'maxLength', + 'cellSpacing', + 'cellPadding', + 'rowSpan', + 'colSpan', + 'useMap', + 'frameBorder', + 'contentEditable', + ], + function () { + n.propFix[this.toLowerCase()] = this; + }, + ); + var ac = /[\t\r\n\f]/g; + n.fn.extend({ + addClass: function (a) { + var b, + c, + d, + e, + f, + g, + h = 'string' == typeof a && a, + i = 0, + j = this.length; + if (n.isFunction(a)) + return this.each(function (b) { + n(this).addClass(a.call(this, b, this.className)); + }); + if (h) + for (b = (a || '').match(E) || []; j > i; i++) + if ( + ((c = this[i]), (d = 1 === c.nodeType && (c.className ? (' ' + c.className + ' ').replace(ac, ' ') : ' '))) + ) { + f = 0; + while ((e = b[f++])) d.indexOf(' ' + e + ' ') < 0 && (d += e + ' '); + (g = n.trim(d)), c.className !== g && (c.className = g); + } + return this; + }, + removeClass: function (a) { + var b, + c, + d, + e, + f, + g, + h = 0 === arguments.length || ('string' == typeof a && a), + i = 0, + j = this.length; + if (n.isFunction(a)) + return this.each(function (b) { + n(this).removeClass(a.call(this, b, this.className)); + }); + if (h) + for (b = (a || '').match(E) || []; j > i; i++) + if ( + ((c = this[i]), (d = 1 === c.nodeType && (c.className ? (' ' + c.className + ' ').replace(ac, ' ') : ''))) + ) { + f = 0; + while ((e = b[f++])) while (d.indexOf(' ' + e + ' ') >= 0) d = d.replace(' ' + e + ' ', ' '); + (g = a ? n.trim(d) : ''), c.className !== g && (c.className = g); + } + return this; + }, + toggleClass: function (a, b) { + var c = typeof a; + return 'boolean' == typeof b && 'string' === c + ? b + ? this.addClass(a) + : this.removeClass(a) + : this.each( + n.isFunction(a) + ? function (c) { + n(this).toggleClass(a.call(this, c, this.className, b), b); + } + : function () { + if ('string' === c) { + var b, + d = 0, + e = n(this), + f = a.match(E) || []; + while ((b = f[d++])) e.hasClass(b) ? e.removeClass(b) : e.addClass(b); + } else + (c === U || 'boolean' === c) && + (this.className && L.set(this, '__className__', this.className), + (this.className = this.className || a === !1 ? '' : L.get(this, '__className__') || '')); + }, + ); + }, + hasClass: function (a) { + for (var b = ' ' + a + ' ', c = 0, d = this.length; d > c; c++) + if (1 === this[c].nodeType && (' ' + this[c].className + ' ').replace(ac, ' ').indexOf(b) >= 0) return !0; + return !1; + }, + }); + var bc = /\r/g; + n.fn.extend({ + val: function (a) { + var b, + c, + d, + e = this[0]; + { + if (arguments.length) + return ( + (d = n.isFunction(a)), + this.each(function (c) { + var e; + 1 === this.nodeType && + ((e = d ? a.call(this, c, n(this).val()) : a), + null == e + ? (e = '') + : 'number' == typeof e + ? (e += '') + : n.isArray(e) && + (e = n.map(e, function (a) { + return null == a ? '' : a + ''; + })), + (b = n.valHooks[this.type] || n.valHooks[this.nodeName.toLowerCase()]), + (b && 'set' in b && void 0 !== b.set(this, e, 'value')) || (this.value = e)); + }) + ); + if (e) + return ( + (b = n.valHooks[e.type] || n.valHooks[e.nodeName.toLowerCase()]), + b && 'get' in b && void 0 !== (c = b.get(e, 'value')) + ? c + : ((c = e.value), 'string' == typeof c ? c.replace(bc, '') : null == c ? '' : c) + ); + } + }, + }), + n.extend({ + valHooks: { + option: { + get: function (a) { + var b = n.find.attr(a, 'value'); + return null != b ? b : n.trim(n.text(a)); + }, + }, + select: { + get: function (a) { + for ( + var b, + c, + d = a.options, + e = a.selectedIndex, + f = 'select-one' === a.type || 0 > e, + g = f ? null : [], + h = f ? e + 1 : d.length, + i = 0 > e ? h : f ? e : 0; + h > i; + i++ + ) + if ( + ((c = d[i]), + !( + (!c.selected && i !== e) || + (k.optDisabled ? c.disabled : null !== c.getAttribute('disabled')) || + (c.parentNode.disabled && n.nodeName(c.parentNode, 'optgroup')) + )) + ) { + if (((b = n(c).val()), f)) return b; + g.push(b); + } + return g; + }, + set: function (a, b) { + var c, + d, + e = a.options, + f = n.makeArray(b), + g = e.length; + while (g--) (d = e[g]), (d.selected = n.inArray(d.value, f) >= 0) && (c = !0); + return c || (a.selectedIndex = -1), f; + }, + }, + }, + }), + n.each(['radio', 'checkbox'], function () { + (n.valHooks[this] = { + set: function (a, b) { + return n.isArray(b) ? (a.checked = n.inArray(n(a).val(), b) >= 0) : void 0; + }, + }), + k.checkOn || + (n.valHooks[this].get = function (a) { + return null === a.getAttribute('value') ? 'on' : a.value; + }); + }), + n.each( + 'blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu'.split( + ' ', + ), + function (a, b) { + n.fn[b] = function (a, c) { + return arguments.length > 0 ? this.on(b, null, a, c) : this.trigger(b); + }; + }, + ), + n.fn.extend({ + hover: function (a, b) { + return this.mouseenter(a).mouseleave(b || a); + }, + bind: function (a, b, c) { + return this.on(a, null, b, c); + }, + unbind: function (a, b) { + return this.off(a, null, b); + }, + delegate: function (a, b, c, d) { + return this.on(b, a, c, d); + }, + undelegate: function (a, b, c) { + return 1 === arguments.length ? this.off(a, '**') : this.off(b, a || '**', c); + }, + }); + var cc = n.now(), + dc = /\?/; + (n.parseJSON = function (a) { + return JSON.parse(a + ''); + }), + (n.parseXML = function (a) { + var b, c; + if (!a || 'string' != typeof a) return null; + try { + (c = new DOMParser()), (b = c.parseFromString(a, 'text/xml')); + } catch (d) { + b = void 0; + } + return (!b || b.getElementsByTagName('parsererror').length) && n.error('Invalid XML: ' + a), b; + }); + var ec = /#.*$/, + fc = /([?&])_=[^&]*/, + gc = /^(.*?):[ \t]*([^\r\n]*)$/gm, + hc = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, + ic = /^(?:GET|HEAD)$/, + jc = /^\/\//, + kc = /^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/, + lc = {}, + mc = {}, + nc = '*/'.concat('*'), + oc = a.location.href, + pc = kc.exec(oc.toLowerCase()) || []; + function qc(a) { + return function (b, c) { + 'string' != typeof b && ((c = b), (b = '*')); + var d, + e = 0, + f = b.toLowerCase().match(E) || []; + if (n.isFunction(c)) + while ((d = f[e++])) + '+' === d[0] ? ((d = d.slice(1) || '*'), (a[d] = a[d] || []).unshift(c)) : (a[d] = a[d] || []).push(c); + }; + } + function rc(a, b, c, d) { + var e = {}, + f = a === mc; + function g(h) { + var i; + return ( + (e[h] = !0), + n.each(a[h] || [], function (a, h) { + var j = h(b, c, d); + return 'string' != typeof j || f || e[j] ? (f ? !(i = j) : void 0) : (b.dataTypes.unshift(j), g(j), !1); + }), + i + ); + } + return g(b.dataTypes[0]) || (!e['*'] && g('*')); + } + function sc(a, b) { + var c, + d, + e = n.ajaxSettings.flatOptions || {}; + for (c in b) void 0 !== b[c] && ((e[c] ? a : d || (d = {}))[c] = b[c]); + return d && n.extend(!0, a, d), a; + } + function tc(a, b, c) { + var d, + e, + f, + g, + h = a.contents, + i = a.dataTypes; + while ('*' === i[0]) i.shift(), void 0 === d && (d = a.mimeType || b.getResponseHeader('Content-Type')); + if (d) + for (e in h) + if (h[e] && h[e].test(d)) { + i.unshift(e); + break; + } + if (i[0] in c) f = i[0]; + else { + for (e in c) { + if (!i[0] || a.converters[e + ' ' + i[0]]) { + f = e; + break; + } + g || (g = e); + } + f = f || g; + } + return f ? (f !== i[0] && i.unshift(f), c[f]) : void 0; + } + function uc(a, b, c, d) { + var e, + f, + g, + h, + i, + j = {}, + k = a.dataTypes.slice(); + if (k[1]) for (g in a.converters) j[g.toLowerCase()] = a.converters[g]; + f = k.shift(); + while (f) + if ( + (a.responseFields[f] && (c[a.responseFields[f]] = b), + !i && d && a.dataFilter && (b = a.dataFilter(b, a.dataType)), + (i = f), + (f = k.shift())) + ) + if ('*' === f) f = i; + else if ('*' !== i && i !== f) { + if (((g = j[i + ' ' + f] || j['* ' + f]), !g)) + for (e in j) + if (((h = e.split(' ')), h[1] === f && (g = j[i + ' ' + h[0]] || j['* ' + h[0]]))) { + g === !0 ? (g = j[e]) : j[e] !== !0 && ((f = h[0]), k.unshift(h[1])); + break; + } + if (g !== !0) + if (g && a['throws']) b = g(b); + else + try { + b = g(b); + } catch (l) { + return { state: 'parsererror', error: g ? l : 'No conversion from ' + i + ' to ' + f }; + } + } + return { state: 'success', data: b }; + } + n.extend({ + active: 0, + lastModified: {}, + etag: {}, + ajaxSettings: { + url: oc, + type: 'GET', + isLocal: hc.test(pc[1]), + global: !0, + processData: !0, + async: !0, + contentType: 'application/x-www-form-urlencoded; charset=UTF-8', + accepts: { + '*': nc, + text: 'text/plain', + html: 'text/html', + xml: 'application/xml, text/xml', + json: 'application/json, text/javascript', + }, + contents: { xml: /xml/, html: /html/, json: /json/ }, + responseFields: { xml: 'responseXML', text: 'responseText', json: 'responseJSON' }, + converters: { '* text': String, 'text html': !0, 'text json': n.parseJSON, 'text xml': n.parseXML }, + flatOptions: { url: !0, context: !0 }, + }, + ajaxSetup: function (a, b) { + return b ? sc(sc(a, n.ajaxSettings), b) : sc(n.ajaxSettings, a); + }, + ajaxPrefilter: qc(lc), + ajaxTransport: qc(mc), + ajax: function (a, b) { + 'object' == typeof a && ((b = a), (a = void 0)), (b = b || {}); + var c, + d, + e, + f, + g, + h, + i, + j, + k = n.ajaxSetup({}, b), + l = k.context || k, + m = k.context && (l.nodeType || l.jquery) ? n(l) : n.event, + o = n.Deferred(), + p = n.Callbacks('once memory'), + q = k.statusCode || {}, + r = {}, + s = {}, + t = 0, + u = 'canceled', + v = { + readyState: 0, + getResponseHeader: function (a) { + var b; + if (2 === t) { + if (!f) { + f = {}; + while ((b = gc.exec(e))) f[b[1].toLowerCase()] = b[2]; + } + b = f[a.toLowerCase()]; + } + return null == b ? null : b; + }, + getAllResponseHeaders: function () { + return 2 === t ? e : null; + }, + setRequestHeader: function (a, b) { + var c = a.toLowerCase(); + return t || ((a = s[c] = s[c] || a), (r[a] = b)), this; + }, + overrideMimeType: function (a) { + return t || (k.mimeType = a), this; + }, + statusCode: function (a) { + var b; + if (a) + if (2 > t) for (b in a) q[b] = [q[b], a[b]]; + else v.always(a[v.status]); + return this; + }, + abort: function (a) { + var b = a || u; + return c && c.abort(b), x(0, b), this; + }, + }; + if ( + ((o.promise(v).complete = p.add), + (v.success = v.done), + (v.error = v.fail), + (k.url = ((a || k.url || oc) + '').replace(ec, '').replace(jc, pc[1] + '//')), + (k.type = b.method || b.type || k.method || k.type), + (k.dataTypes = n + .trim(k.dataType || '*') + .toLowerCase() + .match(E) || ['']), + null == k.crossDomain && + ((h = kc.exec(k.url.toLowerCase())), + (k.crossDomain = !( + !h || + (h[1] === pc[1] && + h[2] === pc[2] && + (h[3] || ('http:' === h[1] ? '80' : '443')) === (pc[3] || ('http:' === pc[1] ? '80' : '443'))) + ))), + k.data && k.processData && 'string' != typeof k.data && (k.data = n.param(k.data, k.traditional)), + rc(lc, k, b, v), + 2 === t) + ) + return v; + (i = n.event && k.global), + i && 0 === n.active++ && n.event.trigger('ajaxStart'), + (k.type = k.type.toUpperCase()), + (k.hasContent = !ic.test(k.type)), + (d = k.url), + k.hasContent || + (k.data && ((d = k.url += (dc.test(d) ? '&' : '?') + k.data), delete k.data), + k.cache === !1 && + (k.url = fc.test(d) ? d.replace(fc, '$1_=' + cc++) : d + (dc.test(d) ? '&' : '?') + '_=' + cc++)), + k.ifModified && + (n.lastModified[d] && v.setRequestHeader('If-Modified-Since', n.lastModified[d]), + n.etag[d] && v.setRequestHeader('If-None-Match', n.etag[d])), + ((k.data && k.hasContent && k.contentType !== !1) || b.contentType) && + v.setRequestHeader('Content-Type', k.contentType), + v.setRequestHeader( + 'Accept', + k.dataTypes[0] && k.accepts[k.dataTypes[0]] + ? k.accepts[k.dataTypes[0]] + ('*' !== k.dataTypes[0] ? ', ' + nc + '; q=0.01' : '') + : k.accepts['*'], + ); + for (j in k.headers) v.setRequestHeader(j, k.headers[j]); + if (k.beforeSend && (k.beforeSend.call(l, v, k) === !1 || 2 === t)) return v.abort(); + u = 'abort'; + for (j in { success: 1, error: 1, complete: 1 }) v[j](k[j]); + if ((c = rc(mc, k, b, v))) { + (v.readyState = 1), + i && m.trigger('ajaxSend', [v, k]), + k.async && + k.timeout > 0 && + (g = setTimeout(function () { + v.abort('timeout'); + }, k.timeout)); + try { + (t = 1), c.send(r, x); + } catch (w) { + if (!(2 > t)) throw w; + x(-1, w); + } + } else x(-1, 'No Transport'); + function x(a, b, f, h) { + var j, + r, + s, + u, + w, + x = b; + 2 !== t && + ((t = 2), + g && clearTimeout(g), + (c = void 0), + (e = h || ''), + (v.readyState = a > 0 ? 4 : 0), + (j = (a >= 200 && 300 > a) || 304 === a), + f && (u = tc(k, v, f)), + (u = uc(k, u, v, j)), + j + ? (k.ifModified && + ((w = v.getResponseHeader('Last-Modified')), + w && (n.lastModified[d] = w), + (w = v.getResponseHeader('etag')), + w && (n.etag[d] = w)), + 204 === a || 'HEAD' === k.type + ? (x = 'nocontent') + : 304 === a + ? (x = 'notmodified') + : ((x = u.state), (r = u.data), (s = u.error), (j = !s))) + : ((s = x), (a || !x) && ((x = 'error'), 0 > a && (a = 0))), + (v.status = a), + (v.statusText = (b || x) + ''), + j ? o.resolveWith(l, [r, x, v]) : o.rejectWith(l, [v, x, s]), + v.statusCode(q), + (q = void 0), + i && m.trigger(j ? 'ajaxSuccess' : 'ajaxError', [v, k, j ? r : s]), + p.fireWith(l, [v, x]), + i && (m.trigger('ajaxComplete', [v, k]), --n.active || n.event.trigger('ajaxStop'))); + } + return v; + }, + getJSON: function (a, b, c) { + return n.get(a, b, c, 'json'); + }, + getScript: function (a, b) { + return n.get(a, void 0, b, 'script'); + }, + }), + n.each(['get', 'post'], function (a, b) { + n[b] = function (a, c, d, e) { + return ( + n.isFunction(c) && ((e = e || d), (d = c), (c = void 0)), + n.ajax({ url: a, type: b, dataType: e, data: c, success: d }) + ); + }; + }), + (n._evalUrl = function (a) { + return n.ajax({ url: a, type: 'GET', dataType: 'script', async: !1, global: !1, throws: !0 }); + }), + n.fn.extend({ + wrapAll: function (a) { + var b; + return n.isFunction(a) + ? this.each(function (b) { + n(this).wrapAll(a.call(this, b)); + }) + : (this[0] && + ((b = n(a, this[0].ownerDocument).eq(0).clone(!0)), + this[0].parentNode && b.insertBefore(this[0]), + b + .map(function () { + var a = this; + while (a.firstElementChild) a = a.firstElementChild; + return a; + }) + .append(this)), + this); + }, + wrapInner: function (a) { + return this.each( + n.isFunction(a) + ? function (b) { + n(this).wrapInner(a.call(this, b)); + } + : function () { + var b = n(this), + c = b.contents(); + c.length ? c.wrapAll(a) : b.append(a); + }, + ); + }, + wrap: function (a) { + var b = n.isFunction(a); + return this.each(function (c) { + n(this).wrapAll(b ? a.call(this, c) : a); + }); + }, + unwrap: function () { + return this.parent() + .each(function () { + n.nodeName(this, 'body') || n(this).replaceWith(this.childNodes); + }) + .end(); + }, + }), + (n.expr.filters.hidden = function (a) { + return a.offsetWidth <= 0 && a.offsetHeight <= 0; + }), + (n.expr.filters.visible = function (a) { + return !n.expr.filters.hidden(a); + }); + var vc = /%20/g, + wc = /\[\]$/, + xc = /\r?\n/g, + yc = /^(?:submit|button|image|reset|file)$/i, + zc = /^(?:input|select|textarea|keygen)/i; + function Ac(a, b, c, d) { + var e; + if (n.isArray(b)) + n.each(b, function (b, e) { + c || wc.test(a) ? d(a, e) : Ac(a + '[' + ('object' == typeof e ? b : '') + ']', e, c, d); + }); + else if (c || 'object' !== n.type(b)) d(a, b); + else for (e in b) Ac(a + '[' + e + ']', b[e], c, d); + } + (n.param = function (a, b) { + var c, + d = [], + e = function (a, b) { + (b = n.isFunction(b) ? b() : null == b ? '' : b), + (d[d.length] = encodeURIComponent(a) + '=' + encodeURIComponent(b)); + }; + if ( + (void 0 === b && (b = n.ajaxSettings && n.ajaxSettings.traditional), + n.isArray(a) || (a.jquery && !n.isPlainObject(a))) + ) + n.each(a, function () { + e(this.name, this.value); + }); + else for (c in a) Ac(c, a[c], b, e); + return d.join('&').replace(vc, '+'); + }), + n.fn.extend({ + serialize: function () { + return n.param(this.serializeArray()); + }, + serializeArray: function () { + return this.map(function () { + var a = n.prop(this, 'elements'); + return a ? n.makeArray(a) : this; + }) + .filter(function () { + var a = this.type; + return ( + this.name && + !n(this).is(':disabled') && + zc.test(this.nodeName) && + !yc.test(a) && + (this.checked || !T.test(a)) + ); + }) + .map(function (a, b) { + var c = n(this).val(); + return null == c + ? null + : n.isArray(c) + ? n.map(c, function (a) { + return { name: b.name, value: a.replace(xc, '\r\n') }; + }) + : { name: b.name, value: c.replace(xc, '\r\n') }; + }) + .get(); + }, + }), + (n.ajaxSettings.xhr = function () { + try { + return new XMLHttpRequest(); + } catch (a) {} + }); + var Bc = 0, + Cc = {}, + Dc = { 0: 200, 1223: 204 }, + Ec = n.ajaxSettings.xhr(); + a.attachEvent && + a.attachEvent('onunload', function () { + for (var a in Cc) Cc[a](); + }), + (k.cors = !!Ec && 'withCredentials' in Ec), + (k.ajax = Ec = !!Ec), + n.ajaxTransport(function (a) { + var b; + return k.cors || (Ec && !a.crossDomain) + ? { + send: function (c, d) { + var e, + f = a.xhr(), + g = ++Bc; + if ((f.open(a.type, a.url, a.async, a.username, a.password), a.xhrFields)) + for (e in a.xhrFields) f[e] = a.xhrFields[e]; + a.mimeType && f.overrideMimeType && f.overrideMimeType(a.mimeType), + a.crossDomain || c['X-Requested-With'] || (c['X-Requested-With'] = 'XMLHttpRequest'); + for (e in c) f.setRequestHeader(e, c[e]); + (b = function (a) { + return function () { + b && + (delete Cc[g], + (b = f.onload = f.onerror = null), + 'abort' === a + ? f.abort() + : 'error' === a + ? d(f.status, f.statusText) + : d( + Dc[f.status] || f.status, + f.statusText, + 'string' == typeof f.responseText ? { text: f.responseText } : void 0, + f.getAllResponseHeaders(), + )); + }; + }), + (f.onload = b()), + (f.onerror = b('error')), + (b = Cc[g] = b('abort')); + try { + f.send((a.hasContent && a.data) || null); + } catch (h) { + if (b) throw h; + } + }, + abort: function () { + b && b(); + }, + } + : void 0; + }), + n.ajaxSetup({ + accepts: { script: 'text/javascript, application/javascript, application/ecmascript, application/x-ecmascript' }, + contents: { script: /(?:java|ecma)script/ }, + converters: { + 'text script': function (a) { + return n.globalEval(a), a; + }, + }, + }), + n.ajaxPrefilter('script', function (a) { + void 0 === a.cache && (a.cache = !1), a.crossDomain && (a.type = 'GET'); + }), + n.ajaxTransport('script', function (a) { + if (a.crossDomain) { + var b, c; + return { + send: function (d, e) { + (b = n('<script>') + .prop({ async: !0, charset: a.scriptCharset, src: a.url }) + .on( + 'load error', + (c = function (a) { + b.remove(), (c = null), a && e('error' === a.type ? 404 : 200, a.type); + }), + )), + l.head.appendChild(b[0]); + }, + abort: function () { + c && c(); + }, + }; + } + }); + var Fc = [], + Gc = /(=)\?(?=&|$)|\?\?/; + n.ajaxSetup({ + jsonp: 'callback', + jsonpCallback: function () { + var a = Fc.pop() || n.expando + '_' + cc++; + return (this[a] = !0), a; + }, + }), + n.ajaxPrefilter('json jsonp', function (b, c, d) { + var e, + f, + g, + h = + b.jsonp !== !1 && + (Gc.test(b.url) + ? 'url' + : 'string' == typeof b.data && + !(b.contentType || '').indexOf('application/x-www-form-urlencoded') && + Gc.test(b.data) && + 'data'); + return h || 'jsonp' === b.dataTypes[0] + ? ((e = b.jsonpCallback = n.isFunction(b.jsonpCallback) ? b.jsonpCallback() : b.jsonpCallback), + h + ? (b[h] = b[h].replace(Gc, '$1' + e)) + : b.jsonp !== !1 && (b.url += (dc.test(b.url) ? '&' : '?') + b.jsonp + '=' + e), + (b.converters['script json'] = function () { + return g || n.error(e + ' was not called'), g[0]; + }), + (b.dataTypes[0] = 'json'), + (f = a[e]), + (a[e] = function () { + g = arguments; + }), + d.always(function () { + (a[e] = f), + b[e] && ((b.jsonpCallback = c.jsonpCallback), Fc.push(e)), + g && n.isFunction(f) && f(g[0]), + (g = f = void 0); + }), + 'script') + : void 0; + }), + (n.parseHTML = function (a, b, c) { + if (!a || 'string' != typeof a) return null; + 'boolean' == typeof b && ((c = b), (b = !1)), (b = b || l); + var d = v.exec(a), + e = !c && []; + return d + ? [b.createElement(d[1])] + : ((d = n.buildFragment([a], b, e)), e && e.length && n(e).remove(), n.merge([], d.childNodes)); + }); + var Hc = n.fn.load; + (n.fn.load = function (a, b, c) { + if ('string' != typeof a && Hc) return Hc.apply(this, arguments); + var d, + e, + f, + g = this, + h = a.indexOf(' '); + return ( + h >= 0 && ((d = n.trim(a.slice(h))), (a = a.slice(0, h))), + n.isFunction(b) ? ((c = b), (b = void 0)) : b && 'object' == typeof b && (e = 'POST'), + g.length > 0 && + n + .ajax({ url: a, type: e, dataType: 'html', data: b }) + .done(function (a) { + (f = arguments), g.html(d ? n('<div>').append(n.parseHTML(a)).find(d) : a); + }) + .complete( + c && + function (a, b) { + g.each(c, f || [a.responseText, b, a]); + }, + ), + this + ); + }), + n.each(['ajaxStart', 'ajaxStop', 'ajaxComplete', 'ajaxError', 'ajaxSuccess', 'ajaxSend'], function (a, b) { + n.fn[b] = function (a) { + return this.on(b, a); + }; + }), + (n.expr.filters.animated = function (a) { + return n.grep(n.timers, function (b) { + return a === b.elem; + }).length; + }); + var Ic = a.document.documentElement; + function Jc(a) { + return n.isWindow(a) ? a : 9 === a.nodeType && a.defaultView; + } + (n.offset = { + setOffset: function (a, b, c) { + var d, + e, + f, + g, + h, + i, + j, + k = n.css(a, 'position'), + l = n(a), + m = {}; + 'static' === k && (a.style.position = 'relative'), + (h = l.offset()), + (f = n.css(a, 'top')), + (i = n.css(a, 'left')), + (j = ('absolute' === k || 'fixed' === k) && (f + i).indexOf('auto') > -1), + j ? ((d = l.position()), (g = d.top), (e = d.left)) : ((g = parseFloat(f) || 0), (e = parseFloat(i) || 0)), + n.isFunction(b) && (b = b.call(a, c, h)), + null != b.top && (m.top = b.top - h.top + g), + null != b.left && (m.left = b.left - h.left + e), + 'using' in b ? b.using.call(a, m) : l.css(m); + }, + }), + n.fn.extend({ + offset: function (a) { + if (arguments.length) + return void 0 === a + ? this + : this.each(function (b) { + n.offset.setOffset(this, a, b); + }); + var b, + c, + d = this[0], + e = { top: 0, left: 0 }, + f = d && d.ownerDocument; + if (f) + return ( + (b = f.documentElement), + n.contains(b, d) + ? (typeof d.getBoundingClientRect !== U && (e = d.getBoundingClientRect()), + (c = Jc(f)), + { top: e.top + c.pageYOffset - b.clientTop, left: e.left + c.pageXOffset - b.clientLeft }) + : e + ); + }, + position: function () { + if (this[0]) { + var a, + b, + c = this[0], + d = { top: 0, left: 0 }; + return ( + 'fixed' === n.css(c, 'position') + ? (b = c.getBoundingClientRect()) + : ((a = this.offsetParent()), + (b = this.offset()), + n.nodeName(a[0], 'html') || (d = a.offset()), + (d.top += n.css(a[0], 'borderTopWidth', !0)), + (d.left += n.css(a[0], 'borderLeftWidth', !0))), + { top: b.top - d.top - n.css(c, 'marginTop', !0), left: b.left - d.left - n.css(c, 'marginLeft', !0) } + ); + } + }, + offsetParent: function () { + return this.map(function () { + var a = this.offsetParent || Ic; + while (a && !n.nodeName(a, 'html') && 'static' === n.css(a, 'position')) a = a.offsetParent; + return a || Ic; + }); + }, + }), + n.each({ scrollLeft: 'pageXOffset', scrollTop: 'pageYOffset' }, function (b, c) { + var d = 'pageYOffset' === c; + n.fn[b] = function (e) { + return J( + this, + function (b, e, f) { + var g = Jc(b); + return void 0 === f + ? g + ? g[c] + : b[e] + : void (g ? g.scrollTo(d ? a.pageXOffset : f, d ? f : a.pageYOffset) : (b[e] = f)); + }, + b, + e, + arguments.length, + null, + ); + }; + }), + n.each(['top', 'left'], function (a, b) { + n.cssHooks[b] = yb(k.pixelPosition, function (a, c) { + return c ? ((c = xb(a, b)), vb.test(c) ? n(a).position()[b] + 'px' : c) : void 0; + }); + }), + n.each({ Height: 'height', Width: 'width' }, function (a, b) { + n.each({ padding: 'inner' + a, content: b, '': 'outer' + a }, function (c, d) { + n.fn[d] = function (d, e) { + var f = arguments.length && (c || 'boolean' != typeof d), + g = c || (d === !0 || e === !0 ? 'margin' : 'border'); + return J( + this, + function (b, c, d) { + var e; + return n.isWindow(b) + ? b.document.documentElement['client' + a] + : 9 === b.nodeType + ? ((e = b.documentElement), + Math.max( + b.body['scroll' + a], + e['scroll' + a], + b.body['offset' + a], + e['offset' + a], + e['client' + a], + )) + : void 0 === d + ? n.css(b, c, g) + : n.style(b, c, d, g); + }, + b, + f ? d : void 0, + f, + null, + ); + }; + }); + }), + (n.fn.size = function () { + return this.length; + }), + (n.fn.andSelf = n.fn.addBack), + 'function' == typeof define && + define.amd && + define('jquery', [], function () { + return n; + }); + var Kc = a.jQuery, + Lc = a.$; + return ( + (n.noConflict = function (b) { + return a.$ === n && (a.$ = Lc), b && a.jQuery === n && (a.jQuery = Kc), n; + }), + typeof b === U && (a.jQuery = a.$ = n), + n + ); +}); diff --git a/src/assets/tiles/tiles.json b/src/assets/tiles/tiles.json new file mode 100644 index 0000000..ab2db40 --- /dev/null +++ b/src/assets/tiles/tiles.json @@ -0,0 +1,160 @@ +{ + "items": [ + { + "id": 1, + "title": "Service Design and Creation (SDC)", + "description": "Open the SDC in a new tab", + "tooltipDE": "SDC ist das visuelle Modellierungs- und Designtool von ONAP. Es erstellt interne Metadaten, die Assets beschreiben, die von allen ONAP-Komponenten verwendet werden, sowohl zur Entwurfszeit als auch zur Laufzeit.", + "tooltipEN": "SDC is the ONAP visual modeling and design tool. It creates internal metadata that describes assets used by all ONAP components, both at design time and run time.", + "imageUrl": "sdc.svg", + "imageAltText": "SDC image", + "redirectUrl": "https://sdc-ui-HOSTNAME/sdc1/portal", + "groups": [], + "roles": [ + "ONAP_ADMIN", + "ONAP_OPERATOR", + "ONAP_DESIGNER" + ] + }, + { + "id": 3, + "title": "Policy Framework", + "description": "Open Policy GUI in a new tab", + "tooltipDE": "Das ONAP Policy Framework legt die Architektur des Frameworks dar und zeigt die APIs, die anderen Komponenten bereitgestellt werden, die mit dem Framework zusammenarbeiten.", + "tooltipEN": "ONAP Policy Framework lays out the architecture of the framework and shows the APIs provided to other components that interwork with the framework.", + "imageUrl": "onap.svg", + "imageAltText": "Policy image", + "redirectUrl": "https://policy-ui-HOSTNAME/", + "groups": [], + "roles": [ + "ONAP_ADMIN" + ] + }, + { + "id": 4, + "title": "Service Orchestration (SO) Monitoring", + "description": "Open SO-Monitoring in a new tab", + "tooltipDE": "Der ONAP Service Orchestrator bietet die höchste Ebene der Service-Orchestrierung in der ONAP-Architektur.", + "tooltipEN": "The ONAP Service Orchestrator provides the highest level of service orchestration in the ONAP architecture.", + "imageUrl": "onap.svg", + "imageAltText": "SO-Monitoring image", + "redirectUrl": "https://so-monitoring-ui-HOSTNAME/", + "groups": [], + "roles": [ + "ONAP_OPERATOR" + ] + }, + { + "id": 7, + "title": "Controller Design Studio (CDS)", + "description": "Open CDS in a new tab", + "tooltipDE": "Die CDS Designer Benutzeroberfläche ist ein Framework zur Automatisierung der Auflösung von Ressourcen für die Instanziierung und aller Konfigurationsbereitstellung, wie z. B. die Konfiguration von Day0, Day1 oder Day2.", + "tooltipEN": "CDS Designer UI is a framework to automate the resolution of resources for instantiation and any config provisioning operation, such as day0, day1, or day2 configuration.", + "imageUrl": "cds.svg", + "imageAltText": "CDS image", + "redirectUrl": "https://cds-ui-HOSTNAME/", + "groups": [], + "roles": [ + "ONAP_ADMIN", + "ONAP_OPERATOR", + "ONAP_DESIGNER" + ] + }, + { + "id": 9, + "title": "Holmes Rules", + "description": "Open Holmes in a new tab", + "tooltipDE": "Das Holmes-Projekt bietet Alarmkorrelation und -analyse für Telekommunikations-Cloudinfrastruktur und -Dienste, einschließlich Hosts, Vims, VNFs und NSs.", + "tooltipEN": "Holmes project provides alarm correlation and analysis for Telecom cloud infrastructure and services, including hosts, vims, VNFs and NSs.", + "imageUrl": "onap.svg", + "imageAltText": "Holmes image", + "redirectUrl": "https://holmes-ui-HOSTNAME/iui/holmes/default.html", + "groups": [], + "roles": [ + "ONAP_ADMIN", + "ONAP_OPERATOR", + "ONAP_DESIGNER" + ] + }, + { + "id": 10, + "title": "A&AI Browser", + "description": "Open the A&AI Browser in a new tab", + "tooltipDE": "AAI ist eine Komponente der ONAP-Laufzeit (Echtzeitansichten von Ressourcen, Services, Produkten, Kundenabonnements und deren Beziehungen).", + "tooltipEN": "AAI is a component of ONAP runtime (Real-time views of Resources, Services, Products, Customer Subscriptions and their relationships).", + "imageUrl": "onap.svg", + "imageAltText": "A&AI Browser image", + "redirectUrl": "https://aai-ui-HOSTNAME/services/aai/webapp/index.html#/browse", + "groups": [], + "roles": [ + "ONAP_ADMIN", + "ONAP_OPERATOR", + "ONAP_DESIGNER" + ] + }, + { + "id": 11, + "title": "DCAE Microservice Onboarding & Design (DCAE MOD)", + "description": "Open the DCAE MOD in a new tab", + "tooltipDE": "DCAE ist der Sammelbegriff für eine Reihe von Komponenten, die gemeinsam die Rolle der Datenerfassung, Analyse und Ereignisgenerierung für ONAP erfüllen. Die Architektur von DCAE zielt auf eine flexible, steckbare, Micros-Service-orientierte, modellbasierte Komponentenbereitstellung und Servicezusammensetzung ab. DCAE unterstützt auch Sammel- und Analysevorgänge an mehreren Standorten, die für große ONAP-Bereitstellungen unerlässlich sind.", + "tooltipEN": "DCAE is the umbrella name for a number of components collectively fulfilling the role of Data Collection, Analytics, and Events generation for ONAP. The architecture of DCAE targets flexible, plug-able, micros-service oriented, model based component deployment and service composition. DCAE also support multi-site collection and analytics operations which are essential for large ONAP deployments.", + "imageUrl": "dcae-mod.svg", + "imageAltText": "DCAE MOD image", + "redirectUrl": "https://dcaemod-ui-HOSTNAME/nifi/", + "groups": [], + "roles": [ + "ONAP_ADMIN", + "ONAP_OPERATOR", + "ONAP_DESIGNER" + ] + }, + { + "id": 12, + "title": "SDN-C Directed Graph Builder (SDC-C DGB)", + "description": "Open the SDN-C Directed Graph Builder in a new tab", + "tooltipDE": "SDNC DG soll eine Ausführungsumgebung für schnell geschriebene und hochgradig angepasste Serviceabläufe bereitstellen.", + "tooltipEN": "SDNC DG is to provide an execution environment for quickly written and highly customized service flows.", + "imageUrl": "sdnc-dg.svg", + "imageAltText": "SDN-C DG image", + "redirectUrl": "https://sdncdg-ui-HOSTNAME/", + "groups": [], + "roles": [ + "ONAP_ADMIN", + "ONAP_OPERATOR", + "ONAP_DESIGNER" + ] + }, + { + "id": 13, + "title": "SDN-C Open Daylight UI (SDN-C ODL)", + "description": "Open the SDN-C Open Daylight UI (SDN-C ODL) in a new tab", + "tooltipDE": "Das OpenDaylight Project ist ein kollaboratives Open-Source-Projekt, das von der Linux Foundation gehostet wird. Das Projekt dient als Plattform für Software-Defined Networking (SDN) zur offenen, zentralisierten Überwachung von Netzwerkgeräten.", + "tooltipEN": "The OpenDaylight Project is a collaborative open-source project hosted by The Linux Foundation. The project serves as a platform for software-defined networking (SDN) for open, centralized, network device monitoring.", + "imageUrl": "sdnc-odl.svg", + "imageAltText": "SDN-C ODL image", + "redirectUrl": "https://sdncodl-ui-HOSTNAME//odlux/index.html", + "groups": [], + "roles": [ + "ONAP_ADMIN", + "ONAP_OPERATOR", + "ONAP_DESIGNER" + ] + }, + { + "id": 14, + "title": "Non-RT RIC", + "description": "Open the Non-RT RIC in a new tab", + "tooltipDE": "Ein \"Non-RealTime RIC (RAN Intelligent Controller)\" Controller ist eine von der ORAN Allianz spezifizierte Orchestrierungs- und Automatisierungsfunktion für das Nicht-Echtzeit-Management von RAN Funktionen. ", + "tooltipEN": "A Non-RealTime RIC (RAN Intelligent Controller) is an Orchestration and Automation function specified by the O-RAN Alliance for non-real-time intelligent management of RAN (Radio Access Network) functions.", + "imageUrl": "onap.svg", + "imageAltText": "Non-RT RIC image", + "redirectUrl": "https://nonrtric-controlpanel-HOSTNAME/", + "groups": [], + "roles": [ + "ONAP_ADMIN", + "ONAP_OPERATOR", + "ONAP_DESIGNER" + ] + } + ] +}
\ No newline at end of file diff --git a/src/assets/version.json b/src/assets/version.json new file mode 100644 index 0000000..cc29ff0 --- /dev/null +++ b/src/assets/version.json @@ -0,0 +1,3 @@ +{ + "number": "VERSIONPLACEHOLDER" +} diff --git a/src/environments/environment.prod.ts b/src/environments/environment.prod.ts new file mode 100644 index 0000000..a533520 --- /dev/null +++ b/src/environments/environment.prod.ts @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Environment } from '../app/model/environment.model'; + + +export const environment: Environment = { + customStyleEnabled: true, + backendServerUrl: window.location.origin + '/api', + hostname: window.location.hostname, + production: true, + keycloakEditProfile: `${window.location.origin}/auth/realms/ONAP/account`, + keycloak: { + issuer: `${window.location.origin}/auth/realms/ONAP`, // Url of the Identity Provider + redirectUri: window.location.origin, // URL of the SPA to redirect the user to after login + clientId: 'portal-app', // The Frontend is registered with this id at the auth-server + responseType: 'code', + scope: 'openid', // set the scope for the permissions the client should request + requireHttps: false, // Don't require https + showDebugInformation: false, + disableAtHashCheck: true, // if at_hash is not present in JWT token + skipIssuerCheck: false, + strictDiscoveryDocumentValidation: true, + }, + dateTimeFormat: 'dd/MM/yyyy HH:mm:ss', + loggingUrl: window.location.origin + '/onap_logging', + supportUrlLink: 'https://wiki.onap.org/', + loggingEnabled: true +}; diff --git a/src/environments/environment.ts b/src/environments/environment.ts new file mode 100644 index 0000000..80d0005 --- /dev/null +++ b/src/environments/environment.ts @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Environment } from '../app/model/environment.model'; + +/** + * The config that is used for local development. + * + * It can be replaced during build by using the `fileReplacements` array. + * `ng build --prod` replaces `environment.ts` with `environment.prod.ts`. + * The list of file replacements can be found in `angular.json`. + */ +export const environment: Environment = { + customStyleEnabled: true, + backendServerUrl: window.location.origin + '/api', + keycloakEditProfile: `${window.location.origin}/auth/realms/ONAP/account`, + hostname: window.location.hostname, + production: false, + keycloak: { + issuer: `${window.location.origin}/auth/realms/ONAP`, // Url of the Identity Provider + redirectUri: window.location.origin, // URL of the SPA to redirect the user to after login + clientId: 'portal-app', // The Frontend is registered with this id at the auth-server + responseType: 'code', + scope: 'openid', // set the scope for the permissions the client should request + requireHttps: false, // Don't require https + showDebugInformation: false, + disableAtHashCheck: true, // if at_hash is not present in JWT token + skipIssuerCheck: true, + strictDiscoveryDocumentValidation: false, + }, + dateTimeFormat: 'dd/MM/yyyy HH:mm:ss', + loggingUrl: window.location.origin + '/onap_logging', + supportUrlLink: 'https://wiki.onap.org/', + loggingEnabled: false +}; +/* + * For easier debugging in development mode, you can import the following file + * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. + * + * This import should be commented out in production mode because it will have a negative impact + * on performance if an error is thrown. + */ diff --git a/src/favicon.ico b/src/favicon.ico Binary files differnew file mode 100644 index 0000000..75268c5 --- /dev/null +++ b/src/favicon.ico diff --git a/src/index.html b/src/index.html new file mode 100644 index 0000000..9ff9ef5 --- /dev/null +++ b/src/index.html @@ -0,0 +1,34 @@ +<!-- + ~ Copyright (c) 2022. Deutsche Telekom AG + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + ~ + ~ SPDX-License-Identifier: Apache-2.0 + --> + + +<!DOCTYPE html> +<html lang="en"> + <head> + <meta charset="utf-8" /> + <title>ONAP Portal</title> + <base href="/" /> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + <link rel="icon" type="image/x-icon" href="favicon.ico" /> + <script src="assets/js/jquery-2.1.3.min.js"></script> + <script src="assets/js/bootstrap.min.js"></script> + </head> + <body> + <app-root></app-root> + </body> +</html> diff --git a/src/keycloak-error.html b/src/keycloak-error.html new file mode 100644 index 0000000..745dd46 --- /dev/null +++ b/src/keycloak-error.html @@ -0,0 +1,196 @@ +<!-- + ~ Copyright (c) 2022. Deutsche Telekom AG + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + ~ + ~ SPDX-License-Identifier: Apache-2.0 + --> + +<!DOCTYPE html> +<html lang="en"> + <head> + <meta charset="UTF-8" /> + <title>ONAP Portal</title> + <meta http-equiv="X-UA-Compatible" content="IE=edge" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + <link rel="icon" type="image/x-icon" href="favicon.ico" /> + <link rel="stylesheet" href="assets/css/bootstrap.css" /> + <link rel="stylesheet" href="styles.css" /> + <script src="assets/js/jquery-2.1.3.min.js"></script> + <script src="assets/js/bootstrap.min.js"></script> + <style> + .navbar { + background-color: #e7e6e6; + height: 55px; + padding: 6px !important; + } + + .sidebar-toggler { + background-color: transparent; + border-style: none; + margin-top: 2px; + } + + .onap-logo { + margin-left: 0.75rem; + margin-bottom: 2px; + } + + .margin-r-6-px { + margin-right: 6px; + } + .margin-l-auto { + margin-left: auto; + } + + .margin-r-3-px { + margin-right: 3px; + } + + .header-icon-styling { + color: var(--black); + width: 20px; + margin-bottom: 8px; + } + + .btn-account { + background-color: transparent; + border-style: none; + font-size: 21px; + cursor: none; + margin-bottom: 7px; + height: 38.25px; + padding-top: 3px; + padding-bottom: 6.73px; + } + + .nav-wrapper { + padding: 6px; + } + + .sidebar-container { + margin-right: -1px; + flex: 0 0 230px; + border-right-style: solid; + border-right-width: 1px; + border-right-color: #b2b2b2; + } + + .sidebar-expanded { + min-width: 250px; + max-width: 250px; + height: calc(100vh - 67px); + display: block; + border-right-style: solid; + border-right-width: 1px; + border-right-color: #c5c5c5; + } + + .portal-version-wrapper { + padding: 2px; + } + + .portal-version-title, + .portal-version-number { + font-size: 13px; + line-height: 15.6px; + margin-bottom: 10px; + } + + .btn:focus { + outline: 0; + box-shadow: none; + } + + .error-content-wrapper { + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + } + + .error-text-wrapper { + font-weight: bold; + } + + .error-text { + font-size: 25px; + } + + img, + button, + button:not(:disabled), + [type='button']:not(:disabled), + [type='reset']:not(:disabled), + [type='submit']:not(:disabled) { + cursor: auto; + } + </style> + </head> + + <body onload="errorInfo()"> + <div> + <nav aria-label="Sidemenu" class="navbar navbar-light"> + <button type="button" class="sidebar-toggler" [attr.aria-label]="'Toggle sidemenu'"> + <img src="assets/images/icons/list-dark.svg" alt="List" /> + </button> + <a class="onap-logo"> + <img style="height: 38px" src="assets/images/onap-logo.png" alt="ONAP Logo" /> + </a> + <div class="d-inline-block margin-r-6-px margin-l-auto"> + <button class="btn btn-invisible header-icon-styling margin-r-3-px p-0" [attr.aria-label]="'Help'"> + <img src="assets/images/icons/question-circle.svg" alt="Help" /> + </button> + <button class="btn btn-invisible header-icon-styling p-0" [attr.aria-label]="'Fullscreen'"> + <img src="assets/images/icons/arrows-fullscreen-dark.svg" alt="Fullscreen" /></button + ><!-- + --><button class="btn btn-account px-3" [attr.aria-label]="'My Account'"> + <img src="assets/images/icons/person-fill-dark.svg" alt="Person" /><!-- + --><img src="assets/images/icons/caret-down-fill-dark.svg" alt="Caret down" /> + </button> + </div> + </nav> + </div> + <div class="nav-wrapper"> + <nav + class="sidebar-container sidebar-expanded overflow-auto d-flex flex-column justify-content-between" + [attr.aria-label]="'Main Menu'" + > + <div class="d-flex justify-content-center text-center mt-auto portal-version-wrapper"> + <h5 class="portal-version-title mr-1">Portal Version:</h5> + <span class="portal-version-number">VERSIONPLACEHOLDER</span> + </div> + </nav> + </div> + <div> + <div class="container text-center error-content-wrapper"> + <div class="row"> + <div class="col"> + <div class="error-text-wrapper"> + <p class="error-text"> + We are not able to authorize you due to a server issue that occured at: <span id="dateTime"></span> + </p> + </div> + </div> + </div> + </div> + </div> + + <script> + function errorInfo() { + const dt = new Date(); + document.getElementById('dateTime').innerHTML = dt.toLocaleString(); + } + </script> + </body> +</html> diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..1e445f4 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { enableProdMode } from '@angular/core'; +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; + +import { AppModule } from './app/app.module'; +import { environment } from './environments/environment'; +import { ajax } from 'rxjs/ajax'; +import { catchError, switchMap } from 'rxjs/operators'; +import { EMPTY, from } from 'rxjs'; +import { ACL_CONFIG, AclConfig } from './app/modules/auth/injection-tokens'; + +if (environment.production) { + enableProdMode(); +} + +const fetchAclConfig$ = ajax.getJSON<AclConfig>(`assets/acl.json`); + +fetchAclConfig$ + .pipe( + switchMap(acl => from(platformBrowserDynamic([{ provide: ACL_CONFIG, useValue: acl }]).bootstrapModule(AppModule))), + catchError(() => { + return EMPTY; + }), + ) + .subscribe(() => { + console.log('App bootstrapped successfully'); + }); diff --git a/src/polyfills.ts b/src/polyfills.ts new file mode 100644 index 0000000..d8ed2ca --- /dev/null +++ b/src/polyfills.ts @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +/*************************************************************************************************** + * Load `$localize` onto the global scope - used if i18n tags appear in Angular templates. + */ +import '@angular/localize/init'; +/** + * This file includes polyfills needed by Angular and is loaded before the app. + * You can add your own extra polyfills to this file. + * + * This file is divided into 2 sections: + * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. + * 2. Application imports. Files imported after ZoneJS that should be loaded before your main + * file. + * + * The current setup is for so-called "evergreen" browsers; the last versions of browsers that + * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), + * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. + * + * Learn more in https://angular.io/guide/browser-support + */ +/*************************************************************************************************** + * BROWSER POLYFILLS + */ +/** IE10 and IE11 requires the following for NgClass support on SVG elements */ +/** + * Web Animations `@angular/platform-browser/animations` + * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari. + * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0). + */ +/** + * By default, zone.js will patch all possible macroTask and DomEvents + * user can disable parts of macroTask/DomEvents patch by setting following flags + * because those flags need to be set before `zone.js` being loaded, and webpack + * will put import in the top of bundle, so user need to create a separate file + * in this directory (for example: zone-flags.ts), and put the following flags + * into that file, and then add the following code before importing zone.js. + * import './zone-flags'; + * + * The flags allowed in zone-flags.ts are listed here. + * + * The following flags will work for all browsers. + * + * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame + * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick + * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames + * + * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js + * with the following flag, it will bypass `zone.js` patch for IE/Edge + * + * (window as any).__Zone_enable_cross_context_check = true; + * + */ +/*************************************************************************************************** + * Zone JS is required by default for Angular itself. + */ +import 'zone.js'; // Included with Angular CLI. + +/*************************************************************************************************** + * APPLICATION IMPORTS + */ diff --git a/src/styles.css b/src/styles.css new file mode 100644 index 0000000..2528e5d --- /dev/null +++ b/src/styles.css @@ -0,0 +1,630 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +/* https://www.w3schools.com/css/css3_variables.asp */ +:root { + --alert-transparency: 0.9; + --light-gray: #f5f5f5; + --dark-gray: #5a5858; + --active-gray: #d9d9d9; + --black: #000; + --white: #fff; + --danger: #d90000; + --secondary: #ededed; + --major: #fad4b8; + --minor: #fecb00; + --intense-blue: #00a0de; + +} + +/* ######################################## + * Colors + * ######################################## + */ + + +.blue { + color: var(--blue); +} + +.orange { + color: #ffa500; +} + +.red { + color: #ff0000; +} + +.green { + color: #008000; +} + +.dark-gray { + color: var(--dark-gray); +} +.black { + color: var(--black); +} + +.max-w-100px { + max-width: 100px; +} +.max-w-120px { + max-width: 120px; +} + +.right-10 { + right: 10px; +} +.opacity-1 { + opacity: 1 !important; +} + +.alert { + z-index: 1; +} + +.alert-primary { + background-color: #cce5ff !important; +} +.alert-secondary { + background-color: #e2e3e5 !important; +} +.alert-success { + background-color: #d4edda !important; +} +.alert-info { + background-color: #d1ecf1 !important; +} +.alert-warning { + background-color: #fff3cd !important; +} +.alert-danger { + color: var(--red) !important; + background-color: #f8d7da !important; +} +.alert-light { + background-color: #fefefe !important; +} +.alert-dark { + background-color: #d6d8d9 !important; +} + +.navbar-collapse.in { + display: block !important; +} + +.btn { + max-height: 40px; +} +.max-w-fit-content { + max-width: fit-content; +} +.btn-delete-bg { + background-position: center; + background-image: url('assets/images/icons/delete-icon.svg'); +} + +.opacity-1 { + opacity: 1 !important; +} + +button[aria-label='Close']:focus { + outline: none; +} + +.breadcrumb-item a { + color: var(--blue) !important; +} +.bg-lightGray { + background-color: var(--light-gray); +} +/* Make pagination responsive: https://github.com/twbs/bootstrap/issues/23504#issuecomment-592757850 */ +ul.pagination { + margin-bottom: 0; + flex-wrap: wrap; +} + +/* Allow other elements to be in line with the pagination */ +ngb-pagination { + display: inline-block; +} + +.form-control:disabled, +.form-control[readonly], +option:disabled { + background-color: #e9ecef !important; + opacity: 1 !important; +} + +/* + Red asterisk that is not visible to screen readers + https://stackoverflow.com/questions/26634156/can-i-prevent-after-pseudo-element-from-being-read-by-screen-readers#26634352 +*/ +.required:after { + content: ''; + display: inline-block; + width: 0.5em; + height: 0.5em; + background-image: url(src/assets/images/icons/Asterisk.svg); + background-size: 0.5em 0.5em; + vertical-align: top; + margin-left: 0.15em; + margin-top: 0.1em; +} + +.breadcrumb-item::before { + margin-top: 4px; +} +.uuid-cell { + width: 350px; + min-width: 350px; + max-width: 350px; +} +.btn-invisible { + background-color: initial; + border: none; +} +.dropdown-toggle::after { + height: 6px !important; +} + +#deployment-summary-accordion > .card { + border-radius: 0.25rem; +} + +/* Override the (overly large) padding of the accordion header element */ +#deployment-summary-accordion > .card > .card-header { + padding-left: 17px; + padding-right: 17px; +} + +/* add a scrollbar to the content area of the accordion */ +#deployment-summary-accordion > .card > div[id^='panel-'] { + max-height: 50vh; + overflow: auto; +} + +/* telekom-styles is removing the bottom border on this element otherwise*/ +.accordion .card:first-of-type { + border: 1px solid #b2b2b2 !important; +} +.w-20px { + width: 20px !important; +} + +/* override the telekom-styles behaviour: Pagination is too small */ +.pagination-sm .page-link { + line-height: 1.8 !important; +} + +/* adding focus to buttons with class btn-default */ +.btn-default:focus { + outline: 5px auto var(--cyan) !important; + outline-offset: -2px !important; +} + +.border-blue { + border-color: var(--light-blue) !important; +} +.ngx-charts-outer { + border: 1px solid rgba(0, 0, 0, 0.1); +} + +.outline-blue { + border: 1px solid var(--light-blue) !important; + border-radius: 0.25rem; +} +.outline-grey { + border-color: 1px solid var(--secondary); + border-radius: 0.25rem; +} + +.border-radius-top-none { + border-top-left-radius: 0 !important; + border-top-right-radius: 0 !important; +} + +.accordion .card:last-of-type { + border-top-left-radius: 0.25rem !important; + border-top-right-radius: 0.25rem !important; +} + +.text-align-start { + text-align: start; +} + +.row-active { + background-color: var(--active-gray) !important; + border: 1px solid var(--light-blue) !important; + border-radius: 0.25rem; +} + +.accordion > .card > .card-header { + padding-left: 0 !important; +} + +.pointer { + cursor: pointer; +} + +.draggable { + cursor: grab; +} + +.draggable:active { + cursor: grabbing; +} + +/* used for perceivedSeverity: major in the alarm list */ +.table-major { + background-color: var(--major) !important; +} + +/* for ng-bootstraps nav tabs in the alarm details. Hovering over elements looks weird otherwise */ +.no-border-hover:hover > a { + border-bottom: none !important; +} + +/* Prevent [sort icons] from breaking into a new line in table headers */ +th { + white-space: nowrap; +} + +/* Override calc() to achieve same height of inputs and buttons */ +.form-control { + height: auto !important; +} +.active-badge { + box-shadow: 0 0 2pt 2pt var(--light-blue); +} + +.badge { + font-size: 100% !important; +} + +.badge-major { + color: var(--dark); + background-color: var(--major); +} + +/* Context menu overrides */ +.ngx-contextmenu { + box-shadow: 0 0 17px 0 rgba(0, 0, 0, 0.59); +} +.ngx-contextmenu > .dropdown-menu > li > a:hover { + text-decoration: none !important; +} + +.border-radius { + border-radius: 0.25rem !important; +} + +.form-control.is-invalid, +.was-validated .form-control:valid { + background-image: url('assets/images/icons/triangular-warning-sign.svg') !important; + background-position: right calc(0.75em + 0.1875rem) center !important; +} + +.no-border { + border: none !important; +} +.border-gray { + border: 1px solid var(--gray); +} + +.btn-outline-secondary { + color: var(--dark-gray) !important; + border-color: var(--dark-gray) !important; +} +.btn-outline-secondary:hover, +.btn-outline-secondary:focus, +.btn-outline-secondary:not(:focus), +.btn-outline-secondary:active { + color: var(--gray-dark) !important; + background-color: var(--light-gray) !important; + border-color: var(--light-gray) !important; +} + +.node-content-wrapper, +.tree-children { + position: relative; +} + +.node-content-wrapper::before, +.tree-children::after { + content: ''; + position: absolute; +} + +.node-content-wrapper::before { + height: 28px; + top: -13px; + width: 20px; + left: -26px; +} + +.tree-node-level-1 > tree-node-wrapper > .node-wrapper > .node-content-wrapper::before { + display: none; +} + +.tree-node-leaf > .node-wrapper > .node-content-wrapper::before { + width: 25px; +} + +.tree-children::after { + height: 100%; + top: -15px; + left: 6px; +} + +.toggle-children-placeholder { + width: 13px !important; +} + +tree-node:last-child > .tree-node > .tree-children::after { + border-left: none; +} + +.toggle-children-wrapper { + padding: 2px 3px 5px 0; +} + +.toggle-children { + z-index: 1; + width: 11px !important; + height: 11px !important; +} + +.toggle-children-wrapper-expanded .toggle-children { + top: 1px; + left: 1px; +} + +.attribute-pane-title { + color: var(--primary); + max-width: 60%; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap !important; + display: inline-block; + margin-top: 0 !important; + margin-bottom: 0 !important; +} + +.mr-15-px { + margin-right: 15px; +} + +.bg-color-blue { + background-color: var(--light-blue); +} + +/* styling for switch that we are using in attribute pane for showing and hiding the attributes */ +/* ------------------------------------------------------------------------------------- */ +.attribute-pane-switch { + height: 0; + width: 0; + visibility: hidden; +} + +.label-for-switch { + cursor: pointer; + text-align: -9999px; + width: 40px; + height: 20px; + background: var(--active-gray); + display: block; + border-radius: 100px; + position: relative; + border: 1px solid var(--primary); +} + +.label-for-switch::after { + content: ''; + position: absolute; + top: 0; + left: 1px; + width: 18px; + height: 18px; + background: var(--primary); + border-radius: 90px; + transition: 0.3s; +} + +#switch:checked + .label-for-switch { + background: var(--primary); +} + +#switch:checked + .label-for-switch:after { + right: calc(18px - 1px); + transform: translateX(100%); + background: var(--active-gray); +} + +.label-for-switch:active:after { + width: 18px; +} + +.text-for-switch { + font-size: 11px; +} +/* ------------------------------------------------------------------------------------- */ + +.toggle-children-wrapper-collapsed .toggle-children, +.toggle-children-wrapper-expanded .toggle-children { + top: 2.4px; +} +.node-custom-content-wrapper { + padding: 2px 5px !important; +} +.node-content-wrapper{ + padding: 0 !important; +} + +/* Display definition lists in a tabular style */ +/* https://stackoverflow.com/questions/1687733/what-html-markups-to-use-for-displaying-label-value-data#1687759 */ +dt { float: left; clear: left; width: 6em; font-weight: bold; } +.ml-2px{ + margin-left: 2px; +} +.overflow-y-scroll{ + overflow-y: scroll; +} + +.alarm-color-critical-outline { + color: var(--white); + background-color: var(--danger) !important; +} +.alarm-color-cleared-outline { + color: var(--black); + border: 1px solid var(--black); +} + +.alarm-color-major-outline { + border: 1px solid var(--major); + color: var(--major); +} + +.alarm-color-minor-outline { + border: 1px solid var(--minor); + color: var(--minor); +} + +.alarm-color-warning-outline { + color: var(--intense-blue); + border: 1px solid var(--intense-blue); +} + +.alarm-color-indeterminate-outline { + border: 1px solid var(--secondary); + color: var(--secondary); +} + +.leaflet-div-icon-hide { + background: none; + border: none; +} + +.alarm-severity-counter { + background-color: white; + border-radius: 4px; + margin: 0 2px; + padding: 0 0.25rem !important; +} + +.bc-icon { + color: var(--primary); +} + +.hover-bg-gray:hover { + background-color: rgb(237, 237, 237); + width: 100% !important; +} + +.pulse{ + z-index: 10!important; + height: 180px; + width: 180px; + background: linear-gradient( + var(--danger), + #d97e87 + ); + position: absolute; + margin: auto; + left: 0; + right: 0; + top: 0; + bottom: 0; + border-radius: 50%; + display: grid; + place-items: center; + font-size: 50px; + color: #ffffff; +} +.pulse:before, +.pulse:after{ + content: ""; + position: absolute; + height: 100%; + width: 100%; + background-color: var(--danger); + border-radius: 50%; + z-index: -1; + opacity: 0.7; +} +.pulse:before{ + animation: pulse 2s ease-out infinite; +} +.pulse:after{ + animation: pulse 2s 1s ease-out infinite; +} +@keyframes pulse{ + 100%{ + transform: scale(2.5); + opacity: 0; + } +} +tree-viewport{ + overflow-x: auto !important; + display: flex !important; +} +.node-content-wrapper{ + border: 1px solid rgba(0,0,0,0); +} +.node-content-wrapper-focused, .node-content-wrapper-focused:hover{ + border: 1px solid var(--primary); +} + +.backdropClass{ + z-index: 1050 !important; +} + +.table > :not(:first-child) { + border-top: none !important; +} + +.leaflet-top, +.leaflet-bottom { + z-index: 998 !important; + } + +.btn-invisible:focus { + border: 2px solid black; + border-radius: 4px; + outline: 0; +} + +/*override onap styles*/ +.btn-secondary:focus { + background-color: #5c636a !important; + border-color: #565e64 !important; +} + +.close:not(:disabled):not(.disabled) { + cursor: pointer; +} + +.close::before { + display: block; + width: 16px; + height: 16px; + content: " "; + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M15.81,14.99l-6.99-7l6.99-7c0.24-0.24,0.2-0.63-0.04-0.83c-0.24-0.2-0.59-0.2-0.79,0l-6.99,7l-6.99-7 C0.75-0.08,0.36-0.04,0.16,0.2c-0.2,0.24-0.2,0.59,0,0.79l6.99,7l-6.99,7c-0.24,0.24-0.2,0.63,0.04,0.83c0.24,0.2,0.59,0.2,0.79,0 l6.99-7l6.99,7c0.24,0.24,0.59,0.24,0.83,0.04C16.04,15.66,16.08,15.26,15.81,14.99C15.85,15.03,15.81,15.03,15.81,14.99z' fill='%23262626'/%3E%3C/svg%3E"); +} diff --git a/src/test.ts b/src/test.ts new file mode 100644 index 0000000..36b9be6 --- /dev/null +++ b/src/test.ts @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +// This file is required by karma.conf.js and loads recursively all the .spec and framework files + +import 'zone.js/testing'; +import { getTestBed } from '@angular/core/testing'; +import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; + +declare const require: { + context( + path: string, + deep?: boolean, + filter?: RegExp, + ): { + keys(): string[]; + <T>(id: string): T; + }; +}; + +// First, initialize the Angular testing environment. +getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting()); +// Then we find all the tests. +const context = require.context('./', true, /\.spec\.ts$/); +// And load the modules. +context.keys().forEach(context); |