mirror of
https://github.com/bitwarden/browser
synced 2025-12-12 14:23:32 +00:00
[PM-22313] Refactor organization vault component (#16017)
* refactor organization, userId, and filter * refactor collections * refactor allGroups to observable * Refactor ciphers WIP * fix filter$ * refactor collections$, refresh$, isEmpty$, proccesingEvents$ * resolve remaining ts-strict errors * refactor *ngIf to @if syntax * rename function * clean up * fix issues from merge conflict * better error handling, clean up * wip add feature flag * refactor org vault: improve null safety & loading * add take(2) to firstLoadComplete observable * add real feature flag * cleanup * fix icon * Add comments * refactor org vault with null checks, update util function * fix type --------- Co-authored-by: Thomas Rittson <trittson@bitwarden.com>
This commit is contained in:
@@ -0,0 +1,156 @@
|
|||||||
|
<app-organization-free-trial-warning
|
||||||
|
*ngIf="useOrganizationWarningsService$ | async"
|
||||||
|
[organization]="organization"
|
||||||
|
(clicked)="navigateToPaymentMethod()"
|
||||||
|
>
|
||||||
|
</app-organization-free-trial-warning>
|
||||||
|
<app-organization-reseller-renewal-warning
|
||||||
|
*ngIf="useOrganizationWarningsService$ | async"
|
||||||
|
[organization]="organization"
|
||||||
|
>
|
||||||
|
</app-organization-reseller-renewal-warning>
|
||||||
|
<ng-container *ngIf="freeTrialWhenWarningsServiceDisabled$ | async as freeTrial">
|
||||||
|
<bit-banner
|
||||||
|
id="free-trial-banner"
|
||||||
|
class="-tw-m-6 tw-flex tw-flex-col tw-pb-6"
|
||||||
|
icon="bwi-billing"
|
||||||
|
bannerType="premium"
|
||||||
|
[showClose]="false"
|
||||||
|
*ngIf="!refreshing && freeTrial.shownBanner"
|
||||||
|
>
|
||||||
|
{{ freeTrial.message }}
|
||||||
|
<a
|
||||||
|
bitLink
|
||||||
|
linkType="secondary"
|
||||||
|
(click)="navigateToPaymentMethod()"
|
||||||
|
class="tw-cursor-pointer"
|
||||||
|
rel="noreferrer noopener"
|
||||||
|
>
|
||||||
|
{{ "clickHereToAddPaymentMethod" | i18n }}
|
||||||
|
</a>
|
||||||
|
</bit-banner>
|
||||||
|
</ng-container>
|
||||||
|
<ng-container *ngIf="resellerWarningWhenWarningsServiceDisabled$ | async as resellerWarning">
|
||||||
|
<bit-banner
|
||||||
|
id="reseller-warning-banner"
|
||||||
|
class="-tw-m-6 tw-flex tw-flex-col tw-pb-6"
|
||||||
|
icon="bwi-billing"
|
||||||
|
bannerType="info"
|
||||||
|
[showClose]="false"
|
||||||
|
*ngIf="!refreshing"
|
||||||
|
>
|
||||||
|
{{ resellerWarning?.message }}
|
||||||
|
</bit-banner>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<app-org-vault-header
|
||||||
|
[filter]="filter"
|
||||||
|
[loading]="refreshing"
|
||||||
|
[organization]="organization"
|
||||||
|
[collection]="selectedCollection"
|
||||||
|
[searchText]="currentSearchText$ | async"
|
||||||
|
(onAddCipher)="addCipher($event)"
|
||||||
|
(onAddCollection)="addCollection()"
|
||||||
|
(onEditCollection)="editCollection(selectedCollection.node, $event.tab, $event.readonly)"
|
||||||
|
(onDeleteCollection)="deleteCollection(selectedCollection.node)"
|
||||||
|
(searchTextChanged)="filterSearchText($event)"
|
||||||
|
></app-org-vault-header>
|
||||||
|
|
||||||
|
<div class="tw-flex tw-flex-row">
|
||||||
|
<div class="tw-w-1/4 tw-mr-5" *ngIf="!hideVaultFilters">
|
||||||
|
<app-organization-vault-filter
|
||||||
|
[organization]="organization"
|
||||||
|
[activeFilter]="activeFilter"
|
||||||
|
[searchText]="currentSearchText$ | async"
|
||||||
|
(searchTextChanged)="filterSearchText($event)"
|
||||||
|
></app-organization-vault-filter>
|
||||||
|
</div>
|
||||||
|
<div [class]="hideVaultFilters ? 'tw-w-full' : 'tw-w-3/4'">
|
||||||
|
<bit-toggle-group
|
||||||
|
*ngIf="showAddAccessToggle && activeFilter.selectedCollectionNode"
|
||||||
|
[selected]="addAccessStatus$ | async"
|
||||||
|
(selectedChange)="addAccessToggle($event)"
|
||||||
|
[attr.aria-label]="'addAccessFilter' | i18n"
|
||||||
|
>
|
||||||
|
<bit-toggle [value]="0">
|
||||||
|
{{ "all" | i18n }}
|
||||||
|
</bit-toggle>
|
||||||
|
|
||||||
|
<bit-toggle [value]="1">
|
||||||
|
{{ "addAccess" | i18n }}
|
||||||
|
</bit-toggle>
|
||||||
|
</bit-toggle-group>
|
||||||
|
<bit-callout type="warning" *ngIf="activeFilter.isDeleted">
|
||||||
|
{{ trashCleanupWarning }}
|
||||||
|
</bit-callout>
|
||||||
|
<app-vault-items
|
||||||
|
#vaultItems
|
||||||
|
[ciphers]="ciphers"
|
||||||
|
[collections]="collections"
|
||||||
|
[allCollections]="allCollections"
|
||||||
|
[allOrganizations]="organization ? [organization] : []"
|
||||||
|
[allGroups]="allGroups"
|
||||||
|
[disabled]="loading"
|
||||||
|
[showOwner]="false"
|
||||||
|
[showPermissionsColumn]="true"
|
||||||
|
[showCollections]="filter.type !== undefined"
|
||||||
|
[showGroups]="
|
||||||
|
organization?.useGroups &&
|
||||||
|
((filter.type === undefined && filter.collectionId === undefined) ||
|
||||||
|
filter.collectionId !== undefined)
|
||||||
|
"
|
||||||
|
[showPremiumFeatures]="organization?.useTotp"
|
||||||
|
[showBulkMove]="false"
|
||||||
|
[showBulkTrashOptions]="filter.type === 'trash'"
|
||||||
|
[useEvents]="organization?.canAccessEventLogs"
|
||||||
|
[showAdminActions]="true"
|
||||||
|
(onEvent)="onVaultItemsEvent($event)"
|
||||||
|
[showBulkEditCollectionAccess]="true"
|
||||||
|
[showBulkAddToCollections]="true"
|
||||||
|
[viewingOrgVault]="true"
|
||||||
|
[addAccessStatus]="addAccessStatus$ | async"
|
||||||
|
[addAccessToggle]="showAddAccessToggle"
|
||||||
|
[activeCollection]="selectedCollection?.node"
|
||||||
|
>
|
||||||
|
</app-vault-items>
|
||||||
|
<ng-container *ngIf="!performingInitialLoad && isEmpty">
|
||||||
|
<bit-no-items *ngIf="!showCollectionAccessRestricted">
|
||||||
|
<span slot="title" class="tw-mt-4 tw-block">{{ "noItemsInList" | i18n }}</span>
|
||||||
|
<button
|
||||||
|
slot="button"
|
||||||
|
bitButton
|
||||||
|
(click)="addCipher()"
|
||||||
|
buttonType="primary"
|
||||||
|
type="button"
|
||||||
|
*ngIf="
|
||||||
|
filter.type !== 'trash' &&
|
||||||
|
filter.collectionId !== Unassigned &&
|
||||||
|
selectedCollection?.node?.canEditItems(organization)
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<i aria-hidden="true" class="bwi bwi-plus"></i> {{ "newItem" | i18n }}
|
||||||
|
</button>
|
||||||
|
</bit-no-items>
|
||||||
|
<collection-access-restricted
|
||||||
|
*ngIf="showCollectionAccessRestricted"
|
||||||
|
[canEditCollection]="selectedCollection?.node?.canEdit(organization)"
|
||||||
|
[canViewCollectionInfo]="selectedCollection?.node?.canViewCollectionInfo(organization)"
|
||||||
|
(viewCollectionClicked)="
|
||||||
|
editCollection(selectedCollection.node, $event.tab, $event.readonly)
|
||||||
|
"
|
||||||
|
>
|
||||||
|
</collection-access-restricted>
|
||||||
|
</ng-container>
|
||||||
|
<div
|
||||||
|
class="tw-mt-6 tw-flex tw-h-full tw-flex-col tw-items-center tw-justify-start"
|
||||||
|
*ngIf="performingInitialLoad"
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
class="bwi bwi-spinner bwi-spin tw-text-muted"
|
||||||
|
title="{{ 'loading' | i18n }}"
|
||||||
|
aria-hidden="true"
|
||||||
|
></i>
|
||||||
|
<span class="tw-sr-only">{{ "loading" | i18n }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,19 +1,28 @@
|
|||||||
import { NgModule } from "@angular/core";
|
import { NgModule } from "@angular/core";
|
||||||
import { RouterModule, Routes } from "@angular/router";
|
import { RouterModule, Routes } from "@angular/router";
|
||||||
|
|
||||||
|
import { featureFlaggedRoute } from "@bitwarden/angular/platform/utils/feature-flagged-route";
|
||||||
import { canAccessVaultTab } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
import { canAccessVaultTab } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
|
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||||
|
|
||||||
import { organizationPermissionsGuard } from "../guards/org-permissions.guard";
|
import { organizationPermissionsGuard } from "../guards/org-permissions.guard";
|
||||||
|
|
||||||
import { VaultComponent } from "./vault.component";
|
import { VaultComponent } from "./deprecated_vault.component";
|
||||||
|
import { vNextVaultComponent } from "./vault.component";
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{
|
...featureFlaggedRoute({
|
||||||
path: "",
|
defaultComponent: VaultComponent,
|
||||||
component: VaultComponent,
|
flaggedComponent: vNextVaultComponent,
|
||||||
canActivate: [organizationPermissionsGuard(canAccessVaultTab)],
|
featureFlag: FeatureFlag.CollectionVaultRefactor,
|
||||||
|
routeOptions: {
|
||||||
data: { titleId: "vaults" },
|
data: { titleId: "vaults" },
|
||||||
|
path: "",
|
||||||
|
canActivate: [organizationPermissionsGuard(canAccessVaultTab)],
|
||||||
},
|
},
|
||||||
|
}),
|
||||||
];
|
];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [RouterModule.forChild(routes)],
|
imports: [RouterModule.forChild(routes)],
|
||||||
exports: [RouterModule],
|
exports: [RouterModule],
|
||||||
|
|||||||
@@ -1,22 +1,31 @@
|
|||||||
<app-organization-free-trial-warning
|
@let organization = organization$ | async;
|
||||||
*ngIf="useOrganizationWarningsService$ | async"
|
@let selectedCollection = selectedCollection$ | async;
|
||||||
|
@let filter = filter$ | async;
|
||||||
|
@let refreshing = refreshingSubject$ | async;
|
||||||
|
@let loading = loading$ | async;
|
||||||
|
|
||||||
|
@if (organization) {
|
||||||
|
@if (useOrganizationWarningsService$ | async) {
|
||||||
|
<app-organization-free-trial-warning
|
||||||
[organization]="organization"
|
[organization]="organization"
|
||||||
(clicked)="navigateToPaymentMethod()"
|
(clicked)="navigateToPaymentMethod()"
|
||||||
>
|
>
|
||||||
</app-organization-free-trial-warning>
|
</app-organization-free-trial-warning>
|
||||||
<app-organization-reseller-renewal-warning
|
}
|
||||||
*ngIf="useOrganizationWarningsService$ | async"
|
|
||||||
[organization]="organization"
|
@if (useOrganizationWarningsService$ | async) {
|
||||||
>
|
<app-organization-reseller-renewal-warning [organization]="organization">
|
||||||
</app-organization-reseller-renewal-warning>
|
</app-organization-reseller-renewal-warning>
|
||||||
<ng-container *ngIf="freeTrialWhenWarningsServiceDisabled$ | async as freeTrial">
|
}
|
||||||
|
|
||||||
|
@let freeTrial = freeTrialWhenWarningsServiceDisabled$ | async;
|
||||||
|
@if (!refreshing && freeTrial?.shownBanner) {
|
||||||
<bit-banner
|
<bit-banner
|
||||||
id="free-trial-banner"
|
id="free-trial-banner"
|
||||||
class="-tw-m-6 tw-flex tw-flex-col tw-pb-6"
|
class="-tw-m-6 tw-flex tw-flex-col tw-pb-6"
|
||||||
icon="bwi-billing"
|
icon="bwi-billing"
|
||||||
bannerType="premium"
|
bannerType="premium"
|
||||||
[showClose]="false"
|
[showClose]="false"
|
||||||
*ngIf="!refreshing && freeTrial.shownBanner"
|
|
||||||
>
|
>
|
||||||
{{ freeTrial.message }}
|
{{ freeTrial.message }}
|
||||||
<a
|
<a
|
||||||
@@ -29,21 +38,23 @@
|
|||||||
{{ "clickHereToAddPaymentMethod" | i18n }}
|
{{ "clickHereToAddPaymentMethod" | i18n }}
|
||||||
</a>
|
</a>
|
||||||
</bit-banner>
|
</bit-banner>
|
||||||
</ng-container>
|
}
|
||||||
<ng-container *ngIf="resellerWarningWhenWarningsServiceDisabled$ | async as resellerWarning">
|
|
||||||
|
@let resellerWarning = resellerWarningWhenWarningsServiceDisabled$ | async;
|
||||||
|
@if (!refreshing && resellerWarning) {
|
||||||
<bit-banner
|
<bit-banner
|
||||||
id="reseller-warning-banner"
|
id="reseller-warning-banner"
|
||||||
class="-tw-m-6 tw-flex tw-flex-col tw-pb-6"
|
class="-tw-m-6 tw-flex tw-flex-col tw-pb-6"
|
||||||
icon="bwi-billing"
|
icon="bwi-billing"
|
||||||
bannerType="info"
|
bannerType="info"
|
||||||
[showClose]="false"
|
[showClose]="false"
|
||||||
*ngIf="!refreshing"
|
|
||||||
>
|
>
|
||||||
{{ resellerWarning?.message }}
|
{{ resellerWarning?.message }}
|
||||||
</bit-banner>
|
</bit-banner>
|
||||||
</ng-container>
|
}
|
||||||
|
|
||||||
<app-org-vault-header
|
@if (filter) {
|
||||||
|
<app-org-vault-header
|
||||||
[filter]="filter"
|
[filter]="filter"
|
||||||
[loading]="refreshing"
|
[loading]="refreshing"
|
||||||
[organization]="organization"
|
[organization]="organization"
|
||||||
@@ -51,13 +62,16 @@
|
|||||||
[searchText]="currentSearchText$ | async"
|
[searchText]="currentSearchText$ | async"
|
||||||
(onAddCipher)="addCipher($event)"
|
(onAddCipher)="addCipher($event)"
|
||||||
(onAddCollection)="addCollection()"
|
(onAddCollection)="addCollection()"
|
||||||
(onEditCollection)="editCollection(selectedCollection.node, $event.tab, $event.readonly)"
|
(onEditCollection)="editCollection(selectedCollection?.node, $event.tab, $event.readonly)"
|
||||||
(onDeleteCollection)="deleteCollection(selectedCollection.node)"
|
(onDeleteCollection)="deleteCollection(selectedCollection?.node)"
|
||||||
(searchTextChanged)="filterSearchText($event)"
|
(searchTextChanged)="filterSearchText($event)"
|
||||||
></app-org-vault-header>
|
></app-org-vault-header>
|
||||||
|
}
|
||||||
|
|
||||||
<div class="tw-flex tw-flex-row">
|
<div class="tw-flex tw-flex-row">
|
||||||
<div class="tw-w-1/4 tw-mr-5" *ngIf="!hideVaultFilters">
|
@let hideVaultFilters = hideVaultFilter$ | async;
|
||||||
|
@if (!hideVaultFilters) {
|
||||||
|
<div class="tw-w-1/4 tw-mr-5">
|
||||||
<app-organization-vault-filter
|
<app-organization-vault-filter
|
||||||
[organization]="organization"
|
[organization]="organization"
|
||||||
[activeFilter]="activeFilter"
|
[activeFilter]="activeFilter"
|
||||||
@@ -65,9 +79,11 @@
|
|||||||
(searchTextChanged)="filterSearchText($event)"
|
(searchTextChanged)="filterSearchText($event)"
|
||||||
></app-organization-vault-filter>
|
></app-organization-vault-filter>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
<div [class]="hideVaultFilters ? 'tw-w-full' : 'tw-w-3/4'">
|
<div [class]="hideVaultFilters ? 'tw-w-full' : 'tw-w-3/4'">
|
||||||
|
@if (showAddAccessToggle && activeFilter.selectedCollectionNode) {
|
||||||
<bit-toggle-group
|
<bit-toggle-group
|
||||||
*ngIf="showAddAccessToggle && activeFilter.selectedCollectionNode"
|
|
||||||
[selected]="addAccessStatus$ | async"
|
[selected]="addAccessStatus$ | async"
|
||||||
(selectedChange)="addAccessToggle($event)"
|
(selectedChange)="addAccessToggle($event)"
|
||||||
[attr.aria-label]="'addAccessFilter' | i18n"
|
[attr.aria-label]="'addAccessFilter' | i18n"
|
||||||
@@ -80,16 +96,22 @@
|
|||||||
{{ "addAccess" | i18n }}
|
{{ "addAccess" | i18n }}
|
||||||
</bit-toggle>
|
</bit-toggle>
|
||||||
</bit-toggle-group>
|
</bit-toggle-group>
|
||||||
<bit-callout type="warning" *ngIf="activeFilter.isDeleted">
|
}
|
||||||
|
|
||||||
|
@if (activeFilter.isDeleted) {
|
||||||
|
<bit-callout type="warning">
|
||||||
{{ trashCleanupWarning }}
|
{{ trashCleanupWarning }}
|
||||||
</bit-callout>
|
</bit-callout>
|
||||||
|
}
|
||||||
|
|
||||||
|
@if (filter) {
|
||||||
<app-vault-items
|
<app-vault-items
|
||||||
#vaultItems
|
#vaultItems
|
||||||
[ciphers]="ciphers"
|
[ciphers]="ciphers$ | async"
|
||||||
[collections]="collections"
|
[collections]="collections$ | async"
|
||||||
[allCollections]="allCollections"
|
[allCollections]="allCollections$ | async"
|
||||||
[allOrganizations]="organization ? [organization] : []"
|
[allOrganizations]="organization ? [organization] : []"
|
||||||
[allGroups]="allGroups"
|
[allGroups]="allGroups$ | async"
|
||||||
[disabled]="loading"
|
[disabled]="loading"
|
||||||
[showOwner]="false"
|
[showOwner]="false"
|
||||||
[showPermissionsColumn]="true"
|
[showPermissionsColumn]="true"
|
||||||
@@ -113,38 +135,44 @@
|
|||||||
[activeCollection]="selectedCollection?.node"
|
[activeCollection]="selectedCollection?.node"
|
||||||
>
|
>
|
||||||
</app-vault-items>
|
</app-vault-items>
|
||||||
<ng-container *ngIf="!performingInitialLoad && isEmpty">
|
}
|
||||||
<bit-no-items *ngIf="!showCollectionAccessRestricted">
|
|
||||||
|
@let showCollectionAccessRestricted = showCollectionAccessRestricted$ | async;
|
||||||
|
@if (!refreshing && (isEmpty$ | async)) {
|
||||||
|
@if (!showCollectionAccessRestricted) {
|
||||||
|
<bit-no-items>
|
||||||
<span slot="title" class="tw-mt-4 tw-block">{{ "noItemsInList" | i18n }}</span>
|
<span slot="title" class="tw-mt-4 tw-block">{{ "noItemsInList" | i18n }}</span>
|
||||||
|
|
||||||
|
@if (
|
||||||
|
filter &&
|
||||||
|
filter.type !== "trash" &&
|
||||||
|
filter.collectionId !== Unassigned &&
|
||||||
|
selectedCollection?.node?.canEditItems(organization)
|
||||||
|
) {
|
||||||
<button
|
<button
|
||||||
slot="button"
|
slot="button"
|
||||||
bitButton
|
bitButton
|
||||||
(click)="addCipher()"
|
(click)="addCipher()"
|
||||||
buttonType="primary"
|
buttonType="primary"
|
||||||
type="button"
|
type="button"
|
||||||
*ngIf="
|
|
||||||
filter.type !== 'trash' &&
|
|
||||||
filter.collectionId !== Unassigned &&
|
|
||||||
selectedCollection?.node?.canEditItems(organization)
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<i aria-hidden="true" class="bwi bwi-plus"></i> {{ "newItem" | i18n }}
|
<i aria-hidden="true" class="bwi bwi-plus"></i> {{ "newItem" | i18n }}
|
||||||
</button>
|
</button>
|
||||||
|
}
|
||||||
</bit-no-items>
|
</bit-no-items>
|
||||||
|
} @else {
|
||||||
<collection-access-restricted
|
<collection-access-restricted
|
||||||
*ngIf="showCollectionAccessRestricted"
|
|
||||||
[canEditCollection]="selectedCollection?.node?.canEdit(organization)"
|
[canEditCollection]="selectedCollection?.node?.canEdit(organization)"
|
||||||
[canViewCollectionInfo]="selectedCollection?.node?.canViewCollectionInfo(organization)"
|
[canViewCollectionInfo]="selectedCollection?.node?.canViewCollectionInfo(organization)"
|
||||||
(viewCollectionClicked)="
|
(viewCollectionClicked)="
|
||||||
editCollection(selectedCollection.node, $event.tab, $event.readonly)
|
editCollection(selectedCollection?.node, $event.tab, $event.readonly)
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
</collection-access-restricted>
|
</collection-access-restricted>
|
||||||
</ng-container>
|
}
|
||||||
<div
|
}
|
||||||
class="tw-mt-6 tw-flex tw-h-full tw-flex-col tw-items-center tw-justify-start"
|
@if (refreshing) {
|
||||||
*ngIf="performingInitialLoad"
|
<div class="tw-mt-6 tw-flex tw-h-full tw-flex-col tw-items-center tw-justify-start">
|
||||||
>
|
|
||||||
<i
|
<i
|
||||||
class="bwi bwi-spinner bwi-spin tw-text-muted"
|
class="bwi bwi-spinner bwi-spin tw-text-muted"
|
||||||
title="{{ 'loading' | i18n }}"
|
title="{{ 'loading' | i18n }}"
|
||||||
@@ -152,5 +180,7 @@
|
|||||||
></i>
|
></i>
|
||||||
<span class="tw-sr-only">{{ "loading" | i18n }}</span>
|
<span class="tw-sr-only">{{ "loading" | i18n }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -6,9 +6,10 @@ import { ViewComponent } from "../../../vault/individual-vault/view.component";
|
|||||||
import { CollectionDialogComponent } from "../shared/components/collection-dialog";
|
import { CollectionDialogComponent } from "../shared/components/collection-dialog";
|
||||||
|
|
||||||
import { CollectionNameBadgeComponent } from "./collection-badge";
|
import { CollectionNameBadgeComponent } from "./collection-badge";
|
||||||
|
import { VaultComponent } from "./deprecated_vault.component";
|
||||||
import { GroupBadgeModule } from "./group-badge/group-badge.module";
|
import { GroupBadgeModule } from "./group-badge/group-badge.module";
|
||||||
import { VaultRoutingModule } from "./vault-routing.module";
|
import { VaultRoutingModule } from "./vault-routing.module";
|
||||||
import { VaultComponent } from "./vault.component";
|
import { vNextVaultComponent } from "./vault.component";
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -19,6 +20,7 @@ import { VaultComponent } from "./vault.component";
|
|||||||
OrganizationBadgeModule,
|
OrganizationBadgeModule,
|
||||||
CollectionDialogComponent,
|
CollectionDialogComponent,
|
||||||
VaultComponent,
|
VaultComponent,
|
||||||
|
vNextVaultComponent,
|
||||||
ViewComponent,
|
ViewComponent,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -51,6 +51,9 @@ export function canAccessOrgAdmin(org: Organization): boolean {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Please use the general `getById` custom rxjs operator instead.
|
||||||
|
*/
|
||||||
export function getOrganizationById(id: string) {
|
export function getOrganizationById(id: string) {
|
||||||
return map<Organization[], Organization | undefined>((orgs) => orgs.find((o) => o.id === id));
|
return map<Organization[], Organization | undefined>((orgs) => orgs.find((o) => o.id === id));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import { ServerConfig } from "../platform/abstractions/config/server-config";
|
|||||||
export enum FeatureFlag {
|
export enum FeatureFlag {
|
||||||
/* Admin Console Team */
|
/* Admin Console Team */
|
||||||
CreateDefaultLocation = "pm-19467-create-default-location",
|
CreateDefaultLocation = "pm-19467-create-default-location",
|
||||||
|
CollectionVaultRefactor = "pm-25030-resolve-ts-upgrade-errors",
|
||||||
|
|
||||||
/* Auth */
|
/* Auth */
|
||||||
PM14938_BrowserExtensionLoginApproval = "pm-14938-browser-extension-login-approvals",
|
PM14938_BrowserExtensionLoginApproval = "pm-14938-browser-extension-login-approvals",
|
||||||
@@ -71,6 +72,7 @@ const FALSE = false as boolean;
|
|||||||
export const DefaultFeatureFlagValue = {
|
export const DefaultFeatureFlagValue = {
|
||||||
/* Admin Console Team */
|
/* Admin Console Team */
|
||||||
[FeatureFlag.CreateDefaultLocation]: FALSE,
|
[FeatureFlag.CreateDefaultLocation]: FALSE,
|
||||||
|
[FeatureFlag.CollectionVaultRefactor]: FALSE,
|
||||||
|
|
||||||
/* Autofill */
|
/* Autofill */
|
||||||
[FeatureFlag.NotificationRefresh]: FALSE,
|
[FeatureFlag.NotificationRefresh]: FALSE,
|
||||||
|
|||||||
@@ -80,6 +80,18 @@ export class CipherViewLikeUtils {
|
|||||||
return cipher.isDeleted;
|
return cipher.isDeleted;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** @returns `true` when the cipher is not assigned to a collection, `false` otherwise. */
|
||||||
|
static isUnassigned = (cipher: CipherViewLike): boolean => {
|
||||||
|
if (this.isCipherListView(cipher)) {
|
||||||
|
return (
|
||||||
|
cipher.organizationId != null &&
|
||||||
|
(cipher.collectionIds == null || cipher.collectionIds.length === 0)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cipher.isUnassigned;
|
||||||
|
};
|
||||||
|
|
||||||
/** @returns `true` when the user can assign the cipher to a collection, `false` otherwise. */
|
/** @returns `true` when the user can assign the cipher to a collection, `false` otherwise. */
|
||||||
static canAssignToCollections = (cipher: CipherViewLike): boolean => {
|
static canAssignToCollections = (cipher: CipherViewLike): boolean => {
|
||||||
if (this.isCipherListView(cipher)) {
|
if (this.isCipherListView(cipher)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user