2023-05-19 17:35:42 +01:00
|
|
|
import { animate, state, style, transition, trigger } from "@angular/animations";
|
|
|
|
|
import { ConnectedPosition } from "@angular/cdk/overlay";
|
2024-10-24 12:53:34 -07:00
|
|
|
import { Component, EventEmitter, Output, Input, OnInit, OnDestroy } from "@angular/core";
|
2024-10-28 16:12:57 -05:00
|
|
|
import { ActivatedRoute } from "@angular/router";
|
2024-10-24 12:53:34 -07:00
|
|
|
import { Observable, map, Subject, takeUntil } from "rxjs";
|
2023-05-19 17:35:42 +01:00
|
|
|
|
2024-10-28 16:12:57 -05:00
|
|
|
import { SelfHostedEnvConfigDialogComponent } from "@bitwarden/auth/angular";
|
|
|
|
|
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
|
|
|
|
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
2023-06-16 14:09:16 +01:00
|
|
|
import {
|
2024-03-21 17:09:44 +01:00
|
|
|
EnvironmentService,
|
2023-06-16 14:09:16 +01:00
|
|
|
Region,
|
2024-03-21 17:09:44 +01:00
|
|
|
RegionConfig,
|
2023-06-16 14:09:16 +01:00
|
|
|
} from "@bitwarden/common/platform/abstractions/environment.service";
|
2024-10-28 16:12:57 -05:00
|
|
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
|
|
|
|
import { DialogService, ToastService } from "@bitwarden/components";
|
2023-05-19 17:35:42 +01:00
|
|
|
|
2024-10-24 12:53:34 -07:00
|
|
|
export const ExtensionDefaultOverlayPosition: ConnectedPosition[] = [
|
|
|
|
|
{
|
|
|
|
|
originX: "start",
|
|
|
|
|
originY: "top",
|
|
|
|
|
overlayX: "start",
|
|
|
|
|
overlayY: "bottom",
|
|
|
|
|
},
|
|
|
|
|
];
|
|
|
|
|
export const DesktopDefaultOverlayPosition: ConnectedPosition[] = [
|
|
|
|
|
{
|
|
|
|
|
originX: "start",
|
|
|
|
|
originY: "top",
|
|
|
|
|
overlayX: "start",
|
|
|
|
|
overlayY: "bottom",
|
|
|
|
|
},
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
export interface EnvironmentSelectorRouteData {
|
|
|
|
|
overlayPosition?: ConnectedPosition[];
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-19 17:35:42 +01:00
|
|
|
@Component({
|
|
|
|
|
selector: "environment-selector",
|
|
|
|
|
templateUrl: "environment-selector.component.html",
|
|
|
|
|
animations: [
|
|
|
|
|
trigger("transformPanel", [
|
|
|
|
|
state(
|
|
|
|
|
"void",
|
|
|
|
|
style({
|
|
|
|
|
opacity: 0,
|
|
|
|
|
}),
|
|
|
|
|
),
|
|
|
|
|
transition(
|
|
|
|
|
"void => open",
|
|
|
|
|
animate(
|
|
|
|
|
"100ms linear",
|
|
|
|
|
style({
|
|
|
|
|
opacity: 1,
|
|
|
|
|
}),
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
transition("* => void", animate("100ms linear", style({ opacity: 0 }))),
|
|
|
|
|
]),
|
|
|
|
|
],
|
|
|
|
|
})
|
2024-10-24 12:53:34 -07:00
|
|
|
export class EnvironmentSelectorComponent implements OnInit, OnDestroy {
|
2024-10-28 16:12:57 -05:00
|
|
|
@Output() onOpenSelfHostedSettings = new EventEmitter<void>();
|
2024-10-24 12:53:34 -07:00
|
|
|
@Input() overlayPosition: ConnectedPosition[] = [
|
2023-05-19 17:35:42 +01:00
|
|
|
{
|
|
|
|
|
originX: "start",
|
|
|
|
|
originY: "bottom",
|
|
|
|
|
overlayX: "start",
|
|
|
|
|
overlayY: "top",
|
|
|
|
|
},
|
|
|
|
|
];
|
2024-03-21 17:09:44 +01:00
|
|
|
|
2024-10-24 12:53:34 -07:00
|
|
|
protected isOpen = false;
|
|
|
|
|
protected ServerEnvironmentType = Region;
|
2024-03-21 17:09:44 +01:00
|
|
|
protected availableRegions = this.environmentService.availableRegions();
|
|
|
|
|
protected selectedRegion$: Observable<RegionConfig | undefined> =
|
|
|
|
|
this.environmentService.environment$.pipe(
|
|
|
|
|
map((e) => e.getRegion()),
|
|
|
|
|
map((r) => this.availableRegions.find((ar) => ar.key === r)),
|
|
|
|
|
);
|
2023-05-19 17:35:42 +01:00
|
|
|
|
2024-10-24 12:53:34 -07:00
|
|
|
private destroy$ = new Subject<void>();
|
|
|
|
|
|
2023-05-19 17:35:42 +01:00
|
|
|
constructor(
|
2024-03-21 17:09:44 +01:00
|
|
|
protected environmentService: EnvironmentService,
|
2024-10-24 12:53:34 -07:00
|
|
|
private route: ActivatedRoute,
|
2024-10-28 16:12:57 -05:00
|
|
|
private dialogService: DialogService,
|
|
|
|
|
private configService: ConfigService,
|
|
|
|
|
private toastService: ToastService,
|
|
|
|
|
private i18nService: I18nService,
|
2023-05-19 17:35:42 +01:00
|
|
|
) {}
|
|
|
|
|
|
2024-10-24 12:53:34 -07:00
|
|
|
ngOnInit() {
|
|
|
|
|
this.route.data.pipe(takeUntil(this.destroy$)).subscribe((data) => {
|
|
|
|
|
if (data && data["overlayPosition"]) {
|
|
|
|
|
this.overlayPosition = data["overlayPosition"];
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ngOnDestroy() {
|
|
|
|
|
this.destroy$.next();
|
|
|
|
|
this.destroy$.complete();
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-16 14:09:16 +01:00
|
|
|
async toggle(option: Region) {
|
2023-05-19 17:35:42 +01:00
|
|
|
this.isOpen = !this.isOpen;
|
2023-05-25 14:38:23 +01:00
|
|
|
if (option === null) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2023-06-16 14:09:16 +01:00
|
|
|
|
2024-10-28 16:12:57 -05:00
|
|
|
/**
|
|
|
|
|
* Opens the self-hosted settings dialog.
|
|
|
|
|
*
|
|
|
|
|
* If the `UnauthenticatedExtensionUIRefresh` feature flag is enabled,
|
|
|
|
|
* the self-hosted settings dialog is opened directly. Otherwise, the
|
|
|
|
|
* `onOpenSelfHostedSettings` event is emitted.
|
|
|
|
|
*/
|
2023-06-16 14:09:16 +01:00
|
|
|
if (option === Region.SelfHosted) {
|
2024-10-28 16:12:57 -05:00
|
|
|
if (await this.configService.getFeatureFlag(FeatureFlag.UnauthenticatedExtensionUIRefresh)) {
|
|
|
|
|
if (await SelfHostedEnvConfigDialogComponent.open(this.dialogService)) {
|
|
|
|
|
this.toastService.showToast({
|
|
|
|
|
variant: "success",
|
|
|
|
|
title: null,
|
|
|
|
|
message: this.i18nService.t("environmentSaved"),
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
this.onOpenSelfHostedSettings.emit();
|
|
|
|
|
}
|
2023-06-16 14:09:16 +01:00
|
|
|
return;
|
2023-05-19 17:35:42 +01:00
|
|
|
}
|
2023-06-16 14:09:16 +01:00
|
|
|
|
2024-03-21 17:09:44 +01:00
|
|
|
await this.environmentService.setEnvironment(option);
|
2023-05-19 17:35:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
close() {
|
|
|
|
|
this.isOpen = false;
|
|
|
|
|
}
|
|
|
|
|
}
|