add storybook

This commit is contained in:
Sebastian 2021-05-31 11:34:48 -03:00
parent 3688f7e4d4
commit c6c17a1c0a
No known key found for this signature in database
GPG Key ID: BE4FF68352439FC1
15 changed files with 5457 additions and 59 deletions

View File

@ -1 +1,2 @@
extension/
/storybook-static/

View File

@ -0,0 +1,22 @@
/*
This file is part of GNU Taler
(C) 2021 Taler Systems S.A.
GNU Taler is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 3, or (at your option) any later version.
GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
/**
*
* @author Sebastian Javier Marchano (sebasjm)
*/
{
}

View File

@ -0,0 +1,39 @@
/*
This file is part of GNU Taler
(C) 2021 Taler Systems S.A.
GNU Taler is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 3, or (at your option) any later version.
GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
/**
*
* @author Sebastian Javier Marchano (sebasjm)
*/
module.exports = {
"stories": [
"../lib/**/*.stories.js"
],
"addons": [
"@storybook/addon-a11y",
"@storybook/addon-essentials" //docs, control, actions, viewpot, toolbar, background
],
// webpackFinal: async (config, { configType }) => {
// // `configType` has a value of 'DEVELOPMENT' or 'PRODUCTION'
// // You can change the configuration based on that.
// // 'PRODUCTION' is used when building the static version of storybook.
// // Make whatever fine-grained changes you need
// // Return the altered config
// return config;
// },
}

View File

@ -0,0 +1,54 @@
/*
This file is part of GNU Taler
(C) 2021 Taler Systems S.A.
GNU Taler is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 3, or (at your option) any later version.
GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
// import "../src/scss/main.scss"
// import { ConfigContextProvider } from '../src/context/config'
// import { TranslationProvider } from '../src/context/translation'
const mockConfig = {
backendURL: 'http://demo.taler.net',
currency: 'KUDOS'
}
// export const parameters = {
// controls: { expanded: true },
// actions: { argTypesRegex: "^on[A-Z].*" },
// }
// export const globalTypes = {
// locale: {
// name: 'Locale',
// description: 'Internationalization locale',
// defaultValue: 'en',
// toolbar: {
// icon: 'globe',
// items: [
// { value: 'en', right: '🇺🇸', title: 'English' },
// { value: 'es', right: '🇪🇸', title: 'Spanish' },
// ],
// },
// },
// };
// export const decorators = [
// (Story, { globals }) => {
// return <TranslationProvider initial={globals.locale}>
// <Story />
// </TranslationProvider>
// },
// (Story) => <ConfigContextProvider value={mockConfig}> <Story /> </ConfigContextProvider>
// ];

View File

@ -11,6 +11,8 @@
"clean": "rimraf dist lib tsconfig.tsbuildinfo",
"test": "jest ./tests",
"compile": "tsc && rollup -c",
"build-storybook": "build-storybook",
"storybook": "start-storybook -p 6006",
"watch": "tsc --watch & rollup -w -c"
},
"dependencies": {
@ -28,6 +30,9 @@
"@rollup/plugin-json": "^4.1.0",
"@rollup/plugin-node-resolve": "^11.1.0",
"@rollup/plugin-replace": "^2.3.4",
"@storybook/addon-a11y": "^6.2.9",
"@storybook/addon-essentials": "^6.2.9",
"@storybook/preact": "^6.2.9",
"@testing-library/preact": "^2.0.1",
"@types/chrome": "^0.0.128",
"@types/history": "^4.7.8",

View File

@ -72,6 +72,11 @@ interface TranslateProps {
* Props to give to the wrapped component.
*/
wrapProps?: any;
/**
* Translated elements
*/
children: ComponentChildren;
}
function getTranslatedChildren(
@ -117,16 +122,14 @@ function getTranslatedChildren(
* </Translate>
* ```
*/
export class Translate extends Component<TranslateProps, any> {
render() {
const s = stringifyChildren(this.props.children);
export function Translate({children, wrap, wrapProps}: TranslateProps): VNode {
const s = stringifyChildren(children);
const translation: string = i18nCore.jed.ngettext(s, s, 1);
const result = getTranslatedChildren(translation, this.props.children);
if (!this.props.wrap) {
const result = getTranslatedChildren(translation, children);
if (!wrap) {
return <div>{result}</div>;
}
return h(this.props.wrap, this.props.wrapProps, result);
}
return h(wrap, wrapProps, result);
}
/**

View File

@ -222,6 +222,9 @@ export function TalerPayDialog({ talerPayUri }: Props): JSX.Element {
);
}
/**
* @deprecated to be removed
*/
export function createPayPage(): JSX.Element {
const url = new URL(document.location.href);
const talerPayUri = url.searchParams.get("talerPayUri");

View File

@ -88,6 +88,9 @@ export function RefundStatusView({ talerRefundUri }: Props): JSX.Element {
);
}
/**
* @deprecated to be removed
*/
export function createRefundPage(): JSX.Element {
const url = new URL(document.location.href);

View File

@ -89,6 +89,9 @@ class ResetNotification extends Component<any, State> {
}
}
/**
* @deprecated to be removed
*/
export function createResetRequiredPage(): JSX.Element {
return <ResetNotification />;
}

View File

@ -96,6 +96,9 @@ export function TalerTipDialog({ talerTipUri }: Props): JSX.Element {
}
}
/**
* @deprecated to be removed
*/
export function createTipPage(): JSX.Element {
const url = new URL(document.location.href);
const talerTipUri = url.searchParams.get("talerTipUri");

View File

@ -194,6 +194,9 @@ export function Welcome(): JSX.Element {
);
}
/**
* @deprecated to be removed
*/
export function createWelcomePage(): JSX.Element {
return <Welcome />;
}

View File

@ -0,0 +1,66 @@
/*
This file is part of GNU Taler
(C) 2021 Taler Systems S.A.
GNU Taler is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 3, or (at your option) any later version.
GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
/**
*
* @author Sebastian Javier Marchano (sebasjm)
*/
import { h } from 'preact';
import { View, ViewProps } from './withdraw';
export default {
title: 'wallet/withdraw',
component: View,
argTypes: {
},
};
export const WithoutURI = (a: any) => <View {...a} />;
WithoutURI.args = {
} as ViewProps
export const WithoutDetails = (a: any) => <View {...a} />;
WithoutDetails.args = {
talerWithdrawUri: 'http://something'
} as ViewProps
export const Cancelled = (a: any) => <View {...a} />;
Cancelled.args = {
talerWithdrawUri: 'http://something',
details: {
amount: 'USD:2',
},
cancelled: true
} as ViewProps
export const CompleteWithExchange = (a: any) => <View {...a} />;
CompleteWithExchange.args = {
talerWithdrawUri: 'http://something',
details: {
amount: 'USD:2',
},
selectedExchange: 'Some exchange'
} as ViewProps
export const CompleteWithoutExchange = (a: any) => <View {...a} />;
CompleteWithoutExchange.args = {
talerWithdrawUri: 'http://something',
details: {
amount: 'USD:2',
},
} as ViewProps

View File

@ -37,34 +37,18 @@ import { JSX } from "preact/jsx-runtime";
interface Props {
talerWithdrawUri?: string;
}
export function WithdrawalDialog({ talerWithdrawUri }: Props): JSX.Element {
const [details, setDetails] = useState<WithdrawUriInfoResponse | undefined>(undefined);
const [selectedExchange, setSelectedExchange] = useState<
string | undefined
>(undefined);
const [cancelled, setCancelled] = useState(false);
const [selecting, setSelecting] = useState(false);
const [errMsg, setErrMsg] = useState<string | undefined>("");
const [updateCounter, setUpdateCounter] = useState(1);
useEffect(() => {
return onUpdateNotification(() => {
setUpdateCounter(updateCounter + 1);
});
}, []);
useEffect(() => {
if (!talerWithdrawUri) return
const fetchData = async (): Promise<void> => {
const res = await getWithdrawalDetailsForUri({ talerWithdrawUri });
setDetails(res);
if (res.defaultExchangeBaseUrl) {
setSelectedExchange(res.defaultExchangeBaseUrl);
}
};
fetchData();
}, [selectedExchange, errMsg, selecting, talerWithdrawUri, updateCounter]);
export interface ViewProps {
talerWithdrawUri?: string;
details?: WithdrawUriInfoResponse;
cancelled?: boolean;
selectedExchange?: string;
accept: () => Promise<void>;
setCancelled: (b: boolean) => void;
setSelecting: (b: boolean) => void;
};
export function View({ talerWithdrawUri, details, cancelled, selectedExchange, accept, setCancelled, setSelecting }: ViewProps) {
if (!talerWithdrawUri) {
return <span>missing withdraw uri</span>;
}
@ -77,18 +61,6 @@ export function WithdrawalDialog({ talerWithdrawUri }: Props): JSX.Element {
return <span>Withdraw operation has been cancelled.</span>;
}
const accept = async (): Promise<void> => {
if (!selectedExchange) {
throw Error("can't accept, no exchange selected");
}
console.log("accepting exchange", selectedExchange);
const res = await acceptWithdrawal(talerWithdrawUri, selectedExchange);
console.log("accept withdrawal response", res);
if (res.confirmTransferUrl) {
document.location.href = res.confirmTransferUrl;
}
};
return (
<div>
<h1>Digital Cash Withdrawal</h1>
@ -133,9 +105,61 @@ export function WithdrawalDialog({ talerWithdrawUri }: Props): JSX.Element {
</p>
</div>
</div>
);
)
}
export function WithdrawalDialog({ talerWithdrawUri }: Props): JSX.Element {
const [details, setDetails] = useState<WithdrawUriInfoResponse | undefined>(undefined);
const [selectedExchange, setSelectedExchange] = useState<
string | undefined
>(undefined);
const [cancelled, setCancelled] = useState(false);
const [selecting, setSelecting] = useState(false);
const [errMsg, setErrMsg] = useState<string | undefined>("");
const [updateCounter, setUpdateCounter] = useState(1);
useEffect(() => {
return onUpdateNotification(() => {
setUpdateCounter(updateCounter + 1);
});
}, []);
useEffect(() => {
if (!talerWithdrawUri) return
const fetchData = async (): Promise<void> => {
const res = await getWithdrawalDetailsForUri({ talerWithdrawUri });
setDetails(res);
if (res.defaultExchangeBaseUrl) {
setSelectedExchange(res.defaultExchangeBaseUrl);
}
};
fetchData();
}, [selectedExchange, errMsg, selecting, talerWithdrawUri, updateCounter]);
const accept = async (): Promise<void> => {
if (!talerWithdrawUri) return
if (!selectedExchange) {
throw Error("can't accept, no exchange selected");
}
console.log("accepting exchange", selectedExchange);
const res = await acceptWithdrawal(talerWithdrawUri, selectedExchange);
console.log("accept withdrawal response", res);
if (res.confirmTransferUrl) {
document.location.href = res.confirmTransferUrl;
}
};
return <View accept={accept}
setCancelled={setCancelled} setSelecting={setSelecting}
cancelled={cancelled} details={details} selectedExchange={selectedExchange}
talerWithdrawUri={talerWithdrawUri}
/>
}
/**
* @deprecated to be removed
*/
export function createWithdrawPage(): JSX.Element {
const url = new URL(document.location.href);
const talerWithdrawUri = url.searchParams.get("talerWithdrawUri");

View File

@ -18,7 +18,6 @@
import { internalSetStrings, str, Translate } from "../src/i18n";
import { render, configure } from "enzyme";
import Adapter from 'enzyme-adapter-preact-pure';
import { h } from "preact";
configure({ adapter: new Adapter() });
@ -49,7 +48,7 @@ test("str translation", (done) => {
const a = "a";
const b = "b";
expect(strAlias`str3 ${a} / ${b}`).toEqual("foo3 b ; a");
const r = render(<TranslateAlias>str1</TranslateAlias>);
const r = render(<Translate>str1</Translate>);
expect(r.text()).toEqual("foo1");
const r2 = render(

File diff suppressed because it is too large Load Diff