\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 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\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-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 store from './react_app/redux';\nimport * as LayoutActions from './react_app/components/Layout/LayoutActions';\nimport { deprecate } from './react_app/common/DeprecationService';\n\nwindow.Turbolinks = {\n visit: url => {\n deprecate(\n 'Turbolinks.visit',\n 'react router or visit(
) method, or legacy tfm.nav.visit()',\n '2.1'\n );\n visit(url);\n },\n};\n\nexport const visit = url => {\n window.location.href = url;\n};\n\nexport const reloadPage = () => {\n window.location.reload();\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 store.dispatch(LayoutActions.changeLocation(loc));\n};\n\nexport const changeOrganization = org => {\n store.dispatch(LayoutActions.changeOrganization(org));\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 $ from 'jquery';\n\nimport 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\nconst railsNotificationToToastNotification = ({ link, type, message }) => {\n const toast = { type, message };\n\n if (link) {\n toast.link = { href: link.href, children: link.text };\n }\n\n return toast;\n};\n\nconst importToastNotificationsFromRails = () => {\n const toastNotificationsContainer = $('#toast-notifications-container');\n if (toastNotificationsContainer.length === 0) return;\n\n const notifications = toastNotificationsContainer.data('notifications');\n if (!notifications) return;\n\n // notify each rails notification\n notifications\n .map(railsNotification =>\n railsNotificationToToastNotification(railsNotification)\n )\n .forEach(toastNotification => notify(toastNotification));\n\n // remove both jquery cache and dom entry to avoid ajax ContentLoad events\n // reloading our toast notifications\n toastNotificationsContainer.attr('data-notifications', '').removeData();\n};\n\n// load toast notifications from Rails on ContentLoad\n// to accommodate rails flash syntax\n$(document).on('ContentLoad', () => {\n clear();\n importToastNotificationsFromRails();\n});\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\nimport $ from 'jquery';\nimport URI from 'urijs';\nimport { translate as __ } from './react_app/common/I18n';\nimport { deprecate } from './react_app/common/DeprecationService';\n\nimport { showLoading, hideLoading, visit } 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 $('[data-table=inline]')\n .not('.dataTable')\n .DataTable({\n language: {\n searchPlaceholder: __('Filter...'),\n },\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 searchPlaceholder: __('Filter...'),\n },\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 el.find('[rel=\"twipsy\"]').tooltip({ container: 'body' });\n el.find('.ellipsis').tooltip({\n container: 'body',\n title() {\n return this.scrollWidth > this.clientWidth ? this.textContent : null;\n },\n });\n el.find('*[title]')\n .not('*[rel],.fa,.pficon')\n .tooltip({ container: 'body' });\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// handle table updates via turoblinks\nexport function updateTable(element) {\n deprecate('updateTable', 'react Table component', '2.1');\n const uri = new URI(window.location.href);\n\n const values = {};\n\n if (['per_page', 'search-form'].includes(element.id)) {\n values.page = '1';\n } else {\n values.page = $('#cur_page_num').val();\n }\n\n const searchTerm = $(element)\n .find('.autocomplete-input')\n .val();\n if (searchTerm !== undefined) {\n values.search = searchTerm.trim();\n }\n values.per_page = $('#pagination-row-dropdown')\n .text()\n .trim();\n uri.setSearch(values);\n\n visit(uri.toString());\n return false;\n}\n\n// generates an absolute, needed in case of running Foreman from a subpath\nexport function foremanUrl(path) {\n return window.URL_PREFIX + path;\n}\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/foreman_tools.js","/* eslint-disable jquery/no-val */\n/* eslint-disable jquery/no-attr */\n\nimport $ from 'jquery';\n\nexport function trendTypeSelected({ value }) {\n $('#trend_trendable_id, #trend_name')\n .attr('disabled', value !== 'FactName')\n .val('');\n}\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/foreman_trends.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","/* 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';\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.getItem('hostQuery');\n const uriSearch = getURIsearch();\n\n // clear selected hosts if new search occurs\n if (uriSearch !== '' && hostQuery !== uriSearch) {\n cleanHostsSelection();\n sessionStorage.setItem('hostQuery', uriSearch);\n return;\n }\n sessionStorage.setItem('hostQuery', 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 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 $('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 $('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 = metadata =>\n forceSingleton('Context', () => React.createContext(metadata));\nexport const useForemanContext = () => React.useContext(getForemanContext());\n\nexport const useForemanVersion = () => useForemanContext().version;\nexport const useForemanSettings = () => useForemanContext().UISettings;\nexport const usePaginationOptions = () => useForemanSettings().perPageOptions;\nexport const useForemanDocUrl = () => useForemanContext().docUrl;\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 { Router } from 'react-router-dom';\nimport history from '../history';\nimport { getForemanContext } from '../Root/Context/ForemanContext';\nimport Layout, { propTypes as LayoutPropTypes } from '../components/Layout';\nimport AppSwitcher from '../routes';\n\nconst ReactApp = ({ data: { layout, metadata } }) => {\n const ForemanContext = getForemanContext(metadata);\n return (\n \n \n \n \n \n \n \n );\n};\n\nReactApp.propTypes = {\n data: PropTypes.shape({\n layout: LayoutPropTypes.data,\n metadata: PropTypes.object.isRequired,\n }).isRequired,\n};\n\nexport default ReactApp;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/Root/ReactApp.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 => props => {\n const didMount = useRef(false);\n const {\n history: { action },\n location: { search },\n } = props;\n useEffect(() => {\n if (action === 'POP' && didMount.current) {\n callback(props);\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 [this.locale] = locale.split('-');\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');\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 get componentName() {\n return this.getAttribute('name');\n }\n get props() {\n return this.dataset.props !== '' ? JSON.parse(this.dataset.props) : {};\n }\n get mountPoint() {\n if (!this._mountPoint) {\n this._mountPoint = this;\n }\n\n return this._mountPoint;\n }\n\n connectedCallback() {\n try {\n mountNode(this.componentName, this, this.props, true);\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error(\n `Unable to mount react-component: ${this.componentName}`,\n error\n );\n }\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 react-component: ${this.componentName}`,\n error\n );\n }\n }\n}\n\nif (!window.customElements.get('react-component')) {\n window.customElements.define('react-component', ReactComponentElement);\n}\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/common/MountingService.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 * Update title of document\n * @param {String} title - the title\n */\nexport const updateDocumentTitle = title => {\n document.title = title;\n};\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';\nimport { foremanUrl } from '../../foreman_tools';\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}`);\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\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};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/common/helpers.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","if (!window.sessionStorage) {\n window.sessionStorage = {\n getItem: () => {},\n setItem: () => {},\n };\n}\n\nconst getValue = key => {\n const value = window.sessionStorage.getItem(key) || 'null';\n\n return JSON.parse(value);\n};\n\nconst setValue = (key, value) =>\n window.sessionStorage.setItem(key, JSON.stringify(value));\n\nexport const notificationsDrawer = {\n getIsOpened: () => getValue('isDrawerOpen'),\n setIsOpened: value => setValue('isDrawerOpen', value),\n getExpandedGroup: () => getValue('expandedGroup'),\n setExpandedGroup: value => setValue('expandedGroup', value),\n getHasUnreadMessages: () => getValue('hasUnreadMessages'),\n setHasUnreadMessages: value => setValue('hasUnreadMessages', value),\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/common/sessionStorage.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 URI params\n */\nexport const getParams = () => ({\n page: getURIpage(),\n perPage: getURIperPage() || null,\n searchQuery: getURIsearch(),\n});\n\n/**\n * Get updated Stringified params\n */\nexport const stringifyParams = ({\n page = 1,\n perPage = 25,\n searchQuery = '',\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 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';\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 { 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 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';\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 {\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 \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 \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: 100 });\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 bookmarkFormSchema = Yup.object().shape({\n name: Yup.string()\n .max(...maxLengthMsg(254))\n .required(requiredMsg()),\n query: Yup.string()\n .max(...maxLengthMsg(4096))\n .required(requiredMsg()),\n});\n\nconst BookmarkForm = ({\n url,\n submitForm,\n controller,\n onCancel,\n initialValues,\n setModalClosed,\n}) => {\n const handleSubmit = async (values, actions) => {\n await submitForm({\n url,\n values: { ...values, controller },\n item: 'Bookmarks',\n message: __('Bookmark was successfully created.'),\n });\n setModalClosed();\n };\n\n return (\n handleSubmit(values, actions)}\n initialValues={initialValues}\n validationSchema={bookmarkFormSchema}\n onCancel={onCancel}\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};\n\nBookmarkForm.defaultProps = {\n onCancel: noop,\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 = ({ setModalClosed, onEnter, title, controller, url }) => (\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};\n\nSearchModal.defaultProps = {\n title: __('Create Bookmark'),\n onEnter: noop,\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 './breadcrumbswitcher.scss';\n\nclass BreadcrumbBar extends React.Component {\n handleOpen() {\n const {\n data: { 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 data: { breadcrumbItems, isSwitchable, 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 data: 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: Breadcrumb.propTypes.items,\n }),\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 data: {\n breadcrumbItems: [],\n isSwitchable: false,\n },\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 { Breadcrumb as PfBreadcrumb } from 'patternfly-react';\nimport EllipsisWithTooltip from 'react-ellipsis-with-tooltip';\nimport './Breadcrumbs.scss';\n\nconst Breadcrumb = ({\n items,\n title,\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 {\n caption,\n caption: { icon, text },\n } = item;\n const overrideTitle = active && titleReplacement;\n const itemTitle = overrideTitle || text || caption;\n const inner = active ? (\n \n {itemTitle}\n \n ) : (\n itemTitle\n );\n\n return (\n \n {icon &&
}{' '}\n {inner}\n \n );\n })}\n {children}\n \n );\n};\n\nBreadcrumb.propTypes = {\n children: PropTypes.node,\n title: PropTypes.bool,\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 title: false,\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 { navigateToSearch } from '../../../services/charts/DonutChartService';\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 handleChartClick =\n chart.search && chart.search.match(/=$/)\n ? null\n : navigateToSearch.bind(null, chart.search);\n const chartProps = {\n data: chart.data ? chart.data : undefined,\n key: `${chart.id}-chart`,\n onclick: handleChartClick,\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 \n );\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","export const CHARTS_DATA = 'CHARTS_DATA';\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/ChartBox/ChartBoxConstants.js","import React, { useEffect } from 'react';\nimport { useSelector, useDispatch, shallowEqual } from 'react-redux';\nimport PropTypes from 'prop-types';\nimport { CHARTS_DATA } from './ChartBoxConstants';\nimport { translate as __ } from '../../common/I18n';\nimport ChartBox from './ChartBox';\n\nimport { get } from '../../redux/API';\nimport {\n selectAPIResponse,\n selectAPIErrorMessage,\n selectAPIStatus,\n} from '../../redux/API/APISelectors';\n\nconst ConnectedChartBox = ({\n className,\n config,\n noDataMsg,\n errorText,\n type,\n chart,\n tip,\n}) => {\n const { id, url, title, search } = chart;\n const key = `${CHARTS_DATA}_${id}`;\n const dispatch = useDispatch();\n useEffect(() => {\n dispatch(get({ key, url }));\n }, [key, url, dispatch]);\n const chartData = useSelector(\n state => selectAPIResponse(state, key),\n shallowEqual\n );\n const error = useSelector(state => selectAPIErrorMessage(state, key));\n const status = useSelector(state => selectAPIStatus(state, key));\n return (\n \n );\n};\n\nConnectedChartBox.propTypes = {\n chart: PropTypes.shape({\n id: PropTypes.string,\n url: PropTypes.string,\n search: PropTypes.string,\n title: PropTypes.string,\n }).isRequired,\n className: PropTypes.string,\n config: PropTypes.string,\n noDataMsg: PropTypes.string,\n errorText: PropTypes.string,\n type: PropTypes.oneOf(['donut', 'bar']).isRequired,\n tip: PropTypes.string,\n};\n\nConnectedChartBox.defaultProps = {\n className: '',\n config: 'regular',\n noDataMsg: __('No data available'),\n errorText: '',\n tip: '',\n};\n\nexport default ConnectedChartBox;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/ChartBox/index.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","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, markCharacterEdits } 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 const markEdits = markCharacterEdits({\n threshold: 30,\n markLongDistanceDiff: true,\n });\n\n // old,new Text\n if (patch === '') {\n const gitDiff = getDiff(oldText, newText);\n const files = parseDiff(gitDiff);\n const hunk = files[0].hunks;\n\n return (\n hunk && \n );\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 renderPath,\n showHide,\n showImport,\n showPreview,\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 template: PropTypes.string,\n templateClass: PropTypes.string,\n name: PropTypes.string,\n title: PropTypes.string,\n renderPath: 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 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';\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 renderPath,\n revertChanges,\n selectedHost,\n selectedView,\n showHide,\n showImport,\n showPreview,\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 \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 renderPath: 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 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 showHide: false,\n template: '',\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 {\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 { 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 { navigateToSearch } from '../../../services/charts/DonutChartService';\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 handleChartClick =\n search && search.match(/=$/) ? null : navigateToSearch.bind(null, search);\n\n const chartProps = {\n data: chartData,\n key: `chart-${id}`,\n onclick: handleChartClick,\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 = ({ data: { 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 data: PropTypes.shape({\n id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),\n path: PropTypes.string,\n title: PropTypes.string,\n search: PropTypes.string,\n }).isRequired,\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 if (selectModalExists(getState(), id)) {\n throw new Error(`ForemanModal with ID ${id} already exists`);\n }\n return dispatch({\n type: ADD_MODAL,\n payload: { id, isOpen, isSubmitting },\n });\n};\n\nconst modalAction = actionType => ({ id }) => (dispatch, getState) => {\n if (!selectModalExists(getState(), id)) {\n throw new Error(\n `${actionType} error: Modal 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 React from 'react';\nimport PropTypes from 'prop-types';\n\nimport { VerticalNav } from 'patternfly-react';\nimport { translate as __ } from '../../common/I18n';\nimport { noop } from '../../common/helpers';\n\nimport { getActive, getCurrentPath, handleMenuClick } from './LayoutHelper';\nimport LayoutContainer from './components/LayoutContainer';\nimport TaxonomySwitcher from './components/TaxonomySwitcher';\nimport UserDropdowns from './components/UserDropdowns';\nimport './layout.scss';\n\nclass Layout extends React.Component {\n componentDidMount() {\n const {\n items,\n data,\n fetchMenuItems,\n changeLocation,\n currentLocation,\n changeOrganization,\n currentOrganization,\n changeActiveMenu,\n activeMenu,\n isCollapsed,\n onCollapse,\n } = this.props;\n if (items.length === 0) fetchMenuItems(data);\n if (isCollapsed) onCollapse();\n\n const activeURLMenu = getActive(data.menu, getCurrentPath());\n if (activeMenu !== activeURLMenu.title) {\n changeActiveMenu(activeURLMenu);\n }\n\n if (\n data.taxonomies.locations &&\n !!data.locations.current_location &&\n currentLocation !== data.locations.current_location\n ) {\n const initialLocTitle = data.locations.current_location;\n const initialLocId = data.locations.available_locations.find(\n loc => loc.title === initialLocTitle\n ).id;\n changeLocation({ title: initialLocTitle, id: initialLocId });\n }\n\n if (\n data.taxonomies.organizations &&\n !!data.orgs.current_org &&\n currentOrganization !== data.orgs.current_org\n ) {\n const initialOrgTitle = data.orgs.current_org;\n const initialOrgId = data.orgs.available_organizations.find(\n org => org.title === initialOrgTitle\n ).id;\n changeOrganization({ title: initialOrgTitle, id: initialOrgId });\n }\n }\n\n render() {\n const {\n items,\n data,\n isLoading,\n isCollapsed,\n onExpand,\n onCollapse,\n changeActiveMenu,\n changeOrganization,\n changeLocation,\n currentOrganization,\n currentLocation,\n activeMenu,\n children,\n history,\n } = this.props;\n\n return (\n \n \n handleMenuClick(primary, activeMenu, changeActiveMenu)\n }\n onNavigate={({ href }) => history.push(href)}\n activePath={`/${__(activeMenu || 'active')}/`}\n onCollapse={onCollapse}\n onExpand={onExpand}\n {...this.props}\n >\n \n \n \n \n \n \n {children}\n \n );\n }\n}\n\nLayout.propTypes = {\n children: PropTypes.node,\n history: PropTypes.shape({\n push: PropTypes.func,\n }).isRequired,\n currentOrganization: PropTypes.string,\n currentLocation: PropTypes.string,\n isLoading: PropTypes.bool,\n isCollapsed: PropTypes.bool,\n activeMenu: PropTypes.string,\n fetchMenuItems: PropTypes.func,\n changeActiveMenu: PropTypes.func,\n changeOrganization: PropTypes.func,\n changeLocation: PropTypes.func,\n onExpand: PropTypes.func,\n onCollapse: 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({\n brand: PropTypes.string,\n stop_impersonation_url: PropTypes.string.isRequired,\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: 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 orgs: 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 root: PropTypes.string.isRequired,\n logo: PropTypes.string.isRequired,\n notification_url: PropTypes.string.isRequired,\n taxonomies: PropTypes.shape({\n locations: PropTypes.bool.isRequired,\n organizations: PropTypes.bool.isRequired,\n }),\n user: 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 }),\n};\n\nLayout.defaultProps = {\n children: null,\n items: [],\n data: {},\n currentOrganization: 'Any Organization',\n currentLocation: 'Any Location',\n isLoading: false,\n isCollapsed: false,\n activeMenu: '',\n fetchMenuItems: noop,\n changeActiveMenu: noop,\n changeOrganization: noop,\n changeLocation: noop,\n onExpand: noop,\n onCollapse: noop,\n};\n\nexport default Layout;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Layout/Layout.js","import { combineMenuItems } from './LayoutHelper';\nimport {\n LAYOUT_SHOW_LOADING,\n LAYOUT_HIDE_LOADING,\n LAYOUT_UPDATE_ITEMS,\n LAYOUT_CHANGE_LOCATION,\n LAYOUT_CHANGE_ACTIVE,\n LAYOUT_CHANGE_ORG,\n LAYOUT_EXPAND,\n LAYOUT_COLLAPSE,\n} from './LayoutConstants';\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 }) => dispatch => {\n dispatch({\n type: LAYOUT_CHANGE_ACTIVE,\n payload: {\n activeMenu: title,\n },\n });\n};\n\nexport const fetchMenuItems = data => dispatch => {\n const items = combineMenuItems(data);\n dispatch({\n type: LAYOUT_UPDATE_ITEMS,\n payload: {\n items,\n },\n });\n};\n\nexport const changeOrganization = org => dispatch => {\n dispatch({\n type: LAYOUT_CHANGE_ORG,\n payload: { org },\n });\n};\n\nexport const changeLocation = location => dispatch => {\n dispatch({\n type: LAYOUT_CHANGE_LOCATION,\n payload: {\n location,\n },\n });\n};\n\nexport const onExpand = () => ({\n type: LAYOUT_EXPAND,\n});\n\nexport const onCollapse = () => ({\n type: LAYOUT_COLLAPSE,\n});\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Layout/LayoutActions.js","export const LAYOUT_SHOW_LOADING = 'LAYOUT_SHOW_LOADING';\nexport const LAYOUT_HIDE_LOADING = 'LAYOUT_HIDE_LOADING';\nexport const LAYOUT_CHANGE_LOCATION = 'LAYOUT_CHANGE_LOCATION';\nexport const LAYOUT_CHANGE_ORG = 'LAYOUT_CHANGE_ORG';\nexport const LAYOUT_CHANGE_ACTIVE = 'LAYOUT_CHANGE_ACTIVE';\nexport const LAYOUT_UPDATE_ITEMS = 'LAYOUT_UPDATE_ITEMS';\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 {\n changeOrganization,\n changeLocation,\n} from '../../../foreman_navigation';\nimport { translate as __ } from '../../common/I18n';\nimport { removeLastSlashFromPath } from '../../common/helpers';\n\nexport const getCurrentPath = () =>\n removeLastSlashFromPath(window.location.pathname);\n\nexport const getActive = (items, path) => {\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' ? 'visible-xs-block' : '',\n };\n items.push(translatedItem);\n });\n\n if (data.taxonomies.organizations) {\n items.push(createOrgItem(data.orgs.available_organizations));\n }\n\n if (data.taxonomies.locations) {\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 url: '/organizations/clear',\n onClick: () => {\n changeOrganization(__('Any Organization'));\n },\n };\n const childrenArray = [];\n childrenArray.push(anyOrg);\n\n orgs.forEach(org => {\n const childObject = {\n type: org.type,\n name: isEmpty(org.title) ? org.title : __(org.title),\n onClick: () => {\n changeOrganization(__(org.title));\n },\n url: org.href,\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: 'visible-xs-block',\n };\n return orgItem;\n};\n\nconst createLocationItem = locations => {\n const anyLoc = {\n name: __('Any Location'),\n url: '/locations/clear',\n onClick: () => {\n changeLocation(__('Any Location'));\n },\n };\n const childrenArray = [];\n childrenArray.push(anyLoc);\n\n locations.forEach(loc => {\n const childObject = {\n type: loc.type,\n name: isEmpty(loc.title) ? loc.title : __(loc.title),\n onClick: () => {\n changeLocation(__(loc.title));\n },\n url: loc.href,\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: 'visible-xs-block',\n };\n return locItem;\n};\n\nexport const checkCollapsed = () => {\n const collapsedState = sessionStorage.getItem(\n `[\"navCollapsed\",\"pinnedPath\"]`\n );\n return !!collapsedState && collapsedState.includes('true');\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Layout/LayoutHelper.js","import Immutable from 'seamless-immutable';\nimport { checkCollapsed } from './LayoutHelper';\n\nimport {\n LAYOUT_SHOW_LOADING,\n LAYOUT_HIDE_LOADING,\n LAYOUT_UPDATE_ITEMS,\n LAYOUT_CHANGE_ORG,\n LAYOUT_CHANGE_LOCATION,\n LAYOUT_CHANGE_ACTIVE,\n LAYOUT_EXPAND,\n LAYOUT_COLLAPSE,\n} from './LayoutConstants';\n\nconst initialState = Immutable({\n items: [],\n isLoading: false,\n isCollapsed: checkCollapsed(),\n activeMenu: 'initialActive',\n currentOrganization: { title: 'Any Organization' },\n currentLocation: { title: 'Any Location' },\n});\n\nexport default (state = initialState, action) => {\n const { payload: { items, activeMenu, org, location } = {}, type } = action;\n\n switch (type) {\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_UPDATE_ITEMS:\n return state.set('items', items);\n\n case LAYOUT_CHANGE_ORG:\n return state.set('currentOrganization', org);\n\n case LAYOUT_CHANGE_LOCATION:\n return state.set('currentLocation', location);\n\n case LAYOUT_CHANGE_ACTIVE:\n return state.set('activeMenu', 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 { createSelector } from 'reselect';\nimport { get, snakeCase } from 'lodash';\nimport { noop } from '../../common/helpers';\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 get(selectLayout(state), 'currentLocation.title');\nexport const selectCurrentOrganization = state =>\n get(selectLayout(state), 'currentOrganization.title');\n\nexport const patternflyMenuItemsSelector = createSelector(\n selectMenuItems,\n selectCurrentLocation,\n selectCurrentOrganization,\n (items, currentLocation, currentOrganization) =>\n patternflyItems(items, currentLocation, currentOrganization)\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\nconst patternflyItems = (data, currentLocation, currentOrganization) =>\n data.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\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Layout/LayoutSelectors.js","import React, { useState } from 'react';\nimport PropTypes from 'prop-types';\n\nimport { OverlayTrigger, Tooltip, Icon, 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 \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 from 'react';\nimport PropTypes from 'prop-types';\nimport classNames from 'classnames';\n\nconst LayoutContainer = ({ isCollapsed, children }) => {\n const classes = classNames(\n 'react-container container-fluid nav-pf-persistent-secondary',\n {\n 'collapsed-nav': isCollapsed,\n }\n );\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 from 'react';\nimport PropTypes from 'prop-types';\nimport { Dropdown } from 'patternfly-react';\n\nconst NavDropdown = ({ activeKey, activeHref, children, ...props }) => (\n \n);\nNavDropdown.propTypes = {\n /** Child node - contents of the element */\n children: PropTypes.node.isRequired,\n /** Additional element css classes */\n className: PropTypes.string,\n /** activeKey, activeHref props for bootstrap navItems */\n activeHref: PropTypes.string,\n activeKey: PropTypes.string,\n};\nNavDropdown.defaultProps = {\n className: '',\n activeHref: '',\n activeKey: '',\n};\nexport default NavDropdown;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Layout/components/NavDropdown.js","import React from 'react';\nimport PropTypes from 'prop-types';\n\nconst NavItem = ({ activeKey, activeHref, children, className, ...props }) => (\n \n {children}\n \n);\nNavItem.propTypes = {\n /** Child node - contents of the element */\n children: PropTypes.node.isRequired,\n /** Additional element css classes */\n className: PropTypes.string,\n /** activeKey, activeHref props for bootstrap navItems */\n activeHref: PropTypes.string,\n activeKey: PropTypes.string,\n};\nNavItem.defaultProps = {\n className: '',\n activeHref: '',\n activeKey: '',\n};\nexport default NavItem;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Layout/components/NavItem.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport NavItem from './NavItem';\nimport { noop } from '../../../common/helpers';\nimport { translate as __ } from '../../../common/I18n';\n\nclass TaxonomyDropdown extends React.Component {\n constructor(props) {\n super(props);\n this.state = { searchValue: '' };\n }\n\n render() {\n const {\n taxonomyType,\n currentTaxonomy,\n taxonomies,\n id,\n changeTaxonomy,\n anyTaxonomyText,\n manageTaxonomyText,\n anyTaxonomyURL,\n manageTaxonomyURL,\n } = this.props;\n\n const filteredTaxonomies = () => {\n const { searchValue } = this.state;\n\n if (searchValue === '') {\n return this.props.taxonomies;\n }\n\n return this.props.taxonomies.filter(item =>\n item.title.toLowerCase().includes(searchValue.toLowerCase())\n );\n };\n\n return (\n \n \n {__(currentTaxonomy)}\n \n \n \n \n );\n }\n}\n\nTaxonomyDropdown.propTypes = {\n taxonomyType: PropTypes.string.isRequired,\n currentTaxonomy: PropTypes.string.isRequired,\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 id: PropTypes.string.isRequired,\n changeTaxonomy: PropTypes.func,\n anyTaxonomyText: PropTypes.string.isRequired,\n manageTaxonomyText: PropTypes.string.isRequired,\n anyTaxonomyURL: PropTypes.string.isRequired,\n manageTaxonomyURL: PropTypes.string.isRequired,\n};\n\nTaxonomyDropdown.defaultProps = {\n changeTaxonomy: noop,\n};\n\nexport default TaxonomyDropdown;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Layout/components/TaxonomyDropdown.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { Nav, Spinner } from 'patternfly-react';\nimport { noop } from '../../../common/helpers';\n\nimport NavItem from './NavItem';\nimport TaxonomyDropdown from './TaxonomyDropdown';\n\nconst TaxonomySwitcher = ({\n currentOrganization,\n currentLocation,\n organizations,\n locations,\n taxonomiesBool,\n isLoading,\n onLocationClick,\n onOrgClick,\n}) => (\n \n);\nTaxonomySwitcher.propTypes = {\n onLocationClick: PropTypes.func,\n onOrgClick: PropTypes.func,\n isLoading: PropTypes.bool,\n currentOrganization: PropTypes.string,\n currentLocation: PropTypes.string,\n organizations: PropTypes.arrayOf(\n PropTypes.shape({\n id: PropTypes.number.isRequired,\n title: PropTypes.string,\n href: PropTypes.string.isRequired,\n })\n ).isRequired,\n locations: PropTypes.arrayOf(\n PropTypes.shape({\n id: PropTypes.number.isRequired,\n title: PropTypes.string,\n href: PropTypes.string.isRequired,\n })\n ).isRequired,\n taxonomiesBool: PropTypes.shape({\n locations: PropTypes.bool.isRequired,\n organizations: PropTypes.bool.isRequired,\n }).isRequired,\n};\nTaxonomySwitcher.defaultProps = {\n isLoading: false,\n currentLocation: 'Any Location',\n currentOrganization: 'Any Organization',\n onLocationClick: noop,\n onOrgClick: noop,\n};\nexport default TaxonomySwitcher;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Layout/components/TaxonomySwitcher.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { Dropdown, VerticalNav, Icon, MenuItem } from 'patternfly-react';\nimport { get } from 'lodash';\nimport NotificationContainer from '../../notifications';\nimport NavDropdown from './NavDropdown';\nimport NavItem from './NavItem';\nimport ImpersonateIcon from './ImpersonateIcon';\nimport { translate as __ } from '../../../common/I18n';\n\nconst UserDropdowns = ({\n activeKey, // eslint-disable-line react/prop-types\n activeHref, // eslint-disable-line react/prop-types\n user,\n changeActiveMenu,\n notificationUrl,\n stopImpersonationUrl,\n ...props\n}) => {\n const userInfo = get(user, 'current_user.user');\n const impersonateIcon = (\n \n );\n return (\n \n \n \n \n {user.impersonated_by && impersonateIcon}\n {userInfo && (\n \n )}\n \n );\n};\n\nUserDropdowns.propTypes = {\n /** Additional element css classes */\n className: PropTypes.string,\n /** User Data Array */\n user: PropTypes.object,\n /** notification URL */\n notificationUrl: PropTypes.string,\n /** changeActiveMenu Func */\n changeActiveMenu: PropTypes.func,\n stopImpersonationUrl: PropTypes.string,\n};\nUserDropdowns.defaultProps = {\n className: '',\n user: {},\n notificationUrl: '',\n changeActiveMenu: null,\n stopImpersonationUrl: '',\n};\nexport default UserDropdowns;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Layout/components/UserDropdowns.js","import { bindActionCreators } from 'redux';\nimport { connect } from 'react-redux';\nimport { withRouter } from 'react-router-dom';\n\nimport * as actions from './LayoutActions';\nimport reducer from './LayoutReducer';\nimport {\n patternflyMenuItemsSelector,\n selectActiveMenu,\n selectCurrentOrganization,\n selectCurrentLocation,\n selectIsLoading,\n selectIsCollapsed,\n} from './LayoutSelectors';\n\nimport Layout from './Layout';\n\n// map state to props\nconst mapStateToProps = state => ({\n items: patternflyMenuItemsSelector(state),\n isLoading: selectIsLoading(state),\n isCollapsed: selectIsCollapsed(state),\n activeMenu: selectActiveMenu(state),\n currentOrganization: selectCurrentOrganization(state),\n currentLocation: selectCurrentLocation(state),\n});\n\n// map action dispatchers to props\nconst mapDispatchToProps = dispatch => bindActionCreators(actions, dispatch);\n\n// export prop-types\nexport const { propTypes } = Layout;\n\n// export reducers\nexport const reducers = { layout: reducer };\n\n// export connected component\nexport default withRouter(connect(mapStateToProps, mapDispatchToProps)(Layout));\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 LoginPageCaption from './components/LoginPageCaption';\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 card={{\n title: __('Log in to your account'),\n form: {\n ...defaultFormProps,\n submitError: submitErrors,\n additionalFields: (\n \n ),\n },\n }}\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 React, { Fragment } from 'react';\nimport PropTypes from 'prop-types';\nimport { translate as __ } from '../../../common/I18n';\n\nconst LoginPageCaption = ({ version, caption }) => (\n \n {__('Welcome')}
\n {version && {`${__('Version')} ${version}`}
}\n {caption && {caption}
}\n \n);\n\nLoginPageCaption.propTypes = {\n caption: PropTypes.string,\n version: PropTypes.string,\n};\n\nLoginPageCaption.defaultProps = {\n caption: null,\n version: null,\n};\n\nexport default LoginPageCaption;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/LoginPage/components/LoginPageCaption.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 React, { useEffect } from 'react';\nimport { Spinner } from 'patternfly-react';\nimport PropTypes from 'prop-types';\nimport { Table } from '../common/table';\nimport { STATUS } from '../../constants';\nimport MessageBox from '../common/MessageBox';\nimport { translate as __ } from '../../common/I18n';\nimport createModelsTableSchema from './ModelsTableSchema';\nimport { getURIQuery } from '../../common/helpers';\n\nconst ModelsTable = ({\n getTableItems,\n sortBy,\n sortOrder,\n error,\n status,\n results,\n}) => {\n useEffect(() => {\n getTableItems(getURIQuery(window.location.href));\n }, [getTableItems]);\n\n if (results.length === 0) {\n return ;\n }\n\n if (status === STATUS.ERROR) {\n return (\n \n );\n }\n\n return (\n \n );\n};\n\nModelsTable.propTypes = {\n results: PropTypes.array.isRequired,\n getTableItems: PropTypes.func.isRequired,\n status: PropTypes.oneOf(Object.keys(STATUS)),\n sortBy: PropTypes.string,\n sortOrder: PropTypes.string,\n error: PropTypes.object,\n};\n\nModelsTable.defaultProps = {\n status: STATUS.PENDING,\n sortBy: '',\n sortOrder: '',\n error: null,\n};\n\nexport default ModelsTable;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/ModelsTable/ModelsTable.js","import { getTableItemsAction } from '../common/table';\nimport {\n MODELS_TABLE_CONTROLLER,\n MODELS_TABLE_ID,\n} from './ModelsTableConstants';\n\nexport const getTableItems = query =>\n getTableItemsAction(MODELS_TABLE_ID, query, `api/${MODELS_TABLE_CONTROLLER}`);\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/ModelsTable/ModelsTableActions.js","export const MODELS_TABLE_CONTROLLER = 'models';\nexport const MODELS_TABLE_ID = 'models_table';\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/ModelsTable/ModelsTableConstants.js","import { createTableReducer } from '../common/table';\nimport { MODELS_TABLE_ID } from './ModelsTableConstants';\n\nexport default createTableReducer(MODELS_TABLE_ID);\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/ModelsTable/ModelsTableReducer.js","import { translate as __ } from '../../common/I18n';\nimport {\n sortControllerFactory,\n column,\n sortableColumn,\n headerFormatterWithProps,\n cellFormatterWithProps,\n nameCellFormatter,\n hostsCountCellFormatter,\n deleteActionCellFormatter,\n cellFormatter,\n} from '../common/table';\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) => {\n const sortController = sortControllerFactory(apiCall, by, order);\n return [\n sortableColumn('name', __('Name'), 4, sortController, [\n nameCellFormatter('models'),\n ]),\n sortableColumn('vendor_class', __('Vendor Class'), 3, sortController),\n sortableColumn('hardware_model', __('Hardware Model'), 3, sortController),\n column(\n 'hosts_count',\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('models'), 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 { connect } from 'react-redux';\nimport { bindActionCreators } from 'redux';\nimport ModelsTable from './ModelsTable';\nimport reducer from './ModelsTableReducer';\nimport * as actions from './ModelsTableActions';\n\nconst mapStateToProps = state => state.models_table;\nconst mapDispatchToProps = dispatch => bindActionCreators(actions, dispatch);\n\nexport const reducers = { models_table: reducer };\n\nexport default connect(mapStateToProps, mapDispatchToProps)(ModelsTable);\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 { translateObject } from '../../common/helpers';\nimport {\n getURIpage,\n getURIperPage,\n changeQuery,\n} from '../../common/urlHelpers';\nimport {\n useForemanSettings,\n usePaginationOptions,\n} 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 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 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 React from 'react';\nimport PropTypes from 'prop-types';\n\nimport ConnectedChartBox from '../ChartBox';\nimport './StatisticsChartsListStyles.scss';\nimport { translate as __ } from '../../common/I18n';\n\nconst StatisticsChartsList = ({ data }) => {\n const chartBoxes = Object.values(data).map(chart => (\n \n ));\n\n return (\n {chartBoxes}
\n );\n};\n\nStatisticsChartsList.propTypes = {\n data: PropTypes.oneOfType([PropTypes.array, PropTypes.object]),\n};\n\nStatisticsChartsList.defaultProps = {\n data: [],\n};\n\nexport default StatisticsChartsList;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/StatisticsChartsList/index.js","import React, { Fragment } from 'react';\nimport PropTypes from 'prop-types';\nimport { FieldLevelHelp } from 'patternfly-react';\n\nimport Form from '../../common/forms/CommonForm';\nimport AutoComplete from '../../AutoComplete';\n\nconst TemplateAutoComplete = ({\n label,\n resourceType,\n id,\n searchQuery,\n initialError,\n info,\n isRequired,\n url,\n template,\n}) => (\n \n);\nTemplateAutoComplete.propTypes = {\n resourceType: PropTypes.string,\n searchQuery: PropTypes.string,\n initialError: PropTypes.string,\n label: PropTypes.string.isRequired,\n info: PropTypes.string,\n isRequired: PropTypes.bool,\n id: PropTypes.number.isRequired,\n url: PropTypes.string.isRequired,\n template: PropTypes.string.isRequired,\n};\n\nTemplateAutoComplete.defaultProps = {\n resourceType: null,\n searchQuery: '',\n initialError: null,\n info: null,\n isRequired: false,\n};\n\nexport default TemplateAutoComplete;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Template/Inputs/AutoComplete.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport DateTime from '../common/forms/DateTime/DateTime';\nimport Autocomplete from './Inputs/AutoComplete';\n\nconst TemplateInput = ({\n data: {\n label,\n resourceType,\n id,\n description,\n required,\n initialError,\n type,\n url,\n supportedTypes,\n template,\n value,\n },\n}) => {\n const [plain, search, date] = supportedTypes;\n\n switch (type) {\n case plain:\n return null;\n case search:\n return (\n \n );\n case date:\n return (\n \n );\n default:\n return null;\n }\n};\n\nTemplateInput.propTypes = {\n data: PropTypes.shape({\n id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),\n type: PropTypes.string,\n url: PropTypes.string,\n resourceType: PropTypes.string,\n initialError: PropTypes.string,\n label: PropTypes.string.isRequired,\n description: PropTypes.string,\n required: PropTypes.bool,\n supportedTypes: PropTypes.arrayOf(PropTypes.string).isRequired,\n template: PropTypes.string.isRequired,\n value: PropTypes.string,\n }),\n};\n\nTemplateInput.defaultProps = {\n data: PropTypes.shape({\n url: null,\n useKeyShortcuts: false,\n resourceType: null,\n initialError: null,\n description: null,\n required: false,\n value: undefined,\n }),\n};\n\nexport default TemplateInput;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/Template/TemplateInput.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 from 'react';\nimport {\n ToastNotificationList,\n ToastNotification,\n TimedToastNotification,\n} from 'patternfly-react';\nimport PropTypes from 'prop-types';\nimport { noop } from '../../common/helpers';\nimport AlertBody from '../common/Alert/AlertBody';\n\nconst ToastsList = ({ messages, deleteToast }) => {\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\n return (\n deleteToast(key)}\n {...toastProps}\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};\n\nToastsList.defaultProps = {\n deleteToast: noop,\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 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 componenet 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 initialDate() {\n const { value } = this.props;\n return Date.parse(value) ? new Date(value) : new Date();\n }\n\n state = {\n value: this.initialDate,\n hiddenValue: this.props.hiddenValue,\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 hiddenValue: PropTypes.bool,\n required: PropTypes.bool,\n};\nDatePicker.defaultProps = {\n value: new Date(),\n name: null,\n locale: 'en-US',\n weekStartsOn: 1,\n id: 'date-picker-popover',\n placement: 'top',\n hiddenValue: true,\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 { formatDateTime } from '../../../common/helpers';\nimport './date-time-picker.scss';\n\nclass DateTimePicker extends React.Component {\n get initialDate() {\n const { value } = this.props;\n return Date.parse(value) ? new Date(value) : new Date();\n }\n\n state = {\n value: this.initialDate,\n typeOfDateInput: MONTH,\n isTimeTableOpen: false,\n hiddenValue: this.props.hiddenValue,\n };\n\n setSelected = date => {\n if (Date.parse(date)) {\n const newDate = new Date(date);\n this.setState({ value: newDate });\n }\n this.setState({\n typeOfDateInput: MONTH,\n isTimeTableOpen: false,\n });\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 this.setState({ hiddenValue: true, value: new Date() })\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 hiddenValue: PropTypes.bool,\n placement: OverlayTrigger.propTypes.placement,\n name: PropTypes.string,\n required: PropTypes.bool,\n};\nDateTimePicker.defaultProps = {\n value: new Date(),\n locale: 'en-US',\n weekStartsOn: 1,\n inputProps: {},\n id: 'datetime-picker-popover',\n hiddenValue: true,\n placement: 'top',\n name: undefined,\n required: false,\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 EmptyStatePattern from './EmptyStatePattern';\nimport PrimaryActionButton from './EmptyStatePrimaryActionButton';\nimport SecondaryActionButtons from './EmptyStateSecondaryActionButtons';\nimport { defaultEmptyStatePropTypes } from './EmptyStatePropTypes';\nimport { translate as __ } from '../../../common/I18n';\n\nconst DefaultEmptyState = props => {\n const {\n icon,\n iconType,\n header,\n description,\n documentation: {\n url,\n label = __('For more information please see'),\n buttonLabel = __('Documentation'),\n } = {},\n action,\n secondaryActions,\n } = props;\n\n const documentationBlock = url ? (\n \n {label}{' '}\n \n {buttonLabel}\n \n \n ) : null;\n\n return (\n : null}\n secondaryActions={}\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 { EmptyState as PfEmptyState } from 'patternfly-react';\nimport { emptyStatePatternPropTypes } from './EmptyStatePropTypes';\n\nconst EmptyStatePattern = props => {\n const {\n documentation,\n action,\n secondaryActions,\n icon,\n iconType,\n header,\n description,\n } = props;\n\n return (\n \n \n {header}\n {description}\n {documentation && {documentation}}\n {action && {action}}\n {secondaryActions && (\n {secondaryActions}\n )}\n \n );\n};\n\nEmptyStatePattern.propTypes = emptyStatePatternPropTypes;\n\nexport default EmptyStatePattern;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/EmptyState/EmptyStatePattern.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { Button } from 'patternfly-react';\nimport { actionButtonPropTypes } from './EmptyStatePropTypes';\n\nconst PrimaryActionButton = ({ action }) => {\n if (!action) {\n return null;\n }\n\n if (action.url) {\n return urlButton(action);\n }\n\n if (action.onClick) {\n return onClickButton(action);\n }\n\n throw new Error(\n 'Primary action button expects action with either url or onClick'\n );\n};\n\n// eslint-disable-next-line react/prop-types\nconst urlButton = ({ url, title }) => (\n \n);\n\n// eslint-disable-next-line react/prop-types\nconst onClickButton = ({ onClick, title }) => (\n \n);\n\nPrimaryActionButton.propTypes = {\n action: PropTypes.shape(actionButtonPropTypes).isRequired,\n};\n\nexport default PrimaryActionButton;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/EmptyState/EmptyStatePrimaryActionButton.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.isRequired,\n header: PropTypes.string.isRequired,\n description: PropTypes.string.isRequired,\n documentation: PropTypes.node,\n action: PropTypes.node,\n secondaryActions: PropTypes.node,\n};\n\nexport const defaultEmptyStatePropTypes = {\n ...emptyStatePatternPropTypes,\n icon: PropTypes.string,\n documentation: PropTypes.shape({\n label: PropTypes.string,\n buttonLabel: PropTypes.string,\n url: PropTypes.string.isRequired,\n }),\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 React from 'react';\nimport PropTypes from 'prop-types';\nimport { Button } from 'patternfly-react';\nimport { actionButtonPropTypes } from './EmptyStatePropTypes';\n\nconst SecondaryActionButtons = ({ actions }) =>\n actions.map(({ title, url }) => (\n \n ));\n\nSecondaryActionButtons.propTypes = {\n actions: PropTypes.arrayOf(PropTypes.shape(actionButtonPropTypes)),\n};\n\nSecondaryActionButtons.defaultProps = {\n actions: [],\n};\n\nexport default SecondaryActionButtons;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/EmptyState/EmptyStateSecondaryActionButtons.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 },\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], true);\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 { 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';\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 { 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 selectFillsComponents = (state, props) => {\n const { id, multiple } = props;\n\n if (selectFillsAmount(state, id)) {\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 }),\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}) => {\n const chartConfig = getDonutChartConfig({ data, config, onclick });\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};\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};\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, { Fragment } from 'react';\nimport PropTypes from 'prop-types';\nimport { FieldLevelHelp } from 'patternfly-react';\nimport DateTimePicker from '../../DateTimePicker/DateTimePicker';\n\nimport Form from '../CommonForm';\nimport { documentLocale } from '../../../../common/I18n';\nimport './DateTimeOverrides.scss';\n\nconst DateTime = ({\n label,\n id,\n info,\n isRequired,\n hideValue,\n locale,\n inputProps,\n value,\n initialError,\n}) => {\n const currentLocale = locale || documentLocale();\n\n return (\n \n );\n};\n\nDateTime.propTypes = {\n label: PropTypes.string.isRequired,\n info: PropTypes.string,\n isRequired: PropTypes.bool,\n id: PropTypes.number.isRequired,\n locale: PropTypes.string,\n inputProps: PropTypes.object,\n value: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.string]),\n initialError: PropTypes.string,\n hideValue: PropTypes.bool,\n};\n\nDateTime.defaultProps = {\n info: undefined,\n isRequired: false,\n locale: null,\n value: new Date(),\n initialError: undefined,\n hideValue: false,\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 prepareErrors = errors =>\n Object.keys(errors).reduce((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\nexport const isInitialValid = ({ validationSchema, initialValues }) =>\n !validationSchema ? true : validationSchema.isValidSync(initialValues);\n\nconst ForemanForm = props => (\n \n props.onSubmit(values, actions).catch(exception => {\n actions.setSubmitting(false);\n actions.setErrors(prepareErrors(exception.errors));\n })\n }\n initialValues={props.initialValues}\n validationSchema={props.validationSchema}\n isInitialValid={isInitialValid}\n >\n {formProps => {\n const disabled = formProps.isSubmitting || !formProps.isValid;\n\n const submissionError = formProps.errors._error;\n return (\n \n );\n }}\n \n);\n\nconst cloneChildren = (children, childProps) => (\n \n {children.map((child, idx) =>\n React.cloneElement(child, { ...childProps, key: idx })\n )}\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.array,\n};\n\nForemanForm.defaultProps = {\n validationSchema: undefined,\n children: [],\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 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 InputFactory from './InputFactory';\nimport { noop } from '../../../common/helpers';\n\nconst InlineMessage = ({ error, helpInline }) => {\n if (!error && !helpInline) {\n return null;\n }\n return (\n \n {error || helpInline}\n \n );\n};\nInlineMessage.propTypes = {\n error: PropTypes.string,\n helpInline: PropTypes.string,\n};\nInlineMessage.defaultProps = {\n error: 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 controlProps = {\n value,\n name,\n disabled,\n required,\n className,\n onChange,\n ...otherProps,\n ...inputProps,\n };\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 ]),\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 TimePicker from '../DateTimePicker/TimePicker';\n\nconst inputComponents = {\n autocomplete: AutoComplete,\n date: DatePicker,\n dateTime: DateTimePicker,\n orderableSelect: OrderableSelect,\n time: TimePicker,\n};\n\nexport const registerInputComponent = (name, Component) => {\n inputComponents[name] = Component;\n};\n\nconst InputFactory = ({ type, ...controlProps }) => {\n if (inputComponents[type]) {\n return (\n \n );\n }\n return ;\n};\n\nInputFactory.propTypes = {\n type: PropTypes.string.isRequired,\n value: PropTypes.oneOfType([\n PropTypes.string,\n PropTypes.number,\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};\n\nInputFactory.defaultProps = {\n name: undefined,\n value: undefined,\n className: '',\n required: false,\n disabled: false,\n onChange: noop,\n};\n\nexport default InputFactory;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/forms/InputFactory.js","import NumericInput from 'react-numeric-input';\nimport React from 'react';\nimport PropTypes from 'prop-types';\n\nimport { noop } from '../../../common/helpers';\nimport CommonForm from './CommonForm';\n\nconst TextInput = ({\n label,\n className,\n value,\n onChange,\n format,\n precision,\n minValue,\n}) => (\n \n \n \n);\n\nTextInput.propTypes = {\n label: PropTypes.string,\n className: PropTypes.string,\n value: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),\n format: PropTypes.func,\n precision: PropTypes.number,\n minValue: PropTypes.number,\n onChange: PropTypes.func,\n};\n\nTextInput.defaultProps = {\n label: '',\n className: '',\n value: 0,\n format: null,\n precision: 0,\n minValue: 0,\n onChange: noop,\n};\n\nexport default TextInput;\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) => (\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 // Get vertical middle\n const hoverMiddleX = (hoverBoundingRect.right - hoverBoundingRect.left) / 2;\n // Determine mouse position\n const clientOffset = monitor.getClientOffset();\n // Get pixels to the top\n const hoverClientX = clientOffset.x - hoverBoundingRect.left;\n // Only perform the move when the mouse has crossed half of the items width\n // When dragging right, only move when the cursor is over 50%\n // When dragging left, only move when the cursor is under 50%\n // Dragging right\n if (dragIndex < hoverIndex && hoverClientX < hoverMiddleX) {\n return null;\n }\n // Dragging left\n if (dragIndex > hoverIndex && hoverClientX > hoverMiddleX) {\n return null;\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 getDropTarget = (dropTypes, getIndex, getMoveFnc) =>\n DropTarget(\n dropTypes,\n { hover: makeOnHover(getIndex, getMoveFnc) },\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 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 )(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 { map } from 'lodash';\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';\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 this.initializeSelect2();\n this.attachEvent();\n }\n\n componentDidUpdate(prevProps) {\n this.initializeSelect2();\n\n if (this.props.status !== prevProps.status) {\n this.attachEvent();\n }\n }\n\n render() {\n const renderOptions = arr =>\n map(arr, (attribute, value) => (\n \n ));\n\n const {\n label,\n className,\n value,\n onChange,\n options,\n disabled,\n status = STATUS.RESOLVED,\n errorMessage = __('An error occured.'),\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 value: PropTypes.string,\n label: PropTypes.string,\n className: PropTypes.string,\n allowClear: PropTypes.bool,\n disabled: PropTypes.bool,\n options: PropTypes.object,\n status: PropTypes.string,\n errorMessage: PropTypes.string,\n onChange: PropTypes.func,\n};\n\nSelect.defaultProps = {\n value: '',\n label: '',\n className: '',\n allowClear: false,\n disabled: false,\n options: {},\n status: STATUS.RESOLVED,\n errorMessage: __('An error occured.'),\n onChange: noop,\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';\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';\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/table/actions/index.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\n// TODO(bshuster): Move the confirmation to DialogModal that uses API to\n// delete the item.\nconst DeleteButton = ({ active, id, name, controller }) =>\n active ? (\n \n ) : null;\n\nDeleteButton.propTypes = {\n active: PropTypes.bool,\n id: PropTypes.number.isRequired,\n name: PropTypes.string.isRequired,\n controller: PropTypes.string.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';\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.isRequired,\n};\n\nNameCell.defaultProps = {\n active: false,\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.string,\n};\n\nTableBody.defaultProps = {\n message: '',\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","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","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 = controllerPluralize => (\n _,\n { rowData: { can_delete: canDelete, name, id } }\n) => (\n \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 = Component => (\n value,\n {\n column: {\n header: { props },\n },\n }\n) => {value};\n\nexport const headerFormatterWithProps = withProps(PfTable.Heading);\nexport const cellFormatterWithProps = withProps(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';\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: { can_edit: 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 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';\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});\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 });\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';\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/table/reducers/index.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';\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/common/table/schemaHelpers/index.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","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 StatisticsChartsList from './StatisticsChartsList';\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 TemplateInput from './Template/TemplateInput';\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';\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: 'StatisticsChartsList', type: StatisticsChartsList },\n { name: 'PowerStatus', type: PowerStatus },\n { name: 'NotificationContainer', type: NotificationContainer },\n { name: 'ToastNotifications', type: ToastsList, data: false },\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: 'TemplateInput', type: TemplateInput },\n { name: 'ExternalLogout', type: ExternalLogout },\n { name: 'Slot', type: Slot },\n { name: 'TypeAheadSelect', type: TypeAheadSelect },\n { name: 'DatePicker', type: DatePicker },\n\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];\n\ncomponentRegistry.registerMultiple(coreComponets);\n\nexport default componentRegistry;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/componentRegistry.js","import { connect } from 'react-redux';\nimport React from 'react';\nimport PropTypes from 'prop-types';\n\nimport { noop } from '../../../common/helpers';\nimport * as HostsActions from '../../../redux/actions/hosts/powerStatus/';\n\nimport PowerStatusInner from './powerStatusInner';\n\nclass PowerStatus extends React.Component {\n componentDidMount() {\n const {\n data: { id, url },\n getHostPowerState,\n } = this.props;\n\n getHostPowerState({ id, url });\n }\n\n render() {\n return ;\n }\n}\n\nPowerStatus.propTypes = {\n data: PropTypes.shape({\n id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),\n url: PropTypes.string,\n }).isRequired,\n power: PropTypes.object,\n getHostPowerState: PropTypes.func,\n};\n\nPowerStatus.defaultProps = {\n power: {},\n getHostPowerState: noop,\n};\n\nconst mapStateToProps = (state, ownProps) => ({\n power: state.hosts.powerStatus[ownProps.data.id] || {},\n});\n\nexport default connect(mapStateToProps, HostsActions)(PowerStatus);\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/hosts/powerStatus/index.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { simpleLoader } from '../../../common/Loader';\nimport './PowerStatusInner.scss';\n\nconst PowerStatusInner = ({ state, title, statusText, error }) => {\n if (error) {\n const errorTitle = [title, statusText].join(' ').trim();\n\n return (\n \n );\n }\n if (!state) {\n return simpleLoader('xs');\n }\n return (\n \n );\n};\n\nPowerStatusInner.propTypes = {\n title: PropTypes.string,\n statusText: PropTypes.string,\n state: PropTypes.string,\n error: PropTypes.string,\n};\n\nPowerStatusInner.defaultProps = {\n title: '',\n statusText: '',\n state: null,\n error: null,\n};\n\nexport default PowerStatusInner;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/components/hosts/powerStatus/powerStatusInner/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 React from 'react';\nimport { OverlayTrigger, Tooltip } from 'patternfly-react';\nimport PropTypes from 'prop-types';\nimport { noop } from '../../../common/helpers';\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';\nimport { reloadPage } from '../../../foreman_navigation';\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 componentDidUpdate() {\n const { error, stopNotificationsPolling } = this.props;\n if (error) {\n const { response: { status } = {} } = error;\n stopNotificationsPolling();\n if (status === 401) {\n reloadPage();\n }\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 error: PropTypes.oneOfType([\n PropTypes.string,\n PropTypes.shape({\n message: PropTypes.string,\n response: PropTypes.object,\n }),\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 error: null,\n translations: NotificationDrawerPanelWrapper.defaultProps.translations,\n};\n\nconst mapStateToProps = state => {\n const {\n notifications,\n isDrawerOpen,\n expandedGroup,\n hasUnreadMessages,\n error,\n } = state.notifications;\n\n return {\n isDrawerOpen,\n notifications: groupBy(notifications, n => n.group),\n expandedGroup,\n isReady: !!notifications,\n hasUnreadMessages,\n error,\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 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';\n\nexport default createBrowserHistory();\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 } = API_OPERATIONS;\n\n/**\n * an API action creator for API get.\n * @param { Object } payload payload for the API get acion.\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 { 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 get = payload => ({ type: GET, payload });\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/redux/API/APIActions.js","export const API_OPERATIONS = { GET: 'API_GET' };\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/redux/API/APIConstants.js","import { API_OPERATIONS } from './';\nimport { get } from './APIRequest';\n\nexport const APIMiddleware = store => next => action => {\n const { type, payload } = action;\n if (type === API_OPERATIONS.GET) {\n get(payload, store);\n }\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","import { API } from './';\nimport { actionTypeGenerator } from './APIActionTypeGenerator';\n\nexport const get = async (\n { key, url, headers = {}, params = {}, actionTypes = {}, payload = {} },\n { dispatch }\n) => {\n const { REQUEST, SUCCESS, FAILURE } = actionTypeGenerator(key, actionTypes);\n const modifiedPayload = { ...payload, url };\n dispatch({\n type: REQUEST,\n key,\n payload: modifiedPayload,\n });\n try {\n const { data } = await API.get(url, headers, params);\n dispatch({\n type: SUCCESS,\n key,\n payload: modifiedPayload,\n response: data,\n });\n } catch (error) {\n dispatch({\n type: FAILURE,\n key,\n payload: modifiedPayload,\n response: error,\n });\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 || STATUS.PENDING;\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 { API } from '../../API';\n\nimport { addToast } from '../toasts';\nimport { sprintf, translate as __ } from '../../../../react_app/common/I18n';\n\nexport class SubmissionError {\n constructor(errors) {\n this.errors = errors;\n }\n}\n\nconst fieldErrors = ({ error }) => {\n const { errors, severity } = error;\n\n if (errors.base) {\n errors._error = {};\n errors._error.errorMsgs = errors.base;\n errors._error.severity = severity;\n delete errors.base;\n }\n\n return new SubmissionError(errors);\n};\n\nexport const onError = error => {\n if (error.response.status === 422) {\n // Handle invalid form data\n throw fieldErrors(error.response.data);\n }\n throw new SubmissionError({\n _error: {\n errorMsgs: [\n `${__('Error submitting data:')} ${error.response.status} ${__(\n error.response.statusText\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 = ({ item, url, values, message, method = 'post' }) => {\n verifyProps(item, values);\n return async dispatch => {\n try {\n const { data } = await API[method](url, values);\n dispatch({\n type: `${item.toUpperCase()}_FORM_SUBMITTED`,\n payload: { item, data },\n });\n dispatch(\n addToast({\n type: 'success',\n // eslint-disable-next-line no-undef\n message: message || sprintf('%s was successfully created.', __(item)),\n })\n );\n } catch (error) {\n onError(error);\n }\n };\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/redux/actions/common/forms.js","import { HOST_POWER_STATUS } from '../../../consts';\nimport { get } from '../../../API';\n\nexport const getHostPowerState = ({ id, url }) =>\n get({\n key: HOST_POWER_STATUS,\n url,\n payload: { id },\n });\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/redux/actions/hosts/powerStatus/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 { notificationsDrawer as sessionStorage } from '../../../common/sessionStorage';\nimport { API, get } from '../../API';\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 getNotifications = url => get({ key: NOTIFICATIONS, url });\n\nexport const startNotificationsPolling = url =>\n withInterval(getNotifications(url), interval);\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 = 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 HOST_POWER_STATUS = 'HOST_POWER_STATUS';\nexport const HOST_POWER_STATUS_REQUEST = 'HOST_POWER_STATUS_REQUEST';\nexport const HOST_POWER_STATUS_SUCCESS = 'HOST_POWER_STATUS_SUCCESS';\nexport const HOST_POWER_STATUS_FAILURE = 'HOST_POWER_STATUS_FAILURE';\nexport 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 createLogger from 'redux-logger';\nimport thunk from 'redux-thunk';\nimport { applyMiddleware, createStore, compose } from 'redux';\nimport forceSingleton from '../common/forceSingleton';\n\nimport reducers from './reducers';\n\nimport { IntervalMiddleware, APIMiddleware } from './middlewares';\n\nlet middleware = [thunk, IntervalMiddleware, APIMiddleware];\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\nif (logReduxToConsole()) middleware = [...middleware, createLogger()];\n\nconst composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;\n\nexport const generateStore = () =>\n createStore(reducers, composeEnhancers(applyMiddleware(...middleware)));\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 unregisteredIntervalException = key =>\n new Error(`Can't find a registered interval process 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 unregisteredIntervalException,\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\n if (!selectDoesIntervalExist(state, intervalKey)) {\n throw unregisteredIntervalException(intervalKey);\n }\n\n const intervalID = selectIntervalID(state, intervalKey);\n 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","export { APIMiddleware } from '../API';\nexport { IntervalMiddleware } from './IntervalMiddleware';\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/redux/middlewares/index.js","import { combineReducers } from 'redux';\nimport storage from './storage';\nimport powerStatus from './powerStatus';\n\nexport default combineReducers({\n storage,\n powerStatus,\n});\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/redux/reducers/hosts/index.js","import Immutable from 'seamless-immutable';\nimport {\n HOST_POWER_STATUS_REQUEST,\n HOST_POWER_STATUS_SUCCESS,\n HOST_POWER_STATUS_FAILURE,\n} from '../../../consts';\n\nconst initialState = Immutable({});\n\nexport default (state = initialState, { type, payload, response }) => {\n switch (type) {\n case HOST_POWER_STATUS_REQUEST:\n return state.set(payload.id, payload);\n case HOST_POWER_STATUS_SUCCESS:\n return state.set(payload.id, response);\n case HOST_POWER_STATUS_FAILURE: {\n const {\n message: errorMessage,\n response: { data },\n } = response;\n\n return state.set(data.id, { error: errorMessage, ...data });\n }\n default:\n return state;\n }\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/redux/reducers/hosts/powerStatus/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 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 modelsReducers } from '../../components/ModelsTable';\nimport { reducers as templateGenerationReducers } from '../../components/TemplateGenerator';\nimport { reducers as factChartReducers } from '../../components/FactCharts';\nimport { reducers as statisticsPageReducers } from '../../routes/Statistics/StatisticsPage';\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';\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 ...modelsReducers,\n ...templateGenerationReducers,\n ...factChartReducers,\n ...typeAheadSelectReducers,\n\n // Pages\n ...statisticsPageReducers,\n ...fillReducers,\n ...auditsPageReducers,\n ...modalReducers,\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 { notificationsDrawer } from '../../../common/sessionStorage';\nimport { actionTypeGenerator } from '../../API';\n\nconst initialState = Immutable({\n isDrawerOpen: notificationsDrawer.getIsOpened(),\n expandedGroup: notificationsDrawer.getExpandedGroup(),\n hasUnreadMessages: notificationsDrawer.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 notificationsDrawer.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 PageLayout from '../../common/PageLayout/PageLayout';\nimport AuditsTable from './components/AuditsTable';\nimport { AUDITS_SEARCH_PROPS, AUDITS_MANUAL_URL } from '../constants';\nimport { useForemanVersion } from '../../../Root/Context/ForemanContext';\n\nconst AuditsPage = ({\n searchQuery,\n fetchAndPush,\n isLoading,\n hasData,\n ...props\n}) => {\n const foremanVersion = useForemanVersion();\n return (\n fetchAndPush({ searchQuery: search, page: 1 })}\n onBookmarkClick={search => fetchAndPush({ searchQuery: search, page: 1 })}\n toolbarButtons={\n \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';\nimport { usePaginationOptions } from '../../../../Root/Context/ForemanContext';\n\nconst AuditsTable = ({ audits, page, itemCount, fetchAndPush }) => {\n const perPageOptions = usePaginationOptions();\n return (\n \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 { getManualURL } from '../../common/helpers';\nimport { 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');\nexport const AUDITS_MANUAL_URL = () => getManualURL('4.1.4Auditing');\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 { 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 { withRenderHandler } from '../../../../common/HOC';\nimport StatisticsChartsList from '../../../../components/StatisticsChartsList';\nimport { translate as __ } from '../../../../common/I18n';\nimport { EmptyStatePattern } from '../../../../components/common/EmptyState';\n\nconst Statistics = ({ statisticsMeta }) => {\n if (!statisticsMeta) {\n return (\n \n );\n }\n return ;\n};\n\nStatistics.propTypes = {\n statisticsMeta: PropTypes.array.isRequired,\n};\n\nexport default withRenderHandler({\n Component: Statistics,\n});\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/Statistics/StatisticsPage/Statistics/Statistics.js","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { Alert } from 'patternfly-react';\nimport PageLayout from '../../common/PageLayout/PageLayout';\nimport Statistics from './Statistics/Statistics';\nimport { translate as __ } from '../../../common/I18n';\n\nconst StatisticsPage = ({ statisticsMeta, discussionUrl, ...props }) => (\n \n \n \n This functionality is deprecated \n \n and will be removed in version 2.2. If you wish continue using it, you\n will need to install the Foreman Statistics plugin when upgrading to\n 2.2.\n \n Join discussion\n \n \n \n \n \n);\n\nStatisticsPage.propTypes = {\n statisticsMeta: PropTypes.array,\n discussionUrl: PropTypes.string,\n};\n\nStatisticsPage.defaultProps = {\n statisticsMeta: [],\n discussionUrl: '',\n};\n\nexport default StatisticsPage;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/Statistics/StatisticsPage/StatisticsPage.js","import API from '../../../redux/API/API';\n\nimport {\n STATISTICS_PAGE_DATA_RESOLVED,\n STATISTICS_PAGE_DATA_FAILED,\n STATISTICS_PAGE_HIDE_LOADING,\n STATISTICS_PAGE_URL,\n} from '../constants';\n\nexport const getStatisticsMeta = (\n url = STATISTICS_PAGE_URL\n) => async dispatch => {\n const onFetchSuccess = ({ data }) => {\n dispatch(hideLoading());\n dispatch({\n type: STATISTICS_PAGE_DATA_RESOLVED,\n payload: {\n metadata: data.charts,\n hasData: data.charts.length > 0,\n discussionUrl: data.discussion_url,\n },\n });\n };\n\n const onFetchError = ({ message }) => {\n dispatch(hideLoading());\n dispatch({\n type: STATISTICS_PAGE_DATA_FAILED,\n payload: {\n message: {\n type: 'error',\n text: message,\n },\n },\n });\n };\n try {\n const response = await API.get(url);\n return onFetchSuccess(response);\n } catch (error) {\n return onFetchError(error);\n }\n};\n\nconst hideLoading = () => ({\n type: STATISTICS_PAGE_HIDE_LOADING,\n});\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/Statistics/StatisticsPage/StatisticsPageActions.js","export const selectStatisticsPage = state => state.statisticsPage;\n\nexport const selectStatisticsMetadata = state =>\n selectStatisticsPage(state).metadata;\nexport const selectStatisticsDiscussionUrl = state =>\n selectStatisticsPage(state).discussionUrl;\nexport const selectStatisticsIsLoading = state =>\n selectStatisticsPage(state).isLoading;\nexport const selectStatisticsMessage = state =>\n selectStatisticsPage(state).message;\nexport const selectStatisticsHasError = state =>\n selectStatisticsPage(state).hasError;\nexport const selectStatisticsHasMetadata = state =>\n selectStatisticsPage(state).hasData;\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/Statistics/StatisticsPage/StatisticsPageSelectors.js","import { compose, bindActionCreators } from 'redux';\nimport { connect } from 'react-redux';\nimport { callOnMount } from '../../../common/HOC';\n\nimport * as actions from './StatisticsPageActions';\nimport withDataReducer from '../../common/reducerHOC/withDataReducer';\nimport {\n selectStatisticsMetadata,\n selectStatisticsDiscussionUrl,\n selectStatisticsMessage,\n selectStatisticsIsLoading,\n selectStatisticsHasMetadata,\n selectStatisticsHasError,\n} from './StatisticsPageSelectors';\n\nimport StatisticsPage from './StatisticsPage';\n\n// map state to props\nconst mapStateToProps = state => ({\n statisticsMeta: selectStatisticsMetadata(state),\n discussionUrl: selectStatisticsDiscussionUrl(state),\n isLoading: selectStatisticsIsLoading(state),\n message: selectStatisticsMessage(state),\n hasData: selectStatisticsHasMetadata(state),\n hasError: selectStatisticsHasError(state),\n});\n\n// map action dispatchers to props\nconst mapDispatchToProps = dispatch => bindActionCreators(actions, dispatch);\n\n// export reducers\nexport const reducers = { statisticsPage: withDataReducer('STATISTICS_PAGE') };\n\n// export connected component\nexport default compose(\n connect(mapStateToProps, mapDispatchToProps),\n callOnMount(({ getStatisticsMeta }) => getStatisticsMeta())\n)(StatisticsPage);\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/Statistics/StatisticsPage/index.js","export const STATISTICS_PAGE_DATA_RESOLVED = 'STATISTICS_PAGE_DATA_RESOLVED';\nexport const STATISTICS_PAGE_DATA_FAILED = 'STATISTICS_PAGE_FETCH_FAILED';\nexport const STATISTICS_PAGE_HIDE_LOADING = 'STATISTICS_PAGE_HIDE_LOADING';\nexport const STATISTICS_PAGE_URL = '/statistics';\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/Statistics/constants.js","import React from 'react';\nimport StatisticsPage from './StatisticsPage';\nimport { STATISTICS_PAGE_URL } from './constants';\n\nexport default {\n path: STATISTICS_PAGE_URL,\n render: props => ,\n};\n\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/react_app/routes/Statistics/index.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 { updateDocumentTitle } from '../../../common/document';\nimport { changeQuery } from '../../../common/urlHelpers';\n\nimport ToastsList from '../../../components/ToastsList';\nimport BreadcrumbBar from '../../../components/BreadcrumbBar';\nimport SearchBar from '../../../components/SearchBar';\n\nconst PageLayout = ({\n header,\n searchable,\n searchProps,\n searchQuery,\n onSearch,\n onBookmarkClick,\n customBreadcrumbs,\n breadcrumbOptions,\n toolbarButtons,\n toastNotifications,\n beforeToolbarComponent,\n isLoading,\n children,\n}) => {\n updateDocumentTitle(header);\n return (\n \n
\n {toastNotifications && (\n
\n \n
\n )}\n
\n {!breadcrumbOptions && (\n
\n
{header}
\n \n )}\n {customBreadcrumbs\n ? { customBreadcrumbs }\n : breadcrumbOptions &&
}\n
\n {beforeToolbarComponent}\n
\n \n {searchable && (\n \n \n
\n )}\n \n \n \n {isLoading && (\n
\n \n
\n )}\n {toolbarButtons}\n
\n \n
\n {children}\n
\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.string,\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: null,\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\nconst initialState = Immutable({\n isLoading: true,\n hasError: false,\n hasData: false,\n message: { type: 'empty', text: '' },\n});\n\nconst withDataReducer = controller => (\n state = initialState,\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 { Switch, Route } from 'react-router-dom';\nimport { routes } from './routes';\nimport { visit } from '../../foreman_navigation';\n\nlet currentPath = window.location.pathname;\n\nconst AppSwitcher = () => {\n const updateCurrentPath = () => {\n currentPath = window.location.pathname;\n };\n\n const handleRailsContainer = () => {\n const railsContainer = document.getElementById('rails-app-content');\n if (railsContainer) railsContainer.remove();\n };\n\n const handleRoute = (Component, props) => {\n handleRailsContainer();\n updateCurrentPath();\n return ;\n };\n\n const handleFallbackRoute = () => {\n const nextPath = window.location.pathname;\n if (currentPath !== nextPath) {\n updateCurrentPath();\n visit(nextPath);\n }\n return null;\n };\n\n return (\n \n {routes.map(({ render: Component, path, ...routeProps }) => (\n handleRoute(Component, props)}\n />\n ))}\n \n \n );\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 Statistics from './Statistics';\nimport Audits from './Audits';\n\nexport const routes = [HostWizard, Statistics, Audits];\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 };\n};\n\nexport const remove = (SlotId, fillId) => {\n const slotItems = slotsRegistry[SlotId];\n\n delete slotItems[fillId];\n};\n\nexport const getSlotComponents = id => Object.values(slotsRegistry[id]);\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\n\n\n// WEBPACK FOOTER //\n// ./webpack/assets/javascripts/services/charts/ChartService.js","import uuidV1 from 'uuid/v1';\nimport { getChartConfig } from './ChartService';\n\nexport const getDonutChartConfig = ({ data, config, onclick, id = uuidV1() }) =>\n getChartConfig({\n type: 'donut',\n data,\n config,\n onclick,\n id,\n });\n\nexport const navigateToSearch = (url, data) => {\n let val = 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 = `\"${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/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 '