mirror of
https://github.com/bitwarden/browser
synced 2025-12-12 14:23:32 +00:00
[PM-12720] - sort organizations in vault item owner select (#13419)
* sort owner select options and filters by name * don't sort filters * fix tests * fix tests * set organizations in ngOninit * move assignment up * Revert change to add-edit.component.ts. Move assignment up. * fix tests
This commit is contained in:
@@ -27,7 +27,7 @@
|
|||||||
[label]="userEmail$ | async"
|
[label]="userEmail$ | async"
|
||||||
></bit-option>
|
></bit-option>
|
||||||
<bit-option
|
<bit-option
|
||||||
*ngFor="let org of config.organizations"
|
*ngFor="let org of organizations"
|
||||||
[value]="org.id"
|
[value]="org.id"
|
||||||
[label]="org.name"
|
[label]="org.name"
|
||||||
></bit-option>
|
></bit-option>
|
||||||
|
|||||||
@@ -59,6 +59,9 @@ describe("ItemDetailsSectionComponent", () => {
|
|||||||
initializedWithCachedCipher,
|
initializedWithCachedCipher,
|
||||||
});
|
});
|
||||||
i18nService = mock<I18nService>();
|
i18nService = mock<I18nService>();
|
||||||
|
i18nService.collator = {
|
||||||
|
compare: (a: string, b: string) => a.localeCompare(b),
|
||||||
|
} as Intl.Collator;
|
||||||
|
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [ItemDetailsSectionComponent, CommonModule, ReactiveFormsModule],
|
imports: [ItemDetailsSectionComponent, CommonModule, ReactiveFormsModule],
|
||||||
@@ -184,16 +187,18 @@ describe("ItemDetailsSectionComponent", () => {
|
|||||||
|
|
||||||
it("should allow ownership change if personal ownership is allowed and there is at least one organization", () => {
|
it("should allow ownership change if personal ownership is allowed and there is at least one organization", () => {
|
||||||
component.config.allowPersonalOwnership = true;
|
component.config.allowPersonalOwnership = true;
|
||||||
component.config.organizations = [{ id: "org1" } as Organization];
|
component.config.organizations = [{ id: "org1", name: "org1" } as Organization];
|
||||||
|
fixture.detectChanges();
|
||||||
expect(component.allowOwnershipChange).toBe(true);
|
expect(component.allowOwnershipChange).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should allow ownership change if personal ownership is not allowed but there is more than one organization", () => {
|
it("should allow ownership change if personal ownership is not allowed but there is more than one organization", () => {
|
||||||
component.config.allowPersonalOwnership = false;
|
component.config.allowPersonalOwnership = false;
|
||||||
component.config.organizations = [
|
component.config.organizations = [
|
||||||
{ id: "org1" } as Organization,
|
{ id: "org1", name: "org1" } as Organization,
|
||||||
{ id: "org2" } as Organization,
|
{ id: "org2", name: "org2" } as Organization,
|
||||||
];
|
];
|
||||||
|
fixture.detectChanges();
|
||||||
expect(component.allowOwnershipChange).toBe(true);
|
expect(component.allowOwnershipChange).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -206,7 +211,8 @@ describe("ItemDetailsSectionComponent", () => {
|
|||||||
|
|
||||||
it("should return the first organization id if personal ownership is not allowed", () => {
|
it("should return the first organization id if personal ownership is not allowed", () => {
|
||||||
component.config.allowPersonalOwnership = false;
|
component.config.allowPersonalOwnership = false;
|
||||||
component.config.organizations = [{ id: "org1" } as Organization];
|
component.config.organizations = [{ id: "org1", name: "Organization 1" } as Organization];
|
||||||
|
fixture.detectChanges();
|
||||||
expect(component.defaultOwner).toBe("org1");
|
expect(component.defaultOwner).toBe("org1");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -250,6 +256,7 @@ describe("ItemDetailsSectionComponent", () => {
|
|||||||
jest.spyOn(component, "allowOwnershipChange", "get").mockReturnValue(false);
|
jest.spyOn(component, "allowOwnershipChange", "get").mockReturnValue(false);
|
||||||
component.config.mode = "edit";
|
component.config.mode = "edit";
|
||||||
component.config.organizations = [{ id: "org1" } as Organization];
|
component.config.organizations = [{ id: "org1" } as Organization];
|
||||||
|
fixture.detectChanges();
|
||||||
expect(component.showOwnership).toBe(true);
|
expect(component.showOwnership).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -322,8 +329,8 @@ describe("ItemDetailsSectionComponent", () => {
|
|||||||
it("should select the first organization if personal ownership is not allowed", async () => {
|
it("should select the first organization if personal ownership is not allowed", async () => {
|
||||||
component.config.allowPersonalOwnership = false;
|
component.config.allowPersonalOwnership = false;
|
||||||
component.config.organizations = [
|
component.config.organizations = [
|
||||||
{ id: "org1" } as Organization,
|
{ id: "org1", name: "org1" } as Organization,
|
||||||
{ id: "org2" } as Organization,
|
{ id: "org2", name: "org2" } as Organization,
|
||||||
];
|
];
|
||||||
component.originalCipherView = {
|
component.originalCipherView = {
|
||||||
name: "cipher1",
|
name: "cipher1",
|
||||||
@@ -517,4 +524,23 @@ describe("ItemDetailsSectionComponent", () => {
|
|||||||
expect(component["readOnlyCollectionsNames"]).toEqual(["Collection 1", "Collection 3"]);
|
expect(component["readOnlyCollectionsNames"]).toEqual(["Collection 1", "Collection 3"]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("organizationOptions", () => {
|
||||||
|
it("should sort the organizations by name", async () => {
|
||||||
|
component.config.mode = "edit";
|
||||||
|
component.config.organizations = [
|
||||||
|
{ id: "org2", name: "org2" } as Organization,
|
||||||
|
{ id: "org1", name: "org1" } as Organization,
|
||||||
|
];
|
||||||
|
component.originalCipherView = {} as CipherView;
|
||||||
|
|
||||||
|
await component.ngOnInit();
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const select = fixture.debugElement.query(By.directive(SelectComponent));
|
||||||
|
const { label } = select.componentInstance.items[0];
|
||||||
|
|
||||||
|
expect(label).toBe("org1");
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import { OrganizationUserType } from "@bitwarden/common/admin-console/enums";
|
|||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
import { CollectionId, OrganizationId } from "@bitwarden/common/types/guid";
|
import { CollectionId, OrganizationId } from "@bitwarden/common/types/guid";
|
||||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||||
import {
|
import {
|
||||||
@@ -74,6 +75,8 @@ export class ItemDetailsSectionComponent implements OnInit {
|
|||||||
/** The email address associated with the active account */
|
/** The email address associated with the active account */
|
||||||
protected userEmail$ = this.accountService.activeAccount$.pipe(map((account) => account.email));
|
protected userEmail$ = this.accountService.activeAccount$.pipe(map((account) => account.email));
|
||||||
|
|
||||||
|
protected organizations: Organization[] = [];
|
||||||
|
|
||||||
@Input({ required: true })
|
@Input({ required: true })
|
||||||
config: CipherFormConfig;
|
config: CipherFormConfig;
|
||||||
|
|
||||||
@@ -90,10 +93,6 @@ export class ItemDetailsSectionComponent implements OnInit {
|
|||||||
return this.config.mode === "partial-edit";
|
return this.config.mode === "partial-edit";
|
||||||
}
|
}
|
||||||
|
|
||||||
get organizations(): Organization[] {
|
|
||||||
return this.config.organizations;
|
|
||||||
}
|
|
||||||
|
|
||||||
get allowPersonalOwnership() {
|
get allowPersonalOwnership() {
|
||||||
return this.config.allowPersonalOwnership;
|
return this.config.allowPersonalOwnership;
|
||||||
}
|
}
|
||||||
@@ -186,6 +185,10 @@ export class ItemDetailsSectionComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
|
this.organizations = this.config.organizations.sort(
|
||||||
|
Utils.getSortFunction(this.i18nService, "name"),
|
||||||
|
);
|
||||||
|
|
||||||
if (!this.allowPersonalOwnership && this.organizations.length === 0) {
|
if (!this.allowPersonalOwnership && this.organizations.length === 0) {
|
||||||
throw new Error("No organizations available for ownership.");
|
throw new Error("No organizations available for ownership.");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user