// Licensed to Cloudera, Inc. under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. Cloudera, Inc. licenses this file // to you under the Apache License, Version 2.0 (the // 'License'); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an 'AS IS' BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. import React, { useState, useMemo } from 'react'; import { i18nReact } from '../../../utils/i18nReact'; import AdminHeader from '../AdminHeader'; import { ConfigurationValue } from './ConfigurationValue'; import { ConfigurationKey } from './ConfigurationKey'; import useLoadData from '../../../utils/hooks/useLoadData/useLoadData'; import LoadingErrorWrapper from '../../../reactComponents/LoadingErrorWrapper/LoadingErrorWrapper'; import { GET_HUE_CONFIG_API } from '../../../api/urls'; import './Configuration.scss'; interface App { name: string; has_ui: boolean; display_name: string; } export interface AdminConfigValue { help: string; key: string; is_anonymous: boolean; values?: AdminConfigValue[]; default?: string; value?: string; } interface Config { help: string; key: string; is_anonymous: boolean; values: AdminConfigValue[]; } interface HueConfig { apps: App[]; config: Config[]; conf_dir: string; } interface VisualSection { header: string; content: Array; } const Configuration: React.FC = (): JSX.Element => { const { t } = i18nReact.useTranslation(); const [selectedSection, setSelectedSection] = useState('desktop'); const [filter, setFilter] = useState(''); const ALL_SECTIONS_OPTION = t('ALL'); const { data: hueConfig, loading, error, reloadData } = useLoadData(GET_HUE_CONFIG_API, { transformKeys: 'none', onSuccess: data => { if (data.apps.find(app => app.name === 'desktop')) { setSelectedSection('desktop'); } } }); const filterConfig = ( config: AdminConfigValue, lowerCaseFilter: string ): AdminConfigValue | undefined => { //Filtering is done on Key and Help only const keyMatches = config.key?.toLowerCase().includes(lowerCaseFilter); const helpMatches = config.help?.toLowerCase().includes(lowerCaseFilter); if (keyMatches || helpMatches) { return config; } if (config.values) { const filteredValues = config.values .map(val => filterConfig(val, lowerCaseFilter)) .filter(Boolean) as AdminConfigValue[]; if (filteredValues.length) { return { ...config, values: filteredValues }; } } return undefined; }; const visualSections = useMemo(() => { const showAllSections = selectedSection === ALL_SECTIONS_OPTION; const selectedFullConfigs = !hueConfig?.config ? [] : showAllSections ? hueConfig.config : hueConfig.config.filter(config => config.key === selectedSection); return selectedFullConfigs .map(selectedSection => ({ header: selectedSection.key, content: selectedSection.values .map(config => filterConfig(config, filter.toLowerCase())) .filter(Boolean) as Config[] })) .filter(headerContentObj => !!headerContentObj.content) as Array; }, [hueConfig, filter, selectedSection]); const renderVisualSection = (visualSection: VisualSection) => { const showingMultipleSections = selectedSection === ALL_SECTIONS_OPTION; const content = visualSection.content; return content.length > 0 ? ( <> {showingMultipleSections && (

{visualSection.header}

)} {content.map((record, index) => (
))} ) : ( !showingMultipleSections && {t('Empty configuration section')} ); }; const optionsIncludingAll = [ ALL_SECTIONS_OPTION, ...(hueConfig?.apps.map(app => app.name) || []) ]; const errors = [ { enabled: !!error, message: t('Failed loading configuration'), description: error, actionText: t('Retry'), onClick: reloadData } ]; return (
{t('Sections')}
{selectedSection && visualSections?.length && visualSections.map(visualSection => (
{renderVisualSection(visualSection)}
))}
); }; export default Configuration;