declare let $: any; const DATA_FIELD_ARRAY_NAMES = [ '.mmui-data-fields', '.mmui-data-field-rows', '.mmui-data-field-columns', '.mmui-data-field-filters', '.mmui-data-field-values', ]; /** * This functions returns an empty state list item element given a css class name * The class name corresponds to the dimensions, dimension levels and pivot columns * @param name - class name * @returns a list item element */ const getEmptyState = function (name) { let msg; if (name == '.mmui-data-fields') { msg = 'n available data field'; } else if (name == '.mmui-data-field-rows') { msg = ' horizontal row'; } else if (name == '.mmui-data-field-columns') { msg = ' vertical column'; } else if (name == '.mmui-data-field-filters') { msg = ' data filter'; } else { msg = ' value'; } return `
No ${filterTypeDisplay} matching "${searchText}"
` ); } else { $(`#${this.parentId} #empty-data-field-msg`).remove(); } } sortOut() { this.outside = true; } sortOver() { this.outside = false; } removeDraggedOutItem(evt, ui) { const emptyDataFieldItem = $( `#${this.parentId} > * .mmui-data-fields li[id="empty"]` ); if (emptyDataFieldItem) { emptyDataFieldItem.remove(); } const item = $(ui.item); if (this.outside && !evt.target.className.includes('mmui-data-fields')) { const dataValue = item.attr('data-value'); const dataLabel = item.attr('data-label'); const dataType = item.attr('data-type'); const dataFields = $(`#${this.parentId} ul[class~="mmui-data-fields"]`); const existInDataFields = dataFields.find(`li[data-value="${dataValue}"]`).length > 0; if (!existInDataFields) { const newElmt = this.createDataFieldItem( dataLabel, dataValue, dataType ); dataFields.append(newElmt); } item.remove(); } } changeSearchMode(evt) { const searchBadges = [ `#${this.parentId} #data-field-filter-all`, `#${this.parentId} #data-field-filter-metric`, `#${this.parentId} #data-field-filter-attribute`, ]; const target = $(evt.target); const id = target.attr('id'); for (let i = 0; i < searchBadges.length; i++) { const badge = $(searchBadges[i]); if (badge.attr('id') != id) { badge.removeClass('badge-primary'); badge.addClass('mmui-badge-muted'); } else { badge.removeClass('mmui-badge-muted'); badge.addClass('badge-primary'); } } const emptyDataFieldItem = $( `#${this.parentId} > * .mmui-data-fields li[id="empty"]` ); const dataFields = $( `#${this.parentId} > * .mmui-data-fields li[class=mmui-data-field]` ); if (dataFields.length < 1) { emptyDataFieldItem.css('display', 'block'); } else { emptyDataFieldItem.css('display', 'none'); for (let i = 0; i < dataFields.length; i++) { $(dataFields[i]).css('display', 'list-item'); } } this.formatDataFieldList(); } formatDataFieldList() { const dataFields = $(`#${this.parentId} > * .badge-primary`).attr('id'); $(`#${this.parentId} .mmui-data-fields > li`).each((index, dataField) => { dataField = $(dataField); const dataFieldText = dataField .find('span.mmui-data-field-label') .text() .toLowerCase(); const searchText = $(`#${this.parentId} .mmui-data-field-search`) .val() .toLowerCase(); if ( (dataFields.includes(dataField.attr('data-type')) || dataFields == 'data-field-filter-all') && dataFieldText.includes(searchText) ) { dataField.css('display', 'list-item'); } else { dataField.css('display', 'none'); } }); } setBorder(evt, ui) { const dataType = $(ui.item).attr('data-type'); const dataValue = $(ui.item).attr('data-value'); if (dataType === 'attribute') { const rows = this.selectElmt('rows'); const columns = this.selectElmt('columns'); const filters = this.selectElmt('filters'); if (rows.find(`li[data-value="${dataValue}"]`).length < 1) { rows.parent().addClass('mmui-highlighted-dimension-drop'); } if (columns.find(`li[data-value="${dataValue}"]`).length < 1) { columns.parent().addClass('mmui-highlighted-dimension-drop'); } if (filters.find(`li[data-value="${dataValue}"]`).length < 1) { filters.parent().addClass('mmui-highlighted-dimension-drop'); } } if (dataType === 'metric') { const values = this.selectElmt('values'); if (values.find(`li[data-value="${dataValue}"]`).length < 1) { values.parent().addClass('mmui-highlighted-dimension-drop'); } } } setSelectedItemStyles(evt, ui) { const dataValue = $(ui.item).attr('data-value'); const fields = $(`#${this.parentId} > * li[data-value="${dataValue}"]`); for (let i = 0; i < fields.length; i++) { const field = fields[i]; field.classList.remove('mmui-deselected-item'); field.classList.add('mmui-selected-item'); } } resetBorder() { const rows = this.selectElmt('rows'); const columns = this.selectElmt('columns'); const filters = this.selectElmt('filters'); const values = this.selectElmt('values'); rows .parent() .removeClass('mmui-highlighted-dimension-drop') .addClass('mmui-dimension-drop'); columns .parent() .removeClass('mmui-highlighted-dimension-drop') .addClass('mmui-dimension-drop'); filters .parent() .removeClass('mmui-highlighted-dimension-drop') .addClass('mmui-dimension-drop'); values .parent() .removeClass('mmui-highlighted-dimension-drop') .addClass('mmui-dimension-drop'); } resetSelectedItemStyles() { const fields = $(`#${this.parentId} > * li[class~="mmui-selected-item"]`); for (let i = 0; i < fields.length; i++) { const field = fields[i]; field.classList.remove('mmui-selected-item'); field.classList.add('mmui-deselected-item'); } } receive() { this.removeDuplicatesInDataFields(); this.checkForTwoOrMoreRows(); this.sortDataFields(); this.formatDataFieldList(); this.checkEmptyStates(); this.disableDataFields(); } /** * Generic sorting function to alphabetize a list of objects in the format [{label: 'Label One', value: 'Value One'}] * @returns am alphabetized list of objects */ sort(a, b) { return b.label.toUpperCase() < a.label.toUpperCase() ? 1 : -1; } /** * This function sorts the available data field list */ sortDataFields() { const dimensionArray = $(`#${this.parentId} > * .mmui-data-fields > li`) .toArray() .map((item) => { const dict: any = {}; dict.label = item.dataset.label; dict.value = item.dataset.value; dict.type = item.dataset.type; return dict; }) .sort(this.sort); let dimStr = ''; for (const item of dimensionArray) { dimStr += this.createDataFieldItem(item.label, item.value, item.type); } if (dimensionArray.length == 0 || dimensionArray[0].value != undefined) { $(`#${this.parentId} .mmui-data-fields`).html(dimStr); } this.formatDataFieldList(); } /** * This function updates the DOM by adding a list item to the appropriate list * It removes existing event handlers and adds a new one and checks for empty states * @param evt - click event * @param ui - ui item */ onUpdate(evt, ui) { if (!evt.target || !ui.sender) { this.sortDataFields(); return; } const className = $(evt.target).attr('class'); const target = $(evt.target); const dataValue = $(ui.item).attr('data-value'); const dataLabel = $(ui.item).attr('data-label'); const dataType = $(ui.item).attr('data-type'); const currentNode = target.find('li[data-value=' + dataValue + ']'); target.find('li[id=empty]').remove(); let elmt; currentNode.find('a').off('click'); const isTargetFields = className.includes('mmui-data-fields'), isTargetRows = className.includes('mmui-data-field-rows'), isTargetColumns = className.includes('mmui-data-field-columns'), isTargetFilters = className.includes('mmui-data-field-filters'), isTargetValues = className.includes('mmui-data-field-values'); if (isTargetFields) { elmt = this.createDataFieldItem(dataLabel, dataValue, dataType); this.sortDataFields(); } else if (isTargetRows) { elmt = this.createDataFieldInputItem( dataLabel, dataValue, dataType, 'rows' ); } else if (isTargetColumns) { elmt = this.createDataFieldInputItem( dataLabel, dataValue, dataType, 'columns' ); } else if (isTargetFilters) { elmt = this.createDataFieldInputItem( dataLabel, dataValue, dataType, 'filters' ); } else if (isTargetValues) { elmt = this.createDataFieldInputItem( dataLabel, dataValue, dataType, 'values' ); } currentNode.replaceWith(elmt); $(`#${this.parentId} > * ul > li > a[data-value=${dataValue}]`).click( (evt) => { evt.preventDefault(); this.onRemove(evt, dataValue, dataLabel, dataType); } ); this.checkIfTwoExistAlready(dataLabel, dataValue, dataType); this.checkIfItemExistsInList(evt, dataLabel, dataValue, dataType); this.checkIfValidMove(evt, dataLabel, dataValue, dataType); this.removeDuplicatesInDataFields(); if (isTargetFields || isTargetRows) { this.checkForTwoOrMoreRows(); } this.formatDataFieldList(); this.checkEmptyStates(); this.disableDataFields(); } disableDataFields() { const dataFields = $( `#${this.parentId} > * ul[class^="mmui-data-fields"] > li[class~="mmui-data-field"]` ); for (let i = 0; i < dataFields.length; i++) { const field = $(dataFields[i]); const dataValue = field.attr('data-value'); const dataType = field.attr('data-type'); const numberOfDataFields = $( `#${this.parentId} li[data-value~=${dataValue}]` ).length; if ( numberOfDataFields > 2 || (numberOfDataFields > 1 && dataType == 'metric') ) { field.addClass('mmui-data-field-disabled'); } } } checkForTwoOrMoreRows() { if ($(`#${this.parentId} .mmui-data-field-rows li`).length > 1) { $(`#${this.parentId} .mmui-data-field-subtotals`).css('display', 'block'); } else { $(`#${this.parentId} .mmui-data-field-subtotals`).css('display', 'none'); } } checkIfTwoExistAlready(dataLabel, dataValue, dataType) { const item = $(`#${this.parentId} li[data-value~=${dataValue}]`); if (item.length > 2 || dataType == 'metric') { this.checkEmptyStates(); } else { const dataField = this.createDataFieldItem( dataLabel, dataValue, dataType ); $(`#${this.parentId} ul[class~="mmui-data-fields"]`).append(dataField); } } checkIfItemExistsInList(evt, dataLabel, dataValue, dataType) { const newElmt = this.createDataFieldItem(dataLabel, dataValue, dataType); const currentElmts = $(evt.target).find(`li[data-value=${dataValue}]`); if (currentElmts.length > 1) { currentElmts.first().remove(); $(`#${this.parentId} ul[class~="mmui-data-fields"]`).append(newElmt); } } checkIfValidMove(evt, dataLabel, dataValue, dataType) { let dataFields = this.selectElmt('data-fields'), rows = this.selectElmt('rows'), columns = this.selectElmt('columns'), filters = this.selectElmt('filters'), values = this.selectElmt('values'), existsInDataFields = false, existsInRows = false, existsInColumns = false, existsInFilters = false, existsInValues = false, rowsListItem = rows.find(`li[data-value=${dataValue}]`), columnsListItem = columns.find(`li[data-value=${dataValue}]`), filtersListItem = filters.find(`li[data-value=${dataValue}]`), valuesListItem = values.find(`li[data-value=${dataValue}]`), dataFieldsListItem = dataFields.find(`li[data-value=${dataValue}]`); if (rowsListItem.length > 0) { existsInRows = true; } if (columnsListItem.length > 0) { existsInColumns = true; } if (filtersListItem.length > 0) { existsInFilters = true; } if (valuesListItem.length > 0) { existsInValues = true; } if (dataFieldsListItem.length > 0) { existsInDataFields = true; } if (dataType == 'attribute') { if (existsInRows && existsInColumns) { const currentElmts = $(evt.target).find(`li[data-value=${dataValue}]`); currentElmts.first().remove(); if (!existsInDataFields) { const newElmt = this.createDataFieldItem( dataLabel, dataValue, dataType ); dataFields.append(newElmt); } } if (existsInValues) { const currentElmts = valuesListItem; currentElmts.first().remove(); if (!existsInDataFields) { const newElmt = this.createDataFieldItem( dataLabel, dataValue, dataType ); dataFields.append(newElmt); } } } else if (dataType == 'metric') { if (existsInValues) { const newElmt = this.createDataFieldItem( dataLabel, dataValue, dataType ); dataFields.append(newElmt); } if (existsInRows) { rowsListItem.first().remove(); const newElmt = this.createDataFieldItem( dataLabel, dataValue, dataType ); dataFields.append(newElmt); } if (existsInColumns) { columnsListItem.first().remove(); const newElmt = this.createDataFieldItem( dataLabel, dataValue, dataType ); dataFields.append(newElmt); } if (existsInFilters) { filtersListItem.first().remove(); const newElmt = this.createDataFieldItem( dataLabel, dataValue, dataType ); dataFields.append(newElmt); } } } removeDuplicatesInDataFields() { const seen = {}; $(`#${this.parentId} > * ul[class~="mmui-data-fields"] li`).each( function () { const txt = $(this).text(); if (seen[txt]) $(this).remove(); else seen[txt] = true; } ); } /** * This function creates a dimension list item for the available dimension list * @param label - the data-label attribute * @param value - the data-value attribute * @returns a list item element */ createDataFieldItem(label, value, dataType) { let metricIcon = ``; if (dataType == 'metric') { metricIcon = ``; } return `