summaryrefslogtreecommitdiff
path: root/packages/taler-wallet-webextension
diff options
context:
space:
mode:
authorSebastian <sebasjm@gmail.com>2021-07-09 23:15:49 -0300
committerSebastian <sebasjm@gmail.com>2021-07-09 23:15:53 -0300
commitd29499b80a992a0d107327c0dfbf31bb2d2ba6f7 (patch)
tree256d181c9f3c3795841c71ef6400f4dce6a738f4 /packages/taler-wallet-webextension
parent5881d957caf3bd7d3311cae7420ceb1e3fa5a9e1 (diff)
downloadwallet-core-d29499b80a992a0d107327c0dfbf31bb2d2ba6f7.tar.gz
wallet-core-d29499b80a992a0d107327c0dfbf31bb2d2ba6f7.tar.bz2
wallet-core-d29499b80a992a0d107327c0dfbf31bb2d2ba6f7.zip
migration css to linaria
Diffstat (limited to 'packages/taler-wallet-webextension')
-rw-r--r--packages/taler-wallet-webextension/.gitignore1
-rw-r--r--packages/taler-wallet-webextension/.storybook/.babelrc2
-rw-r--r--packages/taler-wallet-webextension/.storybook/main.js27
-rw-r--r--packages/taler-wallet-webextension/package.json11
-rw-r--r--packages/taler-wallet-webextension/rollup.config.js18
-rw-r--r--packages/taler-wallet-webextension/src/components/styled/index.tsx135
-rw-r--r--packages/taler-wallet-webextension/src/popup/Backup.stories.tsx32
-rw-r--r--packages/taler-wallet-webextension/src/popup/BackupPage.tsx134
-rw-r--r--packages/taler-wallet-webextension/src/popup/ProviderDetailPage.tsx10
-rw-r--r--packages/taler-wallet-webextension/static/popup.html1
10 files changed, 273 insertions, 98 deletions
diff --git a/packages/taler-wallet-webextension/.gitignore b/packages/taler-wallet-webextension/.gitignore
index 27d7e9786..0974a77aa 100644
--- a/packages/taler-wallet-webextension/.gitignore
+++ b/packages/taler-wallet-webextension/.gitignore
@@ -1,2 +1,3 @@
extension/
/storybook-static/
+/.linaria-cache/
diff --git a/packages/taler-wallet-webextension/.storybook/.babelrc b/packages/taler-wallet-webextension/.storybook/.babelrc
index 39829d509..4476798e2 100644
--- a/packages/taler-wallet-webextension/.storybook/.babelrc
+++ b/packages/taler-wallet-webextension/.storybook/.babelrc
@@ -21,6 +21,6 @@
{
//FIXME: check if we can remove this preset and just use default storybook presets
"presets": [
- "preact-cli/babel"
+ "preact-cli/babel",
]
} \ No newline at end of file
diff --git a/packages/taler-wallet-webextension/.storybook/main.js b/packages/taler-wallet-webextension/.storybook/main.js
index 38ca14b64..cd58d4d1d 100644
--- a/packages/taler-wallet-webextension/.storybook/main.js
+++ b/packages/taler-wallet-webextension/.storybook/main.js
@@ -40,8 +40,9 @@ module.exports = {
'@babel/preset-react', {
runtime: 'automatic',
},
- 'preset-react-jsx-transform'
+ 'preset-react-jsx-transform'
],
+ "@linaria",
],
}),
webpackFinal: (config) => {
@@ -51,6 +52,30 @@ module.exports = {
react: "preact/compat",
"react-dom": "preact/compat",
};
+
+ // we need to add @linaria loader AFTER the babel-loader
+ // https://github.com/callstack/linaria/blob/master/docs/BUNDLERS_INTEGRATION.md#webpack
+ config.module.rules[0] = {
+ ...(config.module.rules[0]),
+ loader: undefined, // Disable the predefined babel-loader on the rule
+ use: [
+ {
+ ...(config.module.rules[0].use[0]),
+ loader: 'babel-loader',
+ },
+ {
+ loader: '@linaria/webpack-loader',
+ options: {
+ sourceMap: true, //always true since this is dev
+ babelOptions: {
+ presets: config.module.rules[0].use[0].options.presets,
+ }
+ // Pass the current babel options to linaria's babel instance
+ }
+ }
+ ]
+ };
+
return config;
},
}
diff --git a/packages/taler-wallet-webextension/package.json b/packages/taler-wallet-webextension/package.json
index 1c6795234..a5908af25 100644
--- a/packages/taler-wallet-webextension/package.json
+++ b/packages/taler-wallet-webextension/package.json
@@ -27,6 +27,15 @@
"@babel/core": "^7.14.0",
"@babel/plugin-transform-react-jsx-source": "^7.12.13",
"@babel/preset-typescript": "^7.13.0",
+
+ "@linaria/babel-preset": "^3.0.0-beta.4",
+ "@linaria/core": "^3.0.0-beta.4",
+ "@linaria/react": "^3.0.0-beta.7",
+ "@linaria/rollup": "^3.0.0-beta.7",
+ "@linaria/shaker": "^3.0.0-beta.7",
+ "@linaria/webpack-loader": "^3.0.0-beta.7",
+ "@rollup/plugin-alias": "^3.1.2",
+
"@rollup/plugin-commonjs": "^17.0.0",
"@rollup/plugin-image": "^2.0.6",
"@rollup/plugin-json": "^4.1.0",
@@ -41,6 +50,7 @@
"@types/jest": "^26.0.23",
"@types/node": "^14.14.22",
"ava": "3.15.0",
+ "babel-loader": "^8.2.2",
"babel-plugin-transform-react-jsx": "^6.24.1",
"enzyme": "^3.11.0",
"enzyme-adapter-preact-pure": "^3.1.0",
@@ -51,6 +61,7 @@
"preact-render-to-string": "^5.1.19",
"rimraf": "^3.0.2",
"rollup": "^2.37.1",
+ "rollup-plugin-css-only": "^3.1.0",
"rollup-plugin-ignore": "^1.0.9",
"rollup-plugin-sourcemaps": "^0.6.3",
"rollup-plugin-terser": "^7.0.2",
diff --git a/packages/taler-wallet-webextension/rollup.config.js b/packages/taler-wallet-webextension/rollup.config.js
index 80b4f6eec..7e7ec0032 100644
--- a/packages/taler-wallet-webextension/rollup.config.js
+++ b/packages/taler-wallet-webextension/rollup.config.js
@@ -6,8 +6,18 @@ import builtins from "builtin-modules";
import replace from "@rollup/plugin-replace";
import ignore from "rollup-plugin-ignore"
import image from '@rollup/plugin-image';
+import linaria from '@linaria/rollup';
+import css from 'rollup-plugin-css-only';
+import alias from '@rollup/plugin-alias';
const makePlugins = () => [
+ alias({
+ entries: [
+ { find: 'react', replacement: 'preact/compat' },
+ { find: 'react-dom', replacement: 'preact/compat' }
+ ]
+ }),
+
ignore(["module", "os"]),
nodeResolve({
browser: true,
@@ -31,6 +41,14 @@ const makePlugins = () => [
json(),
image(),
+
+ linaria({
+ sourceMap: process.env.NODE_ENV !== 'production',
+ }),
+ css({
+ output: 'styles.css',
+ }),
+
];
diff --git a/packages/taler-wallet-webextension/src/components/styled/index.tsx b/packages/taler-wallet-webextension/src/components/styled/index.tsx
new file mode 100644
index 000000000..6e7e736a5
--- /dev/null
+++ b/packages/taler-wallet-webextension/src/components/styled/index.tsx
@@ -0,0 +1,135 @@
+// import { FunctionalComponent, JSX } from 'preact';
+// import styled from './preact-styled'
+
+// import { css } from '@linaria/core';
+import { styled } from '@linaria/react';
+
+export const PopupBox = styled.div`
+ height: calc(320px - 34px - 16px);
+ display: flex;
+ flex-direction: column;
+
+ & > section {
+ overflow: auto;
+ }
+
+ & > footer {
+ padding-top: 5px;
+ flex-direction: row;
+ justify-content: flex-end;
+ display: flex;
+ & > button {
+ margin-left: 5px;
+ }
+ }
+`
+
+const Button = styled.button`
+ display: inline-block;
+ zoom: 1;
+ line-height: normal;
+ white-space: nowrap;
+ vertical-align: middle;
+ text-align: center;
+ cursor: pointer;
+ user-select: none;
+ box-sizing: border-box;
+
+ font-family: inherit;
+ font-size: 100%;
+ padding: 0.5em 1em;
+ color: #444; /* rgba not supported (IE 8) */
+ color: rgba(0, 0, 0, 0.8); /* rgba supported */
+ border: 1px solid #999; /*IE 6/7/8*/
+ border: none rgba(0, 0, 0, 0); /*IE9 + everything else*/
+ background-color: '#e6e6e6';
+ text-decoration: none;
+ border-radius: 2px;
+
+ :focus {
+ outline: 0;
+ }
+
+ [disabled] {
+ border: none;
+ background-image: none;
+ /* csslint ignore:start */
+ filter: alpha(opacity=40);
+ /* csslint ignore:end */
+ opacity: 0.4;
+ cursor: not-allowed;
+ box-shadow: none;
+ pointer-events: none;
+ }
+
+ :hover {
+ filter: alpha(opacity=90);
+ background-image: linear-gradient(
+ transparent,
+ rgba(0, 0, 0, 0.05) 40%,
+ rgba(0, 0, 0, 0.1)
+ );
+ }
+`;
+
+const ButtonVariant = styled(Button)`
+ color: white;
+ border-radius: 4px;
+ text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
+`
+
+export const ButtonPrimary = styled(ButtonVariant)`
+ background-color: rgb(66, 184, 221);
+`
+
+export const ButtonSuccess = styled(ButtonVariant)`
+ background-color: rgb(28, 184, 65);
+`
+
+export const ButtonWarning = styled(ButtonVariant)`
+ background-color: rgb(223, 117, 20);
+`
+
+export const ButtonDestructive = styled(ButtonVariant)`
+ background-color: rgb(202, 60, 60);
+`
+
+export const BoldLight = styled.div`
+color: gray;
+font-weight: bold;
+`
+export const Centered = styled.div`
+ text-align: center;
+ & > :not(:first-child) {
+ margin-top: 15px;
+ }
+`
+export const Row = styled.div`
+ display: flex;
+ border: 1px solid gray;
+ border-radius: 0.5em;
+ margin: 0.5em 0;
+ justify-content: space-between;
+ padding: 0.5em;
+`
+
+export const SmallText = styled.div`
+ font-size: small;
+ margin-top: 0.5em;
+`
+
+export const SmallTextLight = styled(SmallText)`
+ color: gray;
+`
+
+export const CenteredText = styled.div`
+ white-space: nowrap;
+ text-align: center;
+`
+
+export const CenteredTextBold = styled(CenteredText)`
+ white-space: nowrap;
+ text-align: center;
+ font-weight: bold;
+ color: ${((props: any): any => String(props.color) as any) as any};
+`
diff --git a/packages/taler-wallet-webextension/src/popup/Backup.stories.tsx b/packages/taler-wallet-webextension/src/popup/Backup.stories.tsx
index 2d28a6ddc..ed03f2087 100644
--- a/packages/taler-wallet-webextension/src/popup/Backup.stories.tsx
+++ b/packages/taler-wallet-webextension/src/popup/Backup.stories.tsx
@@ -62,7 +62,7 @@ export const LotOfProviders = createExample(TestedComponent, {
"storageLimitInMegabytes": 16,
"supportedProtocolVersion": "0.0"
}
- },{
+ }, {
"active": true,
"syncProviderBaseUrl": "http://sync.taler:9967/",
"lastSuccessfulBackupTimestamp": {
@@ -82,43 +82,57 @@ export const LotOfProviders = createExample(TestedComponent, {
"storageLimitInMegabytes": 16,
"supportedProtocolVersion": "0.0"
}
- },{
+ }, {
"active": false,
"syncProviderBaseUrl": "http://sync.demo.taler.net/",
"paymentProposalIds": [],
"paymentStatus": {
- "type": ProviderPaymentType.Unpaid,
+ "type": ProviderPaymentType.Pending,
},
"terms": {
"annualFee": "KUDOS:0.1",
"storageLimitInMegabytes": 16,
"supportedProtocolVersion": "0.0"
}
- },{
+ }, {
"active": false,
"syncProviderBaseUrl": "http://sync.demo.taler.net/",
"paymentProposalIds": [],
"paymentStatus": {
- "type": ProviderPaymentType.Unpaid,
+ "type": ProviderPaymentType.InsufficientBalance,
},
"terms": {
"annualFee": "KUDOS:0.1",
"storageLimitInMegabytes": 16,
"supportedProtocolVersion": "0.0"
}
- },{
+ }, {
"active": false,
"syncProviderBaseUrl": "http://sync.demo.taler.net/",
"paymentProposalIds": [],
"paymentStatus": {
- "type": ProviderPaymentType.Unpaid,
+ "type": ProviderPaymentType.TermsChanged,
+ newTerms: {
+ annualFee: 'USD:2',
+ storageLimitInMegabytes: 8,
+ supportedProtocolVersion: '2',
+ },
+ oldTerms: {
+ annualFee: 'USD:1',
+ storageLimitInMegabytes: 16,
+ supportedProtocolVersion: '1',
+
+ },
+ paidUntil: {
+ t_ms: 'never'
+ }
},
"terms": {
"annualFee": "KUDOS:0.1",
"storageLimitInMegabytes": 16,
"supportedProtocolVersion": "0.0"
}
- },{
+ }, {
"active": false,
"syncProviderBaseUrl": "http://sync.demo.taler.net/",
"paymentProposalIds": [],
@@ -130,7 +144,7 @@ export const LotOfProviders = createExample(TestedComponent, {
"storageLimitInMegabytes": 16,
"supportedProtocolVersion": "0.0"
}
- },{
+ }, {
"active": false,
"syncProviderBaseUrl": "http://sync.demo.taler.net/",
"paymentProposalIds": [],
diff --git a/packages/taler-wallet-webextension/src/popup/BackupPage.tsx b/packages/taler-wallet-webextension/src/popup/BackupPage.tsx
index d7a2d863c..6e60acc74 100644
--- a/packages/taler-wallet-webextension/src/popup/BackupPage.tsx
+++ b/packages/taler-wallet-webextension/src/popup/BackupPage.tsx
@@ -16,9 +16,14 @@
import { i18n, Timestamp } from "@gnu-taler/taler-util";
-import { ProviderInfo } from "@gnu-taler/taler-wallet-core";
+import { ProviderInfo, ProviderPaymentStatus } from "@gnu-taler/taler-wallet-core";
import { differenceInMonths, formatDuration, intervalToDuration } from "date-fns";
-import { Fragment, JSX, VNode } from "preact";
+import { FunctionalComponent, Fragment, JSX, VNode, AnyComponent } from "preact";
+import {
+ BoldLight, ButtonPrimary, ButtonSuccess, Centered,
+ CenteredText, CenteredTextBold, PopupBox, Row,
+ SmallText, SmallTextLight
+} from "../components/styled";
import { useBackupStatus } from "../hooks/useBackupStatus";
import { Pages } from "./popup";
@@ -31,7 +36,7 @@ export function BackupPage({ onAddProvider }: Props): VNode {
if (!status) {
return <div>Loading...</div>
}
- return <BackupView providers={status.providers} onAddProvider={onAddProvider} onSyncAll={status.sync}/>;
+ return <BackupView providers={status.providers} onAddProvider={onAddProvider} onSyncAll={status.sync} />;
}
export interface ViewProps {
@@ -42,44 +47,35 @@ export interface ViewProps {
export function BackupView({ providers, onAddProvider, onSyncAll }: ViewProps): VNode {
return (
- <div style={{ height: 'calc(320px - 34px - 16px)', overflow: 'auto' }}>
- <div style={{ display: 'flex', flexDirection: 'column' }}>
- <section style={{ flex: '1 0 auto', height: 'calc(320px - 34px - 34px - 16px)', overflow: 'auto' }}>
-
- {!!providers.length && <div>
- {providers.map((provider) => {
- return <BackupLayout
- status={provider.paymentStatus}
- timestamp={provider.lastSuccessfulBackupTimestamp}
- id={provider.syncProviderBaseUrl}
- active={provider.active}
- title={provider.syncProviderBaseUrl}
- />
- })}
- </div>}
- {!providers.length && <div style={{ color: 'gray', fontWeight: 'bold', marginTop: 80, textAlign: 'center' }}>
- <div>No backup providers configured</div>
- <button class="pure-button button-success" style={{ marginTop: 15 }} onClick={onAddProvider}><i18n.Translate>Add provider</i18n.Translate></button>
- </div>}
-
- </section>
- {!!providers.length && <footer style={{ marginTop: 'auto', display: 'flex', flexShrink: 0 }}>
- <div style={{ width: '100%', flexDirection: 'row', justifyContent: 'flex-end', display: 'flex' }}>
- <button class="pure-button button-secondary" style={{ marginLeft: 5 }} onClick={onSyncAll}>{
- providers.length > 1 ?
- <i18n.Translate>Sync all backups</i18n.Translate> :
- <i18n.Translate>Sync now</i18n.Translate>
- }</button>
- <button class="pure-button button-success" style={{ marginLeft: 5 }} onClick={onAddProvider}><i18n.Translate>Add provider</i18n.Translate></button>
- </div>
- </footer>}
- </div>
- </div>
+ <PopupBox style={{ justifyContent: !providers.length ? 'center' : 'space-between' }}>
+ <section>
+ {providers.map((provider) => <BackupLayout
+ status={provider.paymentStatus}
+ timestamp={provider.lastSuccessfulBackupTimestamp}
+ id={provider.syncProviderBaseUrl}
+ active={provider.active}
+ title={provider.syncProviderBaseUrl}
+ />
+ )}
+ {!providers.length && <Centered>
+ <BoldLight>No backup providers configured</BoldLight>
+ <ButtonSuccess onClick={onAddProvider}><i18n.Translate>Add provider</i18n.Translate></ButtonSuccess>
+ </Centered>}
+ </section>
+ {!!providers.length && <footer>
+ <ButtonPrimary onClick={onSyncAll}>{
+ providers.length > 1 ?
+ <i18n.Translate>Sync all backups</i18n.Translate> :
+ <i18n.Translate>Sync now</i18n.Translate>
+ }</ButtonPrimary>
+ <ButtonSuccess onClick={onAddProvider}>Add provider</ButtonSuccess>
+ </footer>}
+ </PopupBox>
)
}
interface TransactionLayoutProps {
- status: any;
+ status: ProviderPaymentStatus;
timestamp?: Timestamp;
title: string;
id: string;
@@ -92,55 +88,33 @@ function BackupLayout(props: TransactionLayoutProps): JSX.Element {
dateStyle: "medium",
timeStyle: "short",
} as any);
+
+
return (
- <div
- style={{
- display: "flex",
- flexDirection: "row",
- border: "1px solid gray",
- borderRadius: "0.5em",
- margin: "0.5em 0",
- justifyContent: "space-between",
- padding: "0.5em",
- }}
- >
- <div
- style={{ display: "flex", flexDirection: "column", color: !props.active ? "gray" : undefined }}
- >
- <div style={{ }}>
- <a href={Pages.provider_detail.replace(':pid', encodeURIComponent(props.id))}><span>{props.title}</span></a>
- </div>
-
- {dateStr && <div style={{ fontSize: "small", marginTop: '0.5em' }}>Last synced: {dateStr}</div>}
- {!dateStr && <div style={{ fontSize: "small", color: 'gray' }}>Not synced</div>}
+ <Row>
+ <div style={{ color: !props.active ? "grey" : undefined }}>
+ <a href={Pages.provider_detail.replace(':pid', encodeURIComponent(props.id))}><span>{props.title}</span></a>
+
+ {dateStr && <SmallText>Last synced: {dateStr}</SmallText>}
+ {!dateStr && <SmallTextLight>Not synced</SmallTextLight>}
</div>
- <div style={{
- marginLeft: "auto",
- display: "flex",
- flexDirection: "column",
- alignItems: "center",
- alignSelf: "center"
- }}>
- <div style={{ display: 'flex', flexDirection: 'column' }}>
- {
- props.status?.type === 'paid' ?
- <Fragment>
- <div style={{ whiteSpace: 'nowrap', textAlign: 'center' }}>
- Expires in
- </div>
- <div style={{ whiteSpace: 'nowrap', textAlign: 'center', fontWeight: 'bold', color: colorByTimeToExpire(props.status.paidUntil) }}>
- {daysUntil(props.status.paidUntil)}
- </div>
- </Fragment>
- :
- 'unpaid'
- }
- </div>
+ <div>
+ {props.status?.type === 'paid' ?
+ <ExpirationText until={props.status.paidUntil} /> :
+ <div>{props.status.type}</div>
+ }
</div>
- </div>
+ </Row>
);
}
+function ExpirationText({ until }: { until: Timestamp }) {
+ return <Fragment>
+ <CenteredText> Expires in </CenteredText>
+ <CenteredTextBold {...({color:colorByTimeToExpire(until)})}> {daysUntil(until)} </CenteredTextBold>
+ </Fragment>
+}
+
function colorByTimeToExpire(d: Timestamp) {
if (d.t_ms === 'never') return 'rgb(28, 184, 65)'
const months = differenceInMonths(d.t_ms, new Date())
diff --git a/packages/taler-wallet-webextension/src/popup/ProviderDetailPage.tsx b/packages/taler-wallet-webextension/src/popup/ProviderDetailPage.tsx
index b7a6f847c..0d48ab070 100644
--- a/packages/taler-wallet-webextension/src/popup/ProviderDetailPage.tsx
+++ b/packages/taler-wallet-webextension/src/popup/ProviderDetailPage.tsx
@@ -15,15 +15,11 @@
*/
-import { BackupBackupProviderTerms, i18n, Timestamp } from "@gnu-taler/taler-util";
+import { i18n, Timestamp } from "@gnu-taler/taler-util";
import { ProviderInfo, ProviderPaymentStatus, ProviderPaymentType } from "@gnu-taler/taler-wallet-core";
-import { ContractTermsUtil } from "@gnu-taler/taler-wallet-core/src/util/contractTerms";
-import { formatDuration, intervalToDuration, format } from "date-fns";
+import { format, formatDuration, intervalToDuration } from "date-fns";
import { Fragment, VNode } from "preact";
-import { useRef, useState } from "preact/hooks";
-import { useBackupStatus } from "../hooks/useBackupStatus";
-import { useProviderStatus } from "../hooks/useProviderStatus.js";
-import * as wxApi from "../wxApi";
+import { useProviderStatus } from "../hooks/useProviderStatus";
interface Props {
pid: string;
diff --git a/packages/taler-wallet-webextension/static/popup.html b/packages/taler-wallet-webextension/static/popup.html
index 9f6520a16..06e447924 100644
--- a/packages/taler-wallet-webextension/static/popup.html
+++ b/packages/taler-wallet-webextension/static/popup.html
@@ -4,6 +4,7 @@
<meta charset="utf-8" />
<link rel="stylesheet" type="text/css" href="/static/style/pure.css" />
<link rel="stylesheet" type="text/css" href="/static/style/popup.css" />
+ <link rel="stylesheet" type="text/css" href="/dist/styles.css" />
<link rel="icon" href="/static/img/icon.png" />
<script src="/dist/popupEntryPoint.js"></script>
</head>