mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-05-17 16:44:49 -04:00
Editor Help Modal (#99)
* removed css from body * added internal-link and translated-internal-link * icon in links are always fixedWidth * added help button Signed-off-by: Philip Molares <philip.molares@udo.edu> Co-authored-by: Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de>
This commit is contained in:
parent
5da45c2dfd
commit
177f639492
32 changed files with 399 additions and 68 deletions
|
@ -9,7 +9,7 @@ export interface LoadingScreenProps {
|
|||
export const LoadingScreen: React.FC<LoadingScreenProps> = ({ failedTitle }) => {
|
||||
return (
|
||||
<div className="loader middle">
|
||||
<div className="icon">
|
||||
<div className="icon text-white">
|
||||
<FontAwesomeIcon icon="file-alt" size="6x"
|
||||
className={failedTitle ? 'animation-shake' : 'animation-pulse'}/>
|
||||
</div>
|
||||
|
|
290
src/components/editor/task-bar/help-button.tsx
Normal file
290
src/components/editor/task-bar/help-button.tsx
Normal file
|
@ -0,0 +1,290 @@
|
|||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import React, { Fragment, useState } from 'react'
|
||||
import { Button, Card, Col, Modal, Row, Table } from 'react-bootstrap'
|
||||
import { Trans, useTranslation } from 'react-i18next'
|
||||
import { TranslatedExternalLink } from '../../links/translated-external-link'
|
||||
|
||||
export const HelpButton: React.FC = () => {
|
||||
const { t } = useTranslation()
|
||||
const [show, setShow] = useState(false)
|
||||
|
||||
const handleShow = () => setShow(true)
|
||||
const handleClose = () => setShow(false)
|
||||
return (
|
||||
<Fragment>
|
||||
<Button title={t('editor.menu.help')} className="ml-2 text-secondary" size="sm" variant="outline-light"
|
||||
onClick={handleShow}>
|
||||
<FontAwesomeIcon icon="question-circle"/>
|
||||
</Button>
|
||||
<Modal show={show} onHide={handleClose} animation={true} className="text-dark" size='lg'>
|
||||
<Modal.Header closeButton>
|
||||
<Modal.Title>
|
||||
<FontAwesomeIcon icon="question-circle"/> <Trans i18nKey={'editor.menu.help'}/>
|
||||
</Modal.Title>
|
||||
</Modal.Header>
|
||||
<Modal.Body className="text-dark">
|
||||
<Row>
|
||||
<Col lg={4}>
|
||||
<Card>
|
||||
<Card.Header><Trans i18nKey='editor.help.contacts.title'/></Card.Header>
|
||||
<Card.Body>
|
||||
<Card.Text>
|
||||
<ul className="list-unstyled">
|
||||
<li>
|
||||
<TranslatedExternalLink
|
||||
i18nKey='editor.help.contacts.community'
|
||||
href='https://community.codimd.org/'
|
||||
icon='users'
|
||||
className='text-primary'
|
||||
/>
|
||||
</li>
|
||||
<li>
|
||||
<TranslatedExternalLink
|
||||
i18nKey='editor.help.contacts.meetUsOn'
|
||||
i18nOption={{ service: 'Matrix' }}
|
||||
href='https://riot.im/app/#/room/#codimd:matrix.org'
|
||||
icon='hashtag'
|
||||
className='text-primary'
|
||||
/>
|
||||
</li>
|
||||
<li>
|
||||
<TranslatedExternalLink
|
||||
i18nKey='editor.help.contacts.reportIssue'
|
||||
href='https://github.com/codimd/server/issues'
|
||||
icon='tag'
|
||||
className='text-primary'
|
||||
/>
|
||||
</li>
|
||||
<li>
|
||||
<TranslatedExternalLink
|
||||
i18nKey='editor.help.contacts.helpTranslating'
|
||||
href='https://translate.codimd.org/'
|
||||
icon='language'
|
||||
className='text-primary'
|
||||
/>
|
||||
</li>
|
||||
</ul>
|
||||
</Card.Text>
|
||||
</Card.Body>
|
||||
</Card>
|
||||
<Card>
|
||||
<Card.Header><Trans i18nKey='editor.help.documents.title'/></Card.Header>
|
||||
<Card.Body>
|
||||
<Card.Text>
|
||||
<ul className="list-unstyled">
|
||||
<li>
|
||||
<TranslatedExternalLink
|
||||
i18nKey='editor.help.documents.features'
|
||||
href='/n/features'
|
||||
icon='dot-circle'
|
||||
className='text-primary'
|
||||
/>
|
||||
</li>
|
||||
<li>
|
||||
<TranslatedExternalLink
|
||||
i18nKey='editor.help.documents.yamlMetadata'
|
||||
href='/n/yaml-data'
|
||||
icon='dot-circle'
|
||||
className='text-primary'
|
||||
/>
|
||||
</li>
|
||||
<li>
|
||||
<TranslatedExternalLink
|
||||
i18nKey='editor.help.documents.slideExample'
|
||||
href='https://github.com/codimd/server/issues'
|
||||
icon='dot-circle'
|
||||
className='text-primary'
|
||||
/>
|
||||
</li>
|
||||
</ul>
|
||||
</Card.Text>
|
||||
</Card.Body>
|
||||
</Card>
|
||||
</Col>
|
||||
<Col lg={8}>
|
||||
<Card>
|
||||
<Card.Header><Trans i18nKey='editor.help.cheatsheet.title'/></Card.Header>
|
||||
<Card.Body>
|
||||
<Card.Text>
|
||||
<Table className="table-condensed table-cheatsheet">
|
||||
<thead>
|
||||
<tr>
|
||||
<td><Trans i18nKey='editor.help.cheatsheet.example'/></td>
|
||||
<td><Trans i18nKey='editor.help.cheatsheet.syntax'/></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="markdown-body"
|
||||
style={{ fontFamily: 'inherit', fontSize: '14px', padding: 0, maxWidth: 'inherit' }}>
|
||||
<tr>
|
||||
<td><Trans i18nKey='editor.editorToolbar.header'/></td>
|
||||
<td>
|
||||
<pre># <Trans i18nKey='editor.editorToolbar.header'/></pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<ul>
|
||||
<li><Trans i18nKey='editor.editorToolbar.unorderedList'/></li>
|
||||
</ul>
|
||||
</td>
|
||||
<td>
|
||||
<pre>- <Trans i18nKey='editor.editorToolbar.unorderedList'/></pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<ol>
|
||||
<li><Trans i18nKey='editor.editorToolbar.orderedList'/></li>
|
||||
</ol>
|
||||
</td>
|
||||
<td>
|
||||
<pre>1. <Trans i18nKey='editor.editorToolbar.orderedList'/></pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<ul>
|
||||
<li className="task-list-item">
|
||||
<input type="checkbox" className="task-list-item-checkbox" disabled={false}/>
|
||||
<label><Trans i18nKey='editor.editorToolbar.checkList'/></label>
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td>
|
||||
<pre>- [ ] <Trans i18nKey='editor.editorToolbar.checkList'/></pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<blockquote><Trans i18nKey='editor.editorToolbar.blockquote'/></blockquote>
|
||||
</td>
|
||||
<td>
|
||||
<pre>> <Trans i18nKey='editor.editorToolbar.blockquote'/></pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong><Trans i18nKey='editor.editorToolbar.bold'/></strong></td>
|
||||
<td>
|
||||
<pre>**<Trans i18nKey='editor.editorToolbar.bold'/>**</pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><i><Trans i18nKey='editor.editorToolbar.italic'/></i></td>
|
||||
<td>
|
||||
<pre>*<Trans i18nKey='editor.editorToolbar.italic'/>*</pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><s><Trans i18nKey='editor.editorToolbar.strikethrough'/></s></td>
|
||||
<td>
|
||||
<pre>~~<Trans i18nKey='editor.editorToolbar.strikethrough'/>~~</pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>19<sup>th</sup></td>
|
||||
<td>
|
||||
<pre>19^th^</pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>H<sub>2</sub>O</td>
|
||||
<td>
|
||||
<pre>H~2~O</pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<ins><Trans i18nKey='editor.help.cheatsheet.underlinedText'/></ins>
|
||||
</td>
|
||||
<td>
|
||||
<pre>++<Trans i18nKey='editor.help.cheatsheet.underlinedText'/>++</pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<mark><Trans i18nKey='editor.help.cheatsheet.highlightedText'/></mark>
|
||||
</td>
|
||||
<td>
|
||||
<pre>==<Trans i18nKey='editor.help.cheatsheet.highlightedText'/>==</pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href='https://example.com'><Trans i18nKey='editor.editorToolbar.link'/></a></td>
|
||||
<td>
|
||||
<pre>[link text](https://example.com)</pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><Trans i18nKey='editor.editorToolbar.image'/></td>
|
||||
<td>
|
||||
<pre></pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><Trans i18nKey='editor.editorToolbar.code'/></code></td>
|
||||
<td>
|
||||
<pre>`<Trans i18nKey='editor.editorToolbar.code'/>`</pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<pre style={{ border: 'none !important' }}>
|
||||
<code className="javascript hljs">
|
||||
<div className="wrapper">
|
||||
<div className="gutter linenumber">
|
||||
<span data-linenumber="1"/>
|
||||
</div>
|
||||
<div className="code">
|
||||
<span className="hljs-keyword">var</span> x = <span className="hljs-number">5</span>;
|
||||
</div>
|
||||
</div>
|
||||
</code>
|
||||
</pre>
|
||||
</td>
|
||||
<td>
|
||||
<pre>```javascript<br/>var x = 5;<br/>```</pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img alt=":smile:" className="emoji" src="./build/emojify.js/dist/images/basic/smile.png"
|
||||
title=":smile:"/></td>
|
||||
<td>
|
||||
<pre>:smile:</pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Extern</td>
|
||||
<td>
|
||||
<pre>{'{'}%youtube youtube_id %{'}'}</pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>L<sup>a</sup>T<sub>e</sub>X</td>
|
||||
<td>
|
||||
<pre>$L^aT_eX$</pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div className="alert alert-info">
|
||||
<p>
|
||||
<Trans i18nKey='editor.help.cheatsheet.exampleAlert'/>
|
||||
</p>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<pre>:::info<br/><Trans i18nKey='editor.help.cheatsheet.exampleAlert'/><br/>:::</pre>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</Table>
|
||||
</Card.Text>
|
||||
</Card.Body>
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
</Modal.Body>
|
||||
</Modal>
|
||||
</Fragment>
|
||||
)
|
||||
}
|
|
@ -7,6 +7,7 @@ import { EditorViewMode } from './editor-view-mode'
|
|||
import { Trans, useTranslation } from 'react-i18next'
|
||||
import { EditorMenu } from './editor-menu'
|
||||
import { ConnectionIndicator } from './connection-indicator'
|
||||
import { HelpButton } from './help-button'
|
||||
|
||||
const TaskBar: React.FC = () => {
|
||||
useTranslation()
|
||||
|
@ -20,10 +21,7 @@ const TaskBar: React.FC = () => {
|
|||
</Navbar.Brand>
|
||||
<EditorViewMode/>
|
||||
<DarkModeButton/>
|
||||
<Button className="ml-2 text-secondary" size="sm"
|
||||
variant="outline-light">
|
||||
<FontAwesomeIcon icon="question-circle"/>
|
||||
</Button>
|
||||
<HelpButton/>
|
||||
</Nav>
|
||||
<Nav className="d-flex align-items-center text-secondary">
|
||||
<Button className="ml-2 text-secondary" size="sm" variant="outline-light">
|
||||
|
|
|
@ -6,7 +6,7 @@ import './layout/style/index.scss'
|
|||
|
||||
export const LandingLayout: React.FC = ({ children }) => {
|
||||
return (
|
||||
<Container>
|
||||
<Container className="text-center text-white">
|
||||
<HeaderBar/>
|
||||
{children}
|
||||
<Footer/>
|
||||
|
|
|
@ -4,16 +4,12 @@ import { useSelector } from 'react-redux'
|
|||
import { ApplicationState } from '../../../../redux'
|
||||
import { ExternalLink } from '../../../links/external-link'
|
||||
import { TranslatedExternalLink } from '../../../links/translated-external-link'
|
||||
import { TranslatedInternalLink } from '../../../links/translated-internal-link'
|
||||
import { VersionInfo } from '../version-info/version-info'
|
||||
|
||||
export const PoweredByLinks: React.FC = () => {
|
||||
useTranslation()
|
||||
|
||||
const defaultLinks =
|
||||
{
|
||||
releases: '/n/release-notes'
|
||||
}
|
||||
|
||||
const config = useSelector((state: ApplicationState) => state.backendConfig)
|
||||
|
||||
return (
|
||||
|
@ -21,8 +17,10 @@ export const PoweredByLinks: React.FC = () => {
|
|||
<Trans i18nKey="landing.footer.poweredBy">
|
||||
<ExternalLink href="https://codimd.org" text="CodiMD"/>
|
||||
</Trans>
|
||||
|
|
||||
<TranslatedInternalLink path='/n/release-notes' i18nKey='landing.footer.releases'/>
|
||||
{
|
||||
Object.entries({ ...defaultLinks, ...(config.specialLinks) }).map(([i18nKey, href]) =>
|
||||
Object.entries({ ...config.specialLinks }).map(([i18nKey, href]) =>
|
||||
<Fragment key={i18nKey}>
|
||||
|
|
||||
<TranslatedExternalLink href={href} i18nKey={'landing.footer.' + i18nKey}/>
|
||||
|
|
|
@ -7,8 +7,6 @@ html {
|
|||
}
|
||||
body {
|
||||
min-height: 100%;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
//text-shadow: 0 1px 3px rgba(0, 0, 0, .5);
|
||||
font-family: "Source Sans Pro", Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
|
|
@ -4,12 +4,15 @@ import { IconProp } from '../../utils/iconProp'
|
|||
|
||||
export interface ExternalLinkProp {
|
||||
href: string;
|
||||
text: string;
|
||||
icon?: IconProp;
|
||||
className?: string
|
||||
}
|
||||
|
||||
export const ExternalLink: React.FC<ExternalLinkProp> = ({ href, text, icon, className = 'text-light' }) => {
|
||||
export interface ExternalLinkTextProp {
|
||||
text: string;
|
||||
}
|
||||
|
||||
export const ExternalLink: React.FC<ExternalLinkProp & ExternalLinkTextProp> = ({ href, text, icon, className = 'text-light' }) => {
|
||||
return (
|
||||
<a href={href}
|
||||
target="_blank"
|
||||
|
@ -18,7 +21,7 @@ export const ExternalLink: React.FC<ExternalLinkProp> = ({ href, text, icon, cla
|
|||
{
|
||||
icon
|
||||
? <Fragment>
|
||||
<FontAwesomeIcon icon={icon}/>
|
||||
<FontAwesomeIcon icon={icon} fixedWidth={true}/>
|
||||
</Fragment>
|
||||
: null
|
||||
}
|
||||
|
|
30
src/components/links/internal-link.tsx
Normal file
30
src/components/links/internal-link.tsx
Normal file
|
@ -0,0 +1,30 @@
|
|||
import React, { Fragment } from 'react'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { LinkContainer } from 'react-router-bootstrap'
|
||||
import { IconProp } from '../../utils/iconProp'
|
||||
|
||||
export interface InternalLinkProp {
|
||||
path: string;
|
||||
icon?: IconProp;
|
||||
className?: string
|
||||
}
|
||||
|
||||
export interface InternalLinkTextProp {
|
||||
text: string;
|
||||
}
|
||||
|
||||
export const InternalLink: React.FC<InternalLinkProp & InternalLinkTextProp> = ({ path, text, icon, className = 'text-light' }) => {
|
||||
return (
|
||||
<LinkContainer to={path}
|
||||
className={className}>
|
||||
{
|
||||
icon
|
||||
? <Fragment>
|
||||
<FontAwesomeIcon icon={icon} fixedWidth={true}/>
|
||||
</Fragment>
|
||||
: null
|
||||
}
|
||||
{text}
|
||||
</LinkContainer>
|
||||
)
|
||||
}
|
|
@ -1,19 +1,17 @@
|
|||
import { StringMap, TOptionsBase } from 'i18next'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { IconProp } from '../../utils/iconProp'
|
||||
import { ExternalLink } from './external-link'
|
||||
import { ExternalLink, ExternalLinkProp } from './external-link'
|
||||
|
||||
export interface TranslatedLinkProps {
|
||||
i18nKey: string;
|
||||
href: string;
|
||||
icon?: IconProp;
|
||||
className?: string
|
||||
i18nOption?: (TOptionsBase & StringMap) | string
|
||||
}
|
||||
|
||||
const TranslatedExternalLink: React.FC<TranslatedLinkProps> = ({ i18nKey, ...props }) => {
|
||||
const TranslatedExternalLink: React.FC<TranslatedLinkProps & ExternalLinkProp> = ({ i18nKey, i18nOption, ...props }) => {
|
||||
const { t } = useTranslation()
|
||||
return (
|
||||
<ExternalLink text={t(i18nKey)} {...props}/>
|
||||
<ExternalLink text={t(i18nKey, i18nOption)} {...props}/>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
11
src/components/links/translated-internal-link.tsx
Normal file
11
src/components/links/translated-internal-link.tsx
Normal file
|
@ -0,0 +1,11 @@
|
|||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { InternalLink, InternalLinkProp } from './internal-link'
|
||||
import { TranslatedLinkProps } from './translated-external-link'
|
||||
|
||||
export const TranslatedInternalLink: React.FC<TranslatedLinkProps & InternalLinkProp> = ({ i18nKey, i18nOption, ...props }) => {
|
||||
const { t } = useTranslation()
|
||||
return (
|
||||
<InternalLink text={t(i18nKey, i18nOption)} {...props}/>
|
||||
)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue