diff --git a/Frontend/karma.conf.js b/Frontend/karma.conf.js index 74211c5..4a72f2c 100644 --- a/Frontend/karma.conf.js +++ b/Frontend/karma.conf.js @@ -2,32 +2,35 @@ // https://karma-runner.github.io/1.0/config/configuration-file.html module.exports = function (config) { - config.set({ - basePath: '', - frameworks: ['jasmine', '@angular-devkit/build-angular'], - plugins: [ - require('karma-jasmine'), - require('karma-firefox-launcher'), - require('karma-chrome-launcher'), - require('karma-jasmine-html-reporter'), - require('karma-coverage-istanbul-reporter'), - require('@angular-devkit/build-angular/plugins/karma') - ], - client: { - clearContext: false // leave Jasmine Spec Runner output visible in browser - }, - coverageIstanbulReporter: { - dir: require('path').join(__dirname, './coverage/Betterzon'), - reports: ['html', 'lcovonly', 'text-summary'], - fixWebpackSourcePaths: true - }, - reporters: ['progress', 'kjhtml'], - port: 9876, - colors: true, - logLevel: config.LOG_INFO, - autoWatch: true, - browsers: ['Firefox'], - singleRun: false, - restartOnFileChange: true - }); + config.set({ + basePath: '', + frameworks: ['jasmine', '@angular-devkit/build-angular'], + plugins: [ + require('karma-jasmine'), + require('karma-firefox-launcher'), + require('karma-chrome-launcher'), + require('karma-jasmine-html-reporter'), + require('karma-coverage-istanbul-reporter'), + require('@angular-devkit/build-angular/plugins/karma') + ], + client: { + clearContext: false, // leave Jasmine Spec Runner output visible in browser + jasmine: { + random: false + } + }, + coverageIstanbulReporter: { + dir: require('path').join(__dirname, './coverage/Betterzon'), + reports: ['html', 'lcovonly', 'text-summary'], + fixWebpackSourcePaths: true + }, + reporters: ['progress', 'kjhtml'], + port: 9876, + colors: true, + logLevel: config.LOG_INFO, + autoWatch: true, + browsers: ['Firefox'], + singleRun: false, + restartOnFileChange: true + }); }; diff --git a/Frontend/src/app/app.component.css b/Frontend/src/app/app.component.css index 9e7b8b4..175325c 100644 --- a/Frontend/src/app/app.component.css +++ b/Frontend/src/app/app.component.css @@ -1,9 +1,10 @@ .wrapper_app { - padding-bottom: 2.5rem; /* Footer height */ + padding-bottom: 2.5rem; /* Footer height */ } + .footer_app { position: relative; bottom: 0; width: 100%; - height: 2.5rem; /* Footer height */ + height: 2.5rem; /* Footer height */ } diff --git a/Frontend/src/app/app.component.spec.ts b/Frontend/src/app/app.component.spec.ts index a309d0b..702527d 100644 --- a/Frontend/src/app/app.component.spec.ts +++ b/Frontend/src/app/app.component.spec.ts @@ -1,8 +1,8 @@ import {TestBed} from '@angular/core/testing'; import {AppComponent} from './app.component'; -import {RouterTestingModule} from "@angular/router/testing"; -import {NgcCookieConsentConfig, NgcCookieConsentModule} from "ngx-cookieconsent"; -import {FormsModule} from "@angular/forms"; +import {RouterTestingModule} from '@angular/router/testing'; +import {NgcCookieConsentConfig, NgcCookieConsentModule} from 'ngx-cookieconsent'; +import {FormsModule} from '@angular/forms'; // For cookie consent module testing const cookieConfig: NgcCookieConsentConfig = { diff --git a/Frontend/src/app/app.component.ts b/Frontend/src/app/app.component.ts index f65d28c..0941258 100644 --- a/Frontend/src/app/app.component.ts +++ b/Frontend/src/app/app.component.ts @@ -1,7 +1,7 @@ import {Component, OnDestroy, OnInit} from '@angular/core'; import {NgcCookieConsentService, NgcInitializeEvent, NgcNoCookieLawEvent, NgcStatusChangeEvent} from 'ngx-cookieconsent'; import {Subscription} from 'rxjs'; -import {ApiService} from "./services/api.service"; +import {ApiService} from './services/api.service'; @Component({ @@ -26,8 +26,7 @@ export class AppComponent implements OnInit, OnDestroy { username?: string; constructor( - private ccService: NgcCookieConsentService, - private api: ApiService + private ccService: NgcCookieConsentService ) { } diff --git a/Frontend/src/app/app.module.ts b/Frontend/src/app/app.module.ts index 153ae2c..9d9af0a 100644 --- a/Frontend/src/app/app.module.ts +++ b/Frontend/src/app/app.module.ts @@ -23,23 +23,23 @@ import {NgcCookieConsentModule, NgcCookieConsentConfig} from 'ngx-cookieconsent' import {MatSlideToggleModule} from '@angular/material/slide-toggle'; import {TopBarComponent} from './components/top-bar/top-bar.component'; import {RouterModule} from '@angular/router'; -import {MatButtonModule} from "@angular/material/button"; +import {MatButtonModule} from '@angular/material/button'; import {MatToolbarModule} from '@angular/material/toolbar'; import {MatIconModule} from '@angular/material/icon'; import {MatSidenavModule} from '@angular/material/sidenav'; -import {MatListModule} from "@angular/material/list"; +import {MatListModule} from '@angular/material/list'; import {BottomBarComponent} from './components/bottom-bar/bottom-bar.component'; -import { HotDealsWidgetComponent } from './components/hot-deals-widget/hot-deals-widget.component'; -import { SliderForProductsComponent } from './components/slider-for-products/slider-for-products.component'; -import { RegistrationComponent } from './components/auth/registration/registration.component'; -import { MatCardModule } from "@angular/material/card"; -import {SigninComponent} from "./components/auth/signin/signin.component"; -import { CopyrightComponent } from './components/copyright/copyright.component'; -import { GreetingInfoSliderComponent } from './components/greeting-info-slider/greeting-info-slider.component'; -import { KundenComponent } from './components/kunden/kunden.component'; -import { AboutUsComponent } from './components/about-us/about-us.component'; -import { ProfileComponent } from './components/profile/profile.component'; -import { ProfilePageComponent } from './pages/profile-page/profile-page.component'; +import {HotDealsWidgetComponent} from './components/hot-deals-widget/hot-deals-widget.component'; +import {SliderForProductsComponent} from './components/slider-for-products/slider-for-products.component'; +import {RegistrationComponent} from './components/auth/registration/registration.component'; +import {MatCardModule} from '@angular/material/card'; +import {SigninComponent} from './components/auth/signin/signin.component'; +import {CopyrightComponent} from './components/copyright/copyright.component'; +import {GreetingInfoSliderComponent} from './components/greeting-info-slider/greeting-info-slider.component'; +import {KundenComponent} from './components/kunden/kunden.component'; +import {AboutUsComponent} from './components/about-us/about-us.component'; +import {ProfileComponent} from './pages/profile/profile.component'; +import {ProfilePageComponent} from './pages/profile-page/profile-page.component'; // For cookie popup const cookieConfig: NgcCookieConsentConfig = { diff --git a/Frontend/src/app/app.routing.ts b/Frontend/src/app/app.routing.ts index 2e13ded..0582366 100644 --- a/Frontend/src/app/app.routing.ts +++ b/Frontend/src/app/app.routing.ts @@ -9,10 +9,10 @@ import {ProductSearchPageComponent} from './pages/product-search-page/product-se import {PageNotFoundPageComponent} from './pages/page-not-found-page/page-not-found-page.component'; import {ImprintComponent} from './pages/imprint/imprint.component'; import {PrivacyComponent} from './pages/privacy/privacy.component'; -import {SigninComponent} from "./components/auth/signin/signin.component"; -import {RegistrationComponent} from "./components/auth/registration/registration.component"; -import {ProfileComponent} from "./components/profile/profile.component"; -import {ProfilePageComponent} from "./pages/profile-page/profile-page.component"; +import {SigninComponent} from './components/auth/signin/signin.component'; +import {RegistrationComponent} from './components/auth/registration/registration.component'; +import {ProfileComponent} from './pages/profile/profile.component'; +import {ProfilePageComponent} from './pages/profile-page/profile-page.component'; const routes: Routes = [ {path: '', component: LandingpageComponent, pathMatch: 'full'}, @@ -22,8 +22,8 @@ const routes: Routes = [ {path: 'datenschutz', component: PrivacyComponent}, {path: 'signin', component: SigninComponent}, {path: 'registration', component: RegistrationComponent}, - {path: "product-detail", component: ProductDetailPageComponent}, - {path: "profile", component: ProfilePageComponent}, + {path: 'product-detail', component: ProductDetailPageComponent}, + {path: 'profile', component: ProfilePageComponent}, {path: '**', component: PageNotFoundPageComponent} ]; diff --git a/Frontend/src/app/components/about-us/about-us.component.html b/Frontend/src/app/components/about-us/about-us.component.html index 55befbc..615befe 100644 --- a/Frontend/src/app/components/about-us/about-us.component.html +++ b/Frontend/src/app/components/about-us/about-us.component.html @@ -10,8 +10,10 @@
-

You follow the same passion as we do and you want to find alternatives to the de-facto monopolist Amazon?

-

In this case, welcome aboard! We’re happy that you share our passion and hope that we can help you achieving this goal with the website.

+

You follow the same passion as we do and you want to find + alternatives to the de-facto monopolist Amazon?

+

In this case, welcome aboard! We’re happy that you share our + passion and hope that we can help you achieving this goal with the website.

diff --git a/Frontend/src/app/components/about-us/about-us.component.spec.ts b/Frontend/src/app/components/about-us/about-us.component.spec.ts index b1910ef..50db267 100644 --- a/Frontend/src/app/components/about-us/about-us.component.spec.ts +++ b/Frontend/src/app/components/about-us/about-us.component.spec.ts @@ -1,25 +1,25 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; -import { AboutUsComponent } from './about-us.component'; +import {AboutUsComponent} from './about-us.component'; describe('AboutUsComponent', () => { - let component: AboutUsComponent; - let fixture: ComponentFixture; + let component: AboutUsComponent; + let fixture: ComponentFixture; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ AboutUsComponent ] - }) - .compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [AboutUsComponent] + }) + .compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(AboutUsComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(AboutUsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/Frontend/src/app/components/auth/auth-routing.module.ts b/Frontend/src/app/components/auth/auth-routing.module.ts index 53cfa71..6347a9a 100644 --- a/Frontend/src/app/components/auth/auth-routing.module.ts +++ b/Frontend/src/app/components/auth/auth-routing.module.ts @@ -1,8 +1,8 @@ -import { NgModule } from '@angular/core'; -import { Routes, RouterModule } from '@angular/router'; -import {RegistrationComponent} from "./registration/registration.component"; -import {SigninComponent} from "./signin/signin.component"; -import {ResetpasswortComponent} from "./resetpasswort/resetpasswort.component"; +import {NgModule} from '@angular/core'; +import {Routes, RouterModule} from '@angular/router'; +import {RegistrationComponent} from './registration/registration.component'; +import {SigninComponent} from './signin/signin.component'; +import {ResetpasswortComponent} from './resetpasswort/resetpasswort.component'; const routes: Routes = [ { @@ -20,7 +20,8 @@ const routes: Routes = [ ]; @NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule] + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] }) -export class AuthRoutingModule { } +export class AuthRoutingModule { +} diff --git a/Frontend/src/app/components/auth/auth.module.ts b/Frontend/src/app/components/auth/auth.module.ts index ad5368f..294110f 100644 --- a/Frontend/src/app/components/auth/auth.module.ts +++ b/Frontend/src/app/components/auth/auth.module.ts @@ -1,22 +1,23 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; -import { AuthRoutingModule } from './auth-routing.module'; -import { SigninComponent } from "./signin/signin.component"; -import { RegistrationComponent } from './registration/registration.component'; -import { ResetpasswortComponent } from './resetpasswort/resetpasswort.component'; +import {AuthRoutingModule} from './auth-routing.module'; +import {SigninComponent} from './signin/signin.component'; +import {RegistrationComponent} from './registration/registration.component'; +import {ResetpasswortComponent} from './resetpasswort/resetpasswort.component'; @NgModule({ - declarations: [SigninComponent, RegistrationComponent, ResetpasswortComponent], - imports: [ - CommonModule, - AuthRoutingModule, - ], - exports: [ - SigninComponent, - RegistrationComponent, - ResetpasswortComponent, - ], + declarations: [SigninComponent, RegistrationComponent, ResetpasswortComponent], + imports: [ + CommonModule, + AuthRoutingModule, + ], + exports: [ + SigninComponent, + RegistrationComponent, + ResetpasswortComponent, + ], }) -export class AuthModule { } +export class AuthModule { +} diff --git a/Frontend/src/app/components/auth/registration/registration.component.css b/Frontend/src/app/components/auth/registration/registration.component.css index 6de2e1b..7885071 100644 --- a/Frontend/src/app/components/auth/registration/registration.component.css +++ b/Frontend/src/app/components/auth/registration/registration.component.css @@ -1,11 +1,12 @@ -.main-content{ +.main-content { width: 50%; border-radius: 20px; - box-shadow: 0 5px 5px rgba(0,0,0,.4); + box-shadow: 0 5px 5px rgba(0, 0, 0, .4); margin: 5em auto; display: flex; } -.company__info{ + +.company__info { background-color: #008080; border-top-left-radius: 20px; border-bottom-left-radius: 20px; @@ -14,63 +15,79 @@ justify-content: center; color: #fff; } -.fa-android{ - font-size:3em; + +.fa-android { + font-size: 3em; } + @media screen and (max-width: 640px) { - .main-content{width: 90%;} - .company__info{ + .main-content { + width: 90%; + } + + .company__info { display: none; } - .login_form{ - border-top-left-radius:20px; - border-bottom-left-radius:20px; + + .login_form { + border-top-left-radius: 20px; + border-bottom-left-radius: 20px; } } -@media screen and (min-width: 642px) and (max-width:800px){ - .main-content{width: 70%;} + +@media screen and (min-width: 642px) and (max-width: 800px) { + .main-content { + width: 70%; + } } -.row > h2{ - color:#008080; + +.row > h2 { + color: #008080; } -.login_form{ + +.login_form { background-color: #fff; - border-top-right-radius:20px; - border-bottom-right-radius:20px; - border-top:1px solid #ccc; - border-right:1px solid #ccc; + border-top-right-radius: 20px; + border-bottom-right-radius: 20px; + border-top: 1px solid #ccc; + border-right: 1px solid #ccc; } -form{ + +form { padding: 0 2em; } -.form__input{ + +.form__input { width: 100%; - border:0px solid transparent; + border: 0px solid transparent; border-radius: 0; border-bottom: 1px solid #aaa; padding: 1em .5em .5em; padding-left: 2em; - outline:none; - margin:1.5em auto; + outline: none; + margin: 1.5em auto; transition: all .5s ease; } -.form__input:focus{ + +.form__input:focus { border-bottom-color: #008080; - box-shadow: 0 0 5px rgba(0,80,80,.4); + box-shadow: 0 0 5px rgba(0, 80, 80, .4); border-radius: 4px; } -.btn_signin{ + +.btn_signin { transition: all .5s ease; width: 100%; border-radius: 30px; - color:#008080; + color: #008080; font-weight: 600; background-color: #fff; border: 1px solid #008080; margin-top: 1.5em; margin-bottom: 1em; } -.btn_signin:hover, .btn:focus{ + +.btn_signin:hover, .btn:focus { background-color: #008080; - color:#fff; + color: #fff; } diff --git a/Frontend/src/app/components/auth/registration/registration.component.html b/Frontend/src/app/components/auth/registration/registration.component.html index e203b31..5c22b82 100644 --- a/Frontend/src/app/components/auth/registration/registration.component.html +++ b/Frontend/src/app/components/auth/registration/registration.component.html @@ -11,18 +11,21 @@
- +
Username is required
- +
- +
- +
diff --git a/Frontend/src/app/components/auth/signin/signin.component.spec.ts b/Frontend/src/app/components/auth/signin/signin.component.spec.ts index b19d8bf..813162a 100644 --- a/Frontend/src/app/components/auth/signin/signin.component.spec.ts +++ b/Frontend/src/app/components/auth/signin/signin.component.spec.ts @@ -1,25 +1,54 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; -import { SigninComponent } from './signin.component'; +import {SigninComponent} from './signin.component'; +import {AbstractMockObservableService} from '../../../mocks/mock.service'; +import {ApiService} from '../../../services/api.service'; +import {FormBuilder, FormControl, Validators} from '@angular/forms'; +import {Router} from '@angular/router'; + +class MockApiService extends AbstractMockObservableService { + loginUser(username: string, password: string): any { + this.content = []; + return this; + } +} describe('SigninComponent', () => { - let component: SigninComponent; - let fixture: ComponentFixture; + let component: SigninComponent; + let fixture: ComponentFixture; + let mockService; + let formBuilder: FormBuilder; + const router = { + navigate: jasmine.createSpy('navigate'), + routerState: jasmine.createSpy('routerState') + }; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ SigninComponent ] - }) - .compileComponents(); - }); + beforeEach(async () => { + mockService = new MockApiService(); + await TestBed.configureTestingModule({ + declarations: [SigninComponent], + providers: [{provide: ApiService, useValue: mockService}, {provide: Router, useValue: router}, FormBuilder] + }) + .compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(SigninComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(SigninComponent); + component = fixture.componentInstance; + formBuilder = TestBed.get(FormBuilder); + component.loginForm = formBuilder.group({ + recipientTypes: new FormControl( + { + value: ['mock'], + disabled: true + }, + Validators.required + ) + }); + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/Frontend/src/app/components/bottom-bar/bottom-bar.component.css b/Frontend/src/app/components/bottom-bar/bottom-bar.component.css index fc3459c..b684088 100644 --- a/Frontend/src/app/components/bottom-bar/bottom-bar.component.css +++ b/Frontend/src/app/components/bottom-bar/bottom-bar.component.css @@ -7,12 +7,14 @@ } .folge-uns-item { - grid-column: 2; grid-row: 1; + grid-column: 2; + grid-row: 1; justify-self: center; } .link-items { - grid-column: 2; grid-row: 2; + grid-column: 2; + grid-row: 2; justify-self: center; } @@ -29,11 +31,13 @@ } .bottom-logo { - grid-column: 1; grid-row: 3; + grid-column: 1; + grid-row: 3; } .bottom-info { - grid-column: 3; grid-row: 3; + grid-column: 3; + grid-row: 3; justify-self: right; } diff --git a/Frontend/src/app/components/bottom-bar/bottom-bar.component.html b/Frontend/src/app/components/bottom-bar/bottom-bar.component.html index 2b4fc09..fd6a8c5 100644 --- a/Frontend/src/app/components/bottom-bar/bottom-bar.component.html +++ b/Frontend/src/app/components/bottom-bar/bottom-bar.component.html @@ -6,15 +6,17 @@

Location

76133 Karlsruhe -
+

FOLLOW US

- - + +
diff --git a/Frontend/src/app/components/bottom-bar/bottom-bar.component.spec.ts b/Frontend/src/app/components/bottom-bar/bottom-bar.component.spec.ts index 0181062..f381b2d 100644 --- a/Frontend/src/app/components/bottom-bar/bottom-bar.component.spec.ts +++ b/Frontend/src/app/components/bottom-bar/bottom-bar.component.spec.ts @@ -1,25 +1,25 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; -import { BottomBarComponent } from "./bottom-bar.component"; +import {BottomBarComponent} from './bottom-bar.component'; -describe("BottomBarComponent", () => { - let component: BottomBarComponent; - let fixture: ComponentFixture; +describe('BottomBarComponent', () => { + let component: BottomBarComponent; + let fixture: ComponentFixture; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ BottomBarComponent ] - }) - .compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [BottomBarComponent] + }) + .compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(BottomBarComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(BottomBarComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/Frontend/src/app/components/copyright/copyright.component.css b/Frontend/src/app/components/copyright/copyright.component.css index e69de29..81713a1 100644 --- a/Frontend/src/app/components/copyright/copyright.component.css +++ b/Frontend/src/app/components/copyright/copyright.component.css @@ -0,0 +1,24 @@ +#imprintSection { + right: 1em; + bottom: 1em; + width: 100%; + text-align: right; + padding-right: 1em; + grid-area: right; +} + +#imprintSection a { + color: white; + text-decoration: none; +} + +#copyright { + display: grid; + grid-template-areas: + 'left center right'; + grid-template-columns: 30% 40% 30%; +} + +#copyright-text { + grid-area: center; +} diff --git a/Frontend/src/app/components/copyright/copyright.component.html b/Frontend/src/app/components/copyright/copyright.component.html index a9545ed..b8044c5 100644 --- a/Frontend/src/app/components/copyright/copyright.component.html +++ b/Frontend/src/app/components/copyright/copyright.component.html @@ -1,3 +1,7 @@ - - +
diff --git a/Frontend/src/app/components/greeting-info-slider/greeting-info-slider.component.html b/Frontend/src/app/components/greeting-info-slider/greeting-info-slider.component.html index dfc774e..4e36064 100644 --- a/Frontend/src/app/components/greeting-info-slider/greeting-info-slider.component.html +++ b/Frontend/src/app/components/greeting-info-slider/greeting-info-slider.component.html @@ -1,7 +1,7 @@
- ... + ...

diff --git a/Frontend/src/app/components/greeting-info-slider/greeting-info-slider.component.spec.ts b/Frontend/src/app/components/greeting-info-slider/greeting-info-slider.component.spec.ts index dfe17d1..f4d3bef 100644 --- a/Frontend/src/app/components/greeting-info-slider/greeting-info-slider.component.spec.ts +++ b/Frontend/src/app/components/greeting-info-slider/greeting-info-slider.component.spec.ts @@ -1,25 +1,25 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; -import { GreetingInfoSliderComponent } from './greeting-info-slider.component'; +import {GreetingInfoSliderComponent} from './greeting-info-slider.component'; describe('GreetingInfoSliderComponent', () => { - let component: GreetingInfoSliderComponent; - let fixture: ComponentFixture; + let component: GreetingInfoSliderComponent; + let fixture: ComponentFixture; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ GreetingInfoSliderComponent ] - }) - .compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [GreetingInfoSliderComponent] + }) + .compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(GreetingInfoSliderComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(GreetingInfoSliderComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/Frontend/src/app/components/header/header.component.html b/Frontend/src/app/components/header/header.component.html index b1a315a..da0aa7a 100644 --- a/Frontend/src/app/components/header/header.component.html +++ b/Frontend/src/app/components/header/header.component.html @@ -5,7 +5,8 @@ Betterzon Logo
dark me diff --git a/Frontend/src/app/components/hot-deals-widget/hot-deals-widget.component.html b/Frontend/src/app/components/hot-deals-widget/hot-deals-widget.component.html index 3374f51..639a671 100644 --- a/Frontend/src/app/components/hot-deals-widget/hot-deals-widget.component.html +++ b/Frontend/src/app/components/hot-deals-widget/hot-deals-widget.component.html @@ -9,26 +9,33 @@
-
+
-
+
{{productsPricesMap[productId]?.product?.name}}
-
Amazon: {{productsPricesMap[productId]?.amazonPrice?.price_in_cents/100}}€
+
Amazon: {{productsPricesMap[productId]?.amazonPrice?.price_in_cents / 100}} + €
-
{{productsPricesMap[productId]?.vendor?.name}}: {{productsPricesMap[productId]?.lowestPrice?.price_in_cents/100}}€
+
{{productsPricesMap[productId]?.vendor?.name}}: {{productsPricesMap[productId]?.lowestPrice?.price_in_cents / 100}} + €
-
+
diff --git a/Frontend/src/app/components/hot-deals-widget/hot-deals-widget.component.spec.ts b/Frontend/src/app/components/hot-deals-widget/hot-deals-widget.component.spec.ts index 9826e63..b9bec22 100644 --- a/Frontend/src/app/components/hot-deals-widget/hot-deals-widget.component.spec.ts +++ b/Frontend/src/app/components/hot-deals-widget/hot-deals-widget.component.spec.ts @@ -1,25 +1,58 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; -import { HotDealsWidgetComponent } from './hot-deals-widget.component'; +import {HotDealsWidgetComponent} from './hot-deals-widget.component'; +import {AbstractMockObservableService} from '../../mocks/mock.service'; +import {ApiService} from '../../services/api.service'; +import {ActivatedRoute, convertToParamMap, Router} from '@angular/router'; +import {Observable, of} from 'rxjs'; + +class MockApiService extends AbstractMockObservableService { + getBestDeals(): any { + this.content = []; + return this; + } + + getProductsByIds(): any { + this.content = []; + return this; + } +} + +class ActivatedRouteMock { + public paramMap = of(convertToParamMap({ + testId: 'abc123', + anotherId: 'd31e8b48-7309-4c83-9884-4142efdf7271', + })); +} describe('HotDealsWidgetComponent', () => { - let component: HotDealsWidgetComponent; - let fixture: ComponentFixture; + let component: HotDealsWidgetComponent; + let fixture: ComponentFixture; + let mockService; + const router = { + navigate: jasmine.createSpy('navigate'), + routerState: jasmine.createSpy('routerState') + }; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ HotDealsWidgetComponent ] - }) - .compileComponents(); - }); + beforeEach(async () => { + mockService = new MockApiService(); + await TestBed.configureTestingModule({ + declarations: [HotDealsWidgetComponent], + providers: [{provide: ApiService, useValue: mockService}, {provide: Router, useValue: router}, { + provide: ActivatedRoute, + useValue: ActivatedRouteMock + }] + }) + .compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(HotDealsWidgetComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(HotDealsWidgetComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/Frontend/src/app/components/kunden/kunden.component.html b/Frontend/src/app/components/kunden/kunden.component.html index e59447c..13bbb89 100644 --- a/Frontend/src/app/components/kunden/kunden.component.html +++ b/Frontend/src/app/components/kunden/kunden.component.html @@ -12,7 +12,8 @@
-
+
@@ -20,7 +21,8 @@
-
+
@@ -28,7 +30,8 @@
-
+
diff --git a/Frontend/src/app/components/kunden/kunden.component.spec.ts b/Frontend/src/app/components/kunden/kunden.component.spec.ts index 3977b33..b413c12 100644 --- a/Frontend/src/app/components/kunden/kunden.component.spec.ts +++ b/Frontend/src/app/components/kunden/kunden.component.spec.ts @@ -1,25 +1,53 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; -import { KundenComponent } from './kunden.component'; +import {KundenComponent} from './kunden.component'; +import {AbstractMockObservableService} from '../../mocks/mock.service'; +import {ApiService} from '../../services/api.service'; +import {ActivatedRoute, convertToParamMap, Router} from '@angular/router'; +import {of} from 'rxjs'; + +class MockApiService extends AbstractMockObservableService { + getProducts(): any { + this.content = []; + return this; + } +} + +class ActivatedRouteMock { + public paramMap = of(convertToParamMap({ + testId: 'abc123', + anotherId: 'd31e8b48-7309-4c83-9884-4142efdf7271', + })); +} describe('KundenComponent', () => { - let component: KundenComponent; - let fixture: ComponentFixture; + let component: KundenComponent; + let fixture: ComponentFixture; + let mockService; + const router = { + navigate: jasmine.createSpy('navigate'), + routerState: jasmine.createSpy('routerState') + }; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ KundenComponent ] - }) - .compileComponents(); - }); + beforeEach(async () => { + mockService = new MockApiService(); + await TestBed.configureTestingModule({ + declarations: [KundenComponent], + providers: [{provide: ApiService, useValue: mockService}, {provide: Router, useValue: router}, { + provide: ActivatedRoute, + useValue: ActivatedRouteMock + }] + }) + .compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(KundenComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(KundenComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/Frontend/src/app/components/product-details/product-details.component.spec.ts b/Frontend/src/app/components/product-details/product-details.component.spec.ts index bcd489d..02c06f0 100644 --- a/Frontend/src/app/components/product-details/product-details.component.spec.ts +++ b/Frontend/src/app/components/product-details/product-details.component.spec.ts @@ -58,6 +58,11 @@ class MockApiService extends AbstractMockObservableService { this.content = [vendor]; return this; } + + getSessionInfoFromLocalStorage(): any { + this.content = []; + return this; + } } describe('ProductDetailsComponent', () => { diff --git a/Frontend/src/app/components/product-list/product-list.component.html b/Frontend/src/app/components/product-list/product-list.component.html index 5c26ab9..725c674 100644 --- a/Frontend/src/app/components/product-list/product-list.component.html +++ b/Frontend/src/app/components/product-list/product-list.component.html @@ -5,43 +5,49 @@
-
+
+
{{product.name}}

{{product.short_description}}

-

-

+

+

-

${{pricesMap[product.product_id]?.price_in_cents/100}}

+

${{pricesMap[product.product_id]?.price_in_cents / 100}}

+
+
+
-
-
- + --> diff --git a/Frontend/src/app/components/product-list/product-list.component.spec.ts b/Frontend/src/app/components/product-list/product-list.component.spec.ts index 46b10a1..f399543 100644 --- a/Frontend/src/app/components/product-list/product-list.component.spec.ts +++ b/Frontend/src/app/components/product-list/product-list.component.spec.ts @@ -70,7 +70,8 @@ describe('ProductListComponent', () => { last_modified: new Date(), manufacturer_id: 1, selling_rank: '1', - category_id: 1 + category_id: 1, + price: 0 }; component.clickedProduct(product); diff --git a/Frontend/src/app/components/product-list/product-list.component.ts b/Frontend/src/app/components/product-list/product-list.component.ts index 1f1bdd3..aab4ac1 100644 --- a/Frontend/src/app/components/product-list/product-list.component.ts +++ b/Frontend/src/app/components/product-list/product-list.component.ts @@ -79,7 +79,7 @@ export class ProductListComponent implements OnInit { this.getPrices(); }); } - + clickedProduct(product: Product): void { this.router.navigate([('/product/' + product.product_id)]); } diff --git a/Frontend/src/app/components/profile/profile.component.spec.ts b/Frontend/src/app/components/profile/profile.component.spec.ts deleted file mode 100644 index e88012e..0000000 --- a/Frontend/src/app/components/profile/profile.component.spec.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { ProfileComponent } from './profile.component'; - -describe('ProfileComponent', () => { - let component: ProfileComponent; - let fixture: ComponentFixture; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ ProfileComponent ] - }) - .compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(ProfileComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/Frontend/src/app/components/slider-for-products/slider-for-products.component.spec.ts b/Frontend/src/app/components/slider-for-products/slider-for-products.component.spec.ts index f051463..d992e33 100644 --- a/Frontend/src/app/components/slider-for-products/slider-for-products.component.spec.ts +++ b/Frontend/src/app/components/slider-for-products/slider-for-products.component.spec.ts @@ -1,25 +1,25 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; -import { SliderForProductsComponent } from './slider-for-products.component'; +import {SliderForProductsComponent} from './slider-for-products.component'; describe('SliderForProductsComponent', () => { - let component: SliderForProductsComponent; - let fixture: ComponentFixture; + let component: SliderForProductsComponent; + let fixture: ComponentFixture; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ SliderForProductsComponent ] - }) - .compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [SliderForProductsComponent] + }) + .compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(SliderForProductsComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(SliderForProductsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/Frontend/src/app/components/top-bar/top-bar.component.html b/Frontend/src/app/components/top-bar/top-bar.component.html index 5266f85..3c06f38 100644 --- a/Frontend/src/app/components/top-bar/top-bar.component.html +++ b/Frontend/src/app/components/top-bar/top-bar.component.html @@ -2,21 +2,32 @@ diff --git a/Frontend/src/app/components/top-bar/top-bar.component.spec.ts b/Frontend/src/app/components/top-bar/top-bar.component.spec.ts index 7d3acaf..42907b5 100644 --- a/Frontend/src/app/components/top-bar/top-bar.component.spec.ts +++ b/Frontend/src/app/components/top-bar/top-bar.component.spec.ts @@ -1,25 +1,48 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; -import { TopBarComponent } from './top-bar.component'; +import {TopBarComponent} from './top-bar.component'; +import {FormBuilder} from '@angular/forms'; +import {ApiService} from '../../services/api.service'; +import {Router} from '@angular/router'; +import {AbstractMockObservableService} from '../../mocks/mock.service'; + +class MockApiService extends AbstractMockObservableService { + getUserInfo(): any { + this.content = []; + return this; + } + + getSessionInfoFromLocalStorage(): any { + this.content = []; + return this; + } +} describe('TopBarComponent', () => { - let component: TopBarComponent; - let fixture: ComponentFixture; + let component: TopBarComponent; + let fixture: ComponentFixture; + let mockService; + const router = { + navigate: jasmine.createSpy('navigate'), + routerState: jasmine.createSpy('routerState') + }; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ TopBarComponent ] - }) - .compileComponents(); - }); + beforeEach(async () => { + mockService = new MockApiService(); + await TestBed.configureTestingModule({ + declarations: [TopBarComponent], + providers: [{provide: ApiService, useValue: mockService}, {provide: Router, useValue: router}] + }) + .compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(TopBarComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(TopBarComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/Frontend/src/app/pages/imprint/imprint.component.html b/Frontend/src/app/pages/imprint/imprint.component.html index 840716f..9c6799b 100644 --- a/Frontend/src/app/pages/imprint/imprint.component.html +++ b/Frontend/src/app/pages/imprint/imprint.component.html @@ -1,5 +1,5 @@ - -
+ +

Impressum

Angaben gemäß § 5 TMG

@@ -17,14 +17,16 @@

Haftung für Inhalte

Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene - Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als + Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir + als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen.

Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. - Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. + Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung + möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen.

@@ -44,16 +46,21 @@

Urheberrecht

- Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht. + Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen + Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. Downloads und Kopien dieser Seite sind nur für den privaten, nicht kommerziellen Gebrauch gestattet.

- Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. - Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung - aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden wir + Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter + beachtet. + Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine + Urheberrechtsverletzung + aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden + wir derartige Inhalte umgehend entfernen.

- + + diff --git a/Frontend/src/app/pages/imprint/imprint.component.ts b/Frontend/src/app/pages/imprint/imprint.component.ts index f3c5441..997a2be 100644 --- a/Frontend/src/app/pages/imprint/imprint.component.ts +++ b/Frontend/src/app/pages/imprint/imprint.component.ts @@ -1,15 +1,16 @@ -import { Component, OnInit } from '@angular/core'; +import {Component, OnInit} from '@angular/core'; @Component({ - selector: 'app-imprint', - templateUrl: './imprint.component.html', - styleUrls: ['./imprint.component.css'] + selector: 'app-imprint', + templateUrl: './imprint.component.html', + styleUrls: ['./imprint.component.css'] }) export class ImprintComponent implements OnInit { - constructor() { } + constructor() { + } - ngOnInit(): void { - } + ngOnInit(): void { + } } diff --git a/Frontend/src/app/pages/landingpage/landingpage.component.ts b/Frontend/src/app/pages/landingpage/landingpage.component.ts index cf3deac..3842ffd 100644 --- a/Frontend/src/app/pages/landingpage/landingpage.component.ts +++ b/Frontend/src/app/pages/landingpage/landingpage.component.ts @@ -1,6 +1,6 @@ import {Component, OnInit} from '@angular/core'; import {Router} from '@angular/router'; -import {ApiService} from "../../services/api.service"; +import {ApiService} from '../../services/api.service'; @Component({ selector: 'app-landingpage', @@ -12,8 +12,7 @@ export class LandingpageComponent implements OnInit { isLoggedIn = false; constructor( - private router: Router, - private api: ApiService + private router: Router ) { } diff --git a/Frontend/src/app/pages/page-not-found-page/page-not-found-page.component.ts b/Frontend/src/app/pages/page-not-found-page/page-not-found-page.component.ts index 9de002b..31d69f2 100644 --- a/Frontend/src/app/pages/page-not-found-page/page-not-found-page.component.ts +++ b/Frontend/src/app/pages/page-not-found-page/page-not-found-page.component.ts @@ -1,15 +1,16 @@ -import { Component, OnInit } from '@angular/core'; +import {Component, OnInit} from '@angular/core'; @Component({ - selector: 'app-page-not-found-page', - templateUrl: './page-not-found-page.component.html', - styleUrls: ['./page-not-found-page.component.css'] + selector: 'app-page-not-found-page', + templateUrl: './page-not-found-page.component.html', + styleUrls: ['./page-not-found-page.component.css'] }) export class PageNotFoundPageComponent implements OnInit { - constructor() { } + constructor() { + } - ngOnInit(): void { - } + ngOnInit(): void { + } } diff --git a/Frontend/src/app/pages/privacy/privacy.component.html b/Frontend/src/app/pages/privacy/privacy.component.html index 29c167f..05646db 100644 --- a/Frontend/src/app/pages/privacy/privacy.component.html +++ b/Frontend/src/app/pages/privacy/privacy.component.html @@ -1,11 +1,12 @@ - -
+ +

Datenschutz­erklärung

1. Datenschutz auf einen Blick

Allgemeine Hinweise

Die folgenden Hinweise geben einen einfachen Überblick darüber, was mit Ihren - personenbezogenen Daten passiert, wenn Sie diese Website besuchen. Personenbezogene Daten sind alle Daten, mit denen + personenbezogenen Daten passiert, wenn Sie diese Website besuchen. Personenbezogene Daten sind alle Daten, mit + denen Sie persönlich identifiziert werden können. Ausführliche Informationen zum Thema Datenschutz entnehmen Sie unserer unter diesem Text aufgeführten Datenschutzerklärung.

@@ -40,8 +41,10 @@ Sie haben jederzeit das Recht, unentgeltlich Auskunft über Herkunft, Empfänger und Zweck Ihrer gespeicherten personenbezogenen Daten zu erhalten. Sie haben außerdem ein Recht, die Berichtigung oder Löschung dieser Daten zu verlangen. Wenn Sie eine Einwilligung zur - Datenverarbeitung erteilt haben, können Sie diese Einwilligung jederzeit für die Zukunft widerrufen. Außerdem - haben Sie das Recht, unter bestimmten Umständen die Einschränkung der Verarbeitung Ihrer personenbezogenen + Datenverarbeitung erteilt haben, können Sie diese Einwilligung jederzeit für die Zukunft widerrufen. + Außerdem + haben Sie das Recht, unter bestimmten Umständen die Einschränkung der Verarbeitung Ihrer + personenbezogenen Daten zu verlangen. Des Weiteren steht Ihnen ein Beschwerderecht bei der zuständigen Aufsichtsbehörde zu.

@@ -85,13 +88,15 @@

Datenschutz

Die Betreiber dieser Seiten nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Wir - behandeln Ihre personenbezogenen Daten vertraulich und entsprechend der gesetzlichen Datenschutzvorschriften sowie + behandeln Ihre personenbezogenen Daten vertraulich und entsprechend der gesetzlichen Datenschutzvorschriften + sowie dieser Datenschutzerklärung.

Wenn Sie diese Website benutzen, werden verschiedene personenbezogene Daten erhoben. Personenbezogene Daten sind Daten, mit denen Sie persönlich identifiziert werden können. Die - vorliegende Datenschutzerklärung erläutert, welche Daten wir erheben und wofür wir sie nutzen. Sie + vorliegende Datenschutzerklärung erläutert, welche Daten wir erheben und wofür wir sie nutzen. + Sie erläutert auch, wie und zu welchem Zweck das geschieht.

@@ -115,7 +120,8 @@ E-Mail: betterzon-privacy@mueller-patrick.tech

- Verantwortliche Stelle ist die natürliche oder juristische Person, die allein oder gemeinsam mit anderen über + Verantwortliche Stelle ist die natürliche oder juristische Person, die allein oder gemeinsam mit anderen + über die Zwecke und Mittel der Verarbeitung von personenbezogenen Daten (z. B. Namen, E-Mail-Adressen o. Ä.) entscheidet.

@@ -124,7 +130,8 @@

Soweit innerhalb dieser Datenschutzerklärung keine speziellere Speicherdauer genannt wurde, verbleiben Ihre personenbezogenen Daten bei uns, bis der Zweck für die Datenverarbeitung entfällt. - Wenn Sie ein berechtigtes Löschersuchen geltend machen oder eine Einwilligung zur Datenverarbeitung widerrufen, + Wenn Sie ein berechtigtes Löschersuchen geltend machen oder eine Einwilligung zur Datenverarbeitung + widerrufen, werden Ihre Daten gelöscht, sofern wir keine anderen rechtlich zulässigen Gründe für die Speicherung Ihrer personenbezogenen Daten haben (z.B. steuer- oder handelsrechtliche Aufbewahrungsfristen); im letztgenannten Fall erfolgt die Löschung nach Fortfall dieser Gründe. @@ -139,7 +146,8 @@ Datenschutzniveau garantiert werden kann. Beispielsweise sind US-Unternehmen dazu verpflichtet, personenbezogene Daten an Sicherheitsbehörden herauszugeben, ohne dass Sie als Betroffener hiergegen gerichtlich vorgehen könnten. Es kann daher nicht ausgeschlossen werden, dass US-Behörden (z.B. Geheimdienste) Ihre auf US-Servern - befindlichen Daten zu Überwachungszwecken verarbeiten, auswerten und dauerhaft speichern. Wir haben auf diese + befindlichen Daten zu Überwachungszwecken verarbeiten, auswerten und dauerhaft speichern. Wir haben auf + diese Verarbeitungstätigkeiten keinen Einfluss.

@@ -150,15 +158,19 @@ erfolgten Datenverarbeitung bleibt vom Widerruf unberührt.

-

Widerspruchsrecht gegen die Datenerhebung in besonderen Fällen sowie gegen Direktwerbung (Art. 21 DSGVO)

+

Widerspruchsrecht gegen die Datenerhebung in besonderen Fällen sowie gegen Direktwerbung (Art. 21 + DSGVO)

WENN DIE DATENVERARBEITUNG AUF GRUNDLAGE VON ART. 6 ABS. 1 LIT. E ODER F DSGVO ERFOLGT, HABEN SIE JEDERZEIT DAS RECHT, AUS GRÜNDEN, DIE SICH AUS IHRER BESONDEREN SITUATION ERGEBEN, GEGEN DIE VERARBEITUNG IHRER PERSONENBEZOGENEN DATEN WIDERSPRUCH EINZULEGEN; DIES GILT AUCH FÜR EIN AUF DIESE BESTIMMUNGEN GESTÜTZTES - PROFILING. DIE JEWEILIGE RECHTSGRUNDLAGE, AUF DENEN EINE VERARBEITUNG BERUHT, ENTNEHMEN SIE DIESER DATENSCHUTZERKLÄRUNG. - WENN SIE WIDERSPRUCH EINLEGEN, WERDEN WIR IHRE BETROFFENEN PERSONENBEZOGENEN DATEN NICHT MEHR VERARBEITEN, ES SEI + PROFILING. DIE JEWEILIGE RECHTSGRUNDLAGE, AUF DENEN EINE VERARBEITUNG BERUHT, ENTNEHMEN SIE DIESER + DATENSCHUTZERKLÄRUNG. + WENN SIE WIDERSPRUCH EINLEGEN, WERDEN WIR IHRE BETROFFENEN PERSONENBEZOGENEN DATEN NICHT MEHR VERARBEITEN, ES + SEI DENN, WIR KÖNNEN ZWINGENDE SCHUTZWÜRDIGE GRÜNDE FÜR DIE VERARBEITUNG NACHWEISEN, DIE IHRE - INTERESSEN, RECHTE UND FREIHEITEN ÜBERWIEGEN ODER DIE VERARBEITUNG DIENT DER GELTENDMACHUNG, AUSÜBUNG ODER + INTERESSEN, RECHTE UND FREIHEITEN ÜBERWIEGEN ODER DIE VERARBEITUNG DIENT DER GELTENDMACHUNG, AUSÜBUNG + ODER VERTEIDIGUNG VON RECHTSANSPRÜCHEN (WIDERSPRUCH NACH ART. 21 ABS. 1 DSGVO).

@@ -166,7 +178,8 @@ DATEN VERARBEITET, UM DIREKTWERBUNG ZU BETREIBEN, SO HABEN SIE DAS RECHT, JEDERZEIT WIDERSPRUCH GEGEN DIE VERARBEITUNG SIE BETREFFENDER PERSONENBEZOGENER DATEN ZUM ZWECKE DERARTIGER WERBUNG EINZULEGEN; DIES GILT AUCH FÜR DAS PROFILING, SOWEIT ES MIT SOLCHER DIREKTWERBUNG IN VERBINDUNG STEHT. WENN SIE WIDERSPRECHEN, WERDEN IHRE - PERSONENBEZOGENEN DATEN ANSCHLIESSEND NICHT MEHR ZUM ZWECKE DER DIREKTWERBUNG VERWENDET (WIDERSPRUCH NACH ART. 21 + PERSONENBEZOGENEN DATEN ANSCHLIESSEND NICHT MEHR ZUM ZWECKE DER DIREKTWERBUNG VERWENDET (WIDERSPRUCH NACH ART. + 21 ABS. 2 DSGVO).

@@ -174,7 +187,8 @@

Im Falle von Verstößen gegen die DSGVO steht den Betroffenen ein Beschwerderecht bei einer Aufsichtsbehörde, insbesondere in dem - Mitgliedstaat ihres gewöhnlichen Aufenthalts, ihres Arbeitsplatzes oder des Orts des mutmaßlichen Verstoßes + Mitgliedstaat ihres gewöhnlichen Aufenthalts, ihres Arbeitsplatzes oder des Orts des mutmaßlichen + Verstoßes zu. Das Beschwerderecht besteht unbeschadet anderweitiger verwaltungsrechtlicher oder gerichtlicher Rechtsbehelfe.

@@ -182,7 +196,8 @@

Recht auf Daten­übertrag­barkeit

Sie haben das Recht, Daten, die wir auf Grundlage Ihrer - Einwilligung oder in Erfüllung eines Vertrags automatisiert verarbeiten, an sich oder an einen Dritten in einem + Einwilligung oder in Erfüllung eines Vertrags automatisiert verarbeiten, an sich oder an einen Dritten in + einem gängigen, maschinenlesbaren Format aushändigen zu lassen. Sofern Sie die direkte Übertragung der Daten an einen anderen Verantwortlichen verlangen, erfolgt dies nur, soweit es technisch machbar ist.

@@ -190,8 +205,10 @@

SSL- bzw. TLS-Verschlüsselung

Diese Seite nutzt aus Sicherheitsgründen und zum Schutz der Übertragung - vertraulicher Inhalte, wie zum Beispiel Bestellungen oder Anfragen, die Sie an uns als Seitenbetreiber senden, eine - SSL- bzw. TLS-Verschlüsselung. Eine verschlüsselte Verbindung erkennen Sie daran, dass die Adresszeile des + vertraulicher Inhalte, wie zum Beispiel Bestellungen oder Anfragen, die Sie an uns als Seitenbetreiber senden, + eine + SSL- bzw. TLS-Verschlüsselung. Eine verschlüsselte Verbindung erkennen Sie daran, dass die Adresszeile + des Browsers von „http://“ auf „https://“ wechselt und an dem Schloss-Symbol in Ihrer Browserzeile.

@@ -203,8 +220,10 @@

Auskunft, Löschung und Berichtigung

Sie haben im Rahmen der geltenden gesetzlichen Bestimmungen - jederzeit das Recht auf unentgeltliche Auskunft über Ihre gespeicherten personenbezogenen Daten, deren Herkunft - und Empfänger und den Zweck der Datenverarbeitung und ggf. ein Recht auf Berichtigung oder Löschung dieser + jederzeit das Recht auf unentgeltliche Auskunft über Ihre gespeicherten personenbezogenen Daten, deren + Herkunft + und Empfänger und den Zweck der Datenverarbeitung und ggf. ein Recht auf Berichtigung oder Löschung + dieser Daten. Hierzu sowie zu weiteren Fragen zum Thema personenbezogene Daten können Sie sich jederzeit an uns wenden.

@@ -216,22 +235,29 @@

  • - Wenn Sie die Richtigkeit Ihrer bei uns gespeicherten personenbezogenen Daten bestreiten, benötigen wir in - der Regel Zeit, um dies zu überprüfen. Für die Dauer der Prüfung haben Sie das Recht, die + Wenn Sie die Richtigkeit Ihrer bei uns gespeicherten personenbezogenen Daten bestreiten, benötigen wir + in + der Regel Zeit, um dies zu überprüfen. Für die Dauer der Prüfung haben Sie das Recht, + die Einschränkung der Verarbeitung Ihrer personenbezogenen Daten zu verlangen.
  • - Wenn die Verarbeitung Ihrer personenbezogenen Daten unrechtmäßig geschah/geschieht, können Sie + Wenn die Verarbeitung Ihrer personenbezogenen Daten unrechtmäßig geschah/geschieht, können + Sie statt der Löschung die Einschränkung der Datenverarbeitung verlangen.
  • - Wenn wir Ihre personenbezogenen Daten nicht mehr benötigen, Sie sie jedoch zur Ausübung, Verteidigung - oder Geltendmachung von Rechtsansprüchen benötigen, haben Sie das Recht, statt der Löschung die + Wenn wir Ihre personenbezogenen Daten nicht mehr benötigen, Sie sie jedoch zur Ausübung, + Verteidigung + oder Geltendmachung von Rechtsansprüchen benötigen, haben Sie das Recht, statt der Löschung + die Einschränkung der Verarbeitung Ihrer personenbezogenen Daten zu verlangen.
  • - Wenn Sie einen Widerspruch nach Art. 21 Abs. 1 DSGVO eingelegt haben, muss eine Abwägung zwischen Ihren und - unseren Interessen vorgenommen werden. Solange noch nicht feststeht, wessen Interessen überwiegen, haben + Wenn Sie einen Widerspruch nach Art. 21 Abs. 1 DSGVO eingelegt haben, muss eine Abwägung zwischen Ihren + und + unseren Interessen vorgenommen werden. Solange noch nicht feststeht, wessen Interessen überwiegen, + haben Sie das Recht, die Einschränkung der Verarbeitung Ihrer personenbezogenen Daten zu verlangen.
@@ -239,7 +265,8 @@ Wenn Sie die Verarbeitung Ihrer personenbezogenen Daten eingeschränkt haben, dürfen diese Daten – von ihrer Speicherung abgesehen – nur mit Ihrer Einwilligung oder zur Geltendmachung, Ausübung oder Verteidigung von Rechtsansprüchen oder zum Schutz der Rechte einer anderen natürlichen oder - juristischen Person oder aus Gründen eines wichtigen öffentlichen Interesses der Europäischen Union + juristischen Person oder aus Gründen eines wichtigen öffentlichen Interesses der Europäischen + Union oder eines Mitgliedstaats verarbeitet werden.

@@ -250,12 +277,14 @@ und richten auf Ihrem Endgerät keinen Schaden an. Sie werden entweder vorübergehend für die Dauer einer Sitzung (Session-Cookies) oder dauerhaft (permanente Cookies) auf Ihrem Endgerät gespeichert. Session-Cookies werden nach Ende Ihres Besuchs automatisch gelöscht. Permanente Cookies bleiben auf Ihrem - Endgerät gespeichert, bis Sie diese selbst löschen oder eine automatische Löschung durch Ihren + Endgerät gespeichert, bis Sie diese selbst löschen oder eine automatische Löschung durch + Ihren Webbrowser erfolgt.

Teilweise können auch Cookies von Drittunternehmen auf Ihrem Endgerät - gespeichert werden, wenn Sie unsere Seite betreten (Third-Party-Cookies). Diese ermöglichen uns oder Ihnen die + gespeichert werden, wenn Sie unsere Seite betreten (Third-Party-Cookies). Diese ermöglichen uns oder Ihnen + die Nutzung bestimmter Dienstleistungen des Drittunternehmens (z.B. Cookies zur Abwicklung von Zahlungsdienstleistungen).

@@ -267,24 +296,31 @@

Cookies, die zur Durchführung des elektronischen Kommunikationsvorgangs (notwendige Cookies) - oder zur Bereitstellung bestimmter, von Ihnen erwünschter Funktionen (funktionale Cookies, z. B. für die - Warenkorbfunktion) oder zur Optimierung der Website (z.B. Cookies zur Messung des Webpublikums) erforderlich sind, - werden auf Grundlage von Art. 6 Abs. 1 lit. f DSGVO gespeichert, sofern keine andere Rechtsgrundlage angegeben wird. - Der Websitebetreiber hat ein berechtigtes Interesse an der Speicherung von Cookies zur technisch fehlerfreien und + oder zur Bereitstellung bestimmter, von Ihnen erwünschter Funktionen (funktionale Cookies, z. B. für + die + Warenkorbfunktion) oder zur Optimierung der Website (z.B. Cookies zur Messung des Webpublikums) erforderlich + sind, + werden auf Grundlage von Art. 6 Abs. 1 lit. f DSGVO gespeichert, sofern keine andere Rechtsgrundlage angegeben + wird. + Der Websitebetreiber hat ein berechtigtes Interesse an der Speicherung von Cookies zur technisch fehlerfreien + und optimierten Bereitstellung seiner Dienste. Sofern eine Einwilligung zur Speicherung von Cookies abgefragt wurde, - erfolgt die Speicherung der betreffenden Cookies ausschließlich auf Grundlage dieser Einwilligung (Art. 6 Abs. + erfolgt die Speicherung der betreffenden Cookies ausschließlich auf Grundlage dieser Einwilligung (Art. 6 + Abs. 1 lit. a DSGVO); die Einwilligung ist jederzeit widerrufbar.

Sie können Ihren Browser so einstellen, - dass Sie über das Setzen von Cookies informiert werden und Cookies nur im Einzelfall erlauben, die Annahme von + dass Sie über das Setzen von Cookies informiert werden und Cookies nur im Einzelfall erlauben, die Annahme + von Cookies für bestimmte Fälle oder generell ausschließen sowie das automatische Löschen der Cookies beim Schließen des Browsers aktivieren. Bei der Deaktivierung von Cookies kann die Funktionalität dieser Website eingeschränkt sein.

Soweit Cookies von Drittunternehmen oder zu Analysezwecken eingesetzt - werden, werden wir Sie hierüber im Rahmen dieser Datenschutzerklärung gesondert informieren und ggf. eine + werden, werden wir Sie hierüber im Rahmen dieser Datenschutzerklärung gesondert informieren und ggf. + eine Einwilligung abfragen.

@@ -318,10 +354,13 @@ den Fall von Anschlussfragen bei uns gespeichert. Diese Daten geben wir nicht ohne Ihre Einwilligung weiter.

- Die Verarbeitung dieser Daten erfolgt auf Grundlage von Art. 6 Abs. 1 lit. b DSGVO, sofern Ihre Anfrage mit der Erfüllung - eines Vertrags zusammenhängt oder zur Durchführung vorvertraglicher Maßnahmen erforderlich ist. In + Die Verarbeitung dieser Daten erfolgt auf Grundlage von Art. 6 Abs. 1 lit. b DSGVO, sofern Ihre Anfrage mit der + Erfüllung + eines Vertrags zusammenhängt oder zur Durchführung vorvertraglicher Maßnahmen erforderlich ist. + In allen übrigen Fällen beruht die Verarbeitung auf unserem berechtigten Interesse an der effektiven - Bearbeitung der an uns gerichteten Anfragen (Art. 6 Abs. 1 lit. f DSGVO) oder auf Ihrer Einwilligung (Art. 6 Abs. 1 + Bearbeitung der an uns gerichteten Anfragen (Art. 6 Abs. 1 lit. f DSGVO) oder auf Ihrer Einwilligung (Art. 6 + Abs. 1 lit. a DSGVO) sofern diese abgefragt wurde.

@@ -335,21 +374,25 @@

Wenn Sie uns per E-Mail, Telefon oder Telefax kontaktieren, wird Ihre Anfrage inklusive aller daraus hervorgehenden personenbezogenen Daten (Name, Anfrage) zum Zwecke der - Bearbeitung Ihres Anliegens bei uns gespeichert und verarbeitet. Diese Daten geben wir nicht ohne Ihre Einwilligung + Bearbeitung Ihres Anliegens bei uns gespeichert und verarbeitet. Diese Daten geben wir nicht ohne Ihre + Einwilligung weiter.

Die Verarbeitung dieser Daten erfolgt auf Grundlage von Art. 6 Abs. 1 lit. b DSGVO, sofern Ihre Anfrage mit der Erfüllung eines Vertrags zusammenhängt oder zur Durchführung vorvertraglicher Maßnahmen - erforderlich ist. In allen übrigen Fällen beruht die Verarbeitung auf unserem berechtigten Interesse an - der effektiven Bearbeitung der an uns gerichteten Anfragen (Art. 6 Abs. 1 lit. f DSGVO) oder auf Ihrer Einwilligung + erforderlich ist. In allen übrigen Fällen beruht die Verarbeitung auf unserem berechtigten Interesse + an + der effektiven Bearbeitung der an uns gerichteten Anfragen (Art. 6 Abs. 1 lit. f DSGVO) oder auf Ihrer + Einwilligung (Art. 6 Abs. 1 lit. a DSGVO) sofern diese abgefragt wurde.

Die von Ihnen an uns per Kontaktanfragen übersandten Daten verbleiben bei uns, bis Sie uns zur Löschung auffordern, Ihre Einwilligung zur Speicherung widerrufen oder der Zweck für die Datenspeicherung entfällt (z. B. nach abgeschlossener Bearbeitung Ihres - Anliegens). Zwingende gesetzliche Bestimmungen – insbesondere gesetzliche Aufbewahrungsfristen – bleiben + Anliegens). Zwingende gesetzliche Bestimmungen – insbesondere gesetzliche Aufbewahrungsfristen – + bleiben unberührt.

@@ -363,10 +406,13 @@

Zu diesem Zweck muss der von Ihnen verwendete Browser Verbindung zu den Servern von Google aufnehmen. Hierdurch erlangt Google Kenntnis darüber, - dass über Ihre IP-Adresse diese Website aufgerufen wurde. Die Nutzung von Google WebFonts erfolgt auf Grundlage - von Art. 6 Abs. 1 lit. f DSGVO. Der Websitebetreiber hat ein berechtigtes Interesse an der einheitlichen Darstellung + dass über Ihre IP-Adresse diese Website aufgerufen wurde. Die Nutzung von Google WebFonts erfolgt auf + Grundlage + von Art. 6 Abs. 1 lit. f DSGVO. Der Websitebetreiber hat ein berechtigtes Interesse an der einheitlichen + Darstellung des Schriftbildes auf seiner Website. Sofern eine entsprechende Einwilligung abgefragt wurde (z. B. eine - Einwilligung zur Speicherung von Cookies), erfolgt die Verarbeitung ausschließlich auf Grundlage von Art. 6 + Einwilligung zur Speicherung von Cookies), erfolgt die Verarbeitung ausschließlich auf Grundlage von Art. + 6 Abs. 1 lit. a DSGVO; die Einwilligung ist jederzeit widerrufbar.

@@ -376,7 +422,8 @@

Weitere Informationen zu Google Web Fonts finden Sie unter https://developers.google.com/fonts/faq - und in der Datenschutzerklärung von Google: https://policies.google.com/privacy?hl=de.

@@ -388,10 +435,12 @@

Beim Aufruf einer Seite lädt Ihr Browser die benötigten Fonts in ihren Browsercache, um Texte, Schriftarten und - Symbole korrekt anzuzeigen. Zu diesem Zweck muss der von Ihnen verwendete Browser Verbindung zu den Servern von Font + Symbole korrekt anzuzeigen. Zu diesem Zweck muss der von Ihnen verwendete Browser Verbindung zu den Servern von + Font Awesome aufnehmen. Hierdurch erlangt Font Awesome Kenntnis darüber, dass über Ihre IP-Adresse diese Website aufgerufen wurde. Die Nutzung von Font Awesome erfolgt auf Grundlage von Art. 6 Abs. 1 lit. f DSGVO. Wir - haben ein berechtigtes Interesse an der einheitlichen Darstellung des Schriftbildes auf unserer Website. Sofern eine + haben ein berechtigtes Interesse an der einheitlichen Darstellung des Schriftbildes auf unserer Website. Sofern + eine entsprechende Einwilligung abgefragt wurde (z. B. eine Einwilligung zur Speicherung von Cookies), erfolgt die Verarbeitung ausschließlich auf Grundlage von Art. 6 Abs. 1 lit. a DSGVO; die Einwilligung ist jederzeit widerrufbar. @@ -405,4 +454,5 @@ von Font Awesome unter: https://fontawesome.com/privacy.

- + + diff --git a/Frontend/src/app/pages/privacy/privacy.component.ts b/Frontend/src/app/pages/privacy/privacy.component.ts index 9e4ed50..b77c1a0 100644 --- a/Frontend/src/app/pages/privacy/privacy.component.ts +++ b/Frontend/src/app/pages/privacy/privacy.component.ts @@ -1,15 +1,16 @@ -import { Component, OnInit } from '@angular/core'; +import {Component, OnInit} from '@angular/core'; @Component({ - selector: 'app-privacy', - templateUrl: './privacy.component.html', - styleUrls: ['./privacy.component.css'] + selector: 'app-privacy', + templateUrl: './privacy.component.html', + styleUrls: ['./privacy.component.css'] }) export class PrivacyComponent implements OnInit { - constructor() { } + constructor() { + } - ngOnInit(): void { - } + ngOnInit(): void { + } } diff --git a/Frontend/src/app/pages/profile-page/profile-page.component.spec.ts b/Frontend/src/app/pages/profile-page/profile-page.component.spec.ts index 9101f43..75355b3 100644 --- a/Frontend/src/app/pages/profile-page/profile-page.component.spec.ts +++ b/Frontend/src/app/pages/profile-page/profile-page.component.spec.ts @@ -1,25 +1,25 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; -import { ProfilePageComponent } from './profile-page.component'; +import {ProfilePageComponent} from './profile-page.component'; describe('ProfilePageComponent', () => { - let component: ProfilePageComponent; - let fixture: ComponentFixture; + let component: ProfilePageComponent; + let fixture: ComponentFixture; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ ProfilePageComponent ] - }) - .compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ProfilePageComponent] + }) + .compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(ProfilePageComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(ProfilePageComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/Frontend/src/app/pages/profile-page/profile-page.component.ts b/Frontend/src/app/pages/profile-page/profile-page.component.ts index c0d41b6..8fa07ba 100644 --- a/Frontend/src/app/pages/profile-page/profile-page.component.ts +++ b/Frontend/src/app/pages/profile-page/profile-page.component.ts @@ -1,15 +1,16 @@ -import { Component, OnInit } from '@angular/core'; +import {Component, OnInit} from '@angular/core'; @Component({ - selector: 'app-profile-page', - templateUrl: './profile-page.component.html', - styleUrls: ['./profile-page.component.css'] + selector: 'app-profile-page', + templateUrl: './profile-page.component.html', + styleUrls: ['./profile-page.component.css'] }) export class ProfilePageComponent implements OnInit { - constructor() { } + constructor() { + } - ngOnInit(): void { - } + ngOnInit(): void { + } } diff --git a/Frontend/src/app/components/profile/profile.component.css b/Frontend/src/app/pages/profile/profile.component.css similarity index 67% rename from Frontend/src/app/components/profile/profile.component.css rename to Frontend/src/app/pages/profile/profile.component.css index f82c74e..df8c098 100644 --- a/Frontend/src/app/components/profile/profile.component.css +++ b/Frontend/src/app/pages/profile/profile.component.css @@ -1,8 +1,8 @@ -.inf-content{ - border:1px solid #DDDDDD; - -webkit-border-radius:10px; - -moz-border-radius:10px; - border-radius:10px; +.inf-content { + border: 1px solid #DDDDDD; + -webkit-border-radius: 10px; + -moz-border-radius: 10px; + border-radius: 10px; box-shadow: 7px 7px 7px rgba(0, 0, 0, 0.3); } diff --git a/Frontend/src/app/components/profile/profile.component.html b/Frontend/src/app/pages/profile/profile.component.html similarity index 94% rename from Frontend/src/app/components/profile/profile.component.html rename to Frontend/src/app/pages/profile/profile.component.html index 24dfdc4..635eaee 100644 --- a/Frontend/src/app/components/profile/profile.component.html +++ b/Frontend/src/app/pages/profile/profile.component.html @@ -2,7 +2,8 @@
- +
  • @@ -86,13 +87,14 @@ {{productsMap[alarm.product_id]?.name}} - {{alarm.defined_price/100}}€ + {{alarm.defined_price / 100}}€ - + diff --git a/Frontend/src/app/pages/profile/profile.component.spec.ts b/Frontend/src/app/pages/profile/profile.component.spec.ts new file mode 100644 index 0000000..1fe50b1 --- /dev/null +++ b/Frontend/src/app/pages/profile/profile.component.spec.ts @@ -0,0 +1,47 @@ +import {ComponentFixture, TestBed} from '@angular/core/testing'; + +import {ProfileComponent} from './profile.component'; +import {AbstractMockObservableService} from '../../mocks/mock.service'; +import {ApiService} from '../../services/api.service'; + +class MockApiService extends AbstractMockObservableService { + getUserInfo(): any { + this.content = []; + return this; + } + + getPriceAlarms(): any { + this.content = []; + return this; + } + + getProductsByIds(): any { + this.content = []; + return this; + } +} + +describe('ProfileComponent', () => { + let component: ProfileComponent; + let fixture: ComponentFixture; + let mockService; + + beforeEach(async () => { + mockService = new MockApiService(); + await TestBed.configureTestingModule({ + declarations: [ProfileComponent], + providers: [{provide: ApiService, useValue: mockService}] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ProfileComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Frontend/src/app/components/profile/profile.component.ts b/Frontend/src/app/pages/profile/profile.component.ts similarity index 100% rename from Frontend/src/app/components/profile/profile.component.ts rename to Frontend/src/app/pages/profile/profile.component.ts diff --git a/Frontend/src/app/services/api.service.spec.ts b/Frontend/src/app/services/api.service.spec.ts index a5865c6..2503ead 100644 --- a/Frontend/src/app/services/api.service.spec.ts +++ b/Frontend/src/app/services/api.service.spec.ts @@ -1,7 +1,7 @@ import {TestBed} from '@angular/core/testing'; import {ApiService} from './api.service'; -import {HttpClientModule} from "@angular/common/http"; +import {HttpClientModule} from '@angular/common/http'; describe('ApiService', () => { let service: ApiService; diff --git a/Frontend/src/app/services/api.service.ts b/Frontend/src/app/services/api.service.ts index 4839482..789d955 100644 --- a/Frontend/src/app/services/api.service.ts +++ b/Frontend/src/app/services/api.service.ts @@ -106,7 +106,7 @@ export class ApiService { let asin = ''; // Check if the parameter is a link or an asin - const linkRegex: RegExp = /^http[s]{0,1}:\/\/.*\/dp\/(.[^\/]*)\/{0,1}.*$/; + const linkRegex: RegExp = /^http[s]?:\/\/.*\/dp\/(.[^\/]*)\/?.*$/; const matches = linkRegex.exec(asinOrLink); if (matches) { // param is a link, extract asin diff --git a/Frontend/src/main.ts b/Frontend/src/main.ts index c7b673c..38c4486 100644 --- a/Frontend/src/main.ts +++ b/Frontend/src/main.ts @@ -1,12 +1,12 @@ -import { enableProdMode } from '@angular/core'; -import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; +import {enableProdMode} from '@angular/core'; +import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; -import { AppModule } from './app/app.module'; -import { environment } from './environments/environment'; +import {AppModule} from './app/app.module'; +import {environment} from './environments/environment'; if (environment.production) { - enableProdMode(); + enableProdMode(); } platformBrowserDynamic().bootstrapModule(AppModule) - .catch(err => console.error(err)); + .catch(err => console.error(err)); diff --git a/Frontend/src/styles.css b/Frontend/src/styles.css index 29431c5..9764d9d 100644 --- a/Frontend/src/styles.css +++ b/Frontend/src/styles.css @@ -74,6 +74,7 @@ h6, .h6, h5, .h5, h4, .h4, h3, .h3, h2, .h2, h1, .h1 { h1, .h1 { font-size: calc(1.375rem + 1.5vw); } + @media (min-width: 1200px) { h1, .h1 { font-size: 2.5rem; @@ -83,6 +84,7 @@ h1, .h1 { h2, .h2 { font-size: calc(1.325rem + 0.9vw); } + @media (min-width: 1200px) { h2, .h2 { font-size: 2rem; @@ -92,6 +94,7 @@ h2, .h2 { h3, .h3 { font-size: calc(1.3rem + 0.6vw); } + @media (min-width: 1200px) { h3, .h3 { font-size: 1.75rem; @@ -101,6 +104,7 @@ h3, .h3 { h4, .h4 { font-size: calc(1.275rem + 0.3vw); } + @media (min-width: 1200px) { h4, .h4 { font-size: 1.5rem; @@ -201,6 +205,7 @@ a { color: #1abc9c; text-decoration: underline; } + a:hover { color: #15967d; } @@ -227,6 +232,7 @@ pre { overflow: auto; font-size: 0.875em; } + pre code { font-size: inherit; color: inherit; @@ -238,6 +244,7 @@ code { color: #d63384; word-wrap: break-word; } + a > code { color: inherit; } @@ -249,6 +256,7 @@ kbd { background-color: #212529; border-radius: 0.25rem; } + kbd kbd { padding: 0; font-size: 1em; @@ -327,6 +335,7 @@ select { select { word-wrap: normal; } + select:disabled { opacity: 1; } @@ -341,6 +350,7 @@ button, [type=submit] { -webkit-appearance: button; } + button:not(:disabled), [type=button]:not(:disabled), [type=reset]:not(:disabled), @@ -372,11 +382,13 @@ legend { font-size: calc(1.275rem + 0.3vw); line-height: inherit; } + @media (min-width: 1200px) { legend { font-size: 1.5rem; } } + legend + * { clear: left; } @@ -456,6 +468,7 @@ progress { font-weight: 300; line-height: 1.2; } + @media (min-width: 1200px) { .display-1 { font-size: 5rem; @@ -467,6 +480,7 @@ progress { font-weight: 300; line-height: 1.2; } + @media (min-width: 1200px) { .display-2 { font-size: 4.5rem; @@ -478,6 +492,7 @@ progress { font-weight: 300; line-height: 1.2; } + @media (min-width: 1200px) { .display-3 { font-size: 4rem; @@ -489,6 +504,7 @@ progress { font-weight: 300; line-height: 1.2; } + @media (min-width: 1200px) { .display-4 { font-size: 3.5rem; @@ -500,6 +516,7 @@ progress { font-weight: 300; line-height: 1.2; } + @media (min-width: 1200px) { .display-5 { font-size: 3rem; @@ -511,6 +528,7 @@ progress { font-weight: 300; line-height: 1.2; } + @media (min-width: 1200px) { .display-6 { font-size: 2.5rem; @@ -530,6 +548,7 @@ progress { .list-inline-item { display: inline-block; } + .list-inline-item:not(:last-child) { margin-right: 0.5rem; } @@ -543,6 +562,7 @@ progress { margin-bottom: 1rem; font-size: 1.25rem; } + .blockquote > :last-child { margin-bottom: 0; } @@ -553,6 +573,7 @@ progress { font-size: 0.875em; color: #6c757d; } + .blockquote-footer::before { content: "— "; } @@ -604,26 +625,31 @@ progress { 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; @@ -633,6 +659,7 @@ progress { margin-right: calc(var(--bs-gutter-x) / -2); margin-left: calc(var(--bs-gutter-x) / -2); } + .row > * { flex-shrink: 0; width: 100%; @@ -1063,6 +1090,7 @@ progress { --bs-gutter-y: 3rem; } } + @media (min-width: 768px) { .col-md { flex: 1 0 0%; @@ -1276,6 +1304,7 @@ progress { --bs-gutter-y: 3rem; } } + @media (min-width: 992px) { .col-lg { flex: 1 0 0%; @@ -1489,6 +1518,7 @@ progress { --bs-gutter-y: 3rem; } } + @media (min-width: 1200px) { .col-xl { flex: 1 0 0%; @@ -1702,6 +1732,7 @@ progress { --bs-gutter-y: 3rem; } } + @media (min-width: 1400px) { .col-xxl { flex: 1 0 0%; @@ -1915,6 +1946,7 @@ progress { --bs-gutter-y: 3rem; } } + .table { --bs-table-bg: transparent; --bs-table-accent-bg: transparent; @@ -1930,18 +1962,22 @@ progress { vertical-align: top; border-color: #dee2e6; } + .table > :not(caption) > * > * { padding: 0.5rem 0.5rem; background-color: var(--bs-table-bg); border-bottom-width: 0.125rem; box-shadow: inset 0 0 0 9999px var(--bs-table-accent-bg); } + .table > tbody { vertical-align: inherit; } + .table > thead { vertical-align: bottom; } + .table > :not(:last-child) > :last-child > * { border-bottom-color: currentColor; } @@ -1957,6 +1993,7 @@ progress { .table-bordered > :not(caption) > * { border-width: 0.125rem 0; } + .table-bordered > :not(caption) > * > * { border-width: 0 0.125rem; } @@ -2087,30 +2124,35 @@ progress { -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; } @@ -2158,17 +2200,21 @@ progress { border-radius: 0.5rem; 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; @@ -2176,25 +2222,31 @@ progress { outline: 0; box-shadow: 0 0 0 0.25rem rgba(26, 188, 156, 0.25); } + .form-control::-webkit-date-and-time-value { height: 1.5em; } + .form-control::-moz-placeholder { color: #6c757d; opacity: 1; } + .form-control:-ms-input-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::file-selector-button { padding: 0.375rem 0.75rem; margin: -0.375rem -0.75rem; @@ -2210,14 +2262,17 @@ progress { 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::file-selector-button { transition: none; } } + .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; @@ -2234,12 +2289,14 @@ progress { -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; } @@ -2255,6 +2312,7 @@ progress { border: solid transparent; border-width: 0.125rem 0; } + .form-control-plaintext.form-control-sm, .form-control-plaintext.form-control-lg { padding-right: 0; padding-left: 0; @@ -2266,12 +2324,14 @@ progress { font-size: 0.875rem; border-radius: 0.25rem; } + .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; @@ -2285,12 +2345,14 @@ progress { font-size: 1.25rem; border-radius: 0.75rem; } + .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; @@ -2301,9 +2363,11 @@ progress { textarea.form-control { min-height: calc(1.5em + 1rem); } + textarea.form-control-sm { min-height: calc(1.5em + 0.75rem); } + textarea.form-control-lg { min-height: calc(1.5em + 1.25rem); } @@ -2313,13 +2377,16 @@ textarea.form-control-lg { 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.5rem; } + .form-control-color::-webkit-color-swatch { height: 1.5em; border-radius: 0.5rem; @@ -2344,18 +2411,22 @@ textarea.form-control-lg { -moz-appearance: none; appearance: none; } + .form-select:focus { border-color: #8ddece; outline: 0; box-shadow: 0 0 0 0.25rem rgba(26, 188, 156, 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; @@ -2381,6 +2452,7 @@ textarea.form-control-lg { padding-left: 1.5em; margin-bottom: 0.125rem; } + .form-check .form-check-input { float: left; margin-left: -1.5em; @@ -2402,40 +2474,50 @@ textarea.form-control-lg { -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: #8ddece; outline: 0; box-shadow: 0 0 0 0.25rem rgba(26, 188, 156, 0.25); } + .form-check-input:checked { background-color: #1abc9c; border-color: #1abc9c; } + .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: #1abc9c; border-color: #1abc9c; 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; } @@ -2443,6 +2525,7 @@ textarea.form-control-lg { .form-switch { padding-left: 2.5em; } + .form-switch .form-check-input { width: 2em; margin-left: -2.5em; @@ -2451,14 +2534,17 @@ textarea.form-control-lg { 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='%238ddece'/%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"); @@ -2474,6 +2560,7 @@ textarea.form-control-lg { clip: rect(0, 0, 0, 0); pointer-events: none; } + .btn-check[disabled] + .btn, .btn-check:disabled + .btn { pointer-events: none; filter: none; @@ -2489,18 +2576,23 @@ textarea.form-control-lg { -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(26, 188, 156, 0.25); } + .form-range:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 0.25rem rgba(26, 188, 156, 0.25); } + .form-range::-moz-focus-outer { border: 0; } + .form-range::-webkit-slider-thumb { width: 1rem; height: 1rem; @@ -2513,15 +2605,18 @@ textarea.form-control-lg { -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: #baebe1; } + .form-range::-webkit-slider-runnable-track { width: 100%; height: 0.5rem; @@ -2531,6 +2626,7 @@ textarea.form-control-lg { border-color: transparent; border-radius: 1rem; } + .form-range::-moz-range-thumb { width: 1rem; height: 1rem; @@ -2542,15 +2638,18 @@ textarea.form-control-lg { -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: #baebe1; } + .form-range::-moz-range-track { width: 100%; height: 0.5rem; @@ -2560,12 +2659,15 @@ textarea.form-control-lg { 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; } @@ -2573,11 +2675,13 @@ textarea.form-control-lg { .form-floating { position: relative; } + .form-floating > .form-control, .form-floating > .form-select { height: 5.5rem; padding: 1.5rem 0; } + .form-floating > label { position: absolute; top: 0; @@ -2589,54 +2693,67 @@ textarea.form-control-lg { 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::-moz-placeholder { color: transparent; } + .form-floating > .form-control:-ms-input-placeholder { color: transparent; } + .form-floating > .form-control::placeholder { color: transparent; } + .form-floating > .form-control:not(:-moz-placeholder-shown) { padding-top: 2.5rem; padding-bottom: 1.5rem; } + .form-floating > .form-control:not(:-ms-input-placeholder) { padding-top: 2.5rem; padding-bottom: 1.5rem; } + .form-floating > .form-control:focus, .form-floating > .form-control:not(:placeholder-shown) { padding-top: 2.5rem; padding-bottom: 1.5rem; } + .form-floating > .form-control:-webkit-autofill { padding-top: 2.5rem; padding-bottom: 1.5rem; } + .form-floating > .form-select { padding-top: 2.5rem; padding-bottom: 1.5rem; } + .form-floating > .form-control:not(:-moz-placeholder-shown) ~ label { opacity: 0.65; transform: scale(0.65) translateY(-0.5rem) translateX(0rem); } + .form-floating > .form-control:not(:-ms-input-placeholder) ~ label { opacity: 0.65; transform: scale(0.65) translateY(-0.5rem) translateX(0rem); } + .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.65) translateY(-0.5rem) translateX(0rem); } + .form-floating > .form-control:-webkit-autofill ~ label { opacity: 0.65; transform: scale(0.65) translateY(-0.5rem) translateX(0rem); @@ -2649,6 +2766,7 @@ textarea.form-control-lg { align-items: stretch; width: 100%; } + .input-group > .form-control, .input-group > .form-select { position: relative; @@ -2656,14 +2774,17 @@ textarea.form-control-lg { 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; } @@ -2711,11 +2832,13 @@ textarea.form-control-lg { 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: -0.125rem; border-top-left-radius: 0; @@ -2759,6 +2882,7 @@ textarea.form-control-lg { 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); @@ -2772,12 +2896,14 @@ textarea.form-control-lg { .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); @@ -2786,12 +2912,15 @@ textarea.form-control-lg { .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; } @@ -2805,6 +2934,7 @@ textarea.form-control-lg { .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 { @@ -2848,6 +2978,7 @@ textarea.form-control-lg { 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); @@ -2861,12 +2992,14 @@ textarea.form-control-lg { .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); @@ -2875,12 +3008,15 @@ textarea.form-control-lg { .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; } @@ -2894,6 +3030,7 @@ textarea.form-control-lg { .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 { @@ -2920,18 +3057,22 @@ textarea.form-control-lg { border-radius: 0.5rem; 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(26, 188, 156, 0.25); } + .btn:disabled, .btn.disabled, fieldset:disabled .btn { pointer-events: none; opacity: 0.65; @@ -2942,25 +3083,30 @@ textarea.form-control-lg { background-color: #1abc9c; border-color: #1abc9c; } + .btn-primary:hover { color: #fff; background-color: #16a085; border-color: #15967d; } + .btn-check:focus + .btn-primary, .btn-primary:focus { color: #fff; background-color: #16a085; border-color: #15967d; box-shadow: 0 0 0 0.25rem rgba(60, 198, 171, 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: #15967d; border-color: #148d75; } + .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(60, 198, 171, 0.5); } + .btn-primary:disabled, .btn-primary.disabled { color: #fff; background-color: #1abc9c; @@ -2972,25 +3118,30 @@ textarea.form-control-lg { background-color: #2c3e50; border-color: #2c3e50; } + .btn-secondary:hover { color: #fff; background-color: #253544; border-color: #233240; } + .btn-check:focus + .btn-secondary, .btn-secondary:focus { color: #fff; background-color: #253544; border-color: #233240; box-shadow: 0 0 0 0.25rem rgba(76, 91, 106, 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: #233240; border-color: #212f3c; } + .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(76, 91, 106, 0.5); } + .btn-secondary:disabled, .btn-secondary.disabled { color: #fff; background-color: #2c3e50; @@ -3002,25 +3153,30 @@ textarea.form-control-lg { 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; @@ -3032,25 +3188,30 @@ textarea.form-control-lg { 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; @@ -3062,25 +3223,30 @@ textarea.form-control-lg { 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; @@ -3092,25 +3258,30 @@ textarea.form-control-lg { 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; @@ -3122,25 +3293,30 @@ textarea.form-control-lg { 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; @@ -3152,25 +3328,30 @@ textarea.form-control-lg { 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; @@ -3181,22 +3362,27 @@ textarea.form-control-lg { color: #1abc9c; border-color: #1abc9c; } + .btn-outline-primary:hover { color: #fff; background-color: #1abc9c; border-color: #1abc9c; } + .btn-check:focus + .btn-outline-primary, .btn-outline-primary:focus { box-shadow: 0 0 0 0.25rem rgba(26, 188, 156, 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: #1abc9c; border-color: #1abc9c; } + .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(26, 188, 156, 0.5); } + .btn-outline-primary:disabled, .btn-outline-primary.disabled { color: #1abc9c; background-color: transparent; @@ -3206,22 +3392,27 @@ textarea.form-control-lg { color: #2c3e50; border-color: #2c3e50; } + .btn-outline-secondary:hover { color: #fff; background-color: #2c3e50; border-color: #2c3e50; } + .btn-check:focus + .btn-outline-secondary, .btn-outline-secondary:focus { box-shadow: 0 0 0 0.25rem rgba(44, 62, 80, 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: #2c3e50; border-color: #2c3e50; } + .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(44, 62, 80, 0.5); } + .btn-outline-secondary:disabled, .btn-outline-secondary.disabled { color: #2c3e50; background-color: transparent; @@ -3231,22 +3422,27 @@ textarea.form-control-lg { 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; @@ -3256,22 +3452,27 @@ textarea.form-control-lg { 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; @@ -3281,22 +3482,27 @@ textarea.form-control-lg { 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; @@ -3306,22 +3512,27 @@ textarea.form-control-lg { 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; @@ -3331,22 +3542,27 @@ textarea.form-control-lg { 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; @@ -3356,22 +3572,27 @@ textarea.form-control-lg { 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; @@ -3382,9 +3603,11 @@ textarea.form-control-lg { color: #1abc9c; text-decoration: underline; } + .btn-link:hover { color: #15967d; } + .btn-link:disabled, .btn-link.disabled { color: #6c757d; } @@ -3404,11 +3627,13 @@ textarea.form-control-lg { .fade { transition: opacity 0.15s linear; } + @media (prefers-reduced-motion: reduce) { .fade { transition: none; } } + .fade:not(.show) { opacity: 0; } @@ -3422,6 +3647,7 @@ textarea.form-control-lg { overflow: hidden; transition: height 0.35s ease; } + @media (prefers-reduced-motion: reduce) { .collapsing { transition: none; @@ -3438,6 +3664,7 @@ textarea.form-control-lg { .dropdown-toggle { white-space: nowrap; } + .dropdown-toggle::after { display: inline-block; margin-left: 0.255em; @@ -3448,6 +3675,7 @@ textarea.form-control-lg { border-bottom: 0; border-left: 0.3em solid transparent; } + .dropdown-toggle:empty::after { margin-left: 0; } @@ -3468,6 +3696,7 @@ textarea.form-control-lg { border: 0.125rem solid rgba(0, 0, 0, 0.15); border-radius: 0.5rem; } + .dropdown-menu[data-bs-popper] { top: 100%; left: 0; @@ -3477,6 +3706,7 @@ textarea.form-control-lg { .dropdown-menu-start { --bs-position: start; } + .dropdown-menu-start[data-bs-popper] { right: auto /* rtl:ignore */; left: 0 /* rtl:ignore */; @@ -3485,6 +3715,7 @@ textarea.form-control-lg { .dropdown-menu-end { --bs-position: end; } + .dropdown-menu-end[data-bs-popper] { right: 0 /* rtl:ignore */; left: auto /* rtl:ignore */; @@ -3494,6 +3725,7 @@ textarea.form-control-lg { .dropdown-menu-sm-start { --bs-position: start; } + .dropdown-menu-sm-start[data-bs-popper] { right: auto /* rtl:ignore */; left: 0 /* rtl:ignore */; @@ -3502,15 +3734,18 @@ textarea.form-control-lg { .dropdown-menu-sm-end { --bs-position: end; } + .dropdown-menu-sm-end[data-bs-popper] { right: 0 /* rtl:ignore */; left: auto /* rtl:ignore */; } } + @media (min-width: 768px) { .dropdown-menu-md-start { --bs-position: start; } + .dropdown-menu-md-start[data-bs-popper] { right: auto /* rtl:ignore */; left: 0 /* rtl:ignore */; @@ -3519,15 +3754,18 @@ textarea.form-control-lg { .dropdown-menu-md-end { --bs-position: end; } + .dropdown-menu-md-end[data-bs-popper] { right: 0 /* rtl:ignore */; left: auto /* rtl:ignore */; } } + @media (min-width: 992px) { .dropdown-menu-lg-start { --bs-position: start; } + .dropdown-menu-lg-start[data-bs-popper] { right: auto /* rtl:ignore */; left: 0 /* rtl:ignore */; @@ -3536,15 +3774,18 @@ textarea.form-control-lg { .dropdown-menu-lg-end { --bs-position: end; } + .dropdown-menu-lg-end[data-bs-popper] { right: 0 /* rtl:ignore */; left: auto /* rtl:ignore */; } } + @media (min-width: 1200px) { .dropdown-menu-xl-start { --bs-position: start; } + .dropdown-menu-xl-start[data-bs-popper] { right: auto /* rtl:ignore */; left: 0 /* rtl:ignore */; @@ -3553,15 +3794,18 @@ textarea.form-control-lg { .dropdown-menu-xl-end { --bs-position: end; } + .dropdown-menu-xl-end[data-bs-popper] { right: 0 /* rtl:ignore */; left: auto /* rtl:ignore */; } } + @media (min-width: 1400px) { .dropdown-menu-xxl-start { --bs-position: start; } + .dropdown-menu-xxl-start[data-bs-popper] { right: auto /* rtl:ignore */; left: 0 /* rtl:ignore */; @@ -3570,17 +3814,20 @@ textarea.form-control-lg { .dropdown-menu-xxl-end { --bs-position: end; } + .dropdown-menu-xxl-end[data-bs-popper] { right: 0 /* rtl:ignore */; left: auto /* rtl:ignore */; } } + .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; @@ -3591,6 +3838,7 @@ textarea.form-control-lg { border-bottom: 0.3em solid; border-left: 0.3em solid transparent; } + .dropup .dropdown-toggle:empty::after { margin-left: 0; } @@ -3602,6 +3850,7 @@ textarea.form-control-lg { margin-top: 0; margin-left: 0.125rem; } + .dropend .dropdown-toggle::after { display: inline-block; margin-left: 0.255em; @@ -3612,9 +3861,11 @@ textarea.form-control-lg { 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; } @@ -3626,15 +3877,18 @@ textarea.form-control-lg { 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; @@ -3644,9 +3898,11 @@ textarea.form-control-lg { 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; } @@ -3671,15 +3927,18 @@ textarea.form-control-lg { 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: #1abc9c; } + .dropdown-item.disabled, .dropdown-item:disabled { color: #adb5bd; pointer-events: none; @@ -3710,26 +3969,33 @@ textarea.form-control-lg { 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: #1abc9c; } + .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; } @@ -3740,11 +4006,13 @@ textarea.form-control-lg { 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, @@ -3765,6 +4033,7 @@ textarea.form-control-lg { flex-wrap: wrap; justify-content: flex-start; } + .btn-toolbar .input-group { width: auto; } @@ -3773,11 +4042,13 @@ textarea.form-control-lg { .btn-group > .btn-group:not(:first-child) { margin-left: -0.125rem; } + .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 { @@ -3789,9 +4060,11 @@ textarea.form-control-lg { 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; } @@ -3811,19 +4084,23 @@ textarea.form-control-lg { 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: -0.125rem; } + .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; @@ -3845,14 +4122,17 @@ textarea.form-control-lg { 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: #15967d; } + .nav-link.disabled { color: #6c757d; pointer-events: none; @@ -3862,6 +4142,7 @@ textarea.form-control-lg { .nav-tabs { border-bottom: 0.125rem solid #dee2e6; } + .nav-tabs .nav-link { margin-bottom: -0.125rem; background: none; @@ -3869,21 +4150,25 @@ textarea.form-control-lg { border-top-left-radius: 0.5rem; border-top-right-radius: 0.5rem; } + .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: -0.125rem; border-top-left-radius: 0; @@ -3895,6 +4180,7 @@ textarea.form-control-lg { border: 0; border-radius: 0.5rem; } + .nav-pills .nav-link.active, .nav-pills .show > .nav-link { color: #fff; @@ -3922,6 +4208,7 @@ textarea.form-control-lg { .tab-content > .tab-pane { display: none; } + .tab-content > .active { display: block; } @@ -3935,6 +4222,7 @@ textarea.form-control-lg { padding-top: 0.5rem; padding-bottom: 0.5rem; } + .navbar > .container, .navbar > .container-fluid, .navbar > .container-sm, @@ -3947,6 +4235,7 @@ textarea.form-control-lg { align-items: center; justify-content: space-between; } + .navbar-brand { padding-top: 0.3125rem; padding-bottom: 0.3125rem; @@ -3955,6 +4244,7 @@ textarea.form-control-lg { text-decoration: none; white-space: nowrap; } + .navbar-nav { display: flex; flex-direction: column; @@ -3962,10 +4252,12 @@ textarea.form-control-lg { margin-bottom: 0; list-style: none; } + .navbar-nav .nav-link { padding-right: 0; padding-left: 0; } + .navbar-nav .dropdown-menu { position: static; } @@ -3990,14 +4282,17 @@ textarea.form-control-lg { border-radius: 0.5rem; 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; @@ -4024,152 +4319,193 @@ textarea.form-control-lg { 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; } } + @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; } } + @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; } } + @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; } } + @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 { 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; } @@ -4177,32 +4513,41 @@ textarea.form-control-lg { .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 { @@ -4212,32 +4557,41 @@ textarea.form-control-lg { .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 { @@ -4255,24 +4609,29 @@ textarea.form-control-lg { border: 0.125rem solid rgba(0, 0, 0, 0.125); border-radius: 0.5rem; } + .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: 0.375rem; border-top-right-radius: 0.375rem; } + .card > .list-group:last-child { border-bottom-width: 0; border-bottom-right-radius: 0.375rem; border-bottom-left-radius: 0.375rem; } + .card > .card-header + .list-group, .card > .list-group + .card-footer { border-top: 0; @@ -4299,6 +4658,7 @@ textarea.form-control-lg { .card-link:hover { text-decoration: none; } + .card-link + .card-link { margin-left: 1rem; } @@ -4309,6 +4669,7 @@ textarea.form-control-lg { background-color: rgba(0, 0, 0, 0.03); border-bottom: 0.125rem solid rgba(0, 0, 0, 0.125); } + .card-header:first-child { border-radius: 0.375rem 0.375rem 0 0; } @@ -4318,6 +4679,7 @@ textarea.form-control-lg { background-color: rgba(0, 0, 0, 0.03); border-top: 0.125rem solid rgba(0, 0, 0, 0.125); } + .card-footer:last-child { border-radius: 0 0 0.375rem 0.375rem; } @@ -4365,39 +4727,48 @@ textarea.form-control-lg { .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; @@ -4419,20 +4790,24 @@ textarea.form-control-lg { 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: #17a98c; background-color: #e8f8f5; box-shadow: inset 0 -0.125rem 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='%2317a98c'%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; @@ -4444,14 +4819,17 @@ textarea.form-control-lg { 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: #8ddece; @@ -4467,25 +4845,31 @@ textarea.form-control-lg { background-color: #fff; border: 0.125rem solid rgba(0, 0, 0, 0.125); } + .accordion-item:first-of-type { border-top-left-radius: 0.5rem; border-top-right-radius: 0.5rem; } + .accordion-item:first-of-type .accordion-button { border-top-left-radius: 0.375rem; border-top-right-radius: 0.375rem; } + .accordion-item:not(:first-of-type) { border-top: 0; } + .accordion-item:last-of-type { border-bottom-right-radius: 0.5rem; border-bottom-left-radius: 0.5rem; } + .accordion-item:last-of-type .accordion-button.collapsed { border-bottom-right-radius: 0.375rem; border-bottom-left-radius: 0.375rem; } + .accordion-item:last-of-type .accordion-collapse { border-bottom-right-radius: 0.5rem; border-bottom-left-radius: 0.5rem; @@ -4498,17 +4882,21 @@ textarea.form-control-lg { .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; } @@ -4524,12 +4912,14 @@ textarea.form-control-lg { .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; } @@ -4549,17 +4939,20 @@ textarea.form-control-lg { border: 0.125rem 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: #15967d; background-color: #e9ecef; border-color: #dee2e6; } + .page-link:focus { z-index: 3; color: #15967d; @@ -4571,12 +4964,14 @@ textarea.form-control-lg { .page-item:not(:first-child) .page-link { margin-left: -0.125rem; } + .page-item.active .page-link { z-index: 3; color: #fff; background-color: #1abc9c; border-color: #1abc9c; } + .page-item.disabled .page-link { color: #6c757d; pointer-events: none; @@ -4592,6 +4987,7 @@ textarea.form-control-lg { border-top-left-radius: 0.5rem; border-bottom-left-radius: 0.5rem; } + .page-item:last-child .page-link { border-top-right-radius: 0.5rem; border-bottom-right-radius: 0.5rem; @@ -4601,10 +4997,12 @@ textarea.form-control-lg { padding: 0.75rem 1.5rem; font-size: 1.25rem; } + .pagination-lg .page-item:first-child .page-link { border-top-left-radius: 0.75rem; border-bottom-left-radius: 0.75rem; } + .pagination-lg .page-item:last-child .page-link { border-top-right-radius: 0.75rem; border-bottom-right-radius: 0.75rem; @@ -4614,10 +5012,12 @@ textarea.form-control-lg { padding: 0.25rem 0.5rem; font-size: 0.875rem; } + .pagination-sm .page-item:first-child .page-link { border-top-left-radius: 0.25rem; border-bottom-left-radius: 0.25rem; } + .pagination-sm .page-item:last-child .page-link { border-top-right-radius: 0.25rem; border-bottom-right-radius: 0.25rem; @@ -4635,6 +5035,7 @@ textarea.form-control-lg { vertical-align: baseline; border-radius: 0.5rem; } + .badge:empty { display: none; } @@ -4663,6 +5064,7 @@ textarea.form-control-lg { .alert-dismissible { padding-right: 3rem; } + .alert-dismissible .btn-close { position: absolute; top: 0; @@ -4676,6 +5078,7 @@ textarea.form-control-lg { background-color: #d1f2eb; border-color: #baebe1; } + .alert-primary .alert-link { color: #0d5a4b; } @@ -4685,6 +5088,7 @@ textarea.form-control-lg { background-color: #d5d8dc; border-color: #c0c5cb; } + .alert-secondary .alert-link { color: #151e26; } @@ -4694,6 +5098,7 @@ textarea.form-control-lg { background-color: #d1e7dd; border-color: #badbcc; } + .alert-success .alert-link { color: #0c4128; } @@ -4703,6 +5108,7 @@ textarea.form-control-lg { background-color: #cff4fc; border-color: #b6effb; } + .alert-info .alert-link { color: #066173; } @@ -4712,6 +5118,7 @@ textarea.form-control-lg { background-color: #fff3cd; border-color: #ffecb5; } + .alert-warning .alert-link { color: #7a5d03; } @@ -4721,6 +5128,7 @@ textarea.form-control-lg { background-color: #f8d7da; border-color: #f5c2c7; } + .alert-danger .alert-link { color: #6a1a21; } @@ -4730,6 +5138,7 @@ textarea.form-control-lg { background-color: #fefefe; border-color: #fdfdfe; } + .alert-light .alert-link { color: #777778; } @@ -4739,6 +5148,7 @@ textarea.form-control-lg { background-color: #d3d3d4; border-color: #bcbebf; } + .alert-dark .alert-link { color: #101214; } @@ -4754,6 +5164,7 @@ textarea.form-control-lg { background-position-x: 1rem; } } + .progress { display: flex; height: 1rem; @@ -4774,6 +5185,7 @@ textarea.form-control-lg { background-color: #1abc9c; transition: width 0.6s ease; } + @media (prefers-reduced-motion: reduce) { .progress-bar { transition: none; @@ -4789,6 +5201,7 @@ textarea.form-control-lg { -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; @@ -4808,6 +5221,7 @@ textarea.form-control-lg { list-style-type: none; counter-reset: section; } + .list-group-numbered > li::before { content: counters(section, ".") ". "; counter-increment: section; @@ -4818,12 +5232,14 @@ textarea.form-control-lg { 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; @@ -4838,28 +5254,34 @@ textarea.form-control-lg { background-color: #fff; border: 0.125rem 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: #1abc9c; border-color: #1abc9c; } + .list-group-item + .list-group-item { border-top-width: 0; } + .list-group-item + .list-group-item.active { margin-top: -0.125rem; border-top-width: 0.125rem; @@ -4868,21 +5290,26 @@ textarea.form-control-lg { .list-group-horizontal { flex-direction: row; } + .list-group-horizontal > .list-group-item:first-child { border-bottom-left-radius: 0.5rem; border-top-right-radius: 0; } + .list-group-horizontal > .list-group-item:last-child { border-top-right-radius: 0.5rem; 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: 0.125rem; border-left-width: 0; } + .list-group-horizontal > .list-group-item + .list-group-item.active { margin-left: -0.125rem; border-left-width: 0.125rem; @@ -4892,128 +5319,160 @@ textarea.form-control-lg { .list-group-horizontal-sm { flex-direction: row; } + .list-group-horizontal-sm > .list-group-item:first-child { border-bottom-left-radius: 0.5rem; border-top-right-radius: 0; } + .list-group-horizontal-sm > .list-group-item:last-child { border-top-right-radius: 0.5rem; 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: 0.125rem; border-left-width: 0; } + .list-group-horizontal-sm > .list-group-item + .list-group-item.active { margin-left: -0.125rem; border-left-width: 0.125rem; } } + @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.5rem; border-top-right-radius: 0; } + .list-group-horizontal-md > .list-group-item:last-child { border-top-right-radius: 0.5rem; 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: 0.125rem; border-left-width: 0; } + .list-group-horizontal-md > .list-group-item + .list-group-item.active { margin-left: -0.125rem; border-left-width: 0.125rem; } } + @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.5rem; border-top-right-radius: 0; } + .list-group-horizontal-lg > .list-group-item:last-child { border-top-right-radius: 0.5rem; 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: 0.125rem; border-left-width: 0; } + .list-group-horizontal-lg > .list-group-item + .list-group-item.active { margin-left: -0.125rem; border-left-width: 0.125rem; } } + @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.5rem; border-top-right-radius: 0; } + .list-group-horizontal-xl > .list-group-item:last-child { border-top-right-radius: 0.5rem; 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: 0.125rem; border-left-width: 0; } + .list-group-horizontal-xl > .list-group-item + .list-group-item.active { margin-left: -0.125rem; border-left-width: 0.125rem; } } + @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.5rem; border-top-right-radius: 0; } + .list-group-horizontal-xxl > .list-group-item:last-child { border-top-right-radius: 0.5rem; 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: 0.125rem; border-left-width: 0; } + .list-group-horizontal-xxl > .list-group-item + .list-group-item.active { margin-left: -0.125rem; border-left-width: 0.125rem; } } + .list-group-flush { border-radius: 0; } + .list-group-flush > .list-group-item { border-width: 0 0 0.125rem; } + .list-group-flush > .list-group-item:last-child { border-bottom-width: 0; } @@ -5022,10 +5481,12 @@ textarea.form-control-lg { color: #10715e; background-color: #d1f2eb; } + .list-group-item-primary.list-group-item-action:hover, .list-group-item-primary.list-group-item-action:focus { color: #10715e; background-color: #bcdad4; } + .list-group-item-primary.list-group-item-action.active { color: #fff; background-color: #10715e; @@ -5036,10 +5497,12 @@ textarea.form-control-lg { color: #1a2530; background-color: #d5d8dc; } + .list-group-item-secondary.list-group-item-action:hover, .list-group-item-secondary.list-group-item-action:focus { color: #1a2530; background-color: #c0c2c6; } + .list-group-item-secondary.list-group-item-action.active { color: #fff; background-color: #1a2530; @@ -5050,10 +5513,12 @@ textarea.form-control-lg { 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; @@ -5064,10 +5529,12 @@ textarea.form-control-lg { color: #087990; background-color: #cff4fc; } + .list-group-item-info.list-group-item-action:hover, .list-group-item-info.list-group-item-action:focus { color: #087990; background-color: #badce3; } + .list-group-item-info.list-group-item-action.active { color: #fff; background-color: #087990; @@ -5078,10 +5545,12 @@ textarea.form-control-lg { color: #997404; background-color: #fff3cd; } + .list-group-item-warning.list-group-item-action:hover, .list-group-item-warning.list-group-item-action:focus { color: #997404; background-color: #e6dbb9; } + .list-group-item-warning.list-group-item-action.active { color: #fff; background-color: #997404; @@ -5092,10 +5561,12 @@ textarea.form-control-lg { 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; @@ -5106,10 +5577,12 @@ textarea.form-control-lg { color: #959596; background-color: #fefefe; } + .list-group-item-light.list-group-item-action:hover, .list-group-item-light.list-group-item-action:focus { color: #959596; background-color: #e5e5e5; } + .list-group-item-light.list-group-item-action.active { color: #fff; background-color: #959596; @@ -5120,10 +5593,12 @@ textarea.form-control-lg { 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; @@ -5141,16 +5616,19 @@ textarea.form-control-lg { border-radius: 0.5rem; 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(26, 188, 156, 0.25); opacity: 1; } + .btn-close:disabled, .btn-close.disabled { pointer-events: none; -webkit-user-select: none; @@ -5175,9 +5653,11 @@ textarea.form-control-lg { box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15); border-radius: 0.5rem; } + .toast:not(.showing):not(.show) { opacity: 0; } + .toast.hide { display: none; } @@ -5189,6 +5669,7 @@ textarea.form-control-lg { max-width: 100%; pointer-events: none; } + .toast-container > :not(:last-child) { margin-bottom: 0.75rem; } @@ -5204,6 +5685,7 @@ textarea.form-control-lg { border-top-left-radius: calc(0.5rem - 1px); border-top-right-radius: calc(0.5rem - 1px); } + .toast-header .btn-close { margin-right: -0.375rem; margin-left: 0.75rem; @@ -5233,18 +5715,22 @@ textarea.form-control-lg { 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); } @@ -5252,10 +5738,12 @@ textarea.form-control-lg { .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; } @@ -5288,9 +5776,11 @@ textarea.form-control-lg { height: 100vh; background-color: #000; } + .modal-backdrop.fade { opacity: 0; } + .modal-backdrop.show { opacity: 0.5; } @@ -5305,6 +5795,7 @@ textarea.form-control-lg { border-top-left-radius: 0.625rem; border-top-right-radius: 0.625rem; } + .modal-header .btn-close { padding: 0.5rem 0.5rem; margin: -0.5rem -0.5rem -0.5rem auto; @@ -5332,6 +5823,7 @@ textarea.form-control-lg { border-bottom-right-radius: 0.625rem; border-bottom-left-radius: 0.625rem; } + .modal-footer > * { margin: 0.25rem; } @@ -5354,34 +5846,41 @@ textarea.form-control-lg { 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; } @@ -5393,21 +5892,26 @@ textarea.form-control-lg { 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; @@ -5415,21 +5919,26 @@ textarea.form-control-lg { 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; @@ -5437,21 +5946,26 @@ textarea.form-control-lg { 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; @@ -5459,21 +5973,26 @@ textarea.form-control-lg { 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; @@ -5481,21 +6000,26 @@ textarea.form-control-lg { 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; @@ -5519,15 +6043,18 @@ textarea.form-control-lg { 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: ""; @@ -5538,9 +6065,11 @@ textarea.form-control-lg { .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; @@ -5550,11 +6079,13 @@ textarea.form-control-lg { .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; @@ -5564,9 +6095,11 @@ textarea.form-control-lg { .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; @@ -5576,11 +6109,13 @@ textarea.form-control-lg { .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; @@ -5624,12 +6159,14 @@ textarea.form-control-lg { border: 0.125rem solid rgba(0, 0, 0, 0.2); border-radius: 0.75rem; } + .popover .popover-arrow { position: absolute; display: block; width: 1rem; height: 0.5rem; } + .popover .popover-arrow::before, .popover .popover-arrow::after { position: absolute; display: block; @@ -5641,11 +6178,13 @@ textarea.form-control-lg { .bs-popover-top > .popover-arrow, .bs-popover-auto[data-popper-placement^=top] > .popover-arrow { bottom: -0.625rem; } + .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: 0.125rem; border-width: 0.5rem 0.5rem 0; @@ -5657,11 +6196,13 @@ textarea.form-control-lg { 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: 0.125rem; border-width: 0.5rem 0.5rem 0.5rem 0; @@ -5671,16 +6212,19 @@ textarea.form-control-lg { .bs-popover-bottom > .popover-arrow, .bs-popover-auto[data-popper-placement^=bottom] > .popover-arrow { top: -0.625rem; } + .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: 0.125rem; 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; @@ -5697,11 +6241,13 @@ textarea.form-control-lg { 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: 0.125rem; border-width: 0.5rem 0 0.5rem 0.5rem; @@ -5717,6 +6263,7 @@ textarea.form-control-lg { border-top-left-radius: 0.625rem; border-top-right-radius: 0.625rem; } + .popover-header:empty { display: none; } @@ -5739,6 +6286,7 @@ textarea.form-control-lg { width: 100%; overflow: hidden; } + .carousel-inner::after { display: block; clear: both; @@ -5755,6 +6303,7 @@ textarea.form-control-lg { backface-visibility: hidden; transition: transform 0.6s ease-in-out; } + @media (prefers-reduced-motion: reduce) { .carousel-item { transition: none; @@ -5784,18 +6333,21 @@ textarea.form-control-lg { 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 { @@ -5821,12 +6373,14 @@ textarea.form-control-lg { 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 { @@ -5884,6 +6438,7 @@ textarea.form-control-lg { margin-left: 15%; list-style: none; } + .carousel-indicators [data-bs-target] { box-sizing: content-box; flex: 0 1 auto; @@ -5902,11 +6457,13 @@ textarea.form-control-lg { 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; } @@ -5926,9 +6483,11 @@ textarea.form-control-lg { .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; } @@ -5944,6 +6503,7 @@ textarea.form-control-lg { transform: rotate(360deg) /* rtl:ignore */; } } + .spinner-border { display: inline-block; width: 2rem; @@ -5981,6 +6541,7 @@ textarea.form-control-lg { transform: none; } } + .spinner-grow { display: inline-block; width: 2rem; @@ -6005,6 +6566,7 @@ textarea.form-control-lg { animation-duration: 1.5s; } } + .offcanvas { position: fixed; bottom: 0; @@ -6018,6 +6580,7 @@ textarea.form-control-lg { outline: 0; transition: transform 0.3s ease-in-out; } + @media (prefers-reduced-motion: reduce) { .offcanvas { transition: none; @@ -6030,6 +6593,7 @@ textarea.form-control-lg { justify-content: space-between; padding: 1rem 1rem; } + .offcanvas-header .btn-close { padding: 0.5rem 0.5rem; margin: -0.5rem -0.5rem -0.5rem auto; @@ -6094,6 +6658,7 @@ textarea.form-control-lg { .link-primary { color: #1abc9c; } + .link-primary:hover, .link-primary:focus { color: #15967d; } @@ -6101,6 +6666,7 @@ textarea.form-control-lg { .link-secondary { color: #2c3e50; } + .link-secondary:hover, .link-secondary:focus { color: #233240; } @@ -6108,6 +6674,7 @@ textarea.form-control-lg { .link-success { color: #198754; } + .link-success:hover, .link-success:focus { color: #146c43; } @@ -6115,6 +6682,7 @@ textarea.form-control-lg { .link-info { color: #0dcaf0; } + .link-info:hover, .link-info:focus { color: #3dd5f3; } @@ -6122,6 +6690,7 @@ textarea.form-control-lg { .link-warning { color: #ffc107; } + .link-warning:hover, .link-warning:focus { color: #ffcd39; } @@ -6129,6 +6698,7 @@ textarea.form-control-lg { .link-danger { color: #dc3545; } + .link-danger:hover, .link-danger:focus { color: #b02a37; } @@ -6136,6 +6706,7 @@ textarea.form-control-lg { .link-light { color: #f8f9fa; } + .link-light:hover, .link-light:focus { color: #f9fafb; } @@ -6143,6 +6714,7 @@ textarea.form-control-lg { .link-dark { color: #212529; } + .link-dark:hover, .link-dark:focus { color: #1a1e21; } @@ -6151,11 +6723,13 @@ textarea.form-control-lg { position: relative; width: 100%; } + .ratio::before { display: block; padding-top: var(--bs-aspect-ratio); content: ""; } + .ratio > * { position: absolute; top: 0; @@ -6209,6 +6783,7 @@ textarea.form-control-lg { z-index: 1020; } } + @media (min-width: 768px) { .sticky-md-top { position: sticky; @@ -6216,6 +6791,7 @@ textarea.form-control-lg { z-index: 1020; } } + @media (min-width: 992px) { .sticky-lg-top { position: sticky; @@ -6223,6 +6799,7 @@ textarea.form-control-lg { z-index: 1020; } } + @media (min-width: 1200px) { .sticky-xl-top { position: sticky; @@ -6230,6 +6807,7 @@ textarea.form-control-lg { z-index: 1020; } } + @media (min-width: 1400px) { .sticky-xxl-top { position: sticky; @@ -6237,6 +6815,7 @@ textarea.form-control-lg { z-index: 1020; } } + .visually-hidden, .visually-hidden-focusable:not(:focus):not(:focus-within) { position: absolute !important; @@ -8162,6 +8741,7 @@ textarea.form-control-lg { text-align: center !important; } } + @media (min-width: 768px) { .float-md-start { float: left !important; @@ -8813,6 +9393,7 @@ textarea.form-control-lg { text-align: center !important; } } + @media (min-width: 992px) { .float-lg-start { float: left !important; @@ -9464,6 +10045,7 @@ textarea.form-control-lg { text-align: center !important; } } + @media (min-width: 1200px) { .float-xl-start { float: left !important; @@ -10115,6 +10697,7 @@ textarea.form-control-lg { text-align: center !important; } } + @media (min-width: 1400px) { .float-xxl-start { float: left !important; @@ -10766,6 +11349,7 @@ textarea.form-control-lg { text-align: center !important; } } + @media (min-width: 1200px) { .fs-1 { font-size: 2.5rem !important; @@ -10783,6 +11367,7 @@ textarea.form-control-lg { font-size: 1.5rem !important; } } + @media print { .d-print-inline { display: inline !important; @@ -10824,6 +11409,7 @@ textarea.form-control-lg { display: none !important; } } + html { height: 100%; scroll-padding-top: calc(4.5rem - 1px); @@ -10832,10 +11418,12 @@ html { .page-section { padding: 6rem 0; } + .page-section .page-section-heading { font-size: 2.25rem; line-height: 2rem; } + @media (min-width: 992px) { .page-section .page-section-heading { font-size: 3rem; @@ -10850,6 +11438,7 @@ html { justify-content: center; align-items: center; } + .divider-custom .divider-custom-line { width: 100%; max-width: 30rem; @@ -10858,19 +11447,24 @@ html { border-radius: 1rem; border-color: #2c3e50; } + .divider-custom .divider-custom-line:first-child { margin-right: 1rem; } + .divider-custom .divider-custom-line:last-child { margin-left: 1rem; } + .divider-custom .divider-custom-icon { color: #2c3e50; font-size: 2rem; } + .divider-custom.divider-light .divider-custom-line { background-color: #fff; } + .divider-custom.divider-light .divider-custom-icon { color: #fff; } @@ -10896,24 +11490,31 @@ html { font-family: "Montserrat", -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-weight: 700; } + #mainNav .navbar-brand { color: #fff; } + #mainNav .navbar-nav { margin-top: 1rem; } + #mainNav .navbar-nav li.nav-item a.nav-link { color: #fff; } + #mainNav .navbar-nav li.nav-item a.nav-link:hover { color: #1abc9c; } + #mainNav .navbar-nav li.nav-item a.nav-link:active, #mainNav .navbar-nav li.nav-item a.nav-link:focus { color: #fff; } + #mainNav .navbar-nav li.nav-item a.nav-link.active { color: #1abc9c; } + #mainNav .navbar-toggler { font-size: 80%; padding: 0.8rem; @@ -10925,17 +11526,21 @@ html { padding-bottom: 1.5rem; transition: padding-top 0.3s, padding-bottom 0.3s; } + #mainNav .navbar-brand { font-size: 1.75em; transition: font-size 0.3s; } + #mainNav .navbar-nav { margin-top: 0; } + #mainNav .navbar-nav > li.nav-item > a.nav-link.active { color: #fff; background: #1abc9c; } + #mainNav .navbar-nav > li.nav-item > a.nav-link.active:active, #mainNav .navbar-nav > li.nav-item > a.nav-link.active:focus, #mainNav .navbar-nav > li.nav-item > a.nav-link.active:hover { color: #fff; background: #1abc9c; @@ -10945,10 +11550,12 @@ html { padding-top: 0.5rem; padding-bottom: 0.5rem; } + #mainNav.navbar-shrink .navbar-brand { font-size: 1.5em; } } + .form-floating input.form-control, .form-floating textarea.form-control { font-size: 1.5rem; @@ -10958,10 +11565,12 @@ html { border-radius: 0; border-width: 1px; } + .form-floating input.form-control:focus, .form-floating textarea.form-control:focus { box-shadow: none; } + .form-floating label { font-size: 1.5rem; color: #6c757d; @@ -10971,13 +11580,16 @@ html { padding-top: calc(6rem + 74px); padding-bottom: 6rem; } + .masthead .masthead-heading { font-size: 2.75rem; line-height: 2.75rem; } + .masthead .masthead-subheading { font-size: 1.25rem; } + .masthead .masthead-avatar { width: 15rem; } @@ -10987,14 +11599,17 @@ html { padding-top: calc(6rem + 104px); padding-bottom: 6rem; } + .masthead .masthead-heading { font-size: 4rem; line-height: 3.5rem; } + .masthead .masthead-subheading { font-size: 1.5rem; } } + .portfolio .portfolio-item { cursor: pointer; position: relative; @@ -11003,6 +11618,7 @@ html { border-radius: 0.5rem; overflow: hidden; } + .portfolio .portfolio-item .portfolio-item-caption { position: absolute; top: 0; @@ -11011,9 +11627,11 @@ html { opacity: 0; background-color: rgba(26, 188, 156, 0.9); } + .portfolio .portfolio-item .portfolio-item-caption:hover { opacity: 1; } + .portfolio .portfolio-item .portfolio-item-caption .portfolio-item-caption-content { font-size: 1.5rem; } @@ -11023,10 +11641,12 @@ html { font-size: 2rem; padding: 1rem; } + .portfolio-modal .portfolio-modal-title { font-size: 2.25rem; line-height: 2rem; } + @media (min-width: 992px) { .portfolio-modal .portfolio-modal-title { font-size: 3rem; diff --git a/Frontend/src/test.ts b/Frontend/src/test.ts index 50193eb..1647182 100644 --- a/Frontend/src/test.ts +++ b/Frontend/src/test.ts @@ -1,23 +1,23 @@ // This file is required by karma.conf.js and loads recursively all the .spec and framework files import 'zone.js/dist/zone-testing'; -import { getTestBed } from '@angular/core/testing'; +import {getTestBed} from '@angular/core/testing'; import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting + BrowserDynamicTestingModule, + platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; declare const require: { - context(path: string, deep?: boolean, filter?: RegExp): { - keys(): string[]; - (id: string): T; - }; + context(path: string, deep?: boolean, filter?: RegExp): { + keys(): string[]; + (id: string): T; + }; }; // First, initialize the Angular testing environment. getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting() + BrowserDynamicTestingModule, + platformBrowserDynamicTesting() ); // Then we find all the tests. const context = require.context('./', true, /\.spec\.ts$/); diff --git a/README.md b/README.md index 45fab35..f4c214e 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Wiki: https://github.com/Mueller-Patrick/Betterzon/wiki # Code Quality [![Codacy Badge](https://app.codacy.com/project/badge/Grade/88e47ebf837b43af9d12147c22f77f7f)](https://www.codacy.com/gh/Mueller-Patrick/Betterzon/dashboard?utm_source=github.com&utm_medium=referral&utm_content=Mueller-Patrick/Betterzon&utm_campaign=Badge_Grade) -[![Code Coverage](https://img.shields.io/badge/coverage-71%25-green)](https://ci.betterzon.xyz) +[![Code Coverage](https://img.shields.io/badge/coverage-81%25-green)](https://ci.betterzon.xyz) # Project Status [![Website Status](https://img.shields.io/website?label=www.betterzon.xyz&style=for-the-badge&url=https%3A%2F%2Fwww.betterzon.xyz)](https://www.betterzon.xyz)