mirror of
https://github.com/bitwarden/browser
synced 2025-12-15 15:53:27 +00:00
* Add feature flag route guard and tests * Add additional test for not showing error toast * Strengthen error toast test with message check * Cleanup leaking test state in platformService mock * Negate if statement to reduce nesting * Update return type to CanActivateFn * Use null check instead of undefined * Introduce interface to support different feature flag types - Switch to observable pattern to access serverConfig$ subject - Add catchError handler to allow navigation in case of unexpected exception - Add additional tests * Add additional test for missing feature flag * Remove subscription to the serverConfig observable Introduce type checking logic to determine the appropriately typed flag getter to use in configService * [AC-1192] Create initial device approvals component and route * [AC-1192] Introduce appIfFeature directive for conditionally rendering content based on feature flags * [AC-1192] Add DeviceApprovals link in Settings navigation * Remove align middle from bitCell directive The bitRow directive supports alignment for the entire row and should be used instead * [AC-1192] Add initial device approvals page template * [AC-1192] Introduce fingerprint pipe * [AC-1192] Create core organization module in bitwarden_license directory * [AC-1192] Add support for new Devices icon to no items component - Add new Devices svg - Make icon property of bit-no-items an Input property * [AC-1192] Introduce organization-auth-request.service.ts with related views/responses * [AC-1192] Display pending requests on device approvals page - Add support for loading spinner and no items component * [AC-1192] Add method to bulk deny auth requests * [AC-1192] Add functionality to deny requests from device approvals page * [AC-1192] Add organizationUserId to pending-auth-request.view.ts * [AC-1192] Add approvePendingRequest method to organization-auth-request.service.ts * [AC-1192] Add logic to approve a device approval request * [AC-1192] Change bitMenuItem directive into a component and implement ButtonLikeAbstraction Update the bitMenuItem to be a component and implement the ButtonLikeAbstraction to support the bitAction directive. * [AC-1192] Update menu items to use bitActions * [AC-1192] Update device approvals description copy * [AC-1192] Revert changes to bitMenuItem directive * [AC-1192] Rework menus to use click handlers - Wrap async actions to catch/log any exceptions, set an in-progress state, and refresh after completion - Show a loading spinner in the header when an action is in progress - Disable all menu items when an action is in progress * [AC-1192] Move Devices icon into admin-console web directory * [AC-1192] bit-no-items formatting * [AC-1192] Update appIfFeature directive to hide content on error * [AC-1192] Remove deprecated providedIn for OrganizationAuthRequestService * [AC-1192] Rename key to encryptedUserKey to be more descriptive * [AC-1192] Cleanup loading/spinner logic on data refresh * [AC-1192] Set middle as the default bitRow.alignContent * [AC-1192] Change default alignRowContent for table story * [AC-1192] Rename userId to fingerprintMaterial to be more general The fingerprint material is not always the userId so this name is more general * [AC-1192] Remove redundant alignContent attribute * [AC-1192] Move fingerprint pipe to platform
201 lines
5.5 KiB
TypeScript
201 lines
5.5 KiB
TypeScript
import { ScrollingModule } from "@angular/cdk/scrolling";
|
|
import { Meta, moduleMetadata, StoryObj } from "@storybook/angular";
|
|
|
|
import { countries } from "../form/countries";
|
|
|
|
import { TableDataSource } from "./table-data-source";
|
|
import { TableModule } from "./table.module";
|
|
|
|
export default {
|
|
title: "Component Library/Table",
|
|
decorators: [
|
|
moduleMetadata({
|
|
imports: [TableModule, ScrollingModule],
|
|
}),
|
|
],
|
|
argTypes: {
|
|
alignRowContent: {
|
|
options: ["top", "middle", "bottom", "baseline"],
|
|
control: { type: "select" },
|
|
},
|
|
},
|
|
parameters: {
|
|
design: {
|
|
type: "figma",
|
|
url: "https://www.figma.com/file/Zt3YSeb6E6lebAffrNLa0h/Tailwind-Component-Library?node-id=1881%3A18371",
|
|
},
|
|
},
|
|
} as Meta;
|
|
|
|
type Story = StoryObj;
|
|
|
|
export const Default: Story = {
|
|
render: (args) => ({
|
|
props: args,
|
|
template: `
|
|
<bit-table>
|
|
<ng-container header>
|
|
<tr>
|
|
<th bitCell>Header 1</th>
|
|
<th bitCell>Header 2</th>
|
|
<th bitCell>Header 3</th>
|
|
</tr>
|
|
</ng-container>
|
|
<ng-template body>
|
|
<tr bitRow [alignContent]="alignRowContent">
|
|
<td bitCell>Cell 1</td>
|
|
<td bitCell>Cell 2 <br> Multiline Cell</td>
|
|
<td bitCell>Cell 3</td>
|
|
</tr>
|
|
<tr bitRow [alignContent]="alignRowContent">
|
|
<td bitCell>Cell 4</td>
|
|
<td bitCell>Cell 5</td>
|
|
<td bitCell>Cell 6</td>
|
|
</tr>
|
|
<tr bitRow [alignContent]="alignRowContent">
|
|
<td bitCell>Cell 7 <br> Multiline Cell</td>
|
|
<td bitCell>Cell 8</td>
|
|
<td bitCell>Cell 9</td>
|
|
</tr>
|
|
</ng-template>
|
|
</bit-table>
|
|
`,
|
|
}),
|
|
args: {
|
|
alignRowContent: "middle",
|
|
},
|
|
};
|
|
|
|
const data = new TableDataSource<{ id: number; name: string; other: string }>();
|
|
|
|
data.data = [...Array(5).keys()].map((i) => ({
|
|
id: i,
|
|
name: `name-${i}`,
|
|
other: `other-${i}`,
|
|
}));
|
|
|
|
export const DataSource: Story = {
|
|
render: (args) => ({
|
|
props: {
|
|
dataSource: data,
|
|
sortFn: (a: any, b: any) => a.id - b.id,
|
|
},
|
|
template: `
|
|
<bit-table [dataSource]="dataSource">
|
|
<ng-container header>
|
|
<tr>
|
|
<th bitCell bitSortable="id" default>Id</th>
|
|
<th bitCell bitSortable="name">Name</th>
|
|
<th bitCell bitSortable="other" [fn]="sortFn">Other</th>
|
|
</tr>
|
|
</ng-container>
|
|
<ng-template body let-rows$>
|
|
<tr bitRow *ngFor="let r of rows$ | async">
|
|
<td bitCell>{{ r.id }}</td>
|
|
<td bitCell>{{ r.name }}</td>
|
|
<td bitCell>{{ r.other }}</td>
|
|
</tr>
|
|
</ng-template>
|
|
</bit-table>
|
|
`,
|
|
}),
|
|
};
|
|
|
|
const data2 = new TableDataSource<{ id: number; name: string; other: string }>();
|
|
|
|
data2.data = [...Array(100).keys()].map((i) => ({
|
|
id: i,
|
|
name: `name-${i}`,
|
|
other: `other-${i}`,
|
|
}));
|
|
|
|
export const Scrollable: Story = {
|
|
render: (args) => ({
|
|
props: {
|
|
dataSource: data2,
|
|
sortFn: (a: any, b: any) => a.id - b.id,
|
|
},
|
|
template: `
|
|
<cdk-virtual-scroll-viewport scrollWindow itemSize="47">
|
|
<bit-table [dataSource]="dataSource">
|
|
<ng-container header>
|
|
<tr>
|
|
<th bitCell bitSortable="id" default>Id</th>
|
|
<th bitCell bitSortable="name">Name</th>
|
|
<th bitCell bitSortable="other" [fn]="sortFn">Other</th>
|
|
</tr>
|
|
</ng-container>
|
|
<ng-template body let-rows$>
|
|
<tr bitRow *cdkVirtualFor="let r of rows$">
|
|
<td bitCell>{{ r.id }}</td>
|
|
<td bitCell>{{ r.name }}</td>
|
|
<td bitCell>{{ r.other }}</td>
|
|
</tr>
|
|
</ng-template>
|
|
</bit-table>
|
|
</cdk-virtual-scroll-viewport>
|
|
`,
|
|
}),
|
|
};
|
|
|
|
const data3 = new TableDataSource<{ value: string; name: string }>();
|
|
|
|
// Chromatic has a max page size, lowering the number of entries to ensure we don't hit it
|
|
data3.data = countries.slice(0, 100);
|
|
|
|
export const Filterable: Story = {
|
|
render: (args) => ({
|
|
props: {
|
|
dataSource: data3,
|
|
sortFn: (a: any, b: any) => a.id - b.id,
|
|
},
|
|
template: `
|
|
<input type="search" placeholder="Search" (input)="dataSource.filter = $event.target.value" />
|
|
<cdk-virtual-scroll-viewport scrollWindow itemSize="47">
|
|
<bit-table [dataSource]="dataSource">
|
|
<ng-container header>
|
|
<tr>
|
|
<th bitCell bitSortable="name" default>Name</th>
|
|
<th bitCell bitSortable="value" width="120px">Value</th>
|
|
</tr>
|
|
</ng-container>
|
|
<ng-template body let-rows$>
|
|
<tr bitRow *cdkVirtualFor="let r of rows$">
|
|
<td bitCell>{{ r.name }}</td>
|
|
<td bitCell>{{ r.value }}</td>
|
|
</tr>
|
|
</ng-template>
|
|
</bit-table>
|
|
</cdk-virtual-scroll-viewport>
|
|
`,
|
|
}),
|
|
};
|
|
|
|
const data4 = new TableDataSource<{ name: string }>();
|
|
|
|
data4.data = [...Array(5).keys()].map((i) => ({
|
|
name: i % 2 == 0 ? `name-${i}`.toUpperCase() : `name-${i}`.toLowerCase(),
|
|
}));
|
|
|
|
export const VariableCase: Story = {
|
|
render: (args) => ({
|
|
props: {
|
|
dataSource: data4,
|
|
},
|
|
template: `
|
|
<bit-table [dataSource]="dataSource">
|
|
<ng-container header>
|
|
<tr>
|
|
<th bitCell bitSortable="name" default>Name</th>
|
|
</tr>
|
|
</ng-container>
|
|
<ng-template body let-rows$>
|
|
<tr bitRow *ngFor="let r of rows$ | async">
|
|
<td bitCell>{{ r.name }}</td>
|
|
</tr>
|
|
</ng-template>
|
|
</bit-table>
|
|
`,
|
|
}),
|
|
};
|