diff --git a/package.json b/package.json index c3c66806..c5b4ce38 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ "react-moment": "^0.7.6", "react-redux": "^5.0.7", "react-router-dom": "^4.2.2", + "react-tag-autocomplete": "^5.5.1", "reactstrap": "^6.0.1", "redux": "^4.0.0", "redux-thunk": "^2.3.0", diff --git a/src/short-urls/CreateShortUrl.js b/src/short-urls/CreateShortUrl.js index 1e31b93b..1fa25940 100644 --- a/src/short-urls/CreateShortUrl.js +++ b/src/short-urls/CreateShortUrl.js @@ -1,5 +1,102 @@ import React from 'react'; +import './CreateShortUrl.scss'; +import downIcon from '@fortawesome/fontawesome-free-solid/faAngleDoubleDown'; +import upIcon from '@fortawesome/fontawesome-free-solid/faAngleDoubleUp'; +import FontAwesomeIcon from '@fortawesome/react-fontawesome'; +import { Collapse } from 'reactstrap'; +import ReactTags from 'react-tag-autocomplete'; +import { assoc, replace } from 'ramda'; -export default function CreateShortUrl() { - return
Create short URL
+export default class CreateShortUrl extends React.Component { + state = { + longUrl: '', + tags: [], + customSlug: null, + validSince: null, + validUntil: null, + maxVisits: null, + 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 = {}) => + this.setState({ [id]: e.target.value })} + {...props} + />; + + return ( +
+
e.preventDefault()}> +
+ this.setState({ longUrl: e.target.value })} + /> +
+ + +
+ +
+ +
+
+
+ {renderOptionalInput('customSlug', 'Custom slug')} +
+
+ {renderOptionalInput('maxVisits', 'Maximum number of visits allowed', 'number', { min: 1 })} +
+
+
+
+ {renderOptionalInput('validSince', 'Enabled since...', 'date')} +
+
+ {renderOptionalInput('validUntil', 'Enabled until...', 'date')} +
+
+
+
+ +
+ + +
+
+
+ ); + } } diff --git a/src/short-urls/CreateShortUrl.scss b/src/short-urls/CreateShortUrl.scss new file mode 100644 index 00000000..c9c2a488 --- /dev/null +++ b/src/short-urls/CreateShortUrl.scss @@ -0,0 +1,19 @@ +@import "../../node_modules/react-tag-autocomplete/example/styles.css"; +@import "../utils/mixins/box-shadow"; +@import "../utils/mixins/border-radius"; + +.create-short-url__btn:not(:first-child) { + margin-left: 5px; +} + +.react-tags { + @include border-radius(.25rem); + transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out, -webkit-box-shadow .15s ease-in-out; +} +.react-tags.is-focused { + color: #495057; + background-color: #fff; + border-color: #80bdff; + outline: 0; + @include box-shadow(0 0 0 0.2rem rgba(0,123,255,.25)); +} diff --git a/src/short-urls/ShortUrlsList.js b/src/short-urls/ShortUrlsList.js index 9c25f711..827dcb14 100644 --- a/src/short-urls/ShortUrlsList.js +++ b/src/short-urls/ShortUrlsList.js @@ -44,6 +44,7 @@ export class ShortUrlsList extends React.Component { renderShortUrls() { const { shortUrlsList, selectedServer, loading } = this.props; + console.log('Is loading?: ', loading); if (loading) { return Loading...; } diff --git a/src/short-urls/reducers/shortUrlsList.js b/src/short-urls/reducers/shortUrlsList.js index d7027247..26a5ffe4 100644 --- a/src/short-urls/reducers/shortUrlsList.js +++ b/src/short-urls/reducers/shortUrlsList.js @@ -27,6 +27,7 @@ export default function reducer(state = initialState, action) { export const listShortUrls = (serverId, params = {}) => { return async dispatch => { + dispatch({ type: LIST_SHORT_URLS_START }); const selectedServer = ServersService.findServerById(serverId); ShlinkApiClient.setConfig(selectedServer); diff --git a/src/utils/mixins/border-radius.scss b/src/utils/mixins/border-radius.scss index 3c034fee..7523e870 100644 --- a/src/utils/mixins/border-radius.scss +++ b/src/utils/mixins/border-radius.scss @@ -1,5 +1,4 @@ @mixin border-radius($radius) { border-radius: $radius; -webkit-border-radius: $radius; - -moz-border-radius: $radius; } diff --git a/src/utils/mixins/box-shadow.scss b/src/utils/mixins/box-shadow.scss new file mode 100644 index 00000000..464f8ece --- /dev/null +++ b/src/utils/mixins/box-shadow.scss @@ -0,0 +1,4 @@ +@mixin box-shadow($shadow) { + -webkit-box-shadow: $shadow; + box-shadow: $shadow; +} diff --git a/yarn.lock b/yarn.lock index 68d4a393..842cba52 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6152,6 +6152,10 @@ react-router@^4.3.1: prop-types "^15.6.1" warning "^4.0.1" +react-tag-autocomplete@^5.5.1: + version "5.5.1" + resolved "https://registry.yarnpkg.com/react-tag-autocomplete/-/react-tag-autocomplete-5.5.1.tgz#6b3f253d3d69eb546925118cdf43138a9aafe113" + react-test-renderer@^16.0.0-0: version "16.4.1" resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.4.1.tgz#f2fb30c2c7b517db6e5b10ed20bb6b0a7ccd8d70"