Completed
Push — master ( 158ed8...34f194 )
by Alejandro
04:53 queued 02:19
created

src/short-urls/CreateShortUrl.js   A

Complexity

Total Complexity 5
Complexity/F 5

Size

Lines of Code 135
Function Count 1

Duplication

Duplicated Lines 0
Ratio 0 %

Test Coverage

Coverage 88.89%

Importance

Changes 0
Metric Value
wmc 5
eloc 121
mnd 4
bc 4
fnc 1
dl 0
loc 135
ccs 16
cts 18
cp 0.8889
rs 10
bpm 4
cpm 5
noi 0
c 0
b 0
f 0

1 Function

Rating   Name   Duplication   Size   Complexity  
C CreateShortUrl.js ➔ render 0 98 5
1
import { faAngleDoubleDown as downIcon, faAngleDoubleUp as upIcon } from '@fortawesome/free-solid-svg-icons';
2
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
3
import { assoc, dissoc, isNil, pipe, replace, trim } from 'ramda';
4
import React from 'react';
5
import { Collapse } from 'reactstrap';
6
import * as PropTypes from 'prop-types';
7
import DateInput from '../utils/DateInput';
8
import Checkbox from '../utils/Checkbox';
9
import { createShortUrlResultType } from './reducers/shortUrlCreation';
10
import UseExistingIfFoundInfoIcon from './UseExistingIfFoundInfoIcon';
11
12 1
const normalizeTag = pipe(trim, replace(/ /g, '-'));
13 2
const formatDate = (date) => isNil(date) ? date : date.format();
14
15 1
const CreateShortUrl = (TagsSelector, CreateShortUrlResult) => class CreateShortUrl extends React.Component {
16
  static propTypes = {
17
    createShortUrl: PropTypes.func,
18
    shortUrlCreationResult: createShortUrlResultType,
19
    resetCreateShortUrl: PropTypes.func,
20
  };
21
22
  state = {
23
    longUrl: '',
24
    tags: [],
25
    customSlug: undefined,
26
    validSince: undefined,
27
    validUntil: undefined,
28
    maxVisits: undefined,
29
    findIfExists: false,
30
    moreOptionsVisible: false,
31
  };
32
33
  render() {
34 7
    const { createShortUrl, shortUrlCreationResult, resetCreateShortUrl } = this.props;
35
36 7
    const changeTags = (tags) => this.setState({ tags: tags.map(normalizeTag) });
37 7
    const renderOptionalInput = (id, placeholder, type = 'text', props = {}) => (
38 14
      <div className="form-group">
39
        <input
40
          className="form-control"
41
          id={id}
42
          type={type}
43
          placeholder={placeholder}
44
          value={this.state[id]}
45 2
          onChange={(e) => this.setState({ [id]: e.target.value })}
46
          {...props}
47
        />
48
      </div>
49
    );
50 7
    const renderDateInput = (id, placeholder, props = {}) => (
51 14
      <div className="form-group">
52
        <DateInput
53
          selected={this.state[id]}
54
          placeholderText={placeholder}
55
          isClearable
56 2
          onChange={(date) => this.setState({ [id]: date })}
57
          {...props}
58
        />
59
      </div>
60
    );
61 7
    const save = (e) => {
62 1
      e.preventDefault();
63 1
      createShortUrl(pipe(
64
        dissoc('moreOptionsVisible'),
65
        assoc('validSince', formatDate(this.state.validSince)),
66
        assoc('validUntil', formatDate(this.state.validUntil))
67
      )(this.state));
68
    };
69
70 7
    return (
71
      <div className="shlink-container">
72
        <form onSubmit={save}>
73
          <div className="form-group">
74
            <input
75
              className="form-control form-control-lg"
76
              type="url"
77
              placeholder="Insert the URL to be shortened"
78
              required
79
              value={this.state.longUrl}
80 1
              onChange={(e) => this.setState({ longUrl: e.target.value })}
81
            />
82
          </div>
83
84
          <Collapse isOpen={this.state.moreOptionsVisible}>
85
            <div className="form-group">
86
              <TagsSelector tags={this.state.tags} onChange={changeTags} />
87
            </div>
88
89
            <div className="row">
90
              <div className="col-sm-6">
91
                {renderOptionalInput('customSlug', 'Custom slug')}
92
                {renderOptionalInput('maxVisits', 'Maximum number of visits allowed', 'number', { min: 1 })}
93
              </div>
94
              <div className="col-sm-6">
95
                {renderDateInput('validSince', 'Enabled since...', { maxDate: this.state.validUntil })}
96
                {renderDateInput('validUntil', 'Enabled until...', { minDate: this.state.validSince })}
97
              </div>
98
            </div>
99
100
            <div className="mb-3 text-right">
101
              <Checkbox
102
                className="mr-2"
103
                checked={this.state.findIfExists}
104
                onChange={(findIfExists) => this.setState({ findIfExists })}
105
              >
106
                Use existing URL if found
107
              </Checkbox>
108
              <UseExistingIfFoundInfoIcon />
109
            </div>
110
          </Collapse>
111
112
          <div>
113
            <button
114
              type="button"
115
              className="btn btn-outline-secondary"
116
              onClick={() => this.setState(({ moreOptionsVisible }) => ({ moreOptionsVisible: !moreOptionsVisible }))}
117
            >
118
              <FontAwesomeIcon icon={this.state.moreOptionsVisible ? upIcon : downIcon} />
119
              &nbsp;
120
              {this.state.moreOptionsVisible ? 'Less' : 'More'} options
121
            </button>
122
            <button className="btn btn-outline-primary float-right" disabled={shortUrlCreationResult.loading}>
123
              {shortUrlCreationResult.loading ? 'Creating...' : 'Create'}
124
            </button>
125
          </div>
126
127
          <CreateShortUrlResult {...shortUrlCreationResult} resetCreateShortUrl={resetCreateShortUrl} />
128
        </form>
129
      </div>
130
    );
131
  }
132
};
133
134
export default CreateShortUrl;
135