\n
\n ${warningMessage}\n `;\n\n if (unavailableClasses.size() > 0) {\n tab.prepend('
');\n puppetKlassesTab.prepend(warning);\n } else {\n puppetKlassesTab.find('#puppetclasses_unavailable_warning').remove();\n tab.find('.pficon-warning-triangle-o').remove();\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/foreman_hostgroups.js","import { uniq, set } from 'lodash';\nimport * as table from './hosts/tableCheckboxes';\n\nexport default {\n table,\n registerPluginAttributes,\n getAttributesToPost,\n copyRegistrationCommand,\n checkPXELoaderCompatibility,\n pxeCompatibility,\n};\n\nconst pluginEditAttributes = {\n architecture: [],\n os: [],\n medium: [],\n image: [],\n};\n\nexport function registerPluginAttributes(componentType, attributes) {\n if (pluginEditAttributes[componentType] !== undefined) {\n const combinedAttributes = pluginEditAttributes[componentType].concat(\n attributes\n );\n pluginEditAttributes[componentType] = uniq(combinedAttributes);\n }\n}\n\nexport function getAttributesToPost(componentType) {\n const defaultAttributes = {\n architecture: ['architecture_id', 'organization_id', 'location_id'],\n os: ['operatingsystem_id', 'organization_id', 'location_id'],\n medium: ['medium_id', 'operatingsystem_id', 'architecture_id'],\n image: ['medium_id', 'operatingsystem_id', 'architecture_id', 'model_id'],\n };\n let attrsToPost = defaultAttributes[componentType];\n\n if (attrsToPost === undefined) {\n return [];\n }\n if (pluginEditAttributes[componentType] !== undefined) {\n attrsToPost = attrsToPost.concat(pluginEditAttributes[componentType]);\n }\n return uniq(attrsToPost);\n}\n\nexport function copyRegistrationCommand() {\n const commandText = document.getElementById('registration_command')\n .textContent;\n const tmpElement = document.createElement('textarea');\n\n tmpElement.textContent = commandText;\n document.body.appendChild(tmpElement);\n tmpElement.select();\n document.execCommand('copy');\n document.body.removeChild(tmpElement);\n}\n\nclass PXECompatibilityCheck {\n constructor(regexp, compatibleLoadersFunc) {\n this.__regexp = regexp;\n this.__compatibleLoadersFunc = compatibleLoadersFunc;\n }\n\n isCompatible(osTitle, pxeLoader) {\n const os = this.__regexp.exec(osTitle);\n\n if (os == null) {\n return null;\n }\n\n const supportedLoaders = this.__compatibleLoadersFunc(os);\n if (supportedLoaders != null) {\n return supportedLoaders.indexOf(pxeLoader) > -1;\n }\n return null;\n }\n}\n\n/* eslint-disable no-unused-vars */\nconst PXE_BIOS = 'PXELinux BIOS';\nconst PXE_UEFI = 'PXELinux UEFI';\nconst GRUB_UEFI = 'Grub UEFI';\nconst GRUB2_UEFI = 'Grub2 UEFI';\nconst GRUB2_UEFI_SB = 'Grub2 UEFI SecureBoot';\n\nexport const pxeCompatibility = {};\n\n// Ubuntu 10.x or older and Grub1\n// Ubuntu 11.x or newer and Grub2\nset(\n pxeCompatibility,\n 'ubuntu',\n new PXECompatibilityCheck(/ubuntu[^\\d]*(\\d+)(?:[.]\\d+)?/, os => {\n if (os[1] <= '10') {\n return [PXE_BIOS, GRUB_UEFI];\n } else if (os[1] > '10') {\n return [PXE_BIOS, GRUB2_UEFI, GRUB2_UEFI_SB];\n }\n return null;\n })\n);\n\n// RHEL 6.x and Grub1\n// RHEL 7.x and Grub2\nset(\n pxeCompatibility,\n 'rhel',\n new PXECompatibilityCheck(\n /(?:red[ ]*hat|rhel|cent[ ]*os|scientific|oracle)[^\\d]*(\\d+)(?:[.]\\d+)?/,\n os => {\n if (os[1] === '6') {\n return [PXE_BIOS, GRUB_UEFI];\n } else if (os[1] >= '7') {\n return [PXE_BIOS, GRUB2_UEFI, GRUB2_UEFI_SB];\n }\n return null;\n }\n )\n);\n\n// Debian 2-6 and Grub1\n// Debian 7+ and Grub2\nset(\n pxeCompatibility,\n 'debian',\n new PXECompatibilityCheck(/debian[^\\d]*(\\d+)(?:[.]\\d+)?/, os => {\n if (os[1] >= '2' && os[1] <= '6') {\n return [PXE_BIOS, GRUB_UEFI];\n } else if (os[1] > '6') {\n return [PXE_BIOS, GRUB2_UEFI, GRUB2_UEFI_SB];\n }\n return null;\n })\n);\n\nexport function checkPXELoaderCompatibility(osTitle, pxeLoader) {\n if (pxeLoader === 'None' || pxeLoader === '') {\n return null;\n }\n let compatible = null;\n\n // eslint-disable-next-line no-param-reassign\n osTitle = osTitle.toLowerCase();\n Object.values(pxeCompatibility).forEach(check => {\n const compatibleCheck = check.isCompatible(osTitle, pxeLoader);\n\n if (compatibleCheck != null) {\n compatible = compatibleCheck;\n }\n });\n return compatible;\n}\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/foreman_hosts.js","/* eslint-disable jquery/no-serialize */\n/* eslint-disable jquery/no-show */\n/* eslint-disable jquery/no-class */\n/* eslint-disable jquery/no-ajax */\n/* eslint-disable jquery/no-hide */\n\nimport $ from 'jquery';\nimport { notify, clear } from './foreman_toast_notifications';\n\nexport function testConnection(item, url) {\n const data = $('form').serialize();\n\n $('#test_connection_indicator').show();\n $(item).addClass('disabled');\n clear();\n $.ajax({\n url,\n type: 'put',\n data,\n success(result, textstatus, xhr) {\n notify({ message: result.message, type: 'success' });\n },\n error(xhr) {\n const error = $.parseJSON(xhr.responseText).message;\n\n notify({ message: error, type: 'danger' });\n },\n complete(result) {\n $('#test_connection_indicator').hide();\n $(item).removeClass('disabled');\n },\n });\n}\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/foreman_http_proxies.js","/* eslint-disable jquery/no-data */\n/* eslint-disable jquery/no-find */\n/* eslint-disable jquery/no-class */\n/* eslint-disable jquery/no-closest */\n/* eslint-disable jquery/no-val */\n/* eslint-disable jquery/no-sizzle */\n/* eslint-disable jquery/no-text */\n\nimport $ from 'jquery';\n\nconst matcherFieldChanged = (element, currentValue) => {\n const { initialValue } = $(element).data();\n\n const popover = $(element)\n .closest('td')\n .find('a.warn-field-changed');\n\n if (initialValue === currentValue) {\n $(element).removeClass('matcher-field-changed');\n $(popover).removeClass('warn-show');\n } else {\n $(element).addClass('matcher-field-changed');\n $(popover).addClass('warn-show');\n }\n};\n\nexport const matcherKeyChanged = element => {\n const currentValue = $(element)\n .find(':selected')\n .text();\n\n matcherFieldChanged(element, currentValue);\n};\n\nexport const matcherValueChanged = element => {\n const currentValue = $(element).val();\n\n matcherFieldChanged(element, currentValue);\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/foreman_lookup_keys.js","/* eslint-disable jquery/no-toggle */\n\nimport $ from 'jquery';\n\nexport function nfsVisibility(osFamily, nfsRequired) {\n $('#nfs-section').toggle(nfsRequired.includes(osFamily.value));\n}\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/foreman_medium.js","/* eslint-disable jquery/no-show */\n\nimport $ from 'jquery';\nimport URI from 'urijs';\nimport { push } from 'connected-react-router';\nimport store from './react_app/redux';\nimport * as LayoutActions from './react_app/components/Layout/LayoutActions';\nimport { deprecate } from './react_app/common/DeprecationService';\n\nexport const visit = url => {\n window.location.href = url;\n};\n\nexport const reloadPage = () => {\n window.location.reload();\n};\n\n/**\n * Push a new url to foreman's react router\n * @param {String} url - the base url i.e `/hosts`\n * @param {Object} searchQuery - the query params, i.e {'per_page': 4, 'page': 2}\n */\nexport const pushUrl = (url, queryParams = {}) => {\n const urlWithQueries = new URI(url).search(queryParams).toString();\n return store.dispatch(push(urlWithQueries));\n};\n\nexport const showLoading = () => {\n store.dispatch(LayoutActions.showLoading());\n};\n\nexport const hideLoading = () => {\n store.dispatch(LayoutActions.hideLoading());\n};\n\nexport const changeLocation = loc => {\n deprecate('changeLocation', 'Context', '2.6');\n};\n\nexport const changeOrganization = org => {\n deprecate('changeOrganization', 'Context', '2.6');\n};\n\nexport const changeActive = active => {\n store.dispatch(LayoutActions.changeActiveMenu({ title: active }));\n};\n\nexport function showContent(layout, unsubscribe) {\n const content = () => {\n $('#content').show();\n unsubscribe();\n };\n // workaround for pages with no layout object\n if (layout.items.length && !layout.isLoading) {\n content();\n } else if ($('#layout').length === 0) content();\n}\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/foreman_navigation.js","/* eslint-disable jquery/no-val */\n\nimport $ from 'jquery';\n\nexport function autofillSshKeyName() {\n const name = $('#ssh_key_name');\n const comment = $('#ssh_key_key')\n .val()\n .match(/^\\S+ \\S+ (.+)\\n?$/);\n\n if (name.val() === '' && comment && comment.length >= 1) {\n return name.val(comment[1]).change();\n }\n\n return true;\n}\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/foreman_ssh_keys.js","import { get } from 'lodash';\nimport store from './react_app/redux';\nimport actionsList from './foreman_actions';\n\n/**\n * invoke an action\n * @param {String} actionName is the name of the action registered in foreman_actionsList\n * @param {args} args action's arguments\n */\nexport const dispatch = (actionName, ...args) => {\n if (!actionsList[actionName]) {\n throw new ReferenceError(\n `Dispatch failed: action ${actionName} doesn't exist`\n );\n }\n return store.dispatch(actionsList[actionName](...args));\n};\n\n/**\n * Observe a state from the store for changes\n * @param {String} state a sub object of the store\n * @param {Function} onChange a callback to run when the store has been changed\n * @return {Function} unsubscribe function\n */\nexport function observeStore(state, onChange) {\n let currentState;\n\n function handleChange() {\n const nextState = select(state);\n if (nextState !== currentState) {\n currentState = nextState;\n onChange(currentState, unsubscribe);\n }\n }\n\n const unsubscribe = store.subscribe(handleChange);\n handleChange();\n return unsubscribe;\n}\n\nfunction select(state) {\n const stateObj = get(store.getState(), state);\n\n if (stateObj === undefined) {\n throw new Error(`State ${state} does not exist`);\n }\n\n return stateObj;\n}\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/foreman_store.js","/* eslint-disable jquery/no-val */\n/* eslint-disable jquery/no-trigger */\n/* eslint-disable jquery/no-each */\n/* eslint-disable jquery/no-toggle */\n/* eslint-disable jquery/no-find */\n/* eslint-disable jquery/no-closest */\n/* eslint-disable jquery/no-is */\n/* eslint-disable func-names */\n\nimport $ from 'jquery';\n\nimport store from './react_app/redux';\nimport { actions as TemplateActions } from './react_app/components/TemplateGenerator';\n\nexport function initTypeChanges() {\n // update the hidden input which serves as template\n // and also all existing inputs in case of editing\n $('select.input_type_selector').each(function() {\n updateVisibilityAfterInputTypeChange($(this));\n });\n\n // every additional input that's added through \"Add Input\" button will also be handled\n $(document).on('change', 'select.input_type_selector', function() {\n updateVisibilityAfterInputTypeChange($(this));\n });\n}\n\nfunction updateVisibilityAfterInputTypeChange(select) {\n const fieldset = select.closest('fieldset');\n fieldset.find('div.custom_input_type_fields').hide();\n fieldset.find(`div.${select.val()}_input_type`).show();\n}\n\nexport const toggleEmailFields = checkbox => {\n const $checkbox = $(checkbox);\n $checkbox\n .closest('form')\n .find('.email-fields')\n .toggle($checkbox.is(':checked'));\n};\n\nexport const generateTemplate = (url, templateInputData) => {\n store.dispatch(TemplateActions.generateTemplate(url, templateInputData));\n};\n\nexport const pollReportData = url => {\n store.dispatch(TemplateActions.pollReportData(url));\n};\n\nexport const inputValueOnchange = input => {\n const searchValue = input.value === 'search';\n const plainValue = input.value === 'plain';\n const inputId = input.dataset.item;\n const $fields = $(input).closest('.fields');\n\n $fields.find(`.resource-type-${inputId}`).toggle(searchValue);\n $fields.find(`.input-options-${inputId}`).toggle(plainValue);\n $fields.find(`.input-hidden-value-${inputId}`).toggle(plainValue);\n};\n\nexport function snippetChanged(item) {\n const checked = $(item).is(':checked');\n\n $('#kind_selector').toggle(!checked);\n $('#snippet_message').toggle(checked);\n $('#association').toggle(!checked);\n if (checked) {\n $('#ptable_os_family').val('');\n $('#ptable_os_family').trigger('change');\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/foreman_template_inputs.js","import store from './react_app/redux';\n\nimport * as ToastActions from './react_app/redux/actions/toasts';\n\nconst isStickyType = type => !['success', 'info'].includes(type);\n\n/**\n * Notify the user with a toast-notification\n */\nexport const notify = ({ message, type, link, sticky = isStickyType(type) }) =>\n store.dispatch(\n ToastActions.addToast({\n type,\n message,\n sticky,\n link,\n })\n );\n\n/**\n * Clear all toast notifications\n */\nexport const clear = () => store.dispatch(ToastActions.clearToasts());\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/foreman_toast_notifications.js","/* eslint-disable jquery/no-val */\n/* eslint-disable jquery/no-find */\n/* eslint-disable jquery/no-text */\n/* eslint-disable jquery/no-ajax */\n/* eslint-disable jquery/no-each */\n/* eslint-disable jquery/no-class */\n\nimport $ from 'jquery';\nimport { sprintf, translate as __ } from './react_app/common/I18n';\n\nimport { showLoading, hideLoading } from './foreman_navigation';\n\nexport * from './react_app/common/DeprecationService';\n\nexport function showSpinner() {\n showLoading();\n}\n\nexport function hideSpinner() {\n hideLoading();\n}\n\nexport function iconText(name, innerText, iconClass) {\n let icon = `
`;\n\n if (innerText !== '') {\n icon += `
${innerText}`;\n }\n return icon;\n}\n\nexport function activateDatatables() {\n const language = {\n searchPlaceholder: __('Filter...'),\n emptyTable: __('No data available in table'),\n info: sprintf(\n __('Showing %s to %s of %s entries'),\n '_START_',\n '_END_',\n '_TOTAL_'\n ),\n infoEmpty: __('Showing 0 to 0 of 0 entries'),\n infoFiltered: sprintf(__('(filtered from %s total entries)'), '_MAX_'),\n lengthMenu: sprintf(__('Show %s entries'), '_MENU_'),\n loadingRecords: __('Loading...'),\n processing: __('Processing...'),\n search: __('Search:'),\n zeroRecords: __('No matching records found'),\n paginate: {\n first: __('First'),\n last: __('Last'),\n next: __('Next'),\n previous: __('Previous'),\n },\n aria: {\n sortAscending: __(': activate to sort column ascending'),\n sortDescending: __(': activate to sort column descending'),\n },\n };\n $('[data-table=inline]')\n .not('.dataTable')\n .DataTable({\n language,\n dom: \"<'row'<'col-md-6'f>r>t<'row'<'col-md-6'i><'col-md-6'p>>\",\n });\n\n $('[data-table=server]')\n .not('.dataTable')\n .each((i, el) => {\n const url = el.getAttribute('data-source');\n\n $(el).DataTable({\n language,\n processing: true,\n serverSide: true,\n ordering: false,\n ajax: url,\n dom: \"<'row'<'col-md-6'f>r>t<'row'<'col-md-6'><'col-md-6'p>>\",\n });\n });\n}\n\nexport function activateTooltips(elParam = 'body') {\n const el = $(elParam);\n\n el.tooltip({\n selector: '[rel=\"twipsy\"],*[title]:not(*[rel],.fa,.pficon)',\n container: 'body',\n trigger: 'hover',\n });\n // Ellipsis have to be initialized for each element for title() to work\n el.find('.ellipsis').tooltip({\n container: 'body',\n title() {\n return this.scrollWidth > this.clientWidth ? this.textContent : null;\n },\n });\n}\n\nexport function initTypeAheadSelect(input) {\n input.select2({\n ajax: {\n url: input.data('url'),\n dataType: 'json',\n quietMillis: 250,\n data: (term, page) => ({\n q: term,\n scope: input.data('scope'),\n }),\n results: data => ({\n results: data.map(({ id, name }) => ({ id, text: name })),\n }),\n cache: true,\n },\n initSelection(element, callback) {\n $.ajax(input.data('url'), {\n data: {\n scope: input.data('scope'),\n },\n dataType: 'json',\n }).done(data => {\n if (data.length > 0) {\n // eslint-disable-next-line standard/no-callback-literal\n callback({ id: data[0].id, text: data[0].name });\n }\n });\n },\n width: '400px',\n });\n}\n\n// generates an absolute, needed in case of running Foreman from a subpath\nexport { foremanUrl } from './react_app/common/helpers';\n\nexport const setTab = () => {\n const urlHash = document.location.hash.split('?')[0];\n if (urlHash.length) {\n const tabContent = $(urlHash);\n const parentTab = tabContent.closest('.tab-pane');\n if (parentTab.exists()) {\n $(`.nav-tabs a[href=\"#${parentTab[0].id}\"]`).tab('show');\n }\n $(`.nav-tabs a[href=\"${urlHash}\"]`).tab('show');\n }\n};\n\nexport function highlightTabErrors() {\n const errorFields = $('.tab-content .has-error');\n errorFields.parents('.tab-pane').each(function fn() {\n $(`a[href=\"#${this.id}\"]`).addClass('tab-error');\n });\n $('.tab-error')\n .first()\n .click();\n $('.nav-pills .tab-error')\n .first()\n .click();\n errorFields\n .first()\n .find('.form-control')\n .focus();\n}\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/foreman_tools.js","import {\n updateOptions as updateTypeAheadSelectOptions,\n updateSelected as updateTypeAheadSelectSelected,\n} from './react_app/components/common/TypeAheadSelect/TypeAheadSelectActions';\nimport store from './react_app/redux';\n\nexport const updateOptions = (options, id) => {\n store.dispatch(updateTypeAheadSelectOptions(options, id));\n};\n\nexport const updateSelected = (selected, id) => {\n store.dispatch(updateTypeAheadSelectSelected(selected, id));\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/foreman_type_ahead_select.js","/* eslint-disable jquery/no-toggle */\n/* eslint-disable jquery/no-ajax */\n/* eslint-disable jquery/no-hide */\n/* eslint-disable jquery/no-show */\n/* eslint-disable jquery/no-html */\n/* eslint-disable jquery/no-closest */\n\nimport $ from 'jquery';\nimport { escape } from 'lodash';\nimport { notify } from './foreman_toast_notifications';\n\nexport function initInheritedRoles() {\n $('#inherited-roles .dropdown-menu a')\n .click(({ target }) => {\n $('#roles_tab li').hide();\n $(`#roles_tab li[data-id = '${target.getAttribute('data-id')}']`).show();\n $(target)\n .closest('.dropdown')\n .children('.btn')\n .html(`${escape(target.text)}
`);\n })\n .first()\n .click();\n}\n\nfunction getSelectValues({ options = [] }) {\n return Object.values(options)\n .filter(opt => opt.selected)\n .map(opt => [opt.value, opt.text]);\n}\n\nexport function taxonomyAdded(taxonomies, type) {\n const selected = [['', ''], ...getSelectValues(taxonomies)];\n const defaults = document.getElementById(`user_default_${type}_id`);\n\n defaults.innerHTML = selected\n .map(opt => `
`)\n .join('');\n}\n\n/* eslint-disable no-undef */\nexport function testMail(item, url, param = {}) {\n const button = $(item);\n const spinner = $('#test_indicator');\n\n button.addClass('disabled');\n spinner.show();\n\n $.ajax({\n url,\n type: 'put',\n data: param,\n success: ({ message }) => notify({ message, type: 'success' }),\n error: ({ responseText }) =>\n notify({\n message: JSON.parse(responseText).message,\n type: 'danger',\n }),\n complete: () => {\n spinner.hide();\n button.removeClass('disabled');\n },\n });\n}\n\nexport function authSourceSelected(param) {\n const id = param.selectedOptions[0].textContent;\n $('#password').toggle(id === 'INTERNAL');\n}\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/foreman_users.js","import { getValue, setValue } from '../react_app/common/SessionStorage';\n\nexport const getHostQuery = () => getValue('hostQuery');\nexport const setHostQuery = value => setValue('hostQuery', value);\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/hosts/HostsSessionStorage.js","/* eslint-disable jquery/no-param */\n/* eslint-disable jquery/no-load */\n/* eslint-disable jquery/no-hide */\n/* eslint-disable jquery/no-show */\n/* eslint-disable jquery/no-find */\n/* eslint-disable jquery/no-text */\n/* eslint-disable jquery/no-data */\n/* eslint-disable jquery/no-val */\n/* eslint-disable jquery/no-attr */\n/* eslint-disable jquery/no-is */\n/* eslint-disable jquery/no-html */\n/* eslint-disable jquery/no-each */\n/* eslint-disable jquery/no-submit */\n/* eslint-disable jquery/no-in-array */\n\nimport $ from 'jquery';\n\nimport {\n sprintf,\n ngettext as n__,\n translate as __,\n} from '../react_app/common/I18n';\nimport { getURIsearch } from '../react_app/common/urlHelpers';\nimport { foremanUrl } from '../foreman_tools';\nimport * as sessionStorage from './HostsSessionStorage';\n\n// Array contains list of host ids\nconst cookieName = `_ForemanSelected${window.location.pathname.replace(\n /\\//,\n ''\n)}`;\nlet foremanSelectedHosts = readFromCookie();\n\n// triggered by a host checkbox change\nexport function hostChecked({ id, checked }) {\n const multipleAlert = $('#multiple-alert');\n const cid = parseInt(id.replace('host_ids_', ''), 10);\n if (checked) addHostId(cid);\n else {\n rmHostId(cid);\n if (multipleAlert.length) {\n multipleAlert.hide('slow');\n multipleAlert.data('multiple', false);\n }\n }\n $.cookie(cookieName, JSON.stringify(foremanSelectedHosts), {\n secure: window.location.protocol === 'https:',\n });\n toggleActions();\n updateCounter();\n return false;\n}\n\nfunction addHostId(id) {\n if ($.inArray(id, foremanSelectedHosts) === -1) foremanSelectedHosts.push(id);\n}\n\nfunction rmHostId(id) {\n const pos = $.inArray(id, foremanSelectedHosts);\n if (pos >= 0) foremanSelectedHosts.splice(pos, 1);\n}\n\nfunction readFromCookie() {\n try {\n const r = $.cookie(cookieName);\n if (r) return $.parseJSON(r);\n return [];\n } catch (err) {\n removeForemanHostsCookie();\n return [];\n }\n}\n\nfunction toggleActions() {\n const dropDownContainer = $('#submit_multiple');\n const dropdown = dropDownContainer.find('a');\n const disabledMessage = __('Please select hosts to perform action on.');\n if (foremanSelectedHosts.length === 0) {\n dropdown.addClass('disabled');\n dropdown.attr('disabled', 'disabled');\n dropDownContainer.attr('title', disabledMessage);\n } else {\n dropdown.removeClass('disabled');\n dropdown.removeAttr('disabled');\n dropDownContainer.removeAttr('title');\n }\n}\n\n// setups checkbox values upon document load\n$(document).on('ContentLoad', () => {\n if (window.location.pathname !== foremanUrl('/hosts')) return;\n\n const hostQuery = sessionStorage.getHostQuery();\n const uriSearch = getURIsearch();\n\n // clear selected hosts if new search occurs\n if (uriSearch !== '' && hostQuery !== uriSearch) {\n cleanHostsSelection();\n sessionStorage.setHostQuery(uriSearch);\n return;\n }\n sessionStorage.setHostQuery(uriSearch);\n\n for (let i = 0; i < foremanSelectedHosts.length; i++) {\n const cid = `host_ids_${foremanSelectedHosts[i]}`;\n const boxes = $(`#${cid}`);\n if (boxes && boxes[0]) boxes[0].checked = true;\n }\n toggleActions();\n updateCounter();\n $('#search-form').submit(() => {\n resetSelection();\n });\n\n // updates the form URL based on the action selection\n $('#confirmation-modal .secondary').click(() => {\n $('#confirmation-modal').modal('hide');\n });\n});\n\nfunction removeForemanHostsCookie() {\n $.removeCookie(cookieName);\n}\n\nexport function resetSelection() {\n removeForemanHostsCookie();\n foremanSelectedHosts = [];\n}\n\nfunction cleanHostsSelection() {\n $('.host_select_boxes').each((index, box) => {\n box.checked = false;\n hostChecked(box);\n });\n resetSelection();\n toggleActions();\n updateCounter();\n return false;\n}\n\nexport function multipleSelection() {\n const { total } = paginationMetaData();\n const alertText = sprintf(\n n__(\n 'Single host is selected in total',\n 'All
%d hosts are selected.',\n total\n ),\n total\n );\n const undoText = __('Undo selection');\n const multpleAlert = $('#multiple-alert');\n multpleAlert\n .find('.text')\n .html(\n `${alertText}
${undoText}`\n );\n multpleAlert.data('multiple', true);\n $('.select_count').html(total);\n}\n\nexport function undoMultipleSelection() {\n const pagination = paginationMetaData();\n const alertText = sprintf(\n n__(\n 'Single host on this page is selected.',\n 'All %s hosts on this page are selected.',\n pagination.perPage\n ),\n pagination.perPage\n );\n const selectText = sprintf(\n n__('Select this host', 'Select all
%s hosts', pagination.total),\n pagination.total\n );\n const multpleAlert = $('#multiple-alert');\n multpleAlert\n .find('.text')\n .html(\n `${alertText}
${selectText}`\n );\n multpleAlert.data('multiple', false);\n $('.select_count').html(pagination.perPage);\n}\n\nexport function toggleCheck() {\n const pagination = paginationMetaData();\n const multpleAlert = $('#multiple-alert');\n const checked = $('#check_all').is(':checked');\n $('.host_select_boxes').each((index, box) => {\n box.checked = checked;\n hostChecked(box);\n });\n if (checked && pagination.perPage - pagination.total < 0) {\n multpleAlert.show('slow');\n multpleAlert.data('multiple', false);\n } else if (!checked) {\n multpleAlert.hide('slow');\n multpleAlert.data('multiple', false);\n cleanHostsSelection();\n }\n return false;\n}\n\nexport function toggleMultipleOkButton({ value }) {\n const btn = $('#confirmation-modal .btn-primary');\n if (value !== 'disabled') btn.removeClass('disabled').attr('disabled', false);\n else btn.addClass('disabled').attr('disabled', true);\n}\n\nexport function submitModalForm() {\n if (!$('#keep_selected').is(':checked')) removeForemanHostsCookie();\n if (isMultple()) {\n const query = $('
')\n .attr('type', 'hidden')\n .attr('name', 'search')\n .val(getURIsearch());\n $('#confirmation-modal form').append(query);\n }\n $('#confirmation-modal form').submit();\n $('#confirmation-modal').modal('hide');\n}\n\nfunction isMultple() {\n return $('#multiple-alert').data('multiple');\n}\n\nfunction getBulkParam() {\n return isMultple()\n ? { search: getURIsearch() }\n : { host_ids: foremanSelectedHosts };\n}\n\nexport function buildModal(element, url) {\n const data = getBulkParam();\n const title = $(element).attr('data-dialog-title');\n $('#confirmation-modal .modal-header h4').text(title);\n $('#confirmation-modal .modal-body')\n .empty()\n .append(\"
\");\n $('#confirmation-modal').modal();\n $('#confirmation-modal .modal-body').load(\n `${url} #content`,\n data,\n (response, status, xhr) => {\n $('#loading').hide();\n $('#submit_multiple').val('');\n if (isMultple()) $('#multiple-modal-alert').show();\n const b = $('#confirmation-modal .btn-primary');\n if ($(response).find('#content form select').length > 0)\n b.addClass('disabled').attr('disabled', true);\n else b.removeClass('disabled').attr('disabled', false);\n }\n );\n return false;\n}\n\nexport function buildRedirect(url) {\n const data = getBulkParam();\n const redirectUrl = url.includes('?')\n ? `${url}&${$.param(data)}`\n : `${url}?${$.param(data)}`;\n\n window.location.replace(redirectUrl);\n}\n\nfunction paginationMetaData() {\n const total = Number(\n document.getElementsByClassName('pagination-pf-items-total')[0].textContent\n );\n const perPage = Number(\n document.getElementById('pagination-row-dropdown').textContent\n );\n return { total, perPage };\n}\n\nfunction updateCounter() {\n const item = $('#check_all');\n if (foremanSelectedHosts)\n $('.select_count').text(foremanSelectedHosts.length);\n let title = '';\n if (item.prop('checked') && foremanSelectedHosts)\n title = `${foremanSelectedHosts.length} - ${item.attr('uncheck-title')}`;\n else title = item.attr('check-title');\n\n item.attr('data-original-title', title);\n item.tooltip({\n trigger: 'hover',\n });\n return false;\n}\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/hosts/tableCheckboxes.js","/* eslint-disable jquery/no-each */\n/* eslint-disable jquery/no-ready */\n/* eslint-disable no-param-reassign */\n/* eslint-disable func-names */\n\nimport $ from 'jquery';\n\nconst megabyte = 1024 * 1024;\nconst gigabyte = 1024 * megabyte;\n\n$(() => {\n $.widget('ui.limitedSpinner', $.ui.spinner, {\n options: {\n softMaximum: 0,\n min: 1,\n errorTarget: null,\n },\n validate() {\n return this._validate();\n },\n _validate() {\n if (this.options.softMaximum !== 0) {\n this.options.errorTarget.toggle(\n this.value() > this.options.softMaximum\n );\n }\n },\n _spin(step, event) {\n const result = this._super(step, event);\n\n this._validate();\n return result;\n },\n });\n\n $.widget('ui.byteSpinner', $.ui.limitedSpinner, {\n options: {\n step: 1,\n min: 1,\n incremental: false,\n valueTarget: null,\n },\n updateValueTarget() {\n this.options.valueTarget.val(this.value());\n },\n _gigabyteSpin(step) {\n if (step > 0) {\n if (step % gigabyte === 0) {\n step = gigabyte;\n } else {\n step = gigabyte - (this.value() % gigabyte);\n }\n } else if (step < 0) {\n if (this.value() % gigabyte === 0) {\n step = -1 * gigabyte;\n } else {\n step = -1 * (this.value() % gigabyte);\n }\n }\n return step;\n },\n _megabyteSpin(step) {\n const megabyteStep = step * 256 * megabyte;\n\n if (this.value() + megabyteStep > gigabyte) {\n step = gigabyte - this.value();\n } else if (this.value() + megabyteStep < megabyte) {\n step *= this.value() - megabyte;\n } else if (this.value() === megabyte && step > 0) {\n step = 255 * megabyte;\n } else {\n step = megabyteStep;\n }\n return step;\n },\n _spin(step, event) {\n let result = null;\n\n if (\n (this.value() > gigabyte && step < 0) ||\n (this.value() >= gigabyte && step > 0)\n ) {\n step = this._gigabyteSpin(step);\n } else {\n step = this._megabyteSpin(step);\n }\n\n result = this._super(step, event);\n this.updateValueTarget();\n\n return result;\n },\n _parse(value) {\n if (typeof value === 'string') {\n if (value.match(/gb$/i)) {\n return parseFloat(value) * gigabyte;\n } else if (value.match(/mb$/i) || parseInt(value, 10) < megabyte) {\n return parseInt(value, 10) * megabyte;\n }\n }\n return value;\n },\n // prints value with unit, if it's multiple of gigabytes use GB, otherwise format in MB\n _format: value =>\n value % gigabyte === 0\n ? `${value / gigabyte} GB`\n : `${value / megabyte} MB`,\n });\n});\n\nexport function initAll(selection = null) {\n // might be called with Event-argument, if used as EventHandler\n window.tfm.tools.deprecate(\n 'initAll()',\n 'react memory and cpu components',\n '3.0'\n );\n if (\n selection !== null &&\n typeof selection === 'object' &&\n (selection.hasOwnProperty('originalEvent') ||\n selection.constructor === $.Event)\n ) {\n selection = null;\n }\n initByte(selection);\n initCounter(selection);\n}\n\nexport function initCounter(selection = null) {\n // Do not initialize form_templates\n window.tfm.tools.deprecate('initCounter()', 'react cpu component', '3.0');\n $('input.counter_spinner', selection)\n .not('.form_template input.counter_spinner')\n .each(function() {\n const field = $(this);\n const errorMessage = field.closest('.form-group').find('.maximum-limit');\n let min = field.data('min');\n min = typeof min === 'number' ? min : 1;\n\n field.limitedSpinner({\n softMaximum: field.data('softMax'),\n errorTarget: errorMessage,\n min,\n });\n\n field.change(() => {\n field.limitedSpinner('validate');\n });\n\n field\n .parents('div.form-group')\n .find('label a')\n .popover();\n });\n}\n\nexport function initByte(selection = null) {\n // Do not initialize form_templates\n window.tfm.tools.deprecate('initByte()', 'react memory component', '3.0');\n $('input.byte_spinner', selection)\n .not('.form_template input.byte_spinner')\n .each(function() {\n const field = $(this);\n const errorMessage = field.closest('.form-group').find('.maximum-limit');\n const valueTarget = field\n .closest('.form-group')\n .find('.real-hidden-value');\n\n field.byteSpinner({\n valueTarget,\n softMaximum: field.data('softMax'),\n errorTarget: errorMessage,\n });\n\n field.change(() => {\n field.byteSpinner('updateValueTarget');\n field.byteSpinner('validate');\n });\n\n field\n .parents('div.form-group')\n .find('label a')\n .popover();\n });\n}\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/jquery.ui.custom_spinners.js","import React from 'react';\nimport forceSingleton from '../../common/forceSingleton';\n\nexport const getForemanContext = contextData =>\n forceSingleton('Context', () => React.createContext(contextData));\nexport const useForemanContext = () => React.useContext(getForemanContext());\n\nconst useForemanMetadata = () => useForemanContext().metadata;\n\nexport const useForemanVersion = () => useForemanMetadata().version;\nexport const useForemanSettings = () => useForemanMetadata().UISettings;\nexport const useForemanDocUrl = () => useForemanMetadata().docUrl;\nexport const useForemanOrganization = () => useForemanMetadata().organization;\nexport const useForemanLocation = () => useForemanMetadata().location;\nexport const useForemanUser = () => useForemanMetadata().user;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/Root/Context/ForemanContext.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { ConnectedRouter } from 'connected-react-router';\nimport { ApolloProvider } from '@apollo/client';\nimport history from '../history';\nimport { getForemanContext } from '../Root/Context/ForemanContext';\nimport Layout, { propTypes as LayoutPropTypes } from '../components/Layout';\nimport AppSwitcher from '../routes';\n\nimport apolloClient from './apollo';\n\nconst ReactApp = ({ layout, metadata, toasts }) => {\n const contextData = { metadata, toasts };\n const ForemanContext = getForemanContext(contextData);\n\n return (\n
\n
\n \n \n \n \n \n \n \n \n
\n );\n};\n\nReactApp.propTypes = {\n layout: LayoutPropTypes.data.isRequired,\n metadata: PropTypes.object.isRequired,\n toasts: PropTypes.array.isRequired,\n};\n\nexport default ReactApp;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/Root/ReactApp.js","import { ApolloClient, ApolloLink, InMemoryCache, from } from '@apollo/client';\nimport { BatchHttpLink } from '@apollo/client/link/batch-http';\n\nimport { foremanUrl } from '../common/helpers';\n\nconst batchLink = new BatchHttpLink({ uri: foremanUrl('/api/graphql') });\n\nconst authLink = new ApolloLink((operation, forward) => {\n operation.setContext({\n headers: {\n 'X-CSRF-Token': document\n .querySelector('meta[name=csrf-token]')\n .getAttribute('content'),\n },\n });\n return forward(operation);\n});\n\nconst client = new ApolloClient({\n link: from([authLink, batchLink]),\n cache: new InMemoryCache(),\n});\n\nexport default client;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/Root/apollo.js","/* eslint-disable no-console, max-len */\n\nexport const deprecate = (oldMethod, newMethod, version) => {\n if (process.env.NODE_ENV !== 'production')\n console.warn(\n `DEPRECATION WARNING: you are using deprecated ${oldMethod}, it will be removed in Foreman ${version}. Use ${newMethod} instead.`\n );\n};\nexport const deprecateObjectProperty = (obj, oldProp, newProp, version) => {\n const oldPropPointer = obj[oldProp];\n\n Object.defineProperty(obj, oldProp, {\n get: () => {\n deprecate(oldProp, newProp, version);\n return oldPropPointer;\n },\n });\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/common/DeprecationService.js","/* eslint-disable react-hooks/exhaustive-deps */\nimport React, { useEffect, useRef } from 'react';\nimport EmptyPage from '../routes/common/EmptyPage';\nimport LoadingPage from '../routes/common/LoadingPage';\n\n/**\n * HOC that runs a function on the initial mount of the component using useEffect\n * @param {Function} callback - function to run\n */\nexport const callOnMount = callback => WrappedComponent => componentProps => {\n // fires callback onMount, [] means don't listen to any props change\n useEffect(() => {\n callback(componentProps);\n }, []);\n\n return
;\n};\n\n/**\n * HOC that runs a function onPopState if search query has changed,\n * assuming the component has withRouter\n * @param {Function} callback - function to run\n */\nexport const callOnPopState = callback => WrappedComponent => componentProps => {\n const didMount = useRef(false);\n const {\n history: { action },\n location: { search },\n } = componentProps;\n useEffect(() => {\n if (action === 'POP' && didMount.current) {\n callback(componentProps);\n } else {\n didMount.current = true;\n }\n }, [search, action]);\n\n return
;\n};\n\n/**\n * HOC That renders a component based on its state\n *\n * the following root Component props are required\n * { isLoading, hasData, hasError }\n *\n * If the default Error and Empty Components are used\n * the following props are also required:\n *\n * { message: { type, text }}\n * @param {ReactElement} Component - Component to render\n * @param {ReactElement} LoadingComponent - Component to render if Loading\n * @param {ReactElement} ErrorComponent - Component to render if Error\n * @param {ReactElement} EmptyComponent - Component to render if no Data exists\n */\nexport const withRenderHandler = ({\n Component,\n LoadingComponent = LoadingPage,\n ErrorComponent = EmptyPage,\n EmptyComponent = EmptyPage,\n}) => componentProps => {\n const { isLoading, hasData, hasError } = componentProps;\n\n if (isLoading && !hasData) return
;\n if (hasError) return
;\n if (hasData) return
;\n return
;\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/common/HOC.js","import Jed from 'jed';\nimport { addLocaleData } from 'react-intl';\nimport forceSingleton from './forceSingleton';\n\nclass IntlLoader {\n constructor(locale, timezone) {\n this.fallbackIntl = !global.Intl;\n\n // eslint-disable-next-line prefer-destructuring\n this.locale = locale.split('-')[0];\n this.timezone = this.fallbackIntl ? 'UTC' : timezone;\n this.ready = this.init();\n }\n\n async init() {\n await this.fetchIntl();\n addLocaleData(\n await import(\n /* webpackChunkName: 'react-intl/locale/[request]' */ `react-intl/locale-data/${this.locale}`\n )\n );\n return true;\n }\n\n async fetchIntl() {\n if (this.fallbackIntl) {\n global.Intl = await import(/* webpackChunkName: \"intl\" */ 'intl');\n await import(\n /* webpackChunkName: 'intl/locale/[request]' */ `intl/locale-data/jsonp/${this.locale}`\n );\n }\n }\n}\n\nconst htmlElemnt = document.getElementsByTagName('html')[0];\nconst langAttr = htmlElemnt.getAttribute('lang') || 'en';\nconst timezoneAttr = htmlElemnt.getAttribute('data-timezone') || 'UTC';\n\nexport const intl = forceSingleton(\n 'Intl',\n () => new IntlLoader(langAttr, timezoneAttr)\n);\n\nconst cheveronPrefix = () => (window.I18N_MARK ? '\\u00BB' : '');\nconst cheveronSuffix = () => (window.I18N_MARK ? '\\u00AB' : '');\n\nexport const documentLocale = () => langAttr;\n\nconst getLocaleData = () => {\n const locales = window.locales || {};\n const locale = documentLocale().replace(/-/g, '_');\n\n if (locales[locale] === undefined) {\n // eslint-disable-next-line no-console\n console.log(\n `could not load translations for ${locale} locale, falling back to default locale.`\n );\n return { domain: 'app', locale_data: { app: { '': {} } } };\n }\n\n return locales[locale];\n};\n\nexport const jed = forceSingleton('Jed', () => new Jed(getLocaleData()));\n\nexport const translate = (...args) =>\n `${cheveronPrefix()}${jed.gettext(...args)}${cheveronSuffix()}`;\nexport const ngettext = (...args) =>\n `${cheveronPrefix()}${jed.ngettext(...args)}${cheveronSuffix()}`;\n\nexport const { sprintf } = jed;\n\nconst i18n = {\n translate,\n ngettext,\n jed,\n sprintf,\n intl,\n};\nexport default i18n;\n\nwindow.__ = translate;\nwindow.n__ = ngettext;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/common/I18n.js","import ReactDOM from 'react-dom';\nimport store from '../redux';\nimport componentRegistry from '../components/componentRegistry';\n\nexport { default as registerReducer } from '../redux/reducers/registerReducer';\n\nexport function mount(component, selector, data, flattenData = false) {\n const reactNode = document.querySelector(selector);\n if (reactNode) {\n ReactDOM.unmountComponentAtNode(reactNode);\n\n mountNode(component, reactNode, data, flattenData);\n } else {\n // eslint-disable-next-line no-console\n console.log(\n `Cannot find '${selector}' element for mounting the '${component}'`\n );\n }\n}\n\nfunction mountNode(component, reactNode, data, flattenData) {\n ReactDOM.render(\n componentRegistry.markup(component, {\n data,\n store,\n flattenData,\n }),\n reactNode\n );\n}\n\n/**\n * This is a html tag (Web component) that can be used for mounting react component from ComponentRegistry.\n */\nclass ReactComponentElement extends HTMLElement {\n static get observedAttributes() {\n return ['data-props'];\n }\n\n get componentName() {\n return this.getAttribute('name');\n }\n get reactProps() {\n return this.dataset.props !== '' ? JSON.parse(this.dataset.props) : {};\n }\n set reactProps(newProps) {\n this.dataset.props = JSON.stringify(newProps);\n }\n get mountPoint() {\n if (!this._mountPoint) {\n this._mountPoint = this;\n }\n\n return this._mountPoint;\n }\n\n attributeChangedCallback(name, oldValue, newValue) {\n switch (name) {\n case 'data-props':\n // if this is not the initial prop set\n if (oldValue !== null) this._render();\n break;\n default:\n // We don't know how to react to default attribute change\n }\n }\n\n connectedCallback() {\n this._render();\n }\n\n disconnectedCallback() {\n try {\n ReactDOM.unmountComponentAtNode(this.mountPoint);\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error(\n `Unable to unmount foreman-react-component: ${this.componentName}`,\n error\n );\n }\n }\n\n _render() {\n try {\n mountNode(this.componentName, this, this.reactProps, true);\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error(\n `Unable to mount foreman-react-component: ${this.componentName}`,\n error\n );\n }\n }\n}\n\nif (!window.customElements.get('foreman-react-component')) {\n window.customElements.define(\n 'foreman-react-component',\n ReactComponentElement\n );\n}\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/common/MountingService.js","if (!window.sessionStorage) {\n window.sessionStorage = {\n getItem: () => {},\n setItem: () => {},\n };\n}\n\nexport const getValue = key => {\n const value = window.sessionStorage.getItem(key) || 'null';\n\n return JSON.parse(value);\n};\n\nexport const setValue = (key, value) =>\n window.sessionStorage.setItem(key, JSON.stringify(value));\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/common/SessionStorage.js","/**\n * Whether or not the page is focused (beeing used atm)\n * @return {boolean}\n */\nexport const doesDocumentHasFocus = () =>\n document.hasFocus ? document.hasFocus() : true;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/common/document.js","/**\n * Force a single instance to protect from code duplication.\n *\n * WARNING: Code duplications happen because of an issue with the build process,\n * so this method might be removed once the issue would be fixed.\n * See: https://projects.theforeman.org/issues/27195\n *\n * @param {String} key A unique-key to save the instance.\n * @param {Function} create A function to create an instance.\n * @return {*} Single Instance,\n * returned by the create method or from the cache.\n */\nconst forceSingleton = (key, create) => {\n window.tfm_forced_singletons = window.tfm_forced_singletons || {};\n\n if (!window.tfm_forced_singletons[key]) {\n window.tfm_forced_singletons[key] = create();\n }\n\n return window.tfm_forced_singletons[key];\n};\n\nexport default forceSingleton;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/common/forceSingleton.js","import { snakeCase, camelCase, debounce } from 'lodash';\nimport URI from 'urijs';\nimport { translate as __ } from './I18n';\n\n/**\n * Our API returns non-ISO8601 dates\n * This method converts those strings into ISO8601 format\n * @param {String} date - non-ISO date to convert\n */\nexport const isoCompatibleDate = date => {\n if (\n typeof date === 'string' &&\n date.match(/\\d{4}-\\d\\d-\\d\\d\\s\\d\\d:\\d\\d:\\d\\d\\s[+-]?\\d{4}/)\n ) {\n // we've matched a date in the format: 2019-03-14 15:39:27 -0400\n return date.replace(/\\s/, 'T').replace(/\\s/, '');\n }\n\n return date;\n};\n\n/**\n * Add a debounce timeout for your methods.\n * @param {Object} context - the context where your method is running.\n * @param {Number} time - the amount of debounce time in miliseconds.\n * @param {Array} methods - Array that contains the methods to run on.\n */\nexport const debounceMethods = (context, time, methods) => {\n methods.forEach(method => {\n const methodName = method.name || method;\n const methodTime = method.time || time;\n // eslint-disable-next-line no-param-reassign\n context[methodName] = debounce(context[methodName], methodTime);\n });\n};\n\n/**\n * Bind your methods to run in a specific context.\n * @param {Object} context - the context where your method should run.\n * @param {Array} methods - Array that contains the methods to run on.\n */\nexport const bindMethods = (context, methods) => {\n methods.forEach(method => {\n // eslint-disable-next-line no-param-reassign\n context[method] = context[method].bind(context);\n });\n};\n\n/**\n * Removes slashes from the beggining and end of the path\n * @param {String} path - the path that should be removed of slashes\n */\nexport const removeLastSlashFromPath = path => {\n if (!path || path.length < 2) return path;\n const lastCharIndex = path.length - 1;\n return path[lastCharIndex] === '/' ? path.slice(0, -1) : path;\n};\n/**\n * An empty function which is usually used as a default function.\n */\nexport const noop = Function.prototype;\n\n/**\n * Opens the link in a new window.\n * @param {String} url - the path to open in a new window.\n */\nexport const newWindowOnClick = url => event => {\n event.preventDefault();\n const newWindow = window.open(url, '_blank');\n newWindow.opener = null;\n};\n\n/**\n * Clear the spaces in both sides of a string and erase multiple spaces.\n * @param {String} string - the string which should be trimmed.\n */\nexport const clearSpaces = string => string.trim().replace(/\\s\\s+/, ' ');\n\nexport const getDisplayName = Component =>\n Component.displayName || Component.name || 'Component';\n/**\n * Use I18n to translate an object of strings\n * @param {Object.
} obj - the object to translate\n * @returns {Object.} a translated object\n */\nexport const translateObject = obj =>\n Object.assign({}, ...Object.entries(obj).map(([k, v]) => ({ [k]: __(v) })));\n\n/**\n * Use I18n to translate an array of strings\n * @param {Array.} arr - the array to translate\n * @returns {Array.} a translated array\n */\nexport const translateArray = arr => arr.map(str => __(str));\n\n/**\n * Return the query in URL as Objects where keys are\n * the parameters and the values are the parameters' values.\n * @param {String} url - the URL\n */\nexport const getURIQuery = url => new URI(url).query(true);\n\n/**\n * Transform object keys to snake case\n */\nexport const propsToSnakeCase = ob =>\n propsToCase(snakeCase, 'propsToSnakeCase only takes objects', ob);\n\n/**\n * Transform object keys to camel case\n */\nexport const propsToCamelCase = ob =>\n propsToCase(camelCase, 'propsToCamelCase only takes objects', ob);\n\nconst propsToCase = (casingFn, errorMsg, ob) => {\n if (typeof ob !== 'object') throw Error(errorMsg);\n\n return Object.keys(ob).reduce((memo, key) => {\n memo[casingFn(key)] = ob[key];\n return memo;\n }, {});\n};\n\n/**\n * Transform object keys to camel case, works for nested objects\n */\nexport const deepPropsToCamelCase = obj =>\n deepPropsToCase(camelCase, 'propsToCamelCase only takes objects')(obj);\n\n/**\n * Transform object keys to snake case, works for nested objects\n */\nexport const deepPropsToSnakeCase = obj =>\n deepPropsToCase(snakeCase, 'propsToSnakeCase only takes objects')(obj);\n\nconst deepPropsToCase = (casingFn, errorMsg) => obj => {\n if (typeof obj !== 'object' || obj === null) {\n return obj;\n }\n if (Array.isArray(obj)) {\n return obj.map(deepPropsToCase(casingFn, errorMsg));\n }\n const transformed = propsToCase(casingFn, errorMsg, obj);\n return Object.keys(transformed).reduce((memo, key) => {\n memo[key] = deepPropsToCase(casingFn, errorMsg)(transformed[key]);\n return memo;\n }, {});\n};\n\n/**\n * Check if a string is a positive integer\n * @param {String} value - the string\n */\nexport const stringIsPositiveNumber = value => {\n const reg = new RegExp('^[0-9]+$');\n return reg.test(value);\n};\n\n/**\n * Get manual url based on version\n * @param {String} section - section id for foreman documetation\n */\nexport const getManualURL = section => foremanUrl(`/links/manual/${section}`);\nexport const getWikiURL = section => foremanUrl(`/links/wiki/${section}`);\n\n/**\n * Transform the Date object to date string accepted in the server\n * @param {Date}\n * @returns {string}\n */\nexport const formatDate = date => formatDateTime(date).split(' ')[0];\n\n/**\n * Transform the Date object to datetime string accepted in the server\n * @param {Date}\n * @returns {string}\n */\nexport const formatDateTime = date => {\n const zeroPadding = n => (n < 10 ? `0${n}` : n);\n const { year, month, day, hour, minutes } = {\n year: date.getFullYear(),\n month: zeroPadding(date.getMonth() + 1),\n day: zeroPadding(date.getDate()),\n hour: zeroPadding(date.getHours()),\n minutes: zeroPadding(date.getMinutes()),\n };\n\n return `${year}-${month}-${day} ${hour}:${minutes}:00`;\n};\n\n// generates an absolute, needed in case of running Foreman from a subpath\nexport const foremanUrl = path => `${window.URL_PREFIX}${path}`;\n\nexport default {\n isoCompatibleDate,\n bindMethods,\n noop,\n debounceMethods,\n clearSpaces,\n newWindowOnClick,\n getDisplayName,\n translateObject,\n translateArray,\n propsToCamelCase,\n propsToSnakeCase,\n deepPropsToCamelCase,\n deepPropsToSnakeCase,\n stringIsPositiveNumber,\n getManualURL,\n formatDate,\n formatDateTime,\n foremanUrl,\n getWikiURL,\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/common/helpers.js","import { useEffect, useRef } from 'react';\nimport { useSelector, useDispatch } from 'react-redux';\nimport uuid from 'uuid/v1';\nimport {\n selectAPIResponse,\n selectAPIStatus,\n} from '../../../redux/API/APISelectors';\nimport { APIActions } from '../../../redux/API';\n\n/**\n * A custom hook that creates an API request\n * @param {string} method the API method (i.e 'post', 'get' etc)\n * @param {string} url the url for the API request\n * @param {object} options adding optional props to the API call, for more details go to the `apiRequest` function in `redux/API`\n * @return {object} returns an object that contains the response, status, key and 'setUrl' for setting the url dynamically\n */\n\nexport const useAPI = (method, url, options) => {\n const dispatch = useDispatch();\n const keyRef = useRef(options?.key);\n\n useEffect(() => {\n if (!keyRef.current) keyRef.current = uuid();\n }, []);\n\n useEffect(() => {\n if (url && method) {\n dispatch(\n APIActions[method]({\n url,\n ...options,\n key: keyRef.current,\n })\n );\n }\n }, [dispatch, url, method, options]);\n\n const response = useSelector(state =>\n selectAPIResponse(state, keyRef.current)\n );\n const status = useSelector(state => selectAPIStatus(state, keyRef.current));\n\n return { response, status, key: keyRef.current };\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/common/hooks/API/APIHooks.js","import React from 'react';\nimport { IntlProvider } from 'react-intl';\nimport { intl } from './I18n';\nimport { getDisplayName } from './helpers';\n\nconst i18nProviderWrapperFactory = (\n initialNow,\n timezone\n) => WrappedComponent => {\n const wrappedName = getDisplayName(WrappedComponent);\n\n class I18nProviderWrapper extends React.Component {\n constructor(props) {\n super(props);\n this.state = { i18nLoaded: false };\n\n // eslint-disable-next-line promise/prefer-await-to-then\n intl.ready.then(() => {\n this.setState({ i18nLoaded: true });\n });\n }\n\n render() {\n if (!this.state.i18nLoaded) {\n return ;\n }\n return (\n \n \n \n );\n }\n }\n I18nProviderWrapper.displayName = `I18nProviderWrapper(${wrappedName})`;\n\n return I18nProviderWrapper;\n};\n\nexport { i18nProviderWrapperFactory };\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/common/i18nProviderWrapperFactory.js","export const KEYCODES = {\n ENTER: 13,\n FWD_SLASH: 47,\n BACK_SLASH: 46,\n ESC: 27,\n TAB_KEY: 9,\n};\nexport default KEYCODES;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/common/keyCodes.js","import URI from 'urijs';\n\nimport { visit } from '../../foreman_navigation';\n\n/**\n * Build a url from given controller, action and id\n * @param {String} controller - the controller\n * @param {String} action - the action\n */\nexport const urlBuilder = (controller, action, id = undefined) =>\n `/${controller}/${id ? `${id}/` : ''}${action}`;\n\n/**\n * Build a url with search query\n * @param {String} base - the base url\n * @param {String} searchQuery - the search query\n */\nexport const urlWithSearch = (base, searchQuery) =>\n `/${base}?search=${searchQuery}`;\n\n/**\n * Get updated URI\n */\nexport const getURI = () => new URI(window.location.href);\n\n/**\n * Get updated page param\n */\nexport const getURIpage = () => Number(getURI().query(true).page) || 1;\n/**\n * Get updated perPage param\n */\nexport const getURIperPage = () => Number(getURI().query(true).per_page);\n/**\n * Get updated searchQuery param\n */\nexport const getURIsearch = () => getURI().query(true).search || '';\n\n/**\n * Get updated sort param\n */\nexport const getURIsort = () => {\n const sortString = getURI().query(true).order;\n if (!sortString) {\n return {};\n }\n const [by, order] = sortString.split(' ');\n return { by, order };\n};\n\n/**\n * Get updated URI params\n */\nexport const getParams = () => ({\n page: getURIpage(),\n perPage: getURIperPage() || null,\n searchQuery: getURIsearch(),\n sort: getURIsort(),\n});\n\n/**\n * Get updated Stringified params\n */\nexport const stringifyParams = ({\n page = 1,\n perPage = 25,\n searchQuery = '',\n sort = {},\n}) => {\n const uri = getURI();\n if (searchQuery !== '')\n uri.search({ page, per_page: perPage, search: searchQuery });\n else uri.search({ page, per_page: perPage });\n\n if (sort.by && sort.order) {\n uri.setSearch('order', `${sort.by} ${sort.order}`);\n }\n\n return uri.search();\n};\n\n/**\n * change current query and trigger navigation\n * @param {URI} uri - URI object\n * @param {Object} newQuery - Query Object\n * @param {Function} navigateTo - navigate func\n */\nexport const changeQuery = (newQuery, navigateTo, uri = getURI()) => {\n uri.setQuery(newQuery);\n if (navigateTo) navigateTo(uri.toString());\n else visit(uri.toString());\n};\n\nexport const exportURL = () => {\n const url = getURI();\n url.addQuery('format', 'csv');\n return `${url.pathname()}${url.search()}`;\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/common/urlHelpers.js","import React from 'react';\n\nimport { Router } from 'react-router-dom';\nimport history from '../history';\nimport AppSwitcher from '../routes';\n\nconst withReactRoutes = Component => props => (\n \n \n \n \n \n);\n\nexport default withReactRoutes;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/common/withReactRoutes.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { translate as __ } from '../../common/I18n';\nimport EmptyState from '../common/EmptyState';\nimport { foremanUrl } from '../../common/helpers';\n\nexport const WelcomeArchitecture = ({ canCreate }) => {\n const action = canCreate && {\n title: __('Create Architecture'),\n url: foremanUrl('/architectures/new'),\n };\n const content = __(`Each entry represents a particular hardware architecture, most commonly x86_64 or i386.\n Foreman also supports the Solaris operating system family, which includes sparc based systems.`);\n const description = (\n <>\n {__(\n 'Before you proceed to using Foreman you should provide information about one or more architectures.'\n )}\n \n {__(\n 'Each architecture can also be associated with more than one operating system and a selector block is provided to allow you to select valid combinations.'\n )}\n >\n );\n\n return (\n \n );\n};\n\nWelcomeArchitecture.propTypes = {\n canCreate: PropTypes.bool,\n};\n\nWelcomeArchitecture.defaultProps = {\n canCreate: false,\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Architectures/Welcome.js","import React from 'react';\nimport { Col } from 'patternfly-react';\nimport PropTypes from 'prop-types';\n\nconst ActionLinks = ({ allowedActions }) => (\n \n {allowedActions &&\n allowedActions.map(\n ({ url, css_class: CssClassString, disabled, name, title }, index) => (\n \n {name || title}\n \n )\n )}\n \n);\n\nActionLinks.propTypes = {\n allowedActions: PropTypes.arrayOf(\n PropTypes.shape({\n url: PropTypes.string,\n title: PropTypes.string,\n name: PropTypes.string,\n css_class: PropTypes.string,\n disabled: PropTypes.bool,\n })\n ),\n};\n\nActionLinks.defaultProps = {\n allowedActions: [],\n};\n\nexport default ActionLinks;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/AuditsList/ActionLinks.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport DiffContainer from '../DiffView/DiffContainer';\nimport { translate as __ } from '../../common/I18n';\n\nconst renderListItems = items =>\n items &&\n items.map((item, index) =>\n item && typeof item === 'string' && item.length > 0 ? (\n \n {item} | \n
\n ) : null\n );\n\nconst renderCols = changeArr =>\n changeArr &&\n changeArr.map(({ css_class: CssClassStr, id_to_label: idToLabel }, index) => (\n 1\n ? `col-6 col-md-4 ${CssClassStr}`\n : `col-12 col-md-8 ${CssClassStr}`\n }\n >\n \n | \n ));\n\nconst renderTableRows = changeEntries =>\n changeEntries &&\n changeEntries.map(({ name, change }, index) => (\n \n \n {name} \n | \n {renderCols(change)}\n
\n ));\n\nconst showAuditChanges = (\n actionDisplayName,\n auditedChangesWithIdToLabel,\n details\n) => {\n const tableClasses = 'table table-bordered table-hover';\n\n if (['add', 'remove'].includes(actionDisplayName) && details.length > 0) {\n return (\n \n {renderListItems(details)}\n
\n );\n }\n\n if (auditedChangesWithIdToLabel.length > 0) {\n return (\n \n {renderTableRows(auditedChangesWithIdToLabel)}\n
\n );\n }\n return null;\n};\n\nclass ExpansiveView extends React.Component {\n showTemplateDiffIfAny() {\n const { template } = this.props.auditedChanges;\n if (template && template[0] !== template[1]) {\n return ;\n }\n return null;\n }\n\n render() {\n const {\n comment,\n actionDisplayName,\n auditedChangesWithIdToLabel,\n details,\n } = this.props;\n\n return (\n \n {this.showTemplateDiffIfAny()}\n {showAuditChanges(\n actionDisplayName,\n auditedChangesWithIdToLabel,\n details\n )}\n {comment && (\n
\n
\n {__('Comments')}\n
\n
{comment}
\n
\n )}\n
\n );\n }\n}\n\nExpansiveView.propTypes = {\n actionDisplayName: PropTypes.string.isRequired,\n auditedChanges: PropTypes.object.isRequired,\n comment: PropTypes.string,\n auditedChangesWithIdToLabel: PropTypes.arrayOf(\n PropTypes.shape({\n change: PropTypes.arrayOf(\n PropTypes.shape({\n css_class: PropTypes.string,\n id_to_label: PropTypes.string,\n })\n ),\n name: PropTypes.string,\n })\n ),\n details: PropTypes.arrayOf(PropTypes.string),\n};\n\nExpansiveView.defaultProps = {\n comment: undefined,\n auditedChangesWithIdToLabel: [],\n details: undefined,\n};\n\nexport default ExpansiveView;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/AuditsList/ExpansiveView.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport EllipsisWithTooltip from 'react-ellipsis-with-tooltip';\n\nconst SearchLink = ({ url, title, id, textValue }) => {\n const linkProps = {\n href: url,\n title,\n id: `resource-link-${id}`,\n };\n\n return (\n \n {textValue}\n \n );\n};\n\nSearchLink.propTypes = {\n url: PropTypes.string.isRequired,\n id: PropTypes.number.isRequired,\n title: PropTypes.string,\n textValue: PropTypes.string,\n};\n\nSearchLink.defaultProps = {\n title: undefined,\n textValue: '',\n};\n\nexport default SearchLink;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/AuditsList/SearchLink.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { Row, Col } from 'patternfly-react';\nimport EllipsisWithTooltip from 'react-ellipsis-with-tooltip';\nimport { translate as __ } from '../../common/I18n';\n\nconst ShowInlineRequestUuid = ({ fetchAndPush, requestUuid, id }) => (\n \n \n \n {__('Request UUID')}\n \n \n \n \n fetchAndPush({ searchQuery: `request_uuid = ${requestUuid}` })\n }\n title={__(\n 'HTTP request UUID, clicking will filter audits for this request. It can also be used for searching in application logs.'\n )}\n >\n {requestUuid}\n \n \n \n
\n \n);\n\nShowInlineRequestUuid.propTypes = {\n fetchAndPush: PropTypes.func.isRequired,\n requestUuid: PropTypes.string.isRequired,\n id: PropTypes.number.isRequired,\n};\n\nexport default ShowInlineRequestUuid;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/AuditsList/ShowInlineRequestUuid.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { Col } from 'patternfly-react';\nimport ShowTaxonomyInline from './ShowTaxonomyInline';\nimport { translate as __ } from '../../common/I18n';\n\nconst ShowOrgsLocs = ({ orgs, locs }) => (\n \n \n \n \n);\n\nShowOrgsLocs.propTypes = {\n orgs: PropTypes.array,\n locs: PropTypes.array,\n};\n\nShowOrgsLocs.defaultProps = {\n orgs: [],\n locs: [],\n};\n\nexport default ShowOrgsLocs;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/AuditsList/ShowOrgsLocs.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { Row, Col } from 'patternfly-react';\n\nconst ShowTaxonomyInline = ({ displayLabel, items }) => {\n const listItems = items.map(\n ({ name, url, disabled, css_class: addCSS }, index) => (\n \n {name}\n \n )\n );\n\n return (\n \n \n {displayLabel}\n \n \n {items && listItems}\n \n
\n );\n};\n\nShowTaxonomyInline.propTypes = {\n displayLabel: PropTypes.string,\n items: PropTypes.arrayOf(\n PropTypes.shape({\n name: PropTypes.string,\n url: PropTypes.string,\n css_class: PropTypes.string,\n disabled: PropTypes.bool,\n })\n ),\n};\n\nShowTaxonomyInline.defaultProps = {\n displayLabel: '',\n items: [],\n};\n\nexport default ShowTaxonomyInline;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/AuditsList/ShowTaxonomyInline.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport EllipsisWithTooltip from 'react-ellipsis-with-tooltip';\nimport { translate as __ } from '../../common/I18n';\n\nconst UserDetails = ({ isAuditLogin, userInfo, remoteAddress }) => {\n const {\n search_path: searchPath,\n display_name: UserDisplayName,\n audit_path: auditPath,\n } = userInfo;\n\n const linkProps = {\n href: searchPath,\n title: __('Filter audits for this user only'),\n className: 'user-info',\n };\n\n if (isAuditLogin) {\n return (\n \n \n \n {UserDisplayName}\n \n \n \n {__('Logged-in')}\n \n \n );\n }\n\n return (\n \n \n \n {UserDisplayName}\n \n \n {remoteAddress ? (\n ({remoteAddress})\n ) : null}\n \n );\n};\n\nUserDetails.propTypes = {\n userInfo: PropTypes.shape({\n search_path: PropTypes.string,\n display_name: PropTypes.string,\n audit_path: PropTypes.string,\n }).isRequired,\n isAuditLogin: PropTypes.bool,\n remoteAddress: PropTypes.string,\n};\n\nUserDetails.defaultProps = {\n isAuditLogin: false,\n remoteAddress: undefined,\n};\n\nexport default UserDetails;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/AuditsList/UserDetails.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { ListView, Row } from 'patternfly-react';\nimport SearchLink from './SearchLink';\nimport ShowInlineRequestUuid from './ShowInlineRequestUuid';\nimport ShowOrgsLocs from './ShowOrgsLocs';\nimport ActionLinks from './ActionLinks';\nimport ExpansiveView from './ExpansiveView';\nimport UserDetails from './UserDetails';\nimport { translate as __ } from '../../common/I18n';\nimport ShortDateTime from '../common/dates/ShortDateTime';\nimport './audit.scss';\n\nconst isAuditLogin = auditedChanges => {\n let name;\n try {\n [name] = Object.keys(auditedChanges);\n } catch (e) {\n name = '';\n }\n return name === 'last_login_on';\n};\n\nconst description = actionDisplayName => (\n \n {actionDisplayName}\n \n);\n\nconst renderAdditionalInfoItems = items =>\n items &&\n items.map((item, index) => (\n {item}\n ));\n\nconst renderTimestamp = date => (\n \n \n \n);\n\nconst renderResourceLink = (auditTitle, auditTitleUrl, id) => {\n if (auditTitleUrl) {\n return (\n \n );\n }\n return auditTitle;\n};\n\nconst AuditsList = ({ data: { audits }, fetchAndPush }) => {\n const initExpanded = audits.length === 1;\n return (\n \n {audits.map(\n ({\n id,\n created_at: createdAt,\n audited_type_name: auditedTypeName,\n audit_title: auditTitle,\n audit_title_url: auditTitleUrl,\n audited_changes: auditedChanges,\n user_info: userInfo,\n remote_address: remoteAddress,\n action_display_name: actionDisplayName,\n affected_organizations: affectedOrganizations,\n affected_locations: affectedLocations,\n allowed_actions: allowedActions,\n request_uuid: requestUuid,\n comment,\n audited_changes_with_id_to_label: auditedChangesWithIdToLabel,\n details,\n }) => (\n \n }\n description={description(actionDisplayName)}\n stacked={false}\n hideCloseIcon\n initExpanded={initExpanded}\n >\n \n \n \n
\n\n \n \n
\n\n \n \n )\n )}\n \n );\n};\nAuditsList.propTypes = {\n data: PropTypes.shape({\n audits: PropTypes.array.isRequired,\n }).isRequired,\n fetchAndPush: PropTypes.func.isRequired,\n};\n\nexport default AuditsList;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/AuditsList/index.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { translate as __ } from '../../common/I18n';\nimport EmptyState from '../common/EmptyState';\nimport { foremanUrl, getManualURL } from '../../common/helpers';\n\nexport const WelcomeAuthSource = ({ canCreate }) => {\n const content = __(\n `The authentication process currently requires an LDAP provider, such as FreeIPA, OpenLDAP or Microsoft's Active Directory.`\n );\n const description = (\n <>\n {__(\n 'Foreman can use LDAP based service for user information and authentication.'\n )}\n \n \n {__('Learn more about LDAP authentication in the documentation.')}\n \n
\n {__(\n 'Foreman can use External service for user information and authentication.'\n )}\n
\n \n {__('Learn more about External authentication in the documentation.')}\n \n >\n );\n const action = canCreate && {\n title: __('Create LDAP Authentication Source'),\n url: foremanUrl('auth_source_ldaps/new'),\n };\n\n return (\n \n );\n};\n\nWelcomeAuthSource.propTypes = {\n canCreate: PropTypes.bool,\n};\n\nWelcomeAuthSource.defaultProps = {\n canCreate: false,\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/AuthSource/Welcome.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { TypeAheadSelect } from 'patternfly-react';\nimport classNames from 'classnames';\nimport Immutable from 'seamless-immutable';\nimport { bindMethods, debounceMethods, noop } from '../../common/helpers';\nimport AutoCompleteMenu from './components/AutoCompleteMenu';\nimport AutoCompleteSearchButton from './components/AutoCompleteSearchButton';\nimport AutoCompleteError from './components/AutoCompleteError';\nimport AutoCompleteAux from './components/AutoCompleteAux';\nimport AutoCompleteFocusShortcut from './components/AutoCompleteFocusShortcut';\nimport { STATUS } from '../../constants';\nimport { TRIGGERS } from './AutoCompleteConstants';\nimport { KEYCODES } from '../../common/keyCodes';\nimport { translate as __ } from '../../common/I18n';\nimport './auto-complete.scss';\n\nclass AutoComplete extends React.Component {\n constructor(props) {\n super(props);\n bindMethods(this, [\n 'handleClear',\n 'handleInputChange',\n 'handleResultsChange',\n 'handleInputFocus',\n 'getResults',\n 'windowKeyPressHandler',\n 'handleKeyDown',\n ]);\n this._typeahead = React.createRef();\n debounceMethods(this, 500, ['handleLoading']);\n }\n\n componentDidMount() {\n window.addEventListener('keypress', this.windowKeyPressHandler);\n const {\n controller,\n searchQuery,\n disabled,\n error,\n id,\n url,\n initialUpdate,\n } = this.props;\n\n initialUpdate({ searchQuery, controller, id, disabled, error, url });\n }\n\n componentDidUpdate(prevProps) {\n this.handleLoading();\n const { searchQuery, trigger } = this.props;\n const { RESET, CONTROLLER_CHANGED } = TRIGGERS;\n if (trigger === RESET || trigger === CONTROLLER_CHANGED) {\n this.handleClear();\n }\n if (prevProps.searchQuery !== searchQuery) {\n const typeahead = this._typeahead && this._typeahead.current;\n typeahead && typeahead.setState({ text: searchQuery });\n }\n }\n\n windowKeyPressHandler(e) {\n const { useKeyShortcuts, handleSearch } = this.props;\n const instance = this._typeahead.current.getInstance();\n const { ENTER, FWD_SLASH, BACK_SLASH } = KEYCODES;\n const { tagName } = e.target;\n const didEventCameFromInput = tagName === 'INPUT' || tagName === 'TEXTAREA';\n\n /**\n Disable this functionality if the event came from an input,\n or if the 'useKeyShortcuts' is falsy.\n */\n if (didEventCameFromInput || !useKeyShortcuts) {\n return;\n }\n\n switch (e.charCode) {\n case ENTER: {\n handleSearch();\n break;\n }\n case FWD_SLASH:\n case BACK_SLASH: {\n const {\n focus,\n state: { showMenu },\n } = instance;\n const isMenuHidden = !showMenu;\n if (isMenuHidden) {\n e.preventDefault();\n focus();\n }\n break;\n }\n default: {\n break;\n }\n }\n }\n\n getResults(searchQuery, trigger, id) {\n const { getResults, controller, url } = this.props;\n getResults({\n url,\n searchQuery,\n controller,\n trigger,\n id,\n });\n }\n\n handleInputFocus({ target: { value } }) {\n const { id, results } = this.props;\n if (results.length === 0) {\n this.getResults(value, TRIGGERS.INPUT_FOCUS, id);\n }\n }\n\n handleInputChange(searchQuery) {\n const { id } = this.props;\n this.getResults(searchQuery, TRIGGERS.INPUT_CHANGE, id);\n }\n\n // Gets the first result from an array of selected results.\n handleResultsChange({ 0: result }) {\n const { id } = this.props;\n if (!result) {\n return;\n }\n this.getResults(result, TRIGGERS.ITEM_SELECT, id);\n /**\n * HACK: I had no choice but to call to an inner function,\n * due to lack of design in react-bootstrap-typeahead.\n */\n this._typeahead.current.getInstance()._showMenu();\n }\n\n handleKeyDown({ keyCode }) {\n const instance = this._typeahead.current.getInstance();\n switch (keyCode) {\n case KEYCODES.ENTER: {\n if (!instance.state.activeItem) {\n this.props.handleSearch();\n }\n break;\n }\n case KEYCODES.ESC: {\n instance.blur();\n break;\n }\n default: {\n break;\n }\n }\n }\n\n handleClear() {\n const { id } = this.props;\n this._typeahead.current.getInstance().clear();\n this.getResults('', TRIGGERS.INPUT_CLEAR, id);\n }\n\n handleLoading() {\n const { status } = this.props;\n const typeahead = this._typeahead && this._typeahead.current;\n const isLoading = status === STATUS.PENDING;\n typeahead && typeahead.setState({ isLoading });\n }\n\n componentWillUnmount() {\n window.removeEventListener('keypress', this.windowKeyPressHandler);\n const { resetData, controller, id } = this.props;\n resetData(controller, id);\n }\n\n render() {\n const {\n id,\n error,\n name,\n value,\n searchQuery,\n inputProps,\n placeholder,\n results,\n useKeyShortcuts,\n disabled,\n } = this.props;\n /** Using a 3rd party library (react-bootstrap-typeahead) that expects a mutable array. */\n const options = Immutable.isImmutable(results)\n ? results.asMutable()\n : results;\n\n return (\n \n
(\n \n )}\n inputProps={{\n className: classNames(\n 'search-input',\n useKeyShortcuts ? 'use-shortcuts' : ''\n ),\n spellCheck: 'false',\n 'data-autocomplete-id': id,\n autoComplete: 'off',\n name,\n ...inputProps,\n }}\n />\n \n \n \n \n );\n }\n}\n\nAutoComplete.propTypes = {\n id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,\n url: PropTypes.string.isRequired,\n name: PropTypes.string,\n value: PropTypes.string,\n results: PropTypes.array,\n searchQuery: PropTypes.string,\n inputProps: PropTypes.object,\n status: PropTypes.string,\n error: PropTypes.string,\n initialError: PropTypes.string,\n controller: PropTypes.string,\n handleSearch: PropTypes.func,\n getResults: PropTypes.func,\n resetData: PropTypes.func,\n initialUpdate: PropTypes.func,\n useKeyShortcuts: PropTypes.bool,\n placeholder: PropTypes.string,\n disabled: PropTypes.bool,\n trigger: PropTypes.string,\n};\n\nAutoComplete.defaultProps = {\n name: null,\n value: null,\n results: [],\n searchQuery: '',\n inputProps: {},\n status: null,\n error: null,\n initialError: null,\n controller: null,\n handleSearch: noop,\n getResults: noop,\n resetData: noop,\n initialUpdate: noop,\n useKeyShortcuts: false,\n placeholder: 'Filter ...',\n disabled: false,\n trigger: null,\n};\n\nAutoComplete.SearchButton = AutoCompleteSearchButton;\nAutoComplete.Error = AutoCompleteError;\n\nexport default AutoComplete;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/AutoComplete/AutoComplete.js","import URI from 'urijs';\nimport { debounce } from 'lodash';\nimport { API } from '../../redux/API';\nimport { STATUS } from '../../constants';\nimport { clearSpaces } from '../../common/helpers';\nimport {\n AUTO_COMPLETE_INIT,\n AUTO_COMPLETE_REQUEST,\n AUTO_COMPLETE_SUCCESS,\n AUTO_COMPLETE_FAILURE,\n AUTO_COMPLETE_RESET,\n AUTO_COMPLETE_DISABLED_CHANGE,\n AUTO_COMPLETE_CONTROLLER_CHANGE,\n TRIGGERS,\n} from './AutoCompleteConstants';\n\nexport const getResults = ({\n url,\n searchQuery,\n controller,\n trigger,\n id,\n}) => dispatch => {\n dispatch(\n startRequest({\n controller,\n searchQuery,\n trigger,\n dispatch,\n id,\n url,\n })\n );\n\n return createAPIRequest({\n searchQuery,\n trigger,\n id,\n dispatch,\n url,\n });\n};\n\nlet createAPIRequest = async ({ searchQuery, trigger, id, dispatch, url }) => {\n if (!url) {\n return dispatch(\n requestFailure({\n error: new Error('No API path was provided.'),\n id,\n dispatch,\n isVisible: false,\n })\n );\n }\n try {\n const path = getAPIPath({ trigger, searchQuery, url });\n const { data } = await API.get(path);\n\n return dispatch(\n requestSuccess({\n data,\n dispatch,\n trigger,\n id,\n })\n );\n } catch (error) {\n return dispatch(\n requestFailure({\n error,\n id,\n dispatch,\n isVisible: error.message === 'Network Error',\n })\n );\n }\n};\n\ncreateAPIRequest = debounce(createAPIRequest, 250);\n\nconst startRequest = ({ controller, searchQuery, trigger, id, url }) => ({\n type: AUTO_COMPLETE_REQUEST,\n payload: {\n controller,\n searchQuery,\n status: STATUS.PENDING,\n trigger,\n error: null,\n id,\n url,\n },\n});\n\nconst requestSuccess = ({ data, trigger, id }) => {\n const { error } = data[0] || {};\n if (error) {\n return requestFailure({ error: new Error(error), id });\n }\n if (!Array.isArray(data)) {\n const noDataError = new Error(\n `Response data is not an array, instead received: ${JSON.stringify(data)}`\n );\n return requestFailure({\n error: noDataError,\n id,\n isVisible: false,\n });\n }\n const results = data.map(result => objectDeepTrim(result, trigger));\n return {\n type: AUTO_COMPLETE_SUCCESS,\n payload: {\n results,\n status: STATUS.RESOLVED,\n id,\n },\n };\n};\n\nconst requestFailure = ({ error, id, isVisible = true }) => ({\n type: AUTO_COMPLETE_FAILURE,\n payload: {\n results: [],\n error: error.message,\n isErrorVisible: isVisible,\n status: STATUS.ERROR,\n id,\n },\n});\n\nconst isFinishedWithPoint = string => string.slice(-1) === '.';\n\nconst getAPIPath = ({ trigger, searchQuery, url }) => {\n const loadNextResults =\n trigger === TRIGGERS.ITEM_SELECT && !isFinishedWithPoint(searchQuery)\n ? ' '\n : '';\n const APISearchQuery = searchQuery + loadNextResults;\n const APIPath = new URI(url);\n APIPath.addSearch({ search: APISearchQuery });\n return APIPath.toString();\n};\n\nexport const resetData = (controller, id) => ({\n type: AUTO_COMPLETE_RESET,\n payload: { controller, id },\n});\n\nexport const initialUpdate = ({\n searchQuery,\n controller,\n error,\n id,\n url,\n disabled,\n}) => ({\n type: AUTO_COMPLETE_INIT,\n payload: {\n searchQuery,\n controller,\n trigger: TRIGGERS.COMPONENT_DID_MOUNT,\n status: STATUS.RESOLVED,\n error,\n isErrorVisible: !!error,\n id,\n disabled,\n url,\n },\n});\n\nconst objectDeepTrim = (obj, trigger) => {\n const copy = { ...obj };\n Object.keys(copy).forEach(key => {\n const addSpace =\n key === 'label' && trigger === TRIGGERS.ITEM_SELECT ? ' ' : '';\n copy[key] = clearSpaces(copy[key]) + addSpace;\n });\n return copy;\n};\n\nexport const updateDisability = (disabled, id) => ({\n type: AUTO_COMPLETE_DISABLED_CHANGE,\n payload: {\n disabled,\n id,\n },\n});\n\nexport const updateController = (controller, url, id) => ({\n type: AUTO_COMPLETE_CONTROLLER_CHANGE,\n payload: {\n controller,\n url,\n trigger: TRIGGERS.CONTROLLER_CHANGED,\n id,\n },\n});\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/AutoComplete/AutoCompleteActions.js","export const AUTO_COMPLETE_INIT = 'AUTO_COMPLETE_INIT';\nexport const AUTO_COMPLETE_REQUEST = 'AUTO_COMPLETE_REQUEST';\nexport const AUTO_COMPLETE_SUCCESS = 'AUTO_COMPLETE_SUCCESS';\nexport const AUTO_COMPLETE_FAILURE = 'AUTO_COMPLETE_FAILURE';\nexport const AUTO_COMPLETE_RESET = 'AUTO_COMPLETE_RESET';\nexport const AUTO_COMPLETE_DISABLED_CHANGE = 'AUTO_COMPLETE_DISABLED_CHANGE';\nexport const AUTO_COMPLETE_CONTROLLER_CHANGE =\n 'AUTO_COMPLETE_CONTROLLER_CHANGE';\nexport const TRIGGERS = {\n INPUT_FOCUS: 'INPUT_FOCUS',\n INPUT_CHANGE: 'INPUT_CHANGE',\n ITEM_SELECT: 'ITEM_SELECT',\n INPUT_CLEAR: 'INPUT_CLEAR',\n COMPONENT_DID_MOUNT: 'COMPONENT_DID_MOUNT',\n RESET: 'RESET',\n CONTROLLER_CHANGED: 'CONTROLLER_CHANGED',\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/AutoComplete/AutoCompleteConstants.js","import Immutable from 'seamless-immutable';\nimport {\n AUTO_COMPLETE_INIT,\n AUTO_COMPLETE_REQUEST,\n AUTO_COMPLETE_SUCCESS,\n AUTO_COMPLETE_FAILURE,\n AUTO_COMPLETE_RESET,\n AUTO_COMPLETE_DISABLED_CHANGE,\n AUTO_COMPLETE_CONTROLLER_CHANGE,\n TRIGGERS,\n} from './AutoCompleteConstants';\n\nconst initialAutocompleteState = {\n controller: null,\n error: null,\n isErrorVisible: false,\n results: [],\n searchQuery: '',\n status: null,\n trigger: null,\n url: undefined,\n disabled: false,\n};\n\nexport default (state = Immutable({}), action) => {\n const {\n type,\n payload: {\n controller,\n error,\n results,\n searchQuery,\n status,\n trigger,\n isErrorVisible,\n id,\n disabled,\n url,\n } = {},\n } = action;\n switch (type) {\n case AUTO_COMPLETE_INIT:\n return state.setIn([id], {\n ...state[id],\n controller,\n error,\n isErrorVisible,\n results,\n searchQuery,\n status,\n trigger,\n disabled,\n url,\n });\n case AUTO_COMPLETE_REQUEST:\n return state.setIn([id], {\n ...state[id],\n controller,\n error,\n searchQuery,\n status,\n trigger,\n url,\n });\n case AUTO_COMPLETE_SUCCESS:\n return state.setIn([id], {\n ...state[id],\n results,\n status,\n });\n case AUTO_COMPLETE_FAILURE:\n return state.setIn([id], {\n ...state[id],\n error,\n isErrorVisible,\n results,\n status,\n });\n case AUTO_COMPLETE_RESET:\n return state.setIn([id], {\n ...initialAutocompleteState,\n trigger: TRIGGERS.RESET,\n });\n case AUTO_COMPLETE_DISABLED_CHANGE:\n return state.setIn([id], {\n ...state[id],\n disabled,\n });\n case AUTO_COMPLETE_CONTROLLER_CHANGE:\n return state.setIn([id], {\n ...state[id],\n controller,\n url,\n trigger,\n });\n default:\n return state;\n }\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/AutoComplete/AutoCompleteReducer.js","import { TRIGGERS } from './AutoCompleteConstants';\n\nexport const selectAutocomplete = ({ autocomplete }, id) => autocomplete[id];\n\nexport const selectAutocompleteProp = (state, id, prop, ownProps) => {\n const selectedAutocomplete = selectAutocomplete(state, id);\n const isAutocompleteInitiated = selectedAutocomplete !== undefined;\n const { trigger } = selectedAutocomplete || {};\n const didComponentReset = prop !== 'trigger' && trigger === TRIGGERS.RESET;\n const propFromOwnProps = ownProps && ownProps[prop];\n\n if (isAutocompleteInitiated) {\n if (didComponentReset) {\n return propFromOwnProps;\n }\n return selectedAutocomplete[prop];\n }\n return propFromOwnProps;\n};\n\nexport const selectAutocompleteError = (state, id, ownProps) => {\n const isErrorVisible = selectAutocompleteIsErrorVisible(state, id, ownProps);\n if (!isErrorVisible) {\n return null;\n }\n return selectAutocompleteProp(state, id, 'error', ownProps);\n};\n\nexport const selectAutocompleteIsErrorVisible = (state, id, ownProps) =>\n selectAutocompleteProp(state, id, 'isErrorVisible', ownProps);\n\nexport const selectAutocompleteResults = (state, id, ownProps) =>\n selectAutocompleteProp(state, id, 'results', ownProps);\n\nexport const selectAutocompleteSearchQuery = (state, id, ownProps) =>\n selectAutocompleteProp(state, id, 'searchQuery', ownProps);\n\nexport const selectAutocompleteStatus = (state, id, ownProps) =>\n selectAutocompleteProp(state, id, 'status', ownProps);\n\nexport const selectAutocompleteController = (state, id, ownProps) =>\n selectAutocompleteProp(state, id, 'controller', ownProps);\n\nexport const selectAutocompleteTrigger = (state, id, ownProps) =>\n selectAutocompleteProp(state, id, 'trigger', ownProps);\n\nexport const selectAutocompleteUrl = (state, id, ownProps) =>\n selectAutocompleteProp(state, id, 'url', ownProps);\n\nexport const selectAutocompleteIsDisabled = (state, id, ownProps) =>\n selectAutocompleteProp(state, id, 'disabled', ownProps);\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/AutoComplete/AutoCompleteSelectors.js","import React from 'react';\nimport AutoCompleteClearButton from './AutoCompleteClearButton';\n\nconst AutoCompleteAux = ({ ...props }) => (\n \n);\n\nAutoCompleteAux.propTypes = {\n ...AutoCompleteClearButton.propTypes,\n};\n\nAutoCompleteAux.defaultProps = {\n ...AutoCompleteClearButton.defaultProps,\n};\n\nexport default AutoCompleteAux;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/AutoComplete/components/AutoCompleteAux.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport UUID from 'uuid/v1';\nimport { Icon, OverlayTrigger, Tooltip } from 'patternfly-react';\nimport { noop } from '../../../common/helpers';\nimport { translate as __ } from '../../../common/I18n';\n\nconst AutoCompleteClearButton = ({ onClear }) => (\n {__('Clear')}}\n placement=\"top\"\n trigger={['hover', 'focus']}\n >\n \n \n);\n\nAutoCompleteClearButton.propTypes = {\n onClear: PropTypes.func,\n};\n\nAutoCompleteClearButton.defaultProps = {\n onClear: noop,\n};\n\nexport default AutoCompleteClearButton;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/AutoComplete/components/AutoCompleteClearButton.js","import React from 'react';\nimport PropTypes from 'prop-types';\n\nconst AutoCompleteError = ({ error }) => (\n {error}
\n);\n\nAutoCompleteError.propTypes = {\n error: PropTypes.string,\n};\n\nAutoCompleteError.defaultProps = {\n error: null,\n};\n\nexport default AutoCompleteError;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/AutoComplete/components/AutoCompleteError.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport UUID from 'uuid/v1';\nimport classNames from 'classnames';\nimport { OverlayTrigger, Tooltip } from 'patternfly-react';\nimport { translate as __ } from '../../../common/I18n';\n\nconst AutoCompleteFocusShortcut = ({ useKeyShortcuts }) => {\n const tooltip = useKeyShortcuts && (\n {__(\"Press ' / ' to focus on search\")}\n );\n return (\n \n \n /\n \n \n );\n};\n\nAutoCompleteFocusShortcut.propTypes = {\n useKeyShortcuts: PropTypes.bool,\n};\n\nAutoCompleteFocusShortcut.defaultProps = {\n useKeyShortcuts: false,\n};\n\nexport default AutoCompleteFocusShortcut;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/AutoComplete/components/AutoCompleteFocusShortcut.js","import React, { Fragment } from 'react';\nimport PropTypes from 'prop-types';\nimport { groupBy } from 'lodash';\nimport { TypeAheadSelect } from 'patternfly-react';\nimport SubstringWrapper from '../../common/SubstringWrapper';\n\nconst { Menu, MenuItem } = TypeAheadSelect;\nconst { Divider, Header } = Menu;\n\nconst AutoCompleteMenu = ({ results, menuProps }) => {\n if (results && results.length === 0) {\n return null;\n }\n\n let itemIndex = 0;\n const grouped = groupBy(results, r => r.category);\n const getMenuItemsByCategory = category =>\n grouped[category].map(result => {\n const item = (\n \n );\n itemIndex += 1;\n return item;\n });\n const items = Object.keys(grouped)\n .sort()\n .map(category => (\n \n {!!itemIndex && }\n \n {getMenuItemsByCategory(category)}\n \n ));\n return ;\n};\n\nAutoCompleteMenu.propTypes = {\n results: PropTypes.array,\n menuProps: PropTypes.object,\n};\n\nAutoCompleteMenu.defaultProps = {\n results: [],\n menuProps: {},\n};\n\nexport default AutoCompleteMenu;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/AutoComplete/components/AutoCompleteMenu.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { Button, Col, Icon } from 'patternfly-react';\nimport { translate as __ } from '../../../common/I18n';\n\nconst SearchButton = ({ className, children, ...props }) => (\n \n);\n\nSearchButton.propTypes = {\n className: PropTypes.string,\n children: PropTypes.node,\n};\n\nSearchButton.defaultProps = {\n className: '',\n children: __('Search'),\n};\n\nexport default SearchButton;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/AutoComplete/components/AutoCompleteSearchButton.js","import { connect } from 'react-redux';\nimport { bindActionCreators } from 'redux';\nimport * as actions from './AutoCompleteActions';\nimport reducer from './AutoCompleteReducer';\nimport AutoComplete from './AutoComplete';\nimport {\n selectAutocompleteError,\n selectAutocompleteResults,\n selectAutocompleteSearchQuery,\n selectAutocompleteStatus,\n selectAutocompleteIsDisabled,\n selectAutocompleteUrl,\n selectAutocompleteTrigger,\n} from './AutoCompleteSelectors';\n\nconst mapStateToProps = (state, ownProps) => {\n const { id } = ownProps;\n return {\n error: selectAutocompleteError(state, id, ownProps),\n results: selectAutocompleteResults(state, id, ownProps),\n searchQuery: selectAutocompleteSearchQuery(state, id, ownProps),\n status: selectAutocompleteStatus(state, id, ownProps),\n disabled: selectAutocompleteIsDisabled(state, id, ownProps),\n url: selectAutocompleteUrl(state, id, ownProps),\n trigger: selectAutocompleteTrigger(state, id, ownProps),\n };\n};\n\nconst mapDispatchToProps = dispatch => bindActionCreators(actions, dispatch);\n\nexport const reducers = { autocomplete: reducer };\n\nexport default connect(mapStateToProps, mapDispatchToProps)(AutoComplete);\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/AutoComplete/index.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport EllipisWithTooltip from 'react-ellipsis-with-tooltip';\nimport { Dropdown, MenuItem, Spinner, Icon } from 'patternfly-react';\nimport { PlusIcon } from '@patternfly/react-icons';\nimport SearchModal from './components/SearchModal';\nimport Bookmark from './components/Bookmark';\nimport DocumentationUrl from '../common/DocumentationLink';\nimport { STATUS } from '../../constants';\nimport { noop } from '../../common/helpers';\nimport { sprintf, translate as __ } from '../../../react_app/common/I18n';\nimport history from '../../history';\nimport { stringifyParams } from '../../common/urlHelpers';\n\nconst Bookmarks = props => {\n const loadBookmarks = () => {\n const { bookmarks, status, url, controller, getBookmarks } = props;\n\n if (bookmarks.length === 0 && status !== STATUS.PENDING) {\n getBookmarks(url, controller);\n }\n };\n\n const manageBookmarks = controller => {\n const query = stringifyParams({ searchQuery: `controller=${controller}` });\n history.push({ pathname: '/bookmarks', search: query });\n };\n\n const {\n controller,\n url,\n canCreate,\n bookmarks,\n errors,\n status,\n documentationUrl,\n onBookmarkClick,\n setModalOpen,\n setModalClosed,\n } = props;\n\n return (\n \n \n \n \n \n \n \n {canCreate && (\n \n )}\n \n \n {status === STATUS.PENDING && (\n \n \n \n )}\n {status === STATUS.RESOLVED &&\n ((bookmarks.length > 0 &&\n bookmarks.map(({ name, query }) => (\n \n ))) || )}\n {status === STATUS.ERROR && (\n \n )}\n \n {canCreate && (\n \n )}\n \n \n \n \n );\n};\n\nBookmarks.propTypes = {\n controller: PropTypes.string.isRequired,\n onBookmarkClick: PropTypes.func.isRequired,\n url: PropTypes.string.isRequired,\n canCreate: PropTypes.bool,\n bookmarks: PropTypes.array,\n errors: PropTypes.string,\n status: PropTypes.string,\n documentationUrl: PropTypes.string,\n getBookmarks: PropTypes.func,\n setModalOpen: PropTypes.func.isRequired,\n setModalClosed: PropTypes.func.isRequired,\n};\n\nBookmarks.defaultProps = {\n canCreate: false,\n bookmarks: [],\n errors: '',\n status: null,\n documentationUrl: '',\n getBookmarks: noop,\n};\n\nexport default Bookmarks;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Bookmarks/Bookmarks.js","import URI from 'urijs';\nimport { get } from '../../redux/API';\nimport { BOOKMARKS } from './BookmarksConstants';\n\nconst _getBookmarks = (url, controller) =>\n get({\n key: BOOKMARKS,\n url,\n payload: { controller },\n });\n\nexport const getBookmarks = (url, controller) => {\n const uri = new URI(url);\n\n // eslint-disable-next-line camelcase\n uri.setSearch({ search: `controller=${controller}`, per_page: 'all' });\n\n return _getBookmarks(uri.toString(), controller);\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Bookmarks/BookmarksActions.js","export const BOOKMARKS = 'BOOKMARKS';\nexport const BOOKMARKS_REQUEST = 'BOOKMARKS_REQUEST';\nexport const BOOKMARKS_SUCCESS = 'BOOKMARKS_SUCCESS';\nexport const BOOKMARKS_FAILURE = 'BOOKMARKS_FAILURE';\nexport const BOOKMARKS_FORM_SUBMITTED = 'BOOKMARKS_FORM_SUBMITTED';\n\nexport const BOOKMARKS_MODAL = 'bookmarksModal';\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Bookmarks/BookmarksConstants.js","import Immutable from 'seamless-immutable';\nimport {\n BOOKMARKS_REQUEST,\n BOOKMARKS_SUCCESS,\n BOOKMARKS_FAILURE,\n BOOKMARKS_FORM_SUBMITTED,\n} from './BookmarksConstants';\nimport { STATUS } from '../../constants';\n\nexport const initialState = Immutable({});\n\nconst sortByName = (a, b) => {\n if (a.name < b.name) {\n return -1;\n }\n if (a.name > b.name) {\n return 1;\n }\n // names must be equal\n return 0;\n};\n\nexport default (state = initialState, { type, payload, response }) => {\n switch (type) {\n case BOOKMARKS_REQUEST:\n return state.set(payload.controller, {\n results: [],\n errors: null,\n status: STATUS.PENDING,\n });\n case BOOKMARKS_SUCCESS:\n return state\n .setIn([payload.controller, 'results'], response.results)\n .setIn([payload.controller, 'status'], STATUS.RESOLVED);\n case BOOKMARKS_FORM_SUBMITTED:\n return state.setIn(\n [payload.data.controller, 'results'],\n [...state[payload.data.controller].results, payload.data].sort(\n sortByName\n )\n );\n case BOOKMARKS_FAILURE:\n return state\n .setIn([payload.controller, 'errors'], response)\n .setIn([payload.controller, 'status'], STATUS.ERROR);\n default:\n return state;\n }\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Bookmarks/BookmarksReducer.js","const selectBookmarkState = state => state.bookmarks;\n\nconst selectBookmarksSubState = (state, controller) =>\n selectBookmarkState(state)[controller];\n\nconst selectBookmarksStateByController = (\n state,\n controller,\n attr,\n defaultValue\n) => {\n const bookmarksState = selectBookmarksSubState(state, controller);\n return bookmarksState ? bookmarksState[attr] : defaultValue;\n};\n\nexport const selectBookmarksStatus = (state, controller) =>\n selectBookmarksStateByController(state, controller, 'status', 'RESOLVED');\n\nexport const selectBookmarksResults = (state, controller) =>\n selectBookmarksStateByController(state, controller, 'results', []);\n\nexport const selectBookmarksErrors = (state, controller) =>\n selectBookmarksStateByController(state, controller, 'errors', null);\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Bookmarks/BookmarksSelectors.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { MenuItem } from 'patternfly-react';\nimport EllipisWithTooltip from 'react-ellipsis-with-tooltip';\n\nconst Bookmark = ({ text, query, onClick }) => (\n \n);\n\nBookmark.propTypes = {\n onClick: PropTypes.func.isRequired,\n text: PropTypes.string.isRequired,\n query: PropTypes.string.isRequired,\n};\n\nexport default Bookmark;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Bookmarks/components/Bookmark.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport * as Yup from 'yup';\n\nimport { noop } from '../../../../common/helpers';\nimport ForemanForm from '../../../common/forms/ForemanForm';\nimport TextField from '../../../common/forms/TextField';\nimport { translate as __ } from '../../../../../react_app/common/I18n';\nimport { maxLengthMsg, requiredMsg } from '../../../common/forms/validators';\n\nconst BookmarkForm = ({\n url,\n submitForm,\n controller,\n onCancel,\n initialValues,\n setModalClosed,\n bookmarks,\n}) => {\n const existsNamesRegex = new RegExp(\n `^(?!(${bookmarks.map(({ name }) => name).join('|')})$).+`\n );\n const bookmarkFormSchema = Yup.object().shape({\n name: Yup.string()\n .max(...maxLengthMsg(254))\n .required(requiredMsg())\n .matches(existsNamesRegex, {\n excludeEmptyString: true,\n message: __('name already exists'),\n }),\n query: Yup.string()\n .max(...maxLengthMsg(4096))\n .required(requiredMsg()),\n });\n\n const handleSubmit = (values, actions) =>\n submitForm({\n url,\n values: { ...values, controller },\n item: 'Bookmarks',\n message: __('Bookmark was successfully created.'),\n successCallback: setModalClosed,\n actions,\n });\n\n return (\n \n \n \n \n \n );\n};\n\nBookmarkForm.propTypes = {\n onCancel: PropTypes.func,\n submitForm: PropTypes.func.isRequired,\n controller: PropTypes.string.isRequired,\n initialValues: PropTypes.object.isRequired,\n url: PropTypes.string.isRequired,\n setModalClosed: PropTypes.func.isRequired,\n bookmarks: PropTypes.array,\n};\n\nBookmarkForm.defaultProps = {\n onCancel: noop,\n bookmarks: [],\n};\n\nexport default BookmarkForm;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Bookmarks/components/BookmarkForm/BookmarkForm.js","import { connect } from 'react-redux';\nimport BookmarkForm from './BookmarkForm';\nimport { submitForm } from '../../../../redux/actions/common/forms';\nimport { selectAutocompleteSearchQuery } from '../../../AutoComplete/AutoCompleteSelectors';\n\nconst mapStateToProps = (state, { controller }) => ({\n initialValues: {\n public: true,\n query: selectAutocompleteSearchQuery(state, 'searchBar', { controller }),\n },\n});\n\nconst mapDispatchToProps = {\n submitForm,\n};\n\nexport default connect(mapStateToProps, mapDispatchToProps)(BookmarkForm);\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Bookmarks/components/BookmarkForm/index.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport ForemanModal from '../../ForemanModal';\nimport { BOOKMARKS_MODAL } from '../BookmarksConstants';\nimport { translate as __ } from '../../../common/I18n';\nimport { noop } from '../../../common/helpers';\nimport BookmarkForm from './BookmarkForm';\n\nconst SearchModal = ({\n setModalClosed,\n onEnter,\n title,\n controller,\n url,\n bookmarks,\n}) => (\n \n \n \n);\n\nSearchModal.propTypes = {\n controller: PropTypes.string.isRequired,\n url: PropTypes.string.isRequired,\n title: PropTypes.string,\n onEnter: PropTypes.func,\n setModalClosed: PropTypes.func.isRequired,\n bookmarks: PropTypes.array,\n};\n\nSearchModal.defaultProps = {\n title: __('Create Bookmark'),\n onEnter: noop,\n bookmarks: [],\n};\n\nexport default SearchModal;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Bookmarks/components/SearchModal.js","import { connect } from 'react-redux';\nimport { BOOKMARKS_MODAL } from './BookmarksConstants';\nimport * as bookmarksActions from './BookmarksActions';\nimport { bindForemanModalActionsToId } from '../ForemanModal/ForemanModalActions';\nimport { selectIsModalOpen } from '../ForemanModal/ForemanModalSelectors';\nimport Bookmarks from './Bookmarks';\nimport reducer from './BookmarksReducer';\nimport {\n selectBookmarksStatus,\n selectBookmarksResults,\n selectBookmarksErrors,\n} from './BookmarksSelectors';\n\nconst mapStateToProps = (state, { controller }) => ({\n errors: selectBookmarksErrors(state, controller),\n bookmarks: selectBookmarksResults(state, controller),\n status: selectBookmarksStatus(state, controller),\n isModalOpen: selectIsModalOpen(state, BOOKMARKS_MODAL),\n});\n\nconst boundModalActions = bindForemanModalActionsToId({ id: BOOKMARKS_MODAL });\n\nconst mapDispatchToProps = {\n ...bookmarksActions,\n ...boundModalActions, // gives us setModalOpen and setModalClosed\n};\n\nexport const reducers = { bookmarks: reducer };\n\nexport default connect(mapStateToProps, mapDispatchToProps)(Bookmarks);\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Bookmarks/index.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { BreadcrumbSwitcher } from 'patternfly-react';\n\nimport { noop } from '../../common/helpers';\nimport Breadcrumb from './components/Breadcrumb';\nimport './BreadcrumbBar.scss';\n\nclass BreadcrumbBar extends React.Component {\n handleOpen() {\n const {\n resource,\n loadSwitcherResourcesByResource,\n currentPage,\n resourceUrl,\n resourceSwitcherItems,\n } = this.props;\n const isUrlFormatValid = resourceSwitcherItems.length\n ? resourceSwitcherItems[0].url ===\n resource.switcherItemUrl?.replace(':id', resourceSwitcherItems[0].id)\n : true;\n if (\n !currentPage ||\n resourceUrl !== resource.resourceUrl ||\n !isUrlFormatValid\n ) {\n loadSwitcherResourcesByResource(resource);\n }\n }\n\n render() {\n const {\n breadcrumbItems,\n isSwitchable,\n resource,\n currentPage,\n totalPages,\n resourceSwitcherItems,\n isLoadingResources,\n hasError,\n isSwitcherOpen,\n toggleSwitcher,\n closeSwitcher,\n loadSwitcherResourcesByResource,\n searchQuery,\n removeSearchQuery,\n searchDebounceTimeout,\n onSwitcherItemClick,\n titleReplacement,\n } = this.props;\n\n const isTitle = breadcrumbItems.length === 1;\n const options = ({ pageIncrement }) => ({\n searchQuery,\n page: Number(currentPage) + pageIncrement,\n });\n\n const handleSwitcherItemClick = (e, href) => {\n closeSwitcher();\n onSwitcherItemClick(e, href);\n };\n\n return (\n \n \n {isSwitchable && (\n toggleSwitcher()}\n onHide={() => closeSwitcher()}\n onOpen={() => this.handleOpen()}\n onSearchChange={event =>\n loadSwitcherResourcesByResource(resource, {\n searchQuery: event.target.value,\n })\n }\n onNextPageClick={() =>\n loadSwitcherResourcesByResource(\n resource,\n options({ pageIncrement: 1 })\n )\n }\n onPrevPageClick={() =>\n loadSwitcherResourcesByResource(\n resource,\n options({ pageIncrement: -1 })\n )\n }\n searchValue={searchQuery}\n onSearchClear={() => removeSearchQuery(resource)}\n searchDebounceTimeout={searchDebounceTimeout}\n onResourceClick={handleSwitcherItemClick}\n />\n )}\n \n {!isTitle &&
}\n \n );\n }\n}\n\nBreadcrumbBar.propTypes = {\n isSwitchable: PropTypes.bool,\n resource: PropTypes.shape({\n nameField: PropTypes.string,\n resourceUrl: PropTypes.string,\n switcherItemUrl: PropTypes.string,\n resourceFilter: PropTypes.string,\n }),\n breadcrumbItems: Breadcrumb.propTypes.items,\n searchDebounceTimeout: PropTypes.number,\n searchQuery: PropTypes.string,\n currentPage: PropTypes.number,\n totalPages: PropTypes.number,\n resourceSwitcherItems: BreadcrumbSwitcher.propTypes.resources,\n resourceUrl: PropTypes.string,\n isLoadingResources: PropTypes.bool,\n hasError: PropTypes.bool,\n isSwitcherOpen: PropTypes.bool,\n titleReplacement: PropTypes.string,\n toggleSwitcher: PropTypes.func,\n closeSwitcher: PropTypes.func,\n loadSwitcherResourcesByResource: PropTypes.func,\n onSwitcherItemClick: PropTypes.func,\n removeSearchQuery: PropTypes.func,\n};\n\nBreadcrumbBar.defaultProps = {\n isSwitchable: false,\n resource: {},\n breadcrumbItems: [],\n searchQuery: '',\n currentPage: null,\n totalPages: 1,\n resourceSwitcherItems: [],\n resourceUrl: null,\n isLoadingResources: false,\n hasError: false,\n isSwitcherOpen: false,\n searchDebounceTimeout: 300,\n titleReplacement: null,\n toggleSwitcher: noop,\n closeSwitcher: noop,\n loadSwitcherResourcesByResource: noop,\n onSwitcherItemClick: noop,\n removeSearchQuery: noop,\n};\n\nexport default BreadcrumbBar;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/BreadcrumbBar/BreadcrumbBar.js","import { flatten, get } from 'lodash';\nimport { translate as __ } from '../../common/I18n';\nimport { API } from '../../redux/API';\n\nimport {\n BREADCRUMB_BAR_TOGGLE_SWITCHER,\n BREADCRUMB_BAR_CLOSE_SWITCHER,\n BREADCRUMB_BAR_RESOURCES_REQUEST,\n BREADCRUMB_BAR_RESOURCES_SUCCESS,\n BREADCRUMB_BAR_RESOURCES_FAILURE,\n BREADCRUMB_BAR_CLEAR_SEARCH,\n BREADCRUMB_BAR_UPDATE_TITLE,\n} from './BreadcrumbBarConstants';\n\nexport const toggleSwitcher = () => ({\n type: BREADCRUMB_BAR_TOGGLE_SWITCHER,\n});\n\nexport const closeSwitcher = () => ({\n type: BREADCRUMB_BAR_CLOSE_SWITCHER,\n});\n\nexport const removeSearchQuery = resource => dispatch => {\n dispatch({\n type: BREADCRUMB_BAR_CLEAR_SEARCH,\n });\n loadSwitcherResourcesByResource(resource)(dispatch);\n};\n\nexport const updateBreadcrumbTitle = title => ({\n type: BREADCRUMB_BAR_UPDATE_TITLE,\n payload: title,\n});\n\nexport const loadSwitcherResourcesByResource = (\n resource,\n { page = 1, searchQuery = '' } = {}\n) => async dispatch => {\n const { resourceUrl, nameField, switcherItemUrl } = resource;\n const options = { page, searchQuery };\n const beforeRequest = () =>\n dispatch({\n type: BREADCRUMB_BAR_RESOURCES_REQUEST,\n payload: { resourceUrl, options },\n });\n\n const onRequestSuccess = response =>\n dispatch({\n type: BREADCRUMB_BAR_RESOURCES_SUCCESS,\n payload: { ...formatResults(response), resourceUrl },\n });\n\n const onRequestFail = error =>\n dispatch({\n type: BREADCRUMB_BAR_RESOURCES_FAILURE,\n payload: { error, resourceUrl },\n });\n\n const formatResults = ({ data }) => {\n const switcherItems = flatten(Object.values(data.results)).map(result => {\n const itemName = get(result, nameField);\n return {\n name: __(itemName),\n id: result.id,\n href: switcherItemUrl\n .replace(':id', result.id)\n .replace(':name', itemName),\n };\n });\n\n return {\n items: switcherItems,\n page: Number(data.page),\n pages: Number(data.subtotal) / Number(data.per_page),\n };\n };\n beforeRequest();\n try {\n const response = await API.get(\n resourceUrl,\n {},\n {\n page,\n per_page: 10,\n search: createSearch(nameField, searchQuery, resource.resourceFilter),\n }\n );\n return onRequestSuccess(response);\n } catch (error) {\n return onRequestFail(error);\n }\n};\n\nexport const createSearch = (nameField, searchQuery, resourceFilter) => {\n let query = '';\n if (resourceFilter) {\n query += resourceFilter;\n }\n\n if (query && searchQuery) {\n query += ` AND ${simpleNameQuery(nameField, searchQuery)}`;\n } else {\n query += simpleNameQuery(nameField, searchQuery);\n }\n\n return query;\n};\n\nconst simpleNameQuery = (nameField, searchQuery) =>\n searchQuery ? `${[nameField]}~${searchQuery}` : '';\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/BreadcrumbBar/BreadcrumbBarActions.js","export const BREADCRUMB_BAR_TOGGLE_SWITCHER = 'BREADCRUMB_BAR_TOGGLE_SWITCHER';\nexport const BREADCRUMB_BAR_CLOSE_SWITCHER = 'BREADCRUMB_BAR_CLOSE_SWITCHER';\nexport const BREADCRUMB_BAR_RESOURCES_REQUEST =\n 'BREADCRUMB_BAR_RESOURCES_REQUEST';\nexport const BREADCRUMB_BAR_RESOURCES_SUCCESS =\n 'BREADCRUMB_BAR_RESOURCES_SUCCESS';\nexport const BREADCRUMB_BAR_RESOURCES_FAILURE =\n 'BREADCRUMB_BAR_RESOURCES_FAILURE';\nexport const BREADCRUMB_BAR_CLEAR_SEARCH = 'BREADCRUMB_BAR_DELETE_SEARCH';\nexport const BREADCRUMB_BAR_UPDATE_TITLE = 'BREADCRUMB_BAR_UPDATE_TITLE';\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/BreadcrumbBar/BreadcrumbBarConstants.js","import Immutable from 'seamless-immutable';\n\nimport {\n BREADCRUMB_BAR_TOGGLE_SWITCHER,\n BREADCRUMB_BAR_CLOSE_SWITCHER,\n BREADCRUMB_BAR_RESOURCES_REQUEST,\n BREADCRUMB_BAR_RESOURCES_SUCCESS,\n BREADCRUMB_BAR_RESOURCES_FAILURE,\n BREADCRUMB_BAR_CLEAR_SEARCH,\n BREADCRUMB_BAR_UPDATE_TITLE,\n} from './BreadcrumbBarConstants';\n\nconst initialState = Immutable({\n resourceSwitcherItems: [],\n isLoadingResources: false,\n isSwitcherOpen: false,\n resourceUrl: null,\n requestError: null,\n currentPage: null,\n searchQuery: '',\n pages: null,\n titleReplacement: null,\n});\n\nexport default (state = initialState, action) => {\n const { payload } = action;\n\n switch (action.type) {\n case BREADCRUMB_BAR_CLEAR_SEARCH:\n return state.set('searchQuery', '');\n\n case BREADCRUMB_BAR_UPDATE_TITLE:\n return state.set('titleReplacement', payload);\n\n case BREADCRUMB_BAR_RESOURCES_REQUEST:\n return state\n .set('resourceSwitcherItems', [])\n .set('resourceUrl', payload.resourceUrl)\n .set('requestError', null)\n .set('isLoadingResources', true)\n .set('searchQuery', payload.options.searchQuery);\n\n case BREADCRUMB_BAR_RESOURCES_SUCCESS:\n return state\n .set('resourceSwitcherItems', payload.items)\n .set('resourceUrl', payload.resourceUrl)\n .set('currentPage', payload.page)\n .set('pages', payload.pages)\n .set('requestError', null)\n .set('isLoadingResources', false);\n\n case BREADCRUMB_BAR_RESOURCES_FAILURE:\n return state\n .set('resourceSwitcherItems', [])\n .set('requestError', payload.error)\n .set('resourceUrl', payload.resourceUrl)\n .set('isLoadingResources', false);\n\n case BREADCRUMB_BAR_TOGGLE_SWITCHER:\n return state.set('isSwitcherOpen', !state.isSwitcherOpen);\n\n case BREADCRUMB_BAR_CLOSE_SWITCHER:\n return state.set('isSwitcherOpen', false);\n\n default:\n return state;\n }\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/BreadcrumbBar/BreadcrumbBarReducer.js","export const selectBreadcrumbBar = state => state.breadcrumbBar;\nexport const selectResourceSwitcherItems = state =>\n selectBreadcrumbBar(state).resourceSwitcherItems;\nexport const selectResourceUrl = state =>\n selectBreadcrumbBar(state).resourceUrl;\nexport const selectIsSwitcherOpen = state =>\n selectBreadcrumbBar(state).isSwitcherOpen;\nexport const selectIsLoadingResources = state =>\n selectBreadcrumbBar(state).isLoadingResources;\nexport const selectHasError = state =>\n selectBreadcrumbBar(state).requestError != null;\nexport const selectCurrentPage = state =>\n selectBreadcrumbBar(state).currentPage;\nexport const selectTotalPages = state => selectBreadcrumbBar(state).pages;\nexport const selectSearchQuery = state =>\n selectBreadcrumbBar(state).searchQuery;\nexport const selectRemoveSearchQuery = state =>\n selectBreadcrumbBar(state).removeSearchQuery;\nexport const selectTitleReplacement = state =>\n selectBreadcrumbBar(state).titleReplacement;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/BreadcrumbBar/BreadcrumbBarSelector.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport classNames from 'classnames';\nimport {\n Breadcrumb as PfBreadcrumb,\n BreadcrumbItem,\n} from '@patternfly/react-core';\nimport EllipsisWithTooltip from 'react-ellipsis-with-tooltip';\nimport './Breadcrumbs.scss';\n\nconst Breadcrumb = ({\n items,\n isTitle,\n titleReplacement,\n children,\n ...props\n}) => {\n if (isTitle) {\n return (\n \n
{items[0].caption}
\n \n );\n }\n\n return (\n \n {items.map((item, index) => {\n const active = index === items.length - 1;\n const { caption, url, onClick } = item;\n const { icon, text } = caption || {};\n\n const overrideTitle = active && titleReplacement;\n const itemTitle = overrideTitle || text || caption || '';\n\n if (!icon && !itemTitle) return null;\n\n const inner = active ? (\n \n {itemTitle}\n \n ) : (\n itemTitle\n );\n\n return (\n \n {icon &&
}{' '}\n {inner}\n {active && children}\n \n );\n })}\n \n );\n};\n\nBreadcrumb.propTypes = {\n children: PropTypes.node,\n titleReplacement: PropTypes.string,\n isTitle: PropTypes.bool,\n items: PropTypes.arrayOf(\n PropTypes.shape({\n caption: PropTypes.oneOfType([\n PropTypes.string.isRequired,\n PropTypes.shape({\n icon: PropTypes.shape({\n url: PropTypes.string,\n alt: PropTypes.string,\n }),\n text: PropTypes.string,\n }),\n ]),\n url: PropTypes.string,\n })\n ),\n};\n\nBreadcrumb.defaultProps = {\n children: null,\n isTitle: false,\n items: [],\n titleReplacement: null,\n};\n\nexport default Breadcrumb;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/BreadcrumbBar/components/Breadcrumb.js","import { bindActionCreators } from 'redux';\nimport { connect } from 'react-redux';\n\nimport * as actions from './BreadcrumbBarActions';\nimport reducer from './BreadcrumbBarReducer';\n\nimport {\n selectResourceSwitcherItems,\n selectIsSwitcherOpen,\n selectResourceUrl,\n selectIsLoadingResources,\n selectHasError,\n selectCurrentPage,\n selectTotalPages,\n selectSearchQuery,\n selectRemoveSearchQuery,\n selectTitleReplacement,\n} from './BreadcrumbBarSelector';\n\nimport BreadcrumbBar from './BreadcrumbBar';\n\n// map state to props\nconst mapStateToProps = state => ({\n resourceSwitcherItems: selectResourceSwitcherItems(state),\n isSwitcherOpen: selectIsSwitcherOpen(state),\n resourceUrl: selectResourceUrl(state),\n isLoadingResources: selectIsLoadingResources(state),\n hasError: selectHasError(state),\n currentPage: selectCurrentPage(state),\n totalPages: selectTotalPages(state),\n searchQuery: selectSearchQuery(state),\n removeSearchQuery: selectRemoveSearchQuery(state),\n titleReplacement: selectTitleReplacement(state),\n});\n\n// map action dispatchers to props\nconst mapDispatchToProps = dispatch => bindActionCreators(actions, dispatch);\n\n// export reducers\nexport const reducers = { breadcrumbBar: reducer };\n\n// export connected component\nexport default connect(mapStateToProps, mapDispatchToProps)(BreadcrumbBar);\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/BreadcrumbBar/index.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { Card, Modal } from 'patternfly-react';\nimport { isEqual } from 'lodash';\nimport classNames from 'classnames';\nimport ElipsisWithTooltip from 'react-ellipsis-with-tooltip';\nimport DonutChart from '../common/charts/DonutChart';\nimport BarChart from '../common/charts/BarChart';\nimport Loader from '../common/Loader';\nimport MessageBox from '../common/MessageBox';\nimport { translate as __ } from '../../common/I18n';\nimport './ChartBox.css';\n\nclass ChartBox extends React.Component {\n constructor(props) {\n super(props);\n this.state = { showModal: false };\n }\n shouldComponentUpdate(nextProps, nextState) {\n return (\n !isEqual(this.props.chart, nextProps.chart) ||\n !isEqual(this.state, nextState)\n );\n }\n\n openModal = () => {\n this.setState({ showModal: true });\n };\n\n closeModal = () => {\n this.setState({ showModal: false });\n };\n\n render() {\n const { chart, type, config, title, status, className } = this.props;\n const components = {\n donut: DonutChart,\n bar: BarChart,\n };\n const Chart = components[type];\n const dataFiltered = chart.data && chart.data.filter(arr => arr[1] !== 0);\n const hasChartData = dataFiltered && dataFiltered.length > 0;\n const headerProps = hasChartData\n ? {\n onClick: this.openModal,\n title: this.props.tip,\n 'data-toggle': 'tooltip',\n 'data-placement': 'top',\n }\n : {};\n const chartProps = {\n searchUrl:\n chart.search && !chart.search.match(/=$/) ? chart.search : null,\n data: chart.data ? chart.data : undefined,\n key: `${chart.id}-chart`,\n };\n\n const barChartProps = {\n ...chartProps,\n xAxisLabel: chart.xAxisLabel,\n yAxisLabel: chart.yAxisLabel,\n };\n\n const chartPropsForType = {\n donut: chartProps,\n bar: barChartProps,\n };\n\n const panelChart = ;\n const error = (\n \n );\n\n return (\n \n \n \n {title} \n \n \n \n {[panelChart, error]}\n {this.state.showModal && (\n \n \n {title}\n \n \n \n \n \n )}\n \n \n );\n }\n}\n\nChartBox.propTypes = {\n status: PropTypes.string.isRequired,\n title: PropTypes.node,\n className: PropTypes.string,\n config: PropTypes.string,\n noDataMsg: PropTypes.string,\n errorText: PropTypes.string,\n type: PropTypes.oneOf(['donut', 'bar']).isRequired,\n chart: PropTypes.object,\n tip: PropTypes.string,\n};\n\nChartBox.defaultProps = {\n title: '',\n className: '',\n config: 'regular',\n noDataMsg: __('No data available'),\n errorText: '',\n chart: {},\n tip: '',\n};\n\nexport default ChartBox;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/ChartBox/ChartBox.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { Row, Col } from 'patternfly-react';\nimport classNames from 'classnames';\nimport ChartBox from '../ChartBox/ChartBox';\nimport { translate as __ } from '../../common/I18n';\nimport { STATUS } from '../../constants';\n\nimport './ConfigReports.scss';\n\nconst ConfigReports = props => {\n const {\n metricsChartData,\n statusChartData,\n metricsData: { tableData, tableClasses, total },\n } = props.data;\n\n const createRow = ([name, value], i) => (\n \n {name} | \n {value} | \n
\n );\n\n const chartBoxProps = {\n className: 'report-chart',\n noDataMsg: __('No data available'),\n status: STATUS.RESOLVED,\n config: 'medium',\n };\n\n return (\n \n \n \n \n\n \n \n \n \n \n {tableData.map((metric, i) => createRow(metric, i))}\n \n \n {__('Total')} | \n {total} | \n
\n \n
\n \n
\n );\n};\n\nConfigReports.propTypes = {\n data: PropTypes.shape({\n metricsChartData: PropTypes.array,\n statusChartData: PropTypes.array,\n metricsData: PropTypes.shape({\n tableData: PropTypes.array,\n total: PropTypes.number,\n tableClasses: PropTypes.string,\n }),\n }).isRequired,\n};\n\nexport default ConfigReports;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/ConfigReports/ConfigReports.js","import React from 'react';\nimport { Modal, Icon, Button } from 'patternfly-react';\nimport PropTypes from 'prop-types';\n\nimport { noop } from '../../../common/helpers';\nimport DiffView from '../../DiffView/DiffView';\nimport DiffRadioButtons from '../../DiffView/DiffRadioButtons';\n\nimport './diffmodal.scss';\n\nconst DiffModal = ({\n title,\n oldText,\n newText,\n diff,\n isOpen,\n toggleModal,\n diffViewType,\n changeViewType,\n}) => (\n \n \n {title}
\n \n \n \n \n \n \n
\n \n \n);\n\nDiffModal.propTypes = {\n title: PropTypes.string,\n diff: PropTypes.string,\n oldText: PropTypes.string,\n newText: PropTypes.string,\n diffViewType: PropTypes.oneOf(['split', 'unified']),\n isOpen: PropTypes.bool,\n changeViewType: PropTypes.func,\n toggleModal: PropTypes.func,\n};\n\nDiffModal.defaultProps = {\n title: '',\n diff: '',\n oldText: '',\n newText: '',\n diffViewType: 'split',\n isOpen: false,\n changeViewType: noop,\n toggleModal: noop,\n};\n\nexport default DiffModal;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/ConfigReports/DiffModal/DiffModal.js","import {\n DIFF_MODAL_TOGGLE,\n DIFF_MODAL_CREATE,\n DIFF_MODAL_VIEWTYPE,\n} from './DiffModalConstants';\n\nexport const toggleModal = () => ({\n type: DIFF_MODAL_TOGGLE,\n});\n\nexport const changeViewType = viewType => dispatch => {\n dispatch({\n type: DIFF_MODAL_VIEWTYPE,\n payload: {\n diffViewType: viewType,\n },\n });\n};\n\nexport const createDiff = (diff, title) => dispatch => {\n dispatch({\n type: DIFF_MODAL_CREATE,\n payload: {\n diff,\n title,\n isOpen: true,\n },\n });\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/ConfigReports/DiffModal/DiffModalActions.js","export const DIFF_MODAL_TOGGLE = 'DIFF_MODAL_TOGGLE';\nexport const DIFF_MODAL_CREATE = 'DIFF_MODAL_CREATE';\nexport const DIFF_MODAL_VIEWTYPE = 'DIFF_MODAL_VIEWTYPE';\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/ConfigReports/DiffModal/DiffModalConstants.js","import Immutable from 'seamless-immutable';\nimport {\n DIFF_MODAL_TOGGLE,\n DIFF_MODAL_CREATE,\n DIFF_MODAL_VIEWTYPE,\n} from './DiffModalConstants';\n\nconst initialState = Immutable({\n isOpen: false,\n diff: '',\n title: '',\n diffViewType: 'split',\n});\n\nexport default (state = initialState, action) => {\n switch (action.type) {\n case DIFF_MODAL_TOGGLE:\n return state.set('isOpen', !state.isOpen);\n case DIFF_MODAL_VIEWTYPE:\n return state.set('diffViewType', action.payload.diffViewType);\n case DIFF_MODAL_CREATE:\n return state.merge(action.payload);\n\n default:\n return state;\n }\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/ConfigReports/DiffModal/DiffModalReducer.js","import { bindActionCreators } from 'redux';\nimport { connect } from 'react-redux';\n\nimport * as actions from './DiffModalActions';\nimport reducer from './DiffModalReducer';\n\nimport DiffModal from './DiffModal';\n\n// map state to props\nconst mapStateToProps = ({ diffModal }) => ({\n isOpen: diffModal.isOpen,\n diff: diffModal.diff,\n title: diffModal.title,\n diffViewType: diffModal.diffViewType,\n});\n\n// map action dispatchers to props\nconst mapDispatchToProps = dispatch => bindActionCreators(actions, dispatch);\n\n// export reducers\nexport const reducers = { diffModal: reducer };\n\n// export connected component\nexport default connect(mapStateToProps, mapDispatchToProps)(DiffModal);\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/ConfigReports/DiffModal/index.js","import React from 'react';\nimport { translate as __ } from '../../common/I18n';\nimport EmptyState from '../common/EmptyState';\nimport { getManualURL, getWikiURL } from '../../common/helpers';\n\nexport const WelcomeConfigReports = () => {\n const content = __(`If you wish to configure Puppet to forward its reports to Foreman, \n please follow setting up reporting and\n e-mail reporting`);\n const description = (\n <>\n {__(\"You don't seem to have any reports.\")}\n \n >\n );\n return (\n \n );\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/ConfigReports/Welcome.js","export const SPLIT = 'split';\nexport const UNIFIED = 'unified';\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/DiffView/DiffConsts.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { bindMethods } from '../../common/helpers';\n\nimport DiffView from './DiffView';\nimport DiffRadioButtons from './DiffRadioButtons';\nimport './diffview.scss';\n\nclass DiffContainer extends React.Component {\n constructor(props) {\n super(props);\n bindMethods(this, ['changeState']);\n this.state = {\n viewType: 'split',\n };\n }\n\n changeState(viewType) {\n this.setState({ viewType });\n }\n\n render() {\n const { patch, oldText, newText, className } = this.props;\n const { viewType } = this.state;\n return (\n \n );\n }\n}\n\nDiffContainer.propTypes = {\n oldText: PropTypes.string,\n newText: PropTypes.string,\n patch: PropTypes.string,\n className: PropTypes.string,\n};\n\nDiffContainer.defaultProps = {\n oldText: '',\n newText: '',\n patch: '',\n className: '',\n};\n\nexport default DiffContainer;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/DiffView/DiffContainer.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport classNames from 'classnames';\nimport { ButtonGroup, Button } from 'patternfly-react';\nimport { translate as __ } from '../../common/I18n';\nimport { SPLIT, UNIFIED } from './DiffConsts';\n\nconst btnClass = (stateView, btnView) =>\n classNames('diff-button', { active: stateView === btnView });\n\nconst radioButton = (stateView, btnView, changeState) => (\n \n);\n\nconst DiffRadioButtons = ({ stateView, changeState }) => (\n \n \n {radioButton(stateView, __('split'), () => {\n changeState(SPLIT);\n })}\n {radioButton(stateView, __('unified'), () => {\n changeState(UNIFIED);\n })}\n \n
\n);\n\nDiffRadioButtons.propTypes = {\n stateView: PropTypes.string.isRequired,\n changeState: PropTypes.func.isRequired,\n};\n\nexport default DiffRadioButtons;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/DiffView/DiffRadioButtons.js","import React from 'react';\nimport PropTypes from 'prop-types';\n\nimport { parseDiff, Diff } from 'react-diff-view';\nimport { formatLines, diffLines } from 'unidiff';\nimport './diffview.scss';\n\nconst getDiff = (oldText, newText) => {\n const diffText = formatLines(diffLines(oldText, newText), { context: 3 });\n // these two lines are faked to mock git diff output\n const header = ['diff --git a/a b/b', 'index 0000000..1111111 100644'];\n return `${header.join('\\n')}\\n${diffText}`;\n};\n\nconst DiffView = ({ oldText, newText, viewType, patch }) => {\n // old,new Text\n if (patch === '') {\n const gitDiff = getDiff(oldText, newText);\n const files = parseDiff(gitDiff);\n const { hunks, type } = files[0];\n return hunks && ;\n }\n // Patch\n const files = parseDiff(\n patch\n .split('\\n')\n .slice(1)\n .join('\\n')\n );\n // eslint-disable-next-line react/prop-types\n const renderFile = ({ oldRevision, newRevision, type, hunks }) => (\n \n );\n\n return {files.map(renderFile)}
;\n};\n\nDiffView.propTypes = {\n // None are required because only one can be used at a time: (old + new || patch)\n oldText: PropTypes.string,\n newText: PropTypes.string,\n viewType: PropTypes.string.isRequired,\n patch: PropTypes.string,\n};\n\nDiffView.defaultProps = {\n oldText: '',\n newText: '',\n patch: '',\n};\n\nexport default DiffView;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/DiffView/DiffView.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { ToastNotification } from 'patternfly-react';\n\nimport { noop } from '../../common/helpers';\nimport DiffView from '../DiffView/DiffView';\nimport EditorView from './components/EditorView';\nimport EditorNavbar from './components/EditorNavbar';\nimport EditorModal from './components/EditorModal';\nimport {\n EDITOR_THEMES,\n EDITOR_KEYBINDINGS,\n EDITOR_MODES,\n} from './EditorConstants';\nimport './editor.scss';\n\nclass Editor extends React.Component {\n componentDidMount() {\n const {\n data: { hosts, templateClass, locked, template, type },\n initializeEditor,\n isMasked,\n isRendering,\n readOnly,\n previewResult,\n selectedView,\n showError,\n } = this.props;\n\n const initializeData = {\n hosts,\n isMasked,\n templateClass,\n isRendering,\n locked,\n readOnly,\n previewResult,\n selectedView,\n showError,\n template,\n type,\n };\n initializeEditor(initializeData);\n }\n\n render() {\n const {\n data: {\n name,\n isSafemodeEnabled,\n renderPath,\n safemodeRenderPath,\n showHide,\n showImport,\n showPreview,\n showHostSelector,\n template,\n title,\n },\n changeDiffViewType,\n changeEditorValue,\n changeSetting,\n changeTab,\n diffViewType,\n dismissErrorToast,\n editorName,\n errorText,\n fetchAndPreview,\n filteredHosts,\n hosts,\n importFile,\n isFetchingHosts,\n isLoading,\n isMasked,\n isMaximized,\n isRendering,\n isSearchingHosts,\n isSelectOpen,\n keyBinding,\n mode,\n onHostSearch,\n onHostSelectToggle,\n onSearchClear,\n previewResult,\n previewTemplate,\n readOnly,\n renderedEditorValue,\n revertChanges,\n searchQuery,\n selectedHost,\n selectedView,\n showError,\n theme,\n toggleMaskValue,\n toggleModal,\n toggleRenderView,\n value,\n } = this.props;\n\n const editorViewProps = {\n value: isRendering ? previewResult : value,\n mode: isRendering ? 'Text' : mode,\n theme,\n keyBinding,\n onChange: isRendering ? noop : changeEditorValue,\n readOnly: readOnly || isRendering,\n isMasked,\n };\n const editorNameTab = {\n input: `${editorName}Code`,\n preview: `${editorName}Preview`,\n };\n\n return (\n \n
dismissErrorToast()}\n >\n {errorText}\n \n
\n
\n
\n
\n \n
\n
\n {!readOnly && (\n
\n )}\n
\n );\n }\n}\n\nEditor.propTypes = {\n data: PropTypes.shape({\n showHide: PropTypes.bool,\n showImport: PropTypes.bool,\n showPreview: PropTypes.bool,\n showHostSelector: PropTypes.bool,\n template: PropTypes.string,\n templateClass: PropTypes.string,\n name: PropTypes.string,\n title: PropTypes.string,\n isSafemodeEnabled: PropTypes.bool,\n renderPath: PropTypes.string,\n safemodeRenderPath: PropTypes.string,\n hosts: PropTypes.array,\n locked: PropTypes.bool,\n type: PropTypes.string,\n }).isRequired,\n selectedHost: PropTypes.shape({\n id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),\n name: PropTypes.string,\n }).isRequired,\n changeDiffViewType: PropTypes.func.isRequired,\n changeEditorValue: PropTypes.func.isRequired,\n changeSetting: PropTypes.func.isRequired,\n changeTab: PropTypes.func.isRequired,\n diffViewType: PropTypes.string.isRequired,\n dismissErrorToast: PropTypes.func.isRequired,\n editorName: PropTypes.string.isRequired,\n errorText: PropTypes.string.isRequired,\n hosts: PropTypes.array.isRequired,\n filteredHosts: PropTypes.array.isRequired,\n importFile: PropTypes.func.isRequired,\n initializeEditor: PropTypes.func.isRequired,\n isMasked: PropTypes.bool.isRequired,\n isMaximized: PropTypes.bool.isRequired,\n isRendering: PropTypes.bool.isRequired,\n isLoading: PropTypes.bool.isRequired,\n isFetchingHosts: PropTypes.bool.isRequired,\n keyBinding: PropTypes.string.isRequired,\n mode: PropTypes.string.isRequired,\n previewTemplate: PropTypes.func.isRequired,\n readOnly: PropTypes.bool.isRequired,\n previewResult: PropTypes.string.isRequired,\n revertChanges: PropTypes.func.isRequired,\n selectedView: PropTypes.string.isRequired,\n showError: PropTypes.bool.isRequired,\n theme: PropTypes.string.isRequired,\n toggleMaskValue: PropTypes.func.isRequired,\n toggleModal: PropTypes.func.isRequired,\n toggleRenderView: PropTypes.func.isRequired,\n value: PropTypes.string.isRequired,\n renderedEditorValue: PropTypes.string.isRequired,\n isSelectOpen: PropTypes.bool.isRequired,\n searchQuery: PropTypes.string.isRequired,\n onHostSelectToggle: PropTypes.func.isRequired,\n onHostSearch: PropTypes.func.isRequired,\n onSearchClear: PropTypes.func.isRequired,\n isSearchingHosts: PropTypes.bool.isRequired,\n fetchAndPreview: PropTypes.func.isRequired,\n};\n\nexport default Editor;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Editor/Editor.js","import { debounce, toString } from 'lodash';\nimport { API } from '../../redux/API';\nimport { translate as __ } from '../../common/I18n';\n\nimport {\n EDITOR_CHANGE_DIFF_VIEW,\n EDITOR_CHANGE_SETTING,\n EDITOR_CHANGE_TAB,\n EDITOR_CHANGE_VALUE,\n EDITOR_DISMISS_ERROR,\n EDITOR_SHOW_ERROR,\n EDITOR_EXEC_PREVIEW,\n EDITOR_SHOW_LOADING,\n EDITOR_HIDE_LOADING,\n EDITOR_IMPORT_FILE,\n EDITOR_INITIALIZE,\n EDITOR_MODAL_TOGGLE,\n EDITOR_REVERT_CHANGES,\n EDITOR_TOGGLE_MASK,\n EDITOR_TOGGLE_RENDER_VIEW,\n EDITOR_HOSTS_URL,\n EDITOR_HOST_SELECT_TOGGLE,\n EDITOR_HOST_SELECT_CLEAR,\n EDITOR_FETCH_HOST_PENDING,\n EDITOR_FETCH_HOST_RESOLVED,\n EDITOR_HOST_SELECT_RESET,\n EDITOR_HOST_ARR,\n EDITOR_HOST_FILTERED_ARR,\n} from './EditorConstants';\n\nimport {\n selectTemplateClass,\n selectValue,\n selectShowError,\n selectIsSelectOpen,\n selectHosts,\n} from './EditorSelectors';\n\nexport const initializeEditor = initializeData => dispatch => {\n const {\n template,\n locked,\n type,\n templateClass,\n readOnly,\n isMasked,\n selectedView,\n isRendering,\n previewResult,\n showError,\n } = initializeData;\n\n const initialState = {};\n // initialize after changing editors\n initialState.selectedHost = { id: '', name: '' };\n initialState.hosts = [];\n initialState.isSearchingHosts = false;\n initialState.value = template || '';\n initialState.templateClass = templateClass;\n if (readOnly !== locked) {\n if (locked === true) initialState.readOnly = true;\n else initialState.readOnly = false;\n }\n if (isMasked && type === 'templates') initialState.isMasked = false;\n if (selectedView !== 'input') initialState.selectedView = 'input';\n if (isRendering) initialState.isRendering = false;\n if (previewResult !== '') initialState.previewResult = '';\n if (showError) initialState.showError = false;\n dispatch({\n type: EDITOR_INITIALIZE,\n payload: initialState,\n });\n};\n\nexport const importFile = e => dispatch => {\n const reader = new FileReader();\n reader.onloadstart = () => dispatch({ type: EDITOR_SHOW_LOADING });\n reader.onloadend = () => dispatch({ type: EDITOR_HIDE_LOADING });\n reader.onload = event => {\n dispatch({\n type: EDITOR_IMPORT_FILE,\n payload: {\n value: event.target.result,\n },\n });\n };\n reader.readAsText(e.target.files[0]);\n};\n\nexport const revertChanges = template => dispatch => {\n dispatch({\n type: EDITOR_REVERT_CHANGES,\n payload: {\n value: template || '',\n isRendering: false,\n },\n });\n};\n\nexport const previewTemplate = ({ host, renderPath }) => async (\n dispatch,\n getState\n) => {\n const { id, name } = host;\n if (selectIsSelectOpen(getState()))\n dispatch({ type: EDITOR_HOST_SELECT_TOGGLE });\n const templateValue = selectValue(getState());\n const isErrorShown = selectShowError(getState());\n\n const params = {\n template: templateValue,\n /* eslint-disable camelcase */\n preview_host_id: id,\n };\n dispatch({ type: EDITOR_SHOW_LOADING });\n try {\n const response = await fetchTemplatePreview(renderPath, params);\n if (isErrorShown) dispatch(dismissErrorToast());\n dispatch({ type: EDITOR_HIDE_LOADING });\n dispatch({\n type: EDITOR_EXEC_PREVIEW,\n payload: {\n renderedEditorValue: templateValue,\n selectedHost: {\n id: toString(id),\n name,\n },\n previewResult: response.data,\n isSearchingHosts: false,\n },\n });\n } catch (error) {\n dispatch({ type: EDITOR_HIDE_LOADING });\n dispatch({\n type: EDITOR_SHOW_ERROR,\n payload: {\n renderedEditorValue: templateValue,\n showError: true,\n errorText: error.response ? __(error.response.data) : '',\n previewResult: __('Error during rendering, Return to Editor tab.'),\n selectedHost: {\n id: toString(id),\n name,\n },\n },\n });\n }\n};\n\nexport const fetchTemplatePreview = (renderPath, params) =>\n API.post(renderPath, params);\n\n// fetch & debounced fetch\nconst fetchHosts = (\n query = '',\n array = EDITOR_HOST_ARR,\n url = EDITOR_HOSTS_URL\n) => (dispatch, getState) =>\n createHostAPIRequest(query, array, url, dispatch, getState);\n\nconst debouncedFetchHosts = (\n query = '',\n array = EDITOR_HOST_ARR,\n url = EDITOR_HOSTS_URL\n) => (dispatch, getState) =>\n debouncedCreateHostAPIRequest(query, array, url, dispatch, getState);\n\n// API & debounced API\nconst createHostAPIRequest = async (query, array, url, dispatch, getState) => {\n const onResultsSuccess = response =>\n dispatch({\n type: EDITOR_FETCH_HOST_RESOLVED,\n payload: { [array]: response.data },\n });\n\n const onResultsError = response =>\n dispatch({\n type: EDITOR_SHOW_ERROR,\n payload: {\n showError: true,\n errorText: __(`Host Fetch ${response}`),\n previewResult: __('Error during rendering, Return to Editor tab.'),\n },\n });\n\n try {\n const response = await API.get(\n url,\n {},\n { q: query, scope: selectTemplateClass(getState()) }\n );\n return onResultsSuccess(response);\n } catch (error) {\n return onResultsError(error);\n }\n};\nconst debouncedCreateHostAPIRequest = debounce(createHostAPIRequest, 250);\n\nexport const onHostSearch = e => (dispatch, getState) => {\n if (e.target.value === '')\n return dispatch({ type: EDITOR_HOST_SELECT_RESET });\n\n const payload = {\n isFetchingHosts: true,\n searchQuery: e.target.value,\n isSearchingHosts: true,\n };\n\n dispatch({ type: EDITOR_FETCH_HOST_PENDING, payload });\n return dispatch(\n debouncedFetchHosts(e.target.value, EDITOR_HOST_FILTERED_ARR)\n );\n};\n\nexport const fetchAndPreview = renderPath => async (dispatch, getState) => {\n dispatch({ type: EDITOR_SHOW_LOADING });\n await dispatch(fetchHosts());\n const hosts = selectHosts(getState());\n if (hosts.length > 0)\n dispatch(previewTemplate({ host: hosts[0], renderPath }));\n else dispatch({ type: EDITOR_HIDE_LOADING });\n};\n\nexport const toggleModal = () => ({\n type: EDITOR_MODAL_TOGGLE,\n});\n\nexport const changeDiffViewType = viewType => dispatch => {\n dispatch({\n type: EDITOR_CHANGE_DIFF_VIEW,\n payload: viewType,\n });\n};\n\nexport const changeEditorValue = value => dispatch => {\n dispatch({\n type: EDITOR_CHANGE_VALUE,\n payload: value,\n });\n};\n\nexport const dismissErrorToast = () => dispatch => {\n dispatch({\n type: EDITOR_DISMISS_ERROR,\n payload: { showError: false, errorText: '' },\n });\n};\n\nexport const changeTab = selectedView => dispatch => {\n dispatch({\n type: EDITOR_CHANGE_TAB,\n payload: selectedView,\n });\n};\n\nexport const toggleMaskValue = () => ({\n type: EDITOR_TOGGLE_MASK,\n});\n\nexport const changeSetting = newSetting => dispatch => {\n dispatch({\n type: EDITOR_CHANGE_SETTING,\n payload: newSetting,\n });\n};\n\nexport const toggleRenderView = isRendering => ({\n type: EDITOR_TOGGLE_RENDER_VIEW,\n});\n\nexport const onSearchClear = () => ({ type: EDITOR_HOST_SELECT_CLEAR });\n\nexport const onHostSelectToggle = () => ({\n type: EDITOR_HOST_SELECT_TOGGLE,\n});\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Editor/EditorActions.js","export const EDITOR_INITIALIZE = 'EDITOR_INITIALIZE';\nexport const EDITOR_IMPORT_FILE = 'EDITOR_IMPORT_FILE';\nexport const EDITOR_REVERT_CHANGES = 'EDITOR_REVERT_CHANGES';\nexport const EDITOR_EXEC_PREVIEW = 'EDITOR_EXEC_PREVIEW';\nexport const EDITOR_MODAL_TOGGLE = 'EDITOR_MODAL_TOGGLE';\nexport const EDITOR_CHANGE_DIFF_VIEW = 'EDITOR_CHANGE_DIFF_VIEW';\nexport const EDITOR_CHANGE_VALUE = 'EDITOR_CHANGE_VALUE';\nexport const EDITOR_SHOW_ERROR = 'EDITOR_SHOW_ERROR';\nexport const EDITOR_DISMISS_ERROR = 'EDITOR_DISMISS_ERROR';\nexport const EDITOR_CHANGE_TAB = 'EDITOR_CHANGE_TAB';\nexport const EDITOR_TOGGLE_MASK = 'EDITOR_TOGGLE_MASK';\nexport const EDITOR_CHANGE_SETTING = 'EDITOR_CHANGE_SETTING';\nexport const EDITOR_TOGGLE_RENDER_VIEW = 'EDITOR_TOGGLE_RENDER_VIEW';\nexport const EDITOR_SHOW_LOADING = 'EDITOR_SHOW_LOADING';\nexport const EDITOR_HIDE_LOADING = 'EDITOR_HIDE_LOADING';\nexport const EDITOR_FETCH_HOST_PENDING = 'EDITOR_FETCH_HOST_PENDING';\nexport const EDITOR_FETCH_HOST_RESOLVED = 'EDITOR_FETCH_HOST_RESOLVED';\nexport const EDITOR_HOST_SELECT_TOGGLE = 'EDITOR_HOST_SELECT_TOGGLE';\nexport const EDITOR_HOST_SELECT_CLEAR = 'EDITOR_HOST_SELECT_CLEAR';\nexport const EDITOR_HOST_SELECT_RESET = 'EDITOR_HOST_SELECT_RESET';\nexport const EDITOR_HOST_INITIAL_FETCH = 'EDITOR_HOST_INITIAL_FETCH';\n\nexport const EDITOR_HOSTS_URL = '/hosts/preview_host_collection.json';\nexport const EDITOR_HOST_ARR = 'hosts';\nexport const EDITOR_HOST_FILTERED_ARR = 'filteredHosts';\nexport const EDITOR_KEYBINDINGS = ['Default', 'Emacs', 'Vim'];\nexport const EDITOR_THEMES = ['Github', 'Monokai'];\nexport const EDITOR_MODES = [\n 'Text',\n 'Json',\n 'Ruby',\n 'Html_ruby',\n 'Sh',\n 'Xml',\n 'Yaml',\n];\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Editor/EditorConstants.js","import Immutable from 'seamless-immutable';\n\nimport {\n EDITOR_CHANGE_DIFF_VIEW,\n EDITOR_CHANGE_SETTING,\n EDITOR_CHANGE_TAB,\n EDITOR_CHANGE_VALUE,\n EDITOR_DISMISS_ERROR,\n EDITOR_SHOW_ERROR,\n EDITOR_EXEC_PREVIEW,\n EDITOR_SHOW_LOADING,\n EDITOR_HIDE_LOADING,\n EDITOR_IMPORT_FILE,\n EDITOR_INITIALIZE,\n EDITOR_MODAL_TOGGLE,\n EDITOR_REVERT_CHANGES,\n EDITOR_TOGGLE_MASK,\n EDITOR_TOGGLE_RENDER_VIEW,\n EDITOR_HOST_SELECT_CLEAR,\n EDITOR_HOST_SELECT_TOGGLE,\n EDITOR_FETCH_HOST_PENDING,\n EDITOR_HOST_SELECT_RESET,\n EDITOR_FETCH_HOST_RESOLVED,\n EDITOR_HOST_INITIAL_FETCH,\n EDITOR_HOST_ARR,\n EDITOR_HOST_FILTERED_ARR,\n} from './EditorConstants';\n\nconst initialState = Immutable({\n [EDITOR_HOST_ARR]: [],\n [EDITOR_HOST_FILTERED_ARR]: [],\n diffViewType: 'split',\n editorName: 'editor',\n errorText: '',\n isFetchingHosts: false,\n isLoading: false,\n isMasked: false,\n isMaximized: false,\n isRendering: false,\n isSearchingHosts: false,\n isSelectOpen: false,\n keyBinding: 'Default',\n mode: 'Ruby',\n previewResult: '',\n renderedEditorValue: '',\n readOnly: false,\n searchQuery: '',\n selectedHost: {\n id: '',\n name: '',\n },\n selectedView: 'input',\n showError: false,\n templateClass: '',\n theme: 'Monokai',\n value: '',\n});\n\nexport default (state = initialState, action) => {\n const { payload } = action;\n\n switch (action.type) {\n case EDITOR_INITIALIZE: {\n return state.merge(payload);\n }\n\n case EDITOR_REVERT_CHANGES: {\n return state.merge(payload);\n }\n\n case EDITOR_IMPORT_FILE: {\n return state.set('value', payload.value);\n }\n\n case EDITOR_EXEC_PREVIEW: {\n return state.merge(payload);\n }\n\n case EDITOR_HOST_SELECT_CLEAR: {\n return state.set('searchQuery', '').set('isSearchingHosts', false);\n }\n\n case EDITOR_MODAL_TOGGLE: {\n return state.set('isMaximized', !state.isMaximized);\n }\n\n case EDITOR_CHANGE_DIFF_VIEW: {\n return state.set('diffViewType', payload);\n }\n\n case EDITOR_CHANGE_VALUE: {\n return state.set('value', payload);\n }\n\n case EDITOR_SHOW_ERROR: {\n return state.merge(payload);\n }\n\n case EDITOR_DISMISS_ERROR: {\n return state.merge(payload);\n }\n\n case EDITOR_CHANGE_TAB: {\n return state.set('selectedView', payload);\n }\n\n case EDITOR_CHANGE_SETTING: {\n return state.merge(payload);\n }\n\n case EDITOR_TOGGLE_MASK: {\n return state.set('isMasked', !state.isMasked);\n }\n\n case EDITOR_TOGGLE_RENDER_VIEW: {\n return state.set('isRendering', !state.isRendering);\n }\n\n case EDITOR_SHOW_LOADING: {\n return state.set('isLoading', true);\n }\n\n case EDITOR_HIDE_LOADING: {\n return state.set('isLoading', false);\n }\n\n case EDITOR_FETCH_HOST_PENDING: {\n return state.merge(payload);\n }\n\n case EDITOR_FETCH_HOST_RESOLVED: {\n return state.set('isFetchingHosts', false).merge(payload);\n }\n\n case EDITOR_HOST_INITIAL_FETCH: {\n return state.set('hosts', payload);\n }\n\n case EDITOR_HOST_SELECT_TOGGLE: {\n return state\n .set('isSelectOpen', !state.isSelectOpen)\n .set('searchQuery', '');\n }\n\n case EDITOR_HOST_SELECT_RESET: {\n return state\n .set('searchQuery', '')\n .set('isFetchingHosts', false)\n .set('isSearchingHosts', false);\n }\n\n default:\n return state;\n }\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Editor/EditorReducer.js","import { createSelector } from 'reselect';\nimport { EDITOR_HOST_ARR, EDITOR_HOST_FILTERED_ARR } from './EditorConstants';\n\nexport const selectEditor = state => state.editor;\n\nexport const selectValue = state => selectEditor(state).value;\nexport const selectPreviewResult = state => selectEditor(state).previewResult;\nexport const selectErrorText = state => selectEditor(state).errorText;\nexport const selectMode = state => selectEditor(state).mode;\nexport const selectKeyBind = state => selectEditor(state).keyBinding;\nexport const selectEditorName = state => selectEditor(state).editorName;\nexport const selectChosenView = state => selectEditor(state).selectedView;\nexport const selectTheme = state => selectEditor(state).theme;\nexport const selectDiffType = state => selectEditor(state).diffViewType;\nexport const selectIsMaximized = state => selectEditor(state).isMaximized;\nexport const selectIsMasked = state => selectEditor(state).isMasked;\nexport const selectIsRendering = state => selectEditor(state).isRendering;\nexport const selectIsLoading = state => selectEditor(state).isLoading;\nexport const selectIsReadOnly = state => selectEditor(state).readOnly;\nexport const selectShowError = state => selectEditor(state).showError;\nexport const selectTemplateClass = state => selectEditor(state).templateClass;\nexport const selectRenderedEditorValue = state =>\n selectEditor(state).renderedEditorValue;\n\n// Select\nexport const selectHosts = state => selectEditor(state)[EDITOR_HOST_ARR];\nexport const selectFilteredHosts = state =>\n selectEditor(state)[EDITOR_HOST_FILTERED_ARR];\nexport const selectIsSearchingHosts = state =>\n selectEditor(state).isSearchingHosts;\nexport const selectChosenHost = state => selectEditor(state).selectedHost;\nexport const selectIsSelectOpen = state => selectEditor(state).isSelectOpen;\nexport const selectSearchQuery = state => selectEditor(state).searchQuery;\nexport const selectIsFetchingHosts = state =>\n selectEditor(state).isFetchingHosts;\n\nexport const navHostsSelector = createSelector(selectHosts, hosts =>\n navHosts(hosts)\n);\n\nexport const navFilteredHostsSelector = createSelector(\n selectFilteredHosts,\n hosts => navHosts(hosts)\n);\n\nconst navHosts = hosts => {\n if (hosts)\n return hosts.map(host => ({ id: host.id.toString(), name: host.name }));\n return [];\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Editor/EditorSelectors.js","import React, { Component } from 'react';\nimport PropTypes from 'prop-types';\nimport { Select } from 'patternfly-react-extensions';\nimport { translate as __ } from '../../../common/I18n';\nimport './editorhostselect.scss';\n\nclass EditorHostSelect extends Component {\n componentDidMount() {\n document.addEventListener('mousedown', this.handleClickOutside);\n }\n\n componentWillUnmount() {\n document.removeEventListener('mousedown', this.handleClickOutside);\n }\n\n setWrapperRef = node => {\n this.selectRef = node;\n };\n\n handleClickOutside = event => {\n if (this.selectRef && !this.selectRef.contains(event.target)) {\n const { open, onToggle } = this.props;\n if (open) onToggle();\n }\n };\n\n onKey = event => {\n if (event.keyCode === 27) {\n const { open, onToggle } = this.props;\n if (open) onToggle();\n }\n };\n\n render() {\n const {\n show,\n isLoading,\n onChange,\n onSearchChange,\n onSearchClear,\n onToggle,\n open,\n options,\n searchQuery,\n selectedItem,\n } = this.props;\n return (\n \n \n
\n );\n }\n}\n\nEditorHostSelect.propTypes = {\n show: PropTypes.bool.isRequired,\n isLoading: PropTypes.bool.isRequired,\n onChange: PropTypes.func.isRequired,\n onSearchChange: PropTypes.func.isRequired,\n onSearchClear: PropTypes.func.isRequired,\n onToggle: PropTypes.func.isRequired,\n open: PropTypes.bool.isRequired,\n options: PropTypes.array.isRequired,\n searchQuery: PropTypes.string.isRequired,\n selectedItem: PropTypes.shape({\n id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),\n name: PropTypes.string,\n }).isRequired,\n};\n\nexport default EditorHostSelect;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Editor/components/EditorHostSelect.js","import React from 'react';\nimport { Modal, Icon, Button } from 'patternfly-react';\nimport PropTypes from 'prop-types';\n\nimport EditorView from './EditorView';\nimport DiffRadioButtons from '../../DiffView/DiffRadioButtons';\nimport DiffView from '../../DiffView/DiffView';\n\nconst EditorModal = ({\n changeDiffViewType,\n changeEditorValue,\n diffViewType,\n editorValue,\n previewValue,\n isMasked,\n isMaximized,\n isRendering,\n keyBinding,\n mode,\n name,\n readOnly,\n selectedView,\n template,\n theme,\n title,\n toggleModal,\n}) => (\n \n \n {title}
\n \n {selectedView === 'diff' && (\n changeDiffViewType(viewType)}\n />\n )}\n \n \n {selectedView === 'diff' ? (\n \n \n
\n ) : (\n \n )}\n \n \n);\n\nEditorModal.propTypes = {\n changeDiffViewType: PropTypes.func.isRequired,\n changeEditorValue: PropTypes.func.isRequired,\n diffViewType: PropTypes.string.isRequired,\n editorValue: PropTypes.string.isRequired,\n previewValue: PropTypes.string.isRequired,\n isRendering: PropTypes.bool.isRequired,\n isMasked: PropTypes.bool.isRequired,\n isMaximized: PropTypes.bool.isRequired,\n keyBinding: PropTypes.string.isRequired,\n mode: PropTypes.string.isRequired,\n name: PropTypes.string.isRequired,\n readOnly: PropTypes.bool.isRequired,\n selectedView: PropTypes.string.isRequired,\n template: PropTypes.string.isRequired,\n theme: PropTypes.string.isRequired,\n title: PropTypes.string,\n toggleModal: PropTypes.func.isRequired,\n};\n\nEditorModal.defaultProps = {\n title: '',\n};\n\nexport default EditorModal;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Editor/components/EditorModal.js","import React, { useState } from 'react';\nimport PropTypes from 'prop-types';\nimport { Nav, Spinner, Alert, Button } from 'patternfly-react';\nimport { translate as __ } from '../../../common/I18n';\nimport EditorRadioButton from './EditorRadioButton';\nimport EditorOptions from './EditorOptions';\nimport EditorHostSelect from './EditorHostSelect';\nimport EditorSafemodeCheckbox from './EditorSafemodeCheckbox';\n\nconst EditorNavbar = ({\n changeDiffViewType,\n changeSetting,\n changeTab,\n diffViewType,\n hosts,\n filteredHosts,\n importFile,\n isDiff,\n isLoading,\n isMasked,\n isRendering,\n isFetchingHosts,\n isSearchingHosts,\n keyBinding,\n keyBindings,\n mode,\n modes,\n previewTemplate,\n isSafemodeEnabled,\n renderPath,\n safemodeRenderPath,\n revertChanges,\n selectedHost,\n selectedView,\n showHide,\n showImport,\n showPreview,\n showHostSelector,\n template,\n theme,\n themes,\n toggleMaskValue,\n toggleModal,\n toggleRenderView,\n value,\n renderedEditorValue,\n previewResult,\n searchQuery,\n onHostSelectToggle,\n onHostSearch,\n onSearchClear,\n isSelectOpen,\n showError,\n fetchAndPreview,\n}) => {\n const [safemode, setSafemode] = useState(isSafemodeEnabled);\n const handleSafeModeChange = ({ currentTarget: { checked: newChecked } }) => {\n setSafemode(newChecked);\n const newRenderPath = newChecked ? safemodeRenderPath : renderPath;\n previewTemplate({ host: selectedHost, renderPath: newRenderPath });\n };\n const selectedRenderPath = safemode ? safemodeRenderPath : renderPath;\n\n return (\n \n
\n
\n
\n );\n};\n\nEditorNavbar.propTypes = {\n changeDiffViewType: PropTypes.func.isRequired,\n changeSetting: PropTypes.func.isRequired,\n changeTab: PropTypes.func.isRequired,\n diffViewType: PropTypes.string.isRequired,\n fetchAndPreview: PropTypes.func.isRequired,\n filteredHosts: PropTypes.array,\n hosts: PropTypes.array,\n importFile: PropTypes.func.isRequired,\n isDiff: PropTypes.bool.isRequired,\n isFetchingHosts: PropTypes.bool.isRequired,\n isLoading: PropTypes.bool.isRequired,\n isMasked: PropTypes.bool.isRequired,\n isRendering: PropTypes.bool.isRequired,\n isSearchingHosts: PropTypes.bool.isRequired,\n isSelectOpen: PropTypes.bool.isRequired,\n keyBinding: PropTypes.string.isRequired,\n keyBindings: PropTypes.array.isRequired,\n mode: PropTypes.string.isRequired,\n modes: PropTypes.array.isRequired,\n onHostSearch: PropTypes.func.isRequired,\n onHostSelectToggle: PropTypes.func.isRequired,\n onSearchClear: PropTypes.func.isRequired,\n previewResult: PropTypes.string.isRequired,\n previewTemplate: PropTypes.func.isRequired,\n renderedEditorValue: PropTypes.string.isRequired,\n isSafemodeEnabled: PropTypes.bool.isRequired,\n renderPath: PropTypes.string,\n safemodeRenderPath: PropTypes.string,\n revertChanges: PropTypes.func.isRequired,\n searchQuery: PropTypes.string.isRequired,\n selectedHost: PropTypes.shape({\n id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),\n name: PropTypes.string,\n }).isRequired,\n selectedView: PropTypes.string.isRequired,\n showError: PropTypes.bool.isRequired,\n showHide: PropTypes.bool,\n showImport: PropTypes.bool.isRequired,\n showPreview: PropTypes.bool.isRequired,\n showHostSelector: PropTypes.bool,\n template: PropTypes.string,\n theme: PropTypes.string.isRequired,\n themes: PropTypes.array.isRequired,\n toggleMaskValue: PropTypes.func.isRequired,\n toggleModal: PropTypes.func.isRequired,\n toggleRenderView: PropTypes.func.isRequired,\n value: PropTypes.string.isRequired,\n};\n\nEditorNavbar.defaultProps = {\n hosts: [],\n filteredHosts: [],\n renderPath: '',\n safemodeRenderPath: '',\n showHide: false,\n template: '',\n showHostSelector: true,\n};\n\nexport default EditorNavbar;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Editor/components/EditorNavbar.js","/* eslint-disable no-alert */\nimport React from 'react';\nimport PropTypes from 'prop-types';\n\nimport {\n Button,\n Icon,\n OverlayTrigger,\n FormControl,\n Tooltip,\n} from 'patternfly-react';\n\nimport { translate as __ } from '../../../common/I18n';\nimport { bindMethods } from '../../../common/helpers';\nimport DiffRadioButtons from '../../DiffView/DiffRadioButtons';\nimport EditorSettings from './EditorSettings';\n\nclass EditorOptions extends React.Component {\n constructor(props) {\n super(props);\n bindMethods(this, ['fileDialog']);\n this.fileInput = React.createRef();\n }\n\n fileDialog() {\n this.fileInput.click();\n }\n\n render() {\n const {\n changeDiffViewType,\n changeSetting,\n changeTab,\n diffViewType,\n importFile,\n isDiff,\n isMasked,\n keyBinding,\n keyBindings,\n mode,\n modes,\n revertChanges,\n selectedView,\n showHide,\n showImport,\n template,\n theme,\n themes,\n toggleMaskValue,\n toggleModal,\n } = this.props;\n\n return (\n \n {selectedView === 'diff' && (\n changeDiffViewType(viewType)}\n />\n )}\n\n |
\n {showHide && (\n {__('Hide Content')}}\n placement=\"top\"\n trigger={['hover']}\n >\n \n \n )}\n {isDiff ? ( // fixing tooltip showing sometimes for disabled icon\n \n {__('Revert Local Changes')}\n \n }\n placement=\"top\"\n trigger={['hover']}\n >\n \n \n ) : (\n \n )}\n {showImport && (\n {__('Import File')}}\n placement=\"top\"\n trigger={['hover']}\n >\n \n \n )}\n \n {__('Maximize')}}\n placement=\"top\"\n trigger={['hover']}\n >\n \n \n
\n );\n }\n}\n\nEditorOptions.propTypes = {\n changeDiffViewType: PropTypes.func.isRequired,\n changeSetting: PropTypes.func.isRequired,\n changeTab: PropTypes.func.isRequired,\n diffViewType: PropTypes.string.isRequired,\n importFile: PropTypes.func.isRequired,\n isDiff: PropTypes.bool.isRequired,\n isMasked: PropTypes.bool.isRequired,\n keyBinding: PropTypes.string.isRequired,\n keyBindings: PropTypes.array.isRequired,\n mode: PropTypes.string.isRequired,\n modes: PropTypes.array.isRequired,\n revertChanges: PropTypes.func.isRequired,\n selectedView: PropTypes.string.isRequired,\n showHide: PropTypes.bool,\n showImport: PropTypes.bool.isRequired,\n template: PropTypes.string,\n theme: PropTypes.string.isRequired,\n themes: PropTypes.array.isRequired,\n toggleMaskValue: PropTypes.func.isRequired,\n toggleModal: PropTypes.func.isRequired,\n};\n\nEditorOptions.defaultProps = {\n showHide: false,\n template: '',\n};\n\nexport default EditorOptions;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Editor/components/EditorOptions.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { Icon, NavItem } from 'patternfly-react';\n\nconst EditorRadioButton = ({\n btnView,\n disabled,\n icon,\n onClick,\n stateView,\n title,\n}) => (\n \n {icon && }\n {icon ? ` ${title}` : title}\n \n);\n\nEditorRadioButton.propTypes = {\n btnView: PropTypes.string.isRequired,\n disabled: PropTypes.bool,\n icon: PropTypes.object,\n onClick: PropTypes.func.isRequired,\n stateView: PropTypes.string.isRequired,\n title: PropTypes.string.isRequired,\n};\n\nEditorRadioButton.defaultProps = {\n icon: null,\n disabled: false,\n};\n\nexport default EditorRadioButton;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Editor/components/EditorRadioButton.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { translate as __ } from '../../../common/I18n';\nimport './editorsafemodecheckbox.scss';\n\nconst EditorSafemodeCheckbox = ({\n show,\n checked,\n disabled,\n handleSafeModeChange,\n}) => {\n if (show) {\n return (\n \n \n \n \n );\n }\n return null;\n};\n\nEditorSafemodeCheckbox.propTypes = {\n show: PropTypes.bool.isRequired,\n checked: PropTypes.bool.isRequired,\n disabled: PropTypes.bool.isRequired,\n handleSafeModeChange: PropTypes.func.isRequired,\n};\n\nexport default EditorSafemodeCheckbox;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Editor/components/EditorSafemodeCheckbox.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport {\n Popover,\n Dropdown,\n MenuItem,\n Button,\n Icon,\n OverlayTrigger,\n} from 'patternfly-react';\nimport { translate as __ } from '../../../common/I18n';\n\nconst EditorSettings = ({\n selectedView,\n changeSetting,\n keyBinding,\n keyBindings,\n mode,\n modes,\n theme,\n themes,\n}) => (\n \n \n
{__('Syntax')}
\n
\n {mode}\n \n {modes.map((aceMode, i) => (\n \n ))}\n \n \n
\n \n
{__('Keybind')}
\n
\n {keyBinding}\n \n {keyBindings.map((keyBind, i) => (\n \n ))}\n \n \n
\n \n
{__('Theme')}
\n
\n {theme}\n \n {themes.map((themeKey, i) => (\n \n ))}\n \n \n
\n \n }\n placement=\"bottom\"\n trigger={['click']}\n rootClose\n >\n \n \n);\n\nEditorSettings.propTypes = {\n changeSetting: PropTypes.func.isRequired,\n keyBinding: PropTypes.string.isRequired,\n keyBindings: PropTypes.array.isRequired,\n selectedView: PropTypes.string.isRequired,\n mode: PropTypes.string.isRequired,\n modes: PropTypes.array.isRequired,\n theme: PropTypes.string.isRequired,\n themes: PropTypes.array.isRequired,\n};\n\nexport default EditorSettings;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Editor/components/EditorSettings.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport AceEditor from 'react-ace';\nimport classNames from 'classnames';\n\nimport { noop } from '../../../common/helpers';\n\nconst EditorView = ({\n className,\n isMasked,\n keyBinding,\n mode,\n name,\n onChange,\n readOnly,\n theme,\n value,\n isSelected,\n}) => (\n onChange(editorValue)}\n name={name}\n className={classNames({\n [className]: isSelected,\n 'mask-editor': isMasked,\n hidden: !isSelected,\n })}\n readOnly={readOnly}\n editorProps={{ $blockScrolling: Infinity }}\n showPrintMargin={false}\n debounceChangePeriod={250}\n />\n);\nEditorView.propTypes = {\n mode: PropTypes.string.isRequired,\n theme: PropTypes.string.isRequired,\n keyBinding: PropTypes.string.isRequired,\n onChange: PropTypes.func,\n readOnly: PropTypes.bool.isRequired,\n name: PropTypes.string.isRequired,\n value: PropTypes.string,\n className: PropTypes.string,\n isMasked: PropTypes.bool.isRequired,\n isSelected: PropTypes.bool,\n};\nEditorView.defaultProps = {\n className: '',\n onChange: noop,\n value: '>',\n isSelected: true,\n};\nexport default EditorView;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Editor/components/EditorView.js","import { bindActionCreators } from 'redux';\nimport { connect } from 'react-redux';\n\nimport * as actions from './EditorActions';\nimport reducer from './EditorReducer';\n\nimport Editor from './Editor';\n\nimport {\n navFilteredHostsSelector,\n navHostsSelector,\n selectChosenHost,\n selectChosenView,\n selectDiffType,\n selectEditorName,\n selectErrorText,\n selectIsFetchingHosts,\n selectIsLoading,\n selectIsMasked,\n selectIsMaximized,\n selectIsReadOnly,\n selectIsRendering,\n selectIsSearchingHosts,\n selectIsSelectOpen,\n selectKeyBind,\n selectMode,\n selectPreviewResult,\n selectRenderedEditorValue,\n selectSearchQuery,\n selectShowError,\n selectTheme,\n selectValue,\n} from './EditorSelectors';\n\n// map state to props\nconst mapStateToProps = state => ({\n diffViewType: selectDiffType(state),\n editorName: selectEditorName(state),\n errorText: selectErrorText(state),\n filteredHosts: navFilteredHostsSelector(state),\n hosts: navHostsSelector(state),\n isFetchingHosts: selectIsFetchingHosts(state),\n isLoading: selectIsLoading(state),\n isMasked: selectIsMasked(state),\n isMaximized: selectIsMaximized(state),\n isRendering: selectIsRendering(state),\n isSearchingHosts: selectIsSearchingHosts(state),\n isSelectOpen: selectIsSelectOpen(state),\n keyBinding: selectKeyBind(state),\n mode: selectMode(state),\n previewResult: selectPreviewResult(state),\n renderedEditorValue: selectRenderedEditorValue(state),\n readOnly: selectIsReadOnly(state),\n searchQuery: selectSearchQuery(state),\n selectedHost: selectChosenHost(state),\n selectedView: selectChosenView(state),\n showError: selectShowError(state),\n theme: selectTheme(state),\n value: selectValue(state),\n});\n\n// map action dispatchers to props\nconst mapDispatchToProps = dispatch => bindActionCreators(actions, dispatch);\n\n// export reducers\nexport const reducers = { editor: reducer };\n\n// export connected component\nexport default connect(mapStateToProps, mapDispatchToProps)(Editor);\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Editor/index.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { translate as __ } from '../../common/I18n';\nimport EmptyState from '../common/EmptyState';\nimport { foremanUrl, getManualURL } from '../../common/helpers';\n\nexport const WelcomeEnv = ({ canCreate }) => {\n const action = canCreate && {\n title: __('Create Puppet Environment'),\n url: foremanUrl('environments/new'),\n };\n\n const content = __(`If you are planning to use Foreman as an external node classifier you should provide information about one or more environments.
\n This information is commonly imported from a pre-existing Puppet configuration by the use of the Puppet classes and environment importer.`);\n return (\n }\n documentation={{ url: getManualURL('4.2.1Environments') }}\n action={action}\n />\n );\n};\n\nWelcomeEnv.propTypes = {\n canCreate: PropTypes.bool,\n};\n\nWelcomeEnv.defaultProps = {\n canCreate: false,\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Enviroments/Welcome.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { Button, Grid } from 'patternfly-react';\nimport { translate as __ } from '../../common/I18n';\nimport './externalLogout.scss';\n\nconst ExternalLogout = ({\n logoSrc,\n version,\n caption,\n submitLink,\n backgroundUrl,\n}) => {\n const style = backgroundUrl\n ? { backgroundImage: `url(${backgroundUrl})` }\n : {};\n return (\n \n
\n \n \n \n \n \n \n \n
\n );\n};\n\nExternalLogout.propTypes = {\n backgroundUrl: PropTypes.string,\n caption: PropTypes.string,\n logoSrc: PropTypes.string,\n version: PropTypes.string,\n submitLink: PropTypes.string.isRequired,\n};\n\nExternalLogout.defaultProps = {\n backgroundUrl: null,\n caption: null,\n logoSrc: null,\n version: null,\n};\n\nexport default ExternalLogout;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/ExternalLogout/ExternalLogout.js","export { default } from './ExternalLogout';\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/ExternalLogout/index.js","import React from 'react';\nimport { Modal, Button, OverlayTrigger, Tooltip } from 'patternfly-react';\nimport PropTypes from 'prop-types';\nimport { noop } from '../../common/helpers';\nimport DonutChart from '../common/charts/DonutChart';\nimport Loader from '../common/Loader';\nimport MessageBox from '../common/MessageBox';\nimport { STATUS } from '../../constants';\nimport {\n sprintf,\n ngettext as n__,\n translate as __,\n} from '../../../react_app/common/I18n';\n\nconst FactChart = ({\n hostsCount,\n modalToDisplay,\n status,\n chartData,\n closeModal,\n openModal,\n search,\n id,\n title,\n}) => {\n const chartProps = {\n data: chartData,\n key: `chart-${id}`,\n searchUrl: search && !search.match(/=$/) ? search : null,\n };\n\n const chart = ;\n\n const requestErrorMsg =\n status === STATUS.ERROR ? __('Request Failed') : __('No data available');\n\n const error = modalToDisplay ? (\n \n ) : (\n false\n );\n\n const tooltip = (\n \n {__('Show distribution chart')}\n \n );\n\n return (\n \n
\n \n \n {modalToDisplay && (\n
\n \n \n {sprintf(__('Fact distribution chart - %s '), title)}\n {hostsCount && (\n \n {sprintf(\n n__('(%s host)', '(%s hosts)', hostsCount),\n hostsCount\n )}\n \n )}\n \n \n \n \n {[chart, error]}\n
\n \n \n )}\n
\n );\n};\n\nFactChart.propTypes = {\n modalToDisplay: PropTypes.bool,\n hostsCount: PropTypes.number,\n openModal: PropTypes.func,\n closeModal: PropTypes.func,\n status: PropTypes.string,\n chartData: PropTypes.arrayOf(PropTypes.array),\n search: PropTypes.string,\n title: PropTypes.string,\n id: PropTypes.number.isRequired,\n};\n\nFactChart.defaultProps = {\n modalToDisplay: false,\n hostsCount: 0,\n openModal: noop,\n closeModal: noop,\n status: null,\n chartData: null,\n search: null,\n title: '',\n};\n\nexport default FactChart;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/FactCharts/FactChart.js","import {\n FACT_CHART_MODAL_OPEN,\n FACT_CHART_MODAL_CLOSE,\n} from './FactChartConstants';\nimport { get } from '../../redux/API';\n\nexport const openModal = ({ id, title, apiKey, apiUrl }) => dispatch => {\n dispatch(get({ key: apiKey, url: apiUrl }));\n dispatch({\n type: FACT_CHART_MODAL_OPEN,\n payload: { id, title },\n });\n};\n\nexport const closeModal = id => ({\n type: FACT_CHART_MODAL_CLOSE,\n payload: { id },\n});\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/FactCharts/FactChartActions.js","export const FACT_CHART = 'FACT_CHART';\nexport const FACT_CHART_MODAL_OPEN = 'FACT_CHART_MODAL_OPEN';\nexport const FACT_CHART_MODAL_CLOSE = 'FACT_CHART_MODAL_CLOSE';\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/FactCharts/FactChartConstants.js","import Immutable from 'seamless-immutable';\nimport {\n FACT_CHART_MODAL_CLOSE,\n FACT_CHART_MODAL_OPEN,\n} from './FactChartConstants';\n\nconst initialState = Immutable({\n modalToDisplay: {},\n});\n\n// should be removed when the modals infrastructure will get merged.\nexport default (state = initialState, { type, payload }) => {\n switch (type) {\n case FACT_CHART_MODAL_OPEN:\n return state\n .set('title', payload.title)\n .set('modalToDisplay', { [payload.id]: true });\n case FACT_CHART_MODAL_CLOSE:\n return state.set('modalToDisplay', {});\n default:\n return state;\n }\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/FactCharts/FactChartReducer.js","import { createSelector } from 'reselect';\nimport {\n selectAPIStatus,\n selectAPIResponse,\n} from '../../redux/API/APISelectors';\n\nexport const selectFactChartData = (state, key) =>\n selectAPIResponse(state, key).values || [];\n\nexport const selectFactChartStatus = (state, key) =>\n selectAPIStatus(state, key);\n\nconst hostCounter = (accumulator, currentValue) => accumulator + currentValue;\n\nexport const selectHostCount = createSelector(selectFactChartData, chartData =>\n chartData.length ? chartData.map(item => item[1]).reduce(hostCounter) : 0\n);\n\nexport const selectFactChart = state => state.factChart;\n\nexport const selectDisplayModal = (state, id) =>\n selectFactChart(state).modalToDisplay[id] || false;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/FactCharts/FactChartSelectors.js","import React from 'react';\nimport { useSelector, useDispatch } from 'react-redux';\nimport PropTypes from 'prop-types';\nimport FactChart from './FactChart';\nimport reducer from './FactChartReducer';\nimport { openModal, closeModal } from './FactChartActions';\nimport { FACT_CHART } from './FactChartConstants';\nimport {\n selectHostCount,\n selectDisplayModal,\n selectFactChartStatus,\n selectFactChartData,\n} from './FactChartSelectors';\n\nconst ConnectedFactChart = ({ id, path, title, search }) => {\n const key = `${FACT_CHART}_${id}`;\n const hostsCount = useSelector(state => selectHostCount(state, key));\n const status = useSelector(state => selectFactChartStatus(state, key));\n const chartData = useSelector(state => selectFactChartData(state, key));\n const modalToDisplay = useSelector(state => selectDisplayModal(state, id));\n const dispatch = useDispatch();\n const dispatchCloseModal = () => dispatch(closeModal(id));\n const dispatchOpenModal = () =>\n dispatch(openModal({ id, title, apiKey: key, apiUrl: path }));\n\n return (\n \n );\n};\n\nConnectedFactChart.propTypes = {\n id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,\n path: PropTypes.string.isRequired,\n title: PropTypes.string.isRequired,\n search: PropTypes.string,\n};\n\nConnectedFactChart.defaultProps = {\n search: null,\n};\n\nexport default ConnectedFactChart;\n\nexport const reducers = { factChart: reducer };\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/FactCharts/index.js","import React from 'react';\nimport { Modal } from 'patternfly-react';\nimport PropTypes from 'prop-types';\nimport ModalContext from './ForemanModalContext';\nimport ForemanModalHeader from './subcomponents/ForemanModalHeader';\nimport ForemanModalFooter from './subcomponents/ForemanModalFooter';\nimport { extractModalNodes } from './helpers';\n\nconst ForemanModal = props => {\n const {\n id,\n title,\n onClose,\n isOpen,\n children,\n isSubmitting,\n submitProps,\n ...propsToPassDown\n } = props;\n // Extract header and footer from children, if provided\n const { headerChild, footerChild, otherChildren } = extractModalNodes(\n children\n );\n const context = {\n isOpen,\n onClose,\n isSubmitting,\n id,\n title,\n submitProps,\n };\n\n const defaultHeader = headerTitle =>\n headerTitle ? : null;\n const headerToRender = headerChild || defaultHeader(title);\n\n const defaultFooter = subProps =>\n Object.keys(subProps).length !== 0 ? : null;\n const footerToRender = footerChild || defaultFooter(submitProps);\n\n return (\n \n \n {headerToRender}\n {otherChildren}\n {footerToRender}\n \n \n );\n};\n\nForemanModal.propTypes = {\n children: PropTypes.node,\n title: PropTypes.string,\n id: PropTypes.string.isRequired,\n isOpen: PropTypes.bool,\n onClose: PropTypes.func.isRequired,\n isSubmitting: PropTypes.bool,\n submitProps: PropTypes.object,\n};\n\nForemanModal.defaultProps = {\n children: null,\n isOpen: false,\n title: '',\n isSubmitting: false,\n submitProps: {},\n};\n\nexport default ForemanModal;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/ForemanModal/ForemanModal.js","import {\n ADD_MODAL,\n SET_MODAL_OPEN,\n SET_MODAL_CLOSED,\n SET_MODAL_START_SUBMITTING,\n SET_MODAL_STOP_SUBMITTING,\n} from './ForemanModalConstants';\nimport { selectModalExists } from './ForemanModalSelectors';\n\nexport const addModal = ({ id, isOpen = false, isSubmitting = false }) => (\n dispatch,\n getState\n) =>\n dispatch({\n type: ADD_MODAL,\n payload: { id, isOpen, isSubmitting },\n });\n\nconst modalAction = actionType => ({ id }) => (dispatch, getState) => {\n if (!selectModalExists(getState(), id)) {\n // eslint-disable-next-line no-console\n console.warn(\n `${actionType} action received, but ForemanModal with id '${id}' does not exist.`\n );\n }\n return dispatch({\n type: actionType,\n payload: { id },\n });\n};\n\nexport const setModalStartSubmitting = modalAction(SET_MODAL_START_SUBMITTING);\nexport const setModalStopSubmitting = modalAction(SET_MODAL_STOP_SUBMITTING);\nexport const setModalOpen = modalAction(SET_MODAL_OPEN);\nexport const setModalClosed = modalAction(SET_MODAL_CLOSED);\n\n// Pass in the ForemanModal id here and get bound action creators with the id already plugged in.\nexport const bindForemanModalActionsToId = ({ id }) => ({\n addModal: () => addModal({ id }),\n setModalOpen: () => setModalOpen({ id }),\n setModalClosed: () => setModalClosed({ id }),\n setModalStartSubmitting: () => setModalStartSubmitting({ id }),\n setModalStopSubmitting: () => setModalStopSubmitting({ id }),\n});\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/ForemanModal/ForemanModalActions.js","export const SET_MODAL_OPEN = 'SET_MODAL_OPEN';\nexport const SET_MODAL_CLOSED = 'SET_MODAL_CLOSED';\nexport const ADD_MODAL = 'ADD_MODAL';\nexport const SET_MODAL_START_SUBMITTING = 'SET_MODAL_START_SUBMITTING';\nexport const SET_MODAL_STOP_SUBMITTING = 'SET_MODAL_STOP_SUBMITTING';\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/ForemanModal/ForemanModalConstants.js","import { createContext } from 'react';\n\n// creating context in a separate file to avoid circular imports\nexport default createContext(null);\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/ForemanModal/ForemanModalContext.js","import { useContext, useEffect } from 'react';\nimport { useDispatch, useSelector } from 'react-redux';\nimport { selectIsModalOpen } from './ForemanModalSelectors';\nimport { setModalOpen, setModalClosed } from './ForemanModalActions';\nimport ModalContext from './ForemanModalContext';\n\n// Because enzyme doesn't support useContext yet\nexport const useModalContext = () => useContext(ModalContext);\n\n// Use in any ForemanModal. Handles Redux actions for creating, opening, and closing the modal.\n// Make sure the id passed in matches the id prop of your .\n// Returns a variable that tells you the state and a function to toggle it.\nexport const useForemanModal = ({ id, isOpen = false }) => {\n if (!id) throw new Error('useForemanModal: ID is required');\n const initialModalState = isOpen;\n const modalOpen = useSelector(state => selectIsModalOpen(state, id)) || false;\n const dispatch = useDispatch();\n const boundSetModalClosed = () => dispatch(setModalClosed({ id }));\n const boundSetModalOpen = () => dispatch(setModalOpen({ id }));\n\n useEffect(() => {\n if (initialModalState === true) boundSetModalOpen();\n }, []); // eslint-disable-line react-hooks/exhaustive-deps\n\n return {\n modalOpen,\n setModalOpen: boundSetModalOpen,\n setModalClosed: boundSetModalClosed,\n };\n};\n\n// to get enzyme hacky test to work\nexport default ModalContext;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/ForemanModal/ForemanModalHooks.js","import Immutable from 'seamless-immutable';\nimport {\n SET_MODAL_OPEN,\n SET_MODAL_CLOSED,\n ADD_MODAL,\n SET_MODAL_START_SUBMITTING,\n SET_MODAL_STOP_SUBMITTING,\n} from './ForemanModalConstants';\n\nconst initialState = Immutable({});\n\n// Modals state has id as key and open state as value:\n// { myModal: {open: true} }\n// Since keys cannot be duplicated, we avoid creating duplicate modals in this way.\n\nexport default (state = initialState, action) => {\n switch (action.type) {\n case SET_MODAL_OPEN:\n return state.setIn([action.payload.id, 'isOpen'], true); // setIn(keypath, value)\n case SET_MODAL_CLOSED:\n return state.setIn([action.payload.id, 'isOpen'], false);\n case ADD_MODAL:\n if (state[action.payload.id]) return state; // if it already exists, don't change its state\n return state.setIn([action.payload.id], {\n isOpen: action.payload.isOpen || false,\n isSubmitting: action.payload.isSubmitting || false,\n });\n case SET_MODAL_START_SUBMITTING:\n return state.setIn([action.payload.id, 'isSubmitting'], true);\n case SET_MODAL_STOP_SUBMITTING:\n return state.setIn([action.payload.id, 'isSubmitting'], false);\n default:\n return state;\n }\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/ForemanModal/ForemanModalReducer.js","export const selectForemanModalsState = state => state.foremanModals;\nexport const selectModalStateById = (state, id) =>\n state.foremanModals && (state.foremanModals[id] || {});\nexport const selectIsModalOpen = (state, id) =>\n selectModalStateById(state, id).isOpen;\nexport const selectIsModalSubmitting = (state, id) =>\n selectModalStateById(state, id).isSubmitting;\nexport const selectModalExists = (state, id) =>\n Object.keys(selectModalStateById(state, id)).length > 0;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/ForemanModal/ForemanModalSelectors.js","import React from 'react';\nimport ForemanModalHeader from './subcomponents/ForemanModalHeader';\nimport ForemanModalFooter from './subcomponents/ForemanModalFooter';\n\n/**\n * Extract Header and Footer child nodes from ForemanModal.\n * @param {PropTypes.node} children ForemanModal props.children\n * @return {object} Child nodes separated out into headerChild, footerChild, otherChildren\n */\nexport const extractModalNodes = children => {\n children = React.Children.toArray(children);\n const headerChild =\n children.find(child => child.type === ForemanModalHeader) || null;\n const footerChild =\n children.find(child => child.type === ForemanModalFooter) || null;\n const otherChildren = children.filter(\n child =>\n child &&\n // child.type !== undefined &&\n child !== headerChild &&\n child !== footerChild\n );\n return { headerChild, footerChild, otherChildren };\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/ForemanModal/helpers.js","import React, { useEffect } from 'react';\nimport PropTypes from 'prop-types';\nimport { useSelector, useDispatch } from 'react-redux';\nimport {\n selectIsModalOpen,\n selectIsModalSubmitting,\n selectModalExists,\n} from './ForemanModalSelectors';\nimport { setModalClosed, addModal } from './ForemanModalActions';\nimport ForemanModal from './ForemanModal';\nimport ForemanModalHeader from './subcomponents/ForemanModalHeader';\nimport ForemanModalFooter from './subcomponents/ForemanModalFooter';\nimport reducer from './ForemanModalReducer';\n\nexport const reducers = { foremanModals: reducer };\n\nconst ConnectedForemanModal = props => {\n const { id, title } = props;\n const isOpen = useSelector(state => selectIsModalOpen(state, id));\n const isSubmitting = useSelector(state => selectIsModalSubmitting(state, id));\n const dispatch = useDispatch();\n const onClose = () => dispatch(setModalClosed({ id }));\n\n const modalExists = useSelector(state => selectModalExists(state, id));\n\n useEffect(() => {\n if (modalExists) return; // don't add modal if it already exists\n // https://github.com/facebook/react/issues/14920\n dispatch(addModal({ id, isOpen: false, isSubmitting: false }));\n }, [modalExists, id, dispatch]);\n\n return (\n \n );\n};\n\nConnectedForemanModal.propTypes = {\n id: PropTypes.string.isRequired,\n title: PropTypes.string,\n};\n\nConnectedForemanModal.defaultProps = {\n title: '',\n};\n\n// Header and Footer use the provided children, or default markup if none provided\n\nConnectedForemanModal.Header = ForemanModalHeader;\nConnectedForemanModal.Footer = ForemanModalFooter;\n\nexport default ConnectedForemanModal;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/ForemanModal/index.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { Modal, Button } from 'patternfly-react';\nimport { useModalContext } from '../ForemanModalHooks';\nimport { translate as __ } from '../../../common/I18n';\n\nimport SubmitOrCancel from './SubmitOrCancel';\n\nconst ForemanModalFooter = props => {\n const childCount = React.Children.count(props.children);\n const { onClose, isSubmitting, id, submitProps } = useModalContext();\n\n // Render the provided children, or default markup if none given\n const closeButton = childCount === 0 && (\n \n );\n\n const submitOrCancel = childCount === 0 && submitProps && (\n \n );\n\n return (\n \n {props.children}\n {submitOrCancel || closeButton}\n \n );\n};\n\nForemanModalFooter.propTypes = {\n children: PropTypes.node,\n};\n\nForemanModalFooter.defaultProps = {\n children: null,\n};\n\nexport default ForemanModalFooter;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/ForemanModal/subcomponents/ForemanModalFooter.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { Modal } from 'patternfly-react';\nimport { useModalContext } from '../ForemanModalHooks';\n\nconst ForemanModalHeader = props => {\n const { title } = useModalContext();\n // title will be falsey if its value is the default ''\n // Render the provided children, or default markup if none given\n return (\n \n {title && {title}}\n {props.children}\n \n );\n};\n\nForemanModalHeader.propTypes = {\n children: PropTypes.node,\n};\n\nForemanModalHeader.defaultProps = {\n children: null,\n};\n\nexport default ForemanModalHeader;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/ForemanModal/subcomponents/ForemanModalHeader.js","import React from 'react';\nimport { Button } from 'patternfly-react';\nimport PropTypes from 'prop-types';\n\nimport { translate as __ } from '../../../../common/I18n';\n\nconst CancelBtn = ({ onCancel, disabled, bsStyle, btnText }) => (\n \n);\n\nCancelBtn.propTypes = {\n onCancel: PropTypes.func.isRequired,\n disabled: PropTypes.bool,\n bsStyle: PropTypes.string,\n btnText: PropTypes.string,\n};\n\nCancelBtn.defaultProps = {\n disabled: false,\n bsStyle: 'default',\n btnText: __('Cancel'),\n};\n\nexport default CancelBtn;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/ForemanModal/subcomponents/SubmitOrCancel/CancelBtn.js","import React from 'react';\nimport { Button } from 'patternfly-react';\nimport PropTypes from 'prop-types';\nimport { translate as __ } from '../../../../common/I18n';\nimport { simpleLoader } from '../../../common/Loader';\n\nconst SubmitBtn = ({ isSubmitting, onSubmit, bsStyle, btnText }) => (\n \n);\n\nSubmitBtn.propTypes = {\n isSubmitting: PropTypes.bool.isRequired,\n onSubmit: PropTypes.func.isRequired,\n bsStyle: PropTypes.string,\n btnText: PropTypes.string,\n};\n\nSubmitBtn.defaultProps = {\n bsStyle: 'primary',\n btnText: __('Submit'),\n};\n\nexport default SubmitBtn;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/ForemanModal/subcomponents/SubmitOrCancel/SubmitBtn.js","import React from 'react';\nimport PropTypes from 'prop-types';\n\nimport SubmitBtn from './SubmitBtn';\nimport CancelBtn from './CancelBtn';\n\nconst SubmitOrCancel = ({\n isSubmitting,\n onCancel,\n onSubmit,\n submitBtnProps,\n cancelBtnProps,\n}) => (\n \n \n \n \n);\n\nSubmitOrCancel.propTypes = {\n isSubmitting: PropTypes.bool.isRequired,\n onCancel: PropTypes.func.isRequired,\n onSubmit: PropTypes.func.isRequired,\n submitBtnProps: PropTypes.object,\n cancelBtnProps: PropTypes.object,\n};\n\nSubmitOrCancel.defaultProps = {\n submitBtnProps: {},\n cancelBtnProps: {},\n};\n\nexport default SubmitOrCancel;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/ForemanModal/subcomponents/SubmitOrCancel/SubmitOrCancel.js","import { deepPropsToCamelCase } from '../../../../common/helpers';\n\nimport { API } from '../../../../redux/API';\n\nimport { addToast } from '../../../../redux/actions/toasts';\nimport { translate as __ } from '../../../../common/I18n';\nimport {\n setModalStartSubmitting,\n setModalStopSubmitting,\n} from '../../ForemanModalActions';\n\nconst onModalError = error => {\n const {\n response: {\n status,\n data: {\n error: { message, fullMessages },\n },\n } = {},\n } = deepPropsToCamelCase(error);\n\n if (message) {\n return message;\n }\n\n if (fullMessages) {\n return fullMessages.join(', ');\n }\n\n return `${status}: ${__('Failed to submit the request.')}`;\n};\n\nexport const submitModal = ({\n url,\n message,\n method = 'delete',\n closeFn,\n getErrorMsg = onModalError,\n onSuccess = () => {},\n id,\n}) => async dispatch => {\n try {\n dispatch(setModalStartSubmitting({ id }));\n const { data } = await API[method](url, {});\n dispatch(setModalStopSubmitting({ id }));\n onSuccess(data);\n closeFn();\n dispatch(\n addToast({\n type: 'success',\n message,\n })\n );\n } catch (error) {\n dispatch(setModalStopSubmitting({ id }));\n dispatch(\n addToast({\n type: 'error',\n message: getErrorMsg(error),\n })\n );\n }\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/ForemanModal/subcomponents/SubmitOrCancel/SubmitOrCancelActions.js","import React from 'react';\nimport { useDispatch } from 'react-redux';\nimport PropTypes from 'prop-types';\n\nimport { submitModal } from './SubmitOrCancelActions';\nimport SubmitOrCancel from './SubmitOrCancel';\n\nconst ConnectedSubmitOrCancel = ({\n isSubmitting,\n onCancel,\n submitProps,\n id,\n}) => {\n const dispatch = useDispatch();\n\n const { submitBtnProps, cancelBtnProps, ...rest } = submitProps;\n\n const boundOnSubmit = () =>\n dispatch(\n submitModal({\n ...rest,\n closeFn: onCancel,\n id,\n })\n );\n\n return (\n \n );\n};\n\nConnectedSubmitOrCancel.propTypes = {\n isSubmitting: PropTypes.bool.isRequired,\n submitProps: PropTypes.object,\n onCancel: PropTypes.func.isRequired,\n id: PropTypes.string.isRequired,\n};\n\nConnectedSubmitOrCancel.defaultProps = {\n submitProps: {},\n};\n\nexport default ConnectedSubmitOrCancel;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/ForemanModal/subcomponents/SubmitOrCancel/index.js","import PropTypes from 'prop-types';\nimport React from 'react';\nimport { Helmet } from 'react-helmet';\n\nconst Head = ({ children }) => {children};\n\nHead.propTypes = {\n children: PropTypes.node.isRequired,\n};\n\nexport default Head;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Head/index.js","import PropTypes from 'prop-types';\nimport React, { useState } from 'react';\nimport {\n Button,\n DropdownItem,\n DropdownSeparator,\n Dropdown,\n KebabToggle,\n} from '@patternfly/react-core';\nimport { foremanUrl } from '../../../../foreman_navigation';\nimport { translate as __ } from '../../../common/I18n';\n\nconst ActionsBar = ({ hostName }) => {\n const [kebabIsOpen, setKebab] = useState(false);\n const onKebabToggle = isOpen => setKebab(isOpen);\n\n const dropdownItems = [\n \n {__('Delete')}\n ,\n \n {__('Clone')}\n ,\n \n {__('Build')}\n ,\n ,\n {__('plugin action 1')},\n \n {__('plugin action 2')}\n ,\n ];\n\n return (\n <>\n \n }\n isOpen={kebabIsOpen}\n isPlain\n dropdownItems={dropdownItems}\n />\n >\n );\n};\n\nActionsBar.propTypes = {\n hostName: PropTypes.string.isRequired,\n};\n\nexport default ActionsBar;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/HostDetails/ActionsBar/index.js","import PropTypes from 'prop-types';\nimport React, { useState } from 'react';\nimport Skeleton from 'react-loading-skeleton';\nimport { ArrowIcon } from '@patternfly/react-icons';\nimport ElipsisWithTooltip from 'react-ellipsis-with-tooltip';\nimport {\n Card,\n DataList,\n DataListItem,\n DataListItemRow,\n DataListItemCells,\n DataListCell,\n CardBody,\n CardTitle,\n Accordion,\n AccordionItem,\n AccordionContent,\n AccordionToggle,\n} from '@patternfly/react-core';\n\nimport { foremanUrl } from '../../../../foreman_tools';\nimport { translate as __ } from '../../../common/I18n';\nimport { useAPI } from '../../../common/hooks/API/APIHooks';\n\nconst AuditCard = ({ hostName }) => {\n const [activeAccordion, setActiveAccordion] = useState(0);\n const onToggle = id => {\n if (id === activeAccordion) {\n setActiveAccordion('');\n } else {\n setActiveAccordion(id);\n }\n };\n\n const url = hostName && foremanUrl(`/api/audits?search=host+%3D+${hostName}`);\n const {\n response: { results },\n } = useAPI('get', url);\n return (\n \n \n {__('Recent Audits')}{' '}\n \n \n \n \n \n \n {!results && (\n \n \n
\n )}\n {results?.map((audit, index) => {\n if (index < 3)\n return (\n \n {\n onToggle(`${audit.request_uuid}-${index}`);\n }}\n isExpanded={\n activeAccordion === `${audit.request_uuid}-${index}`\n }\n id={`${audit.request_uuid}-${index}`}\n >\n {`${audit.action} (by ${audit.user_name})`}\n \n \n \n \n \n );\n return null;\n })}\n \n \n \n );\n};\n\nAuditCard.propTypes = {\n hostName: PropTypes.string,\n};\nAuditCard.defaultProps = {\n hostName: undefined,\n};\n\nexport default AuditCard;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/HostDetails/Audits/index.js","import PropTypes from 'prop-types';\nimport React, { useState } from 'react';\nimport {\n DataList,\n DataListItem,\n DataListItemRow,\n DataListItemCells,\n DataListCell,\n Card,\n CardTitle,\n CardBody,\n Accordion,\n AccordionItem,\n AccordionContent,\n AccordionToggle,\n} from '@patternfly/react-core';\nimport { StarIcon } from '@patternfly/react-icons';\nimport Skeleton from 'react-loading-skeleton';\nimport { translate as __ } from '../../../common/I18n';\n\nconst InterfacesCard = ({ interfaces }) => {\n const [ativeAccordion, setActiveAccordion] = useState(0);\n const onToggle = id => {\n if (id === ativeAccordion) {\n setActiveAccordion('');\n } else {\n setActiveAccordion(id);\n }\n };\n return (\n \n {__('Interfaces')}\n \n \n {!interfaces.length && (\n \n \n
\n )}\n {interfaces.map(Interface => (\n \n {\n onToggle(Interface.identifier);\n }}\n isExpanded={ativeAccordion === Interface.identifier}\n id={Interface.identifier}\n >\n \n {Interface.primary && } {Interface.identifier}\n \n \n \n \n \n \n ))}\n \n \n \n );\n};\n\nInterfacesCard.propTypes = {\n interfaces: PropTypes.array,\n};\nInterfacesCard.defaultProps = {\n interfaces: [],\n};\n\nexport default InterfacesCard;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/HostDetails/Interfaces/index.js","import PropTypes from 'prop-types';\nimport React, { useState } from 'react';\nimport {\n DataList,\n DataListItem,\n DataListItemRow,\n DataListItemCells,\n DataListCell,\n Card,\n CardBody,\n CardTitle,\n Accordion,\n AccordionItem,\n AccordionContent,\n AccordionToggle,\n} from '@patternfly/react-core';\nimport Skeleton from 'react-loading-skeleton';\nimport ElipsisWithTooltip from 'react-ellipsis-with-tooltip';\nimport { translate as __ } from '../../../common/I18n';\n\nconst ParametersCard = ({ paramters }) => {\n const [ativeAccordion, setActiveAccordion] = useState(0);\n const onToggle = id => {\n if (id === ativeAccordion) {\n setActiveAccordion('');\n } else {\n setActiveAccordion(id);\n }\n };\n return (\n \n {__('Parameters')}\n \n \n {!paramters.length && (\n \n \n
\n )}\n\n {paramters.map(param => (\n \n {\n onToggle(param.name);\n }}\n isExpanded={ativeAccordion === param.name}\n id={param.name}\n >\n {param.name}\n \n \n \n \n \n ))}\n \n \n \n );\n};\n\nParametersCard.propTypes = {\n paramters: PropTypes.array,\n};\nParametersCard.defaultProps = {\n paramters: [],\n};\n\nexport default ParametersCard;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/HostDetails/Parameters/index.js","import PropTypes from 'prop-types';\nimport React from 'react';\nimport {\n DataList,\n DataListItem,\n DataListItemRow,\n DataListItemCells,\n Card,\n DataListCell,\n} from '@patternfly/react-core';\nimport SkeletonLoader from '../../common/SkeletonLoader';\nimport { STATUS } from '../../../constants';\nimport { translate as __ } from '../../../common/I18n';\n\nconst Properties = ({ hostData, status }) => (\n \n \n \n);\n\nProperties.propTypes = {\n hostData: PropTypes.shape({\n architecture_name: PropTypes.string,\n domain_name: PropTypes.string,\n ip: PropTypes.string,\n ip6: PropTypes.string,\n location_name: PropTypes.string,\n mac: PropTypes.string,\n operatingsystem_name: PropTypes.string,\n organization_name: PropTypes.string,\n }).isRequired,\n status: PropTypes.string,\n};\n\nProperties.defaultProps = {\n status: STATUS.PENDING,\n};\nexport default Properties;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/HostDetails/Properties/index.js","import PropTypes from 'prop-types';\nimport React, { useCallback } from 'react';\nimport { Alert } from '@patternfly/react-core';\nimport Skeleton from 'react-loading-skeleton';\n\nconst Status = ({ status }) => {\n const statusToLabel = useCallback(() => {\n switch (status) {\n case 'OK':\n return ['success', 'Host Status - OK'];\n case 'Error':\n return ['danger', 'Host Status - ERROR'];\n case 'Warning':\n return ['warning', 'Host Status - WARNING '];\n default:\n return ['info', null];\n }\n }, [status]);\n const [variant, title] = statusToLabel();\n return } />;\n};\n\nStatus.propTypes = {\n status: PropTypes.string.isRequired,\n};\n\nexport default Status;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/HostDetails/Status/index.js","import PropTypes from 'prop-types';\nimport React from 'react';\nimport { Grid, GridItem, Flex, FlexItem } from '@patternfly/react-core';\n\nimport Properties from '../../Properties';\nimport ParametersCard from '../../Parameters';\nimport InterfacesCard from '../../Interfaces';\nimport AuditCard from '../../Audits';\nimport StatusAlert from '../../Status';\nimport Slot from '../../../common/Slot';\nimport { STATUS } from '../../../../constants';\nimport './Details.css';\n\nconst DetailsTab = ({ response, status }) => (\n \n
\n \n \n \n \n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
\n);\n\nDetailsTab.propTypes = {\n response: PropTypes.shape({\n all_parameters: PropTypes.string,\n global_status_label: PropTypes.string,\n interfaces: PropTypes.string,\n name: PropTypes.string,\n }),\n status: PropTypes.string,\n};\n\nDetailsTab.defaultProps = {\n response: {},\n status: STATUS.PENDING,\n};\nexport default DetailsTab;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/HostDetails/Tabs/Details/index.js","import React from 'react';\nimport { addGlobalFill } from '../../common/Fill/GlobalFill';\nimport DetailsTab from './Details';\n\nexport const registerCoreTabs = () => {\n addGlobalFill('host-details-page-tabs', 'Overview', , 1000);\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/HostDetails/Tabs/index.js","import PropTypes from 'prop-types';\nimport React, { useEffect, useState } from 'react';\nimport { useSelector, useDispatch } from 'react-redux';\nimport {\n Grid,\n Tab,\n Tabs,\n GridItem,\n Badge,\n Title,\n Breadcrumb,\n BreadcrumbItem,\n Text,\n TextVariants,\n PageSection,\n} from '@patternfly/react-core';\n\nimport Skeleton from 'react-loading-skeleton';\nimport RelativeDateTime from '../../components/common/dates/RelativeDateTime';\n\nimport { foremanUrl } from '../../../foreman_tools';\nimport { get } from '../../redux/API';\nimport {\n selectAPIResponse,\n selectAPIStatus,\n} from '../../redux/API/APISelectors';\nimport { selectFillsIDs } from '../common/Slot/SlotSelectors';\nimport { selectIsCollapsed } from '../Layout/LayoutSelectors';\nimport ActionsBar from './ActionsBar';\nimport Slot from '../common/Slot';\nimport { registerCoreTabs } from './Tabs';\nimport { translate as __ } from '../../common/I18n';\n\nimport './HostDetails.scss';\n\nconst HostDetails = ({ match, location: { hash } }) => {\n const dispatch = useDispatch();\n const [activeTab, setActiveTab] = useState('Overview');\n const response = useSelector(state =>\n selectAPIResponse(state, 'HOST_DETAILS')\n );\n const status = useSelector(state => selectAPIStatus(state, 'HOST_DETAILS'));\n const isNavCollapsed = useSelector(selectIsCollapsed);\n const tabs = useSelector(state =>\n selectFillsIDs(state, 'host-details-page-tabs')\n );\n\n // This is a workaround due to the tabs overflow mechanism in PF4\n useEffect(() => {\n if (tabs?.length) dispatchEvent(new Event('resize'));\n }, [tabs]);\n\n useEffect(() => {\n registerCoreTabs();\n }, []);\n\n useEffect(() => {\n if (hash) setActiveTab(hash.slice(1));\n }, [hash]);\n\n useEffect(() => {\n dispatch(\n get({\n key: 'HOST_DETAILS',\n url: foremanUrl(`/api/hosts/${match.params.id}`),\n })\n );\n }, [match.params.id, dispatch]);\n\n useEffect(() => {\n // This is a workaround for adding gray background inspiring pf4 desgin\n // TODO: delete it when pf4 layout (Page copmponent) is implemented in foreman\n document.body.classList.add('pf-gray-background');\n return () => document.body.classList.remove('pf-gray-background');\n }, []);\n\n const handleTabClick = (event, tabIndex) => {\n setActiveTab(tabIndex);\n };\n\n return (\n <>\n \n \n
\n {__('Hosts')}\n \n {response.name || }\n \n \n {/* TODO: Replace all br with css */}\n
\n
\n
\n \n \n {/* TODO: Make a generic Skeleton HOC (withSkeleton) */}\n {response.name || }\n \n \n \n {response.operatingsystem_name}{' '}\n {response.architecture_name}\n \n \n } />\n \n \n
\n {/* TODO: extracting text and remove timeago usage in favor i18n */}\n {response.name ? (\n \n created{' '}\n {' '}\n by {response.owner_name} (updated{' '}\n \n )\n
\n ) : (\n \n )}\n \n
\n
\n \n {tabs &&\n tabs.map(tab => (\n \n \n \n
\n \n ))}\n \n \n >\n );\n};\n\nHostDetails.propTypes = {\n match: PropTypes.shape({\n params: PropTypes.shape({\n id: PropTypes.string,\n }),\n }).isRequired,\n location: PropTypes.shape({\n hash: PropTypes.string,\n }).isRequired,\n};\n\nexport default HostDetails;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/HostDetails/index.js","import React from 'react';\n\nimport { VerticalNav } from 'patternfly-react';\nimport { translate as __ } from '../../common/I18n';\n\nimport {\n handleMenuClick,\n layoutPropTypes,\n layoutDefaultProps,\n} from './LayoutHelper';\nimport LayoutContainer from './components/LayoutContainer';\nimport HeaderToolbar from './components/Toolbar/HeaderToolbar';\nimport './layout.scss';\n\nconst Layout = ({\n items,\n data,\n isLoading,\n isCollapsed,\n navigate,\n expandLayoutMenus,\n collapseLayoutMenus,\n changeActiveMenu,\n activeMenu,\n children,\n}) => (\n \n \n handleMenuClick(primary, activeMenu, changeActiveMenu)\n }\n onNavigate={({ href }) => navigate(href)}\n activePath={`/${__(activeMenu || 'active')}/`}\n onCollapse={collapseLayoutMenus}\n onExpand={expandLayoutMenus}\n >\n \n \n \n \n {children}\n \n);\n\nLayout.propTypes = layoutPropTypes;\nLayout.defaultProps = layoutDefaultProps;\n\nexport default Layout;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Layout/Layout.js","import {\n LAYOUT_INITIALIZE,\n LAYOUT_SHOW_LOADING,\n LAYOUT_HIDE_LOADING,\n LAYOUT_CHANGE_ACTIVE,\n LAYOUT_EXPAND,\n LAYOUT_COLLAPSE,\n} from './LayoutConstants';\n\nexport const initializeLayout = ({\n items,\n activeMenu,\n isCollapsed,\n organization,\n location,\n}) => ({\n type: LAYOUT_INITIALIZE,\n payload: {\n items,\n activeMenu,\n isCollapsed,\n organization,\n location,\n },\n});\n\nexport const showLoading = () => ({\n type: LAYOUT_SHOW_LOADING,\n});\n\nexport const hideLoading = () => ({\n type: LAYOUT_HIDE_LOADING,\n});\n\nexport const changeActiveMenu = ({ title }) => ({\n type: LAYOUT_CHANGE_ACTIVE,\n payload: {\n activeMenu: title,\n },\n});\n\nexport const expandLayoutMenus = () => ({\n type: LAYOUT_EXPAND,\n});\n\nexport const collapseLayoutMenus = () => ({\n type: LAYOUT_COLLAPSE,\n});\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Layout/LayoutActions.js","export const LAYOUT_INITIALIZE = 'LAYOUT_INITIALIZE';\nexport const LAYOUT_SHOW_LOADING = 'LAYOUT_SHOW_LOADING';\nexport const LAYOUT_HIDE_LOADING = 'LAYOUT_HIDE_LOADING';\nexport const LAYOUT_CHANGE_ACTIVE = 'LAYOUT_CHANGE_ACTIVE';\nexport const LAYOUT_COLLAPSE = 'LAYOUT_COLLAPSE';\nexport const LAYOUT_EXPAND = 'LAYOUT_EXPAND';\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Layout/LayoutConstants.js","/* eslint-disable no-unused-vars */\n// eslint bug - https://github.com/eslint/eslint/issues/12117\n\nimport { isEmpty } from 'lodash';\nimport PropTypes from 'prop-types';\nimport { translate as __ } from '../../common/I18n';\nimport {\n removeLastSlashFromPath,\n noop,\n foremanUrl,\n} from '../../common/helpers';\n\nexport const createInitialTaxonomy = (currentTaxonomy, availableTaxonomies) => {\n const taxonomyId = availableTaxonomies.find(\n taxonomy => taxonomy.title === currentTaxonomy\n ).id;\n return {\n title: currentTaxonomy,\n id: taxonomyId,\n };\n};\n\nexport const getCurrentPath = () =>\n removeLastSlashFromPath(window.location.pathname);\n\nexport const getActiveMenuItem = (items, path = getCurrentPath()) => {\n for (const item of items) {\n for (const child of item.children) {\n if (child.exact) {\n if (path === child.url) return { title: item.name };\n } else if (path.startsWith(child.url)) return { title: item.name };\n }\n }\n return { title: '' };\n};\n\nexport const handleMenuClick = (primary, activeMenu, changeActive) => {\n if (primary.title !== __(activeMenu)) changeActive(primary);\n};\n\nexport const combineMenuItems = data => {\n const items = [];\n\n data.menu.forEach(item => {\n const translatedChildren = item.children.map(child => ({\n ...child,\n name: isEmpty(child.name) ? child.name : __(child.name),\n }));\n\n const translatedItem = {\n ...item,\n name: __(item.name),\n children: translatedChildren,\n // Hiding user if not on Mobile view\n className: item.name === 'User' ? 'hidden-nav-lg' : '',\n };\n items.push(translatedItem);\n });\n\n items.push(createOrgItem(data.orgs.available_organizations));\n items.push(createLocationItem(data.locations.available_locations));\n\n return items;\n};\n\nconst createOrgItem = orgs => {\n const anyOrg = {\n name: __('Any Organization'),\n onClick: () => {\n window.location.assign(foremanUrl('/organizations/clear'));\n },\n };\n const childrenArray = [anyOrg];\n\n orgs.forEach(org => {\n const childObject = {\n type: org.type,\n name: org.title,\n onClick: () => {\n window.location.assign(org.href);\n },\n };\n childrenArray.push(childObject);\n });\n\n const orgItem = {\n type: 'sub_menu',\n name: __('Organizations'),\n icon: 'fa fa-building',\n children: childrenArray,\n // Hiding Organizations if not on Mobile view\n className: 'organization-menu hidden-nav-lg',\n };\n return orgItem;\n};\n\nconst createLocationItem = locations => {\n const anyLoc = {\n name: __('Any Location'),\n onClick: () => {\n window.location.assign(foremanUrl('/locations/clear'));\n },\n };\n const childrenArray = [anyLoc];\n\n locations.forEach(loc => {\n const childObject = {\n type: loc.type,\n name: loc.title,\n onClick: () => {\n window.location.assign(loc.href);\n },\n };\n childrenArray.push(childObject);\n });\n\n const locItem = {\n type: 'sub_menu',\n name: __('Locations'),\n icon: 'fa fa-globe',\n children: childrenArray,\n // Hiding Locations if not on Mobile view\n className: 'location-menu hidden-nav-lg',\n };\n return locItem;\n};\n\nexport const organizationPropType = PropTypes.shape({\n current_org: PropTypes.string,\n available_organizations: PropTypes.arrayOf(\n PropTypes.shape({\n href: PropTypes.string.isRequired,\n id: PropTypes.number.isRequired,\n title: PropTypes.string,\n })\n ),\n});\n\nexport const locationPropType = PropTypes.shape({\n current_location: PropTypes.string,\n available_locations: PropTypes.arrayOf(\n PropTypes.shape({\n href: PropTypes.string.isRequired,\n id: PropTypes.number.isRequired,\n title: PropTypes.string,\n })\n ),\n});\n\nexport const userPropType = PropTypes.shape({\n current_user: PropTypes.object.isRequired,\n user_dropdown: PropTypes.arrayOf(\n PropTypes.shape({\n children: PropTypes.any,\n icon: PropTypes.string.isRequired,\n name: PropTypes.string.isRequired,\n type: PropTypes.string.isRequired,\n })\n ),\n});\n\nexport const dataPropType = {\n brand: PropTypes.string,\n stop_impersonation_url: PropTypes.string.isRequired,\n instance_title: PropTypes.string,\n menu: PropTypes.arrayOf(\n PropTypes.shape({\n type: PropTypes.string.isRequired,\n name: PropTypes.string.isRequired,\n icon: PropTypes.string.isRequired,\n children: PropTypes.any,\n })\n ),\n locations: locationPropType,\n orgs: organizationPropType,\n root: PropTypes.string.isRequired,\n logo: PropTypes.string.isRequired,\n notification_url: PropTypes.string.isRequired,\n user: userPropType,\n};\n\nexport const layoutPropTypes = {\n children: PropTypes.node,\n isLoading: PropTypes.bool,\n isCollapsed: PropTypes.bool,\n activeMenu: PropTypes.string,\n navigate: PropTypes.func,\n changeActiveMenu: PropTypes.func,\n expandLayoutMenus: PropTypes.func,\n collapseLayoutMenus: PropTypes.func,\n items: PropTypes.arrayOf(\n PropTypes.shape({\n title: PropTypes.string.isRequired,\n className: PropTypes.string,\n iconClass: PropTypes.string.isRequired,\n initialActive: PropTypes.bool,\n subItems: PropTypes.arrayOf(\n PropTypes.shape({\n title: PropTypes.string,\n isDivider: PropTypes.bool,\n className: PropTypes.string,\n href: PropTypes.string,\n })\n ),\n })\n ),\n data: PropTypes.shape(dataPropType),\n};\n\nexport const layoutDefaultProps = {\n children: null,\n items: [],\n data: {},\n isLoading: false,\n isCollapsed: false,\n activeMenu: '',\n navigate: noop,\n changeActiveMenu: noop,\n expandLayoutMenus: noop,\n collapseLayoutMenus: noop,\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Layout/LayoutHelper.js","import Immutable from 'seamless-immutable';\n\nimport {\n LAYOUT_INITIALIZE,\n LAYOUT_SHOW_LOADING,\n LAYOUT_HIDE_LOADING,\n LAYOUT_CHANGE_ACTIVE,\n LAYOUT_EXPAND,\n LAYOUT_COLLAPSE,\n} from './LayoutConstants';\n\nconst initialState = Immutable({\n items: [],\n isLoading: false,\n isCollapsed: false,\n activeMenu: 'initialActive',\n});\n\nexport default (state = initialState, action) => {\n const { payload, type } = action;\n\n switch (type) {\n case LAYOUT_INITIALIZE:\n return state\n .set('items', payload.items)\n .set('activeMenu', payload.activeMenu)\n .set('isCollapsed', payload.isCollapsed)\n .set('currentOrganization', payload.organization)\n .set('currentLocation', payload.location);\n\n case LAYOUT_SHOW_LOADING:\n return state.set('isLoading', true);\n\n case LAYOUT_HIDE_LOADING:\n return state.set('isLoading', false);\n\n case LAYOUT_CHANGE_ACTIVE:\n return state.set('activeMenu', payload.activeMenu);\n\n case LAYOUT_EXPAND:\n return state.set('isCollapsed', false);\n\n case LAYOUT_COLLAPSE:\n return state.set('isCollapsed', true);\n\n default:\n return state;\n }\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Layout/LayoutReducer.js","import { get, snakeCase } from 'lodash';\nimport { noop } from '../../common/helpers';\nimport { deprecate } from '../../common/DeprecationService';\n\nexport const selectLayout = state => state.layout;\n\nexport const selectMenuItems = state => selectLayout(state).items;\nexport const selectActiveMenu = state => selectLayout(state).activeMenu;\nexport const selectIsLoading = state => selectLayout(state).isLoading;\nexport const selectIsCollapsed = state => selectLayout(state).isCollapsed;\nexport const selectCurrentLocation = state => {\n deprecate('selectCurrentLocation', 'useForemanLocation hook', 2.5);\n return get(selectLayout(state), 'currentLocation');\n};\nexport const selectCurrentOrganization = state => {\n deprecate('selectCurrentOrganization', 'useForemanOrganization hook', 2.5);\n return get(selectLayout(state), 'currentOrganization');\n};\n\nexport const patternflyMenuItemsSelector = (\n state,\n currentLocation,\n currentOrganization\n) => {\n const items = selectMenuItems(state);\n return items.map(item => {\n const childrenArray = item.children\n .filter(child => child.name)\n .map(child =>\n childToMenuItem(child, currentLocation, currentOrganization)\n );\n\n return {\n title: item.name,\n iconClass: item.icon,\n subItems: childrenArray,\n className: item.className,\n };\n });\n};\n\nconst childToMenuItem = (child, currentLocation, currentOrganization) => ({\n id: `menu_item_${snakeCase(child.name)}`,\n title: child.name,\n isDivider: child.type === 'divider',\n className:\n child.name === currentLocation || child.name === currentOrganization\n ? 'mobile-active'\n : '',\n href: child.url || '#',\n preventHref: true,\n onClick: child.onClick || noop,\n});\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Layout/LayoutSelectors.js","import { getValue } from '../../common/SessionStorage';\n\nexport const getIsNavbarCollapsed = () =>\n !!getValue(`[\"navCollapsed\",\"pinnedPath\"]`)?.navCollapsed;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Layout/LayoutSessionStorage.js","import React, { useState } from 'react';\nimport PropTypes from 'prop-types';\n\nimport { EyeIcon } from '@patternfly/react-icons';\nimport { OverlayTrigger, Tooltip, MessageDialog } from 'patternfly-react';\nimport { translate as __ } from '../../../../common/I18n';\n\nimport './ImpersonateIcon.scss';\n\nconst ImpersonateIcon = props => {\n const [showModal, setShowModal] = useState(false);\n\n const toggleModal = () => setShowModal(!showModal);\n\n return (\n \n \n {__(\n 'You are impersonating another user, click to stop the impersonation'\n )}\n \n }\n placement=\"bottom\"\n trigger={['hover', 'focus']}\n rootClose={false}\n >\n \n \n \n \n \n props.stopImpersonating(props.stopImpersonationUrl)\n }\n secondaryAction={toggleModal}\n primaryActionButtonContent={__('Confirm')}\n secondaryActionButtonContent={__('Cancel')}\n title={__('Confirm Action')}\n primaryContent={__(\n 'You are about to stop impersonating other user. Are you sure?'\n )}\n />\n \n );\n};\n\nImpersonateIcon.propTypes = {\n stopImpersonationUrl: PropTypes.string.isRequired,\n stopImpersonating: PropTypes.func.isRequired,\n};\n\nexport default ImpersonateIcon;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Layout/components/ImpersonateIcon/ImpersonateIcon.js","import { API } from '../../../../redux/API';\nimport { foremanUrl } from '../../../../../foreman_tools';\n\nimport { addToast } from '../../../../redux/actions/toasts';\n\nexport const stopImpersonating = url => async dispatch => {\n try {\n const { data } = await API.delete(url);\n window.location.href = foremanUrl('/users');\n return dispatch(\n addToast({\n type: data.type,\n message: data.message,\n })\n );\n } catch (error) {\n return dispatch(\n addToast({\n type: 'error',\n message: 'Failed to stop impersonation',\n })\n );\n }\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Layout/components/ImpersonateIcon/ImpersonateIconActions.js","import { connect } from 'react-redux';\nimport { bindActionCreators } from 'redux';\nimport ImpersonateIcon from './ImpersonateIcon';\n\nimport * as ImpersonateIconActions from './ImpersonateIconActions';\n\nconst mapDispatchToProps = dispatch =>\n bindActionCreators(ImpersonateIconActions, dispatch);\n\nexport default connect(null, mapDispatchToProps)(ImpersonateIcon);\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Layout/components/ImpersonateIcon/index.js","import React, { useEffect } from 'react';\nimport PropTypes from 'prop-types';\n\nconst LayoutContainer = ({ isCollapsed, children }) => {\n const classes = 'react-container container-fluid nav-pf-persistent-secondary';\n\n useEffect(() => {\n if (isCollapsed) document.body.classList.add('collapsed-nav');\n else document.body.classList.remove('collapsed-nav');\n }, [isCollapsed]);\n return {children}
;\n};\n\nLayoutContainer.propTypes = {\n isCollapsed: PropTypes.bool.isRequired,\n children: PropTypes.node,\n};\n\nLayoutContainer.defaultProps = {\n children: null,\n};\n\nexport default LayoutContainer;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Layout/components/LayoutContainer.js","import React, { useState, useEffect, useCallback } from 'react';\nimport PropTypes from 'prop-types';\nimport {\n ContextSelector,\n ContextSelectorItem,\n ContextSelectorFooter,\n Button,\n} from '@patternfly/react-core';\nimport { CheckIcon } from '@patternfly/react-icons';\nimport { foremanUrl } from '../../../../common/helpers';\nimport { translate as __ } from '../../../../common/I18n';\nimport './TaxonomyDropdown.scss';\n\nconst TaxonomyDropdown = ({ taxonomyType, currentTaxonomy, taxonomies }) => {\n const id = `${taxonomyType}-dropdown`;\n const anyTaxonomyURL = foremanUrl(`/${taxonomyType}s/clear`);\n const manageTaxonomyURL = foremanUrl(`/${taxonomyType}s`);\n const anyTaxonomyText =\n taxonomyType === 'organization'\n ? __('Any Organization')\n : __('Any Location');\n\n const [searchValue, setSearchValue] = useState('');\n const [isOpen, setIsOpen] = useState(false);\n const [filteredItems, setFilteredItems] = useState(taxonomies);\n\n const onSearchButtonClick = useCallback(() => {\n const filtered =\n searchValue === ''\n ? taxonomies\n : taxonomies.filter(item =>\n item.title.toLowerCase().includes(searchValue.toLowerCase())\n );\n setFilteredItems(filtered || []);\n }, [searchValue, taxonomies]);\n\n useEffect(() => {\n onSearchButtonClick();\n }, [searchValue, onSearchButtonClick]);\n\n const onToggle = (event, newIsOpen) => {\n setIsOpen(newIsOpen);\n };\n const onSelect = () => {\n setIsOpen(!isOpen);\n };\n const onSearchInputChange = (value, event) => {\n setSearchValue(event.target.value);\n };\n\n const selectedIcon = ;\n\n const anyTaxonomyItem = (\n {\n window.location.assign(anyTaxonomyURL);\n }}\n isDisabled={!currentTaxonomy}\n >\n {!currentTaxonomy && selectedIcon}\n {anyTaxonomyText}\n \n );\n const footer = (\n \n \n \n );\n return (\n \n {anyTaxonomyItem}\n {filteredItems.map(({ title, href }, i) => (\n {\n if (href) {\n window.location.assign(href);\n }\n }}\n isDisabled={title === currentTaxonomy}\n >\n {title === currentTaxonomy && selectedIcon}\n {title}\n \n ))}\n \n );\n};\n\nTaxonomyDropdown.propTypes = {\n taxonomyType: PropTypes.oneOf(['organization', 'location']).isRequired,\n currentTaxonomy: PropTypes.string,\n taxonomies: PropTypes.arrayOf(\n PropTypes.shape({\n id: PropTypes.number.isRequired,\n title: PropTypes.string,\n href: PropTypes.string.isRequired,\n })\n ).isRequired,\n};\n\nTaxonomyDropdown.defaultProps = {\n currentTaxonomy: undefined,\n};\n\nexport default TaxonomyDropdown;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Layout/components/TaxonomySwitcher/TaxonomyDropdown.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { ToolbarItem, Spinner } from '@patternfly/react-core';\nimport {\n useForemanOrganization,\n useForemanLocation,\n} from '../../../../Root/Context/ForemanContext';\n\nimport { locationPropType, organizationPropType } from '../../LayoutHelper';\nimport TaxonomyDropdown from './TaxonomyDropdown';\n\nconst TaxonomySwitcher = ({ organizations, locations, isLoading }) => {\n const currentLocation = useForemanLocation()?.title;\n const currentOrganization = useForemanOrganization()?.title;\n return (\n \n \n \n \n \n \n \n {isLoading && }\n \n );\n};\nTaxonomySwitcher.propTypes = {\n isLoading: PropTypes.bool,\n organizations: PropTypes.arrayOf(organizationPropType).isRequired,\n locations: PropTypes.arrayOf(locationPropType).isRequired,\n};\n\nTaxonomySwitcher.defaultProps = {\n isLoading: false,\n};\n\nexport default TaxonomySwitcher;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Layout/components/TaxonomySwitcher/TaxonomySwitcher.js","import React from 'react';\nimport {\n PageHeaderTools,\n PageHeaderToolsGroup,\n PageHeaderToolsItem,\n} from '@patternfly/react-core';\nimport TaxonomySwitcher from '../TaxonomySwitcher/TaxonomySwitcher';\nimport UserDropdowns from './UserDropdowns';\nimport NotificationContainer from '../../../notifications';\nimport ImpersonateIcon from '../ImpersonateIcon';\nimport {\n layoutPropTypes,\n layoutDefaultProps,\n dataPropType,\n} from '../../LayoutHelper';\nimport InstanceTitleViewer from './InstanceTitleViewer';\nimport './HeaderToolbar.scss';\n\nconst HeaderToolbar = ({\n locations,\n orgs,\n notification_url: notificationUrl,\n user,\n stop_impersonation_url: stopImpersonationUrl,\n instance_title: instanceTitle,\n isLoading,\n changeActiveMenu,\n}) => (\n \n \n \n \n \n \n \n \n \n \n \n {user.impersonated_by && (\n \n \n \n )}\n\n \n \n \n \n \n);\nHeaderToolbar.propTypes = {\n ...dataPropType,\n isLoading: layoutPropTypes.isLoading,\n changeActiveMenu: layoutPropTypes.changeActiveMenu,\n};\n\nHeaderToolbar.defaultProps = {\n isLoading: layoutDefaultProps.isLoading,\n changeActiveMenu: layoutDefaultProps.changeActiveMenu,\n};\nexport default HeaderToolbar;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Layout/components/Toolbar/HeaderToolbar.js","import React from 'react';\nimport { Icon, OverlayTrigger, Tooltip } from 'patternfly-react';\nimport PropTypes from 'prop-types';\n\nconst InstanceTitleViewer = ({ title }) => {\n if (!title) {\n return null;\n }\n\n const tooltip = {title};\n\n return (\n \n \n \n );\n};\n\nInstanceTitleViewer.propTypes = {\n /** Title to display */\n title: PropTypes.string,\n};\nInstanceTitleViewer.defaultProps = {\n title: '',\n};\nexport default InstanceTitleViewer;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Layout/components/Toolbar/InstanceTitleViewer.js","import React, { useState } from 'react';\nimport PropTypes from 'prop-types';\nimport {\n Dropdown,\n DropdownToggle,\n DropdownItem,\n DropdownSeparator,\n} from '@patternfly/react-core';\nimport { UserAltIcon } from '@patternfly/react-icons';\n\nimport { userPropType } from '../../LayoutHelper';\nimport { translate as __ } from '../../../../common/I18n';\n\nconst UserDropdowns = ({\n user,\n changeActiveMenu,\n notificationUrl,\n instanceTitle,\n ...props\n}) => {\n const [userDropdownOpen, setUserDropdownOpen] = useState(false);\n\n const onDropdownToggle = newUserDropdownOpen => {\n setUserDropdownOpen(newUserDropdownOpen);\n };\n const onDropdownSelect = () => {\n setUserDropdownOpen(userDropdownOpen);\n };\n const userInfo = user.current_user;\n\n const userDropdownItems = user.user_dropdown[0].children.map((item, i) =>\n item.type === 'divider' ? (\n \n ) : (\n {\n changeActiveMenu({ title: 'User' });\n }}\n {...item.html_options}\n >\n {__(item.name)}\n \n )\n );\n\n return (\n userInfo && (\n \n \n {userInfo.name}\n \n }\n dropdownItems={userDropdownItems}\n {...props}\n />\n )\n );\n};\n\nUserDropdowns.propTypes = {\n /** Additional element css classes */\n className: PropTypes.string,\n /** User Data Array */\n user: userPropType,\n /** notification URL */\n notificationUrl: PropTypes.string,\n /** changeActiveMenu Func */\n changeActiveMenu: PropTypes.func,\n instanceTitle: PropTypes.string,\n};\nUserDropdowns.defaultProps = {\n className: '',\n user: {},\n notificationUrl: '',\n changeActiveMenu: null,\n instanceTitle: '',\n};\nexport default UserDropdowns;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Layout/components/Toolbar/UserDropdowns.js","import React, { useEffect } from 'react';\nimport { useSelector, useDispatch } from 'react-redux';\nimport { useHistory } from 'react-router-dom';\n\nimport {\n initializeLayout,\n changeActiveMenu,\n collapseLayoutMenus,\n expandLayoutMenus,\n} from './LayoutActions';\nimport reducer from './LayoutReducer';\nimport {\n patternflyMenuItemsSelector,\n selectActiveMenu,\n selectIsLoading,\n selectIsCollapsed,\n} from './LayoutSelectors';\nimport { combineMenuItems, getActiveMenuItem } from './LayoutHelper';\nimport { getIsNavbarCollapsed } from './LayoutSessionStorage';\nimport {\n useForemanOrganization,\n useForemanLocation,\n} from '../../Root/Context/ForemanContext';\n\nimport Layout from './Layout';\n\nconst ConnectedLayout = ({ children, data }) => {\n const dispatch = useDispatch();\n\n const currentLocation = useForemanLocation()?.title;\n const currentOrganization = useForemanOrganization()?.title;\n useEffect(() => {\n dispatch(\n initializeLayout({\n items: combineMenuItems(data),\n activeMenu: getActiveMenuItem(data.menu).title,\n isCollapsed: getIsNavbarCollapsed(),\n organization: data.orgs.current_org,\n location: data.locations.current_location,\n })\n );\n }, [data, dispatch]);\n\n const { push: navigate } = useHistory();\n const items = useSelector(state =>\n patternflyMenuItemsSelector(state, currentLocation, currentOrganization)\n );\n const isLoading = useSelector(state => selectIsLoading(state));\n const isCollapsed = useSelector(state => selectIsCollapsed(state));\n const activeMenu = useSelector(state => selectActiveMenu(state));\n\n return (\n dispatch(changeActiveMenu(menu))}\n collapseLayoutMenus={() => dispatch(collapseLayoutMenus())}\n expandLayoutMenus={() => dispatch(expandLayoutMenus())}\n >\n {children}\n \n );\n};\n\n// export prop-types\nexport const { propTypes, defaultProps } = Layout;\n\nConnectedLayout.propTypes = {\n children: propTypes.children,\n data: propTypes.data,\n};\n\nConnectedLayout.defaultProps = {\n children: defaultProps.children,\n data: defaultProps.data,\n};\n\n// export reducers\nexport const reducers = { layout: reducer };\n\n// export connected component\nexport default ConnectedLayout;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Layout/index.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { LoginPage as PFLoginPage } from 'patternfly-react';\nimport { translate as __ } from '../../common/I18n';\nimport { adjustAlerts, defaultFormProps } from './helpers';\nimport './LoginPage.scss';\n\nconst LoginPage = ({\n alerts,\n backgroundUrl,\n caption,\n logoSrc,\n token,\n version,\n}) => {\n const { modifiedAlerts, submitErrors } = adjustAlerts(alerts);\n return (\n \n );\n};\n\nLoginPage.propTypes = {\n alerts: PropTypes.shape({\n success: PropTypes.string,\n warning: PropTypes.string,\n error: PropTypes.string,\n }),\n backgroundUrl: PropTypes.string,\n caption: PropTypes.string,\n logoSrc: PropTypes.string,\n token: PropTypes.string.isRequired,\n version: PropTypes.string,\n};\n\nLoginPage.defaultProps = {\n alerts: null,\n backgroundUrl: null,\n caption: null,\n logoSrc: null,\n version: null,\n};\n\nexport default LoginPage;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/LoginPage/LoginPage.js","import { translate as __ } from '../../common/I18n';\n\nexport const adjustAlerts = alerts => {\n const submitErrors = [];\n const modifiedAlerts = [];\n\n alerts &&\n Object.keys(alerts).forEach(alertType => {\n const alertMessage = alerts[alertType];\n if (alertType === 'error') {\n submitErrors.push(alertMessage);\n } else if (alertMessage) {\n modifiedAlerts.push({\n type: alertType,\n message: alertMessage,\n show: true,\n });\n }\n });\n\n return {\n modifiedAlerts,\n submitErrors,\n };\n};\n\nexport const defaultFormProps = {\n attributes: {\n action: '/users/login',\n method: 'post',\n },\n validate: true,\n topErrorOnly: true,\n usernameField: {\n id: 'login_login',\n attributes: {\n name: 'login[login]',\n autoFocus: true,\n },\n type: 'text',\n placeholder: __('Username'),\n },\n passwordField: {\n id: 'login_password',\n attributes: {\n name: 'login[password]',\n },\n type: 'password',\n placeholder: __('Password'),\n },\n submitText: __('Log In'),\n submitButtonAttributes: {\n id: 'login_submit_btn',\n name: 'commit',\n },\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/LoginPage/helpers.js","export { default } from './LoginPage';\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/LoginPage/index.js","import RCInputNumber from 'rc-input-number';\nimport React, { useEffect, useState } from 'react';\nimport PropTypes from 'prop-types';\nimport { sprintf, translate as __ } from '../../common/I18n';\nimport { MB_FORMAT, MEGABYTES } from './constants';\nimport '../common/forms/NumericInput.scss';\nimport { noop } from '../../common/helpers';\n\nconst MemoryAllocationInput = ({\n value,\n onChange,\n maxValue,\n minValue,\n recommendedMaxValue,\n name,\n id,\n disabled,\n setError,\n setWarning,\n}) => {\n const [valueMB, setValueMB] = useState(value / MEGABYTES);\n\n useEffect(() => {\n const valueBytes = valueMB * MEGABYTES;\n if (maxValue && valueBytes > maxValue) {\n setWarning(null);\n setError(\n sprintf(\n __('Specified value is higher than maximum value %s'),\n `${maxValue / MEGABYTES} ${MB_FORMAT}`\n )\n );\n } else if (recommendedMaxValue && valueBytes > recommendedMaxValue) {\n setError(null);\n setWarning(\n sprintf(\n __('Specified value is higher than recommended maximum %s'),\n `${recommendedMaxValue / MEGABYTES} ${MB_FORMAT}`\n )\n );\n } else {\n setWarning(null);\n }\n }, [valueMB, recommendedMaxValue, maxValue, setError, setWarning]);\n\n const handleChange = v => {\n if (v === valueMB + 1) {\n v = valueMB * 2;\n } else if (v === valueMB - 1) {\n v = Math.floor(valueMB / 2);\n }\n setValueMB(v);\n onChange(v * MEGABYTES);\n };\n\n return (\n <>\n `${v} ${MB_FORMAT}`}\n parser={str => str.replace(/\\D/g, '')}\n onChange={handleChange}\n disabled={disabled}\n min={minValue && minValue / MEGABYTES}\n step={1}\n precision={0}\n name=\"\"\n prefixCls=\"foreman-numeric-input\"\n />\n \n >\n );\n};\n\nMemoryAllocationInput.propTypes = {\n /** Set the default value of the memory allocation input */\n value: PropTypes.number,\n /** Set the recommended max value of the numeric input */\n recommendedMaxValue: PropTypes.number,\n /** Set the max value of the numeric input */\n maxValue: PropTypes.number,\n /** Set the min value of the numeric input */\n minValue: PropTypes.number,\n /** Set the onChange function of the numeric input */\n onChange: PropTypes.func,\n /** Set the name of the input holding the value in bytes */\n name: PropTypes.string,\n /** Set the id of the numeric input */\n id: PropTypes.string,\n /** Set whether the numeric input will be disabled or not */\n disabled: PropTypes.bool,\n /** Component passes the validation error to this function */\n setError: PropTypes.func,\n /** Component passes the validation warning to this function */\n setWarning: PropTypes.func,\n};\n\nMemoryAllocationInput.defaultProps = {\n value: 2048 * MEGABYTES,\n onChange: noop,\n recommendedMaxValue: null,\n maxValue: null,\n minValue: 1,\n name: '',\n id: '',\n disabled: false,\n setError: noop,\n setWarning: noop,\n};\n\nexport default MemoryAllocationInput;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/MemoryAllocationInput/MemoryAllocationInput.js","export const MB_FORMAT = 'MB';\n\nexport const MEGABYTES = 1048576;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/MemoryAllocationInput/constants.js","import MemoryAllocationInput from './MemoryAllocationInput';\n\nexport default MemoryAllocationInput;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/MemoryAllocationInput/index.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { Table } from '../common/table';\nimport createModelsTableSchema from './ModelsTableSchema';\n\nconst ModelsTable = ({\n getTableItems,\n sortBy,\n sortOrder,\n results,\n onDeleteClick,\n id,\n}) => (\n \n);\n\nModelsTable.propTypes = {\n results: PropTypes.array.isRequired,\n getTableItems: PropTypes.func.isRequired,\n onDeleteClick: PropTypes.func.isRequired,\n sortBy: PropTypes.string,\n sortOrder: PropTypes.string,\n id: PropTypes.string,\n};\n\nModelsTable.defaultProps = {\n sortBy: '',\n sortOrder: '',\n id: undefined,\n};\n\nexport default ModelsTable;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/ModelsTable/ModelsTable.js","import { translate as __ } from '../../common/I18n';\nimport {\n column,\n sortableColumn,\n headerFormatterWithProps,\n cellFormatterWithProps,\n nameCellFormatter,\n hostsCountCellFormatter,\n deleteActionCellFormatter,\n cellFormatter,\n} from '../common/table';\n\nconst sortControllerFactory = (apiCall, sortBy, sortOrder) => ({\n apply: (by, order) => {\n apiCall({ sort: { by, order } });\n },\n property: sortBy,\n order: sortOrder,\n});\n\n/**\n * Generate a table schema to the Hardware Models page.\n * @param {Function} apiCall a Redux async action that fetches and stores table data in Redux.\n * See ModelsTableActions.\n * @param {String} by by which column the table is sorted.\n * If none then set it to undefined/null.\n * @param {String} order in what order to sort a column. If none then set it to undefined/null.\n * Otherwise, 'ASC' for ascending and 'DESC' for descending\n * @return {Array}\n */\nconst createModelsTableSchema = (apiCall, by, order, onDeleteClick) => {\n const sortController = sortControllerFactory(apiCall, by, order);\n\n return [\n sortableColumn('name', __('Name'), 4, sortController, [\n nameCellFormatter('models'),\n ]),\n sortableColumn('vendorClass', __('Vendor Class'), 3, sortController),\n sortableColumn('hardwareModel', __('Hardware Model'), 3, sortController),\n column(\n 'hostsCount',\n __('Hosts'),\n [headerFormatterWithProps],\n [hostsCountCellFormatter('model'), cellFormatterWithProps],\n { className: 'col-md-1' },\n { align: 'right' }\n ),\n column(\n 'actions',\n __('Actions'),\n [headerFormatterWithProps],\n [deleteActionCellFormatter(onDeleteClick), cellFormatter]\n ),\n ];\n};\n\nexport default createModelsTableSchema;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/ModelsTable/ModelsTableSchema.js","import React from 'react';\nimport PropTypes from 'prop-types';\n\nimport ModelsTable from './ModelsTable';\nimport { MODEL_DELETE_MODAL_ID } from '../../routes/Models/constants';\nimport { useForemanModal } from '../ForemanModal/ForemanModalHooks';\n\nconst WrappedModelsTable = props => {\n const { setModalOpen } = useForemanModal({ id: MODEL_DELETE_MODAL_ID });\n const { setToDelete, ...rest } = props;\n\n const onDeleteClick = rowData => {\n setToDelete(rowData);\n setModalOpen();\n };\n\n return ;\n};\n\nWrappedModelsTable.propTypes = {\n setToDelete: PropTypes.func.isRequired,\n};\n\nexport default WrappedModelsTable;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/ModelsTable/index.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { isEmpty } from 'lodash';\nimport { Paginator } from 'patternfly-react';\nimport { translate as __ } from '../../common/I18n';\nimport { usePaginationOptions } from './PaginationHooks';\nimport {\n getURIpage,\n getURIperPage,\n changeQuery,\n} from '../../common/urlHelpers';\nimport { useForemanSettings } from '../../Root/Context/ForemanContext';\nimport './pagination.scss';\n\nconst Pagination = props => {\n const {\n data,\n pagination,\n onPageSet,\n onPerPageSelect,\n dropdownButtonId,\n disableNext,\n disablePrev,\n ...otherProps\n } = props;\n\n const { perPage } = useForemanSettings();\n const perPageOptions = usePaginationOptions();\n const urlPage = getURIpage();\n const urlPerPage = getURIperPage() || null;\n const className = isEmpty(data.classNames)\n ? 'col-md-12'\n : `col-md-12 ${data.classNames.pagination_classes}`;\n\n const pageOpts = {\n page: urlPage,\n perPage: urlPerPage || perPage,\n perPageOptions,\n ...pagination,\n };\n\n const messages = {\n firstPage: __('First Page'),\n previousPage: __('Previous Page'),\n currentPage: __('Current Page'),\n nextPage: __('Next Page'),\n lastPage: __('Last Page'),\n perPage: __('per page'),\n of: __('of'),\n };\n\n return (\n \n );\n};\n\nPagination.propTypes = {\n data: PropTypes.shape({\n viewType: PropTypes.string,\n itemCount: PropTypes.number,\n classNames: PropTypes.shape({\n pagination_classes: PropTypes.string,\n }),\n }).isRequired,\n onPageSet: PropTypes.func,\n onPerPageSelect: PropTypes.func,\n dropdownButtonId: PropTypes.string,\n disableNext: PropTypes.bool,\n disablePrev: PropTypes.bool,\n pagination: PropTypes.shape({\n page: PropTypes.number,\n perPageOptions: PropTypes.arrayOf(PropTypes.number),\n }),\n};\n\nPagination.defaultProps = {\n onPageSet: page => changeQuery({ page }),\n onPerPageSelect: perPage => changeQuery({ page: 1, per_page: perPage }),\n dropdownButtonId: 'pagination-row-dropdown',\n pagination: null,\n disableNext: false,\n disablePrev: false,\n};\n\nexport default Pagination;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Pagination/Pagination.js","import { getURIperPage } from '../../common/urlHelpers';\nimport { useForemanSettings } from '../../Root/Context/ForemanContext';\n\nexport const usePaginationOptions = () => {\n const perPageOptions = new Set([5, 10, 15, 25, 50]);\n const { perPage } = useForemanSettings();\n const URIPerPage = getURIperPage();\n\n perPageOptions.add(perPage);\n if (URIPerPage) perPageOptions.add(URIPerPage);\n return [...perPageOptions].sort((a, b) => a - b);\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Pagination/PaginationHooks.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { Paginator } from 'patternfly-react';\nimport Pagination from './Pagination';\n\nconst PaginationWrapper = props => {\n const {\n onPageSet,\n onPerPageSelect,\n onChange,\n pagination,\n dropdownButtonId,\n itemCount,\n viewType,\n ...otherProps\n } = props;\n\n const onPageSetUpdate = page => {\n update({ page });\n onPageSet(page);\n };\n\n const onPerPageSelectUpdate = perPage => {\n update({ perPage, page: 1 });\n onPerPageSelect(perPage);\n };\n\n const update = changes => {\n const newPagination = { ...pagination, ...changes };\n\n onChange({\n page: newPagination.page,\n perPage: newPagination.perPage,\n });\n };\n\n return (\n \n );\n};\n\nPaginationWrapper.defaultProps = {\n onChange: () => {},\n viewType: 'list',\n ...Paginator.defaultProps,\n pagination: {},\n};\n\ndelete PaginationWrapper.defaultProps.messages;\n\nPaginationWrapper.propTypes = {\n ...Paginator.propTypes,\n /** page and per-page selection callback */\n onChange: PropTypes.func,\n /** view type */\n viewType: PropTypes.string,\n /** pagination */\n pagination: PropTypes.shape({\n /** the current page */\n page: PropTypes.number,\n /** the current per page setting */\n perPage: PropTypes.number,\n /** per page options */\n perPageOptions: PropTypes.arrayOf(PropTypes.number),\n }),\n};\n\nexport default PaginationWrapper;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Pagination/PaginationWrapper.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport ReactPasswordStrength from 'react-password-strength';\nimport { translate as __ } from '../../../react_app/common/I18n';\nimport CommonForm from '../common/forms/CommonForm';\nimport { noop } from '../../common/helpers';\n\nimport './PasswordStrength.scss';\n\nconst PasswordStrength = ({\n updatePassword,\n updatePasswordConfirmation,\n doesPasswordsMatch,\n passwordPresent,\n data: { className, id, name, verify, error, userInputIds, required },\n}) => {\n const userInputs =\n userInputIds && userInputIds.length > 0\n ? userInputIds.map(input => document.getElementById(input).value)\n : [];\n\n return (\n \n \n updatePassword(password)}\n minLength={6}\n minScore={2}\n userInputs={userInputs}\n tooShortWord={__('Too short')}\n scoreWords={[\n __('Weak'),\n __('Medium'),\n __('Normal'),\n __('Strong'),\n __('Very strong'),\n ]}\n inputProps={{ name, id, className, autoComplete: 'new-password' }}\n />\n \n {verify && (\n \n updatePasswordConfirmation(target.value)}\n className=\"form-control\"\n />\n \n )}\n
\n );\n};\n\nPasswordStrength.propTypes = {\n updatePassword: PropTypes.func,\n updatePasswordConfirmation: PropTypes.func,\n doesPasswordsMatch: PropTypes.bool,\n passwordPresent: PropTypes.bool,\n data: PropTypes.shape({\n className: PropTypes.string,\n id: PropTypes.string,\n name: PropTypes.string,\n error: PropTypes.node,\n userInputIds: PropTypes.arrayOf(PropTypes.string),\n required: PropTypes.bool,\n verify: PropTypes.shape({\n name: PropTypes.string.isRequired,\n error: PropTypes.node,\n }),\n }).isRequired,\n};\n\nPasswordStrength.defaultProps = {\n updatePassword: noop,\n updatePasswordConfirmation: noop,\n doesPasswordsMatch: false,\n passwordPresent: false,\n};\n\nexport default PasswordStrength;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/PasswordStrength/PasswordStrength.js","import {\n PASSWORD_STRENGTH_PASSWORD_CHANGED,\n PASSWORD_STRENGTH_PASSWORD_CONFIRMATION_CHANGED,\n} from './PasswordStrengthConstants';\n\nexport const updatePassword = password => ({\n type: PASSWORD_STRENGTH_PASSWORD_CHANGED,\n payload: password,\n});\n\nexport const updatePasswordConfirmation = password => ({\n type: PASSWORD_STRENGTH_PASSWORD_CONFIRMATION_CHANGED,\n payload: password,\n});\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/PasswordStrength/PasswordStrengthActions.js","export const PASSWORD_STRENGTH_PASSWORD_CHANGED =\n 'PASSWORD_STRENGTH_PASSWORD_CHANGED';\nexport const PASSWORD_STRENGTH_PASSWORD_CONFIRMATION_CHANGED =\n 'PASSWORD_STRENGTH_PASSWORD_CONFIRMATION_CHANGED';\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/PasswordStrength/PasswordStrengthConstants.js","import Immutable from 'seamless-immutable';\n\nimport {\n PASSWORD_STRENGTH_PASSWORD_CHANGED,\n PASSWORD_STRENGTH_PASSWORD_CONFIRMATION_CHANGED,\n} from './PasswordStrengthConstants';\n\nconst initialState = Immutable({\n password: '',\n passwordConfirmation: '',\n});\n\nexport default (state = initialState, action) => {\n const { payload } = action;\n\n switch (action.type) {\n case PASSWORD_STRENGTH_PASSWORD_CHANGED:\n return state.set('password', payload);\n\n case PASSWORD_STRENGTH_PASSWORD_CONFIRMATION_CHANGED:\n return state.set('passwordConfirmation', payload);\n\n default:\n return state;\n }\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/PasswordStrength/PasswordStrengthReducer.js","export const doesPasswordsMatch = ({ password, passwordConfirmation }) =>\n !passwordConfirmation || password === passwordConfirmation;\n\nexport const passwordPresent = passwordStrength =>\n passwordStrength && !!passwordStrength.password;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/PasswordStrength/PasswordStrengthSelectors.js","import { bindActionCreators } from 'redux';\nimport { connect } from 'react-redux';\n\nimport * as actions from './PasswordStrengthActions';\nimport {\n doesPasswordsMatch,\n passwordPresent,\n} from './PasswordStrengthSelectors';\nimport reducer from './PasswordStrengthReducer';\n\nimport PasswordStrength from './PasswordStrength';\n\n// map state to props\nconst mapStateToProps = ({ passwordStrength }) => ({\n doesPasswordsMatch: doesPasswordsMatch(passwordStrength),\n passwordPresent: passwordPresent(passwordStrength),\n});\n\n// map action dispatchers to props\nconst mapDispatchToProps = dispatch => bindActionCreators(actions, dispatch);\n\n// export reducers\nexport const reducers = { passwordStrength: reducer };\n\n// export connected component\nexport default connect(mapStateToProps, mapDispatchToProps)(PasswordStrength);\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/PasswordStrength/index.js","import React from 'react';\nimport { isEmpty } from 'lodash';\nimport PropTypes from 'prop-types';\nimport AutoComplete from '../AutoComplete';\nimport Bookmarks from '../Bookmarks';\nimport { changeQuery } from '../../common/urlHelpers';\nimport './search-bar.scss';\n\nconst SearchBar = props => {\n const {\n data: { autocomplete, controller, bookmarks },\n searchQuery,\n onSearch,\n initialQuery,\n onBookmarkClick,\n } = props;\n\n return (\n \n
onSearch(searchQuery)}\n searchQuery={initialQuery || autocomplete.searchQuery || ''}\n useKeyShortcuts={autocomplete.useKeyShortcuts}\n url={autocomplete.url}\n controller={controller}\n />\n \n
onSearch(searchQuery)} />\n {!isEmpty(bookmarks) && (\n \n )}\n \n \n );\n};\n\nSearchBar.propTypes = {\n searchQuery: PropTypes.string,\n initialQuery: PropTypes.string,\n onSearch: PropTypes.func,\n onBookmarkClick: PropTypes.func,\n data: PropTypes.shape({\n autocomplete: PropTypes.shape({\n results: PropTypes.array,\n searchQuery: PropTypes.string,\n url: PropTypes.string,\n useKeyShortcuts: PropTypes.bool,\n id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,\n }),\n controller: PropTypes.string,\n bookmarks: PropTypes.shape({ ...Bookmarks.propTypes }),\n }),\n};\n\nSearchBar.defaultProps = {\n searchQuery: '',\n initialQuery: '',\n onSearch: searchQuery => changeQuery({ search: searchQuery.trim(), page: 1 }),\n onBookmarkClick: searchQuery =>\n changeQuery({ search: searchQuery.trim(), page: 1 }),\n data: {\n autocomplete: {\n results: [],\n searchQuery: null,\n url: null,\n useKeyShortcuts: true,\n },\n controller: null,\n bookmarks: {},\n },\n};\n\nexport default SearchBar;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/SearchBar/SearchBar.js","import { connect } from 'react-redux';\nimport SearchBar from './SearchBar';\nimport { selectAutocompleteSearchQuery } from '../AutoComplete/AutoCompleteSelectors';\n\nconst mapStateToProps = (\n state,\n {\n data: {\n autocomplete: { id },\n },\n }\n) => ({\n searchQuery: selectAutocompleteSearchQuery(state, id),\n});\n\nexport default connect(mapStateToProps)(SearchBar);\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/SearchBar/index.js","import {\n LOAD_SETTING_RECORDS,\n SET_EDITING_SETTING,\n} from './SettingRecordsConstants';\n\nexport const loadSettingRecords = settings => async dispatch =>\n dispatch({ type: LOAD_SETTING_RECORDS, payload: settings });\n\nexport const setSettingEditing = setting => async dispatch =>\n dispatch({ type: SET_EDITING_SETTING, payload: { setting } });\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/SettingRecords/SettingRecordsActions.js","export const LOAD_SETTING_RECORDS = 'LOAD_SETTING_RECORDS';\nexport const SETTINGS_FORM_SUBMITTED_SUCCESS =\n 'SETTINGS_FORM_SUBMITTED_SUCCESS';\nexport const SET_EDITING_SETTING = 'SET_EDITING_SETTING';\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/SettingRecords/SettingRecordsConstants.js","import Immutable from 'seamless-immutable';\n\nimport {\n LOAD_SETTING_RECORDS,\n SET_EDITING_SETTING,\n SETTINGS_FORM_SUBMITTED_SUCCESS,\n} from './SettingRecordsConstants';\n\nexport const initialState = Immutable({\n settings: {},\n editing: null,\n});\n\nconst reducer = (state = initialState, { type, payload, response }) => {\n switch (type) {\n case LOAD_SETTING_RECORDS:\n return state.set('settings', payload);\n case SETTINGS_FORM_SUBMITTED_SUCCESS: {\n const categorized = state.settings[response.category];\n const updatedCategory = categorized.map(item =>\n item.name === response.id ? { ...item, value: response.value } : item\n );\n return state.setIn(['settings', response.category], updatedCategory);\n }\n case SET_EDITING_SETTING:\n return state.set('editing', payload.setting);\n default:\n return state;\n }\n};\n\nexport default reducer;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/SettingRecords/SettingRecordsReducer.js","import { createSelector } from 'reselect';\nimport { propsToCamelCase } from '../../common/helpers';\n\nconst selectSettingRecords = state => state.settingRecords;\nexport const selectSettings = state => selectSettingRecords(state).settings;\n\nexport const selectSettingsByCategory = category =>\n createSelector(selectSettings, settings =>\n settings[category].map(propsToCamelCase)\n );\n\nexport const selectSettingById = (id, category) =>\n createSelector(selectSettingsByCategory(category), settings =>\n settings.find(setting => setting.id === id)\n );\n\nexport const selectSettingEditing = state =>\n selectSettingRecords(state).editing;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/SettingRecords/SettingRecordsSelectors.js","import React, { useEffect } from 'react';\nimport { useDispatch } from 'react-redux';\nimport PropTypes from 'prop-types';\n\nimport { loadSettingRecords } from './SettingRecordsActions';\nimport reducer from './SettingRecordsReducer';\n\nexport const reducers = {\n settingRecords: reducer,\n};\n\nconst SettingRecords = ({ settings }) => {\n const dispatch = useDispatch();\n useEffect(() => {\n dispatch(loadSettingRecords(settings));\n });\n\n return ;\n};\n\nSettingRecords.propTypes = {\n settings: PropTypes.object,\n};\n\nSettingRecords.defaultProps = {\n settings: {},\n};\n\nexport default SettingRecords;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/SettingRecords/index.js","import React from 'react';\nimport PropTypes from 'prop-types';\n\nimport ForemanModal from '../ForemanModal';\nimport { sprintf, translate as __ } from '../../common/I18n';\n\nimport SettingForm from './components/SettingForm';\n\nimport { SETTING_UPDATE_MODAL } from './SettingUpdateModalConstants';\n\nconst SettingUpdateModal = ({ setting, setModalClosed }) => (\n \n \n \n
\n \n);\n\nSettingUpdateModal.propTypes = {\n setting: PropTypes.object.isRequired,\n setModalClosed: PropTypes.func.isRequired,\n};\n\nexport default SettingUpdateModal;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/SettingUpdateModal/SettingUpdateModal.js","export const SETTING_UPDATE_MODAL = 'settingUpdateModal';\nexport const SETTING_UPDATE_PATH = '/api/settings/:id';\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/SettingUpdateModal/SettingUpdateModalConstants.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { Field as FormikField } from 'formik';\nimport ForemanForm from '../../../common/forms/ForemanForm';\nimport SettingValueField from '../SettingValueField';\nimport { SETTING_UPDATE_PATH } from '../../SettingUpdateModalConstants';\n\nimport { translate as __ } from '../../../../common/I18n';\n\nconst SettingForm = ({\n setting,\n initialValues,\n setModalClosed,\n submitForm,\n}) => {\n const handleSubmit = (values, actions) => {\n let submitValues = { setting: values };\n\n if (setting && setting.settingsType === 'array') {\n const splitValue = values.value === '' ? [] : values.value.split(',');\n submitValues = { setting: { value: splitValue } };\n }\n\n return submitForm({\n url: SETTING_UPDATE_PATH.replace(':id', setting.id),\n values: submitValues,\n item: 'Settings',\n message: __('Setting was successfully updated.'),\n method: 'put',\n successCallback: setModalClosed,\n actions,\n });\n };\n\n return (\n \n \n \n );\n};\n\nSettingForm.propTypes = {\n setting: PropTypes.object.isRequired,\n initialValues: PropTypes.object.isRequired,\n setModalClosed: PropTypes.func.isRequired,\n submitForm: PropTypes.func.isRequired,\n};\n\nexport default SettingForm;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/SettingUpdateModal/components/SettingForm/SettingForm.js","import React from 'react';\nimport PropTypes from 'prop-types';\n\nimport { useDispatch } from 'react-redux';\nimport { submitForm } from '../../../../redux/actions/common/forms';\nimport SettingForm from './SettingForm';\n\nconst initialValue = setting => {\n if (setting.encrypted) {\n return '';\n }\n\n return setting.value === null ? '' : setting.value;\n};\n\nconst WrappedSettingForm = props => {\n const dispatch = useDispatch();\n\n return (\n dispatch(submitForm(...args))}\n initialValues={{\n value: initialValue(props.setting),\n }}\n {...props}\n />\n );\n};\n\nWrappedSettingForm.propTypes = {\n setting: PropTypes.object.isRequired,\n};\n\nexport default WrappedSettingForm;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/SettingUpdateModal/components/SettingForm/index.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { Col, HelpBlock, FormGroup, FormControl } from 'patternfly-react';\nimport classNames from 'classnames';\n\nimport { translate as __ } from '../../../common/I18n';\nimport { arraySelection } from '../../SettingsTable/SettingsTableHelpers';\nimport { renderOptions } from '../../common/forms/SelectHelpers';\n\nconst SettingValueField = ({ setting, form, field }) => {\n const { selectValues } = setting;\n const cssClasses = classNames({ 'masked-input': setting.encrypted });\n\n let inputField = ;\n\n const error = form.errors && form.errors.value;\n\n if (selectValues) {\n inputField = (\n \n {renderOptions(arraySelection(setting) || selectValues)}\n \n );\n }\n\n if (setting.settingsType === 'boolean') {\n inputField = (\n \n \n \n \n );\n }\n\n if (setting.settingsType === 'array') {\n inputField = (\n \n );\n }\n\n const helpBlock = (\n \n {error}\n \n );\n\n const encryptedHelp = (\n \n {__(\n 'This setting is encrypted. Empty input field is displayed instead of the setting value.'\n )}\n \n );\n\n return (\n \n \n \n {inputField}\n {setting.encrypted && encryptedHelp}\n \n {error && helpBlock}\n \n \n );\n};\n\nSettingValueField.propTypes = {\n setting: PropTypes.object.isRequired,\n form: PropTypes.object.isRequired,\n field: PropTypes.object.isRequired,\n};\n\nexport default SettingValueField;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/SettingUpdateModal/components/SettingValueField.js","import React from 'react';\nimport { useSelector } from 'react-redux';\n\nimport useSettingModal from './useSettingModal';\n\nimport SettingUpdateModal from './SettingUpdateModal';\n\nimport { selectSettingEditing } from '../SettingRecords/SettingRecordsSelectors';\n\nconst WrappedSettingUpdateModal = props => {\n const setting = useSelector(state => selectSettingEditing(state)) || {};\n\n const { setModalClosed } = useSettingModal();\n\n return (\n \n );\n};\n\nexport default WrappedSettingUpdateModal;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/SettingUpdateModal/index.js","import { useForemanModal } from '../ForemanModal/ForemanModalHooks';\n\nimport { SETTING_UPDATE_MODAL } from './SettingUpdateModalConstants';\n\nconst useSettingModal = () => useForemanModal({ id: SETTING_UPDATE_MODAL });\n\nexport default useSettingModal;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/SettingUpdateModal/useSettingModal.js","import React from 'react';\nimport PropTypes from 'prop-types';\n\nimport { Table } from '../common/table';\n\nimport createSettingsTableSchema from './SettingsTableSchema';\n\nconst SettingsTable = ({ settings, onEditClick }) => (\n \n);\n\nSettingsTable.propTypes = {\n settings: PropTypes.array.isRequired,\n onEditClick: PropTypes.func.isRequired,\n};\n\nexport default SettingsTable;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/SettingsTable/SettingsTable.js","import React from 'react';\n\nimport { withTooltip } from './SettingsTableHelpers';\n\nimport SettingName from './components/SettingName';\nimport SettingCell from './components/SettingCell';\n\nexport const settingNameCellFormatter = (value, { rowData }) => {\n const SettingNameWithTooltip = withTooltip(SettingName);\n\n return (\n \n );\n};\n\nexport const settingValueCellFormatter = onEditClick => (\n value,\n { rowData }\n) => ;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/SettingsTable/SettingsTableFormatters.js","import React from 'react';\n\nimport { Tooltip, OverlayTrigger } from 'patternfly-react';\n\nimport { translate as __ } from '../../common/I18n';\n\nimport { deepPropsToCamelCase } from '../../common/helpers';\n\nexport const withTooltip = Component => componentProps => {\n const { tooltipId, tooltipText, ...rest } = componentProps;\n\n return (\n {tooltipText}}\n trigger={['hover', 'focus']}\n placement=\"top\"\n rootClose={false}\n >\n \n \n \n \n );\n};\n\nexport const arraySelection = setting => {\n const { selectValues } = setting;\n\n if (!Array.isArray(selectValues)) {\n return null;\n }\n return deepPropsToCamelCase(selectValues);\n};\n\nconst formatEncryptedDefault = setting => {\n if (setting.encrypted && setting.default) {\n return setting.default\n .split('')\n .map(item => '\\u2219')\n .join('');\n }\n\n return null;\n};\n\nconst formatHashSelectionDefault = setting =>\n formatHashSelection('default', setting);\nconst formatHashSelectionValue = setting =>\n formatHashSelection('value', setting);\n\nconst formatHashSelection = (attr, setting) => {\n const { selectValues } = setting;\n\n const val = setting[attr];\n\n if (!selectValues || !selectValues[val]) {\n return null;\n }\n\n return selectValues[val];\n};\n\nconst formatBooleanDefault = setting => formatBoolean('default', setting);\nconst formatBooleanValue = setting => formatBoolean('value', setting);\n\nconst formatBoolean = (attr, setting) => {\n if (setting.settingsType === 'boolean') {\n if (setting[attr]) {\n return __('Yes');\n }\n return __('No');\n }\n return null;\n};\n\nconst formatArrayValue = setting => formatArray('value', setting);\nconst formatArrayDefault = setting => formatArray('default', setting);\n\nconst formatArray = (attr, setting) => {\n if (setting.settingsType === 'array') {\n return `[${\n setting[attr] && setting[attr].length > 0 ? setting.value.join(', ') : ''\n }]`;\n }\n return null;\n};\n\nconst formatTextValue = setting => setting.value;\nconst formatTextDefault = setting => setting.default;\n\nconst formatEmpty = (attr, emptyValue, setting) => {\n if (!setting[attr]) {\n return emptyValue;\n }\n return null;\n};\n\nconst formatEmptyDefault = setting =>\n formatEmpty('default', __('Not set'), setting);\nconst formatEmptyValue = setting => formatEmpty('value', __('Empty'), setting);\n\nconst formatArraySelectionDefault = setting =>\n formatArraySelection('default', setting);\nconst formatArraySelectionValue = setting =>\n formatArraySelection('value', setting);\n\nconst formatArraySelection = (attr, setting) => {\n const selectValues = arraySelection(setting);\n\n if (!setting[attr] || !selectValues) {\n return null;\n }\n\n // https://github.com/eslint/eslint/issues/12117\n let group;\n for (group of selectValues) {\n if (group.value === setting[attr]) {\n return group.label;\n }\n\n if (group.children) {\n const child = group.children.find(item => item.value === setting[attr]);\n if (child) {\n return child.label;\n }\n }\n }\n return null;\n};\n\nconst reduceFormats = formatters => setting =>\n formatters.reduce((memo, formatter) => {\n if (memo) {\n return memo;\n }\n return formatter.call(this, setting);\n }, null);\n\nexport const valueToString = reduceFormats([\n formatBooleanValue,\n formatArrayValue,\n formatArraySelectionValue,\n formatHashSelectionValue,\n formatEmptyValue,\n formatTextValue,\n]);\n\nexport const defaultToString = reduceFormats([\n formatEncryptedDefault,\n formatBooleanDefault,\n formatArrayDefault,\n formatArraySelectionDefault,\n formatHashSelectionDefault,\n formatEmptyDefault,\n formatTextDefault,\n]);\n\nexport const hasDefault = setting => {\n switch (setting.settingsType) {\n case 'boolean':\n case 'integer': {\n return true;\n }\n case 'array':\n case 'hash':\n case 'string': {\n return !!setting.default && setting.default.length !== 0;\n }\n default: {\n return !!setting.default;\n }\n }\n};\n\nexport const inStrong = markup => {markup};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/SettingsTable/SettingsTableHelpers.js","import {\n column,\n headerFormatterWithProps,\n cellFormatter,\n cellFormatterWithProps,\n} from '../common/table';\nimport { translate as __ } from '../../common/I18n';\n\nimport {\n settingNameCellFormatter,\n settingValueCellFormatter,\n} from './SettingsTableFormatters';\n\nconst createSettingsTableSchema = onEditClick => [\n column(\n 'fullName',\n __('Name'),\n [headerFormatterWithProps],\n [settingNameCellFormatter, cellFormatterWithProps],\n { className: 'col-md-2' }\n ),\n column(\n 'value',\n __('Value'),\n [headerFormatterWithProps],\n [settingValueCellFormatter(onEditClick), cellFormatterWithProps],\n { className: 'col-md-3' }\n ),\n column(\n 'description',\n __('Description'),\n [headerFormatterWithProps],\n [cellFormatter]\n ),\n];\n\nexport default createSettingsTableSchema;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/SettingsTable/SettingsTableSchema.js","import React from 'react';\nimport PropTypes from 'prop-types';\n\nimport { sprintf, translate as __ } from '../../../common/I18n';\n\nimport { withTooltip, defaultToString } from '../SettingsTableHelpers';\n\nimport SettingCellInner from './SettingCellInner';\n\nimport './SettingCell.scss';\n\nconst SettingCell = ({ setting, onEditClick }) => {\n const fieldProps = { setting, tooltipId: setting.name, onEditClick };\n const displayName = setting.fullName || setting.name;\n const defaultStr = defaultToString(setting);\n\n if (setting.readonly) {\n fieldProps.tooltipText = sprintf(\n __(\n 'This setting is defined in the configuration file %s and is read-only.'\n ),\n setting.configFile\n );\n } else {\n fieldProps.tooltipText = `${displayName} (Default: ${defaultStr})`;\n fieldProps.className = 'editable';\n }\n\n const Component = withTooltip(SettingCellInner);\n return ;\n};\n\nSettingCell.propTypes = {\n setting: PropTypes.object.isRequired,\n onEditClick: PropTypes.func,\n};\n\nSettingCell.defaultProps = {\n onEditClick: () => {},\n};\n\nexport default SettingCell;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/SettingsTable/components/SettingCell.js","import React from 'react';\nimport classNames from 'classnames';\nimport PropTypes from 'prop-types';\nimport EllipsisWithTooltip from 'react-ellipsis-with-tooltip';\n\nimport { valueToString, hasDefault, inStrong } from '../SettingsTableHelpers';\n\nconst SettingCellInner = props => {\n const { setting, className, onEditClick, ...rest } = props;\n\n const cssClasses = classNames(className, {\n 'editable-empty': !setting.value && setting.settingsType !== 'boolean',\n 'masked-input': setting.encrypted,\n });\n\n const field = (\n onEditClick(setting)}>\n {valueToString(setting)}\n \n );\n\n const value =\n setting.value !== setting.default && hasDefault(setting)\n ? inStrong(field)\n : field;\n return {value};\n};\n\nSettingCellInner.propTypes = {\n setting: PropTypes.object.isRequired,\n className: PropTypes.string,\n onEditClick: PropTypes.func.isRequired,\n};\n\nSettingCellInner.defaultProps = {\n className: '',\n};\n\nexport default SettingCellInner;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/SettingsTable/components/SettingCellInner.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { translate as __ } from '../../../common/I18n';\n\nconst SettingName = ({ setting }) => (\n <>{setting.fullName ? __(setting.fullName) : setting.name}>\n);\n\nSettingName.propTypes = {\n setting: PropTypes.object.isRequired,\n};\n\nexport default SettingName;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/SettingsTable/components/SettingName.js","import React from 'react';\nimport { useSelector, useDispatch } from 'react-redux';\nimport PropTypes from 'prop-types';\n\nimport { selectSettingsByCategory } from '../SettingRecords/SettingRecordsSelectors';\n\nimport { setSettingEditing } from '../SettingRecords/SettingRecordsActions';\n\nimport SettingsTable from './SettingsTable';\n\nimport useSettingModal from '../SettingUpdateModal/useSettingModal';\n\nconst WrappedSettingsTable = props => {\n const settings = useSelector(state =>\n selectSettingsByCategory(props.category)(state)\n );\n\n const dispatch = useDispatch();\n const { setModalOpen } = useSettingModal();\n\n const onEditClick = async setting => {\n await dispatch(setSettingEditing(setting));\n setModalOpen();\n };\n\n return ;\n};\n\nWrappedSettingsTable.propTypes = {\n category: PropTypes.string.isRequired,\n};\n\nexport default WrappedSettingsTable;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/SettingsTable/index.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { Alert, Button } from 'patternfly-react';\n\nimport { noop } from '../../common/helpers';\nimport { sprintf, translate as __ } from '../../common/I18n';\nimport AlertBody from '../common/Alert/AlertBody';\n\nconst pollingMsg = `\n Report %s is now being generated, the download will start once it's done.\n You can come to this page later to get the results. The result is available for 24 hours.\n`;\nconst doneMsg = `\n Generating of the report %s has been completed.\n Download should start automatically.\n In case it does not, please use the download button below.\n`;\n\nconst getAlert = (type, msg) => (\n \n \n \n);\n\nclass TemplateGenerator extends React.Component {\n getError() {\n const { generatingError, generatingErrorMessages } = this.props;\n const errors =\n generatingErrorMessages &&\n generatingErrorMessages.map(e => e.message).join('\\n');\n\n return errors || generatingError;\n }\n\n renderAlert() {\n const {\n polling,\n data: { templateName },\n } = this.props;\n const error = this.getError();\n if (polling) return getAlert('info', sprintf(pollingMsg, templateName));\n if (error) return getAlert('error', error);\n return getAlert('success', sprintf(doneMsg, templateName));\n }\n\n render() {\n const { polling, dataUrl, pollReportData, generatingError } = this.props;\n\n if (!dataUrl && !polling) return null;\n\n return (\n \n {this.renderAlert()}\n {!polling && !generatingError && (\n \n )}\n \n );\n }\n}\n\nTemplateGenerator.propTypes = {\n data: PropTypes.shape({\n templateName: PropTypes.string.isRequired,\n }).isRequired,\n polling: PropTypes.bool,\n pollReportData: PropTypes.func,\n dataUrl: PropTypes.string,\n generatingError: PropTypes.string,\n generatingErrorMessages: PropTypes.arrayOf(\n PropTypes.shape({ message: PropTypes.string })\n ),\n};\n\nTemplateGenerator.defaultProps = {\n polling: false,\n pollReportData: noop,\n dataUrl: null,\n generatingError: null,\n generatingErrorMessages: null,\n};\n\nexport default TemplateGenerator;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/TemplateGenerator/TemplateGenerator.js","/* eslint-disable promise/prefer-await-to-then */\nimport { saveAs } from 'file-saver';\nimport { API } from '../../redux/API';\n\nimport {\n TEMPLATE_GENERATE_REQUEST,\n TEMPLATE_GENERATE_POLLING,\n TEMPLATE_GENERATE_SUCCESS,\n TEMPLATE_GENERATE_FAILURE,\n} from './TemplateGeneratorConstants';\n\nconst pollingInterval = 3000;\n\nexport const generateTemplate = (url, templateInputData) => dispatch => {\n dispatch({\n type: TEMPLATE_GENERATE_REQUEST,\n payload: { ...templateInputData },\n });\n return API.post(url, templateInputData)\n .then(({ data }) => {\n dispatch(pollReportData(data.data_url));\n })\n .catch(error =>\n dispatch({\n type: TEMPLATE_GENERATE_FAILURE,\n payload: { error, item: templateInputData },\n })\n );\n};\n\nconst _downloadFile = response => {\n const blob = new Blob([response.data], {\n type: response.headers['content-type'],\n });\n const filename = response.headers['content-disposition'].match(\n /filename=\"(.*)\"/\n );\n saveAs(blob, (filename && filename[1]) || 'report.txt');\n};\n\nconst _getErrors = errorResponse => {\n if (!errorResponse || !errorResponse.data) return null;\n if (errorResponse.status === 422) return errorResponse.data.errors;\n if (errorResponse.data.error) return [errorResponse.data.error]; // most of >500\n return [errorResponse.data];\n};\n\nexport const pollReportData = pollUrl => dispatch => {\n dispatch({ type: TEMPLATE_GENERATE_POLLING, payload: { url: pollUrl } });\n\n return API.get(pollUrl, { responseType: 'blob' })\n .then(response => {\n if (response.status === 200) {\n dispatch({ type: TEMPLATE_GENERATE_SUCCESS, payload: {} });\n _downloadFile(response);\n } else if (pollingInterval) {\n setTimeout(() => dispatch(pollReportData(pollUrl)), pollingInterval);\n }\n })\n .catch(error => {\n dispatch({\n type: TEMPLATE_GENERATE_FAILURE,\n payload: { error, messages: _getErrors(error.response) },\n });\n });\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/TemplateGenerator/TemplateGeneratorActions.js","export const TEMPLATE_GENERATE_REQUEST = 'TEMPLATE_GENERATE_REQUEST';\nexport const TEMPLATE_GENERATE_POLLING = 'TEMPLATE_GENERATE_POLLING';\nexport const TEMPLATE_GENERATE_SUCCESS = 'TEMPLATE_GENERATE_SUCCESS';\nexport const TEMPLATE_GENERATE_FAILURE = 'TEMPLATE_GENERATE_FAILURE';\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/TemplateGenerator/TemplateGeneratorConstants.js","import Immutable from 'seamless-immutable';\n\nimport {\n TEMPLATE_GENERATE_REQUEST,\n TEMPLATE_GENERATE_POLLING,\n TEMPLATE_GENERATE_SUCCESS,\n TEMPLATE_GENERATE_FAILURE,\n} from './TemplateGeneratorConstants';\n\nconst initialState = Immutable({\n scheduleInProgress: false,\n polling: false,\n dataUrl: null,\n});\n\nexport default (state = initialState, { type, payload }) => {\n switch (type) {\n case TEMPLATE_GENERATE_REQUEST:\n return state.set('scheduleInProgress', true);\n case TEMPLATE_GENERATE_POLLING:\n return state.merge({\n scheduleInProgress: false,\n dataUrl: payload.url,\n polling: true,\n });\n case TEMPLATE_GENERATE_FAILURE:\n return state.merge({\n scheduleInProgress: false,\n polling: false,\n generatingError: payload.error.message,\n generatingErrorMessages: payload.messages,\n });\n case TEMPLATE_GENERATE_SUCCESS:\n return state.merge({\n scheduleInProgress: false,\n polling: false,\n });\n default:\n return state;\n }\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/TemplateGenerator/TemplateGeneratorReducer.js","const selectTemplates = state => state.templates;\n\nconst selectGeneratingPropsFromTemplates = ({\n polling,\n dataUrl,\n generatingError,\n generatingErrorMessages,\n}) => ({\n polling,\n dataUrl,\n generatingError,\n generatingErrorMessages,\n});\n\nexport const selectGeneratingProps = state =>\n selectGeneratingPropsFromTemplates(selectTemplates(state));\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/TemplateGenerator/TemplateGeneratorSelectors.js","import { bindActionCreators } from 'redux';\nimport { connect } from 'react-redux';\n\nimport { selectGeneratingProps } from './TemplateGeneratorSelectors';\nimport reducer from './TemplateGeneratorReducer';\nimport * as templateActions from './TemplateGeneratorActions';\nimport TemplateGenerator from './TemplateGenerator';\n\nexport const actions = templateActions;\n\n// export reducers\nexport const reducers = { templates: reducer };\n\n// map state to props\nconst mapStateToProps = state => selectGeneratingProps(state);\n\n// map action dispatchers to props\nconst mapDispatchToProps = dispatch => bindActionCreators(actions, dispatch);\n\n// export connected component\nexport default connect(mapStateToProps, mapDispatchToProps)(TemplateGenerator);\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/TemplateGenerator/index.js","import React, { useEffect } from 'react';\nimport {\n ToastNotificationList,\n ToastNotification,\n TimedToastNotification,\n Alert,\n} from 'patternfly-react';\nimport PropTypes from 'prop-types';\nimport { noop } from '../../common/helpers';\nimport AlertBody from '../common/Alert/AlertBody';\n\nconst toastType = type => {\n if (Alert.ALERT_TYPES.includes(type)) return type;\n const message = `Toast notification type '${type}' is invalid. Please use one of the following types: ${Alert.ALERT_TYPES}`;\n switch (type) {\n case 'alert':\n // eslint-disable-next-line no-console\n console.warn(message);\n return 'warning';\n case 'notice':\n // eslint-disable-next-line no-console\n console.warn(message);\n return 'info';\n default:\n // eslint-disable-next-line no-console\n console.error(message);\n return 'info';\n }\n};\n\nconst ToastsList = ({ messages, deleteToast, addToast, railsMessages }) => {\n useEffect(() => {\n railsMessages.forEach(({ message, type, key }) => {\n addToast({ message, type, key });\n });\n }, [addToast, railsMessages]);\n\n const toastsList = Object.entries(messages)\n .map(([key, message]) => ({ key, ...message }))\n .map(({ key, link, message, sticky = false, ...toastProps }) => {\n const ToastComponent = sticky\n ? ToastNotification\n : TimedToastNotification;\n return (\n deleteToast(key)}\n {...toastProps}\n type={toastType(toastProps.type)}\n >\n \n \n );\n });\n return (\n toastsList.length > 0 && (\n {toastsList}\n )\n );\n};\n\nToastsList.propTypes = {\n messages: PropTypes.object.isRequired,\n deleteToast: PropTypes.func,\n addToast: PropTypes.func,\n railsMessages: PropTypes.array,\n};\n\nToastsList.defaultProps = {\n deleteToast: noop,\n addToast: noop,\n railsMessages: [],\n};\n\nexport default ToastsList;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/ToastsList/ToastList.js","import { connect } from 'react-redux';\nimport * as ToastActions from '../../redux/actions/toasts';\nimport ToastsList from './ToastList';\n\nconst mapStateToProps = state => ({\n messages: state.toasts.messages,\n});\n\nexport default connect(mapStateToProps, ToastActions)(ToastsList);\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/ToastsList/index.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport AlertLink from './AlertLink';\n\nconst AlertBody = ({ link, title, message, children }) => (\n \n {link && }\n\n {title && {title}}\n\n {message}\n\n {children}\n \n);\n\nAlertBody.propTypes = {\n message: PropTypes.node,\n link: PropTypes.shape(AlertLink.propTypes),\n title: PropTypes.string,\n children: PropTypes.node,\n};\n\nAlertBody.defaultProps = {\n message: undefined,\n children: undefined,\n link: undefined,\n title: undefined,\n};\n\nexport default AlertBody;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/Alert/AlertBody.js","import React from 'react';\nimport PropTypes from 'prop-types';\n\nconst AlertLink = ({ children, ...props }) => (\n \n);\n\nAlertLink.propTypes = {\n children: PropTypes.string.isRequired,\n href: PropTypes.string,\n onClick: PropTypes.func,\n};\n\nAlertLink.defaultProps = {\n href: undefined,\n onClick: undefined,\n};\n\nexport default AlertLink;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/Alert/AlertLink.js","import React, { useState } from 'react';\nimport PropTypes from 'prop-types';\nimport { Button, OverlayTrigger, Tooltip } from 'patternfly-react';\nimport UUID from 'uuid/v1';\nimport { translate as __ } from '../../../common/I18n';\nimport './clipboard-copy.scss';\n\nconst ClipboardCopy = ({\n text: defaultText,\n successMessage,\n buttonText,\n textareaProps,\n buttonProps,\n}) => {\n const [text, setText] = useState(defaultText);\n\n return (\n \n
\n );\n};\n\nClipboardCopy.propTypes = {\n text: PropTypes.string.isRequired,\n buttonText: PropTypes.string,\n successMessage: PropTypes.string,\n textareaProps: PropTypes.object,\n buttonProps: PropTypes.object,\n};\n\nClipboardCopy.defaultProps = {\n buttonText: __('Copy to clipboard'),\n successMessage: __('Copied!'),\n textareaProps: {},\n buttonProps: {},\n};\n\nexport default ClipboardCopy;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/ClipboardCopy/index.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport componentRegistry from '../../componentRegistry';\n\nconst ComponentWrapper = props => {\n const { component, componentProps } = props.data;\n\n if (component === 'ComponentWrapper') {\n throw new Error('Cannot wrap component wrapper');\n }\n\n const registeredComponent = componentRegistry.getComponent(component);\n\n if (!registeredComponent) {\n throw new Error('Component name is missing!');\n }\n\n const Component = registeredComponent.type;\n\n return ;\n};\n\nComponentWrapper.propTypes = {\n data: PropTypes.shape({\n componentProps: PropTypes.object,\n component: PropTypes.string.isRequired,\n }).isRequired,\n};\n\nexport default ComponentWrapper;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/ComponentWrapper/ComponentWrapper.js","export const YEAR = 'YEAR';\nexport const MONTH = 'MONTH';\nexport const DAY = 'DAY';\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/DateTimePicker/DateComponents/DateConstants.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport classNames from 'classnames';\nimport { addMonths } from './helpers';\nimport MonthView from './MonthView';\nimport YearView from './YearView';\nimport DecadeView from './DecadeView';\nimport { YEAR, DAY, MONTH } from './DateConstants';\n\nclass DateInput extends React.Component {\n state = {\n date: new Date(this.props.date),\n typeOfDateInput: this.props.typeOfDateInput,\n };\n static getDerivedStateFromProps(props, state) {\n if (props.date !== state.date) {\n return {\n date: props.date,\n typeOfDateInput: props.typeOfDateInput,\n };\n }\n return null;\n }\n getPrevMonth = () => {\n const { date } = this.state;\n this.setState({ date: addMonths(date, -1) });\n };\n getNextMonth = () => {\n const { date } = this.state;\n this.setState({ date: addMonths(date, 1) });\n };\n setSelected = day => {\n this.setState({\n date: day,\n });\n this.props.setSelected(day);\n };\n toggleDateView = (type = null) => {\n this.setState({\n typeOfDateInput: type,\n });\n };\n getDateViewByType = type => {\n const { date, locale, weekStartsOn, setSelected } = this.props;\n switch (type) {\n case DAY:\n return (\n \n );\n case YEAR:\n return (\n \n );\n default:\n return (\n \n );\n }\n };\n render() {\n const { className } = this.props;\n const { typeOfDateInput } = this.state;\n return (\n \n {this.getDateViewByType(typeOfDateInput)}\n
\n );\n }\n}\n\nDateInput.propTypes = {\n date: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.string]),\n setSelected: PropTypes.func,\n locale: PropTypes.string,\n weekStartsOn: PropTypes.number,\n className: PropTypes.string,\n typeOfDateInput: PropTypes.string,\n};\n\nDateInput.defaultProps = {\n setSelected: null,\n date: new Date(),\n locale: 'en-US',\n weekStartsOn: 1,\n className: '',\n typeOfDateInput: MONTH,\n};\nexport default DateInput;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/DateTimePicker/DateComponents/DateInput.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport classNames from 'classnames';\n\nconst Day = ({ day, setSelected, classNamesArray }) => {\n const date = day.getDate();\n return (\n {\n setSelected(day);\n }}\n >\n {date}\n | \n );\n};\n\nDay.propTypes = {\n day: PropTypes.instanceOf(Date).isRequired,\n classNamesArray: PropTypes.object,\n setSelected: PropTypes.func,\n};\n\nDay.defaultProps = {\n setSelected: null,\n classNamesArray: [],\n};\nexport default Day;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/DateTimePicker/DateComponents/Day.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { times } from 'lodash';\nimport { addYears } from './helpers';\nimport { noop } from '../../../../common/helpers';\nimport { DecadeViewHeader } from './DecadeViewHeader';\nimport { DecadeViewTable } from './DecadeViewTable';\nimport { YEAR } from './DateConstants';\n\nclass DecadeView extends React.Component {\n state = {\n date: new Date(this.props.date),\n selectedDate: new Date(this.props.date),\n };\n getYearArray = () => {\n const { date } = this.state;\n date.setFullYear(Math.floor(date.getFullYear() / 10) * 10);\n return times(12, i => addYears(date, i).getFullYear());\n };\n getPrevDecade = () => {\n const { date } = this.state;\n this.setState({ date: addYears(date, -10) });\n };\n getNextDecade = () => {\n const { date } = this.state;\n this.setState({ date: addYears(date, 10) });\n };\n setSelectedYear = year => {\n const { setSelected, toggleDateView } = this.props;\n const { date } = this.state;\n date.setFullYear(year);\n setSelected(date);\n toggleDateView(YEAR);\n };\n\n render() {\n const { date, selectedDate } = this.state;\n const currDecade = Math.floor(date.getFullYear() / 10) * 10;\n const selectedYear = selectedDate.getFullYear();\n const yearArray = this.getYearArray();\n return (\n \n );\n }\n}\n\nDecadeView.propTypes = {\n date: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.string]),\n setSelected: PropTypes.func,\n toggleDateView: PropTypes.func,\n};\n\nDecadeView.defaultProps = {\n setSelected: noop,\n toggleDateView: noop,\n date: new Date(),\n};\nexport default DecadeView;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/DateTimePicker/DateComponents/DecadeView.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { noop } from '../../../../common/helpers';\n\nexport const DecadeViewHeader = ({\n currDecade,\n getPrevDecade,\n getNextDecade,\n}) => (\n \n \n \n \n | \n \n {`${currDecade}-${currDecade + 11}`}\n | \n \n \n | \n
\n \n);\n\nDecadeViewHeader.propTypes = {\n currDecade: PropTypes.number,\n getPrevDecade: PropTypes.func,\n getNextDecade: PropTypes.func,\n};\nDecadeViewHeader.defaultProps = {\n currDecade: 20,\n getPrevDecade: noop,\n getNextDecade: noop,\n};\nexport default DecadeViewHeader;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/DateTimePicker/DateComponents/DecadeViewHeader.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { noop } from '../../../../common/helpers';\n\nexport const DecadeViewTable = ({\n yearArray,\n selectedYear,\n setSelectedYear,\n}) => (\n \n \n \n {yearArray.map(year => (\n setSelectedYear(year)}\n className={`year ${year === selectedYear ? 'active' : ''}`}\n key={year}\n >\n {year}\n \n ))}\n | \n
\n \n);\n\nDecadeViewTable.propTypes = {\n yearArray: PropTypes.array,\n selectedYear: PropTypes.number,\n setSelectedYear: PropTypes.func,\n};\nDecadeViewTable.defaultProps = {\n yearArray: [],\n selectedYear: new Date().getFullYear(),\n setSelectedYear: noop,\n};\n\nexport default DecadeViewTable;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/DateTimePicker/DateComponents/DecadeViewTable.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { Icon } from 'patternfly-react';\nimport { YEAR } from './DateConstants';\nimport { getWeekArray } from './HeaderHelpers';\n\nconst Header = ({\n getNextMonth,\n getPrevMonth,\n toggleDateView,\n weekStartsOn,\n date,\n locale,\n}) => {\n date = new Date(date);\n const month = Intl.DateTimeFormat(locale, {\n month: 'long',\n }).format(date);\n const year = date.getFullYear();\n const daysOfTheWeek = getWeekArray(weekStartsOn);\n return (\n \n \n \n \n | \n toggleDateView(YEAR)}\n >\n {month} {year}\n | \n \n \n | \n
\n \n {daysOfTheWeek.map((day, idx) => (\n \n {day}\n | \n ))}\n
\n \n );\n};\n\nHeader.propTypes = {\n date: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.string]),\n getPrevMonth: PropTypes.func,\n getNextMonth: PropTypes.func,\n toggleDateView: PropTypes.func,\n locale: PropTypes.string,\n weekStartsOn: PropTypes.number,\n};\n\nHeader.defaultProps = {\n date: new Date(),\n getPrevMonth: null,\n getNextMonth: null,\n toggleDateView: null,\n locale: 'en-US',\n weekStartsOn: 1,\n};\nexport default Header;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/DateTimePicker/DateComponents/Header.js","import { times } from 'lodash';\nimport { addDays, getWeekStart } from './helpers';\n\nexport const getWeekArray = (weekStartsOn, locale) => {\n const weekStart = getWeekStart(new Date());\n const dayFormat =\n Intl.DateTimeFormat(locale, { weekday: 'short' }).format(weekStart).length >\n 3\n ? 'narrow'\n : 'short';\n return times(7, i =>\n Intl.DateTimeFormat(locale, { weekday: dayFormat })\n .format(addDays(weekStart, (i + weekStartsOn) % 7))\n .slice(0, 2)\n );\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/DateTimePicker/DateComponents/HeaderHelpers.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { chunk, times } from 'lodash';\n\nimport Day from './Day';\nimport {\n addDays,\n addMonths,\n getMonthStart,\n isEqualDate,\n isWeekend,\n} from './helpers';\nimport Header from './Header';\n\nclass MonthView extends React.Component {\n state = {\n selectedDate: new Date(this.props.date),\n date: new Date(this.props.date),\n };\n\n static getDerivedStateFromProps(props, state) {\n const newDate = new Date(props.date);\n if (newDate !== new Date(state.date)) {\n return {\n selectedDate: newDate,\n };\n }\n return null;\n }\n\n calendarArray = date => {\n const { weekStartsOn } = this.props;\n const monthStart = getMonthStart(new Date(date));\n const offset = monthStart.getDay() - weekStartsOn;\n return chunk(\n times(35, i => addDays(monthStart, i - offset)),\n 7\n );\n };\n\n getPrevMonth = () => {\n const { date } = this.state;\n this.setState({ date: addMonths(date, -1) });\n };\n getNextMonth = () => {\n const { date } = this.state;\n this.setState({ date: addMonths(date, 1) });\n };\n setSelected = day => {\n this.setState({\n selectedDate: day,\n date: day,\n });\n this.props.setSelected(day);\n };\n\n render() {\n const { locale, weekStartsOn, toggleDateView } = this.props;\n const { date, selectedDate } = this.state;\n const calendar = this.calendarArray(date);\n return (\n \n
\n \n \n {calendar.map((el, idx) => (\n \n {el.map(day => (\n \n ))}\n
\n ))}\n \n
\n
\n );\n }\n}\n\nMonthView.propTypes = {\n date: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.string]),\n setSelected: PropTypes.func,\n toggleDateView: PropTypes.func,\n locale: PropTypes.string,\n weekStartsOn: PropTypes.number,\n};\n\nMonthView.defaultProps = {\n setSelected: null,\n toggleDateView: null,\n date: new Date(),\n locale: 'en-US',\n weekStartsOn: 1,\n};\nexport default MonthView;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/DateTimePicker/DateComponents/MonthView.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { translate as __ } from '../../../../common/I18n';\n\nconst TodayButton = ({ setSelected }) => (\n \n \n \n \n \n | \n
\n \n
\n);\n\nTodayButton.propTypes = {\n setSelected: PropTypes.func,\n};\n\nTodayButton.defaultProps = {\n setSelected: null,\n};\nexport default TodayButton;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/DateTimePicker/DateComponents/TodayButton.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { times } from 'lodash';\nimport classNames from 'classnames';\nimport { addMonths, addYears } from './helpers';\nimport { noop } from '../../../../common/helpers';\nimport { MONTH, DAY } from './DateConstants';\n\nclass YearView extends React.Component {\n state = {\n date: new Date(this.props.date),\n selectedDate: new Date(this.props.date),\n };\n getMonthArray = () => {\n const date = new Date('1/1/1');\n return times(12, i =>\n Intl.DateTimeFormat(this.props.locale, { month: 'short' }).format(\n addMonths(date, i)\n )\n );\n };\n getPrevYear = () => {\n const { date } = this.state;\n this.setState({ date: addYears(date, -1) });\n };\n getNextYear = () => {\n const { date } = this.state;\n this.setState({ date: addYears(date, 1) });\n };\n setSelectedMonth = month => {\n const { date } = this.state;\n date.setMonth(month);\n this.props.setSelected(date);\n this.props.toggleDateView(MONTH);\n };\n\n render() {\n const { date, selectedDate } = this.state;\n const [currMonth, currYear] = [date.getMonth(), date.getFullYear()];\n const selectedYear = selectedDate.getFullYear();\n const monthArray = this.getMonthArray();\n return (\n \n
\n \n \n \n \n | \n this.props.toggleDateView(DAY)}\n colSpan=\"5\"\n >\n {currYear}\n | \n \n \n | \n
\n \n \n \n \n {monthArray.map((month, idx) => (\n this.setSelectedMonth(idx)}\n className={classNames('month', {\n active: idx === currMonth && selectedYear === currYear,\n })}\n key={idx}\n >\n {month}\n \n ))}\n | \n
\n \n
\n
\n );\n }\n}\n\nYearView.propTypes = {\n date: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.string]),\n setSelected: PropTypes.func,\n toggleDateView: PropTypes.func,\n locale: PropTypes.string,\n};\n\nYearView.defaultProps = {\n setSelected: noop,\n toggleDateView: noop,\n date: new Date(),\n locale: 'en-US',\n};\nexport default YearView;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/DateTimePicker/DateComponents/YearView.js","export const addDays = (date, days) => {\n const result = new Date(date);\n result.setDate(result.getDate() + days);\n return result;\n};\n\nexport const addMonths = (date, months) => {\n const result = new Date(date);\n result.setMonth(result.getMonth() + months);\n return result;\n};\n\nexport const addYears = (date, years) => {\n const result = new Date(date);\n result.setYear(result.getFullYear() + years);\n return result;\n};\n\nexport const isEqualDate = (date1, date2) =>\n date1.getYear() === date2.getYear() &&\n date1.getMonth() === date2.getMonth() &&\n date1.getDate() === date2.getDate();\n\nexport const isWeekend = date => date.getDay() === 6 || date.getDay() === 5;\n\nexport const getMonthStart = date => {\n date.setDate(1);\n return date;\n};\n\nexport const getWeekStart = date => addDays(date, (7 - date.getDay()) % 7);\n\nexport const helpers = {\n addDays,\n addMonths,\n isEqualDate,\n isWeekend,\n getMonthStart,\n getWeekStart,\n};\n\nexport default helpers;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/DateTimePicker/DateComponents/helpers.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport {\n FormControl,\n InputGroup,\n Icon,\n OverlayTrigger,\n Popover,\n} from 'patternfly-react';\nimport DateInput from './DateComponents/DateInput';\nimport TodayButton from './DateComponents/TodayButton';\nimport { formatDate } from '../../../common/helpers';\nimport './date-time-picker.scss';\n\nclass DatePicker extends React.Component {\n get hasDefaultValue() {\n const { value } = this.props;\n return !!Date.parse(value);\n }\n\n get initialDate() {\n const { value } = this.props;\n return this.hasDefaultValue ? new Date(value) : new Date();\n }\n\n state = {\n value: this.initialDate,\n hiddenValue: !this.hasDefaultValue,\n };\n\n setSelected = date => {\n if (Date.parse(date)) {\n const newDate = new Date(date);\n this.setState({ value: newDate });\n }\n };\n\n render() {\n const { locale, weekStartsOn, name, id, placement, required } = this.props;\n const { value, hiddenValue } = this.state;\n const popover = (\n \n \n \n
\n \n \n \n \n );\n return (\n \n \n this.setSelected(e.target.value)}\n />\n this.setState({ hiddenValue: false })}\n >\n \n \n \n \n {!required && (\n \n \n this.setState({ hiddenValue: true, value: new Date() })\n }\n />\n \n )}\n \n
\n );\n }\n}\n\nDatePicker.propTypes = {\n value: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.string]),\n name: PropTypes.string,\n locale: PropTypes.string,\n weekStartsOn: PropTypes.number,\n id: PropTypes.string,\n placement: OverlayTrigger.propTypes.placement,\n required: PropTypes.bool,\n};\nDatePicker.defaultProps = {\n value: null,\n name: null,\n locale: 'en-US',\n weekStartsOn: 1,\n id: 'date-picker-popover',\n placement: 'top',\n required: false,\n};\nexport default DatePicker;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/DateTimePicker/DatePicker.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport {\n FormControl,\n InputGroup,\n Icon,\n OverlayTrigger,\n Popover,\n} from 'patternfly-react';\nimport DateInput from './DateComponents/DateInput';\nimport TodayButton from './DateComponents/TodayButton';\nimport TimeInput from './TimeComponents/TimeInput';\nimport { MONTH } from './DateComponents/DateConstants';\nimport { noop, formatDateTime } from '../../../common/helpers';\nimport './date-time-picker.scss';\n\nclass DateTimePicker extends React.Component {\n get hasDefaultValue() {\n const { value } = this.props;\n return !!Date.parse(value);\n }\n\n get initialDate() {\n const { value } = this.props;\n return this.hasDefaultValue ? new Date(value) : new Date();\n }\n\n state = {\n value: this.initialDate,\n typeOfDateInput: MONTH,\n isTimeTableOpen: false,\n hiddenValue: !this.hasDefaultValue,\n };\n\n setSelected = date => {\n if (Date.parse(date)) {\n const newDate = new Date(date);\n this.setState({ value: newDate });\n this.props.onChange(newDate);\n }\n this.setState({\n typeOfDateInput: MONTH,\n isTimeTableOpen: false,\n });\n };\n\n clearSelected = () => {\n this.setState({ hiddenValue: true, value: new Date() });\n this.props.onChange(undefined);\n };\n\n render() {\n const {\n locale,\n weekStartsOn,\n inputProps,\n id,\n placement,\n name,\n required,\n } = this.props;\n const { value, typeOfDateInput, isTimeTableOpen, hiddenValue } = this.state;\n const popover = (\n \n \n \n \n
\n \n \n \n \n );\n return (\n \n \n this.setSelected(e.target.value)}\n />\n\n this.setState({ hiddenValue: false })}\n >\n \n \n \n \n {!required && (\n \n \n \n )}\n \n
\n );\n }\n}\n\nDateTimePicker.propTypes = {\n value: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.string]),\n locale: PropTypes.string,\n weekStartsOn: PropTypes.number,\n inputProps: PropTypes.object,\n id: PropTypes.string,\n placement: OverlayTrigger.propTypes.placement,\n name: PropTypes.string,\n required: PropTypes.bool,\n onChange: PropTypes.func,\n};\n\nDateTimePicker.defaultProps = {\n value: null,\n locale: 'en-US',\n weekStartsOn: 1,\n inputProps: {},\n id: 'datetime-picker-popover',\n placement: 'top',\n name: undefined,\n required: false,\n onChange: noop,\n};\nexport default DateTimePicker;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/DateTimePicker/DateTimePicker.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { noop } from '../../../../common/helpers';\nimport { HOUR, MINUTE } from './TimeConstants';\n\nclass PickTimeClock extends React.Component {\n state = {\n ampm: this.props.time.getHours() >= 12 ? 'PM' : 'AM',\n };\n componentDidUpdate = prevProps => {\n const newTime = this.props.time;\n if (prevProps.time !== newTime) {\n this.setAMPM(newTime);\n }\n };\n setAMPM = time => {\n this.setState({ ampm: time.getHours() >= 12 ? 'PM' : 'AM' });\n };\n setTime = (type, amount) => {\n const { time } = this.props;\n if (type === HOUR) {\n time.setHours(time.getHours() + amount);\n } else if (type === MINUTE) {\n time.setMinutes(time.getMinutes() + amount);\n }\n this.props.setSelected(time);\n };\n toggleAMPM = () => {\n const { time } = this.props;\n if (this.state.ampm === 'AM') {\n time.setHours(time.getHours() + 12);\n this.setState({ ampm: 'PM' });\n } else {\n time.setHours(time.getHours() - 12);\n this.setState({ ampm: 'AM' });\n }\n this.props.setSelected(time);\n };\n render() {\n const { time, toggleTimeTable } = this.props;\n const minutes = time.getMinutes();\n const hours = time.getHours() % 12 || 12;\n\n return (\n \n
\n \n \n this.setTime(HOUR, 1)}>\n \n \n \n | \n | \n this.setTime(MINUTE, 1)}>\n \n \n \n | \n | \n
\n \n toggleTimeTable(HOUR)}>\n \n {`${hours}`.padStart(2, '0')}\n \n | \n : | \n toggleTimeTable(MINUTE)}>\n \n {`${minutes}`.padStart(2, '0')}\n \n | \n \n \n | \n
\n \n \n this.setTime(HOUR, -1)}\n >\n \n \n | \n | \n \n this.setTime(MINUTE, -1)}\n >\n \n \n | \n | \n
\n \n
\n
\n );\n }\n}\n\nPickTimeClock.propTypes = {\n time: PropTypes.instanceOf(Date).isRequired,\n setSelected: PropTypes.func,\n toggleTimeTable: PropTypes.func,\n};\nPickTimeClock.defaultProps = {\n setSelected: noop,\n toggleTimeTable: noop,\n};\nexport default PickTimeClock;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/DateTimePicker/TimeComponents/PickTimeClock.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { noop } from '../../../../common/helpers';\nimport { HOUR } from './TimeConstants';\n\nclass PickTimeTable extends React.Component {\n setTime = (newTime, type) => {\n const { time, setSelected, toggleTimeTable } = this.props;\n const hours = time.getHours();\n newTime = parseInt(newTime, 10);\n if (type === 'minute') time.setMinutes(newTime);\n else if (type === 'hour') {\n time.setHours(hours < 12 ? newTime % 12 : (newTime % 12) + 12);\n }\n setSelected(time);\n toggleTimeTable();\n };\n getTimeTable = (array, type) => (\n \n
\n \n {array.map((row, idx) => (\n \n {row.map(hour => (\n this.setTime(hour, type)}\n >\n {hour}\n | \n ))}\n
\n ))}\n \n
\n
\n );\n render() {\n const hoursArray = [\n ['12', '01', '02', '03'],\n ['04', '05', '06', '07'],\n ['08', '09', '10', '11'],\n ];\n const minutesArray = [\n ['00', '05', '10', '15'],\n ['20', '25', '30', '35'],\n ['40', '45', '50', '55'],\n ];\n return this.props.type === HOUR\n ? this.getTimeTable(hoursArray, 'hour')\n : this.getTimeTable(minutesArray, 'minute');\n }\n}\nPickTimeTable.propTypes = {\n time: PropTypes.instanceOf(Date).isRequired,\n setSelected: PropTypes.func,\n toggleTimeTable: PropTypes.func,\n type: PropTypes.string.isRequired,\n};\nPickTimeTable.defaultProps = {\n setSelected: noop,\n toggleTimeTable: noop,\n};\nexport default PickTimeTable;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/DateTimePicker/TimeComponents/PickTimeTable.js","export const MINUTE = 'MINUTE';\nexport const HOUR = 'HOUR';\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/DateTimePicker/TimeComponents/TimeConstants.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport PickTimeTable from './PickTimeTable';\nimport PickTimeClock from './PickTimeClock';\nimport { noop } from '../../../../common/helpers';\nimport { HOUR } from './TimeConstants';\n\nclass TimeInput extends React.Component {\n state = {\n isTimeTableOpen: this.props.isTimeTableOpen,\n typeOfTimeInput: HOUR,\n };\n componentDidUpdate = prevProps => {\n const { time: nextTime, isTimeTableOpen } = this.props;\n if (prevProps.time !== nextTime) {\n this.setIsTimeTableOpen(isTimeTableOpen);\n }\n };\n setIsTimeTableOpen = isTimeTableOpen => {\n this.setState({\n isTimeTableOpen,\n });\n };\n toggleTimeTable = type => {\n this.setState({\n typeOfTimeInput: type,\n isTimeTableOpen: !this.state.isTimeTableOpen,\n });\n };\n render() {\n const { time, setSelected } = this.props;\n const { typeOfTimeInput, isTimeTableOpen } = this.state;\n return (\n \n {isTimeTableOpen ? (\n
\n ) : (\n
\n )}\n
\n );\n }\n}\n\nTimeInput.propTypes = {\n setSelected: PropTypes.func,\n time: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.string]),\n isTimeTableOpen: PropTypes.bool,\n};\nTimeInput.defaultProps = {\n setSelected: noop,\n time: new Date(),\n isTimeTableOpen: false,\n};\nexport default TimeInput;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/DateTimePicker/TimeComponents/TimeInput.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport {\n FormControl,\n InputGroup,\n Icon,\n OverlayTrigger,\n Popover,\n} from 'patternfly-react';\nimport TimeInput from './TimeComponents/TimeInput';\n\nclass TimePicker extends React.Component {\n getDateFromTime = time => {\n if (Date.parse(time)) {\n return new Date(time);\n }\n return new Date(`1/1/1 ${time}`);\n };\n state = {\n value: this.getDateFromTime(this.props.value),\n };\n formatDate = () => {\n const { locale } = this.props;\n const { value } = this.state;\n const options = { hour: 'numeric', minute: 'numeric' };\n return value.toLocaleString(locale, options);\n };\n setSelected = date => {\n if (Date.parse(date)) {\n const newDate = new Date(date);\n this.setState({ value: newDate });\n } else if (Date.parse(`1/1/1 ${date}`)) {\n const newDate = new Date(`1/1/1 ${date}`);\n this.setState({ value: newDate });\n }\n };\n render() {\n const { locale } = this.props;\n const popover = (\n \n \n \n );\n return (\n \n \n \n this.setSelected(e.target.value)}\n />\n \n \n \n \n \n
\n );\n }\n}\n\nTimePicker.propTypes = {\n value: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.string]),\n locale: PropTypes.string,\n};\nTimePicker.defaultProps = {\n value: new Date(),\n locale: 'en-US',\n};\nexport default TimePicker;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/DateTimePicker/TimePicker.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { MenuItem, Icon } from 'patternfly-react';\nimport { newWindowOnClick } from '../../../common/helpers';\nimport { translate as __ } from '../../../../react_app/common/I18n';\n\nconst DocumentationLink = ({ href, children }) => (\n \n);\n\nDocumentationLink.propTypes = {\n href: PropTypes.string.isRequired,\n children: PropTypes.node,\n};\n\nDocumentationLink.defaultProps = {\n children: __('Documentation'),\n};\n\nexport default DocumentationLink;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/DocumentationLink/index.js","import React from 'react';\nimport { useDispatch } from 'react-redux';\nimport { push } from 'connected-react-router';\nimport { Button } from '@patternfly/react-core';\nimport EmptyStatePattern from './EmptyStatePattern';\nimport { defaultEmptyStatePropTypes } from './EmptyStatePropTypes';\n\nconst DefaultEmptyState = props => {\n const {\n icon,\n iconType,\n header,\n description,\n documentation,\n action,\n secondaryActions,\n } = props;\n\n const dispatch = useDispatch();\n const actionButtonClickHandler = ({ url, onClick }) => {\n if (onClick) onClick();\n else if (url) dispatch(push(url));\n };\n\n const ActionButton = action ? (\n \n ) : null;\n\n const SecondaryButton = secondaryActions\n ? secondaryActions.map(({ title, url, onClick }) => (\n \n ))\n : null;\n\n return (\n \n );\n};\n\nDefaultEmptyState.propTypes = defaultEmptyStatePropTypes;\n\nDefaultEmptyState.defaultProps = {\n icon: 'add-circle-o',\n secondaryActions: [],\n iconType: 'pf',\n};\n\nexport default DefaultEmptyState;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/EmptyState/DefaultEmptyState.js","import React from 'react';\nimport { Icon } from 'patternfly-react';\nimport {\n Title,\n EmptyState,\n EmptyStateVariant,\n EmptyStateBody,\n EmptyStateSecondaryActions,\n} from '@patternfly/react-core';\nimport { emptyStatePatternPropTypes } from './EmptyStatePropTypes';\nimport { translate as __ } from '../../../common/I18n';\nimport './EmptyState.scss';\n\nconst EmptyStatePattern = props => {\n const {\n documentation,\n action,\n secondaryActions,\n iconType,\n icon,\n header,\n description,\n } = props;\n\n const DocumentationBlock = () => {\n if (!documentation) {\n return null;\n }\n // The documentation prop can also be a customized node\n if (React.isValidElement(documentation)) {\n return documentation;\n }\n const {\n label = __('For more information please see '), // eslint-disable-line react/prop-types\n buttonLabel = __('documentation'), // eslint-disable-line react/prop-types\n url = '#', // eslint-disable-line react/prop-types\n } = documentation;\n return (\n \n {label}\n \n {buttonLabel}\n \n \n );\n };\n\n return (\n \n \n {/* TODO: Add pf4 icons, Redmine issue: #30865 */}\n \n \n \n {header}\n \n \n {description}
\n \n \n {action}\n \n {secondaryActions}\n \n \n );\n};\n\nEmptyStatePattern.propTypes = emptyStatePatternPropTypes;\n\nEmptyStatePattern.defaultProps = {\n icon: 'add-circle-o',\n secondaryActions: [],\n documentation: null,\n action: null,\n iconType: 'pf',\n};\n\nexport default EmptyStatePattern;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/EmptyState/EmptyStatePattern.js","import PropTypes from 'prop-types';\n\nexport const actionButtonPropTypes = {\n title: PropTypes.node.isRequired,\n url: PropTypes.string,\n onChange: PropTypes.func,\n};\n\nexport const emptyStatePatternPropTypes = {\n icon: PropTypes.string,\n iconType: PropTypes.string,\n header: PropTypes.string.isRequired,\n documentation: PropTypes.oneOfType([\n PropTypes.shape({\n label: PropTypes.string,\n buttonLabel: PropTypes.string,\n url: PropTypes.string.isRequired,\n }),\n PropTypes.node,\n ]),\n description: PropTypes.oneOfType([PropTypes.string, PropTypes.node])\n .isRequired,\n action: PropTypes.node,\n secondaryActions: PropTypes.node,\n};\n\nexport const defaultEmptyStatePropTypes = {\n ...emptyStatePatternPropTypes,\n action: PropTypes.shape(actionButtonPropTypes),\n secondaryActions: PropTypes.arrayOf(PropTypes.shape(actionButtonPropTypes)),\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/EmptyState/EmptyStatePropTypes.js","import EmptyStatePattern from './EmptyStatePattern';\nimport DefaultEmptyState from './DefaultEmptyState';\n\nexport default DefaultEmptyState;\nexport { EmptyStatePattern };\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/EmptyState/index.js","import React from 'react';\nimport PropTypes from 'prop-types';\n\nclass Fill extends React.Component {\n componentDidMount() {\n const {\n children,\n overrideProps,\n registerFillComponent,\n slotId,\n weight,\n id,\n } = this.props;\n\n registerFillComponent(slotId, overrideProps, id, children, weight);\n }\n componentWillUnmount() {\n const { slotId, unregisterFillComponent, id } = this.props;\n\n unregisterFillComponent(slotId, id);\n }\n render() {\n return null;\n }\n}\n\nFill.propTypes = {\n // a component to be injected on a slot\n children: PropTypes.oneOfType([PropTypes.node, PropTypes.object]),\n registerFillComponent: PropTypes.func.isRequired,\n unregisterFillComponent: PropTypes.func.isRequired,\n slotId: PropTypes.string.isRequired,\n // ordering between slot's fills, higher will be rendered first\n weight: PropTypes.number.isRequired,\n // fill's id\n id: PropTypes.string.isRequired,\n // a props object to be injected on the slot's children\n overrideProps: PropTypes.object,\n};\n\nFill.defaultProps = {\n children: undefined,\n overrideProps: undefined,\n};\n\nexport default Fill;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/Fill/Fill.js","import { REGISTER_FILL, REMOVE_FILLED_COMPONENT } from './FillConstants';\nimport { add, remove } from '../../../../services/SlotsRegistry';\n\nexport const registerFillComponent = (\n slotId,\n overrideProps,\n fillId,\n component,\n weight\n) => dispatch => {\n add(slotId, fillId, component, weight, overrideProps);\n dispatch({\n type: REGISTER_FILL,\n payload: { slotId, fillId, weight },\n });\n};\n\nexport const unregisterFillComponent = (slotId, fillId) => dispatch => {\n remove(slotId, fillId);\n dispatch({\n type: REMOVE_FILLED_COMPONENT,\n payload: { slotId },\n });\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/Fill/FillActions.js","export const REGISTER_FILL = 'SLOT_AND_FILL_REGISTER_FILL';\n\nexport const REMOVE_FILLED_COMPONENT = 'SLOT_AND_FILL_REMOVE_FILLED_COMPONENT';\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/Fill/FillConstants.js","import Immutable from 'seamless-immutable';\n\nimport { REGISTER_FILL, REMOVE_FILLED_COMPONENT } from './FillConstants';\n\nconst initialState = Immutable({});\n\nexport default (state = initialState, action) => {\n const { payload } = action;\n\n switch (action.type) {\n case REGISTER_FILL:\n return state.setIn([payload.slotId, payload.fillId], payload.weight);\n\n case REMOVE_FILLED_COMPONENT:\n return state.setIn([payload.slotId, payload.fillId], false);\n default:\n return state;\n }\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/Fill/FillReducer.js","import { registerFillComponent } from '../Fill/FillActions';\nimport store from '../../../redux';\n\nexport const addGlobalFill = (slotId, fillId, component, weight) => {\n store.dispatch(\n registerFillComponent(slotId, undefined, fillId, component, weight)\n );\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/Fill/GlobalFill.js","import { bindActionCreators } from 'redux';\nimport { connect } from 'react-redux';\n\nimport * as actions from './FillActions';\nimport reducer from './FillReducer';\n\nimport Fill from './Fill';\n\n// map action dispatchers to props\nconst mapDispatchToProps = dispatch => bindActionCreators(actions, dispatch);\n\n// export reducers\nexport const reducers = { extendable: reducer };\n\n// export connected component\nexport default connect(null, mapDispatchToProps)(Fill);\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/Fill/index.js","import React from 'react';\nimport PropTypes from 'prop-types';\n\nimport { Popover } from '@patternfly/react-core';\nimport { HelpIcon } from '@patternfly/react-icons';\n\nconst LabelIcon = ({ text }) => (\n \n \n \n);\n\nLabelIcon.propTypes = {\n text: PropTypes.string.isRequired,\n};\n\nexport default LabelIcon;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/LabelIcon/index.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { Spinner } from 'patternfly-react';\nimport { STATUS } from '../../../constants';\nimport MessageBox from '../MessageBox';\nimport './Loader.css';\n\nconst _simpleLoader = spinnerSize => (\n \n \n
\n);\n\nconst Loader = ({ status, children, spinnerSize }) => {\n let content;\n\n switch (status) {\n case STATUS.PENDING: {\n return _simpleLoader(spinnerSize);\n }\n case STATUS.RESOLVED: {\n // eslint-disable-next-line prefer-destructuring\n content = children[0];\n break;\n }\n case STATUS.ERROR: {\n // eslint-disable-next-line prefer-destructuring\n content = children[1];\n break;\n }\n default:\n content = ;\n break;\n }\n\n return {content}
;\n};\n\nLoader.propTypes = {\n children: PropTypes.array,\n status: PropTypes.string,\n spinnerSize: PropTypes.string,\n};\n\nLoader.defaultProps = {\n children: ['', ''],\n status: '',\n spinnerSize: 'lg',\n};\n\nexport default Loader;\n\nexport const simpleLoader = _simpleLoader;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/Loader/index.js","// temporary component\n// will be replaced by patternfly markup when available\n// temporary component\n// will be replaced by patternfly markup when available\nimport React from 'react';\nimport PropTypes from 'prop-types';\nimport './MessageBox.css';\n\nconst MessageBox = ({ msg, icontype }) => (\n \n);\n\nMessageBox.propTypes = {\n icontype: PropTypes.string.isRequired,\n msg: PropTypes.string,\n};\n\nMessageBox.defaultProps = {\n msg: '',\n};\n\nexport default MessageBox;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/MessageBox/index.js","import React from 'react';\nimport { Button } from 'patternfly-react';\nimport { Link } from 'react-router-dom';\nimport PropTypes from 'prop-types';\n\nimport withReactRoutes from '../../../common/withReactRoutes';\nimport { translate as __ } from '../../../common/I18n';\n\nconst RedirectCancelButton = props => (\n \n \n \n);\n\nRedirectCancelButton.propTypes = {\n cancelPath: PropTypes.string,\n};\n\nRedirectCancelButton.defaultProps = {\n cancelPath: undefined,\n};\n\nexport default withReactRoutes(RedirectCancelButton);\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/RedirectCancelButton/RedirectCancelButton.js","export { default } from './RedirectCancelButton';\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/RedirectCancelButton/index.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport Skeleton from 'react-loading-skeleton';\n\nimport { STATUS } from '../../../constants';\nimport { translate as __ } from '../../../../react_app/common/I18n';\n\nconst SkeletonLoader = ({\n status,\n skeletonProps,\n emptyState,\n children,\n errorNode,\n}) => {\n switch (status) {\n case STATUS.PENDING: {\n return ;\n }\n case STATUS.RESOLVED: {\n return children || emptyState;\n }\n case STATUS.ERROR: {\n return errorNode || emptyState;\n }\n default:\n return emptyState;\n }\n};\n\nSkeletonLoader.propTypes = {\n status: PropTypes.string.isRequired,\n skeletonProps: PropTypes.object,\n emptyState: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),\n children: PropTypes.node,\n errorNode: PropTypes.node,\n};\n\nSkeletonLoader.defaultProps = {\n skeletonProps: {},\n emptyState: __('N/A'),\n children: undefined,\n errorNode: undefined,\n};\nexport default SkeletonLoader;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/SkeletonLoader/index.js","import { cloneElement, isValidElement } from 'react';\nimport PropTypes from 'prop-types';\n\nconst Slot = ({ fills, id, multi, children = null, ...props }) => {\n const addProps = object => {\n if (multi && !object.key) {\n // eslint-disable-next-line no-console\n console.warn('Please add a key attribute to multiple fills');\n }\n\n if (isValidElement(object)) {\n return cloneElement(object, { ...props });\n }\n\n if (!children) {\n throw new Error('Slot with override props must have a child');\n }\n\n return cloneElement(children, { ...props, ...object });\n };\n\n if (fills.length) return fills.map(component => addProps(component));\n return children;\n};\n\nSlot.propTypes = {\n fills: PropTypes.array,\n id: PropTypes.string.isRequired,\n multi: PropTypes.bool,\n children: PropTypes.node,\n};\n\nSlot.defaultProps = {\n fills: [],\n multi: false,\n children: undefined,\n};\n\nexport default Slot;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/Slot/Slot.js","import { getSlotComponents } from '../../../../services/SlotsRegistry';\n\nexport const selectComponentByWeight = slotId =>\n getSlotComponents(slotId)\n .sort((a, b) => b.weight - a.weight)\n .map(c => c.component) || {};\n\nexport const selectMaxComponent = slotId => selectComponentByWeight(slotId)[0];\n\nexport const selectFillsAmount = (state, id) => {\n const registerdFills = state.extendable[id];\n return registerdFills ? Object.keys(registerdFills).length : 0;\n};\n\nexport const selectFillsIDs = (state, id) => {\n const registerdFills = state.extendable[id];\n if (registerdFills) {\n const fillIDs = Object.keys(registerdFills);\n return fillIDs.sort((a, b) => registerdFills[b] - registerdFills[a]);\n }\n return null;\n};\n\nexport const selectFillsComponents = (state, props) => {\n const { id, multiple, fillID } = props;\n\n if (selectFillsAmount(state, id)) {\n if (fillID) {\n const slotComponent = getSlotComponents(id);\n const getFill = slotComponent.filter(c => c.id === fillID);\n\n return [getFill[0].component];\n }\n if (multiple) return selectComponentByWeight(id);\n return [selectMaxComponent(id)];\n }\n return [];\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/Slot/SlotSelectors.js","import { connect } from 'react-redux';\nimport { selectFillsComponents } from './SlotSelectors';\nimport Slot from './Slot';\n\n// map state to props\nconst mapStateToProps = (state, ownProps) => ({\n fills: selectFillsComponents(state, {\n id: ownProps.id,\n multiple: ownProps.multi,\n fillID: ownProps.fillID,\n }),\n});\n\n// export connected component\nexport default connect(mapStateToProps)(Slot);\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/Slot/index.js","import React from 'react';\nimport PropTypes from 'prop-types';\n\nconst SubstringWrapper = ({ children, substring, Element }) => {\n const regexString = () => {\n try {\n return new RegExp(`(${substring})`, 'gi');\n } catch (e) {\n return substring;\n }\n };\n const spilttedText = () => {\n const parts = children.split(regexString());\n const wrappedText = [];\n\n for (let i = 0; i < parts.length; i += 2) {\n wrappedText[i] = (\n \n {parts[i]}\n {parts[i + 1] && {parts[i + 1]}}\n \n );\n }\n return wrappedText;\n };\n\n return {spilttedText()};\n};\n\nSubstringWrapper.propTypes = {\n children: PropTypes.string.isRequired,\n substring: PropTypes.string.isRequired,\n Element: PropTypes.node,\n};\n\nSubstringWrapper.defaultProps = {\n Element: 'b',\n};\n\nexport default SubstringWrapper;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/SubstringWrapper/index.js","import {\n INIT,\n UPDATE_OPTIONS,\n UPDATE_SELECTED,\n} from './TypeAheadSelectConstants';\nimport { mapSelected } from './TypeAheadSelectSelectors';\n\nexport const initialUpdate = (options, selected, id) => ({\n type: INIT,\n payload: {\n id,\n options,\n selected,\n },\n});\n\nexport const updateOptions = (options, id) => ({\n type: UPDATE_OPTIONS,\n payload: {\n id,\n options,\n },\n});\n\nexport const updateSelected = (selected, id) => ({\n type: UPDATE_SELECTED,\n payload: {\n id,\n selected: mapSelected(selected),\n },\n});\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/TypeAheadSelect/TypeAheadSelectActions.js","export const INIT = 'TYPEAHEAD_INIT';\nexport const UPDATE_OPTIONS = 'TYPEAHEAD_UPDATE_OPTIONS';\nexport const UPDATE_SELECTED = 'TYPEAHEAD_UPDATE_SELECTED';\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/TypeAheadSelect/TypeAheadSelectConstants.js","import Immutable from 'seamless-immutable';\nimport {\n INIT,\n UPDATE_OPTIONS,\n UPDATE_SELECTED,\n} from './TypeAheadSelectConstants';\n\nconst initialState = Immutable({});\n\nexport default (\n state = initialState,\n { type, payload: { id, options, selected } = {} }\n) => {\n switch (type) {\n case INIT:\n return state.setIn([id], {\n ...state[id],\n options,\n selected,\n });\n case UPDATE_OPTIONS:\n return state.setIn([id], {\n ...state[id],\n options,\n });\n case UPDATE_SELECTED:\n return state.setIn([id], {\n ...state[id],\n selected,\n });\n default:\n return state;\n }\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/TypeAheadSelect/TypeAheadSelectReducer.js","import Immutable from 'seamless-immutable';\n\nexport const mapSelected = selected => selected.map(item => item.label || item);\n\nconst selectTypeAheadSelect = ({ typeAheadSelect }, id) =>\n typeAheadSelect[id] || {};\n\nexport const selectTypeAheadSelectExists = ({ typeAheadSelect }, id) =>\n !!typeAheadSelect[id];\n\nexport const selectOptions = (state, id) => {\n const typeAhead = selectTypeAheadSelect(state, id);\n const options = typeAhead.options || [];\n return Immutable.isImmutable(options) ? options.asMutable() : options;\n};\n\nexport const selectSelected = (state, id) =>\n selectTypeAheadSelect(state, id).selected;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/TypeAheadSelect/TypeAheadSelectSelectors.js","import React, { useEffect } from 'react';\nimport { useSelector, useDispatch } from 'react-redux';\nimport PropTypes from 'prop-types';\nimport { TypeAheadSelect } from 'patternfly-react';\nimport { initialUpdate, updateSelected } from './TypeAheadSelectActions';\nimport {\n selectTypeAheadSelectExists,\n selectOptions,\n selectSelected,\n} from './TypeAheadSelectSelectors';\nimport reducer from './TypeAheadSelectReducer';\n\nconst ConnectedTypeAheadSelect = ({\n id,\n options,\n selected,\n allowNew,\n multiple,\n placeholder,\n defaultInputValue,\n clearButton,\n inputProps,\n}) => {\n const dispatch = useDispatch();\n const exists = useSelector(state => selectTypeAheadSelectExists(state, id));\n\n useEffect(() => {\n if (!exists) {\n dispatch(initialUpdate(options, selected, id));\n }\n }, [dispatch, exists, options, selected, id]);\n\n const _selected = useSelector(state => selectSelected(state, id));\n const _options = useSelector(state => selectOptions(state, id));\n const onChange = items => dispatch(updateSelected(items, id));\n\n return (\n \n );\n};\n\nConnectedTypeAheadSelect.propTypes = {\n id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,\n options: PropTypes.array,\n selected: PropTypes.array,\n allowNew: PropTypes.bool,\n multiple: PropTypes.bool,\n placeholder: PropTypes.string,\n defaultInputValue: PropTypes.string,\n clearButton: PropTypes.bool,\n inputProps: PropTypes.object,\n};\n\nConnectedTypeAheadSelect.defaultProps = {\n options: [],\n selected: [],\n allowNew: false,\n multiple: false,\n placeholder: '',\n defaultInputValue: '',\n clearButton: false,\n inputProps: {},\n};\n\nexport default ConnectedTypeAheadSelect;\n\nexport const reducers = { typeAheadSelect: reducer };\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/TypeAheadSelect/index.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { BarChart as PfBarChart } from 'patternfly-react';\nimport { getBarChartConfig } from '../../../../../services/charts/BarChartService';\nimport { noop } from '../../../../common/helpers';\nimport { translate as __ } from '../../../../common/I18n';\nimport MessageBox from '../../MessageBox';\n\nconst BarChart = ({\n data,\n onclick,\n noDataMsg,\n config,\n title,\n unloadData,\n xAxisLabel,\n yAxisLabel,\n}) => {\n const chartConfig = getBarChartConfig({\n data,\n config,\n onclick,\n xAxisLabel,\n yAxisLabel,\n });\n\n if (chartConfig.data.columns.length) {\n return (\n \n );\n }\n return ;\n};\n\nBarChart.propTypes = {\n data: PropTypes.arrayOf(PropTypes.array),\n onclick: PropTypes.func,\n noDataMsg: PropTypes.string,\n config: PropTypes.string,\n title: PropTypes.shape({\n type: PropTypes.string,\n }),\n unloadData: PropTypes.bool,\n xAxisLabel: PropTypes.string,\n yAxisLabel: PropTypes.string,\n};\n\nBarChart.defaultProps = {\n data: null,\n onclick: noop,\n noDataMsg: __('No data available'),\n config: 'regular',\n title: { type: 'percent' },\n unloadData: false,\n yAxisLabel: '',\n xAxisLabel: '',\n};\n\nexport default BarChart;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/charts/BarChart/index.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { DonutChart as PfDonutChart } from 'patternfly-react';\nimport { getDonutChartConfig } from '../../../../../services/charts/DonutChartService';\nimport MessageBox from '../../MessageBox';\nimport { translate as __ } from '../../../../../react_app/common/I18n';\nimport { noop } from '../../../../common/helpers';\n\nconst DonutChart = ({\n data,\n onclick,\n config,\n noDataMsg,\n title,\n unloadData,\n searchUrl,\n searchFilters,\n}) => {\n const chartConfig = getDonutChartConfig({\n data,\n config,\n onclick,\n searchUrl,\n searchFilters,\n });\n\n if (chartConfig.data.columns.length > 0) {\n return (\n \n );\n }\n return ;\n};\n\nDonutChart.propTypes = {\n data: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),\n config: PropTypes.oneOf(['regular', 'medium', 'large']),\n noDataMsg: PropTypes.string,\n title: PropTypes.object,\n unloadData: PropTypes.bool,\n onclick: PropTypes.func,\n searchUrl: PropTypes.string,\n searchFilters: PropTypes.object,\n};\n\nDonutChart.defaultProps = {\n data: undefined,\n config: 'regular',\n noDataMsg: __('No data available'),\n title: { type: 'percent', precision: 1 },\n unloadData: false,\n onclick: noop,\n searchUrl: undefined,\n searchFilters: undefined,\n};\n\nexport default DonutChart;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/charts/DonutChart/index.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { LineChart as PfLineChart } from 'patternfly-react';\n\nimport { translate as __ } from '../../../../../react_app/common/I18n';\nimport { getLineChartConfig } from '../../../../../services/charts/LineChartService';\n\nimport MessageBox from '../../MessageBox';\n\nconst LineChart = ({\n data,\n title,\n config,\n noDataMsg,\n unloadData,\n xAxisDataLabel,\n axisOpts,\n onclick,\n id,\n}) => {\n const chartConfig = getLineChartConfig({\n data,\n config,\n xAxisDataLabel,\n axisOpts,\n onclick,\n id,\n });\n\n if (chartConfig.data.columns.length > 0) {\n return (\n \n );\n }\n return ;\n};\n\nLineChart.propTypes = {\n data: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),\n config: PropTypes.oneOf(['regular', 'timeseries']),\n noDataMsg: PropTypes.string,\n title: PropTypes.object,\n unloadData: PropTypes.bool,\n axisOpts: PropTypes.object,\n xAxisDataLabel: PropTypes.string,\n onclick: PropTypes.func,\n id: PropTypes.string,\n};\n\nLineChart.defaultProps = {\n data: undefined,\n config: 'regular',\n noDataMsg: __('No data available'),\n title: { type: 'percent' },\n unloadData: false,\n axisOpts: {},\n xAxisDataLabel: '',\n onclick: () => {},\n id: undefined,\n};\n\nexport default LineChart;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/charts/LineChart/index.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { FormattedDate, intlShape } from 'react-intl';\nimport { isoCompatibleDate } from '../../../common/helpers';\n\nconst IsoDate = (props, context) => {\n const { date, defaultValue } = props;\n if (date) {\n const isoDate = isoCompatibleDate(date);\n const title = context.intl.formatRelative(isoDate);\n\n return (\n \n \n \n );\n }\n return {defaultValue};\n};\n\nIsoDate.contextTypes = {\n intl: intlShape,\n};\n\nIsoDate.propTypes = {\n date: PropTypes.any,\n defaultValue: PropTypes.string,\n};\n\nIsoDate.defaultProps = {\n date: null,\n defaultValue: '',\n};\n\nexport default IsoDate;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/dates/IsoDate.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { FormattedDate, intlShape } from 'react-intl';\nimport { isoCompatibleDate } from '../../../common/helpers';\n\nconst LongDateTime = (props, context) => {\n const { date, defaultValue } = props;\n if (date) {\n const isoDate = isoCompatibleDate(date);\n const title = props.showRelativeTimeTooltip\n ? context.intl.formatRelative(isoDate)\n : undefined;\n const seconds = props.seconds ? '2-digit' : undefined;\n\n return (\n \n \n \n );\n }\n return {defaultValue};\n};\n\nLongDateTime.contextTypes = {\n intl: intlShape,\n};\n\nLongDateTime.propTypes = {\n date: PropTypes.any,\n defaultValue: PropTypes.string,\n seconds: PropTypes.bool,\n showRelativeTimeTooltip: PropTypes.bool,\n};\n\nLongDateTime.defaultProps = {\n date: null,\n defaultValue: '',\n seconds: false,\n showRelativeTimeTooltip: false,\n};\n\nexport default LongDateTime;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/dates/LongDateTime.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { FormattedRelative, intlShape } from 'react-intl';\nimport { isoCompatibleDate } from '../../../common/helpers';\n\nconst RelativeDateTime = (props, context) => {\n const { date, defaultValue } = props;\n if (date) {\n const isoDate = isoCompatibleDate(date);\n const title = context.intl.formatDate(isoDate, {\n day: '2-digit',\n month: 'short',\n hour: '2-digit',\n minute: '2-digit',\n year: 'numeric',\n });\n\n /* eslint-disable react/style-prop-object */\n return (\n \n \n \n );\n /* eslint-enable react/style-prop-object */\n }\n\n return {defaultValue};\n};\n\nRelativeDateTime.contextTypes = {\n intl: intlShape,\n};\n\nRelativeDateTime.propTypes = {\n date: PropTypes.any,\n defaultValue: PropTypes.string,\n};\n\nRelativeDateTime.defaultProps = {\n date: null,\n defaultValue: '',\n};\n\nexport default RelativeDateTime;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/dates/RelativeDateTime.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { FormattedDate, intlShape } from 'react-intl';\nimport { isoCompatibleDate } from '../../../common/helpers';\n\nconst ShortDateTime = (props, context) => {\n const { date, defaultValue, seconds } = props;\n if (date) {\n const isoDate = isoCompatibleDate(date);\n const title = props.showRelativeTimeTooltip\n ? context.intl.formatRelative(isoDate)\n : undefined;\n const secondsFormat = seconds ? '2-digit' : undefined;\n return (\n \n \n \n );\n }\n return {defaultValue};\n};\n\nShortDateTime.contextTypes = {\n intl: intlShape,\n};\n\nShortDateTime.propTypes = {\n date: PropTypes.any,\n defaultValue: PropTypes.string,\n seconds: PropTypes.bool,\n showRelativeTimeTooltip: PropTypes.bool,\n};\n\nShortDateTime.defaultProps = {\n date: null,\n defaultValue: '',\n seconds: false,\n showRelativeTimeTooltip: false,\n};\n\nexport default ShortDateTime;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/dates/ShortDateTime.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { Button } from 'patternfly-react';\n\nimport { noop } from '../../../common/helpers';\nimport { simpleLoader } from '../Loader';\nimport { translate as __ } from '../../../../react_app/common/I18n';\n\nconst FormActions = ({ onCancel, disabled, submitting }) => (\n \n
\n \n {' ' /* adds whitespace between the buttons */}\n \n
\n
\n);\n\nFormActions.propTypes = {\n disabled: PropTypes.bool,\n submitting: PropTypes.bool,\n onCancel: PropTypes.func,\n};\n\nFormActions.defaultProps = {\n disabled: false,\n submitting: false,\n onCancel: noop,\n};\n\nexport default FormActions;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/forms/Actions.js","import React from 'react';\nimport PropTypes from 'prop-types';\n\nimport { noop } from '../../../common/helpers';\nimport CommonForm from './CommonForm';\n\nconst Checkbox = ({ className, checked, onChange, label, disabled }) => (\n \n \n \n);\n\nCheckbox.propTypes = {\n className: PropTypes.string,\n checked: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),\n label: PropTypes.string,\n disabled: PropTypes.bool,\n onChange: PropTypes.func,\n};\n\nCheckbox.defaultProps = {\n className: '',\n checked: false,\n label: '',\n disabled: false,\n onChange: noop,\n};\n\nexport default Checkbox;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/forms/Checkbox.js","import React from 'react';\nimport PropTypes from 'prop-types';\n\nconst CommonForm = ({\n className,\n label,\n touched,\n error,\n required,\n children,\n inputClassName,\n tooltipHelp,\n}) => (\n \n
\n
{children}
\n {touched && error && (\n
\n {error}\n \n )}\n
\n);\n\nCommonForm.propTypes = {\n className: PropTypes.string,\n label: PropTypes.string,\n touched: PropTypes.bool,\n error: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),\n required: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),\n children: PropTypes.node,\n inputClassName: PropTypes.string,\n tooltipHelp: PropTypes.node,\n};\n\nCommonForm.defaultProps = {\n className: '',\n label: '',\n touched: false,\n error: undefined,\n required: false,\n children: null,\n inputClassName: 'col-md-4',\n tooltipHelp: null,\n};\n\nexport default CommonForm;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/forms/CommonForm.js","import React, { useEffect, useState } from 'react';\nimport RCInputNumber from 'rc-input-number';\nimport PropTypes from 'prop-types';\nimport { translate as __ } from '../../../../common/I18n';\nimport { noop } from '../../../../common/helpers';\n\nconst CounterInput = ({\n id,\n name,\n value,\n disabled,\n step,\n min,\n max,\n recommendedMaxValue,\n onChange,\n setError,\n setWarning,\n}) => {\n const [innerValue, setInnerValue] = useState(value);\n useEffect(() => {\n if (max && innerValue > max) {\n setWarning(null);\n setError(__('Specified value is higher than maximum value'));\n } else if (recommendedMaxValue && innerValue > recommendedMaxValue) {\n setError(null);\n setWarning(__('Specified value is higher than recommended maximum'));\n } else {\n setError(null);\n setWarning(null);\n }\n }, [recommendedMaxValue, max, innerValue]);\n\n const handleChange = v => {\n setInnerValue(v);\n onChange(v);\n };\n\n return (\n \n );\n};\n\nCounterInput.propTypes = {\n /** Set the name of the numeric input */\n name: PropTypes.string,\n /** Set the id of the numeric input */\n id: PropTypes.string,\n /** Set the recommended max value of the numeric input */\n recommendedMaxValue: PropTypes.number,\n /** Set the max value of the numeric input */\n max: PropTypes.number,\n /** Set the min value of the numeric input */\n min: PropTypes.number,\n /** Set whether the numeric input will be disabled or not */\n disabled: PropTypes.bool,\n /** Set the onChange function of the numeric input */\n onChange: PropTypes.func,\n /** Set the default value of the numeric input */\n value: PropTypes.number,\n /** Set the step, the counter will increase and decrease by */\n step: PropTypes.number,\n /** Component passes the validation error to this function */\n setError: PropTypes.func,\n /** Component passes the validation warning to this function */\n setWarning: PropTypes.func,\n};\n\nCounterInput.defaultProps = {\n name: '',\n id: '',\n disabled: false,\n value: 1,\n step: 1,\n min: 1,\n max: null,\n recommendedMaxValue: null,\n onChange: noop,\n setError: noop,\n setWarning: noop,\n};\n\nexport default CounterInput;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/forms/CounterInput/CounterInput.js","import CounterInput from './CounterInput';\n\nexport default CounterInput;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/forms/CounterInput/index.js","import React, { Fragment } from 'react';\nimport PropTypes from 'prop-types';\nimport { FieldLevelHelp } from 'patternfly-react';\nimport { Field } from 'formik';\nimport DateTimePicker from '../../DateTimePicker/DateTimePicker';\n\nimport CommonForm from '../CommonForm';\nimport { documentLocale } from '../../../../common/I18n';\nimport './DateTimeOverrides.scss';\n\nconst DateTime = ({\n label,\n id,\n info,\n isRequired,\n locale,\n inputProps: { name },\n inputProps,\n value,\n initialError,\n}) => {\n const currentLocale = locale || documentLocale();\n\n return (\n (\n {info}}\n />\n )\n }\n >\n setFieldValue(name, newValue)}\n />\n \n )}\n />\n );\n};\n\nDateTime.propTypes = {\n label: PropTypes.string.isRequired,\n info: PropTypes.string,\n isRequired: PropTypes.bool,\n id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired,\n locale: PropTypes.string,\n inputProps: PropTypes.object,\n value: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.string]),\n initialError: PropTypes.string,\n};\n\nDateTime.defaultProps = {\n info: undefined,\n isRequired: false,\n locale: null,\n value: new Date(),\n initialError: undefined,\n inputProps: {},\n};\n\nexport default DateTime;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/forms/DateTime/DateTime.js","import React from 'react';\nimport { Formik } from 'formik';\nimport PropTypes from 'prop-types';\nimport Form from '../Form';\nimport { translate as __ } from '../../../../common/I18n';\n\nexport const isInitialValid = ({ validationSchema, initialValues }) =>\n !validationSchema ? true : validationSchema.isValidSync(initialValues);\n\nconst ForemanForm = ({\n onSubmit,\n children,\n initialValues,\n validationSchema,\n enableReinitialize,\n onCancel,\n}) => (\n \n {formProps => {\n const disabled = formProps.isSubmitting || !formProps.isValid;\n const submissionError = formProps.errors._error;\n\n return (\n \n );\n }}\n \n);\n\nconst cloneChildren = (children, childProps) => (\n \n {children.map\n ? children.map((child, idx) =>\n React.cloneElement(child, { ...childProps, key: idx })\n )\n : React.cloneElement(children, { ...childProps })}\n \n);\n\nForemanForm.propTypes = {\n onSubmit: PropTypes.func.isRequired,\n onCancel: PropTypes.func.isRequired,\n initialValues: PropTypes.object.isRequired,\n validationSchema: PropTypes.object,\n children: PropTypes.oneOfType([PropTypes.object, PropTypes.array]).isRequired,\n enableReinitialize: PropTypes.bool,\n};\n\nForemanForm.defaultProps = {\n validationSchema: undefined,\n enableReinitialize: false,\n};\n\nexport default ForemanForm;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/forms/ForemanForm/ForemanForm.js","export { default } from './ForemanForm';\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/forms/ForemanForm/index.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { Alert } from 'patternfly-react';\n\nimport { noop } from '../../../common/helpers';\nimport AlertBody from '../Alert/AlertBody';\nimport Actions from './Actions';\nimport { translate as __ } from '../../../../react_app/common/I18n';\n\nconst Form = ({\n className,\n onSubmit,\n onCancel,\n children,\n error,\n touched,\n disabled,\n submitting,\n errorTitle,\n}) => (\n \n);\n\nForm.propTypes = {\n children: PropTypes.node,\n className: PropTypes.string,\n error: PropTypes.shape({\n errorMsgs: PropTypes.arrayOf(PropTypes.string),\n severity: PropTypes.string,\n }),\n touched: PropTypes.bool,\n disabled: PropTypes.bool,\n submitting: PropTypes.bool,\n errorTitle: PropTypes.string,\n onSubmit: PropTypes.func,\n onCancel: PropTypes.func,\n};\n\nForm.defaultProps = {\n className: 'form-horizontal well',\n children: null,\n error: null,\n touched: false,\n disabled: false,\n submitting: false,\n errorTitle: `${__('Unable to save')}. `,\n onSubmit: noop,\n onCancel: noop,\n};\n\nexport default Form;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/forms/Form.js","import React, { useState } from 'react';\nimport PropTypes from 'prop-types';\nimport classNames from 'classnames';\nimport {\n Col,\n FormGroup,\n ControlLabel,\n HelpBlock,\n FieldLevelHelp,\n} from 'patternfly-react';\nimport { WarningTriangleIcon, ErrorCircleOIcon } from '@patternfly/react-icons';\nimport InputFactory from './InputFactory';\nimport { noop } from '../../../common/helpers';\n\nconst InlineMessage = ({ error, warning, helpInline }) => {\n if (!error && !warning && !helpInline) {\n return null;\n }\n return (\n \n {error && }\n {!error && warning && }\n {error || warning || helpInline}\n \n );\n};\nInlineMessage.propTypes = {\n error: PropTypes.string,\n warning: PropTypes.string,\n helpInline: PropTypes.string,\n};\nInlineMessage.defaultProps = {\n error: null,\n warning: null,\n helpInline: null,\n};\n\nconst FormField = ({\n type,\n id,\n name,\n className,\n disabled,\n required,\n error,\n value,\n label,\n labelHelp,\n helpInline,\n labelSizeClass,\n inputSizeClass,\n onChange,\n children,\n inputProps,\n ...otherProps\n}) => {\n const [innerError, setError] = useState(error);\n const [innerWarning, setWarning] = useState(null);\n\n const controlProps = {\n value,\n name,\n disabled,\n required,\n className,\n onChange,\n setError,\n setWarning,\n ...otherProps,\n ...inputProps,\n };\n\n let validationState = null;\n if (innerWarning) validationState = 'warning';\n if (innerError) validationState = 'error';\n\n return (\n \n \n {label}\n {required ? '*' : null}\n {labelHelp && (\n {labelHelp}}\n />\n )}\n \n \n {children || }\n \n \n \n );\n};\n\nFormField.propTypes = {\n type: PropTypes.string,\n id: PropTypes.string,\n name: PropTypes.string,\n value: PropTypes.oneOfType([\n PropTypes.string,\n PropTypes.number,\n PropTypes.instanceOf(Date),\n PropTypes.array,\n PropTypes.bool,\n ]),\n className: PropTypes.string,\n label: PropTypes.string,\n labelHelp: PropTypes.string,\n required: PropTypes.bool,\n disabled: PropTypes.bool,\n error: PropTypes.string,\n helpInline: PropTypes.string,\n inputSizeClass: PropTypes.string,\n labelSizeClass: PropTypes.string,\n onChange: PropTypes.func,\n children: PropTypes.element,\n inputProps: PropTypes.object,\n};\n\nFormField.defaultProps = {\n type: 'text',\n id: null,\n name: undefined,\n value: undefined,\n className: '',\n label: '',\n labelHelp: null,\n required: false,\n disabled: false,\n error: null,\n helpInline: null,\n inputSizeClass: 'col-md-4',\n labelSizeClass: 'col-md-2',\n onChange: noop,\n children: null,\n inputProps: null,\n};\n\nexport default FormField;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/forms/FormField.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { FormControl } from 'patternfly-react';\n\nimport { noop } from '../../../common/helpers';\nimport AutoComplete from '../../AutoComplete';\nimport DateTimePicker from '../DateTimePicker/DateTimePicker';\nimport DatePicker from '../DateTimePicker/DatePicker';\nimport OrderableSelect from './OrderableSelect';\nimport MemoryAllocationInput from '../../MemoryAllocationInput';\nimport CounterInput from './CounterInput';\nimport TimePicker from '../DateTimePicker/TimePicker';\nimport Select from './Select';\n\nconst inputComponents = {\n autocomplete: AutoComplete,\n select: Select,\n date: DatePicker,\n dateTime: DateTimePicker,\n orderableSelect: OrderableSelect,\n time: TimePicker,\n memory: MemoryAllocationInput,\n counter: CounterInput,\n};\n\nexport const registerInputComponent = (name, Component) => {\n inputComponents[name] = Component;\n};\n\nexport const getComponentClass = name => inputComponents[name] || 'input';\n\nconst InputFactory = ({ type, setError, setWarning, ...controlProps }) => {\n const componentClass = getComponentClass(type);\n let validations = {};\n if (componentClass !== 'input') validations = { setError, setWarning };\n return (\n \n );\n};\n\nInputFactory.propTypes = {\n type: PropTypes.string,\n value: PropTypes.oneOfType([\n PropTypes.string,\n PropTypes.number,\n PropTypes.bool,\n PropTypes.instanceOf(Date),\n ]),\n name: PropTypes.string,\n disabled: PropTypes.bool,\n required: PropTypes.bool,\n className: PropTypes.string,\n onChange: PropTypes.func,\n setError: PropTypes.func,\n setWarning: PropTypes.func,\n};\n\nInputFactory.defaultProps = {\n type: undefined,\n name: undefined,\n value: undefined,\n className: '',\n required: false,\n disabled: false,\n onChange: noop,\n setError: noop,\n setWarning: noop,\n};\n\nexport default InputFactory;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/forms/InputFactory.js","import RCInputNumber from 'rc-input-number';\nimport React from 'react';\nimport PropTypes from 'prop-types';\nimport './NumericInput.scss';\n\nimport { noop } from '../../../common/helpers';\nimport CommonForm from './CommonForm';\n\nconst NumericInput = ({\n label,\n className,\n value,\n onChange,\n format,\n parser,\n step,\n precision,\n minValue,\n disabled,\n readOnly,\n name,\n id,\n}) => (\n \n \n \n);\n\nNumericInput.propTypes = {\n label: PropTypes.string,\n className: PropTypes.string,\n name: PropTypes.string,\n id: PropTypes.string,\n value: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),\n format: PropTypes.func,\n parser: PropTypes.func,\n step: PropTypes.number,\n precision: PropTypes.number,\n minValue: PropTypes.number,\n disabled: PropTypes.bool,\n onChange: PropTypes.func,\n readOnly: PropTypes.bool,\n};\n\nNumericInput.defaultProps = {\n label: '',\n className: '',\n name: '',\n id: '',\n value: 0,\n format: null,\n parser: undefined,\n step: 1,\n disabled: false,\n precision: 0,\n minValue: 0,\n onChange: noop,\n readOnly: false,\n};\n\nexport default NumericInput;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/forms/NumericInput.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { set } from 'lodash';\nimport { TypeAheadSelect } from 'patternfly-react';\n\nimport { noop } from '../../../../common/helpers';\nimport { orderDragged } from './helpers';\nimport { useInternalValue } from './OrderableSelectHooks';\nimport OrderableToken from './components/OrderableToken';\n\n/**\n * Wraps TypeAheadSelect with an Orderable HOC.\n * Presumes to be wrapped in a DndProvider context.\n * The value can not be changed through props once the component is rendered.\n */\nconst OrderableSelect = ({\n className,\n onChange,\n defaultValue,\n value,\n options,\n name,\n ...props\n}) => {\n const [internalValue, setInternalValue] = useInternalValue(\n value || defaultValue,\n options\n );\n const moveDraggedOption = (dragIndex, hoverIndex) => {\n setInternalValue(orderDragged(internalValue, dragIndex, hoverIndex));\n };\n\n // hack the form-control, which is already in TypeAhead so it would be duplicated\n const classesWithoutFormControl =\n className &&\n className\n .split(/\\s+/)\n .filter(el => el !== 'form-control')\n .join(' ');\n\n return (\n (\n \n \n {name && }\n
\n )}\n {...props}\n className={classesWithoutFormControl}\n options={options}\n selected={internalValue}\n onChange={newValue => {\n setInternalValue(newValue);\n onChange(newValue);\n }}\n />\n );\n};\n\nOrderableSelect.propTypes = {\n options: PropTypes.arrayOf(PropTypes.object).isRequired,\n id: PropTypes.string.isRequired,\n name: PropTypes.string,\n onChange: PropTypes.func,\n defaultValue: PropTypes.array,\n value: PropTypes.array,\n className: PropTypes.string,\n};\n\nOrderableSelect.defaultProps = {\n onChange: noop,\n defaultValue: [],\n value: null,\n name: null,\n className: '',\n};\n\nexport default OrderableSelect;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/forms/OrderableSelect/OrderableSelect.js","import { useState } from 'react';\n\nexport const useInternalValue = (value, options) => {\n const defaultVal = value\n .map(v => options.find(opt => opt.value === v))\n .filter(v => !!v);\n return useState(defaultVal);\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/forms/OrderableSelect/OrderableSelectHooks.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { TypeAheadSelect } from 'patternfly-react';\n\nimport { orderable } from '../helpers';\n\nconst orderConfig = {\n type: 'multiValue',\n getItem: props => ({ value: props.data.value }),\n getIndex: props => props.data.index,\n getMoveFnc: props => props.moveDraggedOption,\n};\n\nconst OrderableToken = ({\n isDragging,\n moveDraggedOption,\n data,\n disabled,\n onRemove,\n tabIndex,\n labelKey,\n}) => (\n \n {data[labelKey]}\n \n);\n\nOrderableToken.propTypes = {\n isDragging: PropTypes.bool.isRequired,\n moveDraggedOption: PropTypes.func.isRequired,\n data: PropTypes.object.isRequired,\n labelKey: PropTypes.string.isRequired,\n disabled: PropTypes.bool,\n tabIndex: PropTypes.number,\n onRemove: PropTypes.func,\n};\n\nOrderableToken.defaultProps = {\n disabled: false,\n tabIndex: -1,\n onRemove: undefined,\n};\n\nexport default orderable(OrderableToken, orderConfig);\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/forms/OrderableSelect/components/OrderableToken.js","import React, { useImperativeHandle, useRef } from 'react';\nimport { DragSource, DropTarget } from 'react-dnd';\nimport PropTypes from 'prop-types';\nimport { set } from 'lodash';\n\nexport const orderDragged = (inputArray, dragIndex, hoverIndex) => {\n const dragedValue = inputArray[dragIndex];\n const ordered = [...inputArray];\n ordered.splice(dragIndex, 1);\n ordered.splice(hoverIndex, 0, dragedValue);\n return ordered;\n};\n\nexport const makeOnHover = (getIndex, getMoveFnc, direction) => (\n props,\n monitor,\n component\n) => {\n const dragIndex = monitor.getItem().index;\n const hoverIndex = getIndex(props);\n\n // Don't replace items with themselves\n if (dragIndex === hoverIndex) return null;\n\n // Determine rectangle on screen\n const hoverBoundingRect = component.getNode().getBoundingClientRect();\n let shouldMove = false;\n\n // Determine which drag direction we should handle and whether to move an item\n if (direction === 'vertical') {\n shouldMove = onHover(\n dragIndex,\n hoverIndex,\n hoverBoundingRect,\n monitor,\n 'y',\n 'bottom',\n 'top'\n );\n } else if (direction === 'horizontal') {\n shouldMove = onHover(\n dragIndex,\n hoverIndex,\n hoverBoundingRect,\n monitor,\n 'x',\n 'right',\n 'left'\n );\n } else {\n throw new Error(\n `Unknown drag direction, expected one of: horizontal, vertical, got: ${direction}`\n );\n }\n\n if (!shouldMove) {\n return null;\n }\n\n // Time to actually perform the action\n getMoveFnc(props)(dragIndex, hoverIndex);\n // Note: we're mutating the monitor item here!\n // Generally it's better to avoid mutations,\n // but it's good here for the sake of performance\n // to avoid expensive index searches.\n monitor.getItem().index = hoverIndex;\n return null;\n};\n\nconst onHover = (\n dragIndex,\n hoverIndex,\n hoverBoundingRect,\n monitor,\n clientAttr,\n rectMaxAttr,\n rectMinAttr\n) => {\n // Get midpoint\n const hoverMiddle =\n (hoverBoundingRect[rectMaxAttr] - hoverBoundingRect[rectMinAttr]) / 2;\n // Determine mouse position\n const clientOffset = monitor.getClientOffset();\n // Get pixels to the border\n const hoverClient = clientOffset[clientAttr] - hoverBoundingRect[rectMinAttr];\n\n // Swap items only when the mouse has moved over the midpoint of other item\n // Dragging right or down\n if (dragIndex < hoverIndex && hoverClient < hoverMiddle) {\n return false;\n }\n // Dragging left or up\n if (dragIndex > hoverIndex && hoverClient > hoverMiddle) {\n return false;\n }\n\n return true;\n};\n\nconst getDropTarget = (dropTypes, getIndex, getMoveFnc, direction) =>\n DropTarget(\n dropTypes,\n { hover: makeOnHover(getIndex, getMoveFnc, direction) },\n connect => ({\n connectDropTarget: connect.dropTarget(),\n })\n );\n\nconst getDragSource = (dragType, getIndex, getItem) =>\n DragSource(\n dragType,\n {\n beginDrag: props => set(getItem(props), 'index', getIndex(props)),\n },\n (connect, monitor) => ({\n connectDragSource: connect.dragSource(),\n isDragging: monitor.isDragging(),\n })\n );\n\nexport const orderable = (\n Component,\n {\n type = 'orderable',\n direction = 'horizontal',\n getItem = props => ({ id: props.id }),\n getIndex = props => props.index,\n getMoveFnc = props => props.moveValue,\n }\n) => {\n const Orderable = React.forwardRef(\n (\n {\n isDragging,\n styleOnDrag,\n connectDragSource,\n connectDropTarget,\n ...props\n },\n ref\n ) => {\n const elementRef = useRef(null);\n connectDragSource(elementRef);\n connectDropTarget(elementRef);\n useImperativeHandle(ref, () => ({\n getNode: () => elementRef.current,\n }));\n return (\n \n \n
\n );\n }\n );\n Orderable.displayName = `Orderable(${Component.displayName ||\n Component.name ||\n 'Component'})`;\n\n Orderable.propTypes = {\n isDragging: PropTypes.bool.isRequired,\n connectDragSource: PropTypes.func.isRequired,\n connectDropTarget: PropTypes.func.isRequired,\n styleOnDrag: PropTypes.object,\n };\n\n Orderable.defaultProps = {\n styleOnDrag: { opacity: 0.6 },\n };\n\n return getDropTarget(\n type,\n getIndex,\n getMoveFnc,\n direction\n )(getDragSource(type, getIndex, getItem)(Orderable));\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/forms/OrderableSelect/helpers.js","import React from 'react';\nimport { DndProvider } from 'react-dnd';\nimport HTML5Backend from 'react-dnd-html5-backend';\n\nimport OrderableSelect from './OrderableSelect';\n\nexport default props => (\n \n \n \n);\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/forms/OrderableSelect/index.js","import $ from 'jquery';\nimport React from 'react';\nimport PropTypes from 'prop-types';\nimport { Spinner } from 'patternfly-react';\n\nimport { translate as __ } from '../../../common/I18n';\nimport { noop } from '../../../common/helpers';\nimport CommonForm from './CommonForm';\nimport { STATUS } from '../../../constants';\nimport MessageBox from '../MessageBox';\nimport { renderOptions } from './SelectHelpers';\n\nclass Select extends React.Component {\n initializeSelect2() {\n const { allowClear } = this.props;\n\n if ($.fn.select2) {\n $(this.select).select2({ allowClear });\n }\n }\n\n attachEvent() {\n const { onChange } = this.props;\n $(this.select)\n .off('change', onChange)\n .on('change', onChange);\n }\n\n componentDidMount() {\n if (this.props.useSelect2) {\n this.initializeSelect2();\n this.attachEvent();\n }\n }\n\n componentDidUpdate(prevProps) {\n if (this.props.useSelect2) {\n this.initializeSelect2();\n if (this.props.status !== prevProps.status) {\n this.attachEvent();\n }\n }\n }\n\n render() {\n const {\n name,\n label,\n className,\n value,\n onChange,\n options,\n disabled,\n status = STATUS.RESOLVED,\n errorMessage = __('An error occurred.'),\n } = this.props;\n\n let content;\n\n const innerSelect = (\n \n \n
\n );\n\n switch (status) {\n case STATUS.RESOLVED: {\n content = innerSelect;\n break;\n }\n case STATUS.PENDING: {\n content = ;\n break;\n }\n case STATUS.ERROR: {\n content = ;\n break;\n }\n default:\n content = ;\n break;\n }\n\n if (!label) {\n return innerSelect;\n }\n return (\n \n {content}\n \n );\n }\n}\n\nSelect.propTypes = {\n name: PropTypes.string,\n value: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),\n label: PropTypes.string,\n className: PropTypes.string,\n allowClear: PropTypes.bool,\n disabled: PropTypes.bool,\n options: PropTypes.oneOfType([PropTypes.array, PropTypes.object]),\n status: PropTypes.string,\n errorMessage: PropTypes.string,\n onChange: PropTypes.func,\n useSelect2: PropTypes.bool,\n};\n\nSelect.defaultProps = {\n name: null,\n value: undefined,\n label: '',\n className: '',\n allowClear: false,\n disabled: false,\n options: {},\n status: STATUS.RESOLVED,\n errorMessage: __('An error occurred.'),\n onChange: noop,\n useSelect2: true,\n};\n\nexport default Select;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/forms/Select.js","import React from 'react';\n\nconst renderOption = (val, text, key = null) => {\n const optValue = val === null || val === undefined ? '' : val;\n\n return (\n \n );\n};\n\nconst renderOptGroup = group => (\n \n);\n\nexport const renderOptions = opts => {\n if (Array.isArray(opts)) {\n return opts.map((opt, index) => {\n if (opt.children) {\n return renderOptGroup(opt);\n }\n return renderOption(opt.value, opt.label, index);\n });\n }\n return Object.entries(opts).map(([val, text]) => renderOption(val, text));\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/forms/SelectHelpers.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { Field } from 'formik';\nimport TextFieldInner from './TextFieldInner';\n\nconst TextField = ({\n name,\n label,\n type,\n className,\n inputClassName,\n required,\n validate,\n}) => (\n (\n \n )}\n />\n);\n\nTextField.propTypes = {\n name: PropTypes.string.isRequired,\n label: PropTypes.string,\n type: PropTypes.string,\n className: PropTypes.string,\n inputClassName: PropTypes.string,\n required: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]),\n validate: PropTypes.func,\n};\n\nTextField.defaultProps = {\n label: '',\n type: 'text',\n className: '',\n required: false,\n inputClassName: undefined,\n validate: undefined,\n};\n\nexport default TextField;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/forms/TextField/TextField.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport CommonForm from '../CommonForm';\n\nconst TextFieldInner = ({\n input,\n label,\n type,\n required,\n className,\n inputClassName,\n meta: { touched, error },\n}) => (\n \n {type === 'textarea' ? (\n \n ) : (\n \n )}\n \n);\n\nTextFieldInner.propTypes = {\n input: PropTypes.object,\n label: PropTypes.string,\n type: PropTypes.string,\n required: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]),\n className: PropTypes.string,\n inputClassName: PropTypes.string,\n meta: PropTypes.shape({ touched: PropTypes.bool, error: PropTypes.string }),\n};\n\nTextFieldInner.defaultProps = {\n input: {},\n label: '',\n type: 'text',\n className: '',\n required: false,\n inputClassName: undefined,\n meta: { touched: false, error: undefined },\n};\n\nexport default TextFieldInner;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/forms/TextField/TextFieldInner.js","import TextField from './TextField';\n\nexport default TextField;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/forms/TextField/index.js","import { translate as __, sprintf } from '../../../../react_app/common/I18n';\n\nexport const maxLengthMsg = number => [\n number,\n sprintf(__('is too long (maximum is %s characters)'), number),\n];\n\nexport const requiredMsg = () => __(\"can't be blank\");\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/forms/validators.js","import URI from 'urijs';\nimport { get } from './../../../../redux/API';\n/**\n * An async Redux action that fetches and stores table data in Redux.\n * @param {String} tableID the table ID for Redux\n * @param {Object} query the API request query\n * @param {String} url the url for the data\n * @return {Function} Redux Thunk function\n */\nconst getTableItemsAction = (tableID, query, fetchUrl) => {\n const url = new URI(fetchUrl);\n url.addSearch({ ...query, include_permissions: true });\n\n return get({\n key: tableID.toUpperCase(),\n url: url.toString(),\n payload: { tableID, url: url.toString() },\n });\n};\n\nexport default getTableItemsAction;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/table/actions/getTableItemsAction.js","export { default as getTableItemsAction } from './getTableItemsAction';\nexport * from './selectionActions';\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/table/actions/index.js","import {\n SELECT_ROWS,\n SELECT_ALL_ROWS,\n UNSELECT_ALL_ROWS,\n UNSELECT_ROWS,\n OPEN_SELECT_ALL,\n} from '../constants/SelectionConstants';\n\nexport const selectPage = (tableID, results) => dispatch => {\n dispatch({\n type: SELECT_ROWS,\n payload: results.map(row => row.id),\n tableID,\n });\n dispatch({\n type: OPEN_SELECT_ALL,\n tableID,\n });\n};\n\nexport const selectAllRows = tableID => ({\n type: SELECT_ALL_ROWS,\n tableID,\n});\n\nexport const unselectAllRows = tableID => ({\n type: UNSELECT_ALL_ROWS,\n tableID,\n});\n\nexport const selectRow = (tableID, id) => ({\n type: SELECT_ROWS,\n payload: [id],\n tableID,\n});\n\nexport const unselectRow = (tableID, id, results) => ({\n type: UNSELECT_ROWS,\n payload: { id, results },\n tableID,\n});\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/table/actions/selectionActions.js","const createTableActionTypes = tableID => ({\n REQUEST: `${tableID.toUpperCase()}_REQUEST`,\n SUCCESS: `${tableID.toUpperCase()}_SUCCESS`,\n FAILURE: `${tableID.toUpperCase()}_FAILURE`,\n});\n\nexport default createTableActionTypes;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/table/actionsHelpers/actionTypeCreator.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { Button } from 'patternfly-react';\nimport { translate as __ } from '../../../../common/I18n';\n\nconst DeleteButton = ({ active, onClick }) =>\n active ? (\n \n ) : null;\n\nDeleteButton.propTypes = {\n active: PropTypes.bool,\n onClick: PropTypes.func.isRequired,\n};\n\nDeleteButton.defaultProps = {\n active: false,\n};\n\nexport default DeleteButton;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/table/components/DeleteButton.js","import React from 'react';\nimport PropTypes from 'prop-types';\n\nconst HostsCountCell = ({ name, controller, children }) => (\n {children}\n);\n\nHostsCountCell.propTypes = {\n name: PropTypes.string.isRequired,\n controller: PropTypes.string.isRequired,\n children: PropTypes.node.isRequired,\n};\n\nHostsCountCell.defaultProps = {};\n\nexport default HostsCountCell;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/table/components/HostsCountCell.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { Link } from 'react-router-dom';\n\nconst NameCell = ({ active, id, name, controller, children }) =>\n active ? (\n {children}\n ) : (\n {}}>\n {children}\n \n );\n\nNameCell.propTypes = {\n active: PropTypes.bool,\n id: PropTypes.number.isRequired,\n name: PropTypes.string.isRequired,\n controller: PropTypes.string.isRequired,\n children: PropTypes.node,\n};\n\nNameCell.defaultProps = {\n active: false,\n children: null,\n};\n\nexport default NameCell;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/table/components/NameCell.js","import React from 'react';\nimport PropTypes from 'prop-types';\n\nconst SortableHeader = ({ onClick, children, sortOrder }) => (\n \n {sortOrder && }\n {children}\n \n);\n\nSortableHeader.propTypes = {\n onClick: PropTypes.func.isRequired,\n children: PropTypes.node.isRequired,\n sortOrder: PropTypes.oneOf(['asc', 'desc', null]),\n};\n\nSortableHeader.defaultProps = {\n sortOrder: null,\n};\n\nexport default SortableHeader;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/table/components/SortableHeader.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { Table as PfTable } from 'patternfly-react';\nimport TableBody from './TableBody';\n\nconst Table = ({ columns, rows, bodyMessage, children, ...props }) => {\n const body = children || [\n ,\n ,\n ];\n\n return (\n \n );\n};\n\nTable.propTypes = {\n columns: PropTypes.arrayOf(PropTypes.object).isRequired,\n rows: PropTypes.arrayOf(PropTypes.object).isRequired,\n bodyMessage: PropTypes.node,\n children: PropTypes.node,\n};\n\nTable.defaultProps = {\n bodyMessage: undefined,\n children: undefined,\n};\n\nexport default Table;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/table/components/Table.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { Table as PfTable } from 'patternfly-react';\n\nimport TableBodyMessage from './TableBodyMessage';\n\nconst TableBody = ({ columns, rows, message, ...props }) => {\n if (message) {\n return (\n {message}\n );\n }\n\n return (\n rowIndex} {...props} />\n );\n};\n\nTableBody.propTypes = {\n columns: PropTypes.arrayOf(PropTypes.object).isRequired,\n rows: PropTypes.arrayOf(PropTypes.object).isRequired,\n message: PropTypes.node,\n};\n\nTableBody.defaultProps = {\n message: undefined,\n};\n\nexport default TableBody;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/table/components/TableBody.js","import React from 'react';\nimport PropTypes from 'prop-types';\n\nconst TableBodyMessage = ({ colSpan, children }) => (\n \n \n {children} | \n
\n \n);\n\nTableBodyMessage.propTypes = {\n colSpan: PropTypes.number.isRequired,\n children: PropTypes.node.isRequired,\n};\n\nexport default TableBodyMessage;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/table/components/TableBodyMessage.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { Table } from 'patternfly-react';\nimport { translate as __ } from '../../../../common/I18n';\nimport { noop } from '../../../../common/helpers';\n\nconst TableSelectionCell = ({ id, label, checked, onChange, ...props }) => (\n \n \n \n);\n\nTableSelectionCell.propTypes = {\n id: PropTypes.string.isRequired,\n label: PropTypes.string,\n checked: PropTypes.bool,\n onChange: PropTypes.func,\n};\n\nTableSelectionCell.defaultProps = {\n label: __('Select row'),\n checked: false,\n onChange: noop,\n};\n\nexport default TableSelectionCell;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/table/components/TableSelectionCell.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { Table } from 'patternfly-react';\nimport { noop } from '../../../../common/helpers';\n\nconst TableSelectionHeaderCell = ({\n id,\n label,\n checked,\n onChange,\n ...props\n}) => (\n \n \n \n);\n\nTableSelectionHeaderCell.propTypes = {\n id: PropTypes.string,\n label: PropTypes.string,\n checked: PropTypes.bool,\n onChange: PropTypes.func,\n};\n\nTableSelectionHeaderCell.defaultProps = {\n id: 'selectAll',\n label: '',\n checked: false,\n onChange: noop,\n};\n\nexport default TableSelectionHeaderCell;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/table/components/TableSelectionHeaderCell.js","export { default as Table } from './Table';\nexport { default as TableBody } from './TableBody';\nexport { default as TableBodyMessage } from './TableBodyMessage';\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/table/components/index.js","export const SELECT_ROWS = 'SELECT_ROWS';\nexport const UNSELECT_ROWS = 'UNSELECT_ROWS';\nexport const UNSELECT_ALL_ROWS = 'UNSELECT_ALL_ROWS';\nexport const SELECT_ALL_ROWS = 'SELECT_ALL_ROWS';\nexport const OPEN_SELECT_ALL = 'OPEN_SELECT_ALL';\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/table/constants/SelectionConstants.js","import React from 'react';\nimport { Table as PfTable } from 'patternfly-react';\n\nexport default value => {value};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/table/formatters/cellFormatter.js","import React from 'react';\nimport DeleteButton from '../components/DeleteButton';\n\nexport const deleteActionCellFormatter = onClick => (_, { rowData }) => {\n const { canDelete } = rowData;\n\n return onClick(rowData)} />;\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/table/formatters/deleteActionCellFormatter.js","import React from 'react';\nimport EllipsisWithTooltip from 'react-ellipsis-with-tooltip';\nimport cellFormatter from './cellFormatter';\n\nexport default value =>\n cellFormatter({value || ''});\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/table/formatters/ellipsisCellFormatter.js","import React from 'react';\nimport { Table as PfTable } from 'patternfly-react';\n\nexport const withProps = fieldType => Component => (\n value,\n {\n column: {\n [fieldType]: { props },\n },\n }\n) => {value};\n\nexport const withHeaderProps = withProps('header');\nexport const withCellProps = withProps('cell');\n\nexport const headerFormatterWithProps = withHeaderProps(PfTable.Heading);\nexport const cellFormatterWithProps = withCellProps(PfTable.Cell);\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/table/formatters/formatterWithProps.js","import React from 'react';\nimport HostsCountCell from '../components/HostsCountCell';\n\nconst hostsCountCellFormatter = controllerSingular => (\n value,\n { rowData: { name } }\n) => (\n \n {value}\n \n);\n\nexport default hostsCountCellFormatter;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/table/formatters/hostsCountCellFormatter.js","export {\n headerFormatterWithProps,\n cellFormatterWithProps,\n} from './formatterWithProps';\nexport { default as cellFormatter } from './cellFormatter';\nexport { default as ellipsisCellFormatter } from './ellipsisCellFormatter';\nexport { default as nameCellFormatter } from './nameCellFormatter';\nexport { default as hostsCountCellFormatter } from './hostsCountCellFormatter';\nexport { default as sortableHeaderFormatter } from './sortableHeaderFormatter';\nexport { deleteActionCellFormatter } from './deleteActionCellFormatter';\nexport { default as selectionCellFormatter } from './selectionCellFormatter';\nexport { default as selectionHeaderCellFormatter } from './selectionHeaderCellFormatter';\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/table/formatters/index.js","import React from 'react';\nimport NameCell from '../components/NameCell';\n\nconst nameCellFormatter = controllerPluralize => (\n value,\n { rowData: { canEdit, id, name } }\n) => (\n \n {value}\n \n);\n\nexport default nameCellFormatter;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/table/formatters/nameCellFormatter.js","import React from 'react';\nimport TableSelectionCell from '../components/TableSelectionCell';\n\nexport const selectionCellFormatter = (selectionController, additionalData) => (\n selectionController.selectRow(additionalData)}\n />\n);\nexport default selectionCellFormatter;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/table/formatters/selectionCellFormatter.js","import React from 'react';\nimport TableSelectionHeaderCell from '../components/TableSelectionHeaderCell';\n\nexport const selectionHeaderCellFormatter = (selectionController, label) => (\n \n);\n\nexport default selectionHeaderCellFormatter;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/table/formatters/selectionHeaderCellFormatter.js","import React from 'react';\nimport SortableHeader from '../components/SortableHeader';\n\nconst sortableHeaderFormatter = sortController => (label, { property }) => {\n const isSorter = property === sortController.property;\n const currentOrder = isSorter ? sortController.order : '';\n const nextOrder = currentOrder === 'ASC' ? 'DESC' : 'ASC';\n\n return (\n {\n sortController.apply(property, nextOrder);\n }}\n sortOrder={isSorter ? sortController.order.toLowerCase() : null}\n >{` ${label}`}\n );\n};\n\nexport default sortableHeaderFormatter;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/table/formatters/sortableHeaderFormatter.js","export * from './formatters';\nexport * from './components';\nexport * from './schemaHelpers';\nexport * from './actions';\nexport * from './reducers';\nexport * from './selectors/selectionSelectors';\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/table/index.js","import Immutable from 'seamless-immutable';\nimport { STATUS } from '../../../../constants';\nimport createTableActionTypes from '../actionsHelpers/actionTypeCreator';\n\nconst initState = Immutable({\n error: null,\n sortBy: '',\n sortOrder: '',\n results: [],\n status: STATUS.PENDING,\n pagination: { page: 1, perPage: 20 },\n total: 0,\n});\n\nconst createTableReducer = tableID => (\n state = initState,\n { type, payload, response }\n) => {\n const { REQUEST, FAILURE, SUCCESS } = createTableActionTypes(tableID);\n\n switch (type) {\n case REQUEST:\n return state.set('status', STATUS.PENDING);\n case SUCCESS:\n return Immutable.merge(state, {\n error: null,\n status: STATUS.RESOLVED,\n results: response.results,\n sortBy: response.sort.by,\n sortOrder: response.sort.order,\n pagination: { page: response.page, perPage: response.per_page },\n total: response.total,\n });\n case FAILURE:\n return Immutable.merge(state, {\n error: response,\n status: STATUS.ERROR,\n results: [],\n });\n default:\n return state;\n }\n};\n\nexport default createTableReducer;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/table/reducers/createTableReducer.js","export { default as createTableReducer } from './createTableReducer';\nexport { default as selectionReducer } from './selectionReducer';\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/table/reducers/index.js","import Immutable from 'seamless-immutable';\nimport { union } from 'lodash';\nimport {\n SELECT_ROWS,\n UNSELECT_ROWS,\n UNSELECT_ALL_ROWS,\n SELECT_ALL_ROWS,\n OPEN_SELECT_ALL,\n} from '../constants/SelectionConstants';\n\nconst initialState = Immutable({\n selectedRows: [],\n allRowsSelected: false,\n showSelectAll: false,\n});\n\nconst getSelectedRows = state => (state ? state.selectedRows : []);\n\nexport const selectionReducer = currentTableID => (\n state = initialState,\n { tableID, type, payload }\n) => {\n if (tableID === undefined || tableID !== currentTableID) return state;\n\n switch (type) {\n case SELECT_ALL_ROWS:\n return state.merge({ allRowsSelected: true });\n case SELECT_ROWS:\n return state.merge({\n selectedRows: union(payload, getSelectedRows(state)),\n });\n case OPEN_SELECT_ALL:\n return state.merge({ showSelectAll: true });\n case UNSELECT_ROWS:\n if (state && state.allRowsSelected) {\n // User can unselect rows if only the page rows are selected\n return state.merge({\n selectedRows: payload.results\n .map(row => row.id)\n .filter(row => row !== payload.id),\n allRowsSelected: false,\n showSelectAll: false,\n });\n }\n return state.merge({\n selectedRows: state.selectedRows.filter(row => row !== payload.id),\n });\n case UNSELECT_ALL_ROWS:\n return state.merge({\n selectedRows: [],\n allRowsSelected: false,\n showSelectAll: false,\n });\n default:\n return state;\n }\n};\nexport default selectionReducer;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/table/reducers/selectionReducer.js","/**\n * Generate a column for a patternfly-3 table.\n * See more in http://patternfly-react.surge.sh/patternfly-3/\n * See an example: components ModelsTableSchema\n * @param {String} property the property name of the table.\n * @param {String} label the column label.\n * @param {Array} headFormat array of functions that format the header. Read more about format\n * functions here:\n * https://reactabular.js.org/#/column-definition/formatters\n * @param {Array} cellFormat array of functions that format column cells. Read more about format\n * functions here:\n * https://reactabular.js.org/#/column-definition/formatters\n * @param {Object} headProps React props that can be passed to the header.\n * @param {Object} cellProps React props that can be passed to cells.\n * @return {Object} the table column.\n */\nexport const column = (\n property,\n label,\n headFormat,\n cellFormat,\n headProps = {},\n cellProps = {}\n) => ({\n property,\n header: {\n label,\n props: headProps,\n formatters: headFormat,\n },\n cell: {\n props: cellProps,\n formatters: cellFormat,\n },\n});\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/table/schemaHelpers/column.js","export { sortControllerFactory, sortableColumn } from './sortableColumn';\nexport { column } from './column';\nexport { getSelectionController } from './selection';\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/table/schemaHelpers/index.js","import {\n selectRow,\n selectPage,\n unselectAllRows,\n unselectRow,\n} from '../actions/selectionActions';\n\nexport const getSelectionController = ({\n tableID,\n allRowsSelected,\n rows,\n selectedRows,\n dispatch,\n}) => {\n const checkAllPageSelected = () =>\n allRowsSelected || rows.length === selectedRows.length;\n\n return {\n allRowsSelected,\n allPageSelected: () => checkAllPageSelected(tableID),\n selectPage: () => {\n if (checkAllPageSelected()) dispatch(unselectAllRows(tableID));\n else {\n dispatch(selectPage(tableID, rows));\n }\n },\n selectRow: ({ rowData: { id } }) => {\n if (selectedRows.includes(id) || allRowsSelected)\n dispatch(unselectRow(tableID, id, allRowsSelected && rows));\n else dispatch(selectRow(tableID, id));\n },\n isSelected: ({ rowData }) =>\n allRowsSelected || selectedRows.includes(rowData.id),\n };\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/table/schemaHelpers/selection.js","import URI from 'urijs';\nimport {\n ellipsisCellFormatter,\n headerFormatterWithProps,\n sortableHeaderFormatter,\n} from '../formatters';\nimport { column } from './column';\n\n/**\n * Generate a sortable column for a patternfly-3 table.\n * See more in http://patternfly-react.surge.sh/patternfly-3/\n * See an example: ModelsTableSchema\n * @param {String} property the property name of the table.\n * @param {String} label the column label.\n * @param {Number} mdWidth column size on medium devices. Note: using bootstrap\n * grid convention.\n * @param {Object} sortController sortController object.\n * See more in sortControllerFactory.\n * @param {Array} additionalCellFormatters array of functions that format column cells\n * @return {Object} the table column.\n */\nexport const sortableColumn = (\n property,\n label,\n mdWidth,\n sortController,\n additionalCellFormatters = []\n) =>\n column(\n property,\n label,\n [sortableHeaderFormatter(sortController), headerFormatterWithProps],\n [...additionalCellFormatters, ellipsisCellFormatter],\n { sort: true, sortDirection: '', className: `col-md-${mdWidth}` }\n );\n\n/**\n * Creates a sort controller for Patternfly-3 table.\n * @param {Function} apiCall a function that fetches and stores data into Redux.\n * @param {String} sortBy the property that the table is sorted by.\n * @param {String} sortOrder the order which the table is sorted by.\n * @return {Object} a sort controller object.\n */\nexport const sortControllerFactory = (apiCall, sortBy, sortOrder) => ({\n apply: (by, order) => {\n const uri = new URI(window.location.href);\n uri.setSearch('order', `${by} ${order}`);\n // FIXME(bshuster): Going back in the browser won't render the state.\n // Using react-router will fix this completely.\n window.history.pushState({ path: uri.toString() }, '', uri.toString());\n apiCall(uri.query(true));\n },\n property: sortBy,\n order: sortOrder,\n});\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/table/schemaHelpers/sortableColumn.js","export const selectSelection = state => state.API;\n\nexport const selectSelectionByID = (state, tableID) =>\n selectSelection(state)[tableID] || {};\n\nexport const selectAllRowsSelected = (state, tableID) =>\n selectSelectionByID(state, tableID).allRowsSelected || false;\n\nexport const selectSelectedRows = (state, tableID) =>\n selectSelectionByID(state, tableID).selectedRows || [];\n\nexport const selectShowSelectAll = (state, tableID) =>\n selectSelectionByID(state, tableID).showSelectAll || false;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/table/selectors/selectionSelectors.js","import React from 'react';\nimport forceSingleton from '../common/forceSingleton';\n\nimport ReactApp from '../Root/ReactApp';\nimport DonutChart from './common/charts/DonutChart';\nimport BarChart from './common/charts/BarChart';\nimport LineChart from './common/charts/LineChart';\nimport PowerStatus from './hosts/powerStatus/';\nimport NotificationContainer from './notifications/';\nimport ToastsList from './ToastsList/';\nimport RelativeDateTime from './common/dates/RelativeDateTime';\nimport LongDateTime from './common/dates/LongDateTime';\nimport ShortDateTime from './common/dates/ShortDateTime';\nimport IsoDate from './common/dates/IsoDate';\nimport FormField from './common/forms/FormField';\nimport InputFactory from './common/forms/InputFactory';\nimport StorageContainer from './hosts/storage/vmware/';\nimport PasswordStrength from './PasswordStrength';\nimport BreadcrumbBar from './BreadcrumbBar';\nimport FactChart from './FactCharts';\nimport Pagination from './Pagination/Pagination';\nimport AutoComplete from './AutoComplete';\nimport SearchBar from './SearchBar';\nimport Layout from './Layout';\nimport EmptyState from './common/EmptyState';\nimport ComponentWrapper from './common/ComponentWrapper/ComponentWrapper';\nimport ChartBox from './ChartBox/ChartBox';\nimport ConfigReports from './ConfigReports/ConfigReports';\nimport DiffModal from './ConfigReports/DiffModal';\nimport { WrapperFactory } from './wrapperFactory';\nimport ModelsTable from './ModelsTable';\nimport TemplateGenerator from './TemplateGenerator';\nimport Editor from './Editor';\nimport LoginPage from './LoginPage';\nimport ExternalLogout from './ExternalLogout';\nimport Slot from './common/Slot';\nimport TypeAheadSelect from './common/TypeAheadSelect';\nimport DatePicker from './common/DateTimePicker/DatePicker';\nimport RedirectCancelButton from './common/RedirectCancelButton';\nimport SettingRecords from './SettingRecords';\nimport SettingsTable from './SettingsTable';\nimport SettingUpdateModal from './SettingUpdateModal';\nimport PersonalAccessTokens from './users/PersonalAccessTokens';\nimport ClipboardCopy from './common/ClipboardCopy';\nimport LabelIcon from './common/LabelIcon';\nimport { WelcomeEnv } from './Enviroments/Welcome';\nimport { WelcomeAuthSource } from './AuthSource/Welcome';\nimport { WelcomeConfigReports } from './ConfigReports/Welcome';\nimport { WelcomeArchitecture } from './Architectures/Welcome';\n\nconst componentRegistry = {\n registry: forceSingleton('component_registry', () => ({})),\n\n register({ name = null, type = null, store = true, data = true }) {\n if (!name || !type) {\n throw new Error('Component name or type is missing');\n }\n if (this.registry[name]) {\n // eslint-disable-next-line no-console\n console.warn(`Component name already taken: ${name}`);\n } else {\n this.registry[name] = { type, store, data };\n }\n\n return this.registry;\n },\n\n registerMultiple(componentObjs) {\n return Object.values(componentObjs).forEach(obj => this.register(obj));\n },\n\n getComponent(name) {\n if (!this.registry[name]) {\n throw new Error(\n `Component not found: ${name} among ${this.registeredComponents()}`\n );\n }\n\n return this.registry[name];\n },\n\n wrapperFactory() {\n return new WrapperFactory();\n },\n\n registeredComponents() {\n return Object.keys(this.registry).join(', ');\n },\n\n defaultWrapper(component, data = null, store = null, flattenData = false) {\n const factory = this.wrapperFactory();\n\n factory.with('i18n');\n if (store && component.store) {\n factory.with('store', store);\n }\n if (data && component.data) {\n factory.with('data', data, flattenData);\n }\n return factory.wrapper;\n },\n\n markup(\n name,\n { data = null, store = null, wrapper = null, flattenData = false }\n ) {\n const currentComponent = this.getComponent(name);\n const componentWrapper =\n wrapper ||\n this.defaultWrapper(currentComponent, data, store, flattenData);\n\n const WrappedComponent = componentWrapper(currentComponent.type);\n\n return ;\n },\n};\n\nconst coreComponets = [\n { name: 'ReactApp', type: ReactApp },\n { name: 'SearchBar', type: SearchBar },\n { name: 'AutoComplete', type: AutoComplete },\n { name: 'DonutChart', type: DonutChart },\n { name: 'LineChart', type: LineChart },\n { name: 'PowerStatus', type: PowerStatus },\n { name: 'NotificationContainer', type: NotificationContainer },\n { name: 'ToastNotifications', type: ToastsList },\n { name: 'StorageContainer', type: StorageContainer },\n { name: 'PasswordStrength', type: PasswordStrength },\n { name: 'BreadcrumbBar', type: BreadcrumbBar },\n { name: 'FactChart', type: FactChart },\n { name: 'Pagination', type: Pagination },\n { name: 'Layout', type: Layout },\n { name: 'EmptyState', type: EmptyState },\n { name: 'BarChart', type: BarChart },\n { name: 'ChartBox', type: ChartBox },\n { name: 'ComponentWrapper', type: ComponentWrapper },\n { name: 'ConfigReports', type: ConfigReports },\n { name: 'DiffModal', type: DiffModal },\n { name: 'ExternalLogout', type: ExternalLogout },\n { name: 'Slot', type: Slot },\n { name: 'TypeAheadSelect', type: TypeAheadSelect },\n { name: 'DatePicker', type: DatePicker },\n { name: 'RedirectCancelButton', type: RedirectCancelButton },\n { name: 'SettingRecords', type: SettingRecords },\n { name: 'SettingsTable', type: SettingsTable },\n { name: 'SettingUpdateModal', type: SettingUpdateModal },\n { name: 'PersonalAccessTokens', type: PersonalAccessTokens },\n { name: 'ClipboardCopy', type: ClipboardCopy },\n { name: 'LabelIcon', type: LabelIcon },\n {\n name: 'RelativeDateTime',\n type: RelativeDateTime,\n data: true,\n store: false,\n },\n {\n name: 'LongDateTime',\n type: LongDateTime,\n data: true,\n store: false,\n },\n {\n name: 'ShortDateTime',\n type: ShortDateTime,\n data: true,\n store: false,\n },\n {\n name: 'IsoDate',\n type: IsoDate,\n data: true,\n store: false,\n },\n { name: 'FormField', type: FormField },\n { name: 'InputFactory', type: InputFactory },\n { name: 'ModelsTable', type: ModelsTable },\n { name: 'Editor', type: Editor },\n\n // Report templates\n { name: 'TemplateGenerator', type: TemplateGenerator },\n { name: 'LoginPage', type: LoginPage },\n { name: 'WelcomeEnv', type: WelcomeEnv },\n { name: 'WelcomeAuthSource', type: WelcomeAuthSource },\n { name: 'WelcomeConfigReports', type: WelcomeConfigReports },\n { name: 'WelcomeArchitecture', type: WelcomeArchitecture },\n];\n\ncomponentRegistry.registerMultiple(coreComponets);\n\nexport default componentRegistry;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/componentRegistry.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { simpleLoader } from '../../common/Loader';\nimport './PowerStatus.scss';\n\nconst PowerStatus = ({ state, title }) =>\n state ? (\n \n ) : (\n simpleLoader('xs')\n );\n\nPowerStatus.propTypes = {\n state: PropTypes.string,\n title: PropTypes.string,\n};\n\nPowerStatus.defaultProps = {\n state: '',\n title: '',\n};\n\nexport default PowerStatus;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/hosts/powerStatus/PowerStatus.js","export const HOST_POWER_STATUS = 'HOST_POWER_STATUS';\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/hosts/powerStatus/PowerStatusConstants.js","import { createSelector } from 'reselect';\nimport {\n selectAPIErrorMessage,\n selectAPIResponse,\n} from '../../../redux/API/APISelectors';\n\nconst selectErrorMessage = (state, key) => selectAPIErrorMessage(state, key);\n\nconst selectStateFromAPI = (state, key) => selectAPIResponse(state, key).state;\n\nconst selectTitleFromAPI = (state, key) => selectAPIResponse(state, key).title;\n\nconst selectStatusText = (state, key) =>\n selectAPIResponse(state, key).statusText;\n\nexport const selectState = createSelector(\n selectStateFromAPI,\n selectErrorMessage,\n (state, error) => (error ? 'na' : state)\n);\n\nexport const selectTitle = createSelector(\n selectTitleFromAPI,\n selectErrorMessage,\n selectStatusText,\n (title, error, statusText) => {\n if (error) {\n let errorTitle = error;\n if (title || statusText) {\n errorTitle = `${title} ${statusText}`.trim();\n }\n return errorTitle;\n }\n return statusText || title;\n }\n);\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/hosts/powerStatus/PowerStatusSelectors.js","import React, { useEffect } from 'react';\nimport PropTypes from 'prop-types';\nimport { useSelector, useDispatch } from 'react-redux';\nimport PowerStatus from './PowerStatus';\nimport { get } from '../../../redux/API';\nimport { HOST_POWER_STATUS } from './PowerStatusConstants';\nimport { selectState, selectTitle } from './PowerStatusSelectors';\n\nconst ConnectedPowerStatus = ({ id, url }) => {\n const key = `${HOST_POWER_STATUS}_${id}`;\n const state = useSelector(store => selectState(store, key));\n const title = useSelector(store => selectTitle(store, key));\n const dispatch = useDispatch();\n\n useEffect(() => {\n dispatch(get({ key, url }));\n }, [url, key, dispatch]);\n\n return ;\n};\n\nConnectedPowerStatus.propTypes = {\n id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,\n url: PropTypes.string.isRequired,\n};\n\nexport default ConnectedPowerStatus;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/hosts/powerStatus/index.js","export const MaxDisksPerController = 15;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/hosts/storage/vmware/StorageContainer.consts.js","import React from 'react';\nimport { Button } from 'patternfly-react';\nimport PropTypes from 'prop-types';\nimport Select from '../../../../../common/forms/Select';\nimport Checkbox from '../../../../../common/forms/Checkbox';\nimport NumericInput from '../../../../../common/forms/NumericInput';\nimport { translate as __ } from '../../../../../../../react_app/common/I18n';\nimport { noop } from '../../../../../../common/helpers';\nimport './disk.scss';\n\nconst Disk = ({\n removeDisk,\n updateDisk,\n name,\n config: { diskModeTypes, vmExists },\n storagePod,\n datastore,\n sizeGb,\n thin,\n eagerZero,\n mode,\n datastores,\n datastoresStatus,\n datastoresError,\n storagePods,\n storagePodsStatus,\n storagePodsError,\n}) => {\n const updateStoragePod = newValues => {\n updateDisk('storagePod', newValues);\n updateDisk('datastore', { target: { value: null } });\n };\n const updateDatastore = newValues => {\n updateDisk('datastore', newValues);\n updateDisk('storagePod', { target: { value: null } });\n };\n\n return (\n \n
\n
\n
{name}
\n
\n {!vmExists && (\n \n )}\n
\n
\n {!(datastore && datastore.length) && (\n
\n );\n};\n\nDisk.propTypes = {\n config: PropTypes.shape({\n diskModeTypes: PropTypes.object,\n vmExists: PropTypes.bool,\n }).isRequired,\n name: PropTypes.string,\n storagePod: PropTypes.string,\n datastore: PropTypes.string,\n sizeGb: PropTypes.number,\n thin: PropTypes.bool,\n eagerZero: PropTypes.bool,\n mode: PropTypes.string,\n datastores: PropTypes.object,\n datastoresStatus: PropTypes.string,\n datastoresError: PropTypes.string,\n storagePods: PropTypes.object,\n storagePodsStatus: PropTypes.string,\n storagePodsError: PropTypes.string,\n removeDisk: PropTypes.func,\n updateDisk: PropTypes.func,\n};\n\nDisk.defaultProps = {\n name: '',\n storagePod: '',\n datastore: '',\n sizeGb: null,\n thin: false,\n eagerZero: false,\n mode: '',\n datastores: {},\n datastoresStatus: undefined,\n datastoresError: undefined,\n storagePods: {},\n storagePodsStatus: undefined,\n storagePodsError: undefined,\n removeDisk: noop,\n updateDisk: noop,\n};\n\nexport default Disk;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/hosts/storage/vmware/controller/disk/index.js","/* eslint-disable camelcase, no-mixed-operators, no-param-reassign */\nimport { Button } from 'patternfly-react';\nimport React from 'react';\nimport PropTypes from 'prop-types';\nimport { number_to_human_size } from 'number_helpers';\n\nimport Select from '../../../../common/forms/Select';\n\nimport Disk from './disk';\nimport {\n sprintf,\n translate as __,\n} from '../../../../../../react_app/common/I18n';\nimport { noop } from '../../../../../common/helpers';\nimport './controller.scss';\n\nconst Controller = ({\n addDiskEnabled,\n addDisk,\n removeDisk,\n updateController,\n updateDisk,\n controller,\n controllerVolumes,\n removeController,\n config,\n datastores,\n datastoresStatus,\n datastoresError,\n storagePods,\n storagePodsStatus,\n storagePodsError,\n}) => {\n const getEventValue = e => {\n if (!e || !e.target) {\n return e;\n }\n return e.target.type === 'checkbox' ? e.target.checked : e.target.value;\n };\n\n const _updateController = (attribute, e) => {\n updateController({ [attribute]: getEventValue(e) });\n };\n\n const _updateDisk = (uuid, attribute, e) => {\n updateDisk(uuid, { [attribute]: getEventValue(e) });\n };\n\n const humanSize = number => number_to_human_size(number, { precision: 2 });\n\n const datastoresStats = () => {\n if (!datastores.length) {\n return {};\n }\n return datastores.reduce((obj, d) => {\n obj[d.name] = sprintf(\n __('%(name)s (free: %(free)s, prov: %(prov)s, total: %(total)s)'),\n {\n name: d.name,\n free: humanSize(d.freespace),\n prov: humanSize(d.capacity + (d.uncommitted || 0) - d.freespace),\n total: humanSize(d.capacity),\n }\n );\n return obj;\n }, {});\n };\n\n const storagePodsStats = () => {\n if (!storagePods.length) {\n return {};\n }\n return storagePods.reduce((obj, s) => {\n obj[s.name] = sprintf(\n __('%(name)s (free: %(free)s, prov: %(prov)s, total: %(total)s)'),\n {\n name: s.name,\n free: humanSize(s.freespace),\n prov: humanSize(s.capacity - s.freespace),\n total: humanSize(s.capacity),\n }\n );\n return obj;\n }, {});\n };\n\n const disks = () =>\n controllerVolumes.map(disk => (\n _updateDisk(disk.key, attribute, e)}\n removeDisk={() => removeDisk(disk.key)}\n config={config}\n datastores={datastoresStats()}\n datastoresStatus={datastoresStatus}\n datastoresError={datastoresError}\n storagePods={storagePodsStats()}\n storagePodsStatus={storagePodsStatus}\n storagePodsError={storagePodsError}\n {...disk}\n />\n ));\n\n return (\n \n
\n
\n \n
\n
\n _updateController('type', e)}\n options={config.controllerTypes}\n />\n \n
\n
\n \n
\n
\n
{disks()}
\n
\n );\n};\n\nController.propTypes = {\n config: PropTypes.object.isRequired,\n controller: PropTypes.object.isRequired,\n addDiskEnabled: PropTypes.bool,\n controllerVolumes: PropTypes.array,\n datastores: PropTypes.arrayOf(\n PropTypes.exact({\n id: PropTypes.string,\n name: PropTypes.string,\n capacity: PropTypes.number,\n freespace: PropTypes.number,\n uncommitted: PropTypes.number,\n })\n ),\n datastoresStatus: PropTypes.string,\n datastoresError: PropTypes.string,\n storagePods: PropTypes.arrayOf(\n PropTypes.exact({\n id: PropTypes.string,\n name: PropTypes.string,\n capacity: PropTypes.number,\n freespace: PropTypes.number,\n })\n ),\n storagePodsStatus: PropTypes.string,\n storagePodsError: PropTypes.string,\n addDisk: PropTypes.func,\n removeDisk: PropTypes.func,\n updateController: PropTypes.func,\n updateDisk: PropTypes.func,\n removeController: PropTypes.func,\n};\n\nController.defaultProps = {\n addDiskEnabled: false,\n controllerVolumes: [],\n datastores: [],\n datastoresStatus: undefined,\n datastoresError: undefined,\n storagePods: [],\n storagePodsStatus: undefined,\n storagePodsError: undefined,\n addDisk: noop,\n removeDisk: noop,\n updateController: noop,\n updateDisk: noop,\n removeController: noop,\n};\n\nexport default Controller;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/hosts/storage/vmware/controller/index.js","import { pick } from 'lodash';\nimport React from 'react';\nimport { Alert, Button } from 'patternfly-react';\nimport { connect } from 'react-redux';\nimport PropTypes from 'prop-types';\n\nimport Controller from './controller/';\nimport * as VmWareActions from '../../../../redux/actions/hosts/storage/vmware';\nimport { MaxDisksPerController } from './StorageContainer.consts';\nimport { translate as __ } from '../../../../../react_app/common/I18n';\nimport { noop } from '../../../../common/helpers';\nimport AlertBody from '../../../common/Alert/AlertBody';\nimport './StorageContainer.scss';\nimport { STATUS } from '../../../../constants';\n\nconst filterKeyFromVolume = volume => {\n // eslint-disable-next-line no-unused-vars\n const { key, ...volumeWithoutKey } = volume;\n return volumeWithoutKey;\n};\n\nexport const controllersToJsonString = (controllers, volumes) =>\n JSON.stringify({\n scsiControllers: controllers,\n volumes: volumes.map(v => filterKeyFromVolume(v)),\n });\n\nclass StorageContainer extends React.Component {\n componentDidMount() {\n const {\n data: { config, controllers, volumes, cluster },\n initController,\n } = this.props;\n\n initController(config, cluster, controllers, volumes);\n }\n\n getDatastoresStatus() {\n const { datastoresLoading, datastoresError } = this.props;\n if (datastoresError) {\n return STATUS.ERROR;\n }\n if (datastoresLoading) {\n return STATUS.PENDING;\n }\n return STATUS.RESOLVED;\n }\n\n getStoragePodsStatus() {\n const { storagePodsLoading, storagePodsError } = this.props;\n if (storagePodsError) {\n return STATUS.ERROR;\n }\n if (storagePodsLoading) {\n return STATUS.PENDING;\n }\n return STATUS.RESOLVED;\n }\n\n renderControllers(controllers) {\n const {\n addDisk,\n updateController,\n removeDisk,\n updateDisk,\n removeController,\n config,\n volumes,\n datastores,\n datastoresError,\n storagePods,\n storagePodsError,\n } = this.props;\n\n return controllers.map((controller, idx) => {\n const controllerVolumes = volumes.filter(\n v => v.controllerKey === controller.key\n );\n\n return (\n removeController(controller.key)}\n controller={controller}\n controllerVolumes={controllerVolumes}\n addDiskEnabled={controllerVolumes.length < MaxDisksPerController}\n addDisk={() => addDisk(controller.key)}\n updateDisk={updateDisk}\n removeDisk={removeDisk}\n updateController={newValues => updateController(idx, newValues)}\n config={config}\n datastores={datastores}\n datastoresError={datastoresError}\n datastoresStatus={this.getDatastoresStatus()}\n storagePods={storagePods}\n storagePodsError={storagePodsError}\n storagePodsStatus={this.getStoragePodsStatus()}\n />\n );\n });\n }\n\n render() {\n const { addController, controllers, volumes, cluster, config } = this.props;\n const paramsScope = config && config.paramsScope;\n const enableAddControllerBtn =\n config && config.addControllerEnabled && !config.vmExists;\n\n if (!cluster) {\n return (\n \n \n \n );\n }\n\n return (\n \n
\n
{__('Storage')}
\n
\n \n
\n
\n
\n {this.renderControllers(controllers)}\n \n
\n
\n );\n }\n}\n\nStorageContainer.propTypes = {\n data: PropTypes.shape({\n config: PropTypes.object.isRequired,\n controllers: PropTypes.array.isRequired,\n volumes: PropTypes.array.isRequired,\n cluster: PropTypes.string,\n }).isRequired,\n controllers: PropTypes.array.isRequired,\n config: PropTypes.object,\n volumes: PropTypes.array,\n cluster: PropTypes.string,\n datastoresLoading: PropTypes.bool,\n datastores: PropTypes.arrayOf(\n PropTypes.shape({\n id: PropTypes.string,\n name: PropTypes.string,\n capacity: PropTypes.number,\n freespace: PropTypes.number,\n uncommitted: PropTypes.number,\n })\n ),\n datastoresError: PropTypes.string,\n storagePodsLoading: PropTypes.bool,\n storagePods: PropTypes.arrayOf(\n PropTypes.shape({\n id: PropTypes.string,\n name: PropTypes.string,\n capacity: PropTypes.number,\n freespace: PropTypes.number,\n })\n ),\n storagePodsError: PropTypes.string,\n addController: PropTypes.func,\n addDisk: PropTypes.func,\n updateController: PropTypes.func,\n removeDisk: PropTypes.func,\n updateDisk: PropTypes.func,\n removeController: PropTypes.func,\n initController: PropTypes.func,\n};\n\nStorageContainer.defaultProps = {\n config: {},\n cluster: '',\n volumes: [],\n datastoresLoading: false,\n storagePodsLoading: false,\n datastores: [],\n storagePods: [],\n datastoresError: undefined,\n storagePodsError: undefined,\n addController: noop,\n addDisk: noop,\n updateController: noop,\n removeDisk: noop,\n updateDisk: noop,\n removeController: noop,\n initController: noop,\n};\n\nconst mapStateToProps = state =>\n pick(state.hosts.storage.vmware, [\n 'controllers',\n 'config',\n 'cluster',\n 'volumes',\n 'datastores',\n 'datastoresLoading',\n 'datastoresError',\n 'storagePods',\n 'storagePodsLoading',\n 'storagePodsError',\n ]);\n\nexport default connect(mapStateToProps, VmWareActions)(StorageContainer);\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/hosts/storage/vmware/index.js","import { getValue, setValue } from '../../common/SessionStorage';\n\nexport const getIsOpened = () => getValue('isDrawerOpen');\nexport const setIsOpened = value => setValue('isDrawerOpen', value);\nexport const getExpandedGroup = () => getValue('expandedGroup');\nexport const setExpandedGroup = value => setValue('expandedGroup', value);\nexport const getHasUnreadMessages = () => getValue('hasUnreadMessages');\nexport const setHasUnreadMessages = value =>\n setValue('hasUnreadMessages', value);\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/notifications/NotificationDrawerSessionStorage.js","import React from 'react';\nimport { OverlayTrigger, Tooltip } from 'patternfly-react';\nimport PropTypes from 'prop-types';\nimport { noop } from '../../../common/helpers';\nimport { translate as __ } from '../../../common/I18n';\n\nconst ToggleIcon = ({ hasUnreadMessages, onClick }) => {\n const iconType = hasUnreadMessages ? 'fa-bell' : 'fa-bell-o';\n const tooltip = {__('Notifications')};\n\n return (\n \n \n \n );\n};\n\nToggleIcon.propTypes = {\n hasUnreadMessages: PropTypes.bool,\n onClick: PropTypes.func,\n};\n\nToggleIcon.defaultProps = {\n hasUnreadMessages: false,\n onClick: noop,\n};\n\nexport default ToggleIcon;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/notifications/ToggleIcon/ToggleIcon.js","import onClickOutside from 'react-onclickoutside';\nimport React from 'react';\nimport PropTypes from 'prop-types';\nimport { connect } from 'react-redux';\nimport { groupBy } from 'lodash';\nimport {\n NotificationDrawerWrapper,\n NotificationDrawerPanelWrapper,\n} from 'patternfly-react';\nimport * as NotificationActions from '../../redux/actions/notifications';\nimport { noop, translateObject } from '../../common/helpers';\n\nimport './notifications.scss';\nimport ToggleIcon from './ToggleIcon/ToggleIcon';\n\nclass notificationContainer extends React.Component {\n componentDidMount() {\n const {\n startNotificationsPolling,\n data: { url },\n } = this.props;\n\n startNotificationsPolling(url);\n }\n\n handleClickOutside() {\n const { isDrawerOpen, isReady, toggleDrawer } = this.props;\n\n if (isReady && isDrawerOpen) {\n toggleDrawer();\n }\n }\n\n componentWillUnmount() {\n const { stopNotificationsPolling } = this.props;\n stopNotificationsPolling();\n }\n\n render() {\n const {\n notifications,\n isDrawerOpen,\n toggleDrawer,\n expandGroup,\n expandedGroup,\n markAsRead,\n markGroupAsRead,\n clearNotification,\n clearGroup,\n hasUnreadMessages,\n isReady,\n clickedLink,\n translations,\n } = this.props;\n\n const notificationGroups = Object.entries(notifications).map(\n ([key, group]) => ({\n panelkey: key,\n panelName: key,\n notifications: group,\n })\n );\n\n return (\n \n \n {isReady && isDrawerOpen && (\n \n )}\n
\n );\n }\n}\n\nnotificationContainer.propTypes = {\n data: PropTypes.shape({\n url: PropTypes.string.isRequired,\n }).isRequired,\n isDrawerOpen: PropTypes.bool,\n isReady: PropTypes.bool,\n notifications: PropTypes.object,\n expandedGroup: PropTypes.string,\n hasUnreadMessages: PropTypes.bool,\n clickedLink: PropTypes.func,\n startNotificationsPolling: PropTypes.func,\n toggleDrawer: PropTypes.func,\n expandGroup: PropTypes.func,\n markAsRead: PropTypes.func,\n markGroupAsRead: PropTypes.func,\n clearNotification: PropTypes.func,\n clearGroup: PropTypes.func,\n stopNotificationsPolling: PropTypes.func,\n translations: PropTypes.shape({\n title: PropTypes.string,\n unreadEvent: PropTypes.string,\n unreadEvents: PropTypes.string,\n emptyState: PropTypes.string,\n readAll: PropTypes.string,\n clearAll: PropTypes.string,\n deleteNotification: PropTypes.string,\n }),\n};\n\nnotificationContainer.defaultProps = {\n isDrawerOpen: false,\n isReady: false,\n notifications: {},\n expandedGroup: null,\n hasUnreadMessages: false,\n clickedLink: noop,\n startNotificationsPolling: noop,\n toggleDrawer: noop,\n expandGroup: noop,\n markAsRead: noop,\n markGroupAsRead: noop,\n clearNotification: noop,\n clearGroup: noop,\n stopNotificationsPolling: noop,\n translations: NotificationDrawerPanelWrapper.defaultProps.translations,\n};\n\nconst mapStateToProps = state => {\n const {\n notifications,\n isDrawerOpen,\n expandedGroup,\n hasUnreadMessages,\n } = state.notifications;\n\n return {\n isDrawerOpen,\n notifications: groupBy(notifications, n => n.group),\n expandedGroup,\n isReady: !!notifications,\n hasUnreadMessages,\n };\n};\n\nexport default connect(\n mapStateToProps,\n NotificationActions\n)(onClickOutside(notificationContainer));\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/notifications/index.js","import React, { Fragment } from 'react';\nimport PropTypes from 'prop-types';\nimport { Alert } from 'patternfly-react';\nimport ClipboardCopy from '../../common/ClipboardCopy';\nimport { translate as __ } from '../../../common/I18n';\n\nconst NewTokenInfo = ({ newPersonalAccessToken, onDismiss }) => (\n \n {newPersonalAccessToken && (\n \n {__('Your New Personal Access Token')}\n \n {__(\n 'Make sure to copy your new personal access token now. You won’t be able to see it again!'\n )}\n \n )}\n \n);\n\nNewTokenInfo.propTypes = {\n onDismiss: PropTypes.func.isRequired,\n newPersonalAccessToken: PropTypes.string,\n};\n\nNewTokenInfo.defaultProps = {\n newPersonalAccessToken: null,\n};\n\nexport default NewTokenInfo;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/users/PersonalAccessTokens/NewPersonalAccessToken.js","import React from 'react';\nimport { useDispatch } from 'react-redux';\nimport PropTypes from 'prop-types';\nimport * as Yup from 'yup';\nimport { Button } from 'patternfly-react';\nimport UUID from 'uuid/v1';\nimport ForemanForm from '../../common/forms/ForemanForm';\nimport TextField from '../../common/forms/TextField';\nimport ForemanModal from '../../ForemanModal';\nimport { useForemanModal } from '../../ForemanModal/ForemanModalHooks';\nimport { maxLengthMsg, requiredMsg } from '../../common/forms/validators';\nimport { translate as __ } from '../../../common/I18n';\nimport { submitForm } from '../../../redux/actions/common/forms';\nimport DateTime from '../../common/forms/DateTime/DateTime';\nimport { MODAL_ID } from './PersonalAccessTokensConstants';\n\nconst tokenFormSchema = Yup.object().shape({\n name: Yup.string()\n .max(...maxLengthMsg(254))\n .required(requiredMsg()),\n expires_at: Yup.date().min(new Date(), __('Cannot be in the past')),\n});\n\nconst PersonalAccessTokenForm = ({ controller, url, initialValues }) => {\n const dispatch = useDispatch();\n const { setModalOpen, setModalClosed } = useForemanModal({\n id: MODAL_ID,\n });\n\n const handleSubmit = (values, actions) => {\n dispatch(\n submitForm({\n url,\n values: { ...values, controller },\n item: 'personal_access_token',\n message: __('Personal Access Token was successfully created.'),\n actions,\n successCallback: setModalClosed,\n })\n );\n };\n\n return (\n \n \n\n \n \n \n \n \n \n \n
\n );\n};\n\nPersonalAccessTokenForm.propTypes = {\n url: PropTypes.string.isRequired,\n initialValues: PropTypes.object,\n controller: PropTypes.string,\n};\nPersonalAccessTokenForm.defaultProps = {\n initialValues: {},\n controller: 'personal_access_tokens',\n};\n\nexport default PersonalAccessTokenForm;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/users/PersonalAccessTokens/PersonalAccessTokenForm.js","import React, { Fragment, useEffect } from 'react';\nimport { useDispatch, useSelector } from 'react-redux';\nimport { Icon } from 'patternfly-react';\nimport PropTypes from 'prop-types';\nimport {\n clearNewPersonalAccessToken,\n getPersonalAccessTokens,\n revokePersonalAccessToken as revokePersonalAccessTokenAction,\n} from './PersonalAccessTokensActions';\nimport {\n selectNewPersonalAccessToken,\n selectTokens,\n} from './PersonalAccessTokensSelectors';\nimport NewPersonalAccessToken from './NewPersonalAccessToken';\nimport PersonalAccessTokenForm from './PersonalAccessTokenForm';\nimport PersonalAccessTokensList from './PersonalAccessTokensList';\nimport { translate as __ } from '../../../common/I18n';\nimport { foremanUrl } from '../../../common/helpers';\n\nconst PersonalAccessTokens = ({ url, canCreate }) => {\n const dispatch = useDispatch();\n useEffect(() => {\n dispatch(getPersonalAccessTokens({ url }));\n }, [url, dispatch]);\n\n const newPersonalAccessToken = useSelector(state =>\n selectNewPersonalAccessToken(state)\n );\n const tokens = useSelector(state => selectTokens(state));\n\n const boundClearNewPersonalAccessToken = () =>\n dispatch(clearNewPersonalAccessToken());\n\n const boundRevokePersonalAccessToken = id =>\n dispatch(revokePersonalAccessTokenAction({ url, id }));\n\n return (\n \n \n {tokens.length > 0 ? (\n \n {canCreate && }\n token['active?'])}\n revokePersonalAccessToken={boundRevokePersonalAccessToken}\n revocable\n />\n !token['active?'])}\n />\n \n ) : (\n \n \n \n \n \n \n \n {__('Personal Access Tokens')}\n {__(\n 'Personal Access Tokens allow you to authenticate API requests without using your password, e.g. '\n )}\n \n {`curl -u admin:token ${foremanUrl(\n '/api/v2/hosts'\n )}`} \n \n {canCreate && }\n | \n
\n \n
\n )}\n \n );\n};\n\nPersonalAccessTokens.propTypes = {\n url: PropTypes.string.isRequired,\n canCreate: PropTypes.bool.isRequired,\n};\n\nexport default PersonalAccessTokens;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/users/PersonalAccessTokens/PersonalAccessTokens.js","import URI from 'urijs';\nimport { API } from '../../../redux/API';\nimport { addToast } from '../../../redux/actions/toasts';\nimport { ajaxRequestAction } from '../../../redux/actions/common';\nimport { translate as __ } from '../../../common/I18n';\nimport {\n PERSONAL_ACCESS_TOKEN_CLEAR,\n PERSONAL_ACCESS_TOKENS_REQUEST,\n PERSONAL_ACCESS_TOKENS_SUCCESS,\n PERSONAL_ACCESS_TOKENS_FAILURE,\n} from './PersonalAccessTokensConstants';\n\nexport const getPersonalAccessTokens = ({ url }) => dispatch => {\n const uri = new URI(url);\n // eslint-disable-next-line camelcase\n uri.setSearch({ per_page: 9999 });\n\n ajaxRequestAction({\n dispatch,\n url: uri,\n requestAction: PERSONAL_ACCESS_TOKENS_REQUEST,\n successAction: PERSONAL_ACCESS_TOKENS_SUCCESS,\n failedAction: PERSONAL_ACCESS_TOKENS_FAILURE,\n });\n};\n\nexport const revokePersonalAccessToken = ({ url, id }) => async dispatch => {\n try {\n await API.delete(`${url}/${id}`);\n dispatch(getPersonalAccessTokens({ url }));\n dispatch(\n addToast({\n type: 'success',\n message: __('Token was successfully revoked.'),\n })\n );\n } catch (error) {\n /* eslint-disable no-console */\n console.log(error);\n dispatch(\n addToast({\n type: 'error',\n message: __('Could not revoke Token: ') + error,\n })\n );\n }\n};\n\nexport const clearNewPersonalAccessToken = () => dispatch =>\n dispatch({\n type: PERSONAL_ACCESS_TOKEN_CLEAR,\n payload: {},\n });\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/users/PersonalAccessTokens/PersonalAccessTokensActions.js","export const PERSONAL_ACCESS_TOKENS_REQUEST = 'PERSONAL_ACCESS_TOKENS_REQUEST';\nexport const PERSONAL_ACCESS_TOKENS_SUCCESS = 'PERSONAL_ACCESS_TOKENS_SUCCESS';\nexport const PERSONAL_ACCESS_TOKENS_FAILURE = 'PERSONAL_ACCESS_TOKENS_FAILURE';\nexport const PERSONAL_ACCESS_TOKEN_FORM_SUBMITTED =\n 'PERSONAL_ACCESS_TOKEN_FORM_SUBMITTED';\nexport const PERSONAL_ACCESS_TOKEN_CLEAR = 'PERSONAL_ACCESS_TOKEN_CLEAR';\nexport const MODAL_ID = 'personal-access-tokens-form-modal';\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/users/PersonalAccessTokens/PersonalAccessTokensConstants.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { Button } from 'patternfly-react';\nimport RelativeDateTime from '../../../common/dates/RelativeDateTime';\nimport { translate as __ } from '../../../../common/I18n';\nimport { noop } from '../../../../common/helpers';\n\nconst PersonalAccessToken = ({\n revokePersonalAccessToken,\n id,\n name,\n created_at: createdAt,\n expires_at: expiresAt,\n last_used_at: lastUsedAt,\n user_id: userId,\n 'active?': isActive,\n 'revoked?': isRevoked,\n}) => (\n \n {name} | \n \n \n | \n \n {(isRevoked && __('Revoked')) || (!expiresAt && __('Never')) || (\n \n )}\n | \n {lastUsedAt ? : __('Never')} | \n \n {isActive && (\n \n )}\n | \n
\n);\n\nPersonalAccessToken.propTypes = {\n id: PropTypes.number.isRequired,\n user_id: PropTypes.number.isRequired,\n name: PropTypes.string.isRequired,\n created_at: PropTypes.string.isRequired,\n revokePersonalAccessToken: PropTypes.func,\n expires_at: PropTypes.string,\n last_used_at: PropTypes.string,\n 'active?': PropTypes.bool.isRequired,\n 'revoked?': PropTypes.bool.isRequired,\n};\n\nPersonalAccessToken.defaultProps = {\n revokePersonalAccessToken: noop,\n expires_at: null,\n last_used_at: null,\n};\n\nexport default PersonalAccessToken;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/users/PersonalAccessTokens/PersonalAccessTokensList/PersonalAccessToken.js","import React, { Fragment } from 'react';\nimport PropTypes from 'prop-types';\nimport PersonalAccessToken from './PersonalAccessToken';\nimport { translate as __ } from '../../../../common/I18n';\nimport { noop } from '../../../../common/helpers';\n\nconst PersonalAccessTokensList = ({\n title,\n tokens,\n revocable,\n revokePersonalAccessToken,\n}) => (\n \n {`${title} (${tokens.length})`}
\n {tokens.length > 0 && (\n \n \n \n {__('Name')} | \n {__('Created')} | \n {revocable ? __('Expires') : __('Expired')} | \n {__('Last Used')} | \n {__('Actions')} | \n
\n \n \n {tokens.map(token => (\n \n ))}\n \n
\n )}\n \n);\n\nPersonalAccessTokensList.propTypes = {\n tokens: PropTypes.array.isRequired,\n title: PropTypes.string,\n revokePersonalAccessToken: PropTypes.func,\n revocable: PropTypes.bool,\n};\n\nPersonalAccessTokensList.defaultProps = {\n revokePersonalAccessToken: noop,\n title: __('Personal Access Tokens'),\n revocable: false,\n};\n\nexport default PersonalAccessTokensList;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/users/PersonalAccessTokens/PersonalAccessTokensList/index.js","import Immutable from 'seamless-immutable';\nimport {\n PERSONAL_ACCESS_TOKENS_REQUEST,\n PERSONAL_ACCESS_TOKENS_SUCCESS,\n PERSONAL_ACCESS_TOKENS_FAILURE,\n PERSONAL_ACCESS_TOKEN_FORM_SUBMITTED,\n PERSONAL_ACCESS_TOKEN_CLEAR,\n} from './PersonalAccessTokensConstants';\n\nconst initialState = Immutable({ tokens: [] });\n\nexport default (state = initialState, { type, payload }) => {\n switch (type) {\n case PERSONAL_ACCESS_TOKENS_REQUEST:\n case PERSONAL_ACCESS_TOKENS_SUCCESS:\n return state.set('tokens', payload.results || []);\n case PERSONAL_ACCESS_TOKENS_FAILURE:\n return state.set(payload.id, { error: payload.error });\n case PERSONAL_ACCESS_TOKEN_FORM_SUBMITTED: {\n const { token_value: newPersonalAccessToken, ...token } = payload.data;\n\n return state\n .set('newPersonalAccessToken', newPersonalAccessToken)\n .set('tokens', [...state.tokens, token]);\n }\n case PERSONAL_ACCESS_TOKEN_CLEAR:\n return state.set('newPersonalAccessToken', null);\n default: {\n return state;\n }\n }\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/users/PersonalAccessTokens/PersonalAccessTokensReducer.js","export const selectNewPersonalAccessToken = state =>\n state.personalAccessTokens.newPersonalAccessToken;\n\nexport const selectTokens = state => state.personalAccessTokens.tokens;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/users/PersonalAccessTokens/PersonalAccessTokensSelectors.js","import PersonalAccessTokens from './PersonalAccessTokens';\nimport reducer from './PersonalAccessTokensReducer';\n\nexport const reducers = { personalAccessTokens: reducer };\n\nexport default PersonalAccessTokens;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/users/PersonalAccessTokens/index.js","import React from 'react';\nimport { Provider } from 'react-redux';\nimport { i18nProviderWrapperFactory } from '../common/i18nProviderWrapperFactory';\nimport { getDisplayName } from '../common/helpers';\n\nconst storeProviderWrapperFactory = store => WrappedComponent => {\n const StoreProvider = props => (\n \n \n \n );\n StoreProvider.displayName = `StoreProvider(${getDisplayName(\n WrappedComponent\n )})`;\n\n return StoreProvider;\n};\n\nconst dataProviderWrapperFactory = (\n data,\n flattenData = false\n) => WrappedComponent => {\n const DataProvider = props => {\n if (flattenData) {\n return ;\n }\n return ;\n };\n DataProvider.displayName = `DataProvider(${getDisplayName(\n WrappedComponent\n )})`;\n\n return DataProvider;\n};\n\nconst propDataMapperWrapperFactory = () => WrappedComponent => {\n const PropDataMapper = props => ;\n PropDataMapper.displayName = `PropDataMapper(${getDisplayName(\n WrappedComponent\n )})`;\n\n return PropDataMapper;\n};\n\nexport const wrapperRegistry = {\n wrappers: {\n data: dataProviderWrapperFactory,\n dataMapper: propDataMapperWrapperFactory,\n store: storeProviderWrapperFactory,\n i18n: i18nProviderWrapperFactory,\n },\n register(name, wrapper) {\n if (this.wrappers[name]) {\n throw new Error(`Wrapper name already taken: ${name}`);\n }\n\n this.wrappers[name] = wrapper;\n },\n getWrapper(name) {\n if (!this.wrappers[name]) {\n throw new Error(`Wrapper not found: ${name}`);\n }\n\n return this.wrappers[name];\n },\n};\n\nexport class WrapperFactory {\n constructor() {\n this.wrapper = component => component;\n }\n\n with(name, ...params) {\n const currentWrapper = this.wrapper;\n const additionalWrapperFactory = wrapperRegistry.getWrapper(name);\n const additionalWrapper = additionalWrapperFactory(...params);\n\n this.wrapper = component => additionalWrapper(currentWrapper(component));\n\n return this;\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/wrapperFactory.js","export const STATUS = {\n PENDING: 'PENDING',\n RESOLVED: 'RESOLVED',\n ERROR: 'ERROR',\n};\n\nexport const getControllerSearchProps = (\n controller,\n id = 'searchBar',\n canCreate = true\n) => ({\n controller,\n autocomplete: {\n id,\n searchQuery: '',\n url: `${controller}/auto_complete_search`,\n useKeyShortcuts: true,\n },\n bookmarks: {\n url: '/api/bookmarks',\n canCreate,\n documentationUrl: `4.1.5Searching`,\n },\n});\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/constants.js","import { createBrowserHistory } from 'history';\nimport forceSingleton from '../react_app/common/forceSingleton';\n\nconst history = forceSingleton('history', () => createBrowserHistory());\nexport default history;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/history.js","import axios from 'axios';\nimport './APITestSetup';\nimport { foremanUrl } from '../../../foreman_tools';\n\nconst getcsrfToken = () => {\n const token = document.querySelector('meta[name=\"csrf-token\"]');\n\n return token ? token.content : '';\n};\n\naxios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';\naxios.defaults.headers.common['X-CSRF-Token'] = getcsrfToken();\n\nexport default {\n get(url, headers = {}, params = {}) {\n return axios.get(foremanUrl(url), {\n headers,\n params,\n });\n },\n put(url, data = {}, headers = {}) {\n return axios.put(foremanUrl(url), data, {\n headers,\n });\n },\n post(url, data = {}, headers = {}) {\n return axios.post(foremanUrl(url), data, {\n headers,\n });\n },\n delete(url, headers = {}) {\n return axios.delete(foremanUrl(url), {\n headers,\n });\n },\n patch(url, data = {}, headers = {}) {\n return axios.patch(foremanUrl(url), data, {\n headers,\n });\n },\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/redux/API/API.js","const actions = ['REQUEST', 'SUCCESS', 'FAILURE'];\n\n/**\n * Auto generates api consts for redux for given key\n * @param {String} key - the unique name of the component\n * @param {Object} actionTypes - custom types to use instead of the auto generated ones\n */\nexport const actionTypeGenerator = (key, actionTypes = {}) => {\n actions.forEach(type => {\n actionTypes[type] = actionTypes[type] || `${key}_${type}`;\n });\n return actionTypes;\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/redux/API/APIActionTypeGenerator.js","import { API_OPERATIONS } from './APIConstants';\n\nconst { GET, POST, PUT, DELETE, PATCH } = API_OPERATIONS;\n\n/**\n * an API action creator.\n * @param { String } type the API action type.\n * @param { Object } payload the API action payload.\n * @param { String } payload.key the unique key of the API request, will be used in the selector too.\n * @param { String } payload.url the url for the API request.\n * @param { String } payload.headers the API get request headers.\n * @param { Object } payload.params the API get request params.\n * @param { Function } payload.handleError an error handling callback.\n * @param { Function } payload.handleSuccess a success handling callback.\n * @param { Function } payload.errorToast an error toast will be triggered with this message after API error.\n * @param { Function } payload.successToast a succes toast will be triggered with this message after API success.\n * @param { Object } payload.payload the API payload which will be passed also to the reducer.\n * @param { Object } payload.actionTypes action types which will replace the default action types.\n */\nexport const apiAction = (type, payload) => ({ type, payload });\n\nexport const get = payload => apiAction(GET, payload);\n\nexport const post = payload => apiAction(POST, payload);\n\nexport const put = payload => apiAction(PUT, payload);\n\nexport const patch = payload => apiAction(PATCH, payload);\n\nexport const APIActions = {\n get,\n post,\n put,\n patch,\n delete: payload => apiAction(DELETE, payload),\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/redux/API/APIActions.js","export const API_OPERATIONS = {\n GET: 'API_GET',\n POST: 'API_POST',\n PUT: 'API_PUT',\n DELETE: 'API_DELETE',\n PATCH: 'API_PATCH',\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/redux/API/APIConstants.js","import { API_OPERATIONS } from './APIConstants';\nimport { API } from './';\n\nexport const getApiMethodByActionType = type => type.substring(4).toLowerCase();\n\nexport const getApiResponse = async ({ type, url, headers, params }) => {\n const method = getApiMethodByActionType(type);\n switch (method) {\n case 'get':\n return API[method](url, headers, params);\n case 'delete':\n return API[method](url, headers);\n default:\n return API[method](url, params, headers);\n }\n};\n\nexport const isAPIAction = ({ type }) =>\n Object.values(API_OPERATIONS).includes(type);\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/redux/API/APIHelpers.js","import { apiRequest } from './APIRequest';\nimport { isAPIAction } from './APIHelpers';\n\nexport const APIMiddleware = store => next => action => {\n if (isAPIAction(action)) {\n apiRequest(action, store);\n }\n return next(action);\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/redux/API/APIMiddleware.js","import Immutable from 'seamless-immutable';\nimport { actionTypeGenerator } from './APIActionTypeGenerator';\nimport { STATUS } from '../../constants';\n\nconst initialState = Immutable({});\n\nconst apiReducer = (state = initialState, { type, key, payload, response }) => {\n if (key === undefined) return state;\n\n const { REQUEST, SUCCESS, FAILURE } = actionTypeGenerator(key);\n const { PENDING, RESOLVED, ERROR } = STATUS;\n\n switch (type) {\n case REQUEST:\n return state.merge({\n [key]: {\n response: null,\n ...state[key],\n payload,\n status: PENDING,\n },\n });\n case SUCCESS:\n return state.merge({\n [key]: {\n payload,\n response,\n status: RESOLVED,\n },\n });\n case FAILURE:\n return state.merge({\n [key]: {\n payload,\n response,\n status: ERROR,\n },\n });\n default:\n return state;\n }\n};\n\nexport default apiReducer;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/redux/API/APIReducer.js","/* eslint-disable no-console */\nimport { getApiResponse } from './APIHelpers';\nimport { actionTypeGenerator } from './APIActionTypeGenerator';\nimport { noop } from '../../common/helpers';\nimport { stopInterval } from '../middlewares/IntervalMiddleware';\nimport { selectDoesIntervalExist } from '../middlewares/IntervalMiddleware/IntervalSelectors';\nimport { addToast } from '../actions/toasts';\n\nexport const apiRequest = async (\n {\n type,\n payload: {\n key,\n url,\n headers = {},\n params = {},\n actionTypes = {},\n handleError = noop,\n handleSuccess = noop,\n successToast,\n errorToast,\n payload = {},\n },\n },\n { dispatch, getState }\n) => {\n const { REQUEST, SUCCESS, FAILURE } = actionTypeGenerator(key, actionTypes);\n const modifiedPayload = { ...payload, url };\n const stopIntervalCallback = selectDoesIntervalExist(getState(), key)\n ? () => dispatch(stopInterval(key))\n : () => console.warn(`There's no interval API request for the key: ${key}`);\n\n dispatch({\n type: REQUEST,\n key,\n payload: modifiedPayload,\n });\n\n try {\n const response = await getApiResponse({ type, url, headers, params });\n\n dispatch({\n type: SUCCESS,\n key,\n payload: modifiedPayload,\n response: response.data,\n });\n\n successToast &&\n dispatch(\n addToast({\n type: 'success',\n message: successToast(response),\n key: SUCCESS,\n })\n );\n\n handleSuccess(response, stopIntervalCallback);\n } catch (error) {\n dispatch({\n type: FAILURE,\n key,\n payload: modifiedPayload,\n response: error,\n });\n\n errorToast &&\n dispatch(\n addToast({ type: 'error', message: errorToast(error), key: FAILURE })\n );\n\n handleError(error, stopIntervalCallback);\n }\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/redux/API/APIRequest.js","import { STATUS } from '../../constants';\n\nexport const selectAPI = state => state.API;\n\nexport const selectAPIByKey = (state, key) => selectAPI(state)[key] || {};\n\nexport const selectAPIStatus = (state, key) =>\n selectAPIByKey(state, key).status;\n\nexport const selectAPIPayload = (state, key) =>\n selectAPIByKey(state, key).payload || {};\n\nexport const selectAPIResponse = (state, key) =>\n selectAPIByKey(state, key).response || {};\n\nexport const selectAPIError = (state, key) =>\n selectAPIStatus(state, key) === STATUS.ERROR\n ? selectAPIResponse(state, key)\n : null;\n\nexport const selectAPIErrorMessage = (state, key) => {\n const error = selectAPIError(state, key);\n return error && error.message;\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/redux/API/APISelectors.js","import axios from 'axios';\n\n// a counter for active requests, like jQuery.active\nwindow.axiosActive = 0;\n\naxios.interceptors.request.use(config => {\n window.axiosActive += 1;\n return config;\n});\n\naxios.interceptors.response.use(response => {\n window.axiosActive -= 1;\n return response;\n});\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/redux/API/APITestSetup.js","import apiReducer from './APIReducer';\n\nexport const reducers = { API: apiReducer };\n\nexport { actionTypeGenerator } from './APIActionTypeGenerator';\nexport { API_OPERATIONS } from './APIConstants';\nexport { APIMiddleware } from './APIMiddleware';\nexport { default as API } from './API';\nexport * from './APIActions';\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/redux/API/index.js","import { APIActions } from '../../API';\nimport { sprintf, translate as __ } from '../../../../react_app/common/I18n';\n\nconst getBaseErrors = ({ error: { errors, severity } }) => {\n let _error;\n if (errors.base) {\n _error = {};\n _error.errorMsgs = errors.base;\n _error.severity = severity;\n delete errors.base;\n }\n\n return _error;\n};\n\nexport const prepareErrors = (errors, base) =>\n Object.keys(errors).reduce(\n (memo, key) => {\n const errorMessages = errors[key];\n\n memo[key] =\n errorMessages && errorMessages.join\n ? errorMessages.join(', ')\n : errorMessages;\n return memo;\n },\n { _error: base }\n );\n\nexport const onError = (error, actions) => {\n actions.setSubmitting(false);\n if (error.response.status === 422) {\n const base = getBaseErrors(error?.response?.data);\n\n actions.setErrors(\n prepareErrors(error?.response?.data?.error?.errors, base)\n );\n } else {\n actions.setErrors({\n _error: {\n errorMsgs: [\n `${__('Error submitting data:')} ${error.response.status} ${__(\n error.response.statusText\n )}`,\n ],\n },\n });\n }\n};\n\nconst verifyProps = (item, values) => {\n if (!item) {\n throw new Error('item must be defined, e.g. Bookmark');\n }\n if (!values) {\n throw new Error('values must be defined');\n }\n};\n\nexport const submitForm = ({\n item,\n url,\n values: params,\n message,\n method = 'post',\n headers,\n apiActionTypes: actionTypes,\n errorToast,\n successToast,\n actions,\n successCallback,\n}) => {\n verifyProps(item, params);\n return dispatch => {\n const uniqueAPIKey = `${item.toUpperCase()}_FORM_SUBMITTED`;\n\n const handleError = error => onError(error, actions);\n\n const handleSuccess = ({ data }) => {\n successCallback();\n dispatch({\n type: uniqueAPIKey,\n payload: { item, data },\n });\n };\n const defaultSuccessToast = () =>\n message || sprintf('%s was successfully created.', __(item));\n\n const defaultErrorToast = error =>\n sprintf(\n __(\n 'Oh no! Something went wrong while submitting the form, the server returned the following error: %s'\n ),\n // eslint-disable-next-line camelcase\n error?.response?.data?.error?.full_messages?.join(', ')\n );\n dispatch(\n APIActions[method]({\n key: uniqueAPIKey,\n url,\n headers,\n params,\n actionTypes,\n handleError,\n handleSuccess,\n successToast: successToast || defaultSuccessToast,\n errorToast: errorToast || defaultErrorToast,\n })\n );\n };\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/redux/actions/common/forms.js","import { API } from '../../../redux/API';\n\nexport const ajaxRequestAction = async ({\n dispatch,\n requestAction,\n successAction,\n failedAction,\n url,\n item = {},\n}) => {\n dispatch({ type: requestAction, payload: item });\n try {\n const { data } = await API.get(url, item.headers || {}, item.params || {});\n return dispatch({ type: successAction, payload: { ...item, ...data } });\n } catch (error) {\n return dispatch({ type: failedAction, payload: { error, item } });\n }\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/redux/actions/common/index.js","import { translate as __ } from '../../../../../react_app/common/I18n';\n\nexport const defaultControllerAttributes = {\n type: 'ParaVirtualSCSIController',\n};\n\nconst _defaultDiskAttributes = {\n sizeGb: 10,\n datastore: '',\n storagePod: '',\n thin: false,\n eagerZero: false,\n name: __('Hard disk'),\n mode: 'persistent',\n};\n\nexport const getDefaultDiskAttributes = _defaultDiskAttributes;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/redux/actions/hosts/storage/vmware.consts.js","import {\n VMWARE_CLUSTER_CHANGE,\n STORAGE_VMWARE_ADD_CONTROLLER,\n STORAGE_VMWARE_ADD_DISK,\n STORAGE_VMWARE_REMOVE_CONTROLLER,\n STORAGE_VMWARE_UPDATE_CONTROLLER,\n STORAGE_VMWARE_REMOVE_DISK,\n STORAGE_VMWARE_UPDATE_DISK,\n STORAGE_VMWARE_INIT,\n STORAGE_VMWARE_DATASTORES,\n STORAGE_VMWARE_STORAGEPODS,\n} from '../../../consts';\nimport { get } from '../../../API';\nimport {\n defaultControllerAttributes,\n getDefaultDiskAttributes,\n} from './vmware.consts';\n\nexport const updateDisk = (key, newValues) => ({\n type: STORAGE_VMWARE_UPDATE_DISK,\n payload: {\n key,\n newValues,\n },\n});\n\nexport const initController = (\n config,\n cluster,\n controllers,\n volumes\n) => dispatch => {\n dispatch({\n type: STORAGE_VMWARE_INIT,\n payload: {\n config,\n controllers: controllers || defaultControllerAttributes,\n volumes: volumes || getDefaultDiskAttributes,\n cluster,\n },\n });\n if (cluster) {\n dispatch(fetchDatastores(config.datastoresUrl, cluster));\n dispatch(fetchStoragePods(config.storagePodsUrl, cluster));\n }\n};\n\nexport const changeCluster = newCluster => (dispatch, getState) => {\n const { config } = getState().hosts.storage.vmware;\n if (newCluster === '') newCluster = null;\n\n dispatch({\n type: VMWARE_CLUSTER_CHANGE,\n payload: {\n cluster: newCluster,\n },\n });\n if (newCluster) {\n dispatch(fetchDatastores(config.datastoresUrl, newCluster));\n dispatch(fetchStoragePods(config.storagePodsUrl, newCluster));\n }\n};\n\nconst fetchStorages = (url, cluster, key) =>\n get({\n key,\n url,\n payload: { params: { cluster_id: cluster } },\n });\n\nexport const fetchDatastores = (url, cluster) =>\n fetchStorages(url, cluster, STORAGE_VMWARE_DATASTORES);\n\nexport const fetchStoragePods = (url, cluster) =>\n fetchStorages(url, cluster, STORAGE_VMWARE_STORAGEPODS);\n\nexport const addController = data => ({\n type: STORAGE_VMWARE_ADD_CONTROLLER,\n payload: {\n controller: defaultControllerAttributes,\n volume: getDefaultDiskAttributes,\n },\n});\n\nexport const updateController = (idx, newValues) => ({\n type: STORAGE_VMWARE_UPDATE_CONTROLLER,\n payload: {\n idx,\n newValues,\n },\n});\n\nexport const removeDisk = key => ({\n type: STORAGE_VMWARE_REMOVE_DISK,\n payload: {\n key,\n },\n});\n\nexport const removeController = controllerKey => ({\n type: STORAGE_VMWARE_REMOVE_CONTROLLER,\n payload: { controllerKey },\n});\n\nexport const addDisk = controllerKey => ({\n type: STORAGE_VMWARE_ADD_DISK,\n payload: {\n controllerKey,\n data: getDefaultDiskAttributes,\n },\n});\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/redux/actions/hosts/storage/vmware.js","export const DEFAULT_INTERVAL = 10000;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/redux/actions/notifications/constants.js","import {\n NOTIFICATIONS,\n NOTIFICATIONS_TOGGLE_DRAWER,\n NOTIFICATIONS_SET_EXPANDED_GROUP,\n NOTIFICATIONS_MARK_AS_READ,\n NOTIFICATIONS_MARK_GROUP_AS_READ,\n NOTIFICATIONS_MARK_AS_CLEAR,\n NOTIFICATIONS_MARK_GROUP_AS_CLEARED,\n NOTIFICATIONS_LINK_CLICKED,\n} from '../../consts';\nimport * as sessionStorage from '../../../components/notifications/NotificationDrawerSessionStorage';\nimport { API, get } from '../../API';\nimport { reloadPage } from '../../../../foreman_navigation';\nimport {\n stopInterval,\n withInterval,\n} from '../../middlewares/IntervalMiddleware';\nimport { DEFAULT_INTERVAL } from './constants';\n\nconst interval = process.env.NOTIFICATIONS_POLLING || DEFAULT_INTERVAL;\n\nconst handleNotificationPollingError = (error, stopNotificationPolling) => {\n if (error.response?.status === 401) {\n stopNotificationPolling();\n reloadPage();\n }\n};\n\nexport const startNotificationsPolling = url =>\n withInterval(\n get({\n key: NOTIFICATIONS,\n url,\n handleError: handleNotificationPollingError,\n }),\n interval\n );\n\nexport const stopNotificationsPolling = () => stopInterval(NOTIFICATIONS);\n\nexport const markAsRead = (group, id) => dispatch => {\n dispatch({\n type: NOTIFICATIONS_MARK_AS_READ,\n payload: {\n group,\n id,\n },\n });\n const url = `/notification_recipients/${id}`;\n const data = { seen: true };\n API.put(url, data);\n};\n\nexport const markGroupAsRead = group => dispatch => {\n dispatch({\n type: NOTIFICATIONS_MARK_GROUP_AS_READ,\n payload: {\n group,\n },\n });\n const url = `/notification_recipients/group/${group}`;\n API.put(url);\n};\n\nexport const clearNotification = (group, id) => dispatch => {\n dispatch({\n type: NOTIFICATIONS_MARK_AS_CLEAR,\n payload: {\n group,\n id,\n },\n });\n const url = `/notification_recipients/${id}`;\n API.delete(url);\n};\n\nexport const clearGroup = group => dispatch => {\n dispatch({\n type: NOTIFICATIONS_MARK_GROUP_AS_CLEARED,\n payload: {\n group,\n },\n });\n const url = `/notification_recipients/group/${group}`;\n API.delete(url);\n};\n\nexport const expandGroup = group => (dispatch, getState) => {\n const currentExpanded = getState().notifications.expandedGroup;\n\n const getNewExpandedGroup = () => (currentExpanded === group ? '' : group);\n\n sessionStorage.setExpandedGroup(getNewExpandedGroup());\n dispatch({\n type: NOTIFICATIONS_SET_EXPANDED_GROUP,\n payload: {\n group: getNewExpandedGroup(),\n },\n });\n};\n\nexport const toggleDrawer = () => (dispatch, getState) => {\n const isDrawerOpened = getState().notifications.isDrawerOpen;\n\n sessionStorage.setIsOpened(!isDrawerOpened);\n dispatch({\n type: NOTIFICATIONS_TOGGLE_DRAWER,\n payload: {\n value: !isDrawerOpened,\n },\n });\n};\n\nexport const clickedLink = (\n { href, external = false },\n toggleDrawerAction = toggleDrawer\n) => dispatch => {\n dispatch(toggleDrawerAction());\n\n const openedWindow = window.open(href, external ? '_blank' : '_self');\n\n if (external) {\n openedWindow.opener = null;\n }\n\n dispatch({\n type: NOTIFICATIONS_LINK_CLICKED,\n payload: { href, external },\n });\n\n return openedWindow;\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/redux/actions/notifications/index.js","import uuidV1 from 'uuid/v1';\n\nimport { TOASTS_ADD, TOASTS_DELETE, TOASTS_CLEAR } from '../../consts';\n\nexport const addToast = toast => {\n const key = toast.key || uuidV1();\n\n return {\n type: TOASTS_ADD,\n payload: {\n key,\n message: { ...toast, key },\n },\n };\n};\n\nexport const deleteToast = key => ({\n type: TOASTS_DELETE,\n payload: { key },\n});\n\nexport const clearToasts = () => ({ type: TOASTS_CLEAR });\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/redux/actions/toasts/index.js","export const TOASTS_ADD = 'TOASTS_ADD';\nexport const TOASTS_CLEAR = 'TOASTS_CLEAR';\nexport const TOASTS_DELETE = 'TOASTS_DELETE';\nexport const VMWARE_CLUSTER_CHANGE = 'VMWARE_CLUSTER_CHANGE';\nexport const STORAGE_VMWARE_INIT = 'STORAGE_VMWARE_INIT';\nexport const STORAGE_VMWARE_ADD_CONTROLLER = 'STORAGE_VMWARE_ADD_CONTROLLER';\nexport const STORAGE_VMWARE_ADD_DISK = 'STORAGE_VMWARE_ADD_DISK';\nexport const STORAGE_VMWARE_REMOVE_CONTROLLER =\n 'STORAGE_VMWARE_REMOVE_CONTROLLER';\nexport const STORAGE_VMWARE_UPDATE_CONTROLLER =\n 'STORAGE_VMWARE_UPDATE_CONTROLLER';\nexport const STORAGE_VMWARE_REMOVE_DISK = 'STORAGE_VMWARE_REMOVE_DISK';\nexport const STORAGE_VMWARE_UPDATE_DISK = 'STORAGE_VMWARE_UPDATE_DISK';\nexport const NOTIFICATIONS = 'NOTIFICATIONS';\nexport const STORAGE_VMWARE_DATASTORES = 'STORAGE_VMWARE_DATASTORES';\nexport const STORAGE_VMWARE_DATASTORES_REQUEST =\n 'STORAGE_VMWARE_DATASTORES_REQUEST';\nexport const STORAGE_VMWARE_DATASTORES_SUCCESS =\n 'STORAGE_VMWARE_DATASTORES_SUCCESS';\nexport const STORAGE_VMWARE_DATASTORES_FAILURE =\n 'STORAGE_VMWARE_DATASTORES_FAILURE';\nexport const STORAGE_VMWARE_STORAGEPODS = 'STORAGE_VMWARE_STORAGEPODS';\nexport const STORAGE_VMWARE_STORAGEPODS_REQUEST =\n 'STORAGE_VMWARE_STORAGEPODS_REQUEST';\nexport const STORAGE_VMWARE_STORAGEPODS_SUCCESS =\n 'STORAGE_VMWARE_STORAGEPODS_SUCCESS';\nexport const STORAGE_VMWARE_STORAGEPODS_FAILURE =\n 'STORAGE_VMWARE_STORAGEPODS_FAILURE';\nexport const NOTIFICATIONS_TOGGLE_DRAWER = 'NOTIFICATIONS_TOGGLE_DRAWER';\nexport const NOTIFICATIONS_SET_EXPANDED_GROUP =\n 'NOTIFICATIONS_SET_EXPANDED_GROUP';\nexport const NOTIFICATIONS_MARK_AS_READ = 'NOTIFICATIONS_MARK_AS_READ';\nexport const NOTIFICATIONS_MARK_GROUP_AS_READ =\n 'NOTIFICATIONS_MARK_GROUP_AS_READ';\nexport const NOTIFICATIONS_MARK_AS_CLEAR = 'NOTIFICATIONS_MARK_AS_CLEAR';\nexport const NOTIFICATIONS_MARK_GROUP_AS_CLEARED =\n 'NOTIFICATIONS_MARK_GROUP_AS_CLEARED';\nexport const NOTIFICATIONS_LINK_CLICKED = 'NOTIFICATIONS_LINK_CLICKED';\nexport const PASSWORD_STRENGTH_PASSWORD_CHANGED =\n 'PASSWORD_STRENGTH_PASSWORD_CHANGED';\nexport const PASSWORD_STRENGTH_PASSWORD_MATCHED =\n 'PASSWORD_STRENGTH_PASSWORD_MATCHED';\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/redux/consts.js","import { applyMiddleware, createStore, compose } from 'redux';\nimport forceSingleton from '../common/forceSingleton';\n\nimport reducers from './reducers';\nimport { middlewares } from './middlewares';\n\nconst composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;\n\nexport const generateStore = () =>\n createStore(reducers, composeEnhancers(applyMiddleware(...middlewares)));\n\nconst store = forceSingleton('redux_store', generateStore);\n\nexport default store;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/redux/index.js","import { STOP_INTERVAL, START_INTERVAL } from './IntervalConstants';\n\nexport const stopInterval = key => ({\n type: STOP_INTERVAL,\n key,\n});\n\nexport const startInterval = (key, intervalID) => ({\n type: START_INTERVAL,\n key,\n intervalID,\n});\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/redux/middlewares/IntervalMiddleware/IntervalActions.js","export const START_INTERVAL = 'START_INTERVAL';\nexport const STOP_INTERVAL = 'STOP_INTERVAL';\nexport const DEFAULT_INTERVAL = 5000;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/redux/middlewares/IntervalMiddleware/IntervalConstants.js","import { DEFAULT_INTERVAL } from './IntervalConstants';\n\nexport const registeredIntervalException = key =>\n new Error(`There is already an interval running and registered for: ${key}.`);\n\nexport const withInterval = (action, interval = getDefaultInterval()) => ({\n ...action,\n interval,\n});\n\nexport const getDefaultInterval = () =>\n process.env.DEFAULT_INTERVAL || DEFAULT_INTERVAL;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/redux/middlewares/IntervalMiddleware/IntervalHelpers.js","import { omit } from 'lodash';\nimport { STOP_INTERVAL } from './IntervalConstants';\nimport { selectDoesIntervalExist, selectIntervalID } from './IntervalSelectors';\nimport {\n registeredIntervalException,\n getDefaultInterval,\n} from './IntervalHelpers';\nimport { startInterval as startIntervalAction } from './IntervalActions';\nimport { whenDocumentIsVisible } from '../common/helpers';\n\nexport const IntervalMiddleware = store => next => action => {\n const { type, key, interval, payload = {} } = action;\n const intervalKey = key || payload.key;\n\n if (interval) {\n if (selectDoesIntervalExist(store.getState(), intervalKey)) {\n throw registeredIntervalException(intervalKey);\n }\n\n // To avoid the action from getting into an endless loop in this middleware.\n const modifiedAction = omit(action, ['interval']);\n const dispatchModifiedAction = () => store.dispatch(modifiedAction);\n\n dispatchModifiedAction(); // force the action to run for the first time.\n const delay =\n typeof interval === 'number' ? interval : getDefaultInterval();\n const intervalFunc = () => whenDocumentIsVisible(dispatchModifiedAction);\n const intervalID = setInterval(intervalFunc, delay);\n return store.dispatch(startIntervalAction(intervalKey, intervalID));\n }\n\n if (type === STOP_INTERVAL) {\n const state = store.getState();\n const intervalID = selectIntervalID(state, intervalKey);\n intervalID && clearInterval(intervalID);\n }\n\n return next(action);\n};\n\nexport default IntervalMiddleware;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/redux/middlewares/IntervalMiddleware/IntervalMiddleware.js","import Immutable from 'seamless-immutable';\nimport { START_INTERVAL, STOP_INTERVAL } from './IntervalConstants';\n\nconst initialState = Immutable({});\n\nexport const reducer = (state = initialState, action) => {\n const { type, key, intervalID } = action;\n switch (type) {\n case START_INTERVAL:\n return state.merge({ [key]: intervalID });\n case STOP_INTERVAL:\n return state.without(key);\n default:\n return state;\n }\n};\n\nexport const reducers = { intervals: reducer };\n\nexport default reducer;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/redux/middlewares/IntervalMiddleware/IntervalReducer.js","export const selectIntervals = state => state.intervals || {};\nexport const selectIntervalID = (state, key) => selectIntervals(state)[key];\nexport const selectDoesIntervalExist = (state, key) =>\n !!selectIntervals(state)[key];\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/redux/middlewares/IntervalMiddleware/IntervalSelectors.js","export { IntervalMiddleware } from './IntervalMiddleware';\nexport { reducers } from './IntervalReducer';\nexport { startInterval, stopInterval } from './IntervalActions';\nexport { withInterval } from './IntervalHelpers';\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/redux/middlewares/IntervalMiddleware/index.js","/**\n * Executes a callback when the document is visible.\n * Used to decrease load when tab is hidden, for example when intervals are running.\n * @param { Function } callback\n */\nexport const whenDocumentIsVisible = callback => {\n const { hidden, msHidden, webkitHidden } = document;\n let isHidden = true;\n const isNotUndefined = n => typeof n !== 'undefined';\n\n if (isNotUndefined(hidden)) {\n // Opera 12.10 and Firefox 18 and later support\n isHidden = hidden;\n } else if (isNotUndefined(msHidden)) {\n isHidden = msHidden;\n } else if (isNotUndefined(webkitHidden)) {\n isHidden = webkitHidden;\n }\n\n if (!isHidden) {\n callback();\n }\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/redux/middlewares/common/helpers.js","import createLogger from 'redux-logger';\nimport thunk from 'redux-thunk';\nimport { routerMiddleware } from 'connected-react-router';\nimport { APIMiddleware } from '../API';\nimport { IntervalMiddleware } from './IntervalMiddleware';\nimport history from '../../history';\n\nconst logReduxToConsole = () => {\n const isProduction = process.env.NODE_ENV === 'production';\n const isLogger = process.env.REDUX_LOGGER;\n\n if (!isProduction && !global.__testing__) {\n if (isLogger === undefined || isLogger === true) return true;\n }\n return isProduction && isLogger;\n};\n\nexport const middlewares = [\n thunk,\n IntervalMiddleware,\n APIMiddleware,\n routerMiddleware(history),\n ...(logReduxToConsole() ? [createLogger()] : []),\n];\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/redux/middlewares/index.js","import { combineReducers } from 'redux';\nimport storage from './storage';\n\nexport default combineReducers({\n storage,\n});\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/redux/reducers/hosts/index.js","import { combineReducers } from 'redux';\nimport vmware from './vmware';\n\nexport default combineReducers({\n vmware,\n});\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/redux/reducers/hosts/storage/index.js","/* eslint no-case-declarations:0 */\n/* eslint no-case-declarations:0 */\nimport { difference, head } from 'lodash';\nimport Immutable from 'seamless-immutable';\nimport uuidV1 from 'uuid/v1';\n\nimport {\n VMWARE_CLUSTER_CHANGE,\n STORAGE_VMWARE_ADD_CONTROLLER,\n STORAGE_VMWARE_ADD_DISK,\n STORAGE_VMWARE_REMOVE_DISK,\n STORAGE_VMWARE_REMOVE_CONTROLLER,\n STORAGE_VMWARE_UPDATE_CONTROLLER,\n STORAGE_VMWARE_UPDATE_DISK,\n STORAGE_VMWARE_INIT,\n STORAGE_VMWARE_DATASTORES_REQUEST,\n STORAGE_VMWARE_DATASTORES_SUCCESS,\n STORAGE_VMWARE_DATASTORES_FAILURE,\n STORAGE_VMWARE_STORAGEPODS_REQUEST,\n STORAGE_VMWARE_STORAGEPODS_SUCCESS,\n STORAGE_VMWARE_STORAGEPODS_FAILURE,\n} from '../../../consts';\n\nconst initialState = Immutable({\n controllers: [],\n volumes: [],\n});\n\nconst availableControllerKeys = [1000, 1001, 1002, 1003, 1004];\n\nconst getAvailableKey = controllers =>\n head(\n difference(\n availableControllerKeys,\n controllers.map(c => c.key)\n )\n );\n\nexport default (state = initialState, { type, payload, response }) => {\n switch (type) {\n case VMWARE_CLUSTER_CHANGE:\n return state.set('cluster', payload.cluster);\n case STORAGE_VMWARE_ADD_CONTROLLER:\n const availableKey = getAvailableKey(state.controllers);\n\n // controller key is assigned here using getAvailableKey\n return state\n .update('controllers', ctrls =>\n ctrls.concat(\n Object.assign({}, payload.controller, { key: availableKey })\n )\n )\n .update('volumes', volumes =>\n volumes.concat(\n Object.assign(\n {},\n payload.volume,\n { controllerKey: availableKey },\n { key: uuidV1() }\n )\n )\n );\n case STORAGE_VMWARE_ADD_DISK:\n return state.set(\n 'volumes',\n state.volumes.concat({\n ...payload.data,\n key: uuidV1(),\n controllerKey: payload.controllerKey,\n })\n );\n case STORAGE_VMWARE_REMOVE_CONTROLLER:\n return state\n .update('controllers', ctrls =>\n ctrls.filter(ctrl => ctrl.key !== payload.controllerKey)\n )\n .update('volumes', volumes =>\n volumes.filter(\n volume => volume.controllerKey !== payload.controllerKey\n )\n );\n case STORAGE_VMWARE_UPDATE_CONTROLLER:\n return state.updateIn(['controllers', payload.idx], controller =>\n Object.assign({}, controller, payload.newValues)\n );\n case STORAGE_VMWARE_UPDATE_DISK:\n return state.set(\n 'volumes',\n state.volumes.map(v =>\n v.key === payload.key ? Object.assign({}, v, payload.newValues) : v\n )\n );\n case STORAGE_VMWARE_REMOVE_DISK:\n return state.set(\n 'volumes',\n state.volumes.filter(v => v.key !== payload.key)\n );\n case STORAGE_VMWARE_INIT:\n const newState = {\n controllers: payload.controllers,\n paramsScope: payload.config.paramsScope,\n datastores: [],\n datastoresLoading: false,\n datastoresError: undefined,\n storagePods: [],\n storagePodsLoading: false,\n storagePodsError: undefined,\n volumes: payload.volumes.map(volume => ({ ...volume, key: uuidV1() })),\n cluster: payload.cluster,\n };\n return initialState\n .set('config', payload.config)\n .setIn(\n ['config', 'addControllerEnabled'],\n !!getAvailableKey(payload.controllers)\n )\n .merge(newState);\n case STORAGE_VMWARE_DATASTORES_REQUEST:\n return state.merge({\n datastoresError: undefined,\n datastores: [],\n datastoresLoading: true,\n });\n case STORAGE_VMWARE_DATASTORES_SUCCESS:\n return state\n .set('datastores', response.results)\n .set('datastoresLoading', false);\n case STORAGE_VMWARE_DATASTORES_FAILURE:\n return state.set('datastoresError', response.message);\n case STORAGE_VMWARE_STORAGEPODS_REQUEST:\n return state.merge({\n storagePodsError: undefined,\n storagePods: [],\n storagePodsLoading: true,\n });\n case STORAGE_VMWARE_STORAGEPODS_SUCCESS:\n return state.merge({\n storagePods: response.results,\n storagePodsLoading: false,\n });\n case STORAGE_VMWARE_STORAGEPODS_FAILURE:\n return state.set('storagePodsError', response.message);\n default:\n return state;\n }\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/redux/reducers/hosts/storage/vmware.js","import { combineReducers } from 'redux';\nimport { connectRouter } from 'connected-react-router';\nimport history from '../../history';\nimport hosts from './hosts';\nimport notifications from './notifications';\nimport toasts from './toasts';\nimport { reducers as passwordStrengthReducers } from '../../components/PasswordStrength';\nimport { reducers as breadcrumbBarReducers } from '../../components/BreadcrumbBar';\nimport { reducers as autoCompleteReducers } from '../../components/AutoComplete';\nimport { reducers as layoutReducers } from '../../components/Layout';\nimport { reducers as diffModalReducers } from '../../components/ConfigReports/DiffModal';\nimport { reducers as editorReducers } from '../../components/Editor';\nimport { reducers as templateGenerationReducers } from '../../components/TemplateGenerator';\nimport { reducers as factChartReducers } from '../../components/FactCharts';\nimport { reducers as fillReducers } from '../../components/common/Fill';\nimport { reducers as typeAheadSelectReducers } from '../../components/common/TypeAheadSelect';\nimport { reducers as auditsPageReducers } from '../../routes/Audits/AuditsPage';\nimport { reducers as intervalReducers } from '../middlewares/IntervalMiddleware';\nimport { reducers as bookmarksReducers } from '../../components/Bookmarks';\nimport { reducers as modalReducers } from '../../components/ForemanModal';\nimport { reducers as apiReducer } from '../API';\nimport { reducers as modelsPageReducers } from '../../routes/Models/ModelsPage';\nimport { reducers as settingRecordsReducers } from '../../components/SettingRecords';\nimport { reducers as personalAccessTokensReducers } from '../../components/users/PersonalAccessTokens';\n\nexport function combineReducersAsync(asyncReducers) {\n return combineReducers({\n ...bookmarksReducers,\n hosts,\n notifications,\n toasts,\n ...passwordStrengthReducers,\n ...breadcrumbBarReducers,\n ...layoutReducers,\n ...asyncReducers,\n ...autoCompleteReducers,\n ...diffModalReducers,\n ...editorReducers,\n ...templateGenerationReducers,\n ...factChartReducers,\n ...typeAheadSelectReducers,\n ...settingRecordsReducers,\n ...personalAccessTokensReducers,\n\n router: connectRouter(history),\n // Pages\n ...fillReducers,\n ...auditsPageReducers,\n ...modalReducers,\n ...modelsPageReducers,\n\n // Middlewares\n ...intervalReducers,\n ...apiReducer,\n });\n}\n\nexport default combineReducersAsync();\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/redux/reducers/index.js","import Immutable from 'seamless-immutable';\n\nimport {\n NOTIFICATIONS_TOGGLE_DRAWER,\n NOTIFICATIONS_SET_EXPANDED_GROUP,\n NOTIFICATIONS_MARK_AS_CLEAR,\n NOTIFICATIONS_MARK_AS_READ,\n NOTIFICATIONS_MARK_GROUP_AS_READ,\n NOTIFICATIONS_MARK_GROUP_AS_CLEARED,\n NOTIFICATIONS,\n} from '../../consts';\nimport * as sessionStorage from '../../../components/notifications/NotificationDrawerSessionStorage';\nimport { actionTypeGenerator } from '../../API';\n\nconst initialState = Immutable({\n isDrawerOpen: sessionStorage.getIsOpened(),\n expandedGroup: sessionStorage.getExpandedGroup(),\n hasUnreadMessages: sessionStorage.getHasUnreadMessages() || false,\n});\n\nconst hasUnreadMessages = notifications => {\n const result = Object.values(notifications).some(n => !n.seen);\n\n // store indicator in sessionStorage.\n // TODO: consider moving this either to a reselect\n // ,store.subscribe OR to a distint redux action\n // leaving it here as it makes the most sense to me.\n sessionStorage.setHasUnreadMessages(result);\n return result;\n};\n\nconst { SUCCESS, FAILURE } = actionTypeGenerator(NOTIFICATIONS);\n\nexport default (state = initialState, { type, payload, response }) => {\n switch (type) {\n case SUCCESS:\n return state.merge({\n notifications: response.notifications,\n hasUnreadMessages: hasUnreadMessages(response.notifications),\n });\n case FAILURE: {\n return state.set('error', response);\n }\n case NOTIFICATIONS_TOGGLE_DRAWER:\n return state.set('isDrawerOpen', payload.value);\n case NOTIFICATIONS_SET_EXPANDED_GROUP:\n return state.set('expandedGroup', payload.group);\n case NOTIFICATIONS_MARK_AS_READ: {\n const notifications = state.notifications.map(n =>\n n.id === payload.id ? { ...n, seen: true } : n\n );\n\n return state.merge({\n notifications,\n hasUnreadMessages: hasUnreadMessages(notifications),\n });\n }\n case NOTIFICATIONS_MARK_AS_CLEAR: {\n const notifications = state.notifications.filter(\n n => n.id !== payload.id\n );\n\n return state.merge({\n notifications,\n hasUnreadMessages: hasUnreadMessages(notifications),\n });\n }\n case NOTIFICATIONS_MARK_GROUP_AS_READ: {\n const notifications = state.notifications.map(n =>\n n.group === payload.group ? { ...n, seen: true } : n\n );\n\n return state.merge({\n notifications,\n hasUnreadMessages: hasUnreadMessages(notifications),\n });\n }\n case NOTIFICATIONS_MARK_GROUP_AS_CLEARED: {\n const notifications = state.notifications.filter(\n n => n.group !== payload.group\n );\n\n return state.merge({\n notifications,\n hasUnreadMessages: hasUnreadMessages(notifications),\n });\n }\n default:\n return state;\n }\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/redux/reducers/notifications/index.js","import forceSingleton from '../../common/forceSingleton';\nimport store from '../index';\nimport { combineReducersAsync } from './index';\n\nconst asyncReducers = forceSingleton('async_reducers', () => ({}));\n\nexport default (name, asyncReducer) => {\n asyncReducers[name] = asyncReducer;\n store.replaceReducer(combineReducersAsync(asyncReducers));\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/redux/reducers/registerReducer.js","import Immutable from 'seamless-immutable';\nimport { TOASTS_ADD, TOASTS_DELETE, TOASTS_CLEAR } from '../../consts';\n\nconst initialState = Immutable({\n messages: {},\n});\n\nexport default (state = initialState, action) => {\n const { payload } = action;\n\n switch (action.type) {\n case TOASTS_ADD: {\n return state.setIn(['messages', payload.key], payload.message);\n }\n\n case TOASTS_DELETE: {\n return state.set('messages', state.messages.without(payload.key));\n }\n\n case TOASTS_CLEAR: {\n return state.set('messages', {});\n }\n\n default: {\n return state;\n }\n }\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/redux/reducers/toasts/index.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { Button, Icon } from 'patternfly-react';\nimport './auditspage.scss';\n\nimport { translate as __ } from '../../../common/I18n';\nimport { getManualURL } from '../../../common/helpers';\nimport PageLayout from '../../common/PageLayout/PageLayout';\nimport AuditsTable from './components/AuditsTable';\nimport { AUDITS_SEARCH_PROPS } from '../constants';\n\nconst AuditsPage = ({\n searchQuery,\n fetchAndPush,\n isLoading,\n hasData,\n ...props\n}) => (\n fetchAndPush({ searchQuery: search, page: 1 })}\n onBookmarkClick={search => fetchAndPush({ searchQuery: search, page: 1 })}\n toolbarButtons={\n \n }\n >\n \n \n);\n\nAuditsPage.propTypes = {\n searchQuery: PropTypes.string.isRequired,\n fetchAndPush: PropTypes.func.isRequired,\n isLoading: PropTypes.bool.isRequired,\n hasData: PropTypes.bool.isRequired,\n};\n\nexport default AuditsPage;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/Audits/AuditsPage/AuditsPage.js","import history from '../../../history';\nimport { API } from '../../../redux/API';\nimport {\n AUDITS_PATH,\n AUDITS_PAGE_DATA_RESOLVED,\n AUDITS_PAGE_DATA_FAILED,\n AUDITS_PAGE_HIDE_LOADING,\n AUDITS_PAGE_UPDATE_QUERY,\n AUDITS_PAGE_CLEAR_ERROR,\n AUDITS_PAGE_SHOW_LOADING,\n} from '../constants';\nimport {\n selectAuditsSelectedPage,\n selectAuditsHasError,\n selectAuditsPerPage,\n selectAuditsSearch,\n selectAuditsIsLoadingPage,\n} from './AuditsPageSelectors';\nimport { stringifyParams, getParams } from '../../../common/urlHelpers';\nimport { translate as __ } from '../../../common/I18n';\n\n// on didMount or popstatee\nexport const initializeAudits = () => dispatch => {\n const params = getParams();\n dispatch(fetchAudits(params));\n if (!history.action === 'POP') {\n history.replace({\n pathname: AUDITS_PATH,\n search: stringifyParams(params),\n });\n }\n};\n\nexport const fetchAudits = (\n { page, perPage, searchQuery },\n url = AUDITS_PATH\n) => async (dispatch, getState) => {\n dispatch({ type: AUDITS_PAGE_SHOW_LOADING });\n if (selectAuditsHasError(getState()))\n dispatch({\n type: AUDITS_PAGE_CLEAR_ERROR,\n });\n\n const onRequestSuccess = ({ data: { audits, itemCount } }) => {\n if (selectAuditsIsLoadingPage(getState()))\n dispatch({ type: AUDITS_PAGE_HIDE_LOADING });\n\n dispatch({\n type: AUDITS_PAGE_UPDATE_QUERY,\n payload: {\n page,\n perPage,\n searchQuery,\n itemCount,\n },\n });\n\n dispatch({\n type: AUDITS_PAGE_DATA_RESOLVED,\n payload: {\n audits,\n hasData: itemCount > 0,\n },\n });\n };\n const onRequestFail = error => {\n if (selectAuditsIsLoadingPage(getState()))\n dispatch({ type: AUDITS_PAGE_HIDE_LOADING });\n\n dispatch({\n type: AUDITS_PAGE_DATA_FAILED,\n payload: {\n message: {\n type: 'error',\n text: `${error.response.status} ${__(error.response.statusText)}`,\n },\n },\n });\n };\n try {\n const response = await API.get(\n url,\n {},\n {\n page,\n per_page: perPage,\n search: searchQuery,\n }\n );\n return onRequestSuccess(response);\n } catch (error) {\n return onRequestFail(error);\n }\n};\n\nexport const fetchAndPush = params => (dispatch, getState) => {\n const query = buildQuery(params, getState());\n dispatch(fetchAudits(query));\n history.push({\n pathname: AUDITS_PATH,\n search: stringifyParams(query),\n });\n};\n\nconst buildQuery = (query, state) => ({\n page: query.page || selectAuditsSelectedPage(state),\n perPage: query.perPage || selectAuditsPerPage(state),\n searchQuery:\n query.searchQuery === undefined\n ? selectAuditsSearch(state)\n : query.searchQuery,\n});\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/Audits/AuditsPage/AuditsPageActions.js","export const selectAuditsPageData = state => state.auditsPage.data;\nexport const selectAuditsPageQuery = state => state.auditsPage.query;\n\nexport const selectAudits = state => selectAuditsPageData(state).audits;\nexport const selectAuditsMessage = state => selectAuditsPageData(state).message;\nexport const selectAuditsIsLoadingPage = state =>\n selectAuditsPageData(state).isLoading;\nexport const selectAuditsHasError = state =>\n selectAuditsPageData(state).hasError;\nexport const selectAuditsHasData = state => selectAuditsPageData(state).hasData;\n\nexport const selectAuditsSelectedPage = state =>\n selectAuditsPageQuery(state).page;\nexport const selectAuditsPerPage = state =>\n selectAuditsPageQuery(state).perPage;\nexport const selectAuditsCount = state =>\n selectAuditsPageQuery(state).itemCount;\nexport const selectAuditsSearch = state =>\n selectAuditsPageQuery(state).searchQuery;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/Audits/AuditsPage/AuditsPageSelectors.js","import React from 'react';\nimport Skeleton from 'react-loading-skeleton';\nimport './auditsloading.scss';\n\nconst AuditsLoadingPage = () => (\n \n \n
\n);\n\nexport default AuditsLoadingPage;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/Audits/AuditsPage/components/AuditsLoadingPage.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { withRenderHandler } from '../../../../common/HOC';\nimport AuditsList from '../../../../components/AuditsList';\nimport AuditsLoadingPage from './AuditsLoadingPage';\nimport Pagination from '../../../../components/Pagination/Pagination';\n\nconst AuditsTable = ({ audits, page, itemCount, fetchAndPush }) => (\n \n \n \n \n);\n\nAuditsTable.propTypes = {\n audits: PropTypes.array.isRequired,\n page: PropTypes.number.isRequired,\n itemCount: PropTypes.number.isRequired,\n fetchAndPush: PropTypes.func.isRequired,\n};\n\nexport default withRenderHandler({\n Component: AuditsTable,\n LoadingComponent: AuditsLoadingPage,\n});\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/Audits/AuditsPage/components/AuditsTable.js","import { connect } from 'react-redux';\nimport { compose, combineReducers, bindActionCreators } from 'redux';\n\nimport * as actions from './AuditsPageActions';\n\nimport AuditsPage from './AuditsPage';\nimport {\n selectAudits,\n selectAuditsCount,\n selectAuditsMessage,\n selectAuditsPerPage,\n selectAuditsSearch,\n selectAuditsSelectedPage,\n selectAuditsHasData,\n selectAuditsHasError,\n selectAuditsIsLoadingPage,\n} from './AuditsPageSelectors';\nimport { callOnMount, callOnPopState } from '../../../common/HOC';\nimport withQueryReducer from '../../common/reducerHOC/withQueryReducer';\nimport withDataReducer from '../../common/reducerHOC/withDataReducer';\n\nconst mapStateToProps = state => ({\n audits: selectAudits(state),\n isLoading: selectAuditsIsLoadingPage(state),\n itemCount: selectAuditsCount(state),\n message: selectAuditsMessage(state),\n page: selectAuditsSelectedPage(state),\n perPage: selectAuditsPerPage(state),\n searchQuery: selectAuditsSearch(state),\n hasError: selectAuditsHasError(state),\n hasData: selectAuditsHasData(state),\n});\n\nconst mapDispatchToProps = dispatch => bindActionCreators(actions, dispatch);\n\nexport const reducers = {\n auditsPage: combineReducers({\n data: withDataReducer('AUDITS_PAGE'),\n query: withQueryReducer('AUDITS_PAGE'),\n }),\n};\n\nexport default compose(\n connect(mapStateToProps, mapDispatchToProps),\n callOnMount(({ initializeAudits }) => initializeAudits()),\n callOnPopState(({ initializeAudits }) => initializeAudits())\n)(AuditsPage);\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/Audits/AuditsPage/index.js","import { getControllerSearchProps } from '../../constants';\n\nexport const AUDITS_PAGE_DATA_RESOLVED = 'AUDITS_PAGE_DATA_RESOLVED';\nexport const AUDITS_PAGE_DATA_FAILED = 'AUDITS_PAGE_DATA_FAILED';\nexport const AUDITS_PAGE_HIDE_LOADING = 'AUDITS_PAGE_HIDE_LOADING';\nexport const AUDITS_PAGE_SHOW_LOADING = 'AUDITS_PAGE_SHOW_LOADING';\nexport const AUDITS_PAGE_UPDATE_QUERY = 'AUDITS_PAGE_UPDATE_QUERY';\nexport const AUDITS_PAGE_CLEAR_ERROR = 'AUDITS_PAGE_CLEAR_ERROR';\n\nexport const AUDITS_PATH = '/audits';\nexport const AUDITS_SEARCH_PROPS = getControllerSearchProps('audits');\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/Audits/constants.js","import React from 'react';\nimport AuditsPage from './AuditsPage';\nimport { AUDITS_PATH } from './constants';\n\nexport default {\n path: AUDITS_PATH,\n render: props => ,\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/Audits/index.js","import React from 'react';\nimport { Switch, Route } from 'react-router-dom';\nimport PropTypes from 'prop-types';\nimport { fallbackRoute, renderRoute } from '../RoutingService';\n\nconst ForemanSwitcher = ({ routes }) => (\n \n {routes}\n renderRoute(null, child, fallbackRoute)}\n key=\"default-route\"\n />\n \n);\n\nForemanSwitcher.propTypes = {\n routes: PropTypes.arrayOf(PropTypes.node).isRequired,\n};\n\nexport default ForemanSwitcher;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/ForemanSwitcher/ForemanSwitcher.js","import PropTypes from 'prop-types';\nimport React from 'react';\nimport { useSelector, shallowEqual } from 'react-redux';\nimport ForemanSwitcher from './ForemanSwitcher';\nimport { selectRoutes } from '../RouterSelector';\n\nconst ConnectedForemanSwitcher = ({ children: coreRoutes }) => {\n const routes = useSelector(() => selectRoutes(coreRoutes), shallowEqual);\n\n return ;\n};\n\nConnectedForemanSwitcher.propTypes = {\n children: PropTypes.arrayOf(PropTypes.node).isRequired,\n};\n\nexport default ConnectedForemanSwitcher;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/ForemanSwitcher/index.js","export const HOST_DETAILS_PATH = '/experimental/hosts/:id';\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/HostDetails/constants.js","import React from 'react';\nimport HostDetails from '../../components/HostDetails';\nimport { HOST_DETAILS_PATH } from './constants';\n\nexport default {\n path: HOST_DETAILS_PATH,\n render: props => ,\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/HostDetails/index.js","import React from 'react';\nimport { Wizard, Button, Icon } from 'patternfly-react';\nimport PageLayout from '../../common/PageLayout/PageLayout';\nimport { translate as __ } from '../../../common/I18n';\n\nclass LoadingWizardExample extends React.Component {\n constructor(props) {\n super(props);\n this.state = { showModal: false };\n }\n close = () => {\n this.setState({ showModal: false });\n };\n open = () => {\n this.setState({ showModal: true });\n };\n render() {\n const { showModal } = this.state;\n\n return (\n \n \n\n \n \n \n \n \n \n
\n
\n {__('This will be one of our coolest pages.')}\n
\n
\n \n \n \n \n \n \n \n \n \n \n );\n }\n}\n\nexport default LoadingWizardExample;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/HostWizard/HostWizardPage/HostWizard.js","export { default } from './HostWizard';\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/HostWizard/HostWizardPage/index.js","import React from 'react';\nimport HostWizard from './HostWizardPage';\n\nexport default {\n path: '/host_wizard',\n render: props => ,\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/HostWizard/index.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { Button } from 'patternfly-react';\nimport { Link } from 'react-router-dom';\n\nimport { translate as __ } from '../../../common/I18n';\nimport PageLayout from '../../common/PageLayout/PageLayout';\nimport ModelsPageContent from './components/ModelsPageContent';\nimport { MODELS_SEARCH_PROPS } from '../constants';\n\nconst ModelsPage = ({\n fetchAndPush,\n search,\n isLoading,\n hasData,\n models,\n page,\n perPage,\n sort,\n hasError,\n itemCount,\n message,\n canCreate,\n toasts,\n}) => {\n const handleSearch = query => fetchAndPush({ searchQuery: query, page: 1 });\n\n const createBtn = (\n \n \n \n );\n\n return (\n \n \n \n );\n};\n\nModelsPage.propTypes = {\n fetchAndPush: PropTypes.func.isRequired,\n search: PropTypes.string,\n isLoading: PropTypes.bool.isRequired,\n hasData: PropTypes.bool.isRequired,\n models: PropTypes.array.isRequired,\n page: PropTypes.number,\n perPage: PropTypes.number,\n sort: PropTypes.object.isRequired,\n hasError: PropTypes.bool.isRequired,\n itemCount: PropTypes.number.isRequired,\n message: PropTypes.object,\n canCreate: PropTypes.bool.isRequired,\n toasts: PropTypes.array.isRequired,\n};\n\nModelsPage.defaultProps = {\n page: null,\n perPage: null,\n search: '',\n message: {},\n};\n\nexport default ModelsPage;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/Models/ModelsPage/ModelsPage.js","import URI from 'urijs';\nimport history from '../../../history';\nimport { get } from '../../../redux/API';\nimport { buildQuery } from './ModelsPageHelpers';\n\nimport { MODELS_API_PATH, MODELS_PATH, API_REQUEST_KEY } from '../constants';\n\nimport { stringifyParams, getParams } from '../../../common/urlHelpers';\n\nexport const initializeModels = () => dispatch => {\n const params = getParams();\n dispatch(fetchModels(params));\n if (!history.action === 'POP') {\n history.replace({\n pathname: MODELS_PATH,\n search: stringifyParams(params),\n });\n }\n};\n\nexport const fetchModels = (\n { page, perPage, searchQuery, sort },\n url = MODELS_API_PATH\n) => {\n const sortString =\n sort && Object.keys(sort).length > 0 ? `${sort.by} ${sort.order}` : '';\n\n const uriWithPrams = new URI(url);\n uriWithPrams.setSearch({\n page,\n per_page: perPage,\n search: searchQuery,\n order: sortString,\n });\n return get({ key: API_REQUEST_KEY, url: uriWithPrams });\n};\n\nexport const fetchAndPush = (params = {}) => (dispatch, getState) => {\n const query = buildQuery(params, getState());\n dispatch(fetchModels(query));\n history.push({\n pathname: MODELS_PATH,\n search: stringifyParams(query),\n });\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/Models/ModelsPage/ModelsPageActions.js","import { snakeCase } from 'lodash';\nimport { compose } from 'redux';\nimport {\n selectSort,\n selectPage,\n selectPerPage,\n selectSearch,\n} from './ModelsPageSelectors';\n\nexport const buildQuery = (query, state) => {\n const querySort = pickSort(query, state);\n\n return {\n page: query.page || selectPage(state),\n perPage: query.perPage || selectPerPage(state),\n searchQuery:\n query.searchQuery === undefined ? selectSearch(state) : query.searchQuery,\n ...(querySort && { sort: querySort }),\n };\n};\n\nexport const pickSort = (query, state) =>\n checkSort(query.sort)\n ? transformSort(query.sort)\n : checkSort(compose(transformSort, selectSort)(state));\n\nconst checkSort = sort => (sort && sort.by && sort.order ? sort : undefined);\n\nconst transformSort = sort => ({ ...sort, by: snakeCase(sort.by) });\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/Models/ModelsPage/ModelsPageHelpers.js","import { camelCase } from 'lodash';\nimport Immutable from 'seamless-immutable';\n\nimport { API_REQUEST_KEY } from '../constants';\nimport { STATUS } from '../../../constants';\nimport { deepPropsToCamelCase } from '../../../common/helpers';\n\nexport const response = {\n results: [],\n page: 0,\n perPage: 0,\n search: '',\n sort: {},\n canCreate: false,\n subtotal: 0,\n message: {},\n};\n\nconst emptyState = Immutable({\n payload: null,\n response,\n status: null,\n});\n\nexport const selectModelsPageData = state =>\n deepPropsToCamelCase(state.API[API_REQUEST_KEY]) || emptyState;\n\nconst selectModelsPageResponse = state =>\n selectModelsPageData(state).response || Immutable(response);\n\nexport const selectIsLoading = state => {\n const { status } = selectModelsPageData(state);\n return !status || status === STATUS.PENDING;\n};\n\nconst selectModelsPageStatus = state => selectModelsPageData(state).status;\n\nexport const selectHasError = state =>\n selectModelsPageStatus(state) === STATUS.ERROR;\n\nexport const selectModels = state => selectModelsPageResponse(state).results;\n\nexport const selectHasData = state => {\n const status = selectModelsPageStatus(state);\n const results = selectModels(state);\n\n return status === STATUS.RESOLVED && results && results.length > 0;\n};\n\nexport const selectPage = state => selectModelsPageResponse(state).page;\nexport const selectPerPage = state => selectModelsPageResponse(state).perPage;\nexport const selectSearch = state => selectModelsPageResponse(state).search;\n\nexport const selectSort = state => {\n const sort = selectModelsPageResponse(state).sort || Immutable({});\n if (sort.by && sort.order) {\n return { ...sort, by: camelCase(sort.by) };\n }\n return sort;\n};\n\nexport const selectCanCreate = state =>\n selectModelsPageResponse(state).canCreate;\nexport const selectSubtotal = state => selectModelsPageResponse(state).subtotal;\nexport const selectMessage = state => selectModelsPageResponse(state).message;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/Models/ModelsPage/ModelsPageSelectors.js","import React from 'react';\nimport PropTypes from 'prop-types';\n\nimport { sprintf, translate as __ } from '../../../../common/I18n';\nimport ForemanModal from '../../../../components/ForemanModal';\nimport { MODEL_DELETE_MODAL_ID } from '../../constants';\n\nconst ModelDeleteModal = props => {\n const { id, name } = props.toDelete;\n\n return (\n \n {sprintf(__('You are about to delete %s. Are you sure?'), name)}\n \n \n );\n};\n\nModelDeleteModal.propTypes = {\n toDelete: PropTypes.object,\n fetchAndPush: PropTypes.func.isRequired,\n};\n\nModelDeleteModal.defaultProps = {\n toDelete: {},\n};\n\nexport default ModelDeleteModal;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/Models/ModelsPage/components/ModelDeleteModal.js","import React, { useState } from 'react';\nimport PropTypes from 'prop-types';\n\nimport ModelsTable from '../../../../components/ModelsTable';\nimport Pagination from '../../../../components/Pagination/PaginationWrapper';\n\nimport ModelDeleteModal from './ModelDeleteModal';\nimport LoadingPage from '../../../common/LoadingPage';\nimport { withRenderHandler } from '../../../../common/HOC';\n\nconst ModelsPageContent = ({\n models,\n search,\n sort,\n fetchAndPush,\n itemCount,\n page,\n perPage,\n}) => {\n const [toDelete, setToDelete] = useState({});\n\n return (\n \n \n \n \n \n );\n};\n\nModelsPageContent.propTypes = {\n models: PropTypes.array.isRequired,\n search: PropTypes.string,\n sort: PropTypes.object.isRequired,\n fetchAndPush: PropTypes.func.isRequired,\n itemCount: PropTypes.number.isRequired,\n page: PropTypes.number.isRequired,\n perPage: PropTypes.number.isRequired,\n};\n\nModelsPageContent.defaultProps = {\n search: '',\n};\n\nexport default withRenderHandler({\n Component: ModelsPageContent,\n LoadingComponent: LoadingPage,\n});\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/Models/ModelsPage/components/ModelsPageContent.js","import React from 'react';\nimport { connect } from 'react-redux';\nimport { compose, bindActionCreators } from 'redux';\n\nimport ModelsPage from './ModelsPage';\nimport * as actions from './ModelsPageActions';\n\nimport { callOnMount, callOnPopState } from '../../../common/HOC';\n\nimport { useForemanContext } from '../../../Root/Context/ForemanContext';\n\nimport {\n selectModels,\n selectPage,\n selectPerPage,\n selectSearch,\n selectSort,\n selectHasData,\n selectHasError,\n selectIsLoading,\n selectSubtotal,\n selectMessage,\n selectCanCreate,\n} from './ModelsPageSelectors';\n\nconst mapStateToProps = state => ({\n models: selectModels(state),\n page: selectPage(state),\n perPage: selectPerPage(state),\n search: selectSearch(state),\n sort: selectSort(state),\n isLoading: selectIsLoading(state),\n hasData: selectHasData(state),\n hasError: selectHasError(state),\n itemCount: selectSubtotal(state),\n message: selectMessage(state),\n canCreate: selectCanCreate(state),\n});\n\nconst mapDispatchToProps = dispatch => bindActionCreators(actions, dispatch);\n\nconst callWithToastsContext = Component => props => {\n const { toasts } = useForemanContext();\n return ;\n};\n\nexport default compose(\n connect(mapStateToProps, mapDispatchToProps),\n callWithToastsContext,\n callOnMount(({ initializeModels }) => initializeModels()),\n callOnPopState(({ initializeModels }) => initializeModels())\n)(ModelsPage);\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/Models/ModelsPage/index.js","import { getControllerSearchProps } from '../../constants';\n\nexport const MODELS_PAGE_DATA_RESOLVED = 'MODELS_PAGE_DATA_RESOLVED';\nexport const MODELS_PAGE_DATA_FAILED = 'MODELS_PAGE_DATA_FAILED';\nexport const MODELS_PAGE_HIDE_LOADING = 'MODELS_PAGE_HIDE_LOADING';\nexport const MODELS_PAGE_SHOW_LOADING = 'MODELS_PAGE_SHOW_LOADING';\nexport const MODELS_PAGE_CLEAR_ERROR = 'MODELS_PAGE_CLEAR_ERROR';\n\nexport const MODELS_SEARCH_PROPS = getControllerSearchProps('models');\nexport const MODELS_API_PATH = '/api/models?include_permissions=true';\nexport const MODELS_PATH = '/models';\nexport const MODEL_DELETE_MODAL_ID = 'modelDeleteModal';\nexport const API_REQUEST_KEY = 'MODELS';\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/Models/constants.js","import React from 'react';\n\nimport ModelsPage from './ModelsPage';\nimport { MODELS_PATH } from './constants';\n\nexport default {\n path: MODELS_PATH,\n render: props => ,\n exact: true,\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/Models/index.js","import { foremanUrl } from '../../../../foreman_tools';\nimport { get, post } from '../../../redux/API';\n\nimport {\n REGISTRATION_COMMANDS_DATA,\n REGISTRATION_COMMANDS_OS_TEMPLATE,\n REGISTRATION_COMMANDS,\n} from '../constants';\n\nexport const dataAction = params =>\n get({\n key: REGISTRATION_COMMANDS_DATA,\n url: foremanUrl('/hosts/register/data'),\n params,\n });\n\nexport const operatingSystemTemplateAction = operatingSystemId =>\n get({\n key: REGISTRATION_COMMANDS_OS_TEMPLATE,\n url: foremanUrl(`/hosts/register/os/${operatingSystemId}`),\n });\n\nexport const commandAction = params =>\n post({\n key: REGISTRATION_COMMANDS,\n url: foremanUrl('/hosts/register'),\n params,\n });\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/RegistrationCommands/RegistrationCommandsPage/RegistrationCommandsPageActions.js","/* eslint-disable camelcase */\nimport React from 'react';\nimport { FormSelectOption } from '@patternfly/react-core';\n\nimport { foremanUrl } from '../../../../foreman_tools';\nimport { sprintf, translate as __ } from '../../../common/I18n';\n\n// Form helpers\nexport const emptyOption = length => (\n 0 ? '' : __('Nothing to select.')}\n />\n);\n\n// OperatingSystem helpers\n\nexport const validatedOS = (operatingSystemId, template) => {\n if (!operatingSystemId) {\n return 'default';\n }\n\n if (template?.name) {\n return 'success';\n }\n return 'error';\n};\n\nexport const osHelperText = (\n operatingSystemId,\n operatingSystems,\n hostGroupId,\n hostGroups,\n template\n) => {\n if (operatingSystemId) {\n return osTemplateHelperText(operatingSystemId, template);\n }\n\n if (hostGroupId) {\n const osId = hostGroups.find(hg => `${hg.id}` === `${hostGroupId}`)\n ?.operatingsystem_id;\n return (\n <>\n {hostGroupOSHelperText(hostGroupId, hostGroups, operatingSystems)}\n
\n {osId && osTemplateHelperText(osId, template)}\n >\n );\n }\n\n return '';\n};\n\nconst osTemplateHelperText = (operatingSystemId, template) => {\n if (!operatingSystemId && template === undefined) {\n return <> >;\n }\n\n if (template?.name) {\n return (\n \n {__('Initial configuration template')}:{' '}\n \n {template.name}\n \n \n );\n }\n\n return (\n \n \n {__('Operating system')}\n {' '}\n {__('does not have assigned host_init_config template')}\n \n );\n};\n\nconst hostGroupOSHelperText = (hostGroupId, hostGroups, operatingSystems) => {\n const osId = hostGroups.find(hg => `${hg.id}` === `${hostGroupId}`)\n ?.operatingsystem_id;\n const hostGroupOS = operatingSystems.find(os => `${os.id}` === `${osId}`);\n\n if (hostGroupOS) {\n return sprintf('Host group OS: %s', hostGroupOS.title);\n }\n return __('No OS from host group');\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/RegistrationCommands/RegistrationCommandsPage/RegistrationCommandsPageHelpers.js","import {\n REGISTRATION_COMMANDS_DATA,\n REGISTRATION_COMMANDS_OS_TEMPLATE,\n REGISTRATION_COMMANDS,\n} from '../constants';\n\nimport {\n selectAPIStatus,\n selectAPIResponse,\n} from '../../../redux/API/APISelectors';\n\n// Form API Data\n\nexport const selectAPIStatusData = state =>\n selectAPIStatus(state, REGISTRATION_COMMANDS_DATA);\n\nexport const selectOrganizations = state =>\n selectAPIResponse(state, REGISTRATION_COMMANDS_DATA).organizations || [];\n\nexport const selectLocations = state =>\n selectAPIResponse(state, REGISTRATION_COMMANDS_DATA).locations || [];\n\nexport const selectHostGroups = state =>\n selectAPIResponse(state, REGISTRATION_COMMANDS_DATA).hostGroups || [];\n\nexport const selectOperatingSystems = state =>\n selectAPIResponse(state, REGISTRATION_COMMANDS_DATA).operatingSystems || [];\n\nexport const selectOperatingSystemTemplate = state =>\n selectAPIResponse(state, REGISTRATION_COMMANDS_OS_TEMPLATE).template;\n\nexport const selectSmartProxies = state =>\n selectAPIResponse(state, REGISTRATION_COMMANDS_DATA).smartProxies || [];\n\nexport const selectConfigParams = state =>\n selectAPIResponse(state, REGISTRATION_COMMANDS_DATA).configParams || {};\n\nexport const selectPluginData = state =>\n selectAPIResponse(state, REGISTRATION_COMMANDS_DATA).pluginData || {};\n\n// Generate Command\n\nexport const selectAPIStatusCommand = state =>\n selectAPIStatus(state, REGISTRATION_COMMANDS);\n\nexport const selectCommand = state =>\n selectAPIResponse(state, REGISTRATION_COMMANDS).command || '';\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/RegistrationCommands/RegistrationCommandsPage/RegistrationCommandsPageSelectors.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { Link } from 'react-router-dom';\n\nimport {\n ActionGroup,\n Button,\n FormHelperText,\n FormGroup,\n} from '@patternfly/react-core';\nimport { ExclamationCircleIcon } from '@patternfly/react-icons';\n\nimport { sprintf, translate as __ } from '../../../../common/I18n';\nimport { foremanUrl } from '../../../../../foreman_tools';\n\nconst Actions = ({ isLoading, isGenerating, handleSubmit, invalidFields }) => (\n <>\n \n \n\n {/* Can't use due to infinitive loop */}\n \n \n \n \n \n }\n isHidden={invalidFields.length === 0}\n >\n {invalidFields.length === 1 &&\n sprintf('Invalid field: %s', invalidFields[0])}\n {invalidFields.length > 1 &&\n sprintf('Invalid fields: %s', invalidFields.join(', '))}\n \n \n >\n);\n\nActions.propTypes = {\n handleSubmit: PropTypes.func.isRequired,\n isLoading: PropTypes.bool.isRequired,\n isGenerating: PropTypes.bool.isRequired,\n invalidFields: PropTypes.oneOfType([PropTypes.array, PropTypes.object]),\n};\n\nActions.defaultProps = {\n invalidFields: [],\n};\n\nexport default Actions;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/RegistrationCommands/RegistrationCommandsPage/components/Actions.js","import React from 'react';\nimport PropTypes from 'prop-types';\n\nimport ConfigParams from './fields/ConfigParams';\nimport Packages from './fields/Packages';\nimport Repository from './fields/Repository';\nimport TokenLifeTime from './fields/TokenLifeTime';\nimport UpdatePackages from './fields/UpdatePackages';\n\nconst Advanced = ({\n configParams,\n setupRemoteExecution,\n setupInsights,\n handleInsights,\n handleRemoteExecution,\n jwtExpiration,\n handleJwtExpiration,\n handleInvalidField,\n packages,\n handlePackages,\n repo,\n handleRepo,\n repoGpgKeyUrl,\n handleRepoGpgKeyUrl,\n updatePackages,\n handleUpdatePackages,\n isLoading,\n}) => (\n <>\n \n \n \n \n \n >\n);\n\nAdvanced.propTypes = {\n configParams: PropTypes.object,\n setupRemoteExecution: PropTypes.string,\n setupInsights: PropTypes.string,\n handleInsights: PropTypes.func.isRequired,\n handleRemoteExecution: PropTypes.func.isRequired,\n jwtExpiration: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),\n handleJwtExpiration: PropTypes.func.isRequired,\n handleInvalidField: PropTypes.func.isRequired,\n packages: PropTypes.string,\n repo: PropTypes.string,\n repoGpgKeyUrl: PropTypes.string,\n handlePackages: PropTypes.func.isRequired,\n handleRepo: PropTypes.func.isRequired,\n handleRepoGpgKeyUrl: PropTypes.func.isRequired,\n updatePackages: PropTypes.bool,\n handleUpdatePackages: PropTypes.func.isRequired,\n isLoading: PropTypes.bool.isRequired,\n};\n\nAdvanced.defaultProps = {\n configParams: {},\n setupRemoteExecution: '',\n setupInsights: '',\n jwtExpiration: 4,\n packages: '',\n repo: '',\n repoGpgKeyUrl: '',\n updatePackages: false,\n};\n\nexport default Advanced;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/RegistrationCommands/RegistrationCommandsPage/components/Advanced.js","import React from 'react';\nimport PropTypes from 'prop-types';\n\nimport {\n Alert,\n FormGroup,\n ClipboardCopy,\n ClipboardCopyVariant,\n} from '@patternfly/react-core';\nimport { translate as __ } from '../../../../common/I18n';\nimport { STATUS } from '../../../../constants';\n\nconst Command = ({ apiStatus, command }) => {\n switch (apiStatus) {\n case STATUS.ERROR:\n return (\n \n );\n case STATUS.RESOLVED:\n return (\n \n \n {command}\n \n \n );\n default:\n return ;\n }\n};\n\nCommand.propTypes = {\n apiStatus: PropTypes.string,\n command: PropTypes.string,\n};\n\nCommand.defaultProps = {\n apiStatus: undefined,\n command: '',\n};\n\nexport default Command;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/RegistrationCommands/RegistrationCommandsPage/components/Command.js","import React from 'react';\nimport PropTypes from 'prop-types';\n\nimport Taxonomies from './fields/Taxonomies';\nimport HostGroup from './fields/HostGroup';\nimport OperatingSystem from './fields/OperatingSystem';\nimport SmartProxy from './fields/SmartProxy';\nimport Insecure from './fields/Insecure';\n\nconst General = ({\n organizationId,\n organizations,\n handleOrganization,\n locationId,\n locations,\n handleLocation,\n hostGroupId,\n hostGroups,\n handleHostGroup,\n operatingSystemId,\n operatingSystems,\n operatingSystemTemplate,\n handleOperatingSystem,\n smartProxyId,\n smartProxies,\n handleSmartProxy,\n insecure,\n handleInsecure,\n handleInvalidField,\n isLoading,\n}) => (\n <>\n \n\n \n\n \n\n \n\n \n >\n);\n\nGeneral.propTypes = {\n organizationId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),\n organizations: PropTypes.array,\n operatingSystems: PropTypes.array,\n smartProxies: PropTypes.array,\n locations: PropTypes.array,\n handleOrganization: PropTypes.func.isRequired,\n locationId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),\n handleLocation: PropTypes.func.isRequired,\n hostGroupId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),\n hostGroups: PropTypes.array,\n handleHostGroup: PropTypes.func.isRequired,\n operatingSystemId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),\n operatingSystemTemplate: PropTypes.oneOfType([\n PropTypes.object,\n PropTypes.string,\n ]),\n handleOperatingSystem: PropTypes.func.isRequired,\n smartProxyId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),\n handleSmartProxy: PropTypes.func.isRequired,\n insecure: PropTypes.bool.isRequired,\n handleInsecure: PropTypes.func.isRequired,\n handleInvalidField: PropTypes.func.isRequired,\n isLoading: PropTypes.bool.isRequired,\n};\n\nGeneral.defaultProps = {\n organizationId: undefined,\n locationId: undefined,\n hostGroupId: undefined,\n hostGroups: [],\n organizations: [],\n locations: [],\n operatingSystems: [],\n smartProxies: [],\n operatingSystemId: undefined,\n operatingSystemTemplate: undefined,\n smartProxyId: undefined,\n};\n\nexport default General;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/RegistrationCommands/RegistrationCommandsPage/components/General.js","import React from 'react';\nimport PropTypes from 'prop-types';\n\nimport {\n FormGroup,\n FormSelectOption,\n FormSelect,\n} from '@patternfly/react-core';\nimport LabelIcon from '../../../../../components/common/LabelIcon';\n\nimport { translate as __ } from '../../../../../common/I18n';\n\nconst ConfigParams = ({\n configParams,\n setupRemoteExecution,\n setupInsights,\n handleRemoteExecution,\n handleInsights,\n isLoading,\n}) => {\n const options = (value = '') => {\n const defaultValue = value ? __('yes') : __('no');\n const defaultLabel = `${__(\n 'Inherit from host parameter'\n )} (${defaultValue})`;\n\n return (\n <>\n \n \n \n >\n );\n };\n\n return (\n <>\n \n }\n fieldId=\"registration_setup_remote_execution\"\n >\n handleRemoteExecution(v)}\n className=\"without_select2\"\n id=\"registration_setup_remote_execution\"\n isDisabled={isLoading}\n isRequired\n >\n {/* eslint-disable-next-line camelcase */\n options(configParams?.host_registration_remote_execution)}\n \n \n \n }\n >\n handleInsights(v)}\n className=\"without_select2\"\n id=\"registration_setup_insights\"\n isDisabled={isLoading}\n isRequired\n >\n {/* eslint-disable-next-line camelcase */\n options(configParams?.host_registration_insights)}\n \n \n >\n );\n};\n\nConfigParams.propTypes = {\n configParams: PropTypes.object,\n setupRemoteExecution: PropTypes.string.isRequired,\n setupInsights: PropTypes.string.isRequired,\n handleRemoteExecution: PropTypes.func.isRequired,\n handleInsights: PropTypes.func.isRequired,\n isLoading: PropTypes.bool.isRequired,\n};\n\nConfigParams.defaultProps = {\n configParams: {},\n};\n\nexport default ConfigParams;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/RegistrationCommands/RegistrationCommandsPage/components/fields/ConfigParams.js","import React from 'react';\nimport PropTypes from 'prop-types';\n\nimport {\n FormGroup,\n FormSelect,\n FormSelectOption,\n} from '@patternfly/react-core';\n\nimport { translate as __ } from '../../../../../common/I18n';\nimport { emptyOption } from '../../RegistrationCommandsPageHelpers';\n\nconst HostGroup = ({ hostGroupId, hostGroups, handleHostGroup, isLoading }) => (\n \n handleHostGroup(v)}\n className=\"without_select2\"\n id=\"reg_host_group\"\n isDisabled={isLoading || hostGroups.length === 0}\n >\n {emptyOption(hostGroups.length)}\n {hostGroups.map((hg, i) => (\n \n ))}\n \n \n);\n\nHostGroup.propTypes = {\n hostGroupId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),\n handleHostGroup: PropTypes.func.isRequired,\n isLoading: PropTypes.bool.isRequired,\n hostGroups: PropTypes.array,\n};\n\nHostGroup.defaultProps = {\n hostGroupId: '',\n hostGroups: [],\n};\n\nexport default HostGroup;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/RegistrationCommands/RegistrationCommandsPage/components/fields/HostGroup.js","import React from 'react';\nimport PropTypes from 'prop-types';\n\nimport { FormGroup, Checkbox } from '@patternfly/react-core';\nimport LabelIcon from '../../../../../components/common/LabelIcon';\n\nimport { translate as __ } from '../../../../../common/I18n';\n\nconst Insecure = ({ insecure, handleInsecure, isLoading }) => (\n \n \n {__('Insecure')}{' '}\n \n \n }\n id=\"reg_insecure\"\n onChange={() => handleInsecure(!insecure)}\n isDisabled={isLoading}\n isChecked={insecure}\n />\n \n);\n\nInsecure.propTypes = {\n insecure: PropTypes.bool.isRequired,\n handleInsecure: PropTypes.func.isRequired,\n isLoading: PropTypes.bool.isRequired,\n};\n\nexport default Insecure;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/RegistrationCommands/RegistrationCommandsPage/components/fields/Insecure.js","/* eslint-disable camelcase */\n/* eslint-disable react-hooks/exhaustive-deps */\n\nimport React, { useEffect } from 'react';\nimport PropTypes from 'prop-types';\nimport { useDispatch } from 'react-redux';\n\nimport {\n FormGroup,\n FormSelect,\n FormSelectOption,\n} from '@patternfly/react-core';\n\nimport LabelIcon from '../../../../../components/common/LabelIcon';\n\nimport { translate as __ } from '../../../../../common/I18n';\n\nimport { operatingSystemTemplateAction } from '../../RegistrationCommandsPageActions';\nimport {\n osHelperText,\n validatedOS,\n emptyOption,\n} from '../../RegistrationCommandsPageHelpers';\n\nconst OperatingSystem = ({\n operatingSystemId,\n operatingSystems,\n operatingSystemTemplate,\n handleOperatingSystem,\n handleInvalidField,\n hostGroupId,\n hostGroups,\n isLoading,\n}) => {\n const dispatch = useDispatch();\n\n // Get info about host-init-config template\n useEffect(() => {\n if (operatingSystemId) {\n dispatch(operatingSystemTemplateAction(operatingSystemId));\n }\n }, [dispatch, operatingSystemId]);\n\n // Handle hostGroupId change: reset selected OS & get info about host-init-config-template\n useEffect(() => {\n if (hostGroupId !== undefined) {\n const hostGroupOsId = hostGroups.find(\n hg => `${hg.id}` === `${hostGroupId}`\n )?.operatingsystem_id;\n\n handleOperatingSystem('');\n dispatch(operatingSystemTemplateAction(hostGroupOsId));\n }\n }, [dispatch, hostGroupId]);\n\n // Validate field\n useEffect(() => {\n if (operatingSystemId === '') {\n handleInvalidField('Operating system', true);\n return;\n }\n if (Object.entries(operatingSystemTemplate).length !== 0) {\n handleInvalidField('Operating system', !!operatingSystemTemplate?.name);\n }\n }, [operatingSystemId, operatingSystemTemplate]);\n\n return (\n \n }\n fieldId=\"reg_os\"\n >\n handleOperatingSystem(v)}\n className=\"without_select2\"\n id=\"reg_os\"\n validated={validatedOS(operatingSystemId, operatingSystemTemplate)}\n isDisabled={isLoading || operatingSystems.length === 0}\n >\n {emptyOption(operatingSystems.length)}\n {operatingSystems.map((os, i) => (\n \n ))}\n \n \n );\n};\n\nOperatingSystem.propTypes = {\n operatingSystemId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),\n hostGroupId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),\n handleOperatingSystem: PropTypes.func.isRequired,\n handleInvalidField: PropTypes.func.isRequired,\n isLoading: PropTypes.bool.isRequired,\n operatingSystems: PropTypes.array,\n hostGroups: PropTypes.array,\n operatingSystemTemplate: PropTypes.oneOfType([\n PropTypes.object,\n PropTypes.string,\n ]),\n};\n\nOperatingSystem.defaultProps = {\n operatingSystemId: undefined,\n hostGroupId: undefined,\n operatingSystems: [],\n hostGroups: [],\n operatingSystemTemplate: {},\n};\n\nexport default OperatingSystem;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/RegistrationCommands/RegistrationCommandsPage/components/fields/OperatingSystem.js","/* eslint-disable camelcase */\nimport React from 'react';\nimport PropTypes from 'prop-types';\n\nimport { FormGroup, TextInput } from '@patternfly/react-core';\nimport LabelIcon from '../../../../../components/common/LabelIcon';\n\nimport { sprintf, translate as __ } from '../../../../../common/I18n';\n\nconst Packages = ({ packages, handlePackages, configParams, isLoading }) => (\n \n }\n fieldId=\"reg_packages\"\n >\n \n \n);\n\nPackages.propTypes = {\n configParams: PropTypes.object,\n packages: PropTypes.string,\n handlePackages: PropTypes.func.isRequired,\n isLoading: PropTypes.bool.isRequired,\n};\n\nPackages.defaultProps = {\n packages: '',\n configParams: {},\n};\n\nexport default Packages;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/RegistrationCommands/RegistrationCommandsPage/components/fields/Packages.js","import React from 'react';\nimport PropTypes from 'prop-types';\n\nimport { FormGroup, TextInput } from '@patternfly/react-core';\n\nimport LabelIcon from '../../../../../components/common/LabelIcon';\n\nimport { translate as __ } from '../../../../../common/I18n';\n\nconst Repository = ({\n repo,\n handleRepo,\n repoGpgKeyUrl,\n handleRepoGpgKeyUrl,\n isLoading,\n}) => (\n <>\n \n }\n >\n \n \n \n }\n >\n \n \n >\n);\n\nRepository.propTypes = {\n repo: PropTypes.string,\n repoGpgKeyUrl: PropTypes.string,\n handleRepo: PropTypes.func.isRequired,\n handleRepoGpgKeyUrl: PropTypes.func.isRequired,\n isLoading: PropTypes.bool.isRequired,\n};\n\nRepository.defaultProps = {\n repo: '',\n repoGpgKeyUrl: '',\n};\n\nexport default Repository;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/RegistrationCommands/RegistrationCommandsPage/components/fields/Repository.js","import React from 'react';\nimport PropTypes from 'prop-types';\n\nimport {\n FormGroup,\n FormSelect,\n FormSelectOption,\n} from '@patternfly/react-core';\n\nimport LabelIcon from '../../../../../components/common/LabelIcon';\n\nimport { translate as __ } from '../../../../../common/I18n';\nimport { emptyOption } from '../../RegistrationCommandsPageHelpers';\n\nconst SmartProxy = ({\n smartProxyId,\n smartProxies,\n handleSmartProxy,\n isLoading,\n}) => (\n \n }\n >\n handleSmartProxy(v)}\n className=\"without_select2\"\n id=\"reg_smart_proxy\"\n isDisabled={isLoading || smartProxies.length === 0}\n >\n {emptyOption(smartProxies.length)}\n {smartProxies.map((sp, i) => (\n \n ))}\n \n \n);\n\nSmartProxy.propTypes = {\n smartProxyId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),\n handleSmartProxy: PropTypes.func.isRequired,\n isLoading: PropTypes.bool.isRequired,\n smartProxies: PropTypes.array,\n};\n\nSmartProxy.defaultProps = {\n smartProxyId: '',\n smartProxies: [],\n};\n\nexport default SmartProxy;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/RegistrationCommands/RegistrationCommandsPage/components/fields/SmartProxy.js","import React from 'react';\nimport PropTypes from 'prop-types';\n\nimport {\n FormGroup,\n FormSelectOption,\n FormSelect,\n} from '@patternfly/react-core';\n\nimport LabelIcon from '../../../../../components/common/LabelIcon';\nimport { translate as __ } from '../../../../../common/I18n';\n\nconst Taxonomies = ({\n organizationId,\n organizations,\n handleOrganization,\n locationId,\n locations,\n handleLocation,\n isLoading,\n}) => (\n <>\n \n }\n >\n handleOrganization(v)}\n className=\"without_select2\"\n id=\"reg_organization\"\n isDisabled={isLoading}\n isRequired\n >\n \n {organizations.map((o, i) => (\n \n ))}\n \n \n\n \n }\n >\n handleLocation(v)}\n className=\"without_select2\"\n id=\"reg_location\"\n isDisabled={isLoading}\n isRequired\n >\n \n {locations.map((l, i) => (\n \n ))}\n \n \n >\n);\n\nTaxonomies.propTypes = {\n organizationId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),\n locations: PropTypes.array,\n organizations: PropTypes.array,\n handleOrganization: PropTypes.func.isRequired,\n locationId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),\n handleLocation: PropTypes.func.isRequired,\n isLoading: PropTypes.bool.isRequired,\n};\n\nTaxonomies.defaultProps = {\n organizationId: '',\n locationId: '',\n organizations: [],\n locations: [],\n};\n\nexport default Taxonomies;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/RegistrationCommands/RegistrationCommandsPage/components/fields/Taxonomies.js","import React from 'react';\nimport PropTypes from 'prop-types';\n\nimport {\n FormGroup,\n TextInput,\n InputGroup,\n InputGroupText,\n Checkbox,\n} from '@patternfly/react-core';\n\nimport LabelIcon from '../../../../../components/common/LabelIcon';\n\nimport { sprintf, translate as __ } from '../../../../../common/I18n';\n\nconst TokenLifeTime = ({ value, onChange, handleInvalidField, isLoading }) => {\n const minValue = 1;\n const maxValue = 999999;\n\n const isValid = v => {\n if (v === 'unlimited') {\n return true;\n }\n\n return v >= minValue && v <= maxValue;\n };\n\n const setValue = v => {\n handleInvalidField('Token life time', isValid(v));\n onChange(v);\n };\n\n return (\n \n }\n >\n \n setValue(v)}\n />\n {__('hours')}\n \n setValue(value === 'unlimited' ? 4 : 'unlimited')}\n id=\"reg_unlimited_token_life_time\"\n isDisabled={isLoading}\n isChecked={value === 'unlimited'}\n />\n \n \n \n );\n};\n\nTokenLifeTime.propTypes = {\n value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),\n onChange: PropTypes.func.isRequired,\n handleInvalidField: PropTypes.func.isRequired,\n isLoading: PropTypes.bool.isRequired,\n};\n\nTokenLifeTime.defaultProps = {\n value: 4,\n};\n\nexport default TokenLifeTime;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/RegistrationCommands/RegistrationCommandsPage/components/fields/TokenLifeTime.js","import React from 'react';\nimport PropTypes from 'prop-types';\n\nimport { FormGroup, Checkbox } from '@patternfly/react-core';\nimport LabelIcon from '../../../../../components/common/LabelIcon';\n\nimport { translate as __ } from '../../../../../common/I18n';\n\nconst UpdatePackages = ({\n updatePackages,\n handleUpdatePackages,\n isLoading,\n}) => (\n \n \n {__('Update packages')}{' '}\n \n \n }\n id=\"reg_update_packages\"\n onChange={() => handleUpdatePackages(!updatePackages)}\n isDisabled={isLoading}\n isChecked={updatePackages}\n />\n \n);\n\nUpdatePackages.propTypes = {\n updatePackages: PropTypes.bool.isRequired,\n handleUpdatePackages: PropTypes.func.isRequired,\n isLoading: PropTypes.bool.isRequired,\n};\n\nexport default UpdatePackages;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/RegistrationCommands/RegistrationCommandsPage/components/fields/UpdatePackages.js","import React, { useState, useEffect } from 'react';\nimport { useSelector, useDispatch } from 'react-redux';\n\nimport {\n Alert,\n Form,\n Grid,\n GridItem,\n Tab,\n Tabs,\n TabContent,\n TabTitleText,\n Title,\n} from '@patternfly/react-core';\nimport { HelpIcon } from '@patternfly/react-icons';\n\nimport { translate as __ } from '../../../common/I18n';\nimport {\n useForemanOrganization,\n useForemanLocation,\n} from '../../../Root/Context/ForemanContext';\nimport { STATUS } from '../../../constants';\nimport Head from '../../../components/Head';\nimport Slot from '../../../components/common/Slot';\n\nimport {\n selectAPIStatusData,\n selectAPIStatusCommand,\n selectOrganizations,\n selectLocations,\n selectHostGroups,\n selectCommand,\n selectConfigParams,\n selectOperatingSystems,\n selectOperatingSystemTemplate,\n selectSmartProxies,\n selectPluginData,\n} from './RegistrationCommandsPageSelectors';\nimport { dataAction, commandAction } from './RegistrationCommandsPageActions';\n\nimport General from './components/General';\nimport Advanced from './components/Advanced';\nimport Actions from './components/Actions';\nimport Command from './components/Command';\nimport './RegistrationCommandsPage.scss';\n\nconst RegistrationCommandsPage = () => {\n const dispatch = useDispatch();\n\n // Context\n const currentOrganization = useForemanOrganization();\n const currentLocation = useForemanLocation();\n\n // Form tabs\n const [activeTab, setActiveTab] = useState(0);\n const generalTabRef = React.createRef();\n const advancedTabRef = React.createRef();\n\n // API statuses\n const apiStatusCommand = useSelector(selectAPIStatusCommand);\n const apiStatusData = useSelector(selectAPIStatusData);\n const isLoading = apiStatusData === STATUS.PENDING;\n const isGenerating = apiStatusCommand === STATUS.PENDING;\n\n // Form data\n const organizations = useSelector(selectOrganizations);\n const locations = useSelector(selectLocations);\n const hostGroups = useSelector(selectHostGroups);\n const operatingSystems = useSelector(selectOperatingSystems);\n const operatingSystemTemplate = useSelector(selectOperatingSystemTemplate);\n const smartProxies = useSelector(selectSmartProxies);\n const configParams = useSelector(selectConfigParams);\n const pluginData = useSelector(selectPluginData);\n\n // Form values\n const [organizationId, setOrganizationId] = useState(currentOrganization?.id);\n const [locationId, setLocationId] = useState(currentLocation?.id);\n const [hostGroupId, setHostGroupId] = useState();\n const [operatingSystemId, setOperatingSystemId] = useState();\n const [smartProxyId, setSmartProxyId] = useState();\n const [insecure, setInsecure] = useState(false);\n const [setupRemoteExecution, setSetupRemoteExecution] = useState('');\n const [setupInsights, setSetupInsights] = useState('');\n const [jwtExpiration, setJwtExpiration] = useState(4);\n const [packages, setPackages] = useState('');\n const [updatePackages, setUpdatePackages] = useState(false);\n const [repo, setRepo] = useState('');\n const [repoGpgKeyUrl, setRepoGpgKeyUrl] = useState('');\n const [invalidFields, setInvalidFields] = useState([]);\n\n // Command\n const command = useSelector(selectCommand);\n\n // Plugins\n const [pluginValues, setPluginValues] = useState({});\n\n const handlePluginValue = data => {\n setPluginValues({ ...pluginValues, ...data });\n };\n\n const handleInvalidField = (field, isValid) => {\n if (isValid) {\n setInvalidFields(invalidFields.filter(f => f !== field));\n } else if (!invalidFields.find(f => f === field)) {\n setInvalidFields([...invalidFields, field].sort());\n }\n };\n\n const handleSubmit = e => {\n e.preventDefault();\n\n const params = {\n organizationId,\n locationId,\n hostgroupId: hostGroupId,\n operatingsystemId: operatingSystemId,\n smartProxyId,\n insecure,\n setupRemoteExecution,\n setupInsights,\n jwtExpiration,\n packages,\n repo,\n repoGpgKeyUrl,\n updatePackages,\n ...pluginValues,\n };\n\n dispatch(commandAction(params));\n };\n\n const changeTab = (e, tab) => {\n e.preventDefault();\n setActiveTab(tab);\n };\n\n // Reset form values when Organization / Location is selected\n useEffect(() => {\n setHostGroupId();\n setOperatingSystemId();\n setSmartProxyId();\n\n dispatch(\n dataAction({ organization_id: organizationId, location_id: locationId })\n );\n }, [dispatch, organizationId, locationId]);\n\n useEffect(() => {\n if (hostGroupId === undefined && operatingSystemId === undefined) {\n return;\n }\n\n const params = {\n organization_id: organizationId,\n location_id: locationId,\n hostgroup_id: hostGroupId,\n operatingsystem_id: operatingSystemId,\n };\n\n dispatch(dataAction(params));\n\n // Disabled lint warning, need to check only hostgroup_id & operatingsystem_id\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [dispatch, hostGroupId, operatingSystemId]);\n\n return (\n <>\n \n {__('Register Host')}\n \n \n >\n );\n};\n\nexport default RegistrationCommandsPage;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/RegistrationCommands/RegistrationCommandsPage/index.js","export const REGISTRATION_PATH = '/hosts/register';\n\nexport const REGISTRATION_COMMANDS_DATA = 'REGISTRATION_COMMANDS_DATA';\nexport const REGISTRATION_COMMANDS_OS_TEMPLATE =\n 'REGISTRATION_COMMANDS_OS_TEMPLATE';\nexport const REGISTRATION_COMMANDS = 'REGISTRATION_COMMANDS';\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/RegistrationCommands/constants.js","import React from 'react';\nimport RegistrationCommandsPage from './RegistrationCommandsPage';\nimport { REGISTRATION_PATH } from './constants';\n\nexport default {\n path: REGISTRATION_PATH,\n render: props => ,\n exact: true,\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/RegistrationCommands/index.js","import { selectComponentByWeight } from '../components/common/Slot/SlotSelectors';\n\nexport const selectRouter = state => state.router;\nexport const selectRouterLocation = state => selectRouter(state).location;\nexport const selectRouterPath = state => selectRouterLocation(state).pathname;\nexport const selectRouterSearch = state => selectRouterLocation(state).search;\nexport const selectRouterHash = state => selectRouterLocation(state).hash;\nexport const selectLastHistoryAction = state => selectRouter(state).action;\nexport const selectRoutes = coreRoutes =>\n coreRoutes.concat(selectComponentByWeight('routes'));\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/RouterSelector.js","import { Route } from 'react-router-dom';\nimport React from 'react';\nimport { visit } from '../../foreman_navigation';\nimport { addGlobalFill } from '../components/common/Fill/GlobalFill';\n\nlet currentPath = window.location.href;\n\n/**\n * Adds a plugin's routes into core\n * @param {String} id plugin's id - can be its name\n * @param {Array} routes an array that contains a plugin's routes\n */\nexport const registerRoutes = (id, routes) =>\n routes.map(\n ({ render, path, beforeRendering = undefined, ...routeProps }, index) =>\n addGlobalFill(\n 'routes',\n `${id}-${index}`,\n \n renderRoute(render, renderProps, beforeRendering)\n }\n />\n )\n );\n\n/**\n * a Helper function for rendering a route\n * @param {Function} renderFn - a component's rendering function\n * @param {Object} props - routing props\n * @param {Function} beforeRenderingCallback - a callback to run before the rendering, if it returns false the rendering will terminate\n */\nexport const renderRoute = (\n renderFn,\n props,\n beforeRenderingCallback = () => true\n) => {\n const {\n location,\n location: { pathname, search },\n } = props;\n if (!beforeRenderingCallback(location)) return null;\n removeRailsContent();\n location && updatePath(`${pathname}${search}`);\n return renderFn(props);\n};\n\nexport const fallbackRoute = () => {\n const nextPath = window.location.href;\n if (currentPath !== nextPath) {\n updatePath(nextPath);\n return visit(nextPath);\n }\n return null;\n};\n\nconst updatePath = newPath => {\n if (newPath) currentPath = newPath;\n};\n\nconst removeRailsContent = () => {\n const railsContainer = document.getElementById('rails-app-content');\n if (railsContainer) railsContainer.remove();\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/RoutingService.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { translate as __ } from '../../../common/I18n';\nimport DefaultEmptyState from '../../../components/common/EmptyState';\nimport './emptypage.scss';\n\nconst EmptyPage = ({ message: { type, text } }) => (\n \n);\n\nEmptyPage.propTypes = {\n message: PropTypes.shape({\n type: PropTypes.oneOf(['empty', 'error']),\n text: PropTypes.string,\n }),\n};\n\nEmptyPage.defaultProps = {\n message: PropTypes.shape({\n type: 'empty',\n text: 'No Results',\n }),\n};\n\nexport default EmptyPage;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/common/EmptyPage/index.js","import React from 'react';\nimport { Spinner } from 'patternfly-react';\nimport './loadingpage.scss';\n\nconst LoadingPage = () => (\n \n \n
\n);\n\nexport default LoadingPage;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/common/LoadingPage/index.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { Row, Col, Spinner } from 'patternfly-react';\nimport { changeQuery } from '../../../common/urlHelpers';\n\nimport ToastsList from '../../../components/ToastsList';\nimport BreadcrumbBar from '../../../components/BreadcrumbBar';\nimport SearchBar from '../../../components/SearchBar';\nimport Head from '../../../components/Head';\n\nconst PageLayout = ({\n searchable,\n searchProps,\n searchQuery,\n onSearch,\n onBookmarkClick,\n customBreadcrumbs,\n breadcrumbOptions,\n toolbarButtons,\n header,\n toastNotifications,\n beforeToolbarComponent,\n isLoading,\n children,\n}) => (\n \n
\n \n
{header}\n \n
\n
\n {!breadcrumbOptions && (\n
\n
{header}
\n \n )}\n {customBreadcrumbs ||\n (breadcrumbOptions &&
)}\n
\n {beforeToolbarComponent}\n
\n \n {searchable && (\n \n )}\n \n \n \n \n {isLoading && (\n
\n \n
\n )}\n {toolbarButtons}\n
\n \n
\n {children}\n
\n
\n);\n\nPageLayout.propTypes = {\n children: PropTypes.node.isRequired,\n searchable: PropTypes.bool.isRequired,\n header: PropTypes.string,\n searchProps: PropTypes.shape({\n autocomplete: PropTypes.shape({\n results: PropTypes.array,\n searchQuery: PropTypes.string,\n url: PropTypes.string,\n useKeyShortcuts: PropTypes.bool,\n }),\n controller: PropTypes.string,\n bookmarks: PropTypes.shape({\n text: PropTypes.string,\n query: PropTypes.string,\n }),\n }),\n customBreadcrumbs: PropTypes.node,\n breadcrumbOptions: PropTypes.shape({\n isSwitchable: PropTypes.bool,\n resource: PropTypes.shape({\n nameField: PropTypes.string,\n resourceUrl: PropTypes.string,\n switcherItemUrl: PropTypes.string,\n resourceFilter: PropTypes.string,\n }),\n breadcrumbItems: PropTypes.arrayOf(\n PropTypes.shape({\n caption: PropTypes.oneOfType([\n PropTypes.string.isRequired,\n PropTypes.shape({\n icon: PropTypes.shape({\n url: PropTypes.string,\n alt: PropTypes.string,\n }),\n text: PropTypes.string,\n }),\n ]),\n url: PropTypes.string,\n })\n ),\n }),\n toolbarButtons: PropTypes.node,\n toastNotifications: PropTypes.array,\n onSearch: PropTypes.func,\n onBookmarkClick: PropTypes.func,\n searchQuery: PropTypes.string,\n beforeToolbarComponent: PropTypes.node,\n isLoading: PropTypes.bool,\n};\n\nPageLayout.defaultProps = {\n searchProps: {},\n header: '',\n searchQuery: '',\n toastNotifications: [],\n customBreadcrumbs: null,\n toolbarButtons: null,\n breadcrumbOptions: null,\n isLoading: false,\n onSearch: searchQuery => changeQuery({ search: searchQuery.trim(), page: 1 }),\n onBookmarkClick: searchQuery =>\n changeQuery({ search: searchQuery.trim(), page: 1 }),\n beforeToolbarComponent: null,\n};\n\nexport default PageLayout;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/common/PageLayout/PageLayout.js","import Immutable from 'seamless-immutable';\n\nexport const initialState = Immutable({\n isLoading: true,\n hasError: false,\n hasData: false,\n message: { type: 'empty', text: '' },\n});\n\nconst withDataReducer = (controller, additionalState = Immutable({})) => (\n state = initialState.merge(additionalState),\n { type, payload }\n) => {\n switch (type) {\n case `${controller}_DATA_RESOLVED`:\n return state.merge({ ...payload, isLoading: false });\n\n case `${controller}_DATA_FAILED`:\n return state.merge({ ...payload, isLoading: false, hasError: true });\n\n case `${controller}_CLEAR_ERROR`:\n return state.set('hasError', false);\n\n case `${controller}_SHOW_LOADING`:\n return state.set('isLoading', true);\n\n case `${controller}_HIDE_LOADING`:\n return state.set('isLoading', false);\n\n default:\n return state;\n }\n};\n\nexport default withDataReducer;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/common/reducerHOC/withDataReducer.js","import Immutable from 'seamless-immutable';\n\nconst initialState = Immutable({\n page: 1,\n searchQuery: '',\n itemCount: 0,\n});\n\nconst withQueryReducer = controller => (\n state = initialState,\n { type, payload }\n) => {\n switch (type) {\n case `${controller}_UPDATE_QUERY`:\n return state.merge(payload);\n\n default:\n return state;\n }\n};\n\nexport default withQueryReducer;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/common/reducerHOC/withQueryReducer.js","import React from 'react';\nimport { Route } from 'react-router-dom';\nimport PropTypes from 'prop-types';\nimport { routes } from './routes';\nimport { renderRoute } from './RoutingService';\nimport ForemanSwitch from './ForemanSwitcher';\n\nconst AppSwitcher = ({ children }) => (\n <>\n \n {routes.map(({ render, path, ...routeProps }) => (\n renderRoute(render, renderProps)}\n />\n ))}\n \n {children}\n >\n);\n\nAppSwitcher.propTypes = {\n children: PropTypes.object,\n};\n\nAppSwitcher.defaultProps = {\n children: null,\n};\n\nexport default AppSwitcher;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/index.js","import HostWizard from './HostWizard';\nimport Audits from './Audits';\nimport Models from './Models';\nimport HostDetails from './HostDetails';\nimport RegistrationCommands from './RegistrationCommands';\n\nexport const routes = [\n HostWizard,\n Audits,\n Models,\n HostDetails,\n RegistrationCommands,\n];\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/routes.js","const slotsRegistry = {};\n\nexport const add = (SlotId, fillId, component, weight, overrideProps) => {\n if (slotsRegistry[SlotId] === undefined) {\n slotsRegistry[SlotId] = {};\n }\n component = component || overrideProps;\n slotsRegistry[SlotId][fillId] = { component, weight, id: fillId };\n};\n\nexport const remove = (SlotId, fillId) => {\n const slotItems = slotsRegistry[SlotId];\n\n delete slotItems[fillId];\n};\n\nexport const getSlotComponents = id =>\n slotsRegistry[id] ? Object.values(slotsRegistry[id]) : [];\n\nexport const getFillsFromSlot = slotId => slotsRegistry[slotId];\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/services/SlotsRegistry/index.js","import uuidV1 from 'uuid/v1';\nimport { getChartConfig } from './ChartService';\n\nexport const getBarChartConfig = ({\n data,\n config,\n onclick,\n xAxisLabel,\n yAxisLabel,\n id = uuidV1(),\n}) => {\n const chartConfig = getChartConfig({\n type: 'bar',\n data,\n config,\n onclick,\n id,\n });\n\n let categories = null;\n let columns = null;\n\n if (data) {\n categories = data.map(dataItem => dataItem[0]);\n\n columns = data.map(x => x[1]);\n\n columns.unshift(xAxisLabel);\n\n chartConfig.data.columns = [columns];\n }\n\n return {\n ...chartConfig,\n\n axis: {\n x: {\n categories,\n type: 'category',\n label: xAxisLabel || null,\n },\n y: {\n label: yAxisLabel || null,\n },\n },\n };\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/services/charts/BarChartService.js","import { intl } from '../../react_app/common/I18n';\n\nconst enums = {\n SIZE: {\n LARGE: { height: 500 },\n REGULAR: { width: 240, height: 240 },\n MEDIUM: { width: 320, height: 320 },\n },\n WIDTH: {\n SMALL: 15,\n MEDIUM: 20,\n LARGE: 25,\n },\n};\n\nconst barChartEnums = {\n SIZE: {\n LARGE: { height: 500 },\n REGULAR: { width: 350, height: 350 },\n MEDIUM: { width: 450, height: 320 },\n SMALL: { height: 290 },\n },\n WIDTH: { ...enums.width },\n};\n\nconst lineChartEnums = {\n SIZE: {\n REGULAR: { width: 1000, height: 350 },\n },\n WIDTH: { ...enums.width },\n};\n\nexport const chartConfig = {\n data: {\n columns: [],\n },\n color: {\n pattern: ['#0088ce', '#ec7a08', '#3f9c35', '#005c66', 'f9d67a', '#703fec'],\n },\n tooltip: {\n show: true,\n },\n legend: { show: false },\n padding: {\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n },\n size: enums.SIZE.REGULAR,\n};\n\nexport const donutChartConfig = {\n ...chartConfig,\n donut: {\n width: enums.WIDTH.SMALL,\n label: { show: false },\n },\n};\n\nexport const donutMediumChartConfig = {\n ...donutChartConfig,\n size: enums.SIZE.MEDIUM,\n legend: { show: false },\n donut: {\n ...donutChartConfig.donut,\n width: enums.WIDTH.MEDIUM,\n },\n};\n\nexport const donutLargeChartConfig = {\n ...donutChartConfig,\n size: enums.SIZE.LARGE,\n legend: { show: true, position: 'bottom' },\n donut: {\n ...donutChartConfig.donut,\n width: enums.WIDTH.LARGE,\n },\n};\n\nexport const barChartConfig = {\n ...chartConfig,\n size: barChartEnums.SIZE.REGULAR,\n padding: null,\n};\n\nexport const mediumBarChartConfig = {\n ...barChartConfig,\n size: barChartEnums.SIZE.MEDIUM,\n};\n\nexport const smallBarChartConfig = {\n ...barChartConfig,\n size: barChartEnums.SIZE.SMALL,\n};\n\nexport const lineChartConfig = {\n ...chartConfig,\n legend: { show: true },\n size: lineChartEnums.SIZE.REGULAR,\n padding: null,\n};\n\nexport const timeseriesLineChartConfig = {\n ...lineChartConfig,\n padding: {\n top: 10,\n bottom: 70,\n left: 30,\n right: 20,\n },\n axis: {\n x: {\n type: 'timeseries',\n tick: {\n format: date => new Intl.DateTimeFormat(intl.locale).format(date),\n rotate: -40,\n },\n },\n },\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/services/charts/ChartService.consts.js","import uuidV1 from 'uuid/v1';\nimport Immutable from 'seamless-immutable';\nimport {\n donutChartConfig,\n donutLargeChartConfig,\n donutMediumChartConfig,\n barChartConfig,\n mediumBarChartConfig,\n smallBarChartConfig,\n lineChartConfig,\n timeseriesLineChartConfig,\n} from './ChartService.consts';\n\nconst chartsSizeConfig = {\n donut: {\n regular: donutChartConfig,\n medium: donutMediumChartConfig,\n large: donutLargeChartConfig,\n },\n bar: {\n regular: barChartConfig,\n small: smallBarChartConfig,\n medium: mediumBarChartConfig,\n },\n line: {\n regular: lineChartConfig,\n timeseries: timeseriesLineChartConfig,\n },\n};\n\nconst doDataExist = data => {\n if (!data || data.length === 0) {\n return false;\n }\n return data.reduce((curr, next) => {\n const value = next[1];\n\n return value !== 0 ? true : curr;\n }, false);\n};\n\nconst getColors = data =>\n data.reduce((curr, next) => {\n const key = next[0];\n const color = next[2];\n\n return color ? { ...curr, [key]: color } : curr;\n }, {});\n\nexport const getChartConfig = ({\n type,\n data,\n config,\n onclick,\n id = uuidV1(),\n}) => {\n const chartConfigForType = chartsSizeConfig[type][config];\n const colors = getColors(data);\n const colorsSize = Object.keys(colors).length;\n const dataExists = doDataExist(data);\n const longNames = [];\n const shortNames = [];\n\n let dataWithShortNames = [];\n\n if (dataExists) {\n dataWithShortNames = data.map(val => {\n const item = Immutable.asMutable(val.slice());\n longNames.push(item[0]);\n item[0] = item[0].length > 30 ? `${val[0].substring(0, 10)}...` : item[0];\n shortNames.push(item[0]);\n return item;\n });\n }\n\n return {\n ...chartConfigForType,\n id,\n data: {\n columns: dataExists ? dataWithShortNames : [],\n onclick,\n ...(colorsSize > 0 ? { colors } : {}),\n },\n // eslint-disable-next-line no-shadow\n tooltip: { format: { name: (d, value, ratio, id) => longNames[id] } },\n\n onrendered: () => {\n shortNames.forEach((name, i) => {\n const nameOfClass = name.replace(/\\W/g, '-');\n const selector = `.c3-legend-item-${nameOfClass} > title`;\n // eslint-disable-next-line no-undef\n const hasTooltip = d3.select(selector)[0][0];\n\n if (!hasTooltip) {\n // eslint-disable-next-line no-undef\n d3.select(`.c3-legend-item-${nameOfClass}`)\n .append('svg:title')\n .text(longNames[i]);\n }\n });\n },\n };\n};\n\nexport const navigateToSearch = (url, searchFilters, data) => {\n let val = searchFilters[data.id] || data.id;\n let setUrl;\n\n window.tfm.tools.showSpinner();\n\n if (url.includes('~VAL1~') || url.includes('~VAL2~')) {\n const vals = val.split(' ');\n\n const val1 = encodeURIComponent(vals[0]);\n const val2 = encodeURIComponent(vals[1]);\n\n setUrl = url.replace('~VAL1~', val1).replace('~VAL2~', val2);\n } else {\n if (val.includes(' ')) {\n val = encodeURIComponent(val);\n }\n setUrl = url.replace('~VAL~', val);\n }\n window.location.href = setUrl;\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/services/charts/ChartService.js","import uuidV1 from 'uuid/v1';\nimport { getChartConfig, navigateToSearch } from './ChartService';\n\nexport const getDonutChartConfig = ({\n data,\n config,\n onclick,\n searchUrl,\n searchFilters,\n id = uuidV1(),\n}) =>\n getChartConfig({\n type: 'donut',\n data,\n config,\n id,\n onclick: (d, element) => {\n if (onclick) onclick(d, element);\n if (searchUrl) navigateToSearch(searchUrl, searchFilters || {}, d);\n },\n });\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/services/charts/DonutChartService.js","import uuidV1 from 'uuid/v1';\nimport { getChartConfig } from './ChartService';\n\nexport const getLineChartConfig = ({\n data,\n config,\n onclick,\n id = uuidV1(),\n xAxisDataLabel,\n axisOpts,\n}) => {\n const chartConfig = getChartConfig({\n type: 'line',\n data,\n config,\n id,\n onclick,\n });\n\n if (chartConfig.data && chartConfig.data.columns) {\n chartConfig.data.columns = chartConfig.data.columns.map(col => {\n const [label, values] = col;\n // destruct data into format line chart accepts,\n // remove last item in column as it specifies the color\n return [label, ...values];\n });\n }\n\n if (config === 'timeseries' && xAxisDataLabel) {\n chartConfig.data.x = xAxisDataLabel;\n } else if (config === 'timeseries' && !xAxisDataLabel) {\n throw new Error('xAxisDataLabel is missing for timeseries line graph');\n }\n\n chartConfig.axis = { ...chartConfig.axis, ...axisOpts };\n\n delete chartConfig.tooltip;\n\n return chartConfig;\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/services/charts/LineChartService.js","/* eslint-disable jquery/no-data */\n/* eslint-disable jquery/no-attr */\n/* eslint-disable jquery/no-class */\n/* eslint-disable jquery/no-text */\n\nimport $ from 'jquery';\nimport {\n SpiceMainConn,\n sendCtrlAltDel as _sendCtrlAltDel,\n} from '@spice-project/spice-html5';\nimport { sprintf, translate as __ } from './react_app/common/I18n';\n\nlet sc = null;\n\nexport function startSpice() {\n const scheme = 'ws://';\n\n const host = window.location.hostname;\n const port = $('#spice-area').data('port');\n const password = $('#spice-area').data('password');\n\n if (!host || !port) {\n // eslint-disable-next-line no-console\n console.log(__('must set host and port'));\n return;\n }\n\n const uri = `${scheme + host}:${port}`;\n\n try {\n sc = new SpiceMainConn({\n uri,\n screen_id: 'spice-screen',\n password,\n onerror: spiceError,\n onsuccess: spiceSuccess,\n });\n } catch (e) {\n alert(e.toString());\n disconnect();\n }\n}\n\nexport function disconnect() {\n if (sc) {\n sc.stop();\n }\n}\n\nfunction spiceError(e) {\n $('#spice-status').text(e);\n $('#spice-status')\n .removeClass('label-success')\n .addClass('label-danger');\n disconnect();\n}\n\nfunction spiceSuccess(m) {\n $('#spice-status').text(\n sprintf(\n __('Connected (unencrypted) to: %s'),\n $('#spice-status').attr('data-host')\n )\n );\n $('#spice-status').addClass('label-success');\n}\n\nexport function connectXPI() {\n if ($('#spice-xpi').length === 0) {\n $('#spice-area').append(\n '