Created common component to handle tags and modal to edit tags

This commit is contained in:
Alejandro Celaya
2018-08-15 11:14:44 +02:00
parent 707c097ed9
commit 854851fefc
9 changed files with 115 additions and 30 deletions

View File

@@ -4,11 +4,11 @@ import FontAwesomeIcon from '@fortawesome/react-fontawesome';
import { assoc, dissoc, isNil, pick, pipe, replace, trim } from 'ramda';
import React from 'react';
import { connect } from 'react-redux';
import TagsInput from 'react-tagsinput'
import { Collapse } from 'reactstrap';
import DateInput from '../common/DateInput';
import CreateShortUrlResult from './helpers/CreateShortUrlResult';
import { createShortUrl, resetCreateShortUrl } from './reducers/shortUrlCreationResult';
import TagsSelector from '../utils/TagsSelector';
export class CreateShortUrl extends React.Component {
state = {
@@ -68,13 +68,7 @@ export class CreateShortUrl extends React.Component {
<Collapse isOpen={this.state.moreOptionsVisible}>
<div className="form-group">
<TagsInput
value={this.state.tags}
onChange={changeTags}
inputProps={{ placeholder: 'Add tags to the URL' }}
onlyUnique
addOnBlur // FIXME Workaround to be able to add tags on Android
/>
<TagsSelector tags={this.state.tags} onChange={changeTags} />
</div>
<div className="row">

View File

@@ -1,7 +1,7 @@
import caretDownIcon from '@fortawesome/fontawesome-free-solid/faCaretDown'
import caretUpIcon from '@fortawesome/fontawesome-free-solid/faCaretUp'
import FontAwesomeIcon from '@fortawesome/react-fontawesome'
import { head, isEmpty, pick, toPairs } from 'ramda'
import { head, isEmpty, pick, toPairs, keys, values } from 'ramda'
import React from 'react'
import { connect } from 'react-redux'
import { DropdownItem, DropdownMenu, DropdownToggle, UncontrolledDropdown } from 'reactstrap'
@@ -34,7 +34,7 @@ export class ShortUrlsList extends React.Component {
'DESC': undefined,
};
return this.state.orderDir ? newOrderMap[this.state.orderDir] : 'ASC';
}
};
orderBy = field => {
const newOrderDir = this.determineOrderDir(field);
this.setState({ orderField: newOrderDir !== undefined ? field : undefined, orderDir: newOrderDir });
@@ -58,8 +58,8 @@ export class ShortUrlsList extends React.Component {
const { orderBy } = props.shortUrlsListParams;
this.state = {
orderField: orderBy ? head(Object.keys(orderBy)) : undefined,
orderDir: orderBy ? head(Object.values(orderBy)) : undefined,
orderField: orderBy ? head(keys(orderBy)) : undefined,
orderDir: orderBy ? head(values(orderBy)) : undefined,
}
}
@@ -71,7 +71,11 @@ export class ShortUrlsList extends React.Component {
renderShortUrls() {
const { shortUrlsList, selectedServer, loading, error, shortUrlsListParams } = this.props;
if (error) {
return <tr><td colSpan="6" className="text-center table-danger">Something went wrong while loading short URLs :(</td></tr>;
return (
<tr>
<td colSpan="6" className="text-center table-danger">Something went wrong while loading short URLs :(</td>
</tr>
);
}
if (loading) {
@@ -102,7 +106,7 @@ export class ShortUrlsList extends React.Component {
</DropdownToggle>
<DropdownMenu className="short-urls-list__order-dropdown">
{toPairs(SORTABLE_FIELDS).map(([key, value]) =>
<DropdownItem active={this.state.orderField === key} onClick={() => this.orderBy(key)}>
<DropdownItem key={key} active={this.state.orderField === key} onClick={() => this.orderBy(key)}>
{value}
{this.renderOrderIcon(key, 'short-urls-list__header-icon--mobile')}
</DropdownItem>)}

View File

@@ -0,0 +1,27 @@
import React from 'react';
import { Modal, ModalBody, ModalFooter, ModalHeader } from 'reactstrap';
import TagsSelector from '../../utils/TagsSelector';
export default class EditTagsModal extends React.Component {
constructor(props) {
super(props);
this.state = { tags: props.shortUrl.tags };
}
render() {
const { isOpen, toggle, url } = this.props;
const changeTags = tags => this.setState({ tags });
return (
<Modal isOpen={isOpen} toggle={toggle} centered>
<ModalHeader toggle={toggle}>Edit tags for <a target="_blank" href={url}>{url}</a></ModalHeader>
<ModalBody>
<TagsSelector tags={this.state.tags} onChange={changeTags} />
</ModalBody>
<ModalFooter>
<button className="btn btn-outline-primary" type="button">Save</button>
</ModalFooter>
</Modal>
);
}
}

View File

@@ -4,7 +4,7 @@ import './QrCodeModal.scss';
export default function QrCodeModal ({ url, toggle, isOpen }) {
return (
<Modal isOpen={isOpen} toggle={toggle} centered={true}>
<Modal isOpen={isOpen} toggle={toggle} centered>
<ModalHeader toggle={toggle}>QR code for <a target="_blank" href={url}>{url}</a></ModalHeader>
<ModalBody>
<div className="text-center">

View File

@@ -45,9 +45,9 @@ export class ShortUrlsRow extends React.Component {
Copied short URL!
</small>
<ShortUrlsRowMenu
shortUrl={completeShortUrl}
completeShortUrl={completeShortUrl}
selectedServer={selectedServer}
shortCode={shortUrl.shortCode}
shortUrl={shortUrl}
onCopyToClipboard={() => {
this.setState({ copiedToClipboard: true });
setTimeout(() => this.setState({ copiedToClipboard: false }), 2000);

View File

@@ -1,5 +1,6 @@
import copyIcon from '@fortawesome/fontawesome-free-regular/faCopy';
import pictureIcon from '@fortawesome/fontawesome-free-regular/faImage';
import tagsIcon from '@fortawesome/fontawesome-free-solid/faTags';
import pieChartIcon from '@fortawesome/fontawesome-free-solid/faChartPie';
import menuIcon from '@fortawesome/fontawesome-free-solid/faEllipsisV';
import qrIcon from '@fortawesome/fontawesome-free-solid/faQrcode';
@@ -11,16 +12,23 @@ import { ButtonDropdown, DropdownItem, DropdownMenu, DropdownToggle } from 'reac
import PreviewModal from './PreviewModal';
import QrCodeModal from './QrCodeModal';
import './ShortUrlsRowMenu.scss';
import EditTagsModal from './EditTagsModal';
export class ShortUrlsRowMenu extends React.Component {
state = { isOpen: false, isQrModalOpen: false, isPreviewOpen: false };
state = {
isOpen: false,
isQrModalOpen: false,
isPreviewOpen: false,
isTagsModalOpen: false,
};
toggle = () => this.setState({ isOpen: !this.state.isOpen });
render() {
const { shortUrl, onCopyToClipboard, selectedServer, shortCode } = this.props;
const { completeShortUrl, onCopyToClipboard, selectedServer, shortUrl } = this.props;
const serverId = selectedServer ? selectedServer.id : '';
const toggleQrCode = () => this.setState({isQrModalOpen: !this.state.isQrModalOpen});
const togglePreview = () => this.setState({isPreviewOpen: !this.state.isPreviewOpen});
const toggleTags = () => this.setState({isTagsModalOpen: !this.state.isTagsModalOpen});
return (
<ButtonDropdown toggle={this.toggle} isOpen={this.state.isOpen} direction="left">
@@ -28,9 +36,18 @@ export class ShortUrlsRowMenu extends React.Component {
&nbsp;<FontAwesomeIcon icon={menuIcon}/>&nbsp;
</DropdownToggle>
<DropdownMenu>
<DropdownItem tag={Link} to={`/server/${serverId}/short-code/${shortCode}/visits`}>
<DropdownItem tag={Link} to={`/server/${serverId}/short-code/${shortUrl.shortCode}/visits`}>
<FontAwesomeIcon icon={pieChartIcon}/> &nbsp;Visit Stats
</DropdownItem>
<DropdownItem onClick={toggleTags}>
<FontAwesomeIcon icon={tagsIcon}/> &nbsp;Edit tags
</DropdownItem>
<EditTagsModal
url={completeShortUrl}
shortUrl={shortUrl}
isOpen={this.state.isTagsModalOpen}
toggle={toggleTags}
/>
<DropdownItem divider/>
@@ -38,7 +55,7 @@ export class ShortUrlsRowMenu extends React.Component {
<FontAwesomeIcon icon={pictureIcon}/> &nbsp;Preview
</DropdownItem>
<PreviewModal
url={shortUrl}
url={completeShortUrl}
isOpen={this.state.isPreviewOpen}
toggle={togglePreview}
/>
@@ -47,14 +64,14 @@ export class ShortUrlsRowMenu extends React.Component {
<FontAwesomeIcon icon={qrIcon}/> &nbsp;QR code
</DropdownItem>
<QrCodeModal
url={shortUrl}
url={completeShortUrl}
isOpen={this.state.isQrModalOpen}
toggle={toggleQrCode}
/>
<DropdownItem divider/>
<CopyToClipboard text={shortUrl} onCopy={onCopyToClipboard}>
<CopyToClipboard text={completeShortUrl} onCopy={onCopyToClipboard}>
<DropdownItem>
<FontAwesomeIcon icon={copyIcon}/> &nbsp;Copy to clipboard
</DropdownItem>