mirror of
https://github.com/bitwarden/browser
synced 2025-12-22 11:13:46 +00:00
Create initial 'Groups' tab
This commit is contained in:
@@ -27,12 +27,12 @@ import { FooterComponent } from "../layouts/footer.component";
|
|||||||
import { FrontendLayoutComponent } from "../layouts/frontend-layout.component";
|
import { FrontendLayoutComponent } from "../layouts/frontend-layout.component";
|
||||||
import { NavbarComponent } from "../layouts/navbar.component";
|
import { NavbarComponent } from "../layouts/navbar.component";
|
||||||
import { UserLayoutComponent } from "../layouts/user-layout.component";
|
import { UserLayoutComponent } from "../layouts/user-layout.component";
|
||||||
|
import { GroupAddEditComponent as OrgGroupAddEditComponent } from "../organizations/groups/group-add-edit.component";
|
||||||
|
import { GroupsComponent as OrgGroupsComponent } from "../organizations/groups/groups.component";
|
||||||
import { OrganizationLayoutComponent } from "../organizations/layouts/organization-layout.component";
|
import { OrganizationLayoutComponent } from "../organizations/layouts/organization-layout.component";
|
||||||
import { CollectionAddEditComponent as OrgCollectionAddEditComponent } from "../organizations/manage/collection-add-edit.component";
|
import { CollectionAddEditComponent as OrgCollectionAddEditComponent } from "../organizations/manage/collection-add-edit.component";
|
||||||
import { CollectionsComponent as OrgManageCollectionsComponent } from "../organizations/manage/collections.component";
|
import { CollectionsComponent as OrgManageCollectionsComponent } from "../organizations/manage/collections.component";
|
||||||
import { EventsComponent as OrgEventsComponent } from "../organizations/manage/events.component";
|
import { EventsComponent as OrgEventsComponent } from "../organizations/manage/events.component";
|
||||||
import { GroupAddEditComponent as OrgGroupAddEditComponent } from "../organizations/manage/group-add-edit.component";
|
|
||||||
import { GroupsComponent as OrgGroupsComponent } from "../organizations/manage/groups.component";
|
|
||||||
import { ManageComponent as OrgManageComponent } from "../organizations/manage/manage.component";
|
import { ManageComponent as OrgManageComponent } from "../organizations/manage/manage.component";
|
||||||
import { PoliciesComponent as OrgPoliciesComponent } from "../organizations/manage/policies.component";
|
import { PoliciesComponent as OrgPoliciesComponent } from "../organizations/manage/policies.component";
|
||||||
import { PolicyEditComponent as OrgPolicyEditComponent } from "../organizations/manage/policy-edit.component";
|
import { PolicyEditComponent as OrgPolicyEditComponent } from "../organizations/manage/policy-edit.component";
|
||||||
|
|||||||
79
apps/web/src/app/organizations/groups/groups.component.html
Normal file
79
apps/web/src/app/organizations/groups/groups.component.html
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
<div class="container page-content">
|
||||||
|
<div class="page-header d-flex">
|
||||||
|
<h1>{{ "groups" | i18n }}</h1>
|
||||||
|
<div class="ml-auto d-flex">
|
||||||
|
<div>
|
||||||
|
<label class="sr-only" for="search">{{ "search" | i18n }}</label>
|
||||||
|
<input
|
||||||
|
type="search"
|
||||||
|
class="form-control form-control-sm"
|
||||||
|
id="search"
|
||||||
|
placeholder="{{ 'search' | i18n }}"
|
||||||
|
[(ngModel)]="searchText"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<button type="button" class="btn btn-sm btn-outline-primary ml-3" (click)="add()">
|
||||||
|
<i class="bwi bwi-plus bwi-fw" aria-hidden="true"></i>
|
||||||
|
{{ "newGroup" | i18n }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<ng-container *ngIf="loading">
|
||||||
|
<i
|
||||||
|
class="bwi bwi-spinner bwi-spin text-muted"
|
||||||
|
title="{{ 'loading' | i18n }}"
|
||||||
|
aria-hidden="true"
|
||||||
|
></i>
|
||||||
|
<span class="sr-only">{{ "loading" | i18n }}</span>
|
||||||
|
</ng-container>
|
||||||
|
<ng-container
|
||||||
|
*ngIf="
|
||||||
|
!loading &&
|
||||||
|
(isPaging() ? pagedGroups : (groups | search: searchText:'name':'id')) as searchedGroups
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<p *ngIf="!searchedGroups.length">{{ "noGroupsInList" | i18n }}</p>
|
||||||
|
<table
|
||||||
|
class="table table-hover table-list"
|
||||||
|
*ngIf="searchedGroups.length"
|
||||||
|
infiniteScroll
|
||||||
|
[infiniteScrollDistance]="1"
|
||||||
|
[infiniteScrollDisabled]="!isPaging()"
|
||||||
|
(scrolled)="loadMore()"
|
||||||
|
>
|
||||||
|
<tbody>
|
||||||
|
<tr *ngFor="let g of searchedGroups">
|
||||||
|
<td>
|
||||||
|
<a href="#" appStopClick (click)="edit(g)">{{ g.name }}</a>
|
||||||
|
</td>
|
||||||
|
<td class="table-list-options">
|
||||||
|
<div class="dropdown" appListDropdown>
|
||||||
|
<button
|
||||||
|
class="btn btn-outline-secondary dropdown-toggle"
|
||||||
|
type="button"
|
||||||
|
data-toggle="dropdown"
|
||||||
|
aria-haspopup="true"
|
||||||
|
aria-expanded="false"
|
||||||
|
appA11yTitle="{{ 'options' | i18n }}"
|
||||||
|
>
|
||||||
|
<i class="bwi bwi-cog bwi-lg" aria-hidden="true"></i>
|
||||||
|
</button>
|
||||||
|
<div class="dropdown-menu dropdown-menu-right">
|
||||||
|
<a class="dropdown-item" href="#" appStopClick (click)="users(g)">
|
||||||
|
<i class="bwi bwi-fw bwi-users" aria-hidden="true"></i>
|
||||||
|
{{ "users" | i18n }}
|
||||||
|
</a>
|
||||||
|
<a class="dropdown-item text-danger" href="#" appStopClick (click)="delete(g)">
|
||||||
|
<i class="bwi bwi-fw bwi-trash" aria-hidden="true"></i>
|
||||||
|
{{ "delete" | i18n }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</ng-container>
|
||||||
|
<ng-template #addEdit></ng-template>
|
||||||
|
<ng-template #usersTemplate></ng-template>
|
||||||
|
</div>
|
||||||
@@ -49,7 +49,7 @@ export class GroupsComponent implements OnInit {
|
|||||||
) {}
|
) {}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
this.route.parent.parent.params.subscribe(async (params) => {
|
this.route.parent.params.subscribe(async (params) => {
|
||||||
this.organizationId = params.organizationId;
|
this.organizationId = params.organizationId;
|
||||||
const organization = await this.organizationService.get(this.organizationId);
|
const organization = await this.organizationService.get(this.organizationId);
|
||||||
if (organization == null || !organization.useGroups) {
|
if (organization == null || !organization.useGroups) {
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
<div class="page-header d-flex">
|
|
||||||
<h1>{{ "groups" | i18n }}</h1>
|
|
||||||
<div class="ml-auto d-flex">
|
|
||||||
<div>
|
|
||||||
<label class="sr-only" for="search">{{ "search" | i18n }}</label>
|
|
||||||
<input
|
|
||||||
type="search"
|
|
||||||
class="form-control form-control-sm"
|
|
||||||
id="search"
|
|
||||||
placeholder="{{ 'search' | i18n }}"
|
|
||||||
[(ngModel)]="searchText"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<button type="button" class="btn btn-sm btn-outline-primary ml-3" (click)="add()">
|
|
||||||
<i class="bwi bwi-plus bwi-fw" aria-hidden="true"></i>
|
|
||||||
{{ "newGroup" | i18n }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<ng-container *ngIf="loading">
|
|
||||||
<i
|
|
||||||
class="bwi bwi-spinner bwi-spin text-muted"
|
|
||||||
title="{{ 'loading' | i18n }}"
|
|
||||||
aria-hidden="true"
|
|
||||||
></i>
|
|
||||||
<span class="sr-only">{{ "loading" | i18n }}</span>
|
|
||||||
</ng-container>
|
|
||||||
<ng-container
|
|
||||||
*ngIf="
|
|
||||||
!loading &&
|
|
||||||
(isPaging() ? pagedGroups : (groups | search: searchText:'name':'id')) as searchedGroups
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<p *ngIf="!searchedGroups.length">{{ "noGroupsInList" | i18n }}</p>
|
|
||||||
<table
|
|
||||||
class="table table-hover table-list"
|
|
||||||
*ngIf="searchedGroups.length"
|
|
||||||
infiniteScroll
|
|
||||||
[infiniteScrollDistance]="1"
|
|
||||||
[infiniteScrollDisabled]="!isPaging()"
|
|
||||||
(scrolled)="loadMore()"
|
|
||||||
>
|
|
||||||
<tbody>
|
|
||||||
<tr *ngFor="let g of searchedGroups">
|
|
||||||
<td>
|
|
||||||
<a href="#" appStopClick (click)="edit(g)">{{ g.name }}</a>
|
|
||||||
</td>
|
|
||||||
<td class="table-list-options">
|
|
||||||
<div class="dropdown" appListDropdown>
|
|
||||||
<button
|
|
||||||
class="btn btn-outline-secondary dropdown-toggle"
|
|
||||||
type="button"
|
|
||||||
data-toggle="dropdown"
|
|
||||||
aria-haspopup="true"
|
|
||||||
aria-expanded="false"
|
|
||||||
appA11yTitle="{{ 'options' | i18n }}"
|
|
||||||
>
|
|
||||||
<i class="bwi bwi-cog bwi-lg" aria-hidden="true"></i>
|
|
||||||
</button>
|
|
||||||
<div class="dropdown-menu dropdown-menu-right">
|
|
||||||
<a class="dropdown-item" href="#" appStopClick (click)="users(g)">
|
|
||||||
<i class="bwi bwi-fw bwi-users" aria-hidden="true"></i>
|
|
||||||
{{ "users" | i18n }}
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item text-danger" href="#" appStopClick (click)="delete(g)">
|
|
||||||
<i class="bwi bwi-fw bwi-trash" aria-hidden="true"></i>
|
|
||||||
{{ "delete" | i18n }}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</ng-container>
|
|
||||||
<ng-template #addEdit></ng-template>
|
|
||||||
<ng-template #usersTemplate></ng-template>
|
|
||||||
@@ -6,11 +6,11 @@ import { Permissions } from "@bitwarden/common/enums/permissions";
|
|||||||
|
|
||||||
import { OrganizationVaultModule } from "../modules/vault/modules/organization-vault/organization-vault.module";
|
import { OrganizationVaultModule } from "../modules/vault/modules/organization-vault/organization-vault.module";
|
||||||
|
|
||||||
|
import { GroupsComponent } from "./groups/groups.component";
|
||||||
import { PermissionsGuard } from "./guards/permissions.guard";
|
import { PermissionsGuard } from "./guards/permissions.guard";
|
||||||
import { OrganizationLayoutComponent } from "./layouts/organization-layout.component";
|
import { OrganizationLayoutComponent } from "./layouts/organization-layout.component";
|
||||||
import { CollectionsComponent } from "./manage/collections.component";
|
import { CollectionsComponent } from "./manage/collections.component";
|
||||||
import { EventsComponent } from "./manage/events.component";
|
import { EventsComponent } from "./manage/events.component";
|
||||||
import { GroupsComponent } from "./manage/groups.component";
|
|
||||||
import { ManageComponent } from "./manage/manage.component";
|
import { ManageComponent } from "./manage/manage.component";
|
||||||
import { PoliciesComponent } from "./manage/policies.component";
|
import { PoliciesComponent } from "./manage/policies.component";
|
||||||
import { MembersComponent } from "./members/members.component";
|
import { MembersComponent } from "./members/members.component";
|
||||||
@@ -143,15 +143,6 @@ const routes: Routes = [
|
|||||||
permissions: [Permissions.AccessEventLogs],
|
permissions: [Permissions.AccessEventLogs],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: "groups",
|
|
||||||
component: GroupsComponent,
|
|
||||||
canActivate: [PermissionsGuard],
|
|
||||||
data: {
|
|
||||||
titleId: "groups",
|
|
||||||
permissions: [Permissions.ManageGroups],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: "policies",
|
path: "policies",
|
||||||
component: PoliciesComponent,
|
component: PoliciesComponent,
|
||||||
@@ -198,6 +189,15 @@ const routes: Routes = [
|
|||||||
permissions: [Permissions.ManageUsers, Permissions.ManageUsersPassword],
|
permissions: [Permissions.ManageUsers, Permissions.ManageUsersPassword],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "groups",
|
||||||
|
component: GroupsComponent,
|
||||||
|
canActivate: [PermissionsGuard],
|
||||||
|
data: {
|
||||||
|
titleId: "groups",
|
||||||
|
permissions: [Permissions.ManageGroups],
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
Reference in New Issue
Block a user