1
0
mirror of https://github.com/bitwarden/browser synced 2026-01-08 19:43:45 +00:00

[PS-1092] Organization Service Observables (#3462)

* Update imports

* Implement observables in a few places

* Add tests

* Get all clients working

* Use _destroy

* Address PR feedback

* Address PR feedback

* Address feedback
This commit is contained in:
Justin Baur
2022-09-27 16:25:19 -04:00
committed by GitHub
parent 2c68518f87
commit c6dccc354c
100 changed files with 1225 additions and 813 deletions

View File

@@ -9,7 +9,7 @@ import { FolderService } from "@bitwarden/common/abstractions/folder/folder.serv
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/abstractions/log.service";
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
import { PasswordGenerationService } from "@bitwarden/common/abstractions/passwordGeneration.service";
import { PasswordRepromptService } from "@bitwarden/common/abstractions/passwordReprompt.service";
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";

View File

@@ -4,11 +4,12 @@ import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
import { CollectionService } from "@bitwarden/common/abstractions/collection.service";
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/abstractions/log.service";
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
import { Organization } from "@bitwarden/common/models/domain/organization";
import { CipherView } from "@bitwarden/common/models/view/cipherView";
import { CollectionView } from "@bitwarden/common/models/view/collectionView";
import { Checkable, isChecked } from "@bitwarden/common/types/checkable";
@Component({
selector: "app-vault-bulk-share",
@@ -20,10 +21,10 @@ export class BulkShareComponent implements OnInit {
@Output() onShared = new EventEmitter();
nonShareableCount = 0;
collections: CollectionView[] = [];
collections: Checkable<CollectionView>[] = [];
organizations: Organization[] = [];
shareableCiphers: CipherView[] = [];
formPromise: Promise<any>;
formPromise: Promise<void>;
private writeableCollections: CollectionView[] = [];
@@ -66,9 +67,7 @@ export class BulkShareComponent implements OnInit {
}
async submit() {
const checkedCollectionIds = this.collections
.filter((c) => (c as any).checked)
.map((c) => c.id);
const checkedCollectionIds = this.collections.filter(isChecked).map((c) => c.id);
try {
this.formPromise = this.cipherService.shareManyWithServer(
this.shareableCiphers,
@@ -90,8 +89,8 @@ export class BulkShareComponent implements OnInit {
}
}
check(c: CollectionView, select?: boolean) {
(c as any).checked = select == null ? !(c as any).checked : select;
check(c: Checkable<CollectionView>, select?: boolean) {
c.checked = select == null ? !c.checked : select;
}
selectAll(select: boolean) {
@@ -106,7 +105,7 @@ export class BulkShareComponent implements OnInit {
this.collections != null
) {
for (let i = 0; i < this.collections.length; i++) {
if ((this.collections[i] as any).checked) {
if (this.collections[i].checked) {
return true;
}
}

View File

@@ -5,7 +5,7 @@ import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
import { EventService } from "@bitwarden/common/abstractions/event.service";
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/abstractions/log.service";
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
import { PasswordRepromptService } from "@bitwarden/common/abstractions/passwordReprompt.service";
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
import { SearchService } from "@bitwarden/common/abstractions/search.service";

View File

@@ -15,78 +15,87 @@
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body" *ngIf="!organizations || !organizations.length">
{{ "noOrganizationsList" | i18n }}
</div>
<div class="modal-body" *ngIf="organizations && organizations.length">
<p>{{ "moveToOrgDesc" | i18n }}</p>
<div class="form-group">
<label for="organization">{{ "organization" | i18n }}</label>
<select
id="organization"
name="OrganizationId"
[(ngModel)]="organizationId"
class="form-control"
(change)="filterCollections()"
>
<option *ngFor="let o of organizations" [ngValue]="o.id">{{ o.name }}</option>
</select>
<ng-container *ngIf="organizations$ | async as organizations">
<div class="modal-body" *ngIf="!organizations || !organizations.length">
{{ "noOrganizationsList" | i18n }}
</div>
<div class="d-flex">
<h3>{{ "collections" | i18n }}</h3>
<div class="ml-auto d-flex" *ngIf="collections && collections.length">
<button type="button" (click)="selectAll(true)" class="btn btn-link btn-sm py-0">
{{ "selectAll" | i18n }}
</button>
<button type="button" (click)="selectAll(false)" class="btn btn-link btn-sm py-0">
{{ "unselectAll" | i18n }}
</button>
<div class="modal-body" *ngIf="organizations && organizations.length">
<p>{{ "moveToOrgDesc" | i18n }}</p>
<div class="form-group">
<label for="organization">{{ "organization" | i18n }}</label>
<select
id="organization"
name="OrganizationId"
[(ngModel)]="organizationId"
class="form-control"
(change)="filterCollections()"
>
<option *ngFor="let o of organizations" [ngValue]="o.id">{{ o.name }}</option>
</select>
</div>
<div class="d-flex">
<h3>{{ "collections" | i18n }}</h3>
<div class="ml-auto d-flex" *ngIf="collections && collections.length">
<button type="button" (click)="selectAll(true)" class="btn btn-link btn-sm py-0">
{{ "selectAll" | i18n }}
</button>
<button type="button" (click)="selectAll(false)" class="btn btn-link btn-sm py-0">
{{ "unselectAll" | i18n }}
</button>
</div>
</div>
<div *ngIf="!collections || !collections.length">
{{ "noCollectionsInList" | i18n }}
</div>
<table
class="table table-hover table-list mb-0"
*ngIf="collections && collections.length"
>
<tbody>
<tr *ngFor="let c of collections; let i = index" (click)="check(c)">
<td class="table-list-checkbox">
<input
type="checkbox"
[(ngModel)]="c.checked"
name="Collection[{{ i }}].Checked"
appStopProp
/>
</td>
<td>
{{ c.name }}
</td>
</tr>
</tbody>
</table>
</div>
<div *ngIf="!collections || !collections.length">
{{ "noCollectionsInList" | i18n }}
<div class="modal-footer">
<button
type="submit"
class="btn btn-primary btn-submit manual"
[disabled]="form.loading || !canSave"
[ngClass]="{ loading: form.loading }"
*ngIf="organizations && organizations.length"
>
<i
class="bwi bwi-spinner bwi-spin"
title="{{ 'loading' | i18n }}"
aria-hidden="true"
></i>
<span>{{ "save" | i18n }}</span>
</button>
<a
href="#"
routerLink="/create-organization"
class="btn btn-primary"
*ngIf="!organizations || !organizations.length"
>
{{ "newOrganization" | i18n }}
</a>
<button type="button" class="btn btn-outline-secondary" data-dismiss="modal">
{{ "cancel" | i18n }}
</button>
</div>
<table class="table table-hover table-list mb-0" *ngIf="collections && collections.length">
<tbody>
<tr *ngFor="let c of collections; let i = index" (click)="check(c)">
<td class="table-list-checkbox">
<input
type="checkbox"
[(ngModel)]="c.checked"
name="Collection[{{ i }}].Checked"
appStopProp
/>
</td>
<td>
{{ c.name }}
</td>
</tr>
</tbody>
</table>
</div>
<div class="modal-footer">
<button
type="submit"
class="btn btn-primary btn-submit manual"
[disabled]="form.loading || !canSave"
[ngClass]="{ loading: form.loading }"
*ngIf="organizations && organizations.length"
>
<i class="bwi bwi-spinner bwi-spin" title="{{ 'loading' | i18n }}" aria-hidden="true"></i>
<span>{{ "save" | i18n }}</span>
</button>
<a
href="#"
routerLink="/create-organization"
class="btn btn-primary"
*ngIf="!organizations || !organizations.length"
>
{{ "newOrganization" | i18n }}
</a>
<button type="button" class="btn btn-outline-secondary" data-dismiss="modal">
{{ "cancel" | i18n }}
</button>
</div>
</ng-container>
</form>
</div>
</div>

View File

@@ -5,7 +5,7 @@ import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
import { CollectionService } from "@bitwarden/common/abstractions/collection.service";
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/abstractions/log.service";
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
import { CollectionView } from "@bitwarden/common/models/view/collectionView";

View File

@@ -102,9 +102,7 @@ export class OrganizationOptionsComponent {
}
try {
this.actionPromise = this.organizationApiService.leave(org.id).then(() => {
return this.syncService.fullSync(true);
});
this.actionPromise = this.organizationApiService.leave(org.id);
await this.actionPromise;
this.platformUtilsService.showToast("success", null, this.i18nService.t("leftOrganization"));
await this.load();

View File

@@ -8,7 +8,7 @@ import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
import { CollectionService } from "@bitwarden/common/abstractions/collection.service";
import { FolderService } from "@bitwarden/common/abstractions/folder/folder.service.abstraction";
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
import { PolicyService } from "@bitwarden/common/abstractions/policy/policy.service.abstraction";
import { StateService } from "@bitwarden/common/abstractions/state.service";
import { CollectionData } from "@bitwarden/common/models/data/collectionData";

View File

@@ -17,7 +17,7 @@ import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
import { PasswordRepromptService } from "@bitwarden/common/abstractions/passwordReprompt.service";
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
import { StateService } from "@bitwarden/common/abstractions/state.service";