Parcourir la source

change action tabs to buttons

Klaudiusz Dembler il y a 4 ans
Parent
commit
4694a7e6f5

+ 6 - 0
pioneer/packages/app-accounts/src/Overview.tsx

@@ -7,6 +7,8 @@ import { SubjectInfo } from '@polkadot/ui-keyring/observable/types';
 import { ComponentProps } from './types';
 
 import React, { useState } from 'react';
+import { Link, useLocation } from 'react-router-dom';
+import { Button as SUIButton } from 'semantic-ui-react';
 import keyring from '@polkadot/ui-keyring';
 import accountObservable from '@polkadot/ui-keyring/observable/accounts';
 import { getLedger, isLedger, withMulti, withObservable } from '@polkadot/react-api';
@@ -35,6 +37,7 @@ async function queryLedger (): Promise<void> {
 }
 
 function Overview ({ accounts, onStatusChange, t }: Props): React.ReactElement<Props> {
+  const { pathname } = useLocation();
   const [isCreateOpen, setIsCreateOpen] = useState(false);
   const [isImportOpen, setIsImportOpen] = useState(false);
   const emptyScreen = !(isCreateOpen || isImportOpen) && accounts && (Object.keys(accounts).length === 0);
@@ -44,6 +47,9 @@ function Overview ({ accounts, onStatusChange, t }: Props): React.ReactElement<P
 
   return (
     <CardGrid
+      topButtons={
+        !emptyScreen && <SUIButton as={Link} to={`${pathname}/vanity`}>Generate a vanity address</SUIButton>
+      }
       buttons={
         <Button.Group>
           <Button

+ 21 - 12
pioneer/packages/app-accounts/src/Vanity/index.tsx

@@ -18,6 +18,7 @@ import matchRegex from '../vanitygen/regex';
 import generatorSort from '../vanitygen/sort';
 import Match from './Match';
 import translate from './translate';
+import Section from '@polkadot/joy-utils/Section';
 
 interface Props extends ComponentProps, I18nProps {}
 
@@ -42,6 +43,10 @@ const BOOL_OPTIONS = [
   { text: 'Yes', value: true }
 ];
 
+const SectionContentWrapper = styled.div`
+  margin-left: -2rem;
+`;
+
 class VanityApp extends TxComponent<Props, State> {
   private results: GeneratorResult[] = [];
 
@@ -72,18 +77,22 @@ class VanityApp extends TxComponent<Props, State> {
 
     return (
       <div className={className}>
-        {this.renderOptions()}
-        {this.renderButtons()}
-        {this.renderStats()}
-        {this.renderMatches()}
-        {createSeed && (
-          <CreateModal
-            onClose={this.closeCreate}
-            onStatusChange={onStatusChange}
-            seed={createSeed}
-            type={type}
-          />
-        )}
+        <Section title="Generate a vanity address">
+          <SectionContentWrapper>
+            {this.renderOptions()}
+            {this.renderButtons()}
+            {this.renderStats()}
+            {this.renderMatches()}
+            {createSeed && (
+              <CreateModal
+                onClose={this.closeCreate}
+                onStatusChange={onStatusChange}
+                seed={createSeed}
+                type={type}
+              />
+            )}
+          </SectionContentWrapper>
+        </Section>
       </div>
     );
   }

+ 0 - 4
pioneer/packages/app-accounts/src/index.tsx

@@ -62,10 +62,6 @@ function AccountsApp ({ allAccounts = {}, basePath, location, onStatusChange, t
               name: 'overview',
               text: t('My accounts')
             },
-            {
-              name: 'vanity',
-              text: t('Vanity address')
-            },
             {
               name: 'memo',
               text: t('My memo')

+ 15 - 8
pioneer/packages/app-address-book/src/Overview.tsx

@@ -7,7 +7,9 @@ import { SubjectInfo } from '@polkadot/ui-keyring/observable/types';
 import { ComponentProps } from './types';
 
 import React, { useState } from 'react';
+import { Link, useLocation } from 'react-router-dom';
 import { Button, CardGrid } from '@polkadot/react-components';
+import { Button as SUIButton, Icon } from 'semantic-ui-react';
 import addressObservable from '@polkadot/ui-keyring/observable/addresses';
 import { withMulti, withObservable } from '@polkadot/react-api';
 
@@ -20,6 +22,7 @@ interface Props extends ComponentProps, I18nProps {
 }
 
 function Overview ({ addresses, onStatusChange, t }: Props): React.ReactElement<Props> {
+  const { pathname } = useLocation();
   const [isCreateOpen, setIsCreateOpen] = useState(false);
   const emptyScreen = !isCreateOpen && (!addresses || Object.keys(addresses).length === 0);
 
@@ -27,15 +30,19 @@ function Overview ({ addresses, onStatusChange, t }: Props): React.ReactElement<
 
   return (
     <CardGrid
+      topButtons={
+        <SUIButton as={Link} to={`${pathname}/memo`}>
+          <Icon name="search" />
+          View memo
+        </SUIButton>
+      }
       buttons={
-        <Button.Group>
-          <Button
-            icon='add'
-            isPrimary
-            label={t('Add contact')}
-            onClick={_toggleCreate}
-          />
-        </Button.Group>
+        <Button
+          icon='add'
+          isPrimary
+          label={t('Add contact')}
+          onClick={_toggleCreate}
+        />
       }
       isEmpty={emptyScreen}
       emptyText={t('No contacts found.')}

+ 29 - 18
pioneer/packages/app-address-book/src/index.tsx

@@ -8,8 +8,10 @@ import { ComponentProps } from './types';
 
 import React from 'react';
 import { Route, Switch } from 'react-router';
+import { Link } from 'react-router-dom';
+import styled from 'styled-components';
+import { Breadcrumb } from 'semantic-ui-react';
 import { HelpOverlay } from '@polkadot/react-components';
-import Tabs from '@polkadot/react-components/Tabs';
 
 import basicMd from './md/basic.md';
 import Overview from './Overview';
@@ -21,6 +23,15 @@ interface Props extends AppProps, I18nProps {
   location: any;
 }
 
+const StyledHeader = styled.header`
+  text-align: left;
+
+  .ui.breadcrumb {
+    padding: 1.4rem 0 0 .4rem;
+    font-size: 1.4rem;
+  }
+`;
+
 function AddressBookApp ({ basePath, onStatusChange, t }: Props): React.ReactElement<Props> {
   const _renderComponent = (Component: React.ComponentType<ComponentProps>): () => React.ReactNode => {
     // eslint-disable-next-line react/display-name
@@ -32,27 +43,27 @@ function AddressBookApp ({ basePath, onStatusChange, t }: Props): React.ReactEle
       />;
   };
 
+  const viewMemoPath = `${basePath}/memo/:accountId?`;
+
   return (
     <main className='address-book--App'>
       <HelpOverlay md={basicMd} />
-      <header>
-        <Tabs
-          basePath={basePath}
-          items={[
-            {
-              isRoot: true,
-              name: 'overview',
-              text: t('My contacts')
-            },
-            {
-              name: 'memo',
-              text: t('View memo')
-            }
-          ]}
-        />
-      </header>
+      <StyledHeader>
+        <Breadcrumb>
+          <Switch>
+            <Route path={viewMemoPath}>
+              <Breadcrumb.Section link as={Link} to={basePath}>Contacts</Breadcrumb.Section>
+              <Breadcrumb.Divider icon="right angle" />
+              <Breadcrumb.Section active>View memo</Breadcrumb.Section>
+            </Route>
+            <Route>
+              <Breadcrumb.Section active>Contacts</Breadcrumb.Section>
+            </Route>
+          </Switch>
+        </Breadcrumb>
+      </StyledHeader>
       <Switch>
-        <Route path={`${basePath}/memo/:accountId?`} component={MemoByAccount} />
+        <Route path={viewMemoPath} component={MemoByAccount} />
         <Route render={_renderComponent(Overview)} />
       </Switch>
     </main>

+ 10 - 5
pioneer/packages/joy-election/src/SealedVotes.tsx

@@ -1,4 +1,6 @@
 import React from 'react';
+import { Link } from 'react-router-dom';
+import { Button } from 'semantic-ui-react';
 
 import { I18nProps } from '@polkadot/react-components/types';
 import { ApiProps } from '@polkadot/react-api/types';
@@ -42,11 +44,14 @@ class Comp extends React.PureComponent<Props> {
           ? <em>No votes by the current account found on the current browser.</em>
           : this.renderVotes(myVotes)
       }</Section>
-      <Section title={`Other votes (${otherVotes.length})`}>{
-        !otherVotes.length
-          ? <em>No votes submitted by other accounts yet.</em>
-          : this.renderVotes(otherVotes)
-      }</Section>
+      <Section title={`Other votes (${otherVotes.length})`}>
+        <Button primary as={Link} to="reveals">Reveal a vote</Button>
+        {
+          !otherVotes.length
+            ? <em>No votes submitted by other accounts yet.</em>
+            : this.renderVotes(otherVotes)
+        }
+      </Section>
     </>;
   }
 }

+ 0 - 4
pioneer/packages/joy-election/src/index.tsx

@@ -51,10 +51,6 @@ class App extends React.PureComponent<Props, State> {
       {
         name: 'votes',
         text: t('Votes') + ` (${commitments.length})`
-      },
-      {
-        name: 'reveals',
-        text: t('Reveal a vote')
       }
     ];
   }

+ 0 - 4
pioneer/packages/joy-media/src/index.tsx

@@ -40,10 +40,6 @@ function App (props: Props) {
     !myAddress ? undefined : {
       name: `account/${myAddress}/channels`,
       text: t('My channels')
-    },
-    {
-      name: 'channels/new',
-      text: t('New channel')
     }
     // !myAddress ? undefined : {
     //   name: `account/${myAddress}/videos`,

+ 1 - 1
pioneer/packages/joy-members/src/index.tsx

@@ -37,7 +37,7 @@ class App extends React.PureComponent<Props> {
       },
       {
         name: 'edit',
-        text: iAmMember ? t('Edit my profile') : t('Register')
+        text: iAmMember ? 'My profile' : t('Register')
       },
       {
         name: 'dashboard',

+ 15 - 6
pioneer/packages/joy-proposals/src/Proposal/ProposalPreviewList.tsx

@@ -1,6 +1,7 @@
 import React, { useState } from 'react';
-import { Card, Container } from 'semantic-ui-react';
+import { Button, Card, Container, Icon } from 'semantic-ui-react';
 import styled from 'styled-components';
+import { Link, useLocation } from 'react-router-dom';
 
 import ProposalPreview from './ProposalPreview';
 import { ParsedProposal } from '@polkadot/joy-utils/types/proposals';
@@ -54,7 +55,9 @@ type ProposalPreviewListProps = {
 
 const FilterContainer = styled.div`
   display: flex;
-  justify-content: flex-end;
+  align-items: flex-start;
+  justify-content: space-between;
+  margin-bottom: 1.75rem;
 `;
 const FilterOption = styled.span`
   display: inline-flex;
@@ -83,10 +86,10 @@ const StyledDropdown = styled(Dropdown)`
   .dropdown {
     width: 200px;
   }
-  margin-bottom: 1.75rem;
 `;
 
 function ProposalPreviewList ({ bestNumber }: ProposalPreviewListProps) {
+  const { pathname } = useLocation();
   const transport = useTransport();
   const [proposals, error, loading] = usePromise<ParsedProposal[]>(() => transport.proposals.proposals(), []);
   const [activeFilter, setActiveFilter] = useState<ProposalFilter>('All');
@@ -109,15 +112,21 @@ function ProposalPreviewList ({ bestNumber }: ProposalPreviewListProps) {
 
   return (
     <Container className="Proposal" fluid>
-      <PromiseComponent error={ error } loading={ loading } message="Fetching proposals...">
-        <FilterContainer>
+      <FilterContainer>
+        <Button primary as={Link} to={`${pathname}/new`}>
+          <Icon name="add" />
+          New proposal
+        </Button>
+        {!loading && (
           <StyledDropdown
             label="Proposal state"
             options={filterOptions}
             value={activeFilter}
             onChange={_onChangePrefix}
           />
-        </FilterContainer>
+        )}
+      </FilterContainer>
+      <PromiseComponent error={ error } loading={ loading } message="Fetching proposals...">
         {
           sortedProposals.length ? (
             <Card.Group>

+ 27 - 17
pioneer/packages/joy-proposals/src/index.tsx

@@ -1,8 +1,10 @@
 import React from 'react';
 import { Route, Switch } from 'react-router';
+import { Link } from 'react-router-dom';
+import styled from 'styled-components';
+import { Breadcrumb } from 'semantic-ui-react';
 
 import { AppProps, I18nProps } from '@polkadot/react-components/types';
-import Tabs, { TabItem } from '@polkadot/react-components/Tabs';
 import { TransportProvider } from '@polkadot/joy-utils/react/context';
 import { ProposalPreviewList, ProposalFromId, ChooseProposalType } from './Proposal';
 
@@ -24,27 +26,35 @@ import {
 
 interface Props extends AppProps, I18nProps {}
 
-function App (props: Props): React.ReactElement<Props> {
-  const { t, basePath } = props;
+const StyledHeader = styled.header`
+  text-align: left;
+
+  .ui.breadcrumb {
+    padding: 1.4rem 0 0 .4rem;
+    font-size: 1.4rem;
+  }
+`;
 
-  const tabs: TabItem[] = [
-    {
-      isRoot: true,
-      name: 'proposals',
-      text: t('Proposals')
-    },
-    {
-      name: 'new',
-      text: t('New Proposal')
-    }
-  ];
+function App (props: Props): React.ReactElement<Props> {
+  const { basePath } = props;
 
   return (
     <TransportProvider>
       <main className="proposal--App">
-        <header>
-          <Tabs basePath={basePath} items={tabs} />
-        </header>
+        <StyledHeader>
+          <Breadcrumb>
+            <Switch>
+              <Route path={`${basePath}/new`}>
+                <Breadcrumb.Section link as={Link} to={basePath}>Proposals</Breadcrumb.Section>
+                <Breadcrumb.Divider icon="right angle" />
+                <Breadcrumb.Section active>New proposal</Breadcrumb.Section>
+              </Route>
+              <Route>
+                <Breadcrumb.Section active>Proposals</Breadcrumb.Section>
+              </Route>
+            </Switch>
+          </Breadcrumb>
+        </StyledHeader>
         <Switch>
           <Route exact path={`${basePath}/new`} component={ChooseProposalType} />
           <Route exact path={`${basePath}/new/text`} component={SignalForm} />

+ 1 - 1
pioneer/packages/react-components/src/CardGrid.tsx

@@ -15,7 +15,7 @@ class CardGrid extends Collection<Props, State> {
 
     return {
       ...state,
-      showHeader: !state.isEmpty || !!props.headerText
+      showFullHeader: !state.isEmpty
     };
   }
 

+ 21 - 8
pioneer/packages/react-components/src/Collection.tsx

@@ -9,6 +9,7 @@ import React from 'react';
 export interface CollectionProps extends I18nProps {
   banner?: React.ReactNode;
   buttons?: React.ReactNode;
+  topButtons?: React.ReactNode;
   children: React.ReactNode;
   className?: string;
   headerText?: React.ReactNode;
@@ -19,7 +20,7 @@ export interface CollectionProps extends I18nProps {
 
 export interface CollectionState {
   isEmpty: boolean;
-  showHeader?: boolean;
+  showFullHeader?: boolean;
 }
 
 export const collectionStyles = `
@@ -33,6 +34,12 @@ export const collectionStyles = `
       margin: 0;
       text-transform: lowercase;
     }
+
+    .ui--Collection-buttons {
+      flex: 1;
+      display: flex;
+      justify-content: space-between;
+    }
   }
 
   .ui--Collection-lowercase {
@@ -61,11 +68,11 @@ export default class Collection<P extends CollectionProps, S extends CollectionS
 
   public render (): React.ReactNode {
     const { banner, className } = this.props;
-    const { isEmpty, showHeader } = this.state;
+    const { isEmpty } = this.state;
 
     return (
       <div className={className}>
-        {showHeader && this.renderHeader()}
+        {this.renderHeader()}
         {banner}
         {isEmpty
           ? this.renderEmpty()
@@ -76,18 +83,24 @@ export default class Collection<P extends CollectionProps, S extends CollectionS
   }
 
   protected renderHeader (): React.ReactNode {
-    const { buttons, headerText } = this.props;
+    const { buttons, topButtons, headerText } = this.props;
+    const { showFullHeader } = this.state;
 
-    if (!headerText && !buttons) {
+    if (!headerText && !buttons && !topButtons) {
       return null;
     }
 
     return (
       <div className='ui--Collection-header'>
-        <h1>{headerText}</h1>
-        {buttons && (
+        {headerText && <h1>{headerText}</h1>}
+        {(buttons || topButtons) && (
           <div className='ui--Collection-buttons'>
-            {buttons}
+            <div>
+              {topButtons}
+            </div>
+            <div>
+              {showFullHeader && buttons}
+            </div>
           </div>
         )}
       </div>