mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2024-12-23 01:20:24 +03:00
Implemented behavior to create new short URLs
This commit is contained in:
parent
f7249cfe6e
commit
92f7fffcf3
6 changed files with 73 additions and 20 deletions
|
@ -8,11 +8,15 @@
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bg-main {
|
||||||
|
background-color: $mainColor !important;
|
||||||
|
}
|
||||||
|
|
||||||
.dropdown-item {
|
.dropdown-item {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.dropdown-item.active {
|
.dropdown-item.active {
|
||||||
background-color: $mainColor !important;
|
@extend .bg-main;
|
||||||
}
|
}
|
||||||
|
|
||||||
.short-urls-container {
|
.short-urls-container {
|
||||||
|
|
|
@ -11,7 +11,7 @@ import { Collapse } from 'reactstrap';
|
||||||
import '../../node_modules/react-datepicker/dist/react-datepicker.css';
|
import '../../node_modules/react-datepicker/dist/react-datepicker.css';
|
||||||
import './CreateShortUrl.scss';
|
import './CreateShortUrl.scss';
|
||||||
import CreateShortUrlResult from './helpers/CreateShortUrlResult';
|
import CreateShortUrlResult from './helpers/CreateShortUrlResult';
|
||||||
import { createShortUrl } from './reducers/shortUrlCreationResult';
|
import { createShortUrl, resetCreateShortUrl } from './reducers/shortUrlCreationResult';
|
||||||
|
|
||||||
export class CreateShortUrl extends React.Component {
|
export class CreateShortUrl extends React.Component {
|
||||||
state = {
|
state = {
|
||||||
|
@ -25,6 +25,8 @@ export class CreateShortUrl extends React.Component {
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
const { createShortUrl, shortUrlCreationResult, resetCreateShortUrl } = this.props;
|
||||||
|
|
||||||
const addTag = tag => this.setState({
|
const addTag = tag => this.setState({
|
||||||
tags: [].concat(this.state.tags, assoc('name', replace(/ /g, '-', tag.name), tag))
|
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 formatDate = date => isNil(date) ? date : date.format();
|
||||||
const save = e => {
|
const save = e => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.props.createShortUrl(pipe(
|
createShortUrl(pipe(
|
||||||
dissoc('moreOptionsVisible'), // Remove moreOptionsVisible property
|
dissoc('moreOptionsVisible'), // Remove moreOptionsVisible property
|
||||||
assoc('tags', pluck('name', this.state.tags)), // Map tags array to use only their names
|
assoc('tags', pluck('name', this.state.tags)), // Map tags array to use only their names
|
||||||
assoc('validSince', formatDate(this.state.validSince)),
|
assoc('validSince', formatDate(this.state.validSince)),
|
||||||
|
@ -120,14 +122,22 @@ export class CreateShortUrl extends React.Component {
|
||||||
|
|
||||||
{this.state.moreOptionsVisible ? 'Less' : 'More'} options
|
{this.state.moreOptionsVisible ? 'Less' : 'More'} options
|
||||||
</button>
|
</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>
|
</div>
|
||||||
|
|
||||||
<CreateShortUrlResult {...this.props.shortUrlCreationResult} />
|
<CreateShortUrlResult {...shortUrlCreationResult} resetCreateShortUrl={resetCreateShortUrl} />
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(pick(['shortUrlCreationResult']), { createShortUrl })(CreateShortUrl);
|
export default connect(pick(['shortUrlCreationResult']), {
|
||||||
|
createShortUrl,
|
||||||
|
resetCreateShortUrl
|
||||||
|
})(CreateShortUrl);
|
||||||
|
|
|
@ -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 { 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 }) {
|
export default class CreateShortUrlResult extends React.Component {
|
||||||
if (loading) {
|
state = { showCopyTooltip: false };
|
||||||
return <div className="text-center">Loading...</div>
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.props.resetCreateShortUrl();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error) {
|
render() {
|
||||||
return <div className="text-center color-danger">An error occurred while creating the URL :(</div>
|
const { error, result } = this.props;
|
||||||
}
|
|
||||||
|
|
||||||
if (isNil(result)) {
|
if (error) {
|
||||||
return null;
|
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>
|
||||||
|
);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
4
src/short-urls/helpers/CreateShortUrlResult.scss
Normal file
4
src/short-urls/helpers/CreateShortUrlResult.scss
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
.create-short-url-result__copy-btn {
|
||||||
|
margin-left: 10px;
|
||||||
|
vertical-align: inherit;
|
||||||
|
}
|
|
@ -38,8 +38,8 @@ export class ShortUrlsRow extends React.Component {
|
||||||
display={this.state.displayMenu}
|
display={this.state.displayMenu}
|
||||||
shortUrl={completeShortUrl}
|
shortUrl={completeShortUrl}
|
||||||
onCopyToClipboard={() => {
|
onCopyToClipboard={() => {
|
||||||
this.setState({copiedToClipboard: true});
|
this.setState({ copiedToClipboard: true });
|
||||||
setTimeout(() => this.setState({copiedToClipboard: false}), 2000);
|
setTimeout(() => this.setState({ copiedToClipboard: false }), 2000);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
|
|
|
@ -3,6 +3,7 @@ import ShlinkApiClient from '../../api/ShlinkApiClient';
|
||||||
const CREATE_SHORT_URL_START = 'shlink/createShortUrl/CREATE_SHORT_URL_START';
|
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_ERROR = 'shlink/createShortUrl/CREATE_SHORT_URL_ERROR';
|
||||||
const CREATE_SHORT_URL = 'shlink/createShortUrl/CREATE_SHORT_URL';
|
const CREATE_SHORT_URL = 'shlink/createShortUrl/CREATE_SHORT_URL';
|
||||||
|
const RESET_CREATE_SHORT_URL = 'shlink/createShortUrl/RESET_CREATE_SHORT_URL';
|
||||||
|
|
||||||
const defaultState = {
|
const defaultState = {
|
||||||
result: null,
|
result: null,
|
||||||
|
@ -27,8 +28,10 @@ export default function reducer(state = defaultState, action) {
|
||||||
return {
|
return {
|
||||||
result: action.result,
|
result: action.result,
|
||||||
saving: false,
|
saving: false,
|
||||||
error: true,
|
error: false,
|
||||||
};
|
};
|
||||||
|
case RESET_CREATE_SHORT_URL:
|
||||||
|
return defaultState;
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
@ -44,3 +47,5 @@ export const createShortUrl = data => async dispatch => {
|
||||||
dispatch({ type: CREATE_SHORT_URL_ERROR });
|
dispatch({ type: CREATE_SHORT_URL_ERROR });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const resetCreateShortUrl = () => ({ type: RESET_CREATE_SHORT_URL });
|
||||||
|
|
Loading…
Reference in a new issue