1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-28 10:33:31 +00:00

dirt: update control flow bitwarden licensed code

This commit is contained in:
Brad Deibert
2026-01-16 12:46:02 -08:00
parent 8e00e2f63a
commit bdb6a0677a
12 changed files with 235 additions and 225 deletions

View File

@@ -1,4 +1,3 @@
import { CommonModule } from "@angular/common";
import { Component, EventEmitter, Input, Output } from "@angular/core";
import { Router } from "@angular/router";
@@ -10,7 +9,7 @@ import { ButtonModule, ButtonType, LinkModule, TypographyModule } from "@bitward
@Component({
selector: "dirt-activity-card",
templateUrl: "./activity-card.component.html",
imports: [CommonModule, TypographyModule, JslibModule, LinkModule, ButtonModule],
imports: [TypographyModule, JslibModule, LinkModule, ButtonModule],
host: {
class:
"tw-box-border tw-bg-background tw-block tw-text-main tw-border-solid tw-border tw-border-secondary-300 tw-border [&:not(bit-layout_*)]:tw-rounded-lg tw-rounded-lg tw-p-6 tw-min-h-56 tw-overflow-hidden",

View File

@@ -1,4 +1,3 @@
import { CommonModule } from "@angular/common";
import {
ChangeDetectionStrategy,
Component,
@@ -44,7 +43,7 @@ export type PasswordChangeView = (typeof PasswordChangeView)[keyof typeof Passwo
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
selector: "dirt-password-change-metric",
imports: [CommonModule, TypographyModule, JslibModule, ProgressModule, ButtonModule],
imports: [TypographyModule, JslibModule, ProgressModule, ButtonModule],
templateUrl: "./password-change-metric.component.html",
})
export class PasswordChangeMetricComponent implements OnInit {

View File

@@ -1,4 +1,3 @@
import { CommonModule } from "@angular/common";
import { ChangeDetectionStrategy, Component, input } from "@angular/core";
import {
@@ -25,7 +24,6 @@ import { DarkImageSourceDirective } from "@bitwarden/vault";
selector: "dirt-assign-tasks-view",
templateUrl: "./assign-tasks-view.component.html",
imports: [
CommonModule,
ButtonModule,
TypographyModule,
I18nPipe,

View File

@@ -1,4 +1,3 @@
import { CommonModule } from "@angular/common";
import {
ChangeDetectionStrategy,
Component,
@@ -79,7 +78,6 @@ export type NewApplicationsDialogResultType =
selector: "dirt-new-applications-dialog",
templateUrl: "./new-applications-dialog.component.html",
imports: [
CommonModule,
ButtonModule,
DialogModule,
TypographyModule,

View File

@@ -6,12 +6,11 @@
{{ title() }}
</div>
<div
class="tw-text-main tw-text-sm sm:tw-text-base tw-font-normal tw-leading-normal"
*ngIf="description()"
>
{{ description() }}
</div>
@if (description()) {
<div class="tw-text-main tw-text-sm sm:tw-text-base tw-font-normal tw-leading-normal">
{{ description() }}
</div>
}
@if (benefits().length > 0) {
<div class="tw-flex tw-flex-col tw-gap-4 sm:tw-gap-5">
@for (benefit of benefits(); track $index) {
@@ -38,69 +37,77 @@
</div>
}
<div class="tw-flex tw-justify-start" *ngIf="buttonText() && buttonAction()">
<button
(click)="buttonAction()()"
bitButton
buttonType="primary"
type="button"
class="tw-px-3 tw-py-1.5 sm:tw-px-4 tw-rounded-full tw-text-sm sm:tw-text-base"
>
<i [class]="buttonIcon() + ' tw-mr-2'" *ngIf="buttonIcon()"></i>
{{ buttonText() }}
</button>
</div>
@if (buttonText() && buttonAction()) {
<div class="tw-flex tw-justify-start">
<button
(click)="buttonAction()()"
bitButton
buttonType="primary"
type="button"
class="tw-px-3 tw-py-1.5 sm:tw-px-4 tw-rounded-full tw-text-sm sm:tw-text-base"
>
@if (buttonIcon()) {
<i [class]="buttonIcon() + ' tw-mr-2'"></i>
}
{{ buttonText() }}
</button>
</div>
}
</div>
<div class="tw-hidden lg:tw-block tw-flex-shrink-0" *ngIf="videoSrc() || icon()">
<div class="tw-size-64 xl:tw-size-80 tw-relative">
@if (videoSrc()) {
<video
class="tw-size-full tw-rounded-lg"
[src]="videoSrc()"
autoplay
loop
muted
playsinline
aria-hidden="true"
></video>
} @else if (icon()) {
<div
class="tw-size-full tw-flex tw-items-center tw-justify-center tw-bg-secondary-100 tw-rounded-lg"
>
<bit-icon
[icon]="icon()"
class="tw-size-16 xl:tw-size-24 tw-text-muted"
@if (videoSrc() || icon()) {
<div class="tw-hidden lg:tw-block tw-flex-shrink-0">
<div class="tw-size-64 xl:tw-size-80 tw-relative">
@if (videoSrc()) {
<video
class="tw-size-full tw-rounded-lg"
[src]="videoSrc()"
autoplay
loop
muted
playsinline
aria-hidden="true"
></bit-icon>
</div>
}
></video>
} @else if (icon()) {
<div
class="tw-size-full tw-flex tw-items-center tw-justify-center tw-bg-secondary-100 tw-rounded-lg"
>
<bit-icon
[icon]="icon()"
class="tw-size-16 xl:tw-size-24 tw-text-muted"
aria-hidden="true"
></bit-icon>
</div>
}
</div>
</div>
</div>
}
<div class="tw-flex lg:tw-hidden tw-w-full tw-justify-center" *ngIf="videoSrc() || icon()">
<div class="tw-size-48 sm:tw-size-64 tw-relative">
@if (videoSrc()) {
<video
class="tw-size-full tw-rounded-lg"
[src]="videoSrc()"
autoplay
loop
muted
playsinline
aria-hidden="true"
></video>
} @else if (icon()) {
<div
class="tw-size-full tw-flex tw-items-center tw-justify-center tw-bg-secondary-100 tw-rounded-lg"
>
<bit-icon
[icon]="icon()"
class="tw-size-12 sm:tw-size-16 tw-text-muted"
@if (videoSrc() || icon()) {
<div class="tw-flex lg:tw-hidden tw-w-full tw-justify-center">
<div class="tw-size-48 sm:tw-size-64 tw-relative">
@if (videoSrc()) {
<video
class="tw-size-full tw-rounded-lg"
[src]="videoSrc()"
autoplay
loop
muted
playsinline
aria-hidden="true"
></bit-icon>
</div>
}
></video>
} @else if (icon()) {
<div
class="tw-size-full tw-flex tw-items-center tw-justify-center tw-bg-secondary-100 tw-rounded-lg"
>
<bit-icon
[icon]="icon()"
class="tw-size-12 sm:tw-size-16 tw-text-muted"
aria-hidden="true"
></bit-icon>
</div>
}
</div>
</div>
</div>
}
</div>

View File

@@ -1,4 +1,3 @@
import { CommonModule } from "@angular/common";
import { ChangeDetectionStrategy, Component, input, isDevMode, OnInit } from "@angular/core";
import { Icon } from "@bitwarden/assets/svg";
@@ -7,7 +6,7 @@ import { ButtonModule, IconModule } from "@bitwarden/components";
@Component({
selector: "empty-state-card",
templateUrl: "./empty-state-card.component.html",
imports: [CommonModule, IconModule, ButtonModule],
imports: [IconModule, ButtonModule],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class EmptyStateCardComponent implements OnInit {

View File

@@ -44,9 +44,11 @@
<!-- Show screen when there is report data OR when feature flag is disabled (show tabs even without data) -->
<div @fadeIn class="tw-min-h-screen tw-flex tw-flex-col">
<div>
<div class="tw-text-main tw-max-w-4xl tw-mb-2" *ngIf="appsCount > 0">
{{ "reviewAtRiskPasswords" | i18n }}
</div>
@if (appsCount > 0) {
<div class="tw-text-main tw-max-w-4xl tw-mb-2">
{{ "reviewAtRiskPasswords" | i18n }}
</div>
}
@let isRunningReport = dataService.isGeneratingReport$ | async;
<div
class="tw-bg-primary-100 tw-rounded-lg tw-w-full tw-px-8 tw-py-4 tw-my-4 tw-flex tw-items-center"
@@ -61,23 +63,25 @@
}}</span>
}
<span class="tw-flex tw-justify-center">
<button
*ngIf="!isRunningReport"
type="button"
bitButton
buttonType="secondary"
class="tw-border-none !tw-font-normal tw-cursor-pointer !tw-py-0"
tabindex="0"
[bitAction]="generateReport.bind(this)"
>
{{ "riskInsightsRunReport" | i18n }}
</button>
@if (!isRunningReport) {
<button
type="button"
bitButton
buttonType="secondary"
class="tw-border-none !tw-font-normal tw-cursor-pointer !tw-py-0"
tabindex="0"
[bitAction]="generateReport.bind(this)"
>
{{ "riskInsightsRunReport" | i18n }}
</button>
}
<span>
<i
*ngIf="isRunningReport"
class="bwi bwi-spinner bwi-spin tw-text-muted tw-text-[1.2rem]"
aria-hidden="true"
></i>
@if (isRunningReport) {
<i
class="bwi bwi-spinner bwi-spin tw-text-muted tw-text-[1.2rem]"
aria-hidden="true"
></i>
}
</span>
</span>
</div>

View File

@@ -12,28 +12,32 @@
<th bitSortable="memberCount" bitCell tabindex="0">{{ "totalMembers" | i18n }}</th>
</ng-container>
<ng-template bitRowDef let-row>
<td
bitCell
*ngIf="showRowCheckBox"
[ngClass]="{ 'tw-bg-primary-100': row.applicationName === openApplication }"
appStopProp
>
<input
bitCheckbox
type="checkbox"
*ngIf="!row.isMarkedAsCritical"
[checked]="selectedUrls.has(row.applicationName)"
(change)="checkboxChange(row.applicationName, $event)"
/>
<i class="bwi bwi-star-f" *ngIf="row.isMarkedAsCritical"></i>
</td>
<td
bitCell
*ngIf="!showRowCheckBox"
[ngClass]="{ 'tw-bg-primary-100': row.applicationName === openApplication }"
>
<i class="bwi bwi-star-f" *ngIf="row.isMarkedAsCritical"></i>
</td>
@if (showRowCheckBox) {
<td
bitCell
[ngClass]="{ 'tw-bg-primary-100': row.applicationName === openApplication }"
appStopProp
>
@if (!row.isMarkedAsCritical) {
<input
bitCheckbox
type="checkbox"
[checked]="selectedUrls.has(row.applicationName)"
(change)="checkboxChange(row.applicationName, $event)"
/>
}
@if (row.isMarkedAsCritical) {
<i class="bwi bwi-star-f"></i>
}
</td>
}
@if (!showRowCheckBox) {
<td bitCell [ngClass]="{ 'tw-bg-primary-100': row.applicationName === openApplication }">
@if (row.isMarkedAsCritical) {
<i class="bwi bwi-star-f"></i>
}
</td>
}
<td
bitCell
class="tw-cursor-pointer"
@@ -45,11 +49,9 @@
tabindex="0"
[attr.aria-label]="'viewItem' | i18n"
>
<app-vault-icon
*ngIf="row.iconCipher"
[cipher]="row.iconCipher"
[size]="24"
></app-vault-icon>
@if (row.iconCipher) {
<app-vault-icon [cipher]="row.iconCipher" [size]="24"></app-vault-icon>
}
</td>
<td
class="tw-cursor-pointer"
@@ -122,27 +124,27 @@
>
{{ row.memberCount }}
</td>
<td
bitCell
*ngIf="showRowMenuForCriticalApps"
[ngClass]="{ 'tw-bg-primary-100': row.applicationName === openApplication }"
appStopProp
>
<button
[bitMenuTriggerFor]="rowMenu"
type="button"
bitIconButton="bwi-ellipsis-v"
size="small"
label="{{ 'options' | i18n }}"
tabindex="0"
></button>
<bit-menu #rowMenu>
<button type="button" bitMenuItem (click)="unmarkAsCritical(row.applicationName)">
{{ "unmarkAsCritical" | i18n }}
</button>
</bit-menu>
</td>
@if (showRowMenuForCriticalApps) {
<td
bitCell
[ngClass]="{ 'tw-bg-primary-100': row.applicationName === openApplication }"
appStopProp
>
<button
[bitMenuTriggerFor]="rowMenu"
type="button"
bitIconButton="bwi-ellipsis-v"
size="small"
label="{{ 'options' | i18n }}"
tabindex="0"
></button>
<bit-menu #rowMenu>
<button type="button" bitMenuItem (click)="unmarkAsCritical(row.applicationName)">
{{ "unmarkAsCritical" | i18n }}
</button>
</bit-menu>
</td>
}
</ng-template>
</bit-table-scroll>
</ng-container>

View File

@@ -1,4 +1,3 @@
import { CommonModule } from "@angular/common";
import { Component, input } from "@angular/core";
import { JslibModule } from "@bitwarden/angular/jslib.module";
@@ -19,7 +18,7 @@ const ProgressStepConfig = Object.freeze({
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({
selector: "dirt-report-loading",
imports: [CommonModule, JslibModule, ProgressModule],
imports: [JslibModule, ProgressModule],
templateUrl: "./report-loading.component.html",
})
export class ReportLoadingComponent {

View File

@@ -1,21 +1,22 @@
<ul
class="tw-inline-grid tw-grid-cols-3 tw-gap-6 tw-m-0 tw-p-0 tw-w-full tw-auto-cols-auto tw-list-none lg:tw-grid-cols-4 lg:tw-gap-10 lg:tw-w-auto"
>
<li
*ngFor="let integration of integrations"
[title]="tooltipI18nKey | i18n: integration.name"
[attr.aria-label]="ariaI18nKey | i18n: integration.name"
>
<app-integration-card
[name]="integration.name"
[linkURL]="integration.linkURL"
[image]="integration.image"
[imageDarkMode]="integration.imageDarkMode"
[externalURL]="integration.type === IntegrationType.SDK"
[newBadgeExpiration]="integration.newBadgeExpiration"
[description]="integration.description | i18n"
[canSetupConnection]="integration.canSetupConnection"
[integrationSettings]="integration"
></app-integration-card>
</li>
@for (integration of integrations; track integration) {
<li
[title]="tooltipI18nKey | i18n: integration.name"
[attr.aria-label]="ariaI18nKey | i18n: integration.name"
>
<app-integration-card
[name]="integration.name"
[linkURL]="integration.linkURL"
[image]="integration.image"
[imageDarkMode]="integration.imageDarkMode"
[externalURL]="integration.type === IntegrationType.SDK"
[newBadgeExpiration]="integration.newBadgeExpiration"
[description]="integration.description | i18n"
[canSetupConnection]="integration.canSetupConnection"
[integrationSettings]="integration"
></app-integration-card>
</li>
}
</ul>

View File

@@ -24,28 +24,32 @@
@if (organization?.useScim || organization?.useDirectory) {
<bit-tab [label]="'userProvisioning' | i18n">
<section class="tw-mb-9" *ngIf="organization?.useScim">
<h2 bitTypography="h2">
{{ "scimIntegration" | i18n }}
</h2>
<p bitTypography="body1">
{{ "scimIntegrationDescStart" | i18n }}
<a bitLink routerLink="../settings/scim">{{ "scimIntegration" | i18n }}</a>
{{ "scimIntegrationDescEnd" | i18n }}
</p>
<app-integration-grid
[integrations]="integrationsList | filterIntegrations: IntegrationType.SCIM"
></app-integration-grid>
</section>
<section class="tw-mb-9" *ngIf="organization?.useDirectory">
<h2 bitTypography="h2">
{{ "bwdc" | i18n }}
</h2>
<p bitTypography="body1">{{ "bwdcDesc" | i18n }}</p>
<app-integration-grid
[integrations]="integrationsList | filterIntegrations: IntegrationType.BWDC"
></app-integration-grid>
</section>
@if (organization?.useScim) {
<section class="tw-mb-9">
<h2 bitTypography="h2">
{{ "scimIntegration" | i18n }}
</h2>
<p bitTypography="body1">
{{ "scimIntegrationDescStart" | i18n }}
<a bitLink routerLink="../settings/scim">{{ "scimIntegration" | i18n }}</a>
{{ "scimIntegrationDescEnd" | i18n }}
</p>
<app-integration-grid
[integrations]="integrationsList | filterIntegrations: IntegrationType.SCIM"
></app-integration-grid>
</section>
}
@if (organization?.useDirectory) {
<section class="tw-mb-9">
<h2 bitTypography="h2">
{{ "bwdc" | i18n }}
</h2>
<p bitTypography="body1">{{ "bwdcDesc" | i18n }}</p>
<app-integration-grid
[integrations]="integrationsList | filterIntegrations: IntegrationType.BWDC"
></app-integration-grid>
</section>
}
</bit-tab>
}

View File

@@ -1,21 +1,18 @@
<app-header>
<bit-search
[formControl]="searchControl"
[placeholder]="'searchMembers' | i18n"
class="tw-grow"
*ngIf="!(isLoading$ | async)"
></bit-search>
@if (!(isLoading$ | async)) {
<bit-search
[formControl]="searchControl"
[placeholder]="'searchMembers' | i18n"
class="tw-grow"
></bit-search>
}
<button
type="button"
bitButton
buttonType="primary"
[bitAction]="exportReportAction"
*ngIf="!(isLoading$ | async)"
>
<span>{{ "export" | i18n }}</span>
<i class="bwi bwi-fw bwi-sign-in" aria-hidden="true"></i>
</button>
@if (!(isLoading$ | async)) {
<button type="button" bitButton buttonType="primary" [bitAction]="exportReportAction">
<span>{{ "export" | i18n }}</span>
<i class="bwi bwi-fw bwi-sign-in" aria-hidden="true"></i>
</button>
}
</app-header>
<div class="tw-max-w-4xl">
@@ -24,7 +21,7 @@
</p>
</div>
<ng-container *ngIf="isLoading$ | async">
@if (isLoading$ | async) {
<div class="tw-flex-col tw-flex tw-justify-center tw-items-center tw-gap-5 tw-mt-4">
<i
class="bwi bwi-2x bwi-spinner bwi-spin tw-text-primary-600"
@@ -33,31 +30,34 @@
></i>
<h2 bitTypography="h1">{{ "loading" | i18n }}</h2>
</div>
</ng-container>
<bit-table-scroll *ngIf="!(isLoading$ | async)" [dataSource]="dataSource" [rowSize]="53">
<ng-container header>
<th bitCell bitSortable="email" default>{{ "members" | i18n }}</th>
<th bitCell bitSortable="groupsCount" class="tw-w-[278px]">{{ "groups" | i18n }}</th>
<th bitCell bitSortable="collectionsCount" class="tw-w-[278px]">{{ "collections" | i18n }}</th>
<th bitCell bitSortable="itemsCount" class="tw-w-[278px]">{{ "items" | i18n }}</th>
</ng-container>
<ng-template bitRowDef let-row>
<td bitCell>
<div class="tw-flex tw-items-center">
<bit-avatar size="small" [text]="row.name" class="tw-mr-3"></bit-avatar>
<div class="tw-flex tw-flex-col">
<button type="button" bitLink (click)="edit(row)">
{{ row.name }}
</button>
<div class="tw-text-sm tw-mt-1 tw-text-muted">
{{ row.email }}
}
@if (!(isLoading$ | async)) {
<bit-table-scroll [dataSource]="dataSource" [rowSize]="53">
<ng-container header>
<th bitCell bitSortable="email" default>{{ "members" | i18n }}</th>
<th bitCell bitSortable="groupsCount" class="tw-w-[278px]">{{ "groups" | i18n }}</th>
<th bitCell bitSortable="collectionsCount" class="tw-w-[278px]">
{{ "collections" | i18n }}
</th>
<th bitCell bitSortable="itemsCount" class="tw-w-[278px]">{{ "items" | i18n }}</th>
</ng-container>
<ng-template bitRowDef let-row>
<td bitCell>
<div class="tw-flex tw-items-center">
<bit-avatar size="small" [text]="row.name" class="tw-mr-3"></bit-avatar>
<div class="tw-flex tw-flex-col">
<button type="button" bitLink (click)="edit(row)">
{{ row.name }}
</button>
<div class="tw-text-sm tw-mt-1 tw-text-muted">
{{ row.email }}
</div>
</div>
</div>
</div>
</td>
<td bitCell class="tw-text-muted tw-w-[278px]">{{ row.groupsCount }}</td>
<td bitCell class="tw-text-muted tw-w-[278px]">{{ row.collectionsCount }}</td>
<td bitCell class="tw-text-muted tw-w-[278px]">{{ row.itemsCount }}</td>
</ng-template>
</bit-table-scroll>
</td>
<td bitCell class="tw-text-muted tw-w-[278px]">{{ row.groupsCount }}</td>
<td bitCell class="tw-text-muted tw-w-[278px]">{{ row.collectionsCount }}</td>
<td bitCell class="tw-text-muted tw-w-[278px]">{{ row.itemsCount }}</td>
</ng-template>
</bit-table-scroll>
}