Skip to content

Commit

Permalink
feat(layer-selector): add new layer selector (#271)
Browse files Browse the repository at this point in the history
* feat(layer-selector): add new layer selector

* style(layer-selector): use emCalc

* refactor(layer-selector): change from span to button, rename

* refactor(layer-selector): change types
  • Loading branch information
KatvonRivia authored Feb 28, 2020
1 parent 5e7bcd0 commit 8f9d1e5
Show file tree
Hide file tree
Showing 21 changed files with 320 additions and 161 deletions.
15 changes: 15 additions & 0 deletions src/scripts/actions/show-layer-selector.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export const SHOW_LAYER_SELECTOR = 'SHOW_LAYER_SELECTOR';

export interface ShowLayerSelectorAction {
type: typeof SHOW_LAYER_SELECTOR;
showLayerSelector: boolean;
}

const showLayerSelectorAction = (
showLayerSelector: boolean
): ShowLayerSelectorAction => ({
type: SHOW_LAYER_SELECTOR,
showLayerSelector
});

export default showLayerSelectorAction;
13 changes: 11 additions & 2 deletions src/scripts/components/app/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ import {HashRouter as Router} from 'react-router-dom';

import rootReducer from '../../reducers/index';
import {languageSelector} from '../../selectors/language';
import {showLayerSelector} from '../../selectors/show-layer-selector';
import UrlSync from '../url-sync/url-sync';
import LayerLoader from '../layer-loader/layer-loader';
import Init from '../init/init';
import LayerSelector from '../layer-selector/layer-selector';
import Navigation from '../navigation/navigation';
import GlobeZoom from '../globe-zoom/globe-zoom';
import {EsaLogo} from '../icons/esa-logo';
Expand All @@ -32,6 +34,7 @@ const App: FunctionComponent = () => (

const TranslatedApp: FunctionComponent = () => {
const language = useSelector(languageSelector);
const layerSelector = useSelector(showLayerSelector);

return (
<Router>
Expand All @@ -40,8 +43,14 @@ const TranslatedApp: FunctionComponent = () => {
<div className={styles.logo}>
<EsaLogo />
</div>
<Navigation />
<GlobeZoom />
{layerSelector ? (
<LayerSelector />
) : (
<React.Fragment>
<Navigation />
<GlobeZoom />
</React.Fragment>
)}
</div>
</IntlProvider>
<UrlSync />
Expand Down
1 change: 1 addition & 0 deletions src/scripts/components/button/button.styl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
.button
display: flex
align-items: center
padding: 0
outline: 0
border: none
background: none
Expand Down
12 changes: 12 additions & 0 deletions src/scripts/components/icons/close-icon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React, {FunctionComponent} from 'react';

export const CloseIcon: FunctionComponent = () => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24">
<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" />
<path d="M0 0h24v24H0z" fill="none" />
</svg>
);
15 changes: 9 additions & 6 deletions src/scripts/components/icons/remove-icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ import React, {FunctionComponent} from 'react';

export const RemoveIcon: FunctionComponent = () => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24">
<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" />
<path d="M0 0h24v24H0z" fill="none" />
width="18"
height="18"
viewBox="0 0 18 18"
xmlns="http://www.w3.org/2000/svg">
<path
fillRule="evenodd"
clipRule="evenodd"
d="M9 1.5C4.86 1.5 1.5 4.86 1.5 9C1.5 13.14 4.86 16.5 9 16.5C13.14 16.5 16.5 13.14 16.5 9C16.5 4.86 13.14 1.5 9 1.5ZM9 15C5.6925 15 3 12.3075 3 9C3 5.6925 5.6925 3 9 3C12.3075 3 15 5.6925 15 9C15 12.3075 12.3075 15 9 15ZM5.87132 6.87868L6.93198 5.81802L9.0533 7.93934L11.1746 5.81802L12.2353 6.87868L10.114 9L12.2353 11.1213L11.1746 12.182L9.0533 10.0607L6.93198 12.182L5.87132 11.1213L7.99264 9L5.87132 6.87868Z"
/>
</svg>
);
31 changes: 31 additions & 0 deletions src/scripts/components/layer-list-item/layer-list-item.styl
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
@require '../../../variables.styl'

.layerItem
display: flex
justify-content: space-between
align-items: center
padding: emCalc(11px) emCalc(32px)
color: $textDefault

&:hover, &:focus
background-color: rgba($darkGrey4, 0.5)

.compare
display: block

.compare
display: none
border: none
background: none
color: $textDefault
text-transform: uppercase
font-size: emCalc(11px)
cursor: pointer

&:hover, &:focus
color: $textColor

.layerTitle
display: flex
align-items: center
cursor: pointer
36 changes: 36 additions & 0 deletions src/scripts/components/layer-list-item/layer-list-item.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React, {FunctionComponent} from 'react';
import {FormattedMessage} from 'react-intl';

import {LayerListItem as LayerListItemType} from '../../types/layer-list';

import styles from './layer-list-item.styl';

interface Props {
layer: LayerListItemType;
isMainSelected: boolean;
onMainSelect: (id: string) => void;
onCompareSelect: (id: string) => void;
}

const LayerListItem: FunctionComponent<Props> = ({
layer,
isMainSelected,
onMainSelect,
onCompareSelect
}) => (
<div className={styles.layerItem} onClick={() => onMainSelect(layer.id)}>
<span className={styles.layerTitle}>{layer.name}</span>
{isMainSelected && (
<button
className={styles.compare}
onClick={event => {
onCompareSelect(layer.id);
event.stopPropagation();
}}>
<FormattedMessage id={'layerSelector.compare'} />
</button>
)}
</div>
);

export default LayerListItem;
25 changes: 1 addition & 24 deletions src/scripts/components/layer-list/layer-list.styl
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,5 @@
overflow: scroll
margin: 0
padding: 0
height: calc(100vh - 80px)
background-color: $darkGrey1
height: 100%
list-style: none

.layerItem
padding: 15px
color: $textDefault
font-size: 1.125em
cursor: pointer

.layerItem:hover, .layerItem:focus
background: $darkGray4
color: $textColor

.layerItemSelected, .layerItemSelected:hover, .layerItemSelected:focus
background: $darkGray4
color: $textColor

.subLayerItem
margin: 5px
padding: 15px

.subLayerItemSelected
background: $darkGray4
color: $textColor
99 changes: 27 additions & 72 deletions src/scripts/components/layer-list/layer-list.tsx
Original file line number Diff line number Diff line change
@@ -1,86 +1,41 @@
import React, {FunctionComponent, MouseEvent} from 'react';
import {useHistory, useParams} from 'react-router';
import cx from 'classnames';
import React, {FunctionComponent} from 'react';

import {LayerList as LayerListType} from '../../types/layer-list';
import LayerListItem from '../layer-list-item/layer-list-item';

import {LayerListItem as LayerListItemType} from '../../types/layer-list';

import styles from './layer-list.styl';

interface Props {
layers: LayerListType;
isMain: boolean;
selectedIds: string[];
layers: LayerListItemType[];
onMainSelect: (id: string) => void;
onCompareSelect: (id: string) => void;
}

const LayerList: FunctionComponent<Props> = ({layers, isMain}) => {
const history = useHistory();
const {mainLayerId = '', compareLayerId = ''} = useParams();
const selectedLayerId = isMain ? mainLayerId : compareLayerId;

const layerClickHandler = (event: MouseEvent, id: string) => {
event.stopPropagation();

if (id === selectedLayerId) {
if (!isMain || !compareLayerId) {
const newPath = isMain ? '/' : `/layers/${mainLayerId}`;
history.push(newPath);
}
return;
}

const newPath = isMain
? `/layers/${id}/${compareLayerId}`
: `/layers/${mainLayerId}/${id}`;

history.push(newPath);
};
const LayerList: FunctionComponent<Props> = ({
selectedIds,
layers,
onMainSelect,
onCompareSelect
}) => {
const [mainId] = selectedIds;
const mainSelected = Boolean(mainId);

return (
<ul className={styles.layerList}>
{layers.map(layer => {
const isSelected = selectedLayerId === layer.id;
const layerItemClasses = cx(
styles.layerItem,
isSelected && styles.layerItemSelected
);

if (layer.subLayers.length === 0) {
return (
<li
className={layerItemClasses}
key={layer.id}
onClick={event => layerClickHandler(event, layer.id)}>
{layer.name}
</li>
);
}

return (
<li className={layerItemClasses} key={layer.id}>
{layer.name}

{layer.subLayers && (
<ul className={styles.subLayersList}>
{layer.subLayers.map(subLayer => {
const isSubSelected = selectedLayerId === subLayer.id;
const subLayerItemClasses = cx(
styles.subLayerItem,
isSubSelected && styles.subLayerItemSelected
);

return (
<li
className={subLayerItemClasses}
onClick={event => layerClickHandler(event, subLayer.id)}
key={subLayer.id}>
{subLayer.name}
</li>
);
})}
</ul>
)}
{layers
.filter(layer => !selectedIds.includes(layer.id))
.map(layer => (
<li key={layer.id}>
<LayerListItem
onMainSelect={id => onMainSelect(id)}
onCompareSelect={id => onCompareSelect(id)}
isMainSelected={mainSelected}
layer={layer}
/>
</li>
);
})}
))}
</ul>
);
};
Expand Down
32 changes: 30 additions & 2 deletions src/scripts/components/layer-selector/layer-selector.styl
Original file line number Diff line number Diff line change
@@ -1,2 +1,30 @@
.layerContainer
padding: 0 10px 0 10px
@require '../../../variables.styl'

.layerSelector
position: absolute
top: 0
right: 0
display: flex
flex-direction: column
min-width: emCalc(300px)
max-width: emCalc(500px)
width: 33%
height: 100%
background-color: $darkGrey2

.header
display: flex
justify-content: space-between
align-items: center
padding: emCalc(24px) emCalc(32px)
background-color: $darkGrey1
color: white

.button
svg
padding: 0

.title
margin: 0
text-transform: uppercase
font-size: emCalc(18px)
Loading

0 comments on commit 8f9d1e5

Please sign in to comment.