Implemented behavior to create new short URLs

This commit is contained in:
Alejandro Celaya 2018-07-29 18:13:18 +02:00
parent f7249cfe6e
commit 92f7fffcf3
6 changed files with 73 additions and 20 deletions

View file

@ -8,11 +8,15 @@
white-space: nowrap;
}
.bg-main {
background-color: $mainColor !important;
}
.dropdown-item {
cursor: pointer;
}
.dropdown-item.active {
background-color: $mainColor !important;
@extend .bg-main;
}
.short-urls-container {

View file

@ -11,7 +11,7 @@ import { Collapse } from 'reactstrap';
import '../../node_modules/react-datepicker/dist/react-datepicker.css';
import './CreateShortUrl.scss';
import CreateShortUrlResult from './helpers/CreateShortUrlResult';
import { createShortUrl } from './reducers/shortUrlCreationResult';
import { createShortUrl, resetCreateShortUrl } from './reducers/shortUrlCreationResult';
export class CreateShortUrl extends React.Component {
state = {
@ -25,6 +25,8 @@ export class CreateShortUrl extends React.Component {
};
render() {
const { createShortUrl, shortUrlCreationResult, resetCreateShortUrl } = this.props;
const addTag = tag => this.setState({
tags: [].concat(this.state.tags, assoc('name', replace(/ /g, '-', tag.name), tag))
});
@ -55,7 +57,7 @@ export class CreateShortUrl extends React.Component {
const formatDate = date => isNil(date) ? date : date.format();
const save = e => {
e.preventDefault();
this.props.createShortUrl(pipe(
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)),
@ -120,14 +122,22 @@ export class CreateShortUrl extends React.Component {
 
{this.state.moreOptionsVisible ? 'Less' : 'More'} options
</button>
<button className="btn btn-outline-primary create-short-url__btn float-right">Create</button>
<button
className="btn btn-outline-primary create-short-url__btn float-right"
disabled={shortUrlCreationResult.loading}
>
{shortUrlCreationResult.loading ? 'Creating...' : 'Create'}
</button>
</div>
<CreateShortUrlResult {...this.props.shortUrlCreationResult} />
<CreateShortUrlResult {...shortUrlCreationResult} resetCreateShortUrl={resetCreateShortUrl} />
</form>
</div>
);
}
}
export default connect(pick(['shortUrlCreationResult']), { createShortUrl })(CreateShortUrl);
export default connect(pick(['shortUrlCreationResult']), {
createShortUrl,
resetCreateShortUrl
})(CreateShortUrl);

View file

@ -1,18 +1,48 @@
import React from 'react';
import copyIcon from '@fortawesome/fontawesome-free-regular/faCopy';
import FontAwesomeIcon from '@fortawesome/react-fontawesome';
import { isNil } from 'ramda';
import React from 'react';
import { CopyToClipboard } from 'react-copy-to-clipboard';
import './CreateShortUrlResult.scss'
import { Tooltip } from 'reactstrap';
export default function CreateShortUrlResult ({ loading, error, result }) {
if (loading) {
return <div className="text-center">Loading...</div>
export default class CreateShortUrlResult extends React.Component {
state = { showCopyTooltip: false };
componentDidMount() {
this.props.resetCreateShortUrl();
}
render() {
const { error, result } = this.props;
if (error) {
return <div className="text-center color-danger">An error occurred while creating the URL :(</div>
return <div className="alert bg-danger text-white mt-3">An error occurred while creating the URL :(</div>
}
if (isNil(result)) {
return null;
}
return <div className="text-center">Great!</div>;
const { shortUrl } = result;
const onCopy = () => {
this.setState({ showCopyTooltip: true });
setTimeout(() => this.setState({ showCopyTooltip: false }), 2000);
};
return (
<div className="alert bg-main text-white mt-3">
<b>Great!</b> The short URL is <b>{shortUrl}</b>
<CopyToClipboard text={shortUrl} onCopy={onCopy}>
<button className="btn btn-light btn-sm create-short-url-result__copy-btn" id="copyBtn">
<FontAwesomeIcon icon={copyIcon}/> Copy
</button>
</CopyToClipboard>
<Tooltip placement="left" isOpen={this.state.showCopyTooltip} target="copyBtn">
Copied!
</Tooltip>
</div>
);
}
};

View file

@ -0,0 +1,4 @@
.create-short-url-result__copy-btn {
margin-left: 10px;
vertical-align: inherit;
}

View file

@ -3,6 +3,7 @@ import ShlinkApiClient from '../../api/ShlinkApiClient';
const CREATE_SHORT_URL_START = 'shlink/createShortUrl/CREATE_SHORT_URL_START';
const CREATE_SHORT_URL_ERROR = 'shlink/createShortUrl/CREATE_SHORT_URL_ERROR';
const CREATE_SHORT_URL = 'shlink/createShortUrl/CREATE_SHORT_URL';
const RESET_CREATE_SHORT_URL = 'shlink/createShortUrl/RESET_CREATE_SHORT_URL';
const defaultState = {
result: null,
@ -27,8 +28,10 @@ export default function reducer(state = defaultState, action) {
return {
result: action.result,
saving: false,
error: true,
error: false,
};
case RESET_CREATE_SHORT_URL:
return defaultState;
default:
return state;
}
@ -44,3 +47,5 @@ export const createShortUrl = data => async dispatch => {
dispatch({ type: CREATE_SHORT_URL_ERROR });
}
};
export const resetCreateShortUrl = () => ({ type: RESET_CREATE_SHORT_URL });