Commit 600c04ea authored by Viacheslav Pavlov's avatar Viacheslav Pavlov
Browse files

Merge branch '253-rtl-layouts' into 'master'

RTL layouts

Closes #253

See merge request genesys-pgr/genesys-ui!265
parents 489e68d1 064fe5b3
......@@ -35,6 +35,7 @@ const virtualPath = document.baseURI.replace(/^(https?:\/\/[^\/]+)?(.*)\/$/, '$2
const detectedLang = initialLanguage ? initialLanguage : detectLocaleFromPath(virtualPath, window.location.pathname, 0);
const historyOptions = { basename: detectedLang !== 'en' ? `${virtualPath}/${detectedLang}` : `${virtualPath}` };
const history = createHistory(historyOptions);
const direction = getDir(detectedLang);
// Configure axios for client
configureBackendApi({ apiUrl: `${virtualPath}/proxy` });
......@@ -44,7 +45,7 @@ const store = composeEnhancers(applyMiddleware(thunk, routerMiddleware(history))
if (__PRELOADED_STATE__ === undefined) {
document.getElementsByTagName('html')[0].setAttribute('lang', detectedLang);
document.getElementsByTagName('html')[0].setAttribute('dir', getDir(detectedLang));
document.getElementsByTagName('html')[0].setAttribute('dir', direction);
checkAccessTokens(store.dispatch)
.then(() => {
......@@ -53,7 +54,7 @@ if (__PRELOADED_STATE__ === undefined) {
<Provider store={ store }>
<ConnectedRouter history={ history }>
<I18nextProvider i18n={ i18nClient } initialLanguage={ initialLanguage } initialI18nStore={ initialI18nStore }>
<MuiThemeProvider theme={ theme }>
<MuiThemeProvider theme={ theme(direction) }>
{ renderRoutes(routes) }
</MuiThemeProvider>
</I18nextProvider>
......@@ -72,7 +73,7 @@ if (__PRELOADED_STATE__ === undefined) {
<Provider store={ store }>
<ConnectedRouter history={ history }>
<I18nextProvider i18n={ i18nClient } initialLanguage={ initialLanguage } initialI18nStore={ initialI18nStore }>
<MuiThemeProvider theme={ theme }>
<MuiThemeProvider theme={ theme(direction) }>
{ renderRoutes(routes) }
</MuiThemeProvider>
</I18nextProvider>
......
......@@ -77,6 +77,7 @@ const prerenderer = (html, errHtml) => (req, res) => {
const pathWithoutLang = req.url.substr(initialLanguage !== defaultLanguage ? 3 : 0, req.url.length);
console.log(`<StaticRouter location="${pathWithoutLang}" basename="${basename}"`);
const direction = getDir(initialLanguage);
const modules = [];
......@@ -84,7 +85,7 @@ const prerenderer = (html, errHtml) => (req, res) => {
<Loadable.Capture report={ (moduleName) => modules.push(moduleName) }>
<ReduxProvider store={ store }>
<JssProvider generateClassName={ generateClassName } registry={ sheets }>
<MuiThemeProvider theme={ theme } sheetsManager={ new Map() }>
<MuiThemeProvider theme={ theme(direction) } sheetsManager={ new Map() }>
<I18nextProvider i18n={ req.i18n }>
<StaticRouter location={ pathWithoutLang } context={ context } basename={ basename }>
{ renderRoutes(routes) }
......
......@@ -107,6 +107,9 @@ const styles = (theme) => ({
color: '#88ba42',
},
},
'html[dir="rtl"] &' : {
left: 0,
},
},
mapIcon: {
fontSize: '20px',
......
......@@ -55,8 +55,8 @@ const AccessionCard = ({ accession, classes, index, addAccessionToMyList, remove
<Card className={ !editMode && (isChecked ? classes.selected : accession.historic ? classes.historic : '') } onTouchStart={ onTouchStart } onTouchEnd={ onTouchEnd }>
<CardContent>
<div className={ classes.firstRow }>
<b>{ index !== undefined && `${index + 1}. ` }</b>
<b>
{ index !== undefined && `${index + 1}. ` }
<AccessionLink to={ accession }>
{ accession.accessionNumber }
{ ` • ` }
......
......@@ -100,27 +100,27 @@ const AccessionFilters = ({handleSubmit, initialValues, initialize, terms, crops
terms={ terms && terms.get('images') }
initialValues
/>
<CollapsibleComponentSearch title={ t('accessions.public.f.climate') }>
<NumberFilter name="geo.climate.bio1" label={ t('accessions.climate.bio1') } />
<NumberFilter name="geo.climate.bio2" label={ t('accessions.climate.bio2') } />
<NumberFilter name="geo.climate.bio3" label={ t('accessions.climate.bio3') } />
<NumberFilter name="geo.climate.bio4" label={ t('accessions.climate.bio4') } />
<NumberFilter name="geo.climate.bio5" label={ t('accessions.climate.bio5') } />
<NumberFilter name="geo.climate.bio6" label={ t('accessions.climate.bio6') } />
<NumberFilter name="geo.climate.bio7" label={ t('accessions.climate.bio7') } />
<NumberFilter name="geo.climate.bio8" label={ t('accessions.climate.bio8') } />
<NumberFilter name="geo.climate.bio9" label={ t('accessions.climate.bio9') } />
<NumberFilter name="geo.climate.bio10" label={ t('accessions.climate.bio10') } />
<NumberFilter name="geo.climate.bio11" label={ t('accessions.climate.bio11') } />
<NumberFilter name="geo.climate.bio12" label={ t('accessions.climate.bio12') } />
<NumberFilter name="geo.climate.bio13" label={ t('accessions.climate.bio13') } />
<NumberFilter name="geo.climate.bio14" label={ t('accessions.climate.bio14') } />
<NumberFilter name="geo.climate.bio15" label={ t('accessions.climate.bio15') } />
<NumberFilter name="geo.climate.bio16" label={ t('accessions.climate.bio16') } />
<NumberFilter name="geo.climate.bio17" label={ t('accessions.climate.bio17') } />
<NumberFilter name="geo.climate.bio18" label={ t('accessions.climate.bio18') } />
<NumberFilter name="geo.climate.bio19" label={ t('accessions.climate.bio19') } />
</CollapsibleComponentSearch>
</CollapsibleComponentSearch>
<CollapsibleComponentSearch title={ t('accessions.public.f.climate') }>
<NumberFilter name="geo.climate.bio1" label={ t('accessions.climate.bio1') } />
<NumberFilter name="geo.climate.bio2" label={ t('accessions.climate.bio2') } />
<NumberFilter name="geo.climate.bio3" label={ t('accessions.climate.bio3') } />
<NumberFilter name="geo.climate.bio4" label={ t('accessions.climate.bio4') } />
<NumberFilter name="geo.climate.bio5" label={ t('accessions.climate.bio5') } />
<NumberFilter name="geo.climate.bio6" label={ t('accessions.climate.bio6') } />
<NumberFilter name="geo.climate.bio7" label={ t('accessions.climate.bio7') } />
<NumberFilter name="geo.climate.bio8" label={ t('accessions.climate.bio8') } />
<NumberFilter name="geo.climate.bio9" label={ t('accessions.climate.bio9') } />
<NumberFilter name="geo.climate.bio10" label={ t('accessions.climate.bio10') } />
<NumberFilter name="geo.climate.bio11" label={ t('accessions.climate.bio11') } />
<NumberFilter name="geo.climate.bio12" label={ t('accessions.climate.bio12') } />
<NumberFilter name="geo.climate.bio13" label={ t('accessions.climate.bio13') } />
<NumberFilter name="geo.climate.bio14" label={ t('accessions.climate.bio14') } />
<NumberFilter name="geo.climate.bio15" label={ t('accessions.climate.bio15') } />
<NumberFilter name="geo.climate.bio16" label={ t('accessions.climate.bio16') } />
<NumberFilter name="geo.climate.bio17" label={ t('accessions.climate.bio17') } />
<NumberFilter name="geo.climate.bio18" label={ t('accessions.climate.bio18') } />
<NumberFilter name="geo.climate.bio19" label={ t('accessions.climate.bio19') } />
</CollapsibleComponentSearch>
</FiltersBlock>
);
......
......@@ -9,6 +9,8 @@ import Card, { CardContent, CardActions } from 'ui/common/Card';
const styles = (theme) => ({
firstRow: {
marginBottom: '1em',
display: 'flex',
justifyContent: 'space-between' as 'space-between',
},
});
const rtlLanguages = ['ar', 'fa'];
......@@ -19,27 +21,27 @@ const ArticleCard = ({ article, classes, index, t, ...other }: { article: Articl
<Card>
<CardContent dir={ rtlLanguages.indexOf(article.lang) !== -1 ? 'rtl' : 'ltr' }>
<div className={ classes.firstRow }>
{ index !== undefined && `${index + 1}. ` }
<ArticleLink to={ article }>
{ article.targetId !== null ?
(
<span>
<div>
<span>{ index !== undefined && `${index + 1}. ` }</span>
<ArticleLink to={ article }>
{ article.targetId !== null ?
(
<span>
<code>
<span>{ article.classPk.shortName }@{ article.targetId }</span>
</code>
</span>
) : (
<span>
) : (
<span>
<code>{ article.slug }</code>
</span>
)
}
{ ` • ` }
{ article.title || t('No title') }
</ArticleLink>
<b className={ rtlLanguages.indexOf(article.lang) !== -1 ? 'float-left' : 'float-right' }>{ article.lang }</b>
)
}
{ ` • ` }
{ article.title || t('No title') }
</ArticleLink>
</div>
<b>{ article.lang }</b>
</div>
<div>
{ article.summary && <div dangerouslySetInnerHTML={ {__html: article.summary} }/> }
......
......@@ -40,6 +40,9 @@ const style = (theme) => ({
},
avatar: {
margin: '1.143rem 0 0 1.429rem',
'html[dir="rtl"] &' : {
margin: '1.143rem 1.429rem 0 0',
},
}
/*tslint:enable*/
});
......
......@@ -58,6 +58,10 @@ const styles = (theme) => ({
width: '50%',
textAlign: 'center' as 'center',
},
'html[dir="rtl"] &' : {
paddingLeft: '0',
paddingRight: '18px',
},
'&:hover > a > *': {
filter: 'brightness(0.5)',
transition: 'all, 0.1s',
......@@ -68,7 +72,7 @@ const styles = (theme) => ({
display: 'none',
},
},
/*tslint:enable*/
share: {
fontSize: '1.3rem',
display: 'inline-block',
......@@ -92,8 +96,14 @@ const styles = (theme) => ({
marginRight: '10px',
[theme.breakpoints.down('xs')]: {
marginRight: '0',
marginLeft: '0',
},
'html[dir="rtl"] &' : {
marginLeft: '10px',
marginRight: '0',
},
},
/*tslint:enable*/
});
interface IArticleSectionProps extends React.ClassAttributes<any> {
......
......@@ -33,7 +33,12 @@ const styles = (theme) => ({
'& > ul': {
marginTop: '30px',
padding: 0,
paddingLeft: '11px',
'html[dir="ltr"] &': {
paddingLeft: '11px',
},
'html[dir="rtl"] &': {
paddingRight: '11px',
},
},
'& > ul > li': {
fontSize: '18px',
......@@ -47,6 +52,9 @@ const styles = (theme) => ({
tableLayout: 'fixed' as 'fixed',
'& th': {
textAlign: 'left' as 'left',
'html[dir="rtl"] &': {
textAlign: 'right' as 'right',
},
},
'& code': {
[theme.breakpoints.down('sm')]: {
......@@ -72,6 +80,9 @@ const styles = (theme) => ({
paddingBottom: '8px',
color: '#777777',
textAlign: 'left' as 'left',
'html[dir="rtl"] &': {
textAlign: 'right' as 'right',
},
},
'& code': {
padding: '2px 4px',
......@@ -153,15 +164,28 @@ const styles = (theme) => ({
fontSize: '16px',
lineHeight: '1.4em',
marginLeft: 0,
'html[dir="rtl"] &': {
marginRight: 0,
},
listStyleType: 'none' as 'none',
'& ul': {
paddingLeft: '0.8em',
'html[dir="ltr"] &': {
paddingLeft: '0.8em',
},
'html[dir="rtl"] &': {
paddingRight: '0.8em',
},
},
},
'& > ul': {
fontSize: '16px',
lineHeight: '1.4em',
marginLeft: '.125em',
'html[dir="ltr"] &': {
marginLeft: '.125em',
},
'html[dir="rtl"] &': {
marginRight: '.125em',
},
padding: 0,
},
'& a': {
......
......@@ -499,7 +499,7 @@ class DetailInfo extends React.Component<IDetailInfoProps, any> {
<Section title={ t('datasets.public.c.datasetDisplay.traitsObserved') }>
<List>
{ dataset.descriptors.map((descriptor: Descriptor) => (
<ListItem key={ descriptor.uuid } className="">
<ListItem key={ descriptor.uuid } className="list-item-rtl">
<ListItemText primary={ <DescriptorLink to={ descriptor }><Markdown source={ descriptor.title }/></DescriptorLink> }
secondary={ descriptor.description && <Markdown source={ descriptor.description }/> }/>
</ListItem>
......
......@@ -36,6 +36,7 @@ class DatasetCreatorAutocompleteField extends React.Component<IDatasetCreatorAut
MenuProps={ {
open: false,
} }
classes={ { select: 'mui-select-rtl', icon: 'mui-select-icon-rtl' } }
>
{
<MenuItem value={ input.value }>{ input.value }</MenuItem>
......
......@@ -83,7 +83,7 @@ class DatasetCreatorForm extends React.Component<IDatasetCreatorFormProps, any>
<div key={ index } className="m-20 p-20 even-row">
<div>
<IconButton aria-label="Delete" style={ { float: 'right' } } onClick={ this.deleteCreator(fields, index) }>
<IconButton aria-label="Delete" className="float-right" onClick={ this.deleteCreator(fields, index) }>
<DeleteIcon/>
</IconButton>
</div>
......
......@@ -114,6 +114,7 @@ class SelectCountryInternal extends React.Component<ISelectCountryCodeInternal,
MenuProps={ {
open: false,
} }
classes={ { select: 'mui-select-rtl', icon: 'mui-select-icon-rtl' } }
>
{
this.state.pickerList ? <MenuItem value={ inputValue }>{ this.state.pickerList.code }</MenuItem> : null
......
......@@ -107,8 +107,11 @@ class LocationForm extends React.Component<ILocationFormProps, any> {
{ fields.map((location, index) => (
<div key={ index } className="p-20 m-20 even-row">
<div style={ { display: 'inline-block', width: '100%' } }>
<IconButton aria-label="Remove location" style={ { float: 'right' } }
onClick={ this.deleteLocation(fields, index) }>
<IconButton
aria-label="Remove location"
className="float-right"
onClick={ this.deleteLocation(fields, index) }
>
<DeleteIcon/>
</IconButton>
</div>
......
......@@ -54,9 +54,17 @@ const styles = (theme) => ({
marginTop: '-83px',
},
cardsContainer: {
paddingRight: '1.5rem',
[theme.breakpoints.down('sm')]: {
paddingRight: '0',
'html[dir="ltr"] &': {
paddingRight: '1.5rem',
[theme.breakpoints.down('sm')]: {
paddingRight: '0',
},
},
'html[dir="rtl"] &': {
paddingLeft: '1.5rem',
[theme.breakpoints.down('sm')]: {
paddingLeft: '0',
},
},
},
});
......
......@@ -248,7 +248,7 @@ class DisplayPage extends React.Component<IDisplayPageProps, any> {
<Section title={ t('descriptors.public.p.display.datasets') }>
<List>
{ descriptorExtra.datasets.map((dataset) => (
<ListItem button key={ dataset.uuid } style={ { padding: '1.429rem' } }>
<ListItem button key={ dataset.uuid } style={ { padding: '1.429rem' } } className="list-item-rtl">
<ListItemText primary={ <DatasetLink to={ dataset }><Markdown basic source={ dataset.title }/></DatasetLink> }
secondary={ `${dataset.versionTag}` }
/>
......@@ -264,7 +264,7 @@ class DisplayPage extends React.Component<IDisplayPageProps, any> {
<Section title={ t('descriptors.public.p.display.cropDescriptors') }>
<List>
{ descriptorExtra.descriptorLists.map((descriptorList) => (
<ListItem button key={ descriptorList.uuid }>
<ListItem button key={ descriptorList.uuid } className="list-item-rtl">
<ListItemText primary={ <DescriptorListLink to={ descriptorList }><Markdown basic source={ descriptorList.title }/></DescriptorListLink> }
secondary={ `${descriptorList.versionTag}` }
/>
......
......@@ -111,6 +111,7 @@ class SelectDescriptorListInternal extends React.Component<ISelectDescriptorList
MenuProps={ {
open: false,
} }
classes={ { select: 'mui-select-rtl', icon: 'mui-select-icon-rtl' } }
>
{
this.state.pickerList ? (
......
......@@ -23,7 +23,7 @@ const DescriptorFilters = ({ handleSubmit, initialize, t, ...other }) => (
<CropFilter/>
</CollapsibleComponentSearch>
<CollapsibleComponentSearch title={ t('descriptors.public.f.category') }>
<StringArrFilter name="category" options={ Descriptor.CATEGORIES }/>
<StringArrFilter name="category" options={ Descriptor.CATEGORIES } byKey/>
</CollapsibleComponentSearch>
<CollapsibleComponentSearch title={ t('descriptors.public.f.tidbits') }>
<BooleanFilter name="used" label={ t('descriptors.public.f.isUsed') }/>
......
......@@ -71,7 +71,13 @@ class SelectVocabulary extends React.Component<ISelectVocabularyProps, any> {
<Grid item xs={ 10 }>
<FormControl fullWidth>
<InputLabel>{ label }</InputLabel>
<Select className={ classes.select } value={ input.value && input.value.uuid } onChange={ this.handleChange } input={ <Input/> }>
<Select
className={ classes.select }
value={ input.value && input.value.uuid }
onChange={ this.handleChange }
input={ <Input/> }
classes={ { select: 'mui-select-rtl', icon: 'mui-select-icon-rtl' } }
>
<option value=""/>
{ vocabularies && vocabularies.map((v) => <option key={ v.uuid } value={ v.uuid }>{ v.title }</option>) }
</Select>
......
......@@ -19,8 +19,8 @@ const InstituteCard = ({ institute, classes, index, t, ...other }: { institute:
<Card>
<CardContent>
<div className={ classes.firstRow }>
<b>{ index !== undefined && `${index + 1}. ` }</b>
<b>
{ index !== undefined && `${index + 1}. ` }
<InstituteLink to={ institute }>
{ institute.code }
{ institute.acronym && ` • ` }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment