tags.js ➔ tagsCard   F
last analyzed

Complexity

Conditions 14

Size

Total Lines 77
Code Lines 45

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 45
dl 0
loc 77
rs 3.6
c 0
b 0
f 0
cc 14

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like tags.js ➔ tagsCard often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
/*
2
    Applies tag to the chosen model
3
4
    @model - string - model name which accepts tags. There must
5
        be a 'MM.add_tag' RPC function for this to work!
6
    @objectId - int - PK of the object that will be tagged
7
    @tagInput - jQuery object - usually an <input> element which
8
        provides the value used for tagging
9
    @toTable - DataTable object - the table which displays the results
10
*/
11
function addTag (model, objectId, tagInput, toTable) {
12
  const tagName = tagInput.value
13
14
  if (tagName.length > 0) {
15
    jsonRPC(model + '.add_tag', [objectId, tagName], function (data) {
0 ignored issues
show
Unused Code introduced by
The parameter data is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
16
      toTable.row.add({ name: tagName }).draw()
17
      $(tagInput).val('')
18
    })
19
  }
20
}
21
22
/*
23
    Displays the tags table inside a card and binds all buttons
24
    and actions for it.
25
26
    @model - string - model name which accepts tags. There must
27
        be a 'MM.add_tag' RPC function for this to work!
28
    @objectId - int - PK of the object that will be tagged
29
    @displayFilter - dict - passed directly to `Tag.filter` to display
30
        tags for @objectId
31
    @permRemove - bool - if we have permission to remove tags
32
33
*/
34
function tagsCard (model, objectId, displayFilter, permRemove) {
35
  // load the tags table
36
  const tagsTable = $('#tags').DataTable({
37
    ajax: function (data, callback, settings) {
0 ignored issues
show
Unused Code introduced by
The parameter settings is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
38
      dataTableJsonRPC('Tag.filter', displayFilter, callback, function (data, callback) {
39
        // b/c tags are now annotated with case, run, plan IDs there are duplicate names.
40
        // Filter them out by only looking at Tag.id uniqueness!
41
        data = arrayToDict(data)
42
        callback({ data: Object.values(data) })
43
      })
44
    },
45
    columns: [
46
      { data: 'name' },
47
      {
48
        data: null,
49
        sortable: false,
50
        render: function (data, type, full, meta) {
0 ignored issues
show
Unused Code introduced by
The parameter type is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
Unused Code introduced by
The parameter full is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
Unused Code introduced by
The parameter meta is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
51
          if (permRemove) {
52
            return '<a href="#tags" class="remove-tag" data-name="' + data.name + '"><span class="pficon-error-circle-o hidden-print"></span></a>'
53
          }
54
          return ''
55
        }
56
      }
57
    ],
58
    dom: 't',
59
    language: {
60
      loadingRecords: '<div class="spinner spinner-lg"></div>',
61
      processing: '<div class="spinner spinner-lg"></div>',
62
      zeroRecords: 'No records found'
63
    },
64
    order: [[0, 'asc']]
65
  })
66
67
  // remove tags button
68
  tagsTable.on('draw', function () {
69
    $('.remove-tag').click(function () {
70
      const tr = $(this).parents('tr')
71
72
      jsonRPC(model + '.remove_tag', [objectId, $(this).data('name')], function (data) {
0 ignored issues
show
Unused Code introduced by
The parameter data is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
73
        tagsTable.row($(tr)).remove().draw()
74
      })
75
    })
76
  })
77
78
  // add tag button and Enter key
79
  $('#add-tag').click(function () {
80
    addTag(model, objectId, $('#id_tags')[0], tagsTable)
81
  })
82
83
  $('#id_tags').keyup(function (event) {
84
    if (event.keyCode === 13) {
85
      addTag(model, objectId, $('#id_tags')[0], tagsTable)
86
    };
87
  })
88
89
  // tag autocomplete
90
  $('#id_tags.typeahead').typeahead({
91
    minLength: 3,
92
    highlight: true
93
  }, {
94
    name: 'tags-autocomplete',
95
    // will display up to X results even if more were returned
96
    limit: 100,
97
    async: true,
98
    display: function (element) {
99
      return element.name
100
    },
101
    source: function (query, processSync, processAsync) {
102
      jsonRPC('Tag.filter', { name__icontains: query }, function (data) {
103
        // b/c tags are now annotated with case, run, plan IDs there are duplicate names.
104
        // Filter them out by only looking at Tag.id uniqueness!
105
        data = arrayToDict(data)
106
        return processAsync(Object.values(data))
107
      })
108
    }
109
  })
110
}
111