Updated styles in javascript to fulfill adidas rules

This commit is contained in:
Alejandro Celaya
2018-08-25 23:39:27 +02:00
parent ed0aa68452
commit 6a016d8e6f
70 changed files with 1250 additions and 759 deletions

View File

@@ -1,13 +1,14 @@
import Storage from './Storage';
import PropTypes from 'prop-types';
import { range } from 'ramda';
import PropTypes from 'prop-types';
import storage from './Storage';
const HEX_COLOR_LENGTH = 6;
const { floor, random } = Math;
const letters = '0123456789ABCDEF';
const buildRandomColor = () =>
`#${
range(0, 6)
.map(() => letters[floor(random() * 16)])
range(0, HEX_COLOR_LENGTH)
.map(() => letters[floor(random() * letters.length)])
.join('')
}`;
@@ -17,12 +18,13 @@ export class ColorGenerator {
this.colors = this.storage.get('colors') || {};
}
getColorForKey = key => {
getColorForKey = (key) => {
const color = this.colors[key];
// If a color has not been set yet, generate a random one and save it
if (!color) {
this.setColorForKey(key, buildRandomColor());
return this.getColorForKey(key);
}
@@ -40,4 +42,6 @@ export const colorGeneratorType = PropTypes.shape({
setColorForKey: PropTypes.func,
});
export default new ColorGenerator(Storage);
const colorGenerator = new ColorGenerator(storage);
export default colorGenerator;

19
src/utils/ExternalLink.js Normal file
View File

@@ -0,0 +1,19 @@
import React from 'react';
import PropTypes from 'prop-types';
const propTypes = {
href: PropTypes.string.isRequired,
children: PropTypes.node,
};
export default function ExternalLink(props) {
const { href, children, ...rest } = props;
return (
<a target="_blank" rel="noopener noreferrer" href={href} {...rest}>
{children}
</a>
);
}
ExternalLink.propTypes = propTypes;

View File

@@ -1,8 +1,15 @@
import React from 'react';
import { Card } from 'reactstrap';
import classnames from 'classnames';
import PropTypes from 'prop-types';
export default function MutedMessage({ children, marginSize = 4 }) {
const DEFAULT_MARGIN_SIZE = 4;
const propTypes = {
marginSize: PropTypes.number,
children: PropTypes.node,
};
export default function MutedMessage({ children, marginSize = DEFAULT_MARGIN_SIZE }) {
const cardClasses = classnames('bg-light', {
[`mt-${marginSize}`]: marginSize > 0,
});
@@ -17,3 +24,5 @@ export default function MutedMessage({ children, marginSize = 4 }) {
</div>
);
}
MutedMessage.propTypes = propTypes;

View File

@@ -5,6 +5,7 @@ import PropTypes from 'prop-types';
import classnames from 'classnames';
import './SearchField.scss';
const DEFAULT_SEARCH_INTERVAL = 500;
const propTypes = {
onChange: PropTypes.func.isRequired,
className: PropTypes.string,
@@ -19,7 +20,7 @@ export default class SearchField extends React.Component {
state = { showClearBtn: false, searchTerm: '' };
timer = null;
searchTermChanged(searchTerm, timeout = 500) {
searchTermChanged(searchTerm, timeout = DEFAULT_SEARCH_INTERVAL) {
this.setState({
showClearBtn: searchTerm !== '',
searchTerm,
@@ -29,6 +30,7 @@ export default class SearchField extends React.Component {
clearTimeout(this.timer);
this.timer = null;
};
resetTimer();
this.timer = setTimeout(() => {
@@ -46,15 +48,15 @@ export default class SearchField extends React.Component {
type="text"
className="form-control form-control-lg search-field__input"
placeholder={placeholder}
onChange={e => this.searchTermChanged(e.target.value)}
value={this.state.searchTerm}
onChange={(e) => this.searchTermChanged(e.target.value)}
/>
<FontAwesomeIcon icon={searchIcon} className="search-field__icon" />
<div
className="close search-field__close"
hidden={! this.state.showClearBtn}
onClick={() => this.searchTermChanged('', 0)}
hidden={!this.state.showClearBtn}
id="search-field__close"
onClick={() => this.searchTermChanged('', 0)}
>
&times;
</div>

View File

@@ -1,13 +1,14 @@
const PREFIX = 'shlink';
const buildPath = path => `${PREFIX}.${path}`;
const buildPath = (path) => `${PREFIX}.${path}`;
export class Storage {
constructor(localStorage) {
this.localStorage = localStorage;
}
get = key => {
get = (key) => {
const item = this.localStorage.getItem(buildPath(key));
return item ? JSON.parse(item) : undefined;
};
@@ -15,4 +16,5 @@ export class Storage {
}
const storage = typeof localStorage !== 'undefined' ? localStorage : {};
export default new Storage(storage);

View File

@@ -1,15 +1,28 @@
import React from 'react';
import ColorGenerator from '../utils/ColorGenerator';
import PropTypes from 'prop-types';
import colorGenerator, { colorGeneratorType } from '../utils/ColorGenerator';
import './Tag.scss';
export default function Tag (
const propTypes = {
colorGenerator: colorGeneratorType,
text: PropTypes.string,
children: PropTypes.node,
clearable: PropTypes.bool,
onClick: PropTypes.func,
onClose: PropTypes.func,
};
const defaultProps = {
colorGenerator,
};
export default function Tag(
{
colorGenerator,
text,
children,
clearable,
onClick = () => ({}),
onClose = () => ({})
onClose = () => ({}),
}
) {
return (
@@ -24,6 +37,5 @@ export default function Tag (
);
}
Tag.defaultProps = {
colorGenerator: ColorGenerator
};
Tag.defaultProps = defaultProps;
Tag.propTypes = propTypes;

View File

@@ -1,38 +1,41 @@
import React from 'react';
import TagsInput from 'react-tagsinput';
import ColorGenerator, { colorGeneratorType } from './ColorGenerator';
import PropTypes from 'prop-types';
import colorGenerator, { colorGeneratorType } from './ColorGenerator';
const defaultProps = {
colorGenerator: ColorGenerator,
colorGenerator,
placeholder: 'Add tags to the URL',
};
const propTypes = {
tags: PropTypes.arrayOf(PropTypes.string).isRequired,
onChange: PropTypes.func.isRequired,
placeholder: PropTypes.string,
colorGenerator: colorGeneratorType
colorGenerator: colorGeneratorType,
};
export default function TagsSelector({ tags, onChange, placeholder, colorGenerator }) {
const renderTag = (props) => {
const { tag, key, disabled, onRemove, classNameRemove, getTagDisplayValue, ...other } = props;
return (
<span key={key} style={{ backgroundColor: colorGenerator.getColorForKey(tag) }} {...other}>
{getTagDisplayValue(tag)}
{!disabled && <span className={classNameRemove} onClick={() => onRemove(key)} />}
</span>
)
);
};
return (
<TagsInput
value={tags}
onChange={onChange}
inputProps={{ placeholder }}
onlyUnique
addOnBlur // FIXME Workaround to be able to add tags on Android
renderTag={renderTag}
// FIXME Workaround to be able to add tags on Android
addOnBlur
onChange={onChange}
/>
);
}