mirror of
https://github.com/bitwarden/browser
synced 2025-12-20 10:13:31 +00:00
[EC-15] Members Grid (#4097)
* [EC-623] Introduce shared organization module and search input component * [EC-623] Add search input story * [EC-15] Introduce Members module - Add members module and members routing module - Move members only components into the members module and folder - Remove members only components from LooseComponents module - Update organization routing module to lazy load members module * [EC-15] Enable ToggleGroup component to support generic values Using a generic type for the ToggleGroup allows using both Strings and Enums as values without causing Typescript compiler warning/errors. * [EC-15] Force no bottom margin for Toggle button label * [EC-15] Update Members page header - Use bit-toggle for member status filter - Update bit-toggle Accepted button to say Needs Confirmation - Use bit-search-input - Update search placeholder text - Update invite member button style and text - Import ToggleGroupModule into ShareModule * [EC-15] Update members table - Use the CL bit-table component - Add new table headings - Replace cog options menu with bit-menu component - Add placeholder for groups/collection badges * [EC-15] Specify default generic type for ToggleGroup * [EC-15] Modify getOrganizationUsers() in Api service - Optionally allow the Api service to fetch org user groups and/or collections - Will eventually be moved to an organization user service, but kept here for now * [EC-15] Update member view to fetch groups/collections for users - Use the new Api service functionality - Fetch the organization's list of groups and decrypted collection for rendering their names in the table * [EC-15] Refresh table after editing user groups * [EC-15] Move new members dialog into members module * [EC-15] Show "All" in collections column for users with AccessAll flag * [EC-15] Update copy after talking with design/product
This commit is contained in:
@@ -354,7 +354,11 @@ export abstract class ApiService {
|
||||
) => Promise<OrganizationUserDetailsResponse>;
|
||||
getOrganizationUserGroups: (organizationId: string, id: string) => Promise<string[]>;
|
||||
getOrganizationUsers: (
|
||||
organizationId: string
|
||||
organizationId: string,
|
||||
options?: {
|
||||
includeCollections?: boolean;
|
||||
includeGroups?: boolean;
|
||||
}
|
||||
) => Promise<ListResponse<OrganizationUserUserDetailsResponse>>;
|
||||
getOrganizationUserResetPasswordDetails: (
|
||||
organizationId: string,
|
||||
|
||||
@@ -32,6 +32,8 @@ export class OrganizationUserUserDetailsResponse extends OrganizationUserRespons
|
||||
email: string;
|
||||
twoFactorEnabled: boolean;
|
||||
usesKeyConnector: boolean;
|
||||
collections: SelectionReadOnlyResponse[] = [];
|
||||
groups: string[] = [];
|
||||
|
||||
constructor(response: any) {
|
||||
super(response);
|
||||
@@ -39,6 +41,14 @@ export class OrganizationUserUserDetailsResponse extends OrganizationUserRespons
|
||||
this.email = this.getResponseProperty("Email");
|
||||
this.twoFactorEnabled = this.getResponseProperty("TwoFactorEnabled");
|
||||
this.usesKeyConnector = this.getResponseProperty("UsesKeyConnector") ?? false;
|
||||
const collections = this.getResponseProperty("Collections");
|
||||
if (collections != null) {
|
||||
this.collections = collections.map((c: any) => new SelectionReadOnlyResponse(c));
|
||||
}
|
||||
const groups = this.getResponseProperty("Groups");
|
||||
if (groups != null) {
|
||||
this.groups = groups;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -984,11 +984,24 @@ export class ApiService implements ApiServiceAbstraction {
|
||||
}
|
||||
|
||||
async getOrganizationUsers(
|
||||
organizationId: string
|
||||
organizationId: string,
|
||||
options?: {
|
||||
includeCollections?: boolean;
|
||||
includeGroups?: boolean;
|
||||
}
|
||||
): Promise<ListResponse<OrganizationUserUserDetailsResponse>> {
|
||||
const params = new URLSearchParams();
|
||||
|
||||
if (options?.includeCollections) {
|
||||
params.set("includeCollections", "true");
|
||||
}
|
||||
if (options?.includeGroups) {
|
||||
params.set("includeGroups", "true");
|
||||
}
|
||||
|
||||
const r = await this.send(
|
||||
"GET",
|
||||
"/organizations/" + organizationId + "/users",
|
||||
`/organizations/${organizationId}/users?${params.toString()}`,
|
||||
null,
|
||||
true,
|
||||
true
|
||||
|
||||
@@ -7,17 +7,17 @@ let nextId = 0;
|
||||
templateUrl: "./toggle-group.component.html",
|
||||
preserveWhitespaces: false,
|
||||
})
|
||||
export class ToggleGroupComponent {
|
||||
export class ToggleGroupComponent<TValue = unknown> {
|
||||
private id = nextId++;
|
||||
name = `bit-toggle-group-${this.id}`;
|
||||
|
||||
@Input() selected?: unknown;
|
||||
@Output() selectedChange = new EventEmitter<unknown>();
|
||||
@Input() selected?: TValue;
|
||||
@Output() selectedChange = new EventEmitter<TValue>();
|
||||
|
||||
@HostBinding("attr.role") role = "radiogroup";
|
||||
@HostBinding("class") classList = ["tw-flex"];
|
||||
|
||||
onInputInteraction(value: unknown) {
|
||||
onInputInteraction(value: TValue) {
|
||||
this.selected = value;
|
||||
this.selectedChange.emit(value);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { HostBinding, Component, Input } from "@angular/core";
|
||||
import { Component, HostBinding, Input } from "@angular/core";
|
||||
|
||||
import { ToggleGroupComponent } from "./toggle-group.component";
|
||||
|
||||
@@ -9,12 +9,12 @@ let nextId = 0;
|
||||
templateUrl: "./toggle.component.html",
|
||||
preserveWhitespaces: false,
|
||||
})
|
||||
export class ToggleComponent {
|
||||
export class ToggleComponent<TValue> {
|
||||
id = nextId++;
|
||||
|
||||
@Input() value?: string;
|
||||
@Input() value?: TValue;
|
||||
|
||||
constructor(private groupComponent: ToggleGroupComponent) {}
|
||||
constructor(private groupComponent: ToggleGroupComponent<TValue>) {}
|
||||
|
||||
@HostBinding("tabIndex") tabIndex = "-1";
|
||||
@HostBinding("class") classList = ["tw-group"];
|
||||
@@ -67,6 +67,9 @@ export class ToggleComponent {
|
||||
"tw-py-1.5",
|
||||
"tw-px-3",
|
||||
|
||||
// Fix for bootstrap styles that add bottom margin
|
||||
"!tw-mb-0",
|
||||
|
||||
// Fix for badge being pushed slightly lower when inside a button.
|
||||
// Insipired by bootstrap, which does the same.
|
||||
"[&>[bitBadge]]:tw-relative",
|
||||
|
||||
Reference in New Issue
Block a user