kiwitcms/Kiwi

View on GitHub
tcms/static/js/tags.js

Summary

Maintainability
A
3 hrs
Test Coverage
import { jsonRPC, dataTableJsonRPC } from './jsonrpc'
import { arrayToDict } from './utils'

/*
    Applies tag to the chosen model

    @model - string - model name which accepts tags. There must
        be a 'MM.add_tag' RPC function for this to work!
    @objectId - int - PK of the object that will be tagged
    @tagInput - jQuery object - usually an <input> element which
        provides the value used for tagging
    @toTable - DataTable object - the table which displays the results
*/
export function addTag (model, objectId, tagInput, toTable) {
    const tagName = tagInput.value

    if (tagName.length > 0) {
        jsonRPC(model + '.add_tag', [objectId, tagName], function (data) {
            toTable.row.add({ name: tagName }).draw()
            $(tagInput).val('')
        })
    }
}

/*
    Displays the tags table inside a card and binds all buttons
    and actions for it.

    @model - string - model name which accepts tags. There must
        be a 'MM.add_tag' RPC function for this to work!
    @objectId - int - PK of the object that will be tagged
    @displayFilter - dict - passed directly to `Tag.filter` to display
        tags for @objectId
    @permRemove - bool - if we have permission to remove tags

*/
export function tagsCard (model, objectId, displayFilter, permRemove) {
    // load the tags table
    const tagsTable = $('#tags').DataTable({
        ajax: function (data, callbackF, settings) {
            dataTableJsonRPC('Tag.filter', displayFilter, callbackF, function (data, callback) {
                // b/c tags are now annotated with case, run, plan IDs there are duplicate names.
                // Filter them out by only looking at Tag.id uniqueness!
                data = arrayToDict(data)
                callbackF({ data: Object.values(data) })
            })
        },
        columns: [
            { data: 'name' },
            {
                data: null,
                sortable: false,
                render: function (data, type, full, meta) {
                    if (permRemove) {
                        return '<a href="#tags" class="remove-tag" data-name="' + data.name + '"><span class="pficon-error-circle-o hidden-print"></span></a>'
                    }
                    return ''
                }
            }
        ],
        dom: 't',
        language: {
            loadingRecords: '<div class="spinner spinner-lg"></div>',
            processing: '<div class="spinner spinner-lg"></div>',
            zeroRecords: 'No records found'
        },
        order: [[0, 'asc']]
    })

    // remove tags button
    tagsTable.on('draw', function () {
        $('.remove-tag').click(function () {
            const tr = $(this).parents('tr')

            jsonRPC(model + '.remove_tag', [objectId, $(this).data('name')], function (data) {
                tagsTable.row($(tr)).remove().draw()
            })
        })
    })

    // add tag button and Enter key
    $('#add-tag').click(function () {
        addTag(model, objectId, $('#id_tags')[0], tagsTable)
    })

    $('#id_tags').keyup(function (event) {
        if (event.keyCode === 13) {
            addTag(model, objectId, $('#id_tags')[0], tagsTable)
        };
    })

    // tag autocomplete
    $('#id_tags.typeahead').typeahead({
        minLength: 3,
        highlight: true
    }, {
        name: 'tags-autocomplete',
        // will display up to X results even if more were returned
        limit: 100,
        async: true,
        display: function (element) {
            return element.name
        },
        source: function (query, processSync, processAsync) {
            jsonRPC('Tag.filter', { name__icontains: query }, function (data) {
                // b/c tags are now annotated with case, run, plan IDs there are duplicate names.
                // Filter them out by only looking at Tag.id uniqueness!
                data = arrayToDict(data)
                return processAsync(Object.values(data))
            })
        }
    })
}