@ibm-adw/skill-toolkit
Version:
Developing your own skills with IBM Automation Digital Worker Skill Toolkit
332 lines (303 loc) • 15.6 kB
JavaScript
/*
Licensed Materials - Property of IBM
5737-I23
Copyright IBM Corp. 2019, 2020. All Rights Reserved.
U.S. Government Users Restricted Rights:
Use, duplication or disclosure restricted by GSA ADP Schedule
Contract with IBM Corp.
*/
import React, { useCallback, useContext, useEffect, useState } from 'react';
import { Link, Redirect, Route, Switch } from 'react-router-dom';
import intl from 'react-intl-universal';
import { LocaleContext, useLocale } from '../../common/locale';
import {
Header,
HeaderName,
HeaderPanel,
Switcher,
SwitcherItem,
SwitcherDivider,
Icon,
Button,
ToastNotification,
Loading,
InlineLoading,
TooltipDefinition
} from 'carbon-components-react';
import {
iconDocument,
iconList,
iconHelp,
iconChevronLeft,
iconChevronRight
} from 'carbon-icons';
import { Restart32, CheckmarkFilled32, ErrorFilled32 } from '@carbon/icons-react';
import axios from 'axios';
import { MainView } from '../main/MainView';
import './App.scss';
const SWITCHER_VALUES = {
INFO: 'info',
CATALOG: 'catalog',
README: 'readme'
};
const SERVER_PORT = (process.env.REACT_APP_SERVER_PORT ? process.env.REACT_APP_SERVER_PORT : '8888');
const SERVER_URL = 'http://localhost:' + SERVER_PORT;
const App = () => {
const localeContext = useContext(LocaleContext);
const nlsLoaded = useLocale(() => [
import(/* webpackChunkName: "nls" */ `./nls/${localeContext.currentLocale}.json`),
import(/* webpackChunkName: "nls" */ `./nls/${localeContext.fallbackLocale}.json`)
]);
const [ switcher, setSwitcher ] = useState(SWITCHER_VALUES.INFO);
const [ isSidePanelExpanded, setIsSidePanelExpanded ] = useState(false);
const [ lastUpdatedDate, setLastUpdatedDate ] = useState('');
const [ skillMetaData, setSkillMetaData ] = useState({});
const [ errorServer, setErrorServer ] = useState(false);
const [ subtitleToaster, setSubtitleToaster ] = useState('');
const [ titleToaster, setTitleToaster ] = useState('');
const [ displaySuccessErrorRefresh, setDisplaySuccessErrorRefresh ] = useState(false);
const [ displayToast, setDisplayToast ] = useState(true);
const [ shouldRefreshSkillData, setShouldRefreshSkillData ] = useState(true);
const setErrorToaster = useCallback((errorBoolean, title, subtitle) => {
setErrorServer(errorBoolean);
if (errorBoolean) {
setDisplayToast(true);
setSubtitleToaster(subtitle);
setTitleToaster(title);
} else {
setDisplayToast(false);
}
},[]);
const handleClick = useCallback((switchToView) => {
return () => {
setSwitcher(switchToView);
setIsSidePanelExpanded(true);
};
}, []);
const sidePanelCallback = useCallback((value) => {
setIsSidePanelExpanded(value);
}, []);
const refreshSkill = useCallback(() => {
setDisplayToast(true);
setShouldRefreshSkillData(true);
}, []);
useEffect(() => {
if (nlsLoaded && shouldRefreshSkillData) {
axios.get(`${SERVER_URL}/specs`, { params: { content: 'info' }})
.then(response => {
setSkillMetaData(response.data);
const today = new Date();
setLastUpdatedDate(today);
setErrorToaster(false);
setShouldRefreshSkillData(() => {
return false;
});
setDisplaySuccessErrorRefresh(true);
setTimeout(() => {
setDisplaySuccessErrorRefresh(false);
}, 1500);
})
.catch(error => {
const today = new Date();
setLastUpdatedDate(today);
setErrorToaster(true, intl.get('errors.LOADING_SKILL.TITLE'), intl.get('errors.LOADING_SKILL.CONTENT', { message : error.message }));
setShouldRefreshSkillData(() => {return false;});
setDisplaySuccessErrorRefresh(true);
setTimeout(() => {
setDisplaySuccessErrorRefresh(false);
}, 1500);
});
}
}, [ nlsLoaded, setErrorToaster, shouldRefreshSkillData ]);
const renderContent = useCallback(() => {
return (
<Switch>
<Route exact path="/" render={(props) => {
return <MainView
{...props}
switcher={switcher}
isSidePanelExpanded={isSidePanelExpanded}
setIsSidePanelExpanded={sidePanelCallback}
setErrorToaster={setErrorToaster}
lastUpdatedDate={lastUpdatedDate}
skillMetaData={skillMetaData}
serverUrl={SERVER_URL}
/>;
}} />
<Route render={() => (<Redirect to="/" />)} />
</Switch>
);
}, [ isSidePanelExpanded, lastUpdatedDate, setErrorToaster, sidePanelCallback, skillMetaData, switcher ]);
if (nlsLoaded) {
return (
<div className='adw--test'>
<div className='adw--test-header'>
<Header aria-label="IBM Platform Name">
<HeaderName
element={Link}
to="/"
prefix={intl.get('app.PRODUCT_NAME_PREFIX')}
className='adw--test-header-name adw--test-header-name-click'
>
{intl.get('app.PRODUCT_NAME')}
</HeaderName>
<HeaderName
prefix={`${skillMetaData.package_name}`}
className='adw--test-header-name'
children={skillMetaData.package_version}
>
{skillMetaData.package_version}
</HeaderName>
<HeaderName
prefix={intl.get('app.LAST_UPDATED_ON_DATE', { updateDate: lastUpdatedDate })}
className='adw--test-header-name adw--test-header-name-click'
>
<Button
className={`adw--test-button-notif ${errorServer ? 'adw--test-button-notif-red' : 'adw--test-button-notif-green'}`}
size="default"
renderIcon={errorServer ? ErrorFilled32 : CheckmarkFilled32}
iconDescription={errorServer ? (displayToast ? intl.get('app.ICON_DESCRIPTION_HIDE_ERRORS') : intl.get('app.ICON_DESCRIPTION_DISPLAY_ERRORS')) : intl.get('app.ICON_DESCRIPTION_LOADING_SUCCESS')}
tooltipPosition="bottom"
tooltipAlignment="center"
disabled={errorServer ? false : true}
onClick={() => setDisplayToast(!displayToast)}
kind='secondary'
hasIconOnly
/>
</HeaderName>
{ shouldRefreshSkillData || displaySuccessErrorRefresh ?
<InlineLoading
style={{ width: 'auto' }}
description={displaySuccessErrorRefresh ? `${errorServer ? intl.get('app.INLINE_LOADING_DESCRIPTION_ERROR') : intl.get('app.INLINE_LOADING_DESCRIPTION_SUCCESS')}` : intl.get('app.INLINE_LOADING_DESCRIPTION_LOADING')}
iconDescription={intl.get('app.ICON_DESCRIPTION_LOADING')}
onSuccess={function noRefCheck() {
}}
//success={shouldRefreshSkillData} // deprecated: changed to status
status={displaySuccessErrorRefresh ? `${errorServer ? 'error' : 'finished'}` : 'active'}
successDelay={1500}
/>
:
<TooltipDefinition
align="start"
direction="bottom"
tooltipText={intl.get('app.TOOLTIP_TEXT_REFRESH')}
triggerClassName=""
>
<Button
className='adw--test-refresh-button'
onClick={refreshSkill}
kind="secondary"
renderIcon={Restart32}
>
{intl.get('app.BUTTON_REFRESH')}
</Button>
</TooltipDefinition>
}
<HeaderPanel aria-label="Header Panel" expanded className={`adw--test-header-panel ${isSidePanelExpanded ? '' : 'adw--test-header-panel-small'}`}>
<Switcher role="menu" aria-label="Switcher Container">
<SwitcherItem
onClick={() => setIsSidePanelExpanded(!isSidePanelExpanded)}
isSelected={false}
aria-label="Chevron"
>
<div className='adw--test-header-panel-link'>
<Icon
icon={isSidePanelExpanded ? iconChevronRight : iconChevronLeft}
fill={switcher === SWITCHER_VALUES.INFO ? '#f3f3f3' : '#bebebe'}
className="adw--test-header-panel-link-icon"
description=""
height="16px"
width="16px"
/>
</div>
</SwitcherItem>
<SwitcherDivider />
<SwitcherItem
onClick={handleClick(SWITCHER_VALUES.INFO)}
isSelected={switcher === SWITCHER_VALUES.INFO}
aria-label="Metadata"
>
<div className='adw--test-header-panel-link'>
<Icon
icon={iconHelp}
fill={switcher === SWITCHER_VALUES.INFO ? '#f3f3f3' : '#bebebe'}
className="adw--test-header-panel-link-icon"
description=""
height="16px"
width="16px"
/>
{isSidePanelExpanded ? intl.get('app.PANEL_METADATA_HEADER') : ''}
</div>
</SwitcherItem>
<SwitcherItem
onClick={handleClick(SWITCHER_VALUES.README)}
isSelected={switcher === SWITCHER_VALUES.README}
aria-label="README"
>
<div className='adw--test-header-panel-link'>
<Icon
icon={iconDocument}
fill={switcher === SWITCHER_VALUES.README ? '#f3f3f3' : '#bebebe'}
className="adw--test-header-panel-link-icon"
description=""
height="16px"
width="16px"
/>
{isSidePanelExpanded ? intl.get('app.PANEL_DOCUMENTATION_HEADER') : ''}
</div>
</SwitcherItem>
<SwitcherDivider />
<SwitcherItem
onClick={handleClick(SWITCHER_VALUES.CATALOG)}
isSelected={switcher === SWITCHER_VALUES.CATALOG}
aria-label="Catalog"
>
<div className='adw--test-header-panel-link'>
<Icon
icon={iconList}
fill={switcher === SWITCHER_VALUES.CATALOG ? '#f3f3f3' : '#bebebe'}
className="adw--test-header-panel-link-icon"
description=""
height="16px"
width="16px"
/>
{isSidePanelExpanded ? intl.get('app.PANEL_WIDGETS_HEADER') : ''}
</div>
</SwitcherItem>
</Switcher>
</HeaderPanel>
</Header>
</div>
<div className={`adw--test-content adw--test-content-panel ${isSidePanelExpanded ? '' : 'adw--test-content-panel-small'}`}>
{ errorServer && displayToast ?
<ToastNotification
className='adw--test-toast-notif'
caption={intl.get('app.LAST_UPDATED_ON_DATE', { updateDate: lastUpdatedDate })}
hideCloseButton={false}
iconDescription={intl.get('app.ICON_DESCRIPTION_HIDE_NOTIFICATION')}
kind="error"
notificationType="toast"
onCloseButtonClick={() => setDisplayToast(false)}
role="alert"
style={{
marginBottom: '.5rem',
minWidth: '30rem'
}}
lowContrast={true}
subtitle={subtitleToaster}
title={titleToaster}
/>
: ''
}
{ shouldRefreshSkillData ?
<Loading withOverlay={false} className='adw--loading'/>
: renderContent()
}
</div>
</div>
);
} else {
return <div><Loading withOverlay={true} /></div>;
}
};
export { App };