UNPKG

mattermost-redux

Version:

Common code (API client, Redux stores, logic, utility functions) for building a Mattermost client

182 lines (181 loc) 5.67 kB
"use strict"; // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. Object.defineProperty(exports, "__esModule", { value: true }); exports.cleanBinding = cleanBinding; exports.validateBindings = validateBindings; exports.cleanForm = cleanForm; const apps_1 = require("mattermost-redux/constants/apps"); function cleanBinding(binding, topLocation) { cleanBindingRec(binding, topLocation, 0); } function cleanBindingRec(binding, topLocation, depth) { if (!binding) { return; } const toRemove = []; const usedLabels = {}; binding.bindings?.forEach((b, i) => { // Inheritance and defaults if (!b.app_id) { b.app_id = binding.app_id; } if (!b.label) { b.label = b.location || ''; } b.location = binding.location + '/' + b.location; // Validation if (!b.app_id) { toRemove.unshift(i); return; } // No empty labels nor "whitespace" labels if (!b.label.trim()) { toRemove.unshift(i); return; } switch (topLocation) { case apps_1.AppBindingLocations.COMMAND: { if (b.label.match(/ |\t/)) { toRemove.unshift(i); return; } if (usedLabels[b.label]) { toRemove.unshift(i); return; } break; } case apps_1.AppBindingLocations.CHANNEL_HEADER_ICON: { // First level of channel header icons must have an icon to show as the icon if (!b.icon && depth === 0) { toRemove.unshift(i); return; } break; } } // Must have only subbindings, a form or a submit call. const hasBindings = Boolean(b.bindings?.length); const hasForm = Boolean(b.form); const hasSubmit = Boolean(b.submit); if ((!hasBindings && !hasForm && !hasSubmit) || (hasBindings && hasForm) || (hasBindings && hasSubmit) || (hasForm && hasSubmit)) { toRemove.unshift(i); return; } if (hasBindings) { cleanBindingRec(b, topLocation, depth + 1); // Remove invalid branches if (!b.bindings?.length) { toRemove.unshift(i); return; } } else if (hasForm) { if (!b.form?.submit && !b.form?.source) { toRemove.unshift(i); return; } cleanForm(b.form); } usedLabels[b.label] = true; }); toRemove.forEach((i) => { binding.bindings?.splice(i, 1); }); } function validateBindings(bindings = []) { if (!bindings || (bindings.length && bindings.length === 0)) { return []; } const filterAndCleanBindings = (location) => { const filteredBindings = bindings.filter((b) => b.location === location); if (filteredBindings?.length === 0) { return []; } filteredBindings.forEach((b) => cleanBinding(b, location)); return filteredBindings.filter((b) => b.bindings?.length); }; const channelHeaderBindings = filterAndCleanBindings(apps_1.AppBindingLocations.CHANNEL_HEADER_ICON); const postMenuBindings = filterAndCleanBindings(apps_1.AppBindingLocations.POST_MENU_ITEM); const commandBindings = filterAndCleanBindings(apps_1.AppBindingLocations.COMMAND); return postMenuBindings.concat(channelHeaderBindings, commandBindings); } function cleanForm(form) { if (!form) { return; } const toRemove = []; const usedLabels = {}; form.fields?.forEach((field, i) => { if (!field.name) { toRemove.unshift(i); return; } if (field.name.match(/ |\t/)) { toRemove.unshift(i); return; } let label = field.label; if (!label) { label = field.name; } if (label.match(/ |\t/)) { toRemove.unshift(i); return; } if (usedLabels[label]) { toRemove.unshift(i); return; } switch (field.type) { case apps_1.AppFieldTypes.STATIC_SELECT: cleanStaticSelect(field); if (!field.options?.length) { toRemove.unshift(i); return; } break; case apps_1.AppFieldTypes.DYNAMIC_SELECT: if (!field.lookup) { toRemove.unshift(i); return; } } usedLabels[label] = true; }); toRemove.forEach((i) => { form.fields.splice(i, 1); }); } function cleanStaticSelect(field) { const toRemove = []; const usedLabels = {}; const usedValues = {}; field.options?.forEach((option, i) => { let label = option.label; if (!label) { label = option.value; } if (!label) { toRemove.unshift(i); return; } if (usedLabels[label]) { toRemove.unshift(i); return; } if (usedValues[option.value]) { toRemove.unshift(i); return; } usedLabels[label] = true; usedValues[option.value] = true; }); toRemove.forEach((i) => { field.options?.splice(i, 1); }); }