2018-07-22 09:36:46 +03:00
|
|
|
import calendarIcon from '@fortawesome/fontawesome-free-regular/faCalendarAlt';
|
2018-07-21 11:38:54 +03:00
|
|
|
import downIcon from '@fortawesome/fontawesome-free-solid/faAngleDoubleDown';
|
|
|
|
import upIcon from '@fortawesome/fontawesome-free-solid/faAngleDoubleUp';
|
|
|
|
import FontAwesomeIcon from '@fortawesome/react-fontawesome';
|
2018-07-28 19:59:32 +03:00
|
|
|
import { assoc, dissoc, isNil, pick, pipe, pluck, replace } from 'ramda';
|
2018-07-21 20:27:00 +03:00
|
|
|
import React from 'react';
|
2018-07-21 20:07:16 +03:00
|
|
|
import DatePicker from 'react-datepicker';
|
2018-07-28 19:59:32 +03:00
|
|
|
import { connect } from 'react-redux';
|
2018-07-21 11:38:54 +03:00
|
|
|
import ReactTags from 'react-tag-autocomplete';
|
2018-07-21 20:27:00 +03:00
|
|
|
import { Collapse } from 'reactstrap';
|
|
|
|
import '../../node_modules/react-datepicker/dist/react-datepicker.css';
|
2018-07-21 20:07:16 +03:00
|
|
|
import './CreateShortUrl.scss';
|
2018-07-28 11:41:05 +03:00
|
|
|
import CreateShortUrlResult from './helpers/CreateShortUrlResult';
|
|
|
|
import { createShortUrl } from './reducers/shortUrlCreationResult';
|
2018-07-20 23:32:50 +03:00
|
|
|
|
2018-07-28 11:41:05 +03:00
|
|
|
export class CreateShortUrl extends React.Component {
|
2018-07-21 11:38:54 +03:00
|
|
|
state = {
|
|
|
|
longUrl: '',
|
|
|
|
tags: [],
|
2018-07-21 20:27:00 +03:00
|
|
|
customSlug: undefined,
|
|
|
|
validSince: undefined,
|
|
|
|
validUntil: undefined,
|
|
|
|
maxVisits: undefined,
|
2018-07-21 11:38:54 +03:00
|
|
|
moreOptionsVisible: false
|
|
|
|
};
|
|
|
|
|
|
|
|
render() {
|
|
|
|
const addTag = tag => this.setState({
|
|
|
|
tags: [].concat(this.state.tags, assoc('name', replace(/ /g, '-', tag.name), tag))
|
|
|
|
});
|
|
|
|
const removeTag = i => {
|
|
|
|
const tags = this.state.tags.slice(0);
|
|
|
|
tags.splice(i, 1);
|
|
|
|
this.setState({ tags });
|
|
|
|
};
|
|
|
|
const renderOptionalInput = (id, placeholder, type = 'text', props = {}) =>
|
|
|
|
<input
|
|
|
|
className="form-control"
|
|
|
|
type={type}
|
|
|
|
placeholder={placeholder}
|
|
|
|
value={this.state[id]}
|
|
|
|
onChange={e => this.setState({ [id]: e.target.value })}
|
|
|
|
{...props}
|
|
|
|
/>;
|
2018-07-28 10:34:31 +03:00
|
|
|
const createDateInput = (id, placeholder, props = {}) =>
|
|
|
|
<DatePicker
|
|
|
|
selected={this.state[id]}
|
|
|
|
className="form-control create-short-url__date-input"
|
|
|
|
placeholderText={placeholder}
|
|
|
|
onChange={date => this.setState({ [id]: date })}
|
|
|
|
dateFormat="YYYY-MM-DD"
|
|
|
|
readOnly
|
|
|
|
{...props}
|
|
|
|
/>;
|
2018-07-28 19:59:32 +03:00
|
|
|
const formatDate = date => isNil(date) ? date : date.format();
|
2018-07-28 11:41:05 +03:00
|
|
|
const save = e => {
|
|
|
|
e.preventDefault();
|
2018-07-28 19:59:32 +03:00
|
|
|
this.props.createShortUrl(pipe(
|
|
|
|
dissoc('moreOptionsVisible'), // Remove moreOptionsVisible property
|
|
|
|
assoc('tags', pluck('name', this.state.tags)), // Map tags array to use only their names
|
|
|
|
assoc('validSince', formatDate(this.state.validSince)),
|
|
|
|
assoc('validUntil', formatDate(this.state.validUntil))
|
|
|
|
)(this.state));
|
2018-07-28 11:41:05 +03:00
|
|
|
};
|
2018-07-21 11:38:54 +03:00
|
|
|
|
|
|
|
return (
|
|
|
|
<div className="short-urls-container">
|
2018-07-28 11:41:05 +03:00
|
|
|
<form onSubmit={save}>
|
2018-07-21 11:38:54 +03:00
|
|
|
<div className="form-group">
|
|
|
|
<input
|
|
|
|
className="form-control form-control-lg"
|
|
|
|
type="url"
|
|
|
|
placeholder="Insert the URL to be shortened"
|
|
|
|
required
|
|
|
|
value={this.state.longUrl}
|
|
|
|
onChange={e => this.setState({ longUrl: e.target.value })}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<Collapse isOpen={this.state.moreOptionsVisible}>
|
|
|
|
<div className="form-group">
|
|
|
|
<ReactTags
|
|
|
|
tags={this.state.tags}
|
|
|
|
handleAddition={addTag}
|
|
|
|
handleDelete={removeTag}
|
|
|
|
allowNew={true}
|
|
|
|
placeholder="Add tags you want to apply to the URL"
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div className="row">
|
|
|
|
<div className="col-sm-6">
|
|
|
|
<div className="form-group">
|
|
|
|
{renderOptionalInput('customSlug', 'Custom slug')}
|
|
|
|
</div>
|
|
|
|
<div className="form-group">
|
|
|
|
{renderOptionalInput('maxVisits', 'Maximum number of visits allowed', 'number', { min: 1 })}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div className="col-sm-6">
|
2018-07-21 20:27:00 +03:00
|
|
|
<div className="form-group create-short-url__date-container">
|
|
|
|
{createDateInput('validSince', 'Enabled since...', { maxDate: this.state.validUntil })}
|
|
|
|
<FontAwesomeIcon icon={calendarIcon} className="create-short-url__date-icon" />
|
2018-07-21 11:38:54 +03:00
|
|
|
</div>
|
2018-07-21 20:27:00 +03:00
|
|
|
<div className="form-group create-short-url__date-container">
|
|
|
|
{createDateInput('validUntil', 'Enabled until...', { minDate: this.state.validSince })}
|
|
|
|
<FontAwesomeIcon icon={calendarIcon} className="create-short-url__date-icon" />
|
2018-07-21 11:38:54 +03:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</Collapse>
|
|
|
|
|
|
|
|
<div>
|
|
|
|
<button
|
|
|
|
type="button"
|
|
|
|
className="btn btn-outline-secondary create-short-url__btn"
|
|
|
|
onClick={() => this.setState({ moreOptionsVisible: !this.state.moreOptionsVisible })}
|
|
|
|
>
|
|
|
|
<FontAwesomeIcon icon={this.state.moreOptionsVisible ? upIcon : downIcon} />
|
|
|
|
|
|
|
|
{this.state.moreOptionsVisible ? 'Less' : 'More'} options
|
|
|
|
</button>
|
|
|
|
<button className="btn btn-outline-primary create-short-url__btn float-right">Create</button>
|
|
|
|
</div>
|
2018-07-28 11:41:05 +03:00
|
|
|
|
2018-07-28 19:59:32 +03:00
|
|
|
<CreateShortUrlResult {...this.props.shortUrlCreationResult} />
|
2018-07-21 11:38:54 +03:00
|
|
|
</form>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
2018-07-20 23:32:50 +03:00
|
|
|
}
|
2018-07-28 11:41:05 +03:00
|
|
|
|
|
|
|
export default connect(pick(['shortUrlCreationResult']), { createShortUrl })(CreateShortUrl);
|