forked from inspectIT/inspectit-ocelot
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Closes inspectIT#811 - Created UI for alert rule configuration
- Loading branch information
Alexander Wert
committed
Jul 7, 2020
1 parent
592354a
commit cb43da4
Showing
29 changed files
with
4,286 additions
and
3,061 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
111 changes: 111 additions & 0 deletions
111
...nts/inspectit-ocelot-configurationserver-ui/src/components/common/dialogs/CreateDialog.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
import React, { useState } from 'react'; | ||
import classNames from 'classnames'; | ||
import { Button } from 'primereact/button'; | ||
import { Dialog } from 'primereact/dialog'; | ||
import { Message } from 'primereact/message'; | ||
import { InputText } from 'primereact/inputtext'; | ||
import { Dropdown } from 'primereact/dropdown'; | ||
import { InputTextarea } from 'primereact/inputtextarea'; | ||
|
||
/** | ||
* A generic dialog for creating new items. | ||
* Optionally a category for the items can be used. The category options will be listed in a dropdown box. | ||
*/ | ||
const CreateDialog = ({ categories, initialCategory, useDescription, title, categoryTitle, elementTitle, text, | ||
visible, onHide, categoryIcon, targetElementIcon, reservedNames, onSuccess }) => { | ||
const [name, setName] = useState(''); | ||
const [category, setCategory] = useState(undefined); | ||
const [description, setDescription] = useState(''); | ||
const [isValid, setValidState] = useState(false); | ||
const [error, setError] = useState(undefined); | ||
|
||
if (!category && initialCategory) { setCategory(initialCategory); } | ||
|
||
const validate = () => { | ||
const reservedName = reservedNames.some(r => r.id === name); | ||
if (reservedName) { | ||
setError('An alerting rule with the given name already exists'); | ||
} else { | ||
setError(undefined); | ||
} | ||
setValidState(!reservedName && !!name && !!category); | ||
}; | ||
|
||
return ( | ||
<Dialog | ||
className="this" | ||
style={{ width: '400px' }} | ||
header={title} | ||
modal={true} | ||
visible={visible} | ||
onHide={onHide} | ||
onShow={() => { | ||
setName(''); | ||
setDescription(''); | ||
setCategory(undefined); | ||
}} | ||
footer={ | ||
<div> | ||
<Button label="Create" disabled={!isValid} onClick={() => onSuccess(name, category, description)} /> | ||
<Button label="Cancel" className="p-button-secondary" onClick={onHide} /> | ||
</div> | ||
} | ||
> | ||
<div style={{ width: '100%', paddingBottom: '0.5em' }}>{text}</div> | ||
<div className="p-grid"> | ||
{ | ||
categories && ( | ||
<div className="p-inputgroup p-col-12" style={{ width: '100%' }}> | ||
<span className="p-inputgroup-addon"> | ||
<i className={classNames('pi', { [categoryIcon]: categoryIcon !== undefined })}></i> | ||
</span> | ||
<Dropdown | ||
style={{ width: '100%' }} | ||
value={category} | ||
options={categories.map(c => ({ label: c, value: c }))} | ||
onChange={(e) => { setCategory(e.value); validate(); }} | ||
placeholder={categoryTitle} /> | ||
</div> | ||
) | ||
} | ||
<div className="p-inputgroup p-col-12" style={{ width: '100%' }}> | ||
<span className="p-inputgroup-addon"> | ||
<i className={classNames('pi', { [targetElementIcon]: targetElementIcon !== undefined })}></i> | ||
</span> | ||
<InputText | ||
style={{ width: '100%' }} | ||
onKeyPress={(e) => (e.key === 'Enter' && isValid && onSuccess(name, category, description))} | ||
value={name} | ||
placeholder={elementTitle} | ||
onChange={(e) => { setName(e.target.value); validate(); }} | ||
/> | ||
</div> | ||
{ | ||
useDescription && ( | ||
<div className="p-inputgroup p-col-12" style={{ width: '100%' }}> | ||
<span className="p-inputgroup-addon"> | ||
<i className="pi pi-align-left"></i> | ||
</span> | ||
<InputTextarea | ||
style={{ width: '100%', height: '8rem' }} | ||
value={description} | ||
onKeyPress={(e) => (e.key === 'Enter' && isValid && onSuccess(name, category, description))} | ||
autoResize={false} | ||
placeholder={'Description'} | ||
onChange={(e) => setDescription(e.target.value)} /> | ||
</div> | ||
) | ||
} | ||
</div> | ||
{ | ||
error && ( | ||
<div style={{ width: '100%', paddingTop: '0.5em' }}> | ||
<Message style={{ width: '100%' }} severity="error" text={error}></Message> | ||
</div> | ||
) | ||
} | ||
</Dialog > | ||
); | ||
}; | ||
|
||
export default CreateDialog; |
34 changes: 34 additions & 0 deletions
34
...nts/inspectit-ocelot-configurationserver-ui/src/components/common/dialogs/DeleteDialog.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import React, { useEffect } from 'react'; | ||
import { Button } from 'primereact/button'; | ||
import { Dialog } from 'primereact/dialog'; | ||
|
||
/** | ||
* A generic Dialog for deleting the given element. | ||
*/ | ||
const DeleteDialog = ({name, visible, onHide, text, onSuccess}) => { | ||
const deleteButton = React.createRef(); | ||
useEffect(() => { | ||
if(deleteButton && deleteButton.current){ | ||
deleteButton.current.element.focus(); | ||
} | ||
}); | ||
return ( | ||
<Dialog | ||
header={text} | ||
modal={true} | ||
visible={visible} | ||
onHide={onHide} | ||
footer={ | ||
<div> | ||
<Button label="Delete" ref={deleteButton} className="p-button-danger" onClick={() => {onSuccess(name); onHide();}} /> | ||
<Button label="Cancel" className="p-button-secondary" onClick={onHide} /> | ||
</div> | ||
} | ||
> | ||
Are you sure you want to delete <b>"{name}"</b> ? This cannot be undone! | ||
</Dialog> | ||
); | ||
}; | ||
|
||
|
||
export default DeleteDialog; |
20 changes: 20 additions & 0 deletions
20
...inspectit-ocelot-configurationserver-ui/src/components/common/value-editors/BoolEditor.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import React, { useState } from 'react'; | ||
import { InputSwitch } from 'primereact/inputswitch'; | ||
|
||
/** | ||
* Editor for Bool type values. | ||
*/ | ||
const BoolEditor = ({ value, disabled, updateValue }) => { | ||
const [val, setValue] = useState(value); | ||
|
||
return (<InputSwitch | ||
disabled={disabled} | ||
checked={val} | ||
onChange={(e) => { | ||
setValue(e.target.value); | ||
updateValue(e.target.value); | ||
}} | ||
/>); | ||
}; | ||
|
||
export default BoolEditor; |
34 changes: 34 additions & 0 deletions
34
...spectit-ocelot-configurationserver-ui/src/components/common/value-editors/NumberEditor.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import React, { useState, useEffect } from 'react'; | ||
import { InputNumber } from 'primereact/inputnumber'; | ||
|
||
/** | ||
* Editor for number type values. | ||
*/ | ||
const NumberEditor = ({ value, type, disabled, updateValue }) => { | ||
const [val, setValue] = useState(value); | ||
|
||
const ref = React.createRef(); | ||
useEffect(() => { | ||
ref.current.inputEl.focus(); | ||
}); | ||
|
||
const minFractionDigits = type === 'int' ? 0 : 1; | ||
const maxFractionDigits = type === 'int' ? 0 : 10; | ||
return (<InputNumber | ||
ref={ref} | ||
disabled={disabled} | ||
style={{ width: '100%' }} | ||
value={val} | ||
onChange={(e) => setValue(e.value)} | ||
mode="decimal" | ||
autoFocus | ||
minFractionDigits={minFractionDigits} | ||
maxFractionDigits={maxFractionDigits} | ||
useGrouping={false} | ||
onKeyPress={(e) => (e.key === 'Enter') && updateValue(val)} | ||
onBlur={() => updateValue(val)} | ||
|
||
/>); | ||
}; | ||
|
||
export default NumberEditor; |
51 changes: 51 additions & 0 deletions
51
...ctit-ocelot-configurationserver-ui/src/components/common/value-editors/SelectionEditor.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import React, { useState, useEffect } from 'react'; | ||
import { Dropdown } from 'primereact/dropdown'; | ||
|
||
/** | ||
* Editor for String type values with predefined selection list. | ||
*/ | ||
const SelectionEditor = ({ value, options, editable, disabled, updateValue, keyfilter }) => { | ||
const [val, setValue] = useState(value); | ||
const wrapperRef = React.createRef(); | ||
const selectItems = !options ? [] : options.map(item => ({ label: item, value: item })); | ||
|
||
// we need this, as onBlur is not working properly with the dropdown box | ||
// (onBlur is triggered when drop down list is opened). | ||
const handleClickOutside = (event) => { | ||
if (wrapperRef && !wrapperRef.current.contains(event.target)) { | ||
updateValue(val) | ||
} | ||
} | ||
|
||
useEffect(() => { | ||
document.addEventListener('mousedown', handleClickOutside); | ||
return () => { document.removeEventListener('mousedown', handleClickOutside); }; | ||
}); | ||
|
||
return ( | ||
<div className="this" ref={wrapperRef}> | ||
<style jsx>{` | ||
.this { | ||
flex-grow: 0; | ||
width: fit-content; | ||
} | ||
.this :global(.p-dropdown) { | ||
min-width: 250px; | ||
} | ||
`}</style> | ||
<Dropdown | ||
disabled={disabled} | ||
value={val} | ||
editable={editable} | ||
options={selectItems} | ||
autoFocus | ||
filter | ||
keyfilter={keyfilter} | ||
onChange={(e) => setValue(e.value)} | ||
onKeyPress={(e) => (e.key === 'Enter') && updateValue(val)} | ||
/> | ||
</div> | ||
); | ||
}; | ||
|
||
export default SelectionEditor; |
21 changes: 21 additions & 0 deletions
21
...ectit-ocelot-configurationserver-ui/src/components/common/value-editors/TextAreaEditor.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import React, { useState } from 'react'; | ||
import { InputTextarea } from 'primereact/inputtextarea'; | ||
|
||
/** | ||
* Editor for long texts. | ||
*/ | ||
const TextAreaEditor = ({ value, type, disabled, updateValue, height}) => { | ||
const [val, setValue] = useState(value); | ||
|
||
const heightObj = height ? {height: height + 'px'} : {}; | ||
return (<InputTextarea | ||
style={{...{width: '100%'},...heightObj}} | ||
disabled={disabled} | ||
value={val} | ||
onChange={(e) => setValue(e.target.value)} | ||
autoFocus | ||
onBlur={() => updateValue(val ? val : null)} | ||
/>); | ||
}; | ||
|
||
export default TextAreaEditor; |
23 changes: 23 additions & 0 deletions
23
...inspectit-ocelot-configurationserver-ui/src/components/common/value-editors/TextEditor.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import React, { useState } from 'react'; | ||
import { InputText } from 'primereact/inputtext'; | ||
|
||
/** | ||
* Editor for String type values. | ||
*/ | ||
const TextEditor = ({ value, disabled, updateValue, keyfilter}) => { | ||
const [val, setValue] = useState(value); | ||
|
||
return ( | ||
<InputText | ||
style={{ width: '100%' }} | ||
disabled={disabled} | ||
value={val} | ||
onChange={(e) => setValue(e.target.value)} | ||
autoFocus | ||
keyfilter={keyfilter} | ||
onKeyPress={(e) => (e.key === 'Enter') && updateValue(val)} | ||
onBlur={() => updateValue(val)} | ||
/>); | ||
}; | ||
|
||
export default TextEditor; |
56 changes: 56 additions & 0 deletions
56
...nts/inspectit-ocelot-configurationserver-ui/src/components/views/alerting/AlertingView.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import React, { useState, useEffect} from 'react'; | ||
import { TabView, TabPanel } from 'primereact/tabview'; | ||
import AlertingRulesView from './rules/AlertingRulesView'; | ||
import * as topicsAPI from './topics/TopicsAPI'; | ||
|
||
/** | ||
* Tab layout for the alerting view. This view provides a navigation between alerting rules and alerting channels. | ||
*/ | ||
const AlertingView = () => { | ||
const [activeIndex, setActiveIndex] = useState(0); | ||
const [availableTopics, setAvailableTopics] = useState([]); | ||
|
||
useEffect(() => { | ||
topicsAPI.fetchTopics((topics)=>setAvailableTopics(topics)); | ||
}); | ||
|
||
return ( | ||
<div className="this"> | ||
<style jsx>{` | ||
.this { | ||
height: 100%; | ||
display: flex; | ||
} | ||
.this :global(.p-tabview-panels) { | ||
display: flex; | ||
flex-grow: 1; | ||
max-height: calc(100% - 35px); | ||
padding: 0; | ||
} | ||
.this :global(.p-tabview-panel) { | ||
flex-grow: 1; | ||
display: flex; | ||
} | ||
.this :global(.tabView) { | ||
display: flex; | ||
flex-direction: column; | ||
height: 100%; | ||
width: 100%; | ||
} | ||
`}</style> | ||
<TabView className="tabView" activeIndex={activeIndex} onTabChange={(e) => setActiveIndex(e.index)}> | ||
<TabPanel header="Alerting Rules"> | ||
<AlertingRulesView availableTopics={availableTopics}/> | ||
</TabPanel> | ||
{/* Placeholder for the second part of the alerting UI | ||
<TabPanel header="Alerting Topics"> | ||
</TabPanel> */} | ||
</TabView> | ||
</div> | ||
); | ||
}; | ||
|
||
export default AlertingView; |
Oops, something went wrong.