Drop Storybook from the project (#881)
This commit is contained in:
parent
a6e4e72270
commit
1d79a5d9a8
36 changed files with 62 additions and 25292 deletions
|
@ -1,4 +1,3 @@
|
|||
.git
|
||||
cypress
|
||||
.github
|
||||
.storybook
|
||||
|
|
1
.github/workflows/node.js.yml
vendored
1
.github/workflows/node.js.yml
vendored
|
@ -30,4 +30,3 @@ jobs:
|
|||
- run: npm run lint
|
||||
- run: npm run test
|
||||
- run: npm run build
|
||||
- run: npm run build-storybook
|
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -89,9 +89,6 @@ lib/
|
|||
# https://create-react-app.dev/docs/using-the-public-folder/#docsNav
|
||||
# public
|
||||
|
||||
# Storybook build outputs
|
||||
storybook-static/
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
module.exports = {
|
||||
core: {
|
||||
builder: "webpack5"
|
||||
},
|
||||
stories: [
|
||||
"../src/**/*.stories.mdx",
|
||||
"../src/**/*.stories.@(js|jsx|ts|tsx)"
|
||||
],
|
||||
addons: [
|
||||
"@storybook/addon-links",
|
||||
"@storybook/addon-essentials",
|
||||
{
|
||||
name: "@storybook/addon-postcss",
|
||||
options: {
|
||||
// Explicitly enable PostCSS 8+ (see: https://storybook.js.org/addons/@storybook/addon-postcss)
|
||||
postcssLoaderOptions: {
|
||||
implementation: require("postcss"),
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
<link rel="stylesheet" href="https://unpkg.com/@patternfly/patternfly@4/patternfly.css" crossorigin />
|
||||
<link rel="stylesheet" href="https://unpkg.com/@patternfly/patternfly@4/patternfly-addons.css" crossorigin />
|
||||
<!-- <script src="https://unpkg.com/keycloak-js@10.0.1/dist/keycloak.min.js"></script> -->
|
||||
|
||||
<script>
|
||||
// window.onload = () => {
|
||||
// keycloak = new Keycloak({
|
||||
// url: "http://localhost:8180/auth/",
|
||||
// realm: "master",
|
||||
// clientId: 'new'
|
||||
// });
|
||||
// keycloak.init({ onLoad: 'check-sso', flow: 'standard', responseMode: 'fragment' }).then((authenticated) => {
|
||||
// if (!authenticated) {
|
||||
// keycloak.login({ redirectUri: window.location.href });
|
||||
// }
|
||||
// }).catch((error) => {
|
||||
// console.log(error);
|
||||
// alert('failed to initialize');
|
||||
// });
|
||||
// }
|
||||
</script>
|
||||
|
||||
<style>
|
||||
#root {
|
||||
padding: 3rem;
|
||||
}
|
||||
|
||||
.bg-checkerboard {
|
||||
background-image: linear-gradient(45deg, #808080 25%, transparent 25%),
|
||||
linear-gradient(-45deg, #808080 25%, transparent 25%),
|
||||
linear-gradient(45deg, transparent 75%, #808080 75%),
|
||||
linear-gradient(-45deg, transparent 75%, #808080 75%);
|
||||
background-size: 20px 20px;
|
||||
background-position: 0 0, 0 10px, 10px -10px, -10px 0px;
|
||||
}
|
||||
</style>
|
|
@ -1,9 +0,0 @@
|
|||
export const parameters = {
|
||||
actions: { argTypesRegex: "^on[A-Z].*" },
|
||||
controls: {
|
||||
matchers: {
|
||||
color: /(background|color)$/i,
|
||||
date: /Date$/,
|
||||
},
|
||||
},
|
||||
}
|
24288
package-lock.json
generated
24288
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -21,8 +21,6 @@
|
|||
"test": "jest",
|
||||
"start:cypress": "cypress open",
|
||||
"start:cypress-tests": "cypress run",
|
||||
"storybook": "start-storybook -p 6006",
|
||||
"build-storybook": "build-storybook",
|
||||
"prepare": "husky install"
|
||||
},
|
||||
"dependencies": {
|
||||
|
@ -49,13 +47,6 @@
|
|||
"@snowpack/plugin-postcss": "^1.4.3",
|
||||
"@snowpack/plugin-react-refresh": "^2.5.0",
|
||||
"@snowpack/plugin-typescript": "^1.2.1",
|
||||
"@storybook/addon-actions": "^6.3.4",
|
||||
"@storybook/addon-essentials": "^6.3.4",
|
||||
"@storybook/addon-links": "^6.3.4",
|
||||
"@storybook/addon-postcss": "^2.0.0",
|
||||
"@storybook/builder-webpack5": "^6.3.2",
|
||||
"@storybook/manager-webpack5": "^6.3.2",
|
||||
"@storybook/react": "^6.3.4",
|
||||
"@testing-library/jest-dom": "^5.14.1",
|
||||
"@testing-library/react": "^12.0.0",
|
||||
"@types/file-saver": "^2.0.3",
|
||||
|
|
|
@ -1,8 +1,67 @@
|
|||
import { render, waitFor } from "@testing-library/react";
|
||||
import React from "react";
|
||||
import { MockAdminClient } from "../../stories/MockAdminClient";
|
||||
import type KeycloakAdminClient from "keycloak-admin";
|
||||
import type { ServerInfoRepresentation } from "keycloak-admin/lib/defs/serverInfoRepesentation";
|
||||
import React, { ReactNode } from "react";
|
||||
import { HashRouter } from "react-router-dom";
|
||||
import { AccessContextProvider } from "../../context/access/Access";
|
||||
import { AdminClient } from "../../context/auth/AdminClient";
|
||||
import { RealmContext } from "../../context/realm-context/RealmContext";
|
||||
import { ServerInfoContext } from "../../context/server-info/ServerInfoProvider";
|
||||
import serverInfo from "../../context/server-info/__tests__/mock.json";
|
||||
import { WhoAmIContextProvider } from "../../context/whoami/WhoAmI";
|
||||
import whoamiMock from "../../context/whoami/__tests__/mock-whoami.json";
|
||||
import { DataLoader } from "./DataLoader";
|
||||
|
||||
/**
|
||||
* This component provides some mocked default react context so that other components can work in a storybook.
|
||||
* In it's simplest form wrap your component like so:
|
||||
* @example
|
||||
* <MockAdminClient>
|
||||
* <SomeComponent />
|
||||
* </MockAdminClient>
|
||||
* @example <caption>With an endpoint, roles => findOneById</caption>
|
||||
* <MockAdminClient mock={{ roles: { findOneById: () => mockJson } }}>
|
||||
* <<SomeComponent />
|
||||
* </MockAdminClient>
|
||||
* @param props mock endpoints to be mocked
|
||||
*/
|
||||
export const MockAdminClient = (props: {
|
||||
children: ReactNode;
|
||||
mock?: object;
|
||||
}) => {
|
||||
return (
|
||||
<HashRouter>
|
||||
<ServerInfoContext.Provider
|
||||
value={serverInfo as unknown as ServerInfoRepresentation}
|
||||
>
|
||||
<AdminClient.Provider
|
||||
value={
|
||||
{
|
||||
...props.mock,
|
||||
keycloak: {},
|
||||
whoAmI: { find: () => Promise.resolve(whoamiMock) },
|
||||
setConfig: () => {},
|
||||
} as unknown as KeycloakAdminClient
|
||||
}
|
||||
>
|
||||
<WhoAmIContextProvider>
|
||||
<RealmContext.Provider
|
||||
value={{
|
||||
realm: "master",
|
||||
setRealm: () => {},
|
||||
realms: [],
|
||||
refresh: () => Promise.resolve(),
|
||||
}}
|
||||
>
|
||||
<AccessContextProvider>{props.children}</AccessContextProvider>
|
||||
</RealmContext.Provider>
|
||||
</WhoAmIContextProvider>
|
||||
</AdminClient.Provider>
|
||||
</ServerInfoContext.Provider>
|
||||
</HashRouter>
|
||||
);
|
||||
};
|
||||
|
||||
describe("DataLoader", () => {
|
||||
it("loads the data and renders the result", async () => {
|
||||
const loader = () => Promise.resolve(["a", "b"]);
|
||||
|
|
|
@ -19,7 +19,6 @@ import events from "./events/messages";
|
|||
import realmSettings from "./realm-settings/messages";
|
||||
import realmSettingsHelp from "./realm-settings/help";
|
||||
import authentication from "./authentication/messages";
|
||||
import storybook from "./stories/messages";
|
||||
import userFederation from "./user-federation/messages";
|
||||
import userFederationHelp from "./user-federation/help";
|
||||
import identityProviders from "./identity-providers/messages";
|
||||
|
@ -52,7 +51,6 @@ const initOptions = {
|
|||
...identityProvidersHelp,
|
||||
...userFederation,
|
||||
...userFederationHelp,
|
||||
...storybook,
|
||||
},
|
||||
},
|
||||
lng: "en",
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
import React, { useState } from "react";
|
||||
import { Button } from "@patternfly/react-core";
|
||||
import type { Meta, Story } from "@storybook/react";
|
||||
import type { ServerInfoRepresentation } from "keycloak-admin/lib/defs/serverInfoRepesentation";
|
||||
|
||||
import serverInfo from "../context/server-info/__tests__/mock.json";
|
||||
import { ServerInfoContext } from "../context/server-info/ServerInfoProvider";
|
||||
import {
|
||||
AddMapperDialog,
|
||||
AddMapperDialogProps,
|
||||
} from "../client-scopes/add/MapperDialog";
|
||||
|
||||
export default {
|
||||
title: "Add mapper dialog",
|
||||
component: AddMapperDialog,
|
||||
} as Meta;
|
||||
|
||||
const Template: Story<AddMapperDialogProps> = (args) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
return (
|
||||
<ServerInfoContext.Provider
|
||||
value={serverInfo as unknown as ServerInfoRepresentation}
|
||||
>
|
||||
<AddMapperDialog
|
||||
{...args}
|
||||
open={open}
|
||||
toggleDialog={() => setOpen(!open)}
|
||||
/>
|
||||
<Button onClick={() => setOpen(true)}>Show</Button>
|
||||
</ServerInfoContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export const BuildInDialog = Template.bind({});
|
||||
BuildInDialog.args = {
|
||||
protocol: "openid-connect",
|
||||
filter: [],
|
||||
};
|
||||
|
||||
export const ProtocolMapperDialog = Template.bind({});
|
||||
ProtocolMapperDialog.args = {
|
||||
protocol: "openid-connect",
|
||||
};
|
|
@ -1,33 +0,0 @@
|
|||
import React from "react";
|
||||
import { AlertVariant, Button } from "@patternfly/react-core";
|
||||
import type { Meta } from "@storybook/react";
|
||||
|
||||
import { AlertPanel } from "../components/alert/AlertPanel";
|
||||
import { AlertProvider, useAlerts } from "../components/alert/Alerts";
|
||||
|
||||
export default {
|
||||
title: "Alert Panel",
|
||||
component: AlertPanel,
|
||||
} as Meta;
|
||||
|
||||
export const Api = () => (
|
||||
<AlertPanel
|
||||
alerts={[{ key: 1, message: "Hello", variant: AlertVariant.default }]}
|
||||
onCloseAlert={() => {}}
|
||||
/>
|
||||
);
|
||||
|
||||
const AlertButton = () => {
|
||||
const { addAlert } = useAlerts();
|
||||
return (
|
||||
<Button onClick={() => addAlert("Hello", AlertVariant.default)}>Add</Button>
|
||||
);
|
||||
};
|
||||
|
||||
export const AddAlert = () => {
|
||||
return (
|
||||
<AlertProvider>
|
||||
<AlertButton />
|
||||
</AlertProvider>
|
||||
);
|
||||
};
|
|
@ -1,67 +0,0 @@
|
|||
import React from "react";
|
||||
import {
|
||||
TextContent,
|
||||
Text,
|
||||
TextVariants,
|
||||
ButtonVariant,
|
||||
} from "@patternfly/react-core";
|
||||
import type { Meta, Story } from "@storybook/react";
|
||||
import { action } from "@storybook/addon-actions";
|
||||
|
||||
import {
|
||||
ConfirmDialogModal,
|
||||
ConfirmDialogModalProps,
|
||||
useConfirmDialog,
|
||||
} from "../components/confirm-dialog/ConfirmDialog";
|
||||
|
||||
export default {
|
||||
title: "Confirmation Dialog",
|
||||
component: ConfirmDialogModal,
|
||||
} as Meta;
|
||||
|
||||
const Template: Story<ConfirmDialogModalProps> = (args) => (
|
||||
<ConfirmDialogModal {...args} />
|
||||
);
|
||||
|
||||
export const Simple = Template.bind({});
|
||||
Simple.args = {
|
||||
titleKey: "Delete app02?",
|
||||
messageKey: "If you delete this client, all associated data will be removed.",
|
||||
continueButtonLabel: "Delete",
|
||||
continueButtonVariant: ButtonVariant.danger,
|
||||
};
|
||||
|
||||
export const Children = Template.bind({});
|
||||
Children.args = {
|
||||
titleKey: "Children as content!",
|
||||
continueButtonVariant: ButtonVariant.primary,
|
||||
children: (
|
||||
<>
|
||||
<TextContent>
|
||||
<Text component={TextVariants.h3}>Hello World</Text>
|
||||
</TextContent>
|
||||
<p>Example of some other patternfly components.</p>
|
||||
</>
|
||||
),
|
||||
};
|
||||
|
||||
const Test = () => {
|
||||
const [toggle, Dialog] = useConfirmDialog({
|
||||
titleKey: "Delete app02?",
|
||||
messageKey:
|
||||
"If you delete this client, all associated data will be removed.",
|
||||
continueButtonLabel: "Delete",
|
||||
onConfirm: action("confirm"),
|
||||
onCancel: action("cancel"),
|
||||
});
|
||||
return (
|
||||
<>
|
||||
<button id="show" onClick={toggle}>
|
||||
Show
|
||||
</button>
|
||||
<Dialog />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const Api = () => <Test />;
|
|
@ -1,50 +0,0 @@
|
|||
import React, { ReactNode } from "react";
|
||||
import type { Meta } from "@storybook/react";
|
||||
|
||||
import { DataLoader } from "../components/data-loader/DataLoader";
|
||||
|
||||
export default {
|
||||
title: "Data Loader",
|
||||
component: DataLoader,
|
||||
} as Meta;
|
||||
|
||||
type Post = {
|
||||
title: string;
|
||||
body: string;
|
||||
};
|
||||
|
||||
export const loadPosts = () => {
|
||||
const PostLoader = (props: { url: string; children: ReactNode }) => {
|
||||
const loader = async () => {
|
||||
const wait = (ms: number, value: Post) =>
|
||||
new Promise((resolve) => setTimeout(resolve, ms, value));
|
||||
return await fetch(props.url)
|
||||
.then((res) => res.json())
|
||||
.then((value) => wait(3000, value));
|
||||
};
|
||||
return <DataLoader loader={loader}>{props.children}</DataLoader>;
|
||||
};
|
||||
|
||||
return (
|
||||
<PostLoader url="https://jsonplaceholder.typicode.com/posts">
|
||||
{(posts: Post[]) => (
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{posts.map((post, i) => (
|
||||
<tr key={i}>
|
||||
<td>{post.title}</td>
|
||||
<td>{post.body}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
)}
|
||||
</PostLoader>
|
||||
);
|
||||
};
|
|
@ -1,32 +0,0 @@
|
|||
import React, { useState } from "react";
|
||||
import type { Meta } from "@storybook/react";
|
||||
|
||||
import { DownloadDialog } from "../components/download-dialog/DownloadDialog";
|
||||
import { MockAdminClient } from "./MockAdminClient";
|
||||
|
||||
export default {
|
||||
title: "Download Dialog",
|
||||
component: DownloadDialog,
|
||||
} as Meta;
|
||||
|
||||
const Test = () => {
|
||||
const [open, setOpen] = useState(false);
|
||||
const toggle = () => setOpen(!open);
|
||||
|
||||
return (
|
||||
<MockAdminClient
|
||||
mock={{ clients: { getInstallationProviders: () => '{some: "json"}' } }}
|
||||
>
|
||||
<button id="show" onClick={toggle}>
|
||||
Show
|
||||
</button>
|
||||
<DownloadDialog
|
||||
id="58577281-7af7-410c-a085-61ff3040be6d"
|
||||
open={open}
|
||||
toggleDialog={toggle}
|
||||
/>
|
||||
</MockAdminClient>
|
||||
);
|
||||
};
|
||||
|
||||
export const Show = () => <Test />;
|
|
@ -1,32 +0,0 @@
|
|||
import React from "react";
|
||||
import type { Meta, Story } from "@storybook/react";
|
||||
import {
|
||||
FormattedLink,
|
||||
FormattedLinkProps,
|
||||
} from "../components/external-link/FormattedLink";
|
||||
|
||||
export default {
|
||||
title: "Formatted link",
|
||||
component: FormattedLink,
|
||||
} as Meta;
|
||||
|
||||
const Template: Story<FormattedLinkProps> = (args) => (
|
||||
<FormattedLink {...args} />
|
||||
);
|
||||
|
||||
export const WithTitle = Template.bind({});
|
||||
WithTitle.args = {
|
||||
title: "With title",
|
||||
href: "http://test.nl",
|
||||
};
|
||||
|
||||
export const WithoutTitle = Template.bind({});
|
||||
WithoutTitle.args = {
|
||||
href: "http://some-other-link.nl/super",
|
||||
};
|
||||
|
||||
export const ApplicationLink = Template.bind({});
|
||||
ApplicationLink.args = {
|
||||
title: "Application link",
|
||||
href: "/application/main",
|
||||
};
|
|
@ -1,81 +0,0 @@
|
|||
import React, { useContext } from "react";
|
||||
import {
|
||||
Page,
|
||||
PageHeader,
|
||||
PageHeaderTools,
|
||||
PageHeaderToolsItem,
|
||||
PageSection,
|
||||
FormGroup,
|
||||
Form,
|
||||
TextInput,
|
||||
} from "@patternfly/react-core";
|
||||
import type { Meta } from "@storybook/react";
|
||||
|
||||
import { HelpItem } from "../components/help-enabler/HelpItem";
|
||||
import {
|
||||
Help,
|
||||
HelpContext,
|
||||
HelpHeader,
|
||||
} from "../components/help-enabler/HelpHeader";
|
||||
|
||||
export default {
|
||||
title: "Help System Example",
|
||||
component: HelpHeader,
|
||||
} as Meta;
|
||||
|
||||
export const HelpSystem = () => (
|
||||
<Help>
|
||||
<HelpSystemTest />
|
||||
</Help>
|
||||
);
|
||||
|
||||
export const HelpItems = () => (
|
||||
<HelpItem
|
||||
helpText="This explains the related field"
|
||||
forLabel="Field label"
|
||||
forID="storybook-example-id"
|
||||
/>
|
||||
);
|
||||
|
||||
export const FormFieldHelp = () => (
|
||||
<Form isHorizontal>
|
||||
<FormGroup
|
||||
label="Label"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="This explains the related field"
|
||||
forLabel="Field label"
|
||||
forID="storybook-form-help"
|
||||
/>
|
||||
}
|
||||
fieldId="storybook-form-help"
|
||||
>
|
||||
<TextInput isRequired type="text" id="storybook-form-help"></TextInput>
|
||||
</FormGroup>
|
||||
</Form>
|
||||
);
|
||||
|
||||
const HelpSystemTest = () => {
|
||||
const { enabled } = useContext(HelpContext);
|
||||
return (
|
||||
<Page
|
||||
header={
|
||||
<PageHeader
|
||||
headerTools={
|
||||
<PageHeaderTools>
|
||||
<PageHeaderToolsItem>
|
||||
<HelpHeader />
|
||||
</PageHeaderToolsItem>
|
||||
<PageHeaderToolsItem>dummy user...</PageHeaderToolsItem>
|
||||
</PageHeaderTools>
|
||||
}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<PageSection>Help system is {enabled ? "enabled" : "not on"}</PageSection>
|
||||
<PageSection variant="light">
|
||||
<FormFieldHelp />
|
||||
</PageSection>
|
||||
</Page>
|
||||
);
|
||||
};
|
|
@ -1,22 +0,0 @@
|
|||
import React from "react";
|
||||
import type { Meta, Story } from "@storybook/react";
|
||||
|
||||
import {
|
||||
JsonFileUpload,
|
||||
JsonFileUploadProps,
|
||||
} from "../components/json-file-upload/JsonFileUpload";
|
||||
|
||||
export default {
|
||||
title: "Json file upload dailog",
|
||||
component: JsonFileUpload,
|
||||
parameters: { actions: { argTypesRegex: "^on.*" } },
|
||||
} as Meta;
|
||||
|
||||
const Template: Story<JsonFileUploadProps> = (args) => (
|
||||
<JsonFileUpload {...args} />
|
||||
);
|
||||
|
||||
export const Dialog = Template.bind({});
|
||||
Dialog.args = {
|
||||
id: "jsonFile",
|
||||
};
|
|
@ -1,65 +0,0 @@
|
|||
import React from "react";
|
||||
import type { IFormatterValueType } from "@patternfly/react-table";
|
||||
import type { Meta, Story } from "@storybook/react";
|
||||
|
||||
import clients from "../clients/__tests__/mock-clients.json";
|
||||
|
||||
import {
|
||||
KeycloakDataTable,
|
||||
DataListProps,
|
||||
} from "../components/table-toolbar/KeycloakDataTable";
|
||||
|
||||
export default {
|
||||
title: "Keycloak Data Table",
|
||||
component: KeycloakDataTable,
|
||||
} as Meta;
|
||||
|
||||
const wait = (ms: number, value: any) =>
|
||||
new Promise((resolve) => setTimeout(resolve, ms, value));
|
||||
|
||||
const Template: Story<DataListProps<any>> = (args) => (
|
||||
<KeycloakDataTable {...args} />
|
||||
);
|
||||
|
||||
export const SimpleList = Template.bind({});
|
||||
SimpleList.args = {
|
||||
ariaLabelKey: "clients:clientList",
|
||||
searchPlaceholderKey: "common:search",
|
||||
columns: [
|
||||
{ name: "clientId", displayKey: "common:clientId" },
|
||||
{ name: "protocol", displayKey: "common:type" },
|
||||
{
|
||||
name: "description",
|
||||
displayKey: "common:description",
|
||||
cellFormatters: [
|
||||
(data?: IFormatterValueType) => {
|
||||
return data ? data : "—";
|
||||
},
|
||||
],
|
||||
},
|
||||
{ name: "baseUrl", displayKey: "clients:homeURL" },
|
||||
],
|
||||
loader: async () => clients,
|
||||
};
|
||||
|
||||
export const LoadingList = Template.bind({});
|
||||
LoadingList.args = {
|
||||
ariaLabelKey: "clients:clientList",
|
||||
searchPlaceholderKey: "common:search",
|
||||
columns: [{ name: "title" }, { name: "body" }],
|
||||
isPaginated: true,
|
||||
loader: async () => {
|
||||
const res = await fetch("https://jsonplaceholder.typicode.com/posts/");
|
||||
const value = await res.json();
|
||||
return wait(3000, value) as any;
|
||||
},
|
||||
};
|
||||
|
||||
export const EmptyList = Template.bind({});
|
||||
EmptyList.args = {
|
||||
ariaLabelKey: "clients:clientList",
|
||||
searchPlaceholderKey: "common:search",
|
||||
columns: [{ name: "title" }, { name: "body" }],
|
||||
loader: () => Promise.resolve([]),
|
||||
emptyState: <h1>Wait what? No content?</h1>,
|
||||
};
|
|
@ -1,27 +0,0 @@
|
|||
import React from "react";
|
||||
import type { Meta, Story } from "@storybook/react";
|
||||
import {
|
||||
ListEmptyState,
|
||||
ListEmptyStateProps,
|
||||
} from "../components/list-empty-state/ListEmptyState";
|
||||
|
||||
function handleClick() {
|
||||
alert("Button clicked to add a thing.");
|
||||
}
|
||||
|
||||
export default {
|
||||
title: "List empty state",
|
||||
component: ListEmptyState,
|
||||
} as Meta;
|
||||
|
||||
const Template: Story<ListEmptyStateProps> = (args) => (
|
||||
<ListEmptyState {...args} />
|
||||
);
|
||||
|
||||
export const View = Template.bind({});
|
||||
View.args = {
|
||||
message: "No things",
|
||||
instructions: "You haven't created any things for this list.",
|
||||
primaryActionText: "Add it now!",
|
||||
secondaryActions: [{ text: "Add a thing", onClick: handleClick }],
|
||||
};
|
|
@ -1,24 +0,0 @@
|
|||
import React from "react";
|
||||
import type { Meta } from "@storybook/react";
|
||||
import type { ServerInfoRepresentation } from "keycloak-admin/lib/defs/serverInfoRepesentation";
|
||||
|
||||
import serverInfo from "../context/server-info/__tests__/mock.json";
|
||||
import clientScopeMock from "../client-scopes/__tests__/mock-client-scope.json";
|
||||
import { ServerInfoContext } from "../context/server-info/ServerInfoProvider";
|
||||
import { MapperList } from "../client-scopes/details/MapperList";
|
||||
import { MockAdminClient } from "./MockAdminClient";
|
||||
|
||||
export default {
|
||||
title: "Mapper List",
|
||||
component: MapperList,
|
||||
} as Meta;
|
||||
|
||||
export const MapperListExample = () => (
|
||||
<ServerInfoContext.Provider
|
||||
value={serverInfo as unknown as ServerInfoRepresentation}
|
||||
>
|
||||
<MockAdminClient>
|
||||
<MapperList clientScope={clientScopeMock} refresh={() => {}} />
|
||||
</MockAdminClient>
|
||||
</ServerInfoContext.Provider>
|
||||
);
|
|
@ -1,63 +0,0 @@
|
|||
import React, { ReactNode } from "react";
|
||||
import { HashRouter } from "react-router-dom";
|
||||
import type KeycloakAdminClient from "keycloak-admin";
|
||||
import type { ServerInfoRepresentation } from "keycloak-admin/lib/defs/serverInfoRepesentation";
|
||||
|
||||
import { AccessContextProvider } from "../context/access/Access";
|
||||
import { WhoAmIContextProvider } from "../context/whoami/WhoAmI";
|
||||
import { RealmContext } from "../context/realm-context/RealmContext";
|
||||
import { AdminClient } from "../context/auth/AdminClient";
|
||||
import { ServerInfoContext } from "../context/server-info/ServerInfoProvider";
|
||||
|
||||
import whoamiMock from "../context/whoami/__tests__/mock-whoami.json";
|
||||
import serverInfo from "../context/server-info/__tests__/mock.json";
|
||||
|
||||
/**
|
||||
* This component provides some mocked default react context so that other components can work in a storybook.
|
||||
* In it's simplest form wrap your component like so:
|
||||
* @example
|
||||
* <MockAdminClient>
|
||||
* <SomeComponent />
|
||||
* </MockAdminClient>
|
||||
* @example <caption>With an endpoint, roles => findOneById</caption>
|
||||
* <MockAdminClient mock={{ roles: { findOneById: () => mockJson } }}>
|
||||
* <<SomeComponent />
|
||||
* </MockAdminClient>
|
||||
* @param props mock endpoints to be mocked
|
||||
*/
|
||||
export const MockAdminClient = (props: {
|
||||
children: ReactNode;
|
||||
mock?: object;
|
||||
}) => {
|
||||
return (
|
||||
<HashRouter>
|
||||
<ServerInfoContext.Provider
|
||||
value={serverInfo as unknown as ServerInfoRepresentation}
|
||||
>
|
||||
<AdminClient.Provider
|
||||
value={
|
||||
{
|
||||
...props.mock,
|
||||
keycloak: {},
|
||||
whoAmI: { find: () => Promise.resolve(whoamiMock) },
|
||||
setConfig: () => {},
|
||||
} as unknown as KeycloakAdminClient
|
||||
}
|
||||
>
|
||||
<WhoAmIContextProvider>
|
||||
<RealmContext.Provider
|
||||
value={{
|
||||
realm: "master",
|
||||
setRealm: () => {},
|
||||
realms: [],
|
||||
refresh: () => Promise.resolve(),
|
||||
}}
|
||||
>
|
||||
<AccessContextProvider>{props.children}</AccessContextProvider>
|
||||
</RealmContext.Provider>
|
||||
</WhoAmIContextProvider>
|
||||
</AdminClient.Provider>
|
||||
</ServerInfoContext.Provider>
|
||||
</HashRouter>
|
||||
);
|
||||
};
|
|
@ -1,39 +0,0 @@
|
|||
import React from "react";
|
||||
import type { Meta, Story } from "@storybook/react";
|
||||
import { action } from "@storybook/addon-actions";
|
||||
import { FormProvider, useForm } from "react-hook-form";
|
||||
import { Button } from "@patternfly/react-core";
|
||||
|
||||
import {
|
||||
MultiLineInput,
|
||||
MultiLineInputProps,
|
||||
toValue,
|
||||
} from "../components/multi-line-input/MultiLineInput";
|
||||
|
||||
export default {
|
||||
title: "MultiLineInput component",
|
||||
component: MultiLineInput,
|
||||
} as Meta;
|
||||
|
||||
const Template: Story<MultiLineInputProps> = (args) => {
|
||||
const form = useForm({ mode: "onChange" });
|
||||
return (
|
||||
<form
|
||||
onSubmit={form.handleSubmit((data) => {
|
||||
action("submit")(toValue(data.items));
|
||||
})}
|
||||
>
|
||||
<FormProvider {...form}>
|
||||
<MultiLineInput {...args} />
|
||||
</FormProvider>
|
||||
<br />
|
||||
<br />
|
||||
<Button type="submit">Submit</Button>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
export const View = Template.bind({});
|
||||
View.args = {
|
||||
name: "items",
|
||||
};
|
|
@ -1,20 +0,0 @@
|
|||
import React from "react";
|
||||
import type { Meta } from "@storybook/react";
|
||||
import { Page } from "@patternfly/react-core";
|
||||
import { NewRealmForm } from "../realm/add/NewRealmForm";
|
||||
import { MockAdminClient } from "./MockAdminClient";
|
||||
|
||||
export default {
|
||||
title: "New realm form",
|
||||
component: NewRealmForm,
|
||||
} as Meta;
|
||||
|
||||
export const view = () => {
|
||||
return (
|
||||
<Page>
|
||||
<MockAdminClient>
|
||||
<NewRealmForm />
|
||||
</MockAdminClient>
|
||||
</Page>
|
||||
);
|
||||
};
|
|
@ -1,18 +0,0 @@
|
|||
import React from "react";
|
||||
import type { Meta } from "@storybook/react";
|
||||
import { MockAdminClient } from "./MockAdminClient";
|
||||
import rolesMock from "../realm-roles/__tests__/mock-roles.json";
|
||||
import { RealmRoleTabs } from "../realm-roles/RealmRoleTabs";
|
||||
|
||||
export default {
|
||||
title: "Roles tabs",
|
||||
component: RealmRoleTabs,
|
||||
} as Meta;
|
||||
|
||||
export const RolesTabsExample = () => {
|
||||
return (
|
||||
<MockAdminClient mock={{ roles: { findOneById: () => rolesMock[0] } }}>
|
||||
<RealmRoleTabs />
|
||||
</MockAdminClient>
|
||||
);
|
||||
};
|
|
@ -1,21 +0,0 @@
|
|||
import React from "react";
|
||||
import { Page } from "@patternfly/react-core";
|
||||
import type { Meta } from "@storybook/react";
|
||||
|
||||
import { MockAdminClient } from "./MockAdminClient";
|
||||
import { RealmRoleTabs } from "../realm-roles/RealmRoleTabs";
|
||||
|
||||
export default {
|
||||
title: "New role form",
|
||||
component: RealmRoleTabs,
|
||||
} as Meta;
|
||||
|
||||
export const View = () => {
|
||||
return (
|
||||
<Page>
|
||||
<MockAdminClient>
|
||||
<RealmRoleTabs />
|
||||
</MockAdminClient>
|
||||
</Page>
|
||||
);
|
||||
};
|
|
@ -1,39 +0,0 @@
|
|||
import React from "react";
|
||||
import type { Meta } from "@storybook/react";
|
||||
import { Page } from "@patternfly/react-core";
|
||||
import type { ServerInfoRepresentation } from "keycloak-admin/lib/defs/serverInfoRepesentation";
|
||||
|
||||
import serverInfo from "../context/server-info/__tests__/mock.json";
|
||||
import roles from "../realm-roles/__tests__/mock-roles.json";
|
||||
import clients from "../clients/__tests__/mock-clients.json";
|
||||
import { ServerInfoContext } from "../context/server-info/ServerInfoProvider";
|
||||
|
||||
import { RoleMappingForm } from "../client-scopes/add/RoleMappingForm";
|
||||
import { MockAdminClient } from "./MockAdminClient";
|
||||
|
||||
export default {
|
||||
title: "Role Mapping Form",
|
||||
component: RoleMappingForm,
|
||||
} as Meta;
|
||||
|
||||
export const RoleMappingFormExample = () => (
|
||||
<ServerInfoContext.Provider
|
||||
value={serverInfo as unknown as ServerInfoRepresentation}
|
||||
>
|
||||
<MockAdminClient
|
||||
mock={{
|
||||
roles: {
|
||||
find: () => roles,
|
||||
},
|
||||
clients: {
|
||||
find: () => clients,
|
||||
listRoles: () => roles,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Page>
|
||||
<RoleMappingForm />
|
||||
</Page>
|
||||
</MockAdminClient>
|
||||
</ServerInfoContext.Provider>
|
||||
);
|
|
@ -1,18 +0,0 @@
|
|||
import React from "react";
|
||||
import type { Meta } from "@storybook/react";
|
||||
import { ScrollForm } from "../components/scroll-form/ScrollForm";
|
||||
|
||||
export default {
|
||||
title: "Scroll spy scroll form",
|
||||
component: ScrollForm,
|
||||
} as Meta;
|
||||
|
||||
export const View = () => {
|
||||
return (
|
||||
<ScrollForm sections={["Revocation", "Clustering", "Fine grain stuff"]}>
|
||||
<div style={{ height: "2400px" }}>One</div>
|
||||
<div style={{ height: "2400px" }}>Two</div>
|
||||
<div style={{ height: "2400px" }}>fine grain</div>
|
||||
</ScrollForm>
|
||||
);
|
||||
};
|
|
@ -1,67 +0,0 @@
|
|||
import React from "react";
|
||||
import {
|
||||
Nav,
|
||||
NavItem,
|
||||
NavList,
|
||||
PageSidebar,
|
||||
Page,
|
||||
} from "@patternfly/react-core";
|
||||
import type { Meta } from "@storybook/react";
|
||||
|
||||
import { RealmSelector } from "../components/realm-selector/RealmSelector";
|
||||
import { RealmContext } from "../context/realm-context/RealmContext";
|
||||
import { HashRouter } from "react-router-dom";
|
||||
|
||||
export default {
|
||||
title: "Header",
|
||||
component: RealmSelector,
|
||||
} as Meta;
|
||||
|
||||
export const Header = () => {
|
||||
return (
|
||||
<HashRouter>
|
||||
<RealmContext.Provider
|
||||
value={{
|
||||
realm: "master",
|
||||
setRealm: () => {},
|
||||
realms: [
|
||||
{ id: "master", realm: "Master" },
|
||||
{ id: "photoz", realm: "Photoz" },
|
||||
],
|
||||
refresh: () => Promise.resolve(),
|
||||
}}
|
||||
>
|
||||
<Page
|
||||
sidebar={
|
||||
<PageSidebar
|
||||
nav={
|
||||
<Nav>
|
||||
<NavList>
|
||||
<RealmSelector />
|
||||
<NavItem id="default-link1" to="#default-link1" itemId={0}>
|
||||
Link 1
|
||||
</NavItem>
|
||||
<NavItem
|
||||
id="default-link2"
|
||||
to="#default-link2"
|
||||
itemId={1}
|
||||
isActive
|
||||
>
|
||||
Current link
|
||||
</NavItem>
|
||||
<NavItem id="default-link3" to="#default-link3" itemId={2}>
|
||||
Link 3
|
||||
</NavItem>
|
||||
<NavItem id="default-link4" to="#default-link4" itemId={3}>
|
||||
Link 4
|
||||
</NavItem>
|
||||
</NavList>
|
||||
</Nav>
|
||||
}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</RealmContext.Provider>
|
||||
</HashRouter>
|
||||
);
|
||||
};
|
|
@ -1,22 +0,0 @@
|
|||
import React from "react";
|
||||
import type { Meta } from "@storybook/react";
|
||||
import { Page } from "@patternfly/react-core";
|
||||
import { UserFederationKerberosSettings } from "../user-federation/UserFederationKerberosSettings";
|
||||
import { MockAdminClient } from "./MockAdminClient";
|
||||
|
||||
export default {
|
||||
title: "User Federation Kerberos Settings Tab",
|
||||
component: UserFederationKerberosSettings,
|
||||
} as Meta;
|
||||
|
||||
export const view = () => {
|
||||
return (
|
||||
<Page>
|
||||
<MockAdminClient
|
||||
mock={{ components: { findOne: () => Promise.resolve({}) } }}
|
||||
>
|
||||
<UserFederationKerberosSettings />
|
||||
</MockAdminClient>
|
||||
</Page>
|
||||
);
|
||||
};
|
|
@ -1,22 +0,0 @@
|
|||
import React from "react";
|
||||
import type { Meta } from "@storybook/react";
|
||||
import { Page, PageSection } from "@patternfly/react-core";
|
||||
import { UserFederationKerberosWizard } from "../user-federation/UserFederationKerberosWizard";
|
||||
import { MockAdminClient } from "./MockAdminClient";
|
||||
|
||||
export default {
|
||||
title: "User Federation Kerberos Wizard",
|
||||
component: UserFederationKerberosWizard,
|
||||
} as Meta;
|
||||
|
||||
export const view = () => {
|
||||
return (
|
||||
<Page style={{ height: "80vh" }}>
|
||||
<PageSection isFilled>
|
||||
<MockAdminClient>
|
||||
<UserFederationKerberosWizard />
|
||||
</MockAdminClient>
|
||||
</PageSection>
|
||||
</Page>
|
||||
);
|
||||
};
|
|
@ -1,22 +0,0 @@
|
|||
import React from "react";
|
||||
import type { Meta } from "@storybook/react";
|
||||
import { Page } from "@patternfly/react-core";
|
||||
import { UserFederationLdapSettings } from "../user-federation/UserFederationLdapSettings";
|
||||
import { MockAdminClient } from "./MockAdminClient";
|
||||
|
||||
export default {
|
||||
title: "User Federation LDAP Settings Tab",
|
||||
component: UserFederationLdapSettings,
|
||||
} as Meta;
|
||||
|
||||
export const view = () => {
|
||||
return (
|
||||
<Page>
|
||||
<MockAdminClient
|
||||
mock={{ components: { findOne: () => Promise.resolve({}) } }}
|
||||
>
|
||||
<UserFederationLdapSettings />
|
||||
</MockAdminClient>
|
||||
</Page>
|
||||
);
|
||||
};
|
|
@ -1,20 +0,0 @@
|
|||
import React from "react";
|
||||
import type { Meta } from "@storybook/react";
|
||||
import { Page } from "@patternfly/react-core";
|
||||
import { UserFederationLdapWizard } from "../user-federation/UserFederationLdapWizard";
|
||||
import { MockAdminClient } from "./MockAdminClient";
|
||||
|
||||
export default {
|
||||
title: "User Federation LDAP Wizard",
|
||||
component: UserFederationLdapWizard,
|
||||
} as Meta;
|
||||
|
||||
export const view = () => {
|
||||
return (
|
||||
<Page style={{ height: "80vh" }}>
|
||||
<MockAdminClient>
|
||||
<UserFederationLdapWizard />
|
||||
</MockAdminClient>{" "}
|
||||
</Page>
|
||||
);
|
||||
};
|
|
@ -1,43 +0,0 @@
|
|||
import React from "react";
|
||||
import type { Meta, Story } from "@storybook/react";
|
||||
import { DropdownItem, Page } from "@patternfly/react-core";
|
||||
import {
|
||||
ViewHeader,
|
||||
ViewHeaderProps,
|
||||
} from "../components/view-header/ViewHeader";
|
||||
|
||||
export default {
|
||||
title: "View Header",
|
||||
component: ViewHeader,
|
||||
} as Meta;
|
||||
|
||||
const Template: Story<ViewHeaderProps> = (args) => (
|
||||
<Page>
|
||||
<ViewHeader {...args} />
|
||||
</Page>
|
||||
);
|
||||
|
||||
export const Extended = Template.bind({});
|
||||
Extended.args = {
|
||||
titleKey: "This is the title",
|
||||
badge: "badge",
|
||||
subKey: "This is the description.",
|
||||
subKeyLinkProps: {
|
||||
title: "More information",
|
||||
href: "http://google.com",
|
||||
},
|
||||
dropdownItems: [
|
||||
<DropdownItem key="first" value="first-item" onClick={() => {}}>
|
||||
First item
|
||||
</DropdownItem>,
|
||||
<DropdownItem key="second" value="second-item" onClick={() => {}}>
|
||||
Second item
|
||||
</DropdownItem>,
|
||||
],
|
||||
};
|
||||
|
||||
export const Simple = Template.bind({});
|
||||
Simple.args = {
|
||||
titleKey: "Title simple",
|
||||
subKey: "Some lengthy description about what this is about.",
|
||||
};
|
|
@ -1,22 +0,0 @@
|
|||
import React from "react";
|
||||
import type { Meta, Story } from "@storybook/react";
|
||||
import {
|
||||
WizardSectionHeader,
|
||||
WizardSectionHeaderProps,
|
||||
} from "../components/wizard-section-header/WizardSectionHeader";
|
||||
|
||||
export default {
|
||||
title: "Wizard Section Header",
|
||||
component: WizardSectionHeader,
|
||||
} as Meta;
|
||||
|
||||
const Template: Story<WizardSectionHeaderProps> = (args) => (
|
||||
<WizardSectionHeader {...args} />
|
||||
);
|
||||
|
||||
export const TitleAndDescription = Template.bind({});
|
||||
TitleAndDescription.args = {
|
||||
title: "Section title",
|
||||
description: "This is a description of the section",
|
||||
showDescription: true,
|
||||
};
|
|
@ -1,6 +0,0 @@
|
|||
export default {
|
||||
storybook: {
|
||||
helpPlaceholder:
|
||||
"Sometimes you need some help and it's nice when the app does that",
|
||||
},
|
||||
};
|
Loading…
Reference in a new issue