mirror of
https://github.com/Telecominfraproject/wlan-cloud-ucentral-ui-libs.git
synced 2025-11-01 19:27:49 +00:00
Version 1.0.1
This commit is contained in:
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "ucentral-libs",
|
||||
"version": "0.9.91",
|
||||
"version": "1.0.1",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "ucentral-libs",
|
||||
"version": "0.9.91",
|
||||
"version": "1.0.1",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"@coreui/coreui": "^3.4.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ucentral-libs",
|
||||
"version": "0.9.91",
|
||||
"version": "1.0.1",
|
||||
"main": "dist/index.js",
|
||||
"source": "src/index.js",
|
||||
"engines": {
|
||||
|
||||
@@ -34,7 +34,7 @@ const ApiStatusCard = ({ t, info, reload }) => {
|
||||
|
||||
return (
|
||||
<CCard>
|
||||
<CCardHeader className="my-0 p-1 text-light" style={{ backgroundColor: '#2f3d54' }}>
|
||||
<CCardHeader className="dark-header">
|
||||
<div style={{ fontWeight: '600' }} className=" text-value-lg float-left">
|
||||
{info.title}
|
||||
</div>
|
||||
@@ -167,6 +167,7 @@ const ApiStatusCard = ({ t, info, reload }) => {
|
||||
</CModalHeader>
|
||||
<CModalBody>
|
||||
<CDataTable
|
||||
addTableClasses="table-sm"
|
||||
border
|
||||
items={info?.certificates.map((cert) => ({
|
||||
...cert,
|
||||
|
||||
@@ -3,7 +3,15 @@ import PropTypes from 'prop-types';
|
||||
import { CImg } from '@coreui/react';
|
||||
import { emailToName } from '../../utils/formatting';
|
||||
|
||||
const Avatar = ({ src, fallback }) => {
|
||||
const getSize = (size) => {
|
||||
if (size === 'lg') {
|
||||
return 'avatar-lg';
|
||||
}
|
||||
|
||||
return '';
|
||||
};
|
||||
|
||||
const Avatar = ({ src, fallback, size }) => {
|
||||
const [error, setError] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -14,8 +22,8 @@ const Avatar = ({ src, fallback }) => {
|
||||
|
||||
if (!src || src === '' || src === 'data:;base64,' || error) {
|
||||
return (
|
||||
<div className="c-avatar avatar">
|
||||
<div className="avatar bg-secondary">
|
||||
<div className={`c-avatar avatar ${getSize(size)}`}>
|
||||
<div className={`avatar bg-secondary ${getSize(size)}`}>
|
||||
{fallback === 'N/A' ? fallback : emailToName(fallback)}
|
||||
</div>
|
||||
</div>
|
||||
@@ -23,18 +31,20 @@ const Avatar = ({ src, fallback }) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="c-avatar avatar">
|
||||
<CImg className="avatar" src={src} onError={() => setError(true)} />
|
||||
<div className={`c-avatar avatar ${getSize(size)}`}>
|
||||
<CImg className={`avatar ${getSize(size)}`} src={src} onError={() => setError(true)} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Avatar.propTypes = {
|
||||
size: PropTypes.string,
|
||||
src: PropTypes.string,
|
||||
fallback: PropTypes.string,
|
||||
};
|
||||
|
||||
Avatar.defaultProps = {
|
||||
size: 'md',
|
||||
src: '',
|
||||
fallback: 'N/A',
|
||||
};
|
||||
|
||||
224
src/components/CompactNotesTable/index.js
Normal file
224
src/components/CompactNotesTable/index.js
Normal file
@@ -0,0 +1,224 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
CDataTable,
|
||||
CRow,
|
||||
CCol,
|
||||
CButton,
|
||||
CModal,
|
||||
CModalHeader,
|
||||
CPopover,
|
||||
CModalTitle,
|
||||
CModalBody,
|
||||
CInput,
|
||||
} from '@coreui/react';
|
||||
import CIcon from '@coreui/icons-react';
|
||||
import { cilPlus, cilSave, cilSearch, cilX } from '@coreui/icons';
|
||||
import { prettyDate } from '../../utils/formatting';
|
||||
import useToggle from '../../hooks/useToggle';
|
||||
|
||||
const CompactNotesTable = ({ t, notes, addNote, loading, editable, switchToDetailed }) => {
|
||||
const [currentNote, setCurrentNote] = useState('');
|
||||
const [showModal, toggleModal] = useToggle(false);
|
||||
const [showAddModal, toggleAddModal] = useToggle(false);
|
||||
const [tempNotes, setTempNotes] = useState([]);
|
||||
|
||||
const columns = [{ key: 'note', label: t('configuration.note'), _style: { width: '50%' } }];
|
||||
|
||||
const detailedColumns = [
|
||||
{ key: 'created', label: t('common.date'), _style: { width: '30%' } },
|
||||
{ key: 'createdBy', label: t('common.by'), _style: { width: '20%' } },
|
||||
{ key: 'note', label: t('configuration.note'), _style: { width: '50%' } },
|
||||
];
|
||||
|
||||
const saveTemp = () => {
|
||||
for (const note of tempNotes) {
|
||||
if (note.new) {
|
||||
addNote(note.note);
|
||||
}
|
||||
}
|
||||
toggleModal();
|
||||
};
|
||||
|
||||
const addSingleNote = () => {
|
||||
addNote(currentNote);
|
||||
toggleAddModal();
|
||||
};
|
||||
|
||||
const addTempNote = () => {
|
||||
const newNotes = [...tempNotes];
|
||||
newNotes.unshift({
|
||||
note: currentNote,
|
||||
new: true,
|
||||
created: new Date().getTime() / 1000,
|
||||
createdBy: '',
|
||||
});
|
||||
setTempNotes(newNotes);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setTempNotes(notes);
|
||||
setCurrentNote('');
|
||||
}, [notes]);
|
||||
|
||||
useEffect(() => {
|
||||
if (showAddModal || showModal) setCurrentNote('');
|
||||
}, [showAddModal, showModal]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<CRow>
|
||||
<CCol>
|
||||
<div className="overflow-auto border" style={{ height: '200px' }}>
|
||||
<CDataTable
|
||||
responsive
|
||||
border
|
||||
addTableClasses="m-0 p-0 table-sm"
|
||||
loading={loading}
|
||||
fields={columns}
|
||||
items={notes.sort((a, b) => (a.created <= b.created ? 1 : -1)) || []}
|
||||
noItemsView={{ noItems: t('common.no_items') }}
|
||||
columnHeaderSlot={{
|
||||
note: (
|
||||
// eslint-disable-next-line react/jsx-indent
|
||||
<div className="align-middle">
|
||||
{t('configuration.notes')}
|
||||
<CButton
|
||||
className="ml-2 float-right"
|
||||
size="sm"
|
||||
color="primary"
|
||||
variant="outline"
|
||||
onClick={switchToDetailed ?? toggleModal}
|
||||
>
|
||||
<CIcon size="sm" content={cilSearch} />
|
||||
</CButton>
|
||||
<CButton
|
||||
hidden={!editable}
|
||||
className="ml-2 float-right"
|
||||
size="sm"
|
||||
color="primary"
|
||||
variant="outline"
|
||||
onClick={toggleAddModal}
|
||||
>
|
||||
<CIcon size="sm" content={cilPlus} />
|
||||
</CButton>
|
||||
</div>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</CCol>
|
||||
</CRow>
|
||||
<CModal size="lg" show={showModal} onClose={toggleModal}>
|
||||
<CModalHeader className="p-1">
|
||||
<CModalTitle className="pl-1 pt-1">{t('configuration.notes')}</CModalTitle>
|
||||
<div className="text-right">
|
||||
<CPopover content={t('common.save')}>
|
||||
<CButton
|
||||
hidden={!editable}
|
||||
color="primary"
|
||||
variant="outline"
|
||||
className="ml-2"
|
||||
onClick={saveTemp}
|
||||
>
|
||||
<CIcon content={cilSave} />
|
||||
</CButton>
|
||||
</CPopover>
|
||||
<CPopover content={t('common.close')}>
|
||||
<CButton color="primary" variant="outline" className="ml-2" onClick={toggleModal}>
|
||||
<CIcon content={cilX} />
|
||||
</CButton>
|
||||
</CPopover>
|
||||
</div>
|
||||
</CModalHeader>
|
||||
<CModalBody>
|
||||
{editable ? (
|
||||
<div className="d-flex flex-row mb-3">
|
||||
<CInput
|
||||
id="notes-input"
|
||||
name="text-input"
|
||||
value={currentNote}
|
||||
onChange={(e) => setCurrentNote(e.target.value)}
|
||||
/>
|
||||
<CButton
|
||||
className="ml-3"
|
||||
onClick={addTempNote}
|
||||
disabled={loading || currentNote === ''}
|
||||
color="primary"
|
||||
>
|
||||
<CIcon content={cilPlus} />
|
||||
</CButton>
|
||||
</div>
|
||||
) : null}
|
||||
<div className="overflow-auto border" style={{ height: '500px' }}>
|
||||
<CDataTable
|
||||
responsive
|
||||
border
|
||||
addTableClasses="m-0 p-0"
|
||||
loading={loading}
|
||||
fields={detailedColumns}
|
||||
items={tempNotes || []}
|
||||
noItemsView={{ noItems: t('common.no_items') }}
|
||||
sorterValue={{ column: 'created', desc: 'true' }}
|
||||
scopedSlots={{
|
||||
created: (item) => (
|
||||
<td>
|
||||
{item.created && item.created !== 0 ? prettyDate(item.created) : t('common.na')}
|
||||
</td>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</CModalBody>
|
||||
</CModal>
|
||||
<CModal size="lg" show={showAddModal} onClose={toggleAddModal}>
|
||||
<CModalHeader className="p-1">
|
||||
<CModalTitle className="pl-1 pt-1">{t('common.add_note')}</CModalTitle>
|
||||
<div className="text-right">
|
||||
<CPopover content={t('common.add')}>
|
||||
<CButton
|
||||
disabled={currentNote === ''}
|
||||
color="primary"
|
||||
variant="outline"
|
||||
className="ml-2"
|
||||
onClick={addSingleNote}
|
||||
>
|
||||
<CIcon content={cilPlus} />
|
||||
</CButton>
|
||||
</CPopover>
|
||||
<CPopover content={t('common.close')}>
|
||||
<CButton color="primary" variant="outline" className="ml-2" onClick={toggleAddModal}>
|
||||
<CIcon content={cilX} />
|
||||
</CButton>
|
||||
</CPopover>
|
||||
</div>
|
||||
</CModalHeader>
|
||||
<CModalBody>
|
||||
<h6>{t('common.add_note_explanation')}</h6>
|
||||
<CInput
|
||||
id="notes-input"
|
||||
name="text-input"
|
||||
value={currentNote}
|
||||
onChange={(e) => setCurrentNote(e.target.value)}
|
||||
/>
|
||||
</CModalBody>
|
||||
</CModal>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
CompactNotesTable.propTypes = {
|
||||
t: PropTypes.func.isRequired,
|
||||
notes: PropTypes.instanceOf(Array).isRequired,
|
||||
addNote: PropTypes.func.isRequired,
|
||||
loading: PropTypes.bool.isRequired,
|
||||
editable: PropTypes.bool,
|
||||
switchToDetailed: PropTypes.func,
|
||||
};
|
||||
|
||||
CompactNotesTable.defaultProps = {
|
||||
editable: true,
|
||||
switchToDetailed: null,
|
||||
};
|
||||
|
||||
export default CompactNotesTable;
|
||||
@@ -1,13 +1,21 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { CButtonToolbar, CDataTable, CPopover, CButton } from '@coreui/react';
|
||||
import { cilPencil, cilMagnifyingGlass } from '@coreui/icons';
|
||||
import { cilFilterSquare, cilMagnifyingGlass, cilSpreadsheet } from '@coreui/icons';
|
||||
import CIcon from '@coreui/icons-react';
|
||||
import ReactTooltip from 'react-tooltip';
|
||||
import DeleteButton from './DeleteButton';
|
||||
import FormattedDate from '../FormattedDate';
|
||||
|
||||
const ConfigurationTable = ({ t, history, loading, configs, toggleInUse, deleteConfig }) => {
|
||||
const ConfigurationTable = ({
|
||||
t,
|
||||
history,
|
||||
loading,
|
||||
configs,
|
||||
toggleInUse,
|
||||
deleteConfig,
|
||||
toggleEffects,
|
||||
}) => {
|
||||
const columns = [
|
||||
{ key: 'name', label: t('user.name'), _style: { width: '20%' } },
|
||||
{ key: 'description', label: t('user.description'), _style: { width: '20%' } },
|
||||
@@ -35,7 +43,7 @@ const ConfigurationTable = ({ t, history, loading, configs, toggleInUse, deleteC
|
||||
|
||||
return (
|
||||
<CDataTable
|
||||
addTableClasses="ignore-overflow"
|
||||
addTableClasses="ignore-overflow table-sm"
|
||||
items={configs ?? []}
|
||||
fields={columns}
|
||||
hover
|
||||
@@ -60,7 +68,7 @@ const ConfigurationTable = ({ t, history, loading, configs, toggleInUse, deleteC
|
||||
<CButtonToolbar
|
||||
role="group"
|
||||
className="justify-content-flex-end"
|
||||
style={{ width: '150px' }}
|
||||
style={{ width: '200px' }}
|
||||
>
|
||||
<CPopover content={t('configuration.view_in_use')}>
|
||||
<CButton
|
||||
@@ -73,7 +81,21 @@ const ConfigurationTable = ({ t, history, loading, configs, toggleInUse, deleteC
|
||||
onClick={() => toggleInUse(item)}
|
||||
style={{ width: '33px', height: '30px' }}
|
||||
>
|
||||
<CIcon name="cil-magnifying-glass" content={cilMagnifyingGlass} size="sm" />
|
||||
<CIcon name="cil-spreadsheet" content={cilSpreadsheet} size="sm" />
|
||||
</CButton>
|
||||
</CPopover>
|
||||
<CPopover content={t('configuration.view_affected_devices')}>
|
||||
<CButton
|
||||
disabled={item.inUse.length === 0}
|
||||
color="primary"
|
||||
variant="outline"
|
||||
shape="square"
|
||||
size="sm"
|
||||
className="mx-2"
|
||||
onClick={() => toggleEffects(item)}
|
||||
style={{ width: '33px', height: '30px' }}
|
||||
>
|
||||
<CIcon name="cil-filter-square" content={cilFilterSquare} size="sm" />
|
||||
</CButton>
|
||||
</CPopover>
|
||||
<DeleteButton
|
||||
@@ -82,7 +104,7 @@ const ConfigurationTable = ({ t, history, loading, configs, toggleInUse, deleteC
|
||||
deleteConfig={deleteConfig}
|
||||
hideTooltips={hideTooltips}
|
||||
/>
|
||||
<CPopover content={t('configuration.edit_configuration')}>
|
||||
<CPopover content={t('configuration.view_config')}>
|
||||
<CButton
|
||||
color="primary"
|
||||
variant="outline"
|
||||
@@ -92,7 +114,7 @@ const ConfigurationTable = ({ t, history, loading, configs, toggleInUse, deleteC
|
||||
onClick={() => history.push(`/configuration/${item.id}`)}
|
||||
style={{ width: '33px', height: '30px' }}
|
||||
>
|
||||
<CIcon name="cil-pencil" content={cilPencil} size="sm" />
|
||||
<CIcon name="cil-magnifying-glass" content={cilMagnifyingGlass} size="sm" />
|
||||
</CButton>
|
||||
</CPopover>
|
||||
</CButtonToolbar>
|
||||
@@ -110,6 +132,7 @@ ConfigurationTable.propTypes = {
|
||||
configs: PropTypes.instanceOf(Array).isRequired,
|
||||
toggleInUse: PropTypes.func.isRequired,
|
||||
deleteConfig: PropTypes.func.isRequired,
|
||||
toggleEffects: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default ConfigurationTable;
|
||||
|
||||
@@ -20,7 +20,7 @@ const DeleteButton = ({ t, contact, deleteContact, hideTooltips }) => {
|
||||
variant="outline"
|
||||
shape="square"
|
||||
size="sm"
|
||||
className="mx-2"
|
||||
className="mx-1"
|
||||
data-tip
|
||||
data-for={tooltipId}
|
||||
data-event="click"
|
||||
|
||||
@@ -55,7 +55,7 @@ const ContactTable = ({
|
||||
return (
|
||||
<>
|
||||
<CDataTable
|
||||
addTableClasses="ignore-overflow"
|
||||
addTableClasses="ignore-overflow table-sm"
|
||||
items={contacts}
|
||||
fields={columns}
|
||||
hover
|
||||
@@ -94,7 +94,7 @@ const ContactTable = ({
|
||||
<CButtonToolbar
|
||||
role="group"
|
||||
className="justify-content-flex-end"
|
||||
style={{ width: '140px' }}
|
||||
style={{ width: '125px' }}
|
||||
>
|
||||
<CPopover content={t('inventory.assign_ent_ven')}>
|
||||
<div>
|
||||
@@ -104,7 +104,7 @@ const ContactTable = ({
|
||||
variant="outline"
|
||||
shape="square"
|
||||
size="sm"
|
||||
className="mx-2"
|
||||
className="mx-1"
|
||||
onClick={() => assignToEntity(item.id)}
|
||||
style={{ width: '33px', height: '30px' }}
|
||||
>
|
||||
@@ -124,7 +124,7 @@ const ContactTable = ({
|
||||
variant="outline"
|
||||
shape="square"
|
||||
size="sm"
|
||||
className="ml-2"
|
||||
className="mx-1"
|
||||
onClick={() => toggleEditModal(item.id)}
|
||||
style={{ width: '33px', height: '30px' }}
|
||||
>
|
||||
|
||||
97
src/components/DetailedNotesTable/index.js
Normal file
97
src/components/DetailedNotesTable/index.js
Normal file
@@ -0,0 +1,97 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { CDataTable, CRow, CCol, CButton, CInput } from '@coreui/react';
|
||||
import CIcon from '@coreui/icons-react';
|
||||
import { cilPlus } from '@coreui/icons';
|
||||
import { prettyDate } from '../../utils/formatting';
|
||||
|
||||
const DetailedNotesTable = ({ t, notes, addNote, loading, editable }) => {
|
||||
const [currentNote, setCurrentNote] = useState('');
|
||||
|
||||
const detailedColumns = [
|
||||
{ key: 'created', label: t('common.date'), _style: { width: '1%' } },
|
||||
{ key: 'note', label: t('configuration.note'), _style: { width: '50%' } },
|
||||
{ key: 'createdBy', label: t('common.by'), _style: { width: '1%' } },
|
||||
];
|
||||
|
||||
const addNewNote = () => {
|
||||
addNote(currentNote);
|
||||
};
|
||||
useEffect(() => {
|
||||
setCurrentNote('');
|
||||
}, [notes]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<CRow>
|
||||
<CCol>
|
||||
{editable ? (
|
||||
<div className="d-flex flex-row mt-2 mb-2">
|
||||
<CInput
|
||||
id="notes-input"
|
||||
name="text-input"
|
||||
value={currentNote}
|
||||
onChange={(e) => setCurrentNote(e.target.value)}
|
||||
/>
|
||||
<CButton
|
||||
className="ml-3"
|
||||
onClick={addNewNote}
|
||||
disabled={loading || currentNote === ''}
|
||||
color="primary"
|
||||
>
|
||||
<CIcon content={cilPlus} />
|
||||
</CButton>
|
||||
</div>
|
||||
) : null}
|
||||
<div className="overflow-auto border mb-2" style={{ height: '200px' }}>
|
||||
<CDataTable
|
||||
responsive
|
||||
border
|
||||
addTableClasses="m-0 p-0 table-sm"
|
||||
loading={loading}
|
||||
fields={detailedColumns}
|
||||
items={notes || []}
|
||||
noItemsView={{ noItems: t('common.no_items') }}
|
||||
sorterValue={{ column: 'created', desc: 'true' }}
|
||||
scopedSlots={{
|
||||
created: (item) => (
|
||||
<td>
|
||||
<div style={{ width: '150px' }}>
|
||||
{item.created && item.created !== 0
|
||||
? prettyDate(item.created)
|
||||
: t('common.na')}
|
||||
</div>
|
||||
</td>
|
||||
),
|
||||
createdBy: (item) => (
|
||||
<td>
|
||||
<div style={{ width: '300px' }}>{item.createdBy}</div>
|
||||
</td>
|
||||
),
|
||||
note: (item) => (
|
||||
<td>
|
||||
<div style={{ minWidth: '200px' }}>{item.note}</div>
|
||||
</td>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</CCol>
|
||||
</CRow>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
DetailedNotesTable.propTypes = {
|
||||
t: PropTypes.func.isRequired,
|
||||
notes: PropTypes.instanceOf(Array).isRequired,
|
||||
addNote: PropTypes.func.isRequired,
|
||||
loading: PropTypes.bool.isRequired,
|
||||
editable: PropTypes.bool,
|
||||
};
|
||||
|
||||
DetailedNotesTable.defaultProps = {
|
||||
editable: true,
|
||||
};
|
||||
|
||||
export default DetailedNotesTable;
|
||||
@@ -45,7 +45,10 @@ const DeviceBadge = ({ t, device, deviceIcons }) => {
|
||||
|
||||
return (
|
||||
<CPopover content={device.verifiedCertificate} placement="top">
|
||||
<div className={`c-avatar c-avatar-lg ${getCertColor()}`}>
|
||||
<div
|
||||
style={{ height: '35px', width: '35px' }}
|
||||
className={`c-avatar c-avatar-lg ${getCertColor()}`}
|
||||
>
|
||||
<img src={src} className={styles.icon} alt={device.deviceType} />
|
||||
<CPopover content={device.connected ? t('common.connected') : t('common.not_connected')}>
|
||||
<span
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.icon {
|
||||
height: 36px;
|
||||
width: 36px;
|
||||
height: 25px;
|
||||
width: 25px;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ const getIcon = (health) => {
|
||||
|
||||
const DeviceDashboard = ({ t, data }) => (
|
||||
<div>
|
||||
<CRow>
|
||||
<CRow className="mt-3">
|
||||
<CCol>
|
||||
<CWidgetIcon
|
||||
text={t('common.last_dashboard_refresh')}
|
||||
@@ -57,7 +57,7 @@ const DeviceDashboard = ({ t, data }) => (
|
||||
<CRow>
|
||||
<CCol>
|
||||
<CCard>
|
||||
<CCardHeader>{t('common.device_status')}</CCardHeader>
|
||||
<CCardHeader className="dark-header">{t('common.device_status')}</CCardHeader>
|
||||
<CCardBody>
|
||||
<CChartPie
|
||||
datasets={data.status.datasets}
|
||||
@@ -80,7 +80,7 @@ const DeviceDashboard = ({ t, data }) => (
|
||||
</CCol>
|
||||
<CCol>
|
||||
<CCard>
|
||||
<CCardHeader>{t('common.device_health')}</CCardHeader>
|
||||
<CCardHeader className="dark-header">{t('common.device_health')}</CCardHeader>
|
||||
<CCardBody>
|
||||
<CChartPie
|
||||
datasets={data.healths.datasets}
|
||||
@@ -104,7 +104,7 @@ const DeviceDashboard = ({ t, data }) => (
|
||||
</CCol>
|
||||
<CCol>
|
||||
<CCard>
|
||||
<CCardHeader>
|
||||
<CCardHeader className="dark-header">
|
||||
{data.totalAssociations}{' '}
|
||||
{data.totalAssociations === 1
|
||||
? t('wifi_analysis.association')
|
||||
@@ -137,7 +137,7 @@ const DeviceDashboard = ({ t, data }) => (
|
||||
<CRow>
|
||||
<CCol>
|
||||
<CCard>
|
||||
<CCardHeader>{t('common.vendors')}</CCardHeader>
|
||||
<CCardHeader className="dark-header">{t('common.vendors')}</CCardHeader>
|
||||
<CCardBody>
|
||||
<CChartBar
|
||||
datasets={data.vendors.datasets}
|
||||
@@ -162,7 +162,7 @@ const DeviceDashboard = ({ t, data }) => (
|
||||
</CCol>
|
||||
<CCol>
|
||||
<CCard>
|
||||
<CCardHeader>{t('firmware.device_types')}</CCardHeader>
|
||||
<CCardHeader className="dark-header">{t('firmware.device_types')}</CCardHeader>
|
||||
<CCardBody>
|
||||
<CChartPie
|
||||
datasets={data.deviceType.datasets}
|
||||
@@ -186,7 +186,7 @@ const DeviceDashboard = ({ t, data }) => (
|
||||
</CCol>
|
||||
<CCol>
|
||||
<CCard>
|
||||
<CCardHeader>{t('common.uptimes')}</CCardHeader>
|
||||
<CCardHeader className="dark-header">{t('common.uptimes')}</CCardHeader>
|
||||
<CCardBody>
|
||||
<CChartBar
|
||||
datasets={data.upTimes.datasets}
|
||||
@@ -213,7 +213,7 @@ const DeviceDashboard = ({ t, data }) => (
|
||||
<CRow>
|
||||
<CCol>
|
||||
<CCard>
|
||||
<CCardHeader>{t('common.certificates')}</CCardHeader>
|
||||
<CCardHeader className="dark-header">{t('common.certificates')}</CCardHeader>
|
||||
<CCardBody>
|
||||
<CChartPie
|
||||
datasets={data.certificates.datasets}
|
||||
@@ -236,7 +236,7 @@ const DeviceDashboard = ({ t, data }) => (
|
||||
</CCol>
|
||||
<CCol>
|
||||
<CCard>
|
||||
<CCardHeader>{t('common.commands')}</CCardHeader>
|
||||
<CCardHeader className="dark-header">{t('common.commands')}</CCardHeader>
|
||||
<CCardBody>
|
||||
<CChartBar
|
||||
datasets={data.commands.datasets}
|
||||
@@ -261,7 +261,7 @@ const DeviceDashboard = ({ t, data }) => (
|
||||
</CCol>
|
||||
<CCol>
|
||||
<CCard>
|
||||
<CCardHeader>{t('common.memory_used')}</CCardHeader>
|
||||
<CCardHeader className="dark-header">{t('common.memory_used')}</CCardHeader>
|
||||
<CCardBody>
|
||||
<CChartBar
|
||||
datasets={data.memoryUsed.datasets}
|
||||
|
||||
@@ -54,11 +54,11 @@ const DeviceDetails = ({ t, loading, getData, status, deviceConfig, lastStats })
|
||||
|
||||
return (
|
||||
<CCard className="m-0">
|
||||
<CCardHeader className="p-1">
|
||||
<CCardHeader className="dark-header">
|
||||
<div className="d-flex flex-row-reverse align-items-center">
|
||||
<div className="text-right">
|
||||
<CPopover content={t('common.refresh')}>
|
||||
<CButton size="sm" color="primary" variant="outline" onClick={getData}>
|
||||
<CButton size="sm" color="info" onClick={getData}>
|
||||
<CIcon content={cilSync} />
|
||||
</CButton>
|
||||
</CPopover>
|
||||
|
||||
@@ -76,6 +76,7 @@ const DeviceFirmwareModal = ({
|
||||
<CCol>
|
||||
<div className="overflow-auto" style={{ height: '600px' }}>
|
||||
<CDataTable
|
||||
addTableClasses="table-sm"
|
||||
items={firmwareVersions}
|
||||
fields={fields}
|
||||
loading={loading}
|
||||
|
||||
@@ -92,14 +92,14 @@ const DeviceListTable = ({
|
||||
const tooltipId = createUuid();
|
||||
let text = t('firmware.unknown_firmware_status');
|
||||
let upgradeText = t('firmware.upgrade_to_latest');
|
||||
let icon = <CIcon size="lg" name="cil-arrow-circle-top" content={cilArrowCircleTop} />;
|
||||
let icon = <CIcon size="md" name="cil-arrow-circle-top" content={cilArrowCircleTop} />;
|
||||
let color = 'secondary';
|
||||
if (latest !== undefined) {
|
||||
text = t('firmware.newer_firmware_available');
|
||||
color = 'warning';
|
||||
|
||||
if (latest) {
|
||||
icon = <CIcon size="lg" name="cil-check-circle" content={cilCheckCircle} />;
|
||||
icon = <CIcon size="md" name="cil-check-circle" content={cilCheckCircle} />;
|
||||
text = t('firmware.latest_version_installed');
|
||||
upgradeText = t('firmware.reinstall_latest');
|
||||
color = 'success';
|
||||
@@ -107,7 +107,7 @@ const DeviceListTable = ({
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<CButton color={color} data-tip data-for={tooltipId} data-event="click">
|
||||
<CButton size="sm" color={color} data-tip data-for={tooltipId} data-event="click">
|
||||
{icon}
|
||||
</CButton>
|
||||
<ReactTooltip
|
||||
@@ -252,15 +252,15 @@ const DeviceListTable = ({
|
||||
|
||||
return (
|
||||
<>
|
||||
<CCard>
|
||||
<CCardHeader>
|
||||
<CCard className="m-0 p-0">
|
||||
<CCardHeader className="dark-header">
|
||||
<div className="float-left" style={{ width: '400px' }}>
|
||||
{searchBar}
|
||||
</div>
|
||||
</CCardHeader>
|
||||
<CCardBody className="p-0">
|
||||
<CDataTable
|
||||
addTableClasses="ignore-overflow"
|
||||
addTableClasses="ignore-overflow table-sm"
|
||||
items={devices ?? []}
|
||||
fields={columns}
|
||||
hover
|
||||
@@ -268,7 +268,7 @@ const DeviceListTable = ({
|
||||
loading={loading}
|
||||
scopedSlots={{
|
||||
deviceType: (item) => (
|
||||
<td className="pt-3 text-center">
|
||||
<td className="align-middle text-center">
|
||||
<DeviceBadge t={t} device={item} deviceIcons={deviceIcons} />
|
||||
</td>
|
||||
),
|
||||
|
||||
@@ -37,11 +37,11 @@ const DeviceStatusCard = ({
|
||||
lastStats,
|
||||
}) => (
|
||||
<CCard>
|
||||
<CCardHeader className="p-1">
|
||||
<CCardHeader className="dark-header">
|
||||
<div className="d-flex flex-row-reverse align-items-center">
|
||||
<div className="text-right">
|
||||
<CPopover content={t('common.refresh')}>
|
||||
<CButton size="sm" color="primary" variant="outline" onClick={getData}>
|
||||
<CButton size="sm" color="info" onClick={getData}>
|
||||
<CIcon content={cilSync} />
|
||||
</CButton>
|
||||
</CPopover>
|
||||
|
||||
@@ -7,13 +7,11 @@ import {
|
||||
CFormGroup,
|
||||
CInvalidFeedback,
|
||||
CFormText,
|
||||
CRow,
|
||||
CButton,
|
||||
CSwitch,
|
||||
} from '@coreui/react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Select from 'react-select';
|
||||
import NotesTable from '../NotesTable';
|
||||
import FormattedDate from '../FormattedDate';
|
||||
import selectStyles from '../../utils/selectStyles';
|
||||
|
||||
@@ -23,7 +21,6 @@ const EditConfigurationForm = ({
|
||||
fields,
|
||||
updateField,
|
||||
updateFieldWithKey,
|
||||
addNote,
|
||||
editing,
|
||||
toggleInUseModal,
|
||||
deviceTypes,
|
||||
@@ -84,188 +81,159 @@ const EditConfigurationForm = ({
|
||||
return (
|
||||
<CForm>
|
||||
<CFormGroup row>
|
||||
<CCol>
|
||||
<CRow className="pb-0">
|
||||
<CLabel lg="5" xl="3" col htmlFor="name">
|
||||
<div>{t('user.name')}:</div>
|
||||
</CLabel>
|
||||
<CCol lg="7" xl="9">
|
||||
{editing ? (
|
||||
<div>
|
||||
<CInput
|
||||
id="name"
|
||||
type="text"
|
||||
required
|
||||
value={fields.name.value}
|
||||
onChange={updateField}
|
||||
invalid={fields.name.error}
|
||||
disabled={disable}
|
||||
maxLength="50"
|
||||
/>
|
||||
<CFormText hidden={!fields.name.error} color={fields.name.error ? 'danger' : ''}>
|
||||
{t('common.required')}
|
||||
</CFormText>
|
||||
</div>
|
||||
) : (
|
||||
<p className="mt-2 mb-0">{fields.name.value}</p>
|
||||
)}
|
||||
</CCol>
|
||||
</CRow>
|
||||
<CRow className="pb-0">
|
||||
<CLabel lg="5" xl="3" col htmlFor="name">
|
||||
<div>{t('user.description')}:</div>
|
||||
</CLabel>
|
||||
<CCol lg="7" xl="9">
|
||||
{editing ? (
|
||||
<div>
|
||||
<CInput
|
||||
id="description"
|
||||
type="text"
|
||||
required
|
||||
value={fields.description.value}
|
||||
onChange={updateField}
|
||||
invalid={fields.description.error}
|
||||
disabled={disable}
|
||||
maxLength="50"
|
||||
/>
|
||||
<CInvalidFeedback>{t('common.required')}</CInvalidFeedback>
|
||||
</div>
|
||||
) : (
|
||||
<p className="mt-2 mb-0">{fields.description.value}</p>
|
||||
)}
|
||||
</CCol>
|
||||
</CRow>
|
||||
<CRow className="pt-1">
|
||||
<CLabel lg="5" xl="3" col htmlFor="name">
|
||||
<div>{t('configuration.device_types')}:</div>
|
||||
</CLabel>
|
||||
<CCol lg="7" xl="9">
|
||||
<Select
|
||||
isMulti
|
||||
styles={selectStyles}
|
||||
closeMenuOnSelect={false}
|
||||
name="Device Types"
|
||||
options={typeOptions}
|
||||
onChange={typeOnChange}
|
||||
value={chosenTypes}
|
||||
className={`basic-multi-select ${fields.deviceTypes.error ? 'border-danger' : ''}`}
|
||||
classNamePrefix="select"
|
||||
isDisabled={!editing}
|
||||
<CLabel className="mb-2" md="5" lg="2" xl="2" xxl="1" col htmlFor="name">
|
||||
<div>{t('user.name')}:</div>
|
||||
</CLabel>
|
||||
<CCol md="7" lg="4" xl="4" xxl="5">
|
||||
{editing ? (
|
||||
<div>
|
||||
<CInput
|
||||
id="name"
|
||||
type="text"
|
||||
required
|
||||
value={fields.name.value}
|
||||
onChange={updateField}
|
||||
invalid={fields.name.error}
|
||||
disabled={disable}
|
||||
maxLength="50"
|
||||
/>
|
||||
<CFormText hidden={!fields.deviceTypes.error} color="danger">
|
||||
{t('configuration.need_device_type')}
|
||||
</CFormText>
|
||||
</CCol>
|
||||
</CRow>
|
||||
<CRow className="pt-1 pb-0">
|
||||
<CLabel lg="5" xl="3" col htmlFor="name">
|
||||
<div>RRM:</div>
|
||||
</CLabel>
|
||||
<CCol lg="7" xl="9">
|
||||
<div style={{ width: '120px' }}>
|
||||
<Select
|
||||
id="rrm"
|
||||
styles={selectStyles}
|
||||
value={{ value: fields.rrm.value, label: fields.rrm.value }}
|
||||
onChange={(v) => updateFieldWithKey('rrm', { value: v.value })}
|
||||
options={[
|
||||
{ label: 'on', value: 'on' },
|
||||
{ label: 'off', value: 'off' },
|
||||
{ label: 'inherit', value: 'inherit' },
|
||||
]}
|
||||
isDisabled={!editing}
|
||||
/>
|
||||
</div>
|
||||
<CFormText color="danger" hidden={!fields.rrm.error}>
|
||||
<CFormText hidden={!fields.name.error} color={fields.name.error ? 'danger' : ''}>
|
||||
{t('common.required')}
|
||||
</CFormText>
|
||||
</CCol>
|
||||
</CRow>
|
||||
<CRow className="py-1">
|
||||
<CLabel col lg="5" xl="3" htmlFor="firmwareUpgrade">
|
||||
Firmware Upgrade
|
||||
</CLabel>
|
||||
<CCol lg="7" xl="9">
|
||||
<div style={{ width: '120px' }}>
|
||||
<Select
|
||||
id="rrm"
|
||||
styles={selectStyles}
|
||||
value={{
|
||||
value: fields.firmwareUpgrade.value,
|
||||
label: fields.firmwareUpgrade.value,
|
||||
}}
|
||||
onChange={(v) => updateFieldWithKey('firmwareUpgrade', { value: v.value })}
|
||||
options={[
|
||||
{ label: 'yes', value: 'yes' },
|
||||
{ label: 'no', value: 'no' },
|
||||
{ label: 'inherit', value: 'inherit' },
|
||||
]}
|
||||
isDisabled={!editing}
|
||||
/>
|
||||
</div>
|
||||
</CCol>
|
||||
</CRow>
|
||||
<CRow className="py-1">
|
||||
<CLabel col lg="5" xl="3" htmlFor="firmwareRCOnly">
|
||||
Only Release Candidates
|
||||
</CLabel>
|
||||
<CCol lg="7" xl="9">
|
||||
<CSwitch
|
||||
id="firmwareRCOnly"
|
||||
color="primary"
|
||||
defaultChecked={fields.firmwareRCOnly.value}
|
||||
onClick={() =>
|
||||
updateFieldWithKey('firmwareRCOnly', { value: !fields.firmwareRCOnly.value })
|
||||
}
|
||||
size="lg"
|
||||
disabled={!editing || fields.firmwareUpgrade.value === 'no'}
|
||||
/>
|
||||
</CCol>
|
||||
</CRow>
|
||||
<CRow className="pb-0">
|
||||
<CLabel lg="5" xl="3" col htmlFor="name">
|
||||
<div>{t('configuration.used_by')}:</div>
|
||||
</CLabel>
|
||||
<CCol lg="7" xl="9">
|
||||
<CButton
|
||||
disabled={fields.inUse.value.length === 0}
|
||||
className="ml-0 pl-0"
|
||||
color="link"
|
||||
onClick={toggleInUseModal}
|
||||
>
|
||||
{config?.parsedInUse}
|
||||
</CButton>
|
||||
</CCol>
|
||||
</CRow>
|
||||
</div>
|
||||
) : (
|
||||
<p className="mt-2 mb-0">{fields.name.value}</p>
|
||||
)}
|
||||
</CCol>
|
||||
<CCol className="mt-2">
|
||||
<CRow className="pb-0">
|
||||
<CLabel lg="5" xl="3" col htmlFor="name">
|
||||
<div>{t('common.created')}:</div>
|
||||
</CLabel>
|
||||
<CCol lg="7" xl="9">
|
||||
<p className="mt-2 mb-0">
|
||||
<FormattedDate date={fields.created.value} />
|
||||
</p>
|
||||
</CCol>
|
||||
</CRow>
|
||||
<CRow className="pb-0">
|
||||
<CLabel lg="5" xl="3" col htmlFor="name">
|
||||
<div>{t('common.modified')}:</div>
|
||||
</CLabel>
|
||||
<CCol lg="7" xl="9">
|
||||
<p className="mt-2 mb-0">
|
||||
<FormattedDate date={fields.modified.value} />
|
||||
</p>
|
||||
</CCol>
|
||||
</CRow>
|
||||
<NotesTable
|
||||
t={t}
|
||||
notes={fields.notes.value}
|
||||
addNote={addNote}
|
||||
loading={disable}
|
||||
editable={editing}
|
||||
<CLabel className="mb-2" md="5" lg="2" xl="2" xxl="1" col htmlFor="name">
|
||||
<div>{t('user.description')}:</div>
|
||||
</CLabel>
|
||||
<CCol md="7" lg="4" xl="4" xxl="5">
|
||||
{editing ? (
|
||||
<div>
|
||||
<CInput
|
||||
id="description"
|
||||
type="text"
|
||||
required
|
||||
value={fields.description.value}
|
||||
onChange={updateField}
|
||||
invalid={fields.description.error}
|
||||
disabled={disable}
|
||||
maxLength="50"
|
||||
/>
|
||||
<CInvalidFeedback>{t('common.required')}</CInvalidFeedback>
|
||||
</div>
|
||||
) : (
|
||||
<p className="mt-2 mb-0">{fields.description.value}</p>
|
||||
)}
|
||||
</CCol>
|
||||
<CLabel className="mb-2" md="5" lg="2" xl="2" xxl="1" col htmlFor="name">
|
||||
<div>{t('configuration.device_types')}:</div>
|
||||
</CLabel>
|
||||
<CCol md="7" lg="4" xl="4" xxl="5">
|
||||
<Select
|
||||
isMulti
|
||||
styles={selectStyles}
|
||||
closeMenuOnSelect={false}
|
||||
name="Device Types"
|
||||
options={typeOptions}
|
||||
onChange={typeOnChange}
|
||||
value={chosenTypes}
|
||||
className={`basic-multi-select ${fields.deviceTypes.error ? 'border-danger' : ''}`}
|
||||
classNamePrefix="select"
|
||||
isDisabled={!editing}
|
||||
/>
|
||||
<CFormText hidden={!fields.deviceTypes.error} color="danger">
|
||||
{t('configuration.need_device_type')}
|
||||
</CFormText>
|
||||
</CCol>
|
||||
<CLabel className="mb-2" md="5" lg="2" xl="2" xxl="1" col htmlFor="name">
|
||||
<div>RRM:</div>
|
||||
</CLabel>
|
||||
<CCol md="7" lg="4" xl="4" xxl="5">
|
||||
<div style={{ width: '120px' }}>
|
||||
<Select
|
||||
id="rrm"
|
||||
styles={selectStyles}
|
||||
value={{ value: fields.rrm.value, label: fields.rrm.value }}
|
||||
onChange={(v) => updateFieldWithKey('rrm', { value: v.value })}
|
||||
options={[
|
||||
{ label: 'on', value: 'on' },
|
||||
{ label: 'off', value: 'off' },
|
||||
{ label: 'inherit', value: 'inherit' },
|
||||
]}
|
||||
isDisabled={!editing}
|
||||
/>
|
||||
</div>
|
||||
<CFormText color="danger" hidden={!fields.rrm.error}>
|
||||
{t('common.required')}
|
||||
</CFormText>
|
||||
</CCol>
|
||||
<CLabel col className="mb-2" md="5" lg="2" xl="2" xxl="1" htmlFor="firmwareUpgrade">
|
||||
Firmware Upgrade
|
||||
</CLabel>
|
||||
<CCol md="7" lg="4" xl="4" xxl="5">
|
||||
<div style={{ width: '120px' }}>
|
||||
<Select
|
||||
id="rrm"
|
||||
styles={selectStyles}
|
||||
value={{
|
||||
value: fields.firmwareUpgrade.value,
|
||||
label: fields.firmwareUpgrade.value,
|
||||
}}
|
||||
onChange={(v) => updateFieldWithKey('firmwareUpgrade', { value: v.value })}
|
||||
options={[
|
||||
{ label: 'yes', value: 'yes' },
|
||||
{ label: 'no', value: 'no' },
|
||||
{ label: 'inherit', value: 'inherit' },
|
||||
]}
|
||||
isDisabled={!editing}
|
||||
/>
|
||||
</div>
|
||||
</CCol>
|
||||
<CLabel col className="mb-2" md="5" lg="2" xl="2" xxl="1" htmlFor="firmwareRCOnly">
|
||||
Only Release Candidates
|
||||
</CLabel>
|
||||
<CCol md="7" lg="4" xl="4" xxl="5">
|
||||
<CSwitch
|
||||
id="firmwareRCOnly"
|
||||
color="primary"
|
||||
defaultChecked={fields.firmwareRCOnly.value}
|
||||
onClick={() =>
|
||||
updateFieldWithKey('firmwareRCOnly', { value: !fields.firmwareRCOnly.value })
|
||||
}
|
||||
size="lg"
|
||||
disabled={!editing || fields.firmwareUpgrade.value === 'no'}
|
||||
/>
|
||||
</CCol>
|
||||
<CLabel className="mb-2" md="5" lg="2" xl="2" xxl="1" col htmlFor="name">
|
||||
<div>{t('common.created')}:</div>
|
||||
</CLabel>
|
||||
<CCol md="7" lg="4" xl="4" xxl="5">
|
||||
<p className="mt-2 mb-0">
|
||||
<FormattedDate date={fields.created.value} />
|
||||
</p>
|
||||
</CCol>
|
||||
<CLabel className="mb-2" md="5" lg="2" xl="2" xxl="1" col htmlFor="name">
|
||||
<div>{t('common.modified')}:</div>
|
||||
</CLabel>
|
||||
<CCol md="7" lg="4" xl="4" xxl="5">
|
||||
<p className="mt-2 mb-0">
|
||||
<FormattedDate date={fields.modified.value} />
|
||||
</p>
|
||||
</CCol>
|
||||
<CLabel className="mb-2" md="5" lg="2" xl="2" xxl="1" col htmlFor="inUse">
|
||||
<div>{t('configuration.used_by')}:</div>
|
||||
</CLabel>
|
||||
<CCol md="7" lg="4" xl="4" xxl="5">
|
||||
<CButton
|
||||
disabled={fields.inUse.value.length === 0}
|
||||
className="ml-0 pl-0"
|
||||
color="link"
|
||||
onClick={toggleInUseModal}
|
||||
>
|
||||
{config?.parsedInUse}
|
||||
</CButton>
|
||||
</CCol>
|
||||
</CFormGroup>
|
||||
</CForm>
|
||||
@@ -278,7 +246,6 @@ EditConfigurationForm.propTypes = {
|
||||
fields: PropTypes.instanceOf(Object).isRequired,
|
||||
updateField: PropTypes.func.isRequired,
|
||||
updateFieldWithKey: PropTypes.func.isRequired,
|
||||
addNote: PropTypes.func.isRequired,
|
||||
editing: PropTypes.bool.isRequired,
|
||||
toggleInUseModal: PropTypes.func.isRequired,
|
||||
deviceTypes: PropTypes.instanceOf(Array).isRequired,
|
||||
|
||||
@@ -16,7 +16,6 @@ import {
|
||||
CButton,
|
||||
} from '@coreui/react';
|
||||
import FormattedDate from '../FormattedDate';
|
||||
import NotesTable from '../NotesTable';
|
||||
import RequiredAsterisk from '../RequiredAsterisk';
|
||||
import selectStyles from '../../utils/selectStyles';
|
||||
|
||||
@@ -27,9 +26,9 @@ const EditContactForm = ({
|
||||
updateField,
|
||||
updateFieldWithKey,
|
||||
entities,
|
||||
addNote,
|
||||
batchSetField,
|
||||
hideEntities,
|
||||
editing,
|
||||
}) => {
|
||||
const [filter, setFilter] = useState('');
|
||||
|
||||
@@ -83,7 +82,7 @@ const EditContactForm = ({
|
||||
{ label: 'TECHNICIAN', value: 'TECHNICIAN' },
|
||||
{ label: 'CORPORATE', value: 'CORPORATE' },
|
||||
]}
|
||||
isDisabled={disable}
|
||||
isDisabled={disable || !editing}
|
||||
/>
|
||||
</div>
|
||||
<CFormText hidden={!fields.type.error} color={fields.type.error ? 'danger' : ''}>
|
||||
@@ -95,34 +94,46 @@ const EditContactForm = ({
|
||||
<RequiredAsterisk />
|
||||
</CLabel>
|
||||
<CCol sm="4">
|
||||
<CInput
|
||||
id="name"
|
||||
type="text"
|
||||
required
|
||||
value={fields.name.value}
|
||||
onChange={updateField}
|
||||
invalid={fields.name.error}
|
||||
disabled={disable}
|
||||
maxLength="50"
|
||||
/>
|
||||
<CFormText hidden={!fields.name.error} color={fields.name.error ? 'danger' : ''}>
|
||||
{t('common.required')}
|
||||
</CFormText>
|
||||
{editing ? (
|
||||
<div>
|
||||
<CInput
|
||||
id="name"
|
||||
type="text"
|
||||
required
|
||||
value={fields.name.value}
|
||||
onChange={updateField}
|
||||
invalid={fields.name.error}
|
||||
disabled={disable}
|
||||
maxLength="50"
|
||||
/>
|
||||
<CFormText hidden={!fields.name.error} color={fields.name.error ? 'danger' : ''}>
|
||||
{t('common.required')}
|
||||
</CFormText>
|
||||
</div>
|
||||
) : (
|
||||
<p className="mt-2 mb-0">{fields.name.value}</p>
|
||||
)}
|
||||
</CCol>
|
||||
<CLabel className="mb-2" sm="2" col htmlFor="title">
|
||||
{t('contact.user_title')}
|
||||
</CLabel>
|
||||
<CCol sm="4">
|
||||
<CInput
|
||||
id="title"
|
||||
type="text"
|
||||
required
|
||||
value={fields.title.value}
|
||||
onChange={updateField}
|
||||
invalid={fields.title.error}
|
||||
disabled={disable}
|
||||
maxLength="50"
|
||||
/>
|
||||
{editing ? (
|
||||
<div>
|
||||
<CInput
|
||||
id="title"
|
||||
type="text"
|
||||
required
|
||||
value={fields.title.value}
|
||||
onChange={updateField}
|
||||
invalid={fields.title.error}
|
||||
disabled={disable}
|
||||
maxLength="50"
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<p className="mt-2 mb-0">{fields.title.value}</p>
|
||||
)}
|
||||
</CCol>
|
||||
<CLabel className="mb-2" sm="2" col htmlFor="salutation">
|
||||
{t('contact.salutation')}
|
||||
@@ -144,7 +155,7 @@ const EditContactForm = ({
|
||||
{ label: 'Mx.', value: 'Mx.' },
|
||||
{ label: 'Dr.', value: 'Dr.' },
|
||||
]}
|
||||
isDisabled={disable}
|
||||
isDisabled={disable || !editing}
|
||||
/>
|
||||
</div>
|
||||
</CCol>
|
||||
@@ -153,119 +164,184 @@ const EditContactForm = ({
|
||||
<RequiredAsterisk />
|
||||
</CLabel>
|
||||
<CCol sm="4">
|
||||
<CInput
|
||||
id="firstname"
|
||||
type="text"
|
||||
required
|
||||
value={fields.firstname.value}
|
||||
onChange={updateField}
|
||||
invalid={fields.firstname.error}
|
||||
disabled={disable}
|
||||
maxLength="50"
|
||||
/>
|
||||
<CFormText
|
||||
hidden={!fields.firstname.error}
|
||||
color={fields.firstname.error ? 'danger' : ''}
|
||||
>
|
||||
{t('common.required')}
|
||||
</CFormText>
|
||||
{editing ? (
|
||||
<div>
|
||||
<CInput
|
||||
id="firstname"
|
||||
type="text"
|
||||
required
|
||||
value={fields.firstname.value}
|
||||
onChange={updateField}
|
||||
invalid={fields.firstname.error}
|
||||
disabled={disable}
|
||||
maxLength="50"
|
||||
/>
|
||||
<CFormText
|
||||
hidden={!fields.firstname.error}
|
||||
color={fields.firstname.error ? 'danger' : ''}
|
||||
>
|
||||
{t('common.required')}
|
||||
</CFormText>
|
||||
</div>
|
||||
) : (
|
||||
<p className="mt-2 mb-0">{fields.firstname.value}</p>
|
||||
)}
|
||||
</CCol>
|
||||
<CLabel className="mb-2" sm="2" col htmlFor="lastname">
|
||||
{t('contact.last_name')}
|
||||
<RequiredAsterisk />
|
||||
</CLabel>
|
||||
<CCol sm="4">
|
||||
<CInput
|
||||
id="lastname"
|
||||
type="text"
|
||||
required
|
||||
value={fields.lastname.value}
|
||||
onChange={updateField}
|
||||
invalid={fields.lastname.error}
|
||||
disabled={disable}
|
||||
maxLength="50"
|
||||
/>
|
||||
<CFormText hidden={!fields.lastname.error} color={fields.lastname.error ? 'danger' : ''}>
|
||||
{t('common.required')}
|
||||
</CFormText>
|
||||
{editing ? (
|
||||
<div>
|
||||
<CInput
|
||||
id="lastname"
|
||||
type="text"
|
||||
required
|
||||
value={fields.lastname.value}
|
||||
onChange={updateField}
|
||||
invalid={fields.lastname.error}
|
||||
disabled={disable}
|
||||
maxLength="50"
|
||||
/>
|
||||
<CFormText
|
||||
hidden={!fields.lastname.error}
|
||||
color={fields.lastname.error ? 'danger' : ''}
|
||||
>
|
||||
{t('common.required')}
|
||||
</CFormText>
|
||||
</div>
|
||||
) : (
|
||||
<p className="mt-2 mb-0">{fields.lastname.value}</p>
|
||||
)}
|
||||
</CCol>
|
||||
<CLabel className="mb-2" sm="2" col htmlFor="initials">
|
||||
{t('contact.initials')}
|
||||
</CLabel>
|
||||
<CCol sm="4">
|
||||
<CInput
|
||||
id="initials"
|
||||
type="text"
|
||||
required
|
||||
value={fields.initials.value}
|
||||
onChange={updateField}
|
||||
disabled={disable}
|
||||
maxLength="50"
|
||||
/>
|
||||
{editing ? (
|
||||
<div>
|
||||
<CInput
|
||||
id="initials"
|
||||
type="text"
|
||||
required
|
||||
value={fields.initials.value}
|
||||
onChange={updateField}
|
||||
disabled={disable}
|
||||
maxLength="50"
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<p className="mt-2 mb-0">{fields.initials.value}</p>
|
||||
)}
|
||||
</CCol>
|
||||
<CLabel sm="2" col htmlFor="visual">
|
||||
{t('contact.visual')}
|
||||
</CLabel>
|
||||
<CCol sm="4">
|
||||
<CInput
|
||||
id="visual"
|
||||
type="text"
|
||||
required
|
||||
value={fields.visual.value}
|
||||
onChange={updateField}
|
||||
disabled={disable}
|
||||
maxLength="50"
|
||||
/>
|
||||
{editing ? (
|
||||
<div>
|
||||
<CInput
|
||||
id="visual"
|
||||
type="text"
|
||||
required
|
||||
value={fields.visual.value}
|
||||
onChange={updateField}
|
||||
disabled={disable}
|
||||
maxLength="50"
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<p className="mt-2 mb-0">{fields.visual.value}</p>
|
||||
)}
|
||||
</CCol>
|
||||
<CLabel className="mb-2" sm="2" col htmlFor="primaryEmail">
|
||||
{t('contact.primary_email')}
|
||||
<RequiredAsterisk />
|
||||
</CLabel>
|
||||
<CCol sm="4">
|
||||
<CInput
|
||||
id="primaryEmail"
|
||||
type="text"
|
||||
required
|
||||
value={fields.primaryEmail.value}
|
||||
onChange={updateField}
|
||||
invalid={fields.primaryEmail.error}
|
||||
disabled={disable}
|
||||
maxLength="50"
|
||||
/>
|
||||
<CFormText
|
||||
hidden={!fields.primaryEmail.error}
|
||||
color={fields.primaryEmail.error ? 'danger' : ''}
|
||||
>
|
||||
{t('common.required')}
|
||||
</CFormText>
|
||||
{editing ? (
|
||||
<div>
|
||||
<CInput
|
||||
id="primaryEmail"
|
||||
type="text"
|
||||
required
|
||||
value={fields.primaryEmail.value}
|
||||
onChange={updateField}
|
||||
invalid={fields.primaryEmail.error}
|
||||
disabled={disable}
|
||||
maxLength="50"
|
||||
/>
|
||||
<CFormText
|
||||
hidden={!fields.primaryEmail.error}
|
||||
color={fields.primaryEmail.error ? 'danger' : ''}
|
||||
>
|
||||
{t('common.required')}
|
||||
</CFormText>
|
||||
</div>
|
||||
) : (
|
||||
<p className="mt-2 mb-0">{fields.primaryEmail.value}</p>
|
||||
)}
|
||||
</CCol>
|
||||
<CLabel className="mb-2" sm="2" col htmlFor="secondaryEmail">
|
||||
{t('contact.secondary_email')}
|
||||
</CLabel>
|
||||
<CCol sm="4">
|
||||
<CInput
|
||||
id="secondaryEmail"
|
||||
type="text"
|
||||
required
|
||||
value={fields.secondaryEmail.value}
|
||||
onChange={updateField}
|
||||
disabled={disable}
|
||||
maxLength="50"
|
||||
/>
|
||||
{editing ? (
|
||||
<div>
|
||||
<CInput
|
||||
id="secondaryEmail"
|
||||
type="text"
|
||||
required
|
||||
value={fields.secondaryEmail.value}
|
||||
onChange={updateField}
|
||||
disabled={disable}
|
||||
maxLength="50"
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<p className="mt-2 mb-0">{fields.secondaryEmail.value}</p>
|
||||
)}
|
||||
</CCol>
|
||||
<CLabel className="mb-2" sm="2" col htmlFor="accessPIN">
|
||||
{t('contact.access_pin')}
|
||||
</CLabel>
|
||||
<CCol sm="4">
|
||||
<CInput
|
||||
id="accessPIN"
|
||||
type="text"
|
||||
required
|
||||
value={fields.accessPIN.value}
|
||||
onChange={updateField}
|
||||
disabled={disable}
|
||||
maxLength="50"
|
||||
/>
|
||||
{editing ? (
|
||||
<div>
|
||||
<CInput
|
||||
id="accessPIN"
|
||||
type="text"
|
||||
required
|
||||
value={fields.accessPIN.value}
|
||||
onChange={updateField}
|
||||
disabled={disable}
|
||||
maxLength="50"
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<p className="mt-2 mb-0">{fields.accessPIN.value}</p>
|
||||
)}
|
||||
</CCol>
|
||||
<CLabel sm="2" col htmlFor="description">
|
||||
{t('user.description')}
|
||||
</CLabel>
|
||||
<CCol sm="4">
|
||||
{editing ? (
|
||||
<div>
|
||||
<CInput
|
||||
id="description"
|
||||
type="text"
|
||||
required
|
||||
value={fields.description.value}
|
||||
onChange={updateField}
|
||||
disabled={disable}
|
||||
maxLength="50"
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<p className="mt-2 mb-0">{fields.description.value}</p>
|
||||
)}
|
||||
</CCol>
|
||||
<CLabel className="mb-2" sm="2" col htmlFor="phones">
|
||||
Landlines
|
||||
@@ -274,7 +350,7 @@ const EditContactForm = ({
|
||||
<CreatableSelect
|
||||
isMulti
|
||||
id="phones"
|
||||
isDisabled={disable}
|
||||
isDisabled={disable || !editing}
|
||||
onChange={onPhonesChange}
|
||||
components={{ NoOptionsMessage }}
|
||||
options={[]}
|
||||
@@ -289,7 +365,7 @@ const EditContactForm = ({
|
||||
<CreatableSelect
|
||||
id="mobiles"
|
||||
isMulti
|
||||
isDisabled={disable}
|
||||
isDisabled={disable || !editing}
|
||||
onChange={onMobilesChange}
|
||||
components={{ NoOptionsMessage }}
|
||||
options={[]}
|
||||
@@ -297,20 +373,6 @@ const EditContactForm = ({
|
||||
placeholder={t('common.type_for_options')}
|
||||
/>
|
||||
</CCol>
|
||||
<CLabel sm="2" col htmlFor="description">
|
||||
{t('user.description')}
|
||||
</CLabel>
|
||||
<CCol sm="4">
|
||||
<CInput
|
||||
id="description"
|
||||
type="text"
|
||||
required
|
||||
value={fields.description.value}
|
||||
onChange={updateField}
|
||||
disabled={disable}
|
||||
maxLength="50"
|
||||
/>
|
||||
</CCol>
|
||||
</CRow>
|
||||
<CFormGroup row className="pb-1">
|
||||
<CLabel sm="2" col htmlFor="title">
|
||||
@@ -362,6 +424,7 @@ const EditContactForm = ({
|
||||
color="primary"
|
||||
variant="outline"
|
||||
onClick={() => selectEntity(item)}
|
||||
disabled={!editing}
|
||||
>
|
||||
{t('common.select')}
|
||||
</CButton>
|
||||
@@ -372,7 +435,6 @@ const EditContactForm = ({
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<NotesTable t={t} notes={fields.notes.value} addNote={addNote} loading={disable} editable />
|
||||
</CForm>
|
||||
);
|
||||
};
|
||||
@@ -384,9 +446,9 @@ EditContactForm.propTypes = {
|
||||
updateField: PropTypes.func.isRequired,
|
||||
updateFieldWithKey: PropTypes.func.isRequired,
|
||||
entities: PropTypes.instanceOf(Array).isRequired,
|
||||
addNote: PropTypes.func.isRequired,
|
||||
batchSetField: PropTypes.func.isRequired,
|
||||
hideEntities: PropTypes.bool,
|
||||
editing: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
EditContactForm.defaultProps = {
|
||||
|
||||
@@ -1,18 +1,7 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
CForm,
|
||||
CInput,
|
||||
CLabel,
|
||||
CCol,
|
||||
CFormGroup,
|
||||
CInvalidFeedback,
|
||||
CRow,
|
||||
CButton,
|
||||
CLink,
|
||||
} from '@coreui/react';
|
||||
import { CForm, CInput, CLabel, CCol, CInvalidFeedback, CRow, CButton, CLink } from '@coreui/react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Select from 'react-select';
|
||||
import NotesTable from '../NotesTable';
|
||||
import FormattedDate from '../FormattedDate';
|
||||
import selectStyles from '../../utils/selectStyles';
|
||||
|
||||
@@ -22,7 +11,6 @@ const EditEntityForm = ({
|
||||
fields,
|
||||
updateField,
|
||||
updateFieldDirectly,
|
||||
addNote,
|
||||
editing,
|
||||
toggleAssociate,
|
||||
toggleContact,
|
||||
@@ -30,209 +18,184 @@ const EditEntityForm = ({
|
||||
toggleLocation,
|
||||
}) => (
|
||||
<CForm>
|
||||
<CFormGroup row>
|
||||
<CCol>
|
||||
<CRow className="pb-0">
|
||||
<CLabel lg="5" xl="3" col htmlFor="name">
|
||||
<div>{t('user.name')}:</div>
|
||||
<CRow>
|
||||
<CLabel className="mb-2" md="5" lg="2" xl="2" xxl="1" col htmlFor="name">
|
||||
<div>{t('user.name')}:</div>
|
||||
</CLabel>
|
||||
<CCol md="7" lg="4" xl="4" xxl="5">
|
||||
{editing ? (
|
||||
<div>
|
||||
<CInput
|
||||
id="name"
|
||||
type="text"
|
||||
required
|
||||
value={fields.name.value}
|
||||
onChange={updateField}
|
||||
invalid={fields.name.error}
|
||||
disabled={disable}
|
||||
maxLength="50"
|
||||
/>
|
||||
<CInvalidFeedback>{t('common.required')}</CInvalidFeedback>
|
||||
</div>
|
||||
) : (
|
||||
<p className="mt-2 mb-0">{fields.name.value}</p>
|
||||
)}
|
||||
</CCol>
|
||||
<CLabel className="mb-2" md="5" lg="2" xl="2" xxl="1" col htmlFor="name">
|
||||
<div>{t('user.description')}:</div>
|
||||
</CLabel>
|
||||
<CCol md="7" lg="4" xl="4" xxl="5">
|
||||
{editing ? (
|
||||
<div>
|
||||
<CInput
|
||||
id="description"
|
||||
type="text"
|
||||
required
|
||||
value={fields.description.value}
|
||||
onChange={updateField}
|
||||
disabled={disable}
|
||||
maxLength="50"
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<p className="mt-2 mb-0">{fields.description.value}</p>
|
||||
)}
|
||||
</CCol>
|
||||
<CLabel className="mb-2" md="5" lg="2" xl="2" xxl="1" col htmlFor="name">
|
||||
<div>RRM:</div>
|
||||
</CLabel>
|
||||
<CCol md="7" lg="4" xl="4" xxl="5">
|
||||
<div style={{ width: '120px' }}>
|
||||
<Select
|
||||
id="rrm"
|
||||
styles={selectStyles}
|
||||
value={{ value: fields.rrm.value, label: fields.rrm.value }}
|
||||
onChange={(v) => updateFieldDirectly('rrm', { value: v.value })}
|
||||
options={[
|
||||
{ label: 'on', value: 'on' },
|
||||
{ label: 'off', value: 'off' },
|
||||
{ label: 'inherit', value: 'inherit' },
|
||||
]}
|
||||
isDisabled={!editing}
|
||||
/>
|
||||
</div>
|
||||
</CCol>
|
||||
<CLabel className="mb-2" md="5" lg="2" xl="2" xxl="1" col htmlFor="sourceIp">
|
||||
<div>{t('entity.ip_detection')}:</div>
|
||||
</CLabel>
|
||||
<CCol md="7" lg="4" xl="4" xxl="5">
|
||||
{editing ? (
|
||||
<CButton className="pl-0 text-left" color="link" onClick={toggleIpModal}>
|
||||
{fields.sourceIP.value.length === 0
|
||||
? t('entity.add_ips')
|
||||
: fields.sourceIP.value.join(', ')}
|
||||
</CButton>
|
||||
) : (
|
||||
<div className="mt-2 mb-0">
|
||||
<p className="mb-0">
|
||||
{fields.sourceIP.value.length === 0
|
||||
? t('entity.no_ips')
|
||||
: fields.sourceIP.value.join(', ')}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</CCol>
|
||||
<CLabel className="mb-2" md="5" lg="2" xl="2" xxl="1" col htmlFor="name">
|
||||
<div>{t('common.created')}:</div>
|
||||
</CLabel>
|
||||
<CCol md="7" lg="4" xl="4" xxl="5">
|
||||
<div className="mt-2 mb-0">
|
||||
<FormattedDate date={fields.created.value} />
|
||||
</div>
|
||||
</CCol>
|
||||
<CLabel className="mb-2" md="5" lg="2" xl="2" xxl="1" col htmlFor="name">
|
||||
<div>{t('common.modified')}:</div>
|
||||
</CLabel>
|
||||
<CCol md="7" lg="4" xl="4" xxl="5">
|
||||
<div className="mt-2 mb-0">
|
||||
<FormattedDate date={fields.modified.value} />
|
||||
</div>
|
||||
</CCol>
|
||||
{fields.contact ? (
|
||||
<>
|
||||
<CLabel className="mb-2" md="5" lg="2" xl="2" xxl="1" col htmlFor="name">
|
||||
<div>{t('contact.title')}:</div>
|
||||
</CLabel>
|
||||
<CCol lg="7" xxl="9">
|
||||
<CCol md="7" lg="4" xl="4" xxl="5">
|
||||
{editing ? (
|
||||
<div>
|
||||
<CInput
|
||||
id="name"
|
||||
type="text"
|
||||
required
|
||||
value={fields.name.value}
|
||||
onChange={updateField}
|
||||
invalid={fields.name.error}
|
||||
disabled={disable}
|
||||
maxLength="50"
|
||||
/>
|
||||
<CInvalidFeedback>{t('common.required')}</CInvalidFeedback>
|
||||
</div>
|
||||
) : (
|
||||
<p className="mt-2 mb-0">{fields.name.value}</p>
|
||||
)}
|
||||
</CCol>
|
||||
</CRow>
|
||||
<CRow className="pb-0">
|
||||
<CLabel lg="5" xl="3" col htmlFor="name">
|
||||
<div>{t('user.description')}:</div>
|
||||
</CLabel>
|
||||
<CCol lg="7" xxl="9">
|
||||
{editing ? (
|
||||
<div>
|
||||
<CInput
|
||||
id="description"
|
||||
type="text"
|
||||
required
|
||||
value={fields.description.value}
|
||||
onChange={updateField}
|
||||
disabled={disable}
|
||||
maxLength="50"
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<p className="mt-2 mb-0">{fields.description.value}</p>
|
||||
)}
|
||||
</CCol>
|
||||
</CRow>
|
||||
<CRow className="pb-0">
|
||||
<CLabel lg="5" xl="3" col htmlFor="name">
|
||||
<div>RRM:</div>
|
||||
</CLabel>
|
||||
<CCol lg="7" xxl="9">
|
||||
<div style={{ width: '120px' }}>
|
||||
<Select
|
||||
id="rrm"
|
||||
styles={selectStyles}
|
||||
value={{ value: fields.rrm.value, label: fields.rrm.value }}
|
||||
onChange={(v) => updateFieldDirectly('rrm', { value: v.value })}
|
||||
options={[
|
||||
{ label: 'on', value: 'on' },
|
||||
{ label: 'off', value: 'off' },
|
||||
{ label: 'inherit', value: 'inherit' },
|
||||
]}
|
||||
isDisabled={!editing}
|
||||
/>
|
||||
</div>
|
||||
</CCol>
|
||||
</CRow>
|
||||
<CRow className="pb-0">
|
||||
<CLabel lg="5" xl="3" col htmlFor="name">
|
||||
<div>{t('configuration.title')}:</div>
|
||||
</CLabel>
|
||||
<CCol lg="7" xxl="9">
|
||||
{editing ? (
|
||||
<CButton className="pl-0 text-left" color="link" onClick={toggleAssociate}>
|
||||
{fields.deviceConfiguration.value.length === 0
|
||||
? t('configuration.add_configuration')
|
||||
: fields.deviceConfiguration.value.map((c) => c.name).join(', ')}
|
||||
<CButton className="pl-0 text-left" color="link" onClick={toggleContact}>
|
||||
{fields.contact.value === '' ? t('contact.add_contact') : fields.contact.value}
|
||||
</CButton>
|
||||
) : (
|
||||
<div className="mt-2 mb-0">
|
||||
{fields.deviceConfiguration.value.length === 0 ? (
|
||||
<p className="mb-0">{t('configuration.no_associated_config')}</p>
|
||||
{fields.contact.uuid === '' ? (
|
||||
<p className="mb-0">{t('contact.no_associated_contact')}</p>
|
||||
) : (
|
||||
<p className="mb-0">
|
||||
{' '}
|
||||
{fields.deviceConfiguration.value.map((c) => c.name).join(', ')}
|
||||
</p>
|
||||
<CLink
|
||||
className="c-subheader-nav-link"
|
||||
aria-current="page"
|
||||
to={() => `/contacts`}
|
||||
>
|
||||
{fields.contact.value}
|
||||
</CLink>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</CCol>
|
||||
</CRow>
|
||||
{fields.contact ? (
|
||||
<CRow className="pb-0">
|
||||
<CLabel lg="5" xl="3" col htmlFor="name">
|
||||
<div>{t('contact.title')}:</div>
|
||||
</CLabel>
|
||||
<CCol lg="7" xxl="9">
|
||||
{editing ? (
|
||||
<CButton className="pl-0 text-left" color="link" onClick={toggleContact}>
|
||||
{fields.contact.value === '' ? t('contact.add_contact') : fields.contact.value}
|
||||
</CButton>
|
||||
) : (
|
||||
<div className="mt-2 mb-0">
|
||||
{fields.contact.uuid === '' ? (
|
||||
<p className="mb-0">{t('contact.no_associated_contact')}</p>
|
||||
) : (
|
||||
<CLink
|
||||
className="c-subheader-nav-link"
|
||||
aria-current="page"
|
||||
to={() => `/contacts`}
|
||||
>
|
||||
{fields.contact.value}
|
||||
</CLink>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</CCol>
|
||||
</CRow>
|
||||
) : null}
|
||||
{fields.location ? (
|
||||
<CRow className="pb-0">
|
||||
<CLabel lg="5" xl="3" col htmlFor="name">
|
||||
<div>{t('location.title')}:</div>
|
||||
</CLabel>
|
||||
<CCol lg="7" xxl="9">
|
||||
{editing ? (
|
||||
<CButton className="pl-0 text-left" color="link" onClick={toggleLocation}>
|
||||
{fields.location.value === '' ? t('location.add') : fields.location.value}
|
||||
</CButton>
|
||||
) : (
|
||||
<div className="mt-2 mb-0">
|
||||
{fields.location.uuid === '' ? (
|
||||
<p className="mb-0">{t('location.no_associated')}</p>
|
||||
) : (
|
||||
<CLink
|
||||
className="c-subheader-nav-link"
|
||||
aria-current="page"
|
||||
to={() => `/location`}
|
||||
>
|
||||
{fields.location.value}
|
||||
</CLink>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</CCol>
|
||||
</CRow>
|
||||
) : null}
|
||||
<CRow className="pb-0">
|
||||
<CLabel lg="5" xl="3" col htmlFor="sourceIp">
|
||||
<div>{t('entity.ip_detection')}:</div>
|
||||
</>
|
||||
) : null}
|
||||
{fields.location ? (
|
||||
<>
|
||||
<CLabel className="mb-2" md="5" lg="2" xl="2" xxl="1" col htmlFor="name">
|
||||
<div>{t('location.title')}:</div>
|
||||
</CLabel>
|
||||
<CCol lg="7" xxl="9">
|
||||
<CCol md="7" lg="4" xl="4" xxl="5">
|
||||
{editing ? (
|
||||
<CButton className="pl-0 text-left" color="link" onClick={toggleIpModal}>
|
||||
{fields.sourceIP.value.length === 0
|
||||
? t('entity.add_ips')
|
||||
: fields.sourceIP.value.join(', ')}
|
||||
<CButton className="pl-0 text-left" color="link" onClick={toggleLocation}>
|
||||
{fields.location.value === '' ? t('location.add') : fields.location.value}
|
||||
</CButton>
|
||||
) : (
|
||||
<div className="mt-2 mb-0">
|
||||
<p className="mb-0">
|
||||
{fields.sourceIP.value.length === 0
|
||||
? t('entity.no_ips')
|
||||
: fields.sourceIP.value.join(', ')}
|
||||
</p>
|
||||
{fields.location.uuid === '' ? (
|
||||
<p className="mb-0">{t('location.no_associated')}</p>
|
||||
) : (
|
||||
<CLink
|
||||
className="c-subheader-nav-link"
|
||||
aria-current="page"
|
||||
to={() => `/location`}
|
||||
>
|
||||
{fields.location.value}
|
||||
</CLink>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</CCol>
|
||||
</CRow>
|
||||
<CRow className="pb-0">
|
||||
<CLabel lg="5" xl="3" col htmlFor="name">
|
||||
<div>{t('common.created')}:</div>
|
||||
</CLabel>
|
||||
<CCol lg="7" xxl="9">
|
||||
<div className="mt-2 mb-0">
|
||||
<FormattedDate date={fields.created.value} />
|
||||
</div>
|
||||
</CCol>
|
||||
</CRow>
|
||||
</>
|
||||
) : null}
|
||||
<CLabel className="mb-2" sm="2" col htmlFor="name">
|
||||
<div>{t('configuration.configurations')}:</div>
|
||||
</CLabel>
|
||||
<CCol sm="10">
|
||||
{editing ? (
|
||||
<CButton className="pl-0 text-left" color="link" onClick={toggleAssociate}>
|
||||
{fields.deviceConfiguration.value.length === 0
|
||||
? t('configuration.add_configuration')
|
||||
: fields.deviceConfiguration.value.map((c) => c.name).join(', ')}
|
||||
</CButton>
|
||||
) : (
|
||||
<div className="mt-2 mb-0">
|
||||
{fields.deviceConfiguration.value.length === 0 ? (
|
||||
<p className="mb-0">{t('configuration.no_associated_config')}</p>
|
||||
) : (
|
||||
<p className="mb-0">
|
||||
{' '}
|
||||
{fields.deviceConfiguration.value.map((c) => c.name).join(', ')}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</CCol>
|
||||
<CCol className="mt-1">
|
||||
<CRow className="pb-0">
|
||||
<CLabel lg="5" xl="3" col htmlFor="name">
|
||||
<div>{t('common.modified')}:</div>
|
||||
</CLabel>
|
||||
<CCol lg="7" xxl="9">
|
||||
<div className="mt-2 mb-0">
|
||||
<FormattedDate date={fields.modified.value} />
|
||||
</div>
|
||||
</CCol>
|
||||
</CRow>
|
||||
<NotesTable
|
||||
t={t}
|
||||
notes={fields.notes.value}
|
||||
addNote={addNote}
|
||||
loading={disable}
|
||||
editable={editing}
|
||||
/>
|
||||
</CCol>
|
||||
</CFormGroup>
|
||||
</CRow>
|
||||
</CForm>
|
||||
);
|
||||
|
||||
@@ -242,7 +205,6 @@ EditEntityForm.propTypes = {
|
||||
fields: PropTypes.instanceOf(Object).isRequired,
|
||||
updateField: PropTypes.func.isRequired,
|
||||
updateFieldDirectly: PropTypes.func.isRequired,
|
||||
addNote: PropTypes.func.isRequired,
|
||||
editing: PropTypes.bool.isRequired,
|
||||
toggleAssociate: PropTypes.func.isRequired,
|
||||
toggleContact: PropTypes.func,
|
||||
|
||||
@@ -2,7 +2,6 @@ import React from 'react';
|
||||
import { CForm, CInput, CLabel, CCol, CFormGroup, CFormText, CRow } from '@coreui/react';
|
||||
import Select from 'react-select';
|
||||
import PropTypes from 'prop-types';
|
||||
import NotesTable from '../NotesTable';
|
||||
import RequiredAsterisk from '../RequiredAsterisk';
|
||||
import selectStyles from '../../utils/selectStyles';
|
||||
|
||||
@@ -12,8 +11,8 @@ const EditInventoryTagForm = ({
|
||||
fields,
|
||||
updateField,
|
||||
updateFieldDirectly,
|
||||
addNote,
|
||||
deviceTypes,
|
||||
editing,
|
||||
}) => (
|
||||
<CForm>
|
||||
<CFormGroup row className="mb-1">
|
||||
@@ -28,19 +27,25 @@ const EditInventoryTagForm = ({
|
||||
<RequiredAsterisk />
|
||||
</CLabel>
|
||||
<CCol sm="8">
|
||||
<CInput
|
||||
id="name"
|
||||
type="text"
|
||||
required
|
||||
value={fields.name.value}
|
||||
onChange={updateField}
|
||||
invalid={fields.name.error}
|
||||
disabled={disable}
|
||||
maxLength="50"
|
||||
/>
|
||||
<CFormText hidden={!fields.name.error} color={fields.name.error ? 'danger' : ''}>
|
||||
{t('common.required')}
|
||||
</CFormText>
|
||||
{editing ? (
|
||||
<div>
|
||||
<CInput
|
||||
id="name"
|
||||
type="text"
|
||||
required
|
||||
value={fields.name.value}
|
||||
onChange={updateField}
|
||||
invalid={fields.name.error}
|
||||
disabled={disable}
|
||||
maxLength="50"
|
||||
/>
|
||||
<CFormText hidden={!fields.name.error} color={fields.name.error ? 'danger' : ''}>
|
||||
{t('common.required')}
|
||||
</CFormText>
|
||||
</div>
|
||||
) : (
|
||||
<p className="mt-2 mb-0">{fields.name.value}</p>
|
||||
)}
|
||||
</CCol>
|
||||
</CFormGroup>
|
||||
<CFormGroup row className="mb-1">
|
||||
@@ -48,15 +53,21 @@ const EditInventoryTagForm = ({
|
||||
{t('user.description')}
|
||||
</CLabel>
|
||||
<CCol sm="8">
|
||||
<CInput
|
||||
id="description"
|
||||
type="text"
|
||||
required
|
||||
value={fields.description.value}
|
||||
onChange={updateField}
|
||||
disabled={disable}
|
||||
maxLength="50"
|
||||
/>
|
||||
{editing ? (
|
||||
<div>
|
||||
<CInput
|
||||
id="description"
|
||||
type="text"
|
||||
required
|
||||
value={fields.description.value}
|
||||
onChange={updateField}
|
||||
disabled={disable}
|
||||
maxLength="50"
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<p className="mt-2 mb-0">{fields.description.value}</p>
|
||||
)}
|
||||
</CCol>
|
||||
</CFormGroup>
|
||||
<CFormGroup row className="mb-1">
|
||||
@@ -72,7 +83,7 @@ const EditInventoryTagForm = ({
|
||||
value={{ value: fields.deviceType.value, label: fields.deviceType.value }}
|
||||
onChange={(v) => updateFieldDirectly('deviceType', { value: v.value })}
|
||||
options={deviceTypes.map((v) => ({ value: v, label: v }))}
|
||||
isDisabled={disable}
|
||||
isDisabled={disable || !editing}
|
||||
/>
|
||||
</div>
|
||||
<CFormText
|
||||
@@ -100,7 +111,7 @@ const EditInventoryTagForm = ({
|
||||
{ label: 'off', value: 'off' },
|
||||
{ label: 'inherit', value: 'inherit' },
|
||||
]}
|
||||
isDisabled={disable}
|
||||
isDisabled={disable || !editing}
|
||||
/>
|
||||
</div>
|
||||
<CFormText hidden={!fields.rrm.error} color={fields.rrm.error ? 'danger' : ''}>
|
||||
@@ -108,11 +119,6 @@ const EditInventoryTagForm = ({
|
||||
</CFormText>
|
||||
</CCol>
|
||||
</CRow>
|
||||
<CRow>
|
||||
<CCol>
|
||||
<NotesTable t={t} notes={fields.notes.value} addNote={addNote} loading={disable} />
|
||||
</CCol>
|
||||
</CRow>
|
||||
</CForm>
|
||||
);
|
||||
|
||||
@@ -123,7 +129,7 @@ EditInventoryTagForm.propTypes = {
|
||||
updateField: PropTypes.func.isRequired,
|
||||
updateFieldDirectly: PropTypes.func.isRequired,
|
||||
deviceTypes: PropTypes.instanceOf(Array).isRequired,
|
||||
addNote: PropTypes.func.isRequired,
|
||||
editing: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
export default EditInventoryTagForm;
|
||||
|
||||
@@ -17,7 +17,6 @@ import {
|
||||
} from '@coreui/react';
|
||||
import countryList from 'utils/countryList';
|
||||
import FormattedDate from '../FormattedDate';
|
||||
import NotesTable from '../NotesTable';
|
||||
import RequiredAsterisk from '../RequiredAsterisk';
|
||||
|
||||
const EditLocationForm = ({
|
||||
@@ -27,9 +26,9 @@ const EditLocationForm = ({
|
||||
updateField,
|
||||
updateFieldWithKey,
|
||||
entities,
|
||||
addNote,
|
||||
locationSearch,
|
||||
batchSetField,
|
||||
editing,
|
||||
}) => {
|
||||
const [filter, setFilter] = useState('');
|
||||
|
||||
@@ -63,33 +62,45 @@ const EditLocationForm = ({
|
||||
<RequiredAsterisk />
|
||||
</CLabel>
|
||||
<CCol sm="4">
|
||||
<CInput
|
||||
id="name"
|
||||
type="text"
|
||||
required
|
||||
value={fields.name.value}
|
||||
onChange={updateField}
|
||||
invalid={fields.name.error}
|
||||
disabled={disable}
|
||||
maxLength="50"
|
||||
/>
|
||||
<CFormText hidden={!fields.name.error} color={fields.name.error ? 'danger' : ''}>
|
||||
{t('common.required')}
|
||||
</CFormText>
|
||||
{editing ? (
|
||||
<div>
|
||||
<CInput
|
||||
id="name"
|
||||
type="text"
|
||||
required
|
||||
value={fields.name.value}
|
||||
onChange={updateField}
|
||||
invalid={fields.name.error}
|
||||
disabled={disable}
|
||||
maxLength="50"
|
||||
/>
|
||||
<CFormText hidden={!fields.name.error} color={fields.name.error ? 'danger' : ''}>
|
||||
{t('common.required')}
|
||||
</CFormText>
|
||||
</div>
|
||||
) : (
|
||||
<p className="mt-2 mb-0">{fields.name.value}</p>
|
||||
)}
|
||||
</CCol>
|
||||
<CLabel sm="2" col htmlFor="description">
|
||||
{t('user.description')}
|
||||
</CLabel>
|
||||
<CCol sm="4">
|
||||
<CInput
|
||||
id="description"
|
||||
type="text"
|
||||
required
|
||||
value={fields.description.value}
|
||||
onChange={updateField}
|
||||
disabled={disable}
|
||||
maxLength="50"
|
||||
/>
|
||||
{editing ? (
|
||||
<div>
|
||||
<CInput
|
||||
id="description"
|
||||
type="text"
|
||||
required
|
||||
value={fields.description.value}
|
||||
onChange={updateField}
|
||||
disabled={disable}
|
||||
maxLength="50"
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<p className="mt-2 mb-0">{fields.description.value}</p>
|
||||
)}
|
||||
</CCol>
|
||||
<CLabel className="mb-2" sm="2" col htmlFor="type">
|
||||
{t('contact.type')}
|
||||
@@ -114,7 +125,7 @@ const EditLocationForm = ({
|
||||
{ label: 'UNKNOWN', value: 'UNKNOWN' },
|
||||
{ label: 'CORPORATE', value: 'CORPORATE' },
|
||||
]}
|
||||
isDisabled={disable}
|
||||
isDisabled={disable || !editing}
|
||||
/>
|
||||
</div>
|
||||
<CFormText hidden={!fields.type.error} color={fields.type.error ? 'danger' : ''}>
|
||||
@@ -125,15 +136,21 @@ const EditLocationForm = ({
|
||||
{t('location.building_name')}
|
||||
</CLabel>
|
||||
<CCol sm="4">
|
||||
<CInput
|
||||
id="buildingName"
|
||||
type="text"
|
||||
required
|
||||
value={fields.buildingName.value}
|
||||
onChange={updateField}
|
||||
disabled={disable}
|
||||
maxLength="50"
|
||||
/>
|
||||
{editing ? (
|
||||
<div>
|
||||
<CInput
|
||||
id="buildingName"
|
||||
type="text"
|
||||
required
|
||||
value={fields.buildingName.value}
|
||||
onChange={updateField}
|
||||
disabled={disable}
|
||||
maxLength="50"
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<p className="mt-2 mb-0">{fields.buildingName.value}</p>
|
||||
)}
|
||||
</CCol>
|
||||
<CLabel className="mb-3" sm="2" col htmlFor="phones">
|
||||
Landlines
|
||||
@@ -142,7 +159,7 @@ const EditLocationForm = ({
|
||||
<CreatableSelect
|
||||
isMulti
|
||||
id="phones"
|
||||
isDisabled={disable}
|
||||
isDisabled={disable || !editing}
|
||||
onChange={onPhonesChange}
|
||||
components={{ NoOptionsMessage }}
|
||||
options={[]}
|
||||
@@ -157,7 +174,7 @@ const EditLocationForm = ({
|
||||
<CreatableSelect
|
||||
id="mobiles"
|
||||
isMulti
|
||||
isDisabled={disable}
|
||||
isDisabled={disable || !editing}
|
||||
onChange={onMobilesChange}
|
||||
components={{ NoOptionsMessage }}
|
||||
options={[]}
|
||||
@@ -175,24 +192,30 @@ const EditLocationForm = ({
|
||||
<RequiredAsterisk />
|
||||
</CLabel>
|
||||
<CCol sm="4">
|
||||
<CInput
|
||||
id="addressLines"
|
||||
type="text"
|
||||
required
|
||||
value={fields.addressLines.value[0]}
|
||||
onChange={(e) =>
|
||||
updateFieldWithKey('addressLines', { value: [e.target.value], error: false })
|
||||
}
|
||||
disabled={disable}
|
||||
invalid={fields.addressLines.error}
|
||||
maxLength="50"
|
||||
/>
|
||||
<CFormText
|
||||
hidden={!fields.addressLines.error}
|
||||
color={fields.addressLines.error ? 'danger' : ''}
|
||||
>
|
||||
{t('common.required')}
|
||||
</CFormText>
|
||||
{editing ? (
|
||||
<div>
|
||||
<CInput
|
||||
id="addressLines"
|
||||
type="text"
|
||||
required
|
||||
value={fields.addressLines.value[0]}
|
||||
onChange={(e) =>
|
||||
updateFieldWithKey('addressLines', { value: [e.target.value], error: false })
|
||||
}
|
||||
disabled={disable}
|
||||
invalid={fields.addressLines.error}
|
||||
maxLength="50"
|
||||
/>
|
||||
<CFormText
|
||||
hidden={!fields.addressLines.error}
|
||||
color={fields.addressLines.error ? 'danger' : ''}
|
||||
>
|
||||
{t('common.required')}
|
||||
</CFormText>
|
||||
</div>
|
||||
) : (
|
||||
<p className="mt-2 mb-0">{fields.addressLines.value[0]}</p>
|
||||
)}
|
||||
</CCol>
|
||||
<CLabel className="mb-2" sm="2" col htmlFor="country">
|
||||
{t('location.country')}
|
||||
@@ -211,7 +234,7 @@ const EditLocationForm = ({
|
||||
}}
|
||||
onChange={(v) => updateFieldWithKey('country', { value: v.value })}
|
||||
options={countryList}
|
||||
isDisabled={disable}
|
||||
isDisabled={disable || !editing}
|
||||
/>
|
||||
<CFormText hidden={!fields.country.error} color={fields.country.error ? 'danger' : ''}>
|
||||
{t('common.required')}
|
||||
@@ -223,71 +246,95 @@ const EditLocationForm = ({
|
||||
<RequiredAsterisk />
|
||||
</CLabel>
|
||||
<CCol sm="4">
|
||||
<CInput
|
||||
id="city"
|
||||
type="text"
|
||||
required
|
||||
value={fields.city.value}
|
||||
onChange={updateField}
|
||||
invalid={fields.city.error}
|
||||
disabled={disable}
|
||||
maxLength="50"
|
||||
/>
|
||||
<CFormText hidden={!fields.city.error} color={fields.city.error ? 'danger' : ''}>
|
||||
{t('common.required')}
|
||||
</CFormText>
|
||||
{editing ? (
|
||||
<div>
|
||||
<CInput
|
||||
id="city"
|
||||
type="text"
|
||||
required
|
||||
value={fields.city.value}
|
||||
onChange={updateField}
|
||||
invalid={fields.city.error}
|
||||
disabled={disable}
|
||||
maxLength="50"
|
||||
/>
|
||||
<CFormText hidden={!fields.city.error} color={fields.city.error ? 'danger' : ''}>
|
||||
{t('common.required')}
|
||||
</CFormText>
|
||||
</div>
|
||||
) : (
|
||||
<p className="mt-2 mb-0">{fields.city.value}</p>
|
||||
)}
|
||||
</CCol>
|
||||
<CLabel className="mb-2" sm="2" col htmlFor="state">
|
||||
{t('location.state')}
|
||||
<RequiredAsterisk />
|
||||
</CLabel>
|
||||
<CCol sm="4">
|
||||
<CInput
|
||||
id="state"
|
||||
type="text"
|
||||
required
|
||||
value={fields.state.value}
|
||||
onChange={updateField}
|
||||
invalid={fields.state.error}
|
||||
disabled={disable}
|
||||
maxLength="50"
|
||||
/>
|
||||
<CFormText hidden={!fields.state.error} color={fields.state.error ? 'danger' : ''}>
|
||||
{t('common.required')}
|
||||
</CFormText>
|
||||
{editing ? (
|
||||
<div>
|
||||
<CInput
|
||||
id="state"
|
||||
type="text"
|
||||
required
|
||||
value={fields.state.value}
|
||||
onChange={updateField}
|
||||
invalid={fields.state.error}
|
||||
disabled={disable}
|
||||
maxLength="50"
|
||||
/>
|
||||
<CFormText hidden={!fields.state.error} color={fields.state.error ? 'danger' : ''}>
|
||||
{t('common.required')}
|
||||
</CFormText>
|
||||
</div>
|
||||
) : (
|
||||
<p className="mt-2 mb-0">{fields.state.value}</p>
|
||||
)}
|
||||
</CCol>
|
||||
<CLabel className="mb-2" sm="2" col htmlFor="postal">
|
||||
{t('location.postal')}
|
||||
<RequiredAsterisk />
|
||||
</CLabel>
|
||||
<CCol sm="4">
|
||||
<CInput
|
||||
id="postal"
|
||||
type="text"
|
||||
required
|
||||
value={fields.postal.value}
|
||||
onChange={updateField}
|
||||
invalid={fields.postal.error}
|
||||
disabled={disable}
|
||||
maxLength="50"
|
||||
/>
|
||||
<CFormText hidden={!fields.postal.error} color={fields.postal.error ? 'danger' : ''}>
|
||||
{t('common.required')}
|
||||
</CFormText>
|
||||
{editing ? (
|
||||
<div>
|
||||
<CInput
|
||||
id="postal"
|
||||
type="text"
|
||||
required
|
||||
value={fields.postal.value}
|
||||
onChange={updateField}
|
||||
invalid={fields.postal.error}
|
||||
disabled={disable}
|
||||
maxLength="50"
|
||||
/>
|
||||
<CFormText hidden={!fields.postal.error} color={fields.postal.error ? 'danger' : ''}>
|
||||
{t('common.required')}
|
||||
</CFormText>
|
||||
</div>
|
||||
) : (
|
||||
<p className="mt-2 mb-0">{fields.postal.value}</p>
|
||||
)}
|
||||
</CCol>
|
||||
<CLabel sm="2" col htmlFor="geoCode">
|
||||
{t('location.geocode')}
|
||||
</CLabel>
|
||||
<CCol sm="4">
|
||||
<CInput
|
||||
id="geoCode"
|
||||
type="text"
|
||||
required
|
||||
value={fields.geoCode.value}
|
||||
onChange={updateField}
|
||||
disabled={disable}
|
||||
maxLength="50"
|
||||
/>
|
||||
{editing ? (
|
||||
<div>
|
||||
<CInput
|
||||
id="geoCode"
|
||||
type="text"
|
||||
required
|
||||
value={fields.geoCode.value}
|
||||
onChange={updateField}
|
||||
disabled={disable}
|
||||
maxLength="50"
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<p className="mt-2 mb-0">{fields.geoCode.value}</p>
|
||||
)}
|
||||
</CCol>
|
||||
</CRow>
|
||||
<CFormGroup row className="pt-2 pb-1">
|
||||
@@ -335,6 +382,7 @@ const EditLocationForm = ({
|
||||
<td className="align-middle p-1">
|
||||
<CPopover content={t('entity.select_entity')}>
|
||||
<CButton
|
||||
disabled={!editing}
|
||||
size="sm"
|
||||
color="primary"
|
||||
variant="outline"
|
||||
@@ -348,7 +396,6 @@ const EditLocationForm = ({
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<NotesTable t={t} notes={fields.notes.value} addNote={addNote} loading={disable} editable />
|
||||
</CForm>
|
||||
);
|
||||
};
|
||||
@@ -360,9 +407,9 @@ EditLocationForm.propTypes = {
|
||||
updateField: PropTypes.func.isRequired,
|
||||
updateFieldWithKey: PropTypes.func.isRequired,
|
||||
entities: PropTypes.instanceOf(Array).isRequired,
|
||||
addNote: PropTypes.func.isRequired,
|
||||
locationSearch: PropTypes.node.isRequired,
|
||||
batchSetField: PropTypes.func.isRequired,
|
||||
editing: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
export default EditLocationForm;
|
||||
|
||||
@@ -3,7 +3,6 @@ import {
|
||||
CButton,
|
||||
CCol,
|
||||
CForm,
|
||||
CFormGroup,
|
||||
CInput,
|
||||
CInputGroup,
|
||||
CInputGroupAppend,
|
||||
@@ -19,8 +18,6 @@ import PropTypes from 'prop-types';
|
||||
import parsePhoneNumber from 'libphonenumber-js';
|
||||
import CIcon from '@coreui/icons-react';
|
||||
import ValidatePhoneNumberModal from 'components/ValidatePhoneNumberModal';
|
||||
import NotesTable from '../NotesTable';
|
||||
import LoadingButton from '../LoadingButton';
|
||||
import Avatar from '../Avatar';
|
||||
import useToggle from '../../hooks/useToggle';
|
||||
|
||||
@@ -31,7 +28,6 @@ const EditMyProfile = ({
|
||||
updateWithKey,
|
||||
loading,
|
||||
policies,
|
||||
addNote,
|
||||
avatar,
|
||||
newAvatar,
|
||||
deleteAvatar,
|
||||
@@ -40,6 +36,7 @@ const EditMyProfile = ({
|
||||
sendPhoneNumberTest,
|
||||
testVerificationCode,
|
||||
editing,
|
||||
avatarDeleted,
|
||||
}) => {
|
||||
const [showPhoneModal, togglePhoneModal] = useToggle(false);
|
||||
const [showPassword, setShowPassword] = useState(false);
|
||||
@@ -70,175 +67,174 @@ const EditMyProfile = ({
|
||||
|
||||
return (
|
||||
<CForm>
|
||||
<CFormGroup row>
|
||||
<CLabel lg="2" xxl="1" col htmlFor="name">
|
||||
{t('user.name')}
|
||||
</CLabel>
|
||||
<CCol lg="4" xxl="5">
|
||||
{editing ? (
|
||||
<CInput id="name" value={user.name.value} onChange={updateUserWithId} maxLength="20" />
|
||||
) : (
|
||||
<p className="mt-2 mb-0">{user.name.value}</p>
|
||||
)}
|
||||
</CCol>
|
||||
<CLabel lg="2" xxl="1" col htmlFor="description">
|
||||
{t('user.description')}
|
||||
</CLabel>
|
||||
<CCol lg="4" xxl="5">
|
||||
{editing ? (
|
||||
<CInput
|
||||
id="description"
|
||||
value={user.description.value}
|
||||
onChange={updateUserWithId}
|
||||
maxLength="50"
|
||||
<CRow>
|
||||
<CCol md="3" xl="2">
|
||||
<Avatar
|
||||
src={(avatar !== newAvatar && newAvatar !== '') || avatarDeleted ? newAvatar : avatar}
|
||||
fallback={user.email.value}
|
||||
size="lg"
|
||||
/>
|
||||
<CRow className="my-2">
|
||||
<CCol>
|
||||
<CButton
|
||||
className="ml-2"
|
||||
color="primary"
|
||||
disabled={
|
||||
!editing || loading || !avatar || avatar === '' || avatar === 'data:;base64,'
|
||||
}
|
||||
onClick={deleteAvatar}
|
||||
>
|
||||
{t('user.delete_avatar')}
|
||||
</CButton>
|
||||
</CCol>
|
||||
</CRow>
|
||||
<CRow className="ml-2">
|
||||
<CInputFile
|
||||
disabled={!editing}
|
||||
id="file-input"
|
||||
name="file-input"
|
||||
accept="image/*"
|
||||
onChange={showPreview}
|
||||
key={fileInputKey}
|
||||
/>
|
||||
) : (
|
||||
<p className="mt-2 mb-0">{user.description.value}</p>
|
||||
)}
|
||||
</CRow>
|
||||
</CCol>
|
||||
</CFormGroup>
|
||||
<CFormGroup row>
|
||||
<CLabel lg="2" xxl="1" col htmlFor="mfaMethod">
|
||||
MFA
|
||||
</CLabel>
|
||||
<CCol lg="4" xxl="5">
|
||||
<CSelect
|
||||
disabled={!editing}
|
||||
custom
|
||||
id="mfaMethod"
|
||||
onChange={updateUserWithId}
|
||||
value={user.mfaMethod.value}
|
||||
style={{ width: '100px' }}
|
||||
>
|
||||
<option value="">Off</option>
|
||||
<option value="sms">SMS</option>
|
||||
<option value="email">Email</option>
|
||||
</CSelect>
|
||||
</CCol>
|
||||
<CLabel lg="2" xxl="1" col htmlFor="name">
|
||||
{t('user.phone_number')}
|
||||
</CLabel>
|
||||
<CCol lg="4" xxl="5">
|
||||
{editing ? (
|
||||
<CButton color="link" onClick={togglePhoneModal} className="pl-0">
|
||||
{parseNumber()}
|
||||
</CButton>
|
||||
) : (
|
||||
<p className="mt-2 mb-0">{parseNumber()}</p>
|
||||
)}
|
||||
</CCol>
|
||||
</CFormGroup>
|
||||
<CFormGroup row>
|
||||
<CLabel lg="2" xxl="1" col htmlFor="newPassword">
|
||||
{t('login.new_password')}
|
||||
</CLabel>
|
||||
<CCol lg="4" xxl="5">
|
||||
{editing ? (
|
||||
<CInputGroup>
|
||||
<CInput
|
||||
type={showPassword ? 'text' : 'password'}
|
||||
id="newPassword"
|
||||
value={user.newPassword.value}
|
||||
onChange={updateUserWithId}
|
||||
invalid={user.newPassword.error}
|
||||
maxLength="50"
|
||||
/>
|
||||
<CInputGroupAppend>
|
||||
<CPopover content={t('user.show_hide_password')}>
|
||||
<CButton type="button" onClick={toggleShowPassword} color="secondary">
|
||||
<CIcon
|
||||
name={showPassword ? 'cil-envelope-open' : 'cil-envelope-closed'}
|
||||
size="sm"
|
||||
/>
|
||||
</CButton>
|
||||
</CPopover>
|
||||
</CInputGroupAppend>
|
||||
<CInvalidFeedback>{t('user.make_sure_same_password')}</CInvalidFeedback>
|
||||
</CInputGroup>
|
||||
) : null}
|
||||
</CCol>
|
||||
<CLabel lg="2" xxl="1" col htmlFor="confirmNewPassword">
|
||||
{t('user.confirm_new_password')}
|
||||
</CLabel>
|
||||
<CCol lg="4" xxl="5">
|
||||
{editing ? (
|
||||
<CInputGroup>
|
||||
<CInput
|
||||
type={showPassword ? 'text' : 'password'}
|
||||
id="confirmNewPassword"
|
||||
value={user.confirmNewPassword.value}
|
||||
onChange={updateUserWithId}
|
||||
invalid={user.newPassword.error}
|
||||
maxLength="50"
|
||||
/>
|
||||
<CInputGroupAppend>
|
||||
<CPopover content={t('user.show_hide_password')}>
|
||||
<CButton type="button" onClick={toggleShowPassword} color="secondary">
|
||||
<CIcon
|
||||
name={showPassword ? 'cil-envelope-open' : 'cil-envelope-closed'}
|
||||
size="sm"
|
||||
/>
|
||||
</CButton>
|
||||
</CPopover>
|
||||
</CInputGroupAppend>
|
||||
<CInvalidFeedback>{t('user.make_sure_same_password')}</CInvalidFeedback>
|
||||
</CInputGroup>
|
||||
) : null}
|
||||
</CCol>
|
||||
</CFormGroup>
|
||||
<CFormGroup row>
|
||||
<CLabel lg="2" xl="1" col htmlFor="avatar" className="pt-2">
|
||||
{t('user.avatar')}
|
||||
</CLabel>
|
||||
<CCol lg="10" xl="5" className="pt-2">
|
||||
<CCol md="9" xl="10">
|
||||
<CRow>
|
||||
<CCol lg="2" xl="2" className="pt-2">
|
||||
{t('common.current')}
|
||||
<div className="pt-5">Preview</div>
|
||||
<CCol sm="12" md="6">
|
||||
<CRow>
|
||||
<CLabel className="mb-2" md="6" xl="4" col htmlFor="name">
|
||||
{t('user.name')}
|
||||
</CLabel>
|
||||
<CCol md="6" xl="8">
|
||||
{editing ? (
|
||||
<CInput
|
||||
id="name"
|
||||
value={user.name.value}
|
||||
onChange={updateUserWithId}
|
||||
maxLength="20"
|
||||
/>
|
||||
) : (
|
||||
<p className="mt-2 mb-0">{user.name.value}</p>
|
||||
)}
|
||||
</CCol>
|
||||
</CRow>
|
||||
<CRow>
|
||||
<CLabel className="mb-2" md="6" xl="4" col htmlFor="mfaMethod">
|
||||
MFA
|
||||
</CLabel>
|
||||
<CCol md="6" xl="8">
|
||||
<CSelect
|
||||
disabled={!editing}
|
||||
custom
|
||||
id="mfaMethod"
|
||||
onChange={updateUserWithId}
|
||||
value={user.mfaMethod.value}
|
||||
style={{ width: '100px' }}
|
||||
>
|
||||
<option value="">Off</option>
|
||||
<option value="sms">SMS</option>
|
||||
<option value="email">Email</option>
|
||||
</CSelect>
|
||||
</CCol>
|
||||
</CRow>
|
||||
<CRow>
|
||||
<CLabel className="mb-2" md="6" xl="4" col htmlFor="name">
|
||||
{t('user.phone_number')}
|
||||
</CLabel>
|
||||
<CCol md="6" xl="8">
|
||||
{editing ? (
|
||||
<CButton color="link" onClick={togglePhoneModal} className="pl-0">
|
||||
{parseNumber()}
|
||||
</CButton>
|
||||
) : (
|
||||
<p className="mt-2 mb-0">{parseNumber()}</p>
|
||||
)}
|
||||
</CCol>
|
||||
</CRow>
|
||||
</CCol>
|
||||
<CCol lg="1" xl="1">
|
||||
<Avatar src={avatar} fallback={user.email.value} />
|
||||
<div className="pt-3">
|
||||
<Avatar src={newAvatar} fallback={user.email.value} />
|
||||
</div>
|
||||
</CCol>
|
||||
<CCol className="pt-2">
|
||||
<div className="mt-1 mb-4">
|
||||
<LoadingButton
|
||||
label={t('user.delete_avatar')}
|
||||
isLoadingLabel={t('user.deleting')}
|
||||
isLoading={loading}
|
||||
action={deleteAvatar}
|
||||
block={false}
|
||||
disabled={
|
||||
!editing || loading || !avatar || avatar === '' || avatar === 'data:;base64,'
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className="pt-1">
|
||||
<CInputFile
|
||||
disabled={!editing}
|
||||
id="file-input"
|
||||
name="file-input"
|
||||
accept="image/*"
|
||||
onChange={showPreview}
|
||||
key={fileInputKey}
|
||||
/>
|
||||
</div>
|
||||
<CCol sm="12" md="6">
|
||||
<CRow>
|
||||
<CLabel className="mb-2" md="6" xl="4" col htmlFor="description">
|
||||
{t('user.description')}
|
||||
</CLabel>
|
||||
<CCol md="6" xl="8">
|
||||
{editing ? (
|
||||
<CInput
|
||||
id="description"
|
||||
value={user.description.value}
|
||||
onChange={updateUserWithId}
|
||||
maxLength="50"
|
||||
/>
|
||||
) : (
|
||||
<p className="mt-2 mb-0">{user.description.value}</p>
|
||||
)}
|
||||
</CCol>
|
||||
</CRow>
|
||||
<CRow>
|
||||
<CLabel className="mb-2" md="6" xl="4" col htmlFor="newPassword">
|
||||
{t('login.new_password')}
|
||||
</CLabel>
|
||||
<CCol md="6" xl="8">
|
||||
{editing ? (
|
||||
<CInputGroup>
|
||||
<CInput
|
||||
type={showPassword ? 'text' : 'password'}
|
||||
id="newPassword"
|
||||
value={user.newPassword.value}
|
||||
onChange={updateUserWithId}
|
||||
invalid={user.newPassword.error}
|
||||
maxLength="50"
|
||||
/>
|
||||
<CInputGroupAppend>
|
||||
<CPopover content={t('user.show_hide_password')}>
|
||||
<CButton type="button" onClick={toggleShowPassword} color="secondary">
|
||||
<CIcon
|
||||
name={showPassword ? 'cil-envelope-open' : 'cil-envelope-closed'}
|
||||
size="sm"
|
||||
/>
|
||||
</CButton>
|
||||
</CPopover>
|
||||
</CInputGroupAppend>
|
||||
<CInvalidFeedback>{t('user.make_sure_same_password')}</CInvalidFeedback>
|
||||
</CInputGroup>
|
||||
) : null}
|
||||
</CCol>
|
||||
</CRow>
|
||||
<CRow>
|
||||
<CLabel className="mb-2" md="6" xl="4" col htmlFor="confirmNewPassword">
|
||||
{t('user.confirm_new_password')}
|
||||
</CLabel>
|
||||
<CCol md="6" xl="8">
|
||||
{editing ? (
|
||||
<CInputGroup>
|
||||
<CInput
|
||||
type={showPassword ? 'text' : 'password'}
|
||||
id="confirmNewPassword"
|
||||
value={user.confirmNewPassword.value}
|
||||
onChange={updateUserWithId}
|
||||
invalid={user.newPassword.error}
|
||||
maxLength="50"
|
||||
/>
|
||||
<CInputGroupAppend>
|
||||
<CPopover content={t('user.show_hide_password')}>
|
||||
<CButton type="button" onClick={toggleShowPassword} color="secondary">
|
||||
<CIcon
|
||||
name={showPassword ? 'cil-envelope-open' : 'cil-envelope-closed'}
|
||||
size="sm"
|
||||
/>
|
||||
</CButton>
|
||||
</CPopover>
|
||||
</CInputGroupAppend>
|
||||
<CInvalidFeedback>{t('user.make_sure_same_password')}</CInvalidFeedback>
|
||||
</CInputGroup>
|
||||
) : null}
|
||||
</CCol>
|
||||
</CRow>
|
||||
</CCol>
|
||||
</CRow>
|
||||
</CCol>
|
||||
<CCol lg="12" xl="6" className="pt-2">
|
||||
<NotesTable
|
||||
t={t}
|
||||
notes={user.notes.value}
|
||||
addNote={addNote}
|
||||
loading={loading}
|
||||
size="lg"
|
||||
editable={editing}
|
||||
/>
|
||||
</CCol>
|
||||
</CFormGroup>
|
||||
</CRow>
|
||||
<CRow>
|
||||
<CCol />
|
||||
<CCol xs={2} className="mt-2 text-right">
|
||||
@@ -271,7 +267,6 @@ EditMyProfile.propTypes = {
|
||||
updateUserWithId: PropTypes.func.isRequired,
|
||||
loading: PropTypes.bool.isRequired,
|
||||
policies: PropTypes.instanceOf(Object).isRequired,
|
||||
addNote: PropTypes.func.isRequired,
|
||||
avatar: PropTypes.string,
|
||||
newAvatar: PropTypes.string,
|
||||
showPreview: PropTypes.func.isRequired,
|
||||
@@ -281,6 +276,7 @@ EditMyProfile.propTypes = {
|
||||
testVerificationCode: PropTypes.func.isRequired,
|
||||
updateWithKey: PropTypes.func.isRequired,
|
||||
editing: PropTypes.bool.isRequired,
|
||||
avatarDeleted: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
EditMyProfile.defaultProps = {
|
||||
|
||||
@@ -17,9 +17,8 @@ import {
|
||||
} from '@coreui/react';
|
||||
import PropTypes from 'prop-types';
|
||||
import CIcon from '@coreui/icons-react';
|
||||
import NotesTable from '../NotesTable';
|
||||
|
||||
const EditUserForm = ({ t, user, updateUserWithId, loading, policies, addNote }) => {
|
||||
const EditUserForm = ({ t, user, updateUserWithId, policies, editing }) => {
|
||||
const [showPassword, setShowPassword] = useState(false);
|
||||
|
||||
const toggleShowPassword = () => {
|
||||
@@ -33,18 +32,26 @@ const EditUserForm = ({ t, user, updateUserWithId, loading, policies, addNote })
|
||||
{t('user.name')}
|
||||
</CLabel>
|
||||
<CCol sm="4">
|
||||
<CInput id="name" value={user.name.value} onChange={updateUserWithId} maxLength="20" />
|
||||
{editing ? (
|
||||
<CInput id="name" value={user.name.value} onChange={updateUserWithId} maxLength="20" />
|
||||
) : (
|
||||
<p className="mt-2 mb-0">{user.name.value}</p>
|
||||
)}
|
||||
</CCol>
|
||||
<CLabel sm="2" col htmlFor="description">
|
||||
{t('user.description')}
|
||||
</CLabel>
|
||||
<CCol sm="4">
|
||||
<CInput
|
||||
id="description"
|
||||
value={user.description.value}
|
||||
onChange={updateUserWithId}
|
||||
maxLength="50"
|
||||
/>
|
||||
{editing ? (
|
||||
<CInput
|
||||
id="description"
|
||||
value={user.description.value}
|
||||
onChange={updateUserWithId}
|
||||
maxLength="50"
|
||||
/>
|
||||
) : (
|
||||
<p className="mt-2 mb-0">{user.description.value}</p>
|
||||
)}
|
||||
</CCol>
|
||||
</CFormGroup>
|
||||
<CFormGroup row>
|
||||
@@ -52,7 +59,13 @@ const EditUserForm = ({ t, user, updateUserWithId, loading, policies, addNote })
|
||||
{t('user.user_role')}
|
||||
</CLabel>
|
||||
<CCol sm="4">
|
||||
<CSelect custom id="userRole" onChange={updateUserWithId} value={user.userRole.value}>
|
||||
<CSelect
|
||||
custom
|
||||
id="userRole"
|
||||
onChange={updateUserWithId}
|
||||
value={user.userRole.value}
|
||||
disabled={!editing}
|
||||
>
|
||||
<option value="accounting">Accounting</option>
|
||||
<option value="admin">Admin</option>
|
||||
<option value="csr">CSR</option>
|
||||
@@ -68,27 +81,31 @@ const EditUserForm = ({ t, user, updateUserWithId, loading, policies, addNote })
|
||||
{t('login.new_password')}
|
||||
</CLabel>
|
||||
<CCol sm="4">
|
||||
<CInputGroup>
|
||||
<CInput
|
||||
type={showPassword ? 'text' : 'password'}
|
||||
id="currentPassword"
|
||||
value={user.currentPassword.value}
|
||||
onChange={updateUserWithId}
|
||||
invalid={user.currentPassword.error}
|
||||
maxLength="50"
|
||||
/>
|
||||
<CInputGroupAppend>
|
||||
<CPopover content={t('user.show_hide_password')}>
|
||||
<CButton type="button" onClick={toggleShowPassword} color="secondary">
|
||||
<CIcon
|
||||
name={showPassword ? 'cil-envelope-open' : 'cil-envelope-closed'}
|
||||
size="sm"
|
||||
/>
|
||||
</CButton>
|
||||
</CPopover>
|
||||
</CInputGroupAppend>
|
||||
<CInvalidFeedback>{t('user.provide_password')}</CInvalidFeedback>
|
||||
</CInputGroup>
|
||||
{editing ? (
|
||||
<CInputGroup>
|
||||
<CInput
|
||||
type={showPassword ? 'text' : 'password'}
|
||||
id="currentPassword"
|
||||
value={user.currentPassword.value}
|
||||
onChange={updateUserWithId}
|
||||
invalid={user.currentPassword.error}
|
||||
maxLength="50"
|
||||
/>
|
||||
<CInputGroupAppend>
|
||||
<CPopover content={t('user.show_hide_password')}>
|
||||
<CButton type="button" onClick={toggleShowPassword} color="secondary">
|
||||
<CIcon
|
||||
name={showPassword ? 'cil-envelope-open' : 'cil-envelope-closed'}
|
||||
size="sm"
|
||||
/>
|
||||
</CButton>
|
||||
</CPopover>
|
||||
</CInputGroupAppend>
|
||||
<CInvalidFeedback>{t('user.provide_password')}</CInvalidFeedback>
|
||||
</CInputGroup>
|
||||
) : (
|
||||
<p className="mt-2 mb-0" />
|
||||
)}
|
||||
</CCol>
|
||||
</CFormGroup>
|
||||
<CFormGroup row>
|
||||
@@ -98,6 +115,7 @@ const EditUserForm = ({ t, user, updateUserWithId, loading, policies, addNote })
|
||||
<CCol sm="1">
|
||||
<CInputGroup>
|
||||
<CSwitch
|
||||
disabled={!editing}
|
||||
id="changePassword"
|
||||
color="success"
|
||||
defaultChecked={user.changePassword.value}
|
||||
@@ -106,9 +124,6 @@ const EditUserForm = ({ t, user, updateUserWithId, loading, policies, addNote })
|
||||
/>
|
||||
</CInputGroup>
|
||||
</CCol>
|
||||
<CCol sm="8">
|
||||
<NotesTable t={t} notes={user.notes.value} addNote={addNote} loading={loading} />
|
||||
</CCol>
|
||||
</CFormGroup>
|
||||
<CRow>
|
||||
<CCol />
|
||||
@@ -132,9 +147,8 @@ EditUserForm.propTypes = {
|
||||
t: PropTypes.func.isRequired,
|
||||
user: PropTypes.instanceOf(Object).isRequired,
|
||||
updateUserWithId: PropTypes.func.isRequired,
|
||||
loading: PropTypes.bool.isRequired,
|
||||
policies: PropTypes.instanceOf(Object).isRequired,
|
||||
addNote: PropTypes.func.isRequired,
|
||||
editing: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
export default React.memo(EditUserForm);
|
||||
|
||||
@@ -1,9 +1,21 @@
|
||||
import React from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { CButton, CModal, CModalBody, CModalHeader, CModalTitle, CPopover } from '@coreui/react';
|
||||
import {
|
||||
CButton,
|
||||
CModal,
|
||||
CModalBody,
|
||||
CModalHeader,
|
||||
CModalTitle,
|
||||
CPopover,
|
||||
CNav,
|
||||
CNavLink,
|
||||
CTabPane,
|
||||
CTabContent,
|
||||
} from '@coreui/react';
|
||||
import CIcon from '@coreui/icons-react';
|
||||
import { cilSave, cilX } from '@coreui/icons';
|
||||
import { cilPencil, cilSave, cilX } from '@coreui/icons';
|
||||
import EditUserForm from '../EditUserForm';
|
||||
import DetailedNotesTable from '../DetailedNotesTable';
|
||||
|
||||
const EditUserModal = ({
|
||||
t,
|
||||
@@ -13,39 +25,99 @@ const EditUserModal = ({
|
||||
loading,
|
||||
policies,
|
||||
show,
|
||||
editing,
|
||||
toggleEditing,
|
||||
toggle,
|
||||
addNote,
|
||||
}) => (
|
||||
<CModal show={show} onClose={toggle} size="xl">
|
||||
<CModalHeader className="p-1">
|
||||
<CModalTitle className="pl-1 pt-1">
|
||||
{t('user.edit')} {user.email.value}
|
||||
</CModalTitle>
|
||||
<div className="text-right">
|
||||
<CPopover content={t('common.save')}>
|
||||
<CButton color="primary" variant="outline" onClick={saveUser} disabled={loading}>
|
||||
<CIcon content={cilSave} />
|
||||
</CButton>
|
||||
</CPopover>
|
||||
<CPopover content={t('common.close')}>
|
||||
<CButton color="primary" variant="outline" className="ml-2" onClick={toggle}>
|
||||
<CIcon content={cilX} />
|
||||
</CButton>
|
||||
</CPopover>
|
||||
</div>
|
||||
</CModalHeader>
|
||||
<CModalBody>
|
||||
<EditUserForm
|
||||
t={t}
|
||||
user={user}
|
||||
updateUserWithId={updateUserWithId}
|
||||
loading={loading}
|
||||
policies={policies}
|
||||
addNote={addNote}
|
||||
/>
|
||||
</CModalBody>
|
||||
</CModal>
|
||||
);
|
||||
}) => {
|
||||
const [index, setIndex] = useState(0);
|
||||
|
||||
const toggleModal = () => {
|
||||
toggleEditing();
|
||||
toggle();
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (show) setIndex(0);
|
||||
}, [show]);
|
||||
|
||||
return (
|
||||
<CModal show={show} onClose={toggle} size="xl">
|
||||
<CModalHeader className="p-1">
|
||||
<CModalTitle className="pl-1 pt-1">
|
||||
{t('user.edit')} {user.email.value}
|
||||
</CModalTitle>
|
||||
<div className="text-right">
|
||||
<CPopover content={t('common.save')}>
|
||||
<CButton color="primary" variant="outline" onClick={saveUser} disabled={loading}>
|
||||
<CIcon content={cilSave} />
|
||||
</CButton>
|
||||
</CPopover>
|
||||
<CPopover content={t('common.edit')}>
|
||||
<CButton
|
||||
disabled={editing}
|
||||
color="primary"
|
||||
variant="outline"
|
||||
onClick={toggleEditing}
|
||||
className="ml-2"
|
||||
>
|
||||
<CIcon name="cil-pencil" content={cilPencil} />
|
||||
</CButton>
|
||||
</CPopover>
|
||||
<CPopover content={t('common.close')}>
|
||||
<CButton color="primary" variant="outline" className="ml-2" onClick={toggleModal}>
|
||||
<CIcon content={cilX} />
|
||||
</CButton>
|
||||
</CPopover>
|
||||
</div>
|
||||
</CModalHeader>
|
||||
<CModalBody className="px-3 pt-0">
|
||||
<CNav variant="tabs" className="mb-0 p-0">
|
||||
<CNavLink
|
||||
className="font-weight-bold"
|
||||
href="#"
|
||||
active={index === 0}
|
||||
onClick={() => setIndex(0)}
|
||||
>
|
||||
{t('common.main')}
|
||||
</CNavLink>
|
||||
<CNavLink
|
||||
className="font-weight-bold"
|
||||
href="#"
|
||||
active={index === 1}
|
||||
onClick={() => setIndex(1)}
|
||||
>
|
||||
{t('configuration.notes')}
|
||||
</CNavLink>
|
||||
</CNav>
|
||||
<CTabContent>
|
||||
<CTabPane active={index === 0} className="pt-2">
|
||||
{index === 0 ? (
|
||||
<EditUserForm
|
||||
t={t}
|
||||
user={user}
|
||||
updateUserWithId={updateUserWithId}
|
||||
policies={policies}
|
||||
editing={editing}
|
||||
/>
|
||||
) : null}
|
||||
</CTabPane>
|
||||
<CTabPane active={index === 1}>
|
||||
{index === 1 ? (
|
||||
<DetailedNotesTable
|
||||
t={t}
|
||||
notes={user.notes.value}
|
||||
addNote={addNote}
|
||||
loading={loading}
|
||||
editable={editing}
|
||||
/>
|
||||
) : null}
|
||||
</CTabPane>
|
||||
</CTabContent>
|
||||
</CModalBody>
|
||||
</CModal>
|
||||
);
|
||||
};
|
||||
|
||||
EditUserModal.propTypes = {
|
||||
t: PropTypes.func.isRequired,
|
||||
@@ -55,6 +127,8 @@ EditUserModal.propTypes = {
|
||||
saveUser: PropTypes.func.isRequired,
|
||||
policies: PropTypes.instanceOf(Object).isRequired,
|
||||
show: PropTypes.bool.isRequired,
|
||||
editing: PropTypes.bool.isRequired,
|
||||
toggleEditing: PropTypes.func.isRequired,
|
||||
toggle: PropTypes.func.isRequired,
|
||||
addNote: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
@@ -29,7 +29,7 @@ const FirmwareDashboard = ({ t, data }) => {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<CRow>
|
||||
<CRow className="mt-3">
|
||||
<CCol>
|
||||
<CWidgetIcon
|
||||
text={t('common.last_dashboard_refresh')}
|
||||
@@ -79,7 +79,7 @@ const FirmwareDashboard = ({ t, data }) => {
|
||||
<CRow>
|
||||
<CCol>
|
||||
<CCard>
|
||||
<CCardHeader>{t('common.firmware_installed')}</CCardHeader>
|
||||
<CCardHeader className="dark-header">{t('common.firmware_installed')}</CCardHeader>
|
||||
<CCardBody>
|
||||
<CChartPie
|
||||
datasets={data.firmwareDistribution.datasets}
|
||||
@@ -96,7 +96,7 @@ const FirmwareDashboard = ({ t, data }) => {
|
||||
</CCol>
|
||||
<CCol>
|
||||
<CCard>
|
||||
<CCardHeader>{t('common.devices_using_latest')}</CCardHeader>
|
||||
<CCardHeader className="dark-header">{t('common.devices_using_latest')}</CCardHeader>
|
||||
<CCardBody>
|
||||
<CChartBar
|
||||
datasets={data.latest.datasets}
|
||||
@@ -121,7 +121,7 @@ const FirmwareDashboard = ({ t, data }) => {
|
||||
</CCol>
|
||||
<CCol>
|
||||
<CCard>
|
||||
<CCardHeader>Unknown Firmware</CCardHeader>
|
||||
<CCardHeader className="dark-header">Unknown Firmware</CCardHeader>
|
||||
<CCardBody>
|
||||
<CChartBar
|
||||
datasets={data.unknownFirmwares.datasets}
|
||||
@@ -148,7 +148,7 @@ const FirmwareDashboard = ({ t, data }) => {
|
||||
<CRow>
|
||||
<CCol>
|
||||
<CCard>
|
||||
<CCardHeader>{t('common.device_status')}</CCardHeader>
|
||||
<CCardHeader className="dark-header">{t('common.device_status')}</CCardHeader>
|
||||
<CCardBody>
|
||||
<CChartPie
|
||||
datasets={data.status.datasets}
|
||||
@@ -171,7 +171,7 @@ const FirmwareDashboard = ({ t, data }) => {
|
||||
</CCol>
|
||||
<CCol>
|
||||
<CCard>
|
||||
<CCardHeader>{t('firmware.device_types')}</CCardHeader>
|
||||
<CCardHeader className="dark-header">{t('firmware.device_types')}</CCardHeader>
|
||||
<CCardBody>
|
||||
<CChartPie
|
||||
datasets={data.deviceType.datasets}
|
||||
@@ -195,7 +195,7 @@ const FirmwareDashboard = ({ t, data }) => {
|
||||
</CCol>
|
||||
<CCol>
|
||||
<CCard>
|
||||
<CCardHeader>OUIs</CCardHeader>
|
||||
<CCardHeader className="dark-header">OUIs</CCardHeader>
|
||||
<CCardBody>
|
||||
<CChartBar
|
||||
datasets={data.ouis.datasets}
|
||||
@@ -222,9 +222,15 @@ const FirmwareDashboard = ({ t, data }) => {
|
||||
<CRow>
|
||||
<CCol>
|
||||
<CCard>
|
||||
<CCardHeader>{t('common.endpoints')}</CCardHeader>
|
||||
<CCardHeader className="dark-header">{t('common.endpoints')}</CCardHeader>
|
||||
<CCardBody>
|
||||
<CDataTable items={data.endpoints ?? []} fields={columns} hover border />
|
||||
<CDataTable
|
||||
addTableClasses="table-sm"
|
||||
items={data.endpoints ?? []}
|
||||
fields={columns}
|
||||
hover
|
||||
border
|
||||
/>
|
||||
</CCardBody>
|
||||
</CCard>
|
||||
</CCol>
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
import React, { useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { CCard, CCardBody, CCardHeader, CCol, CCollapse, CInput, CRow } from '@coreui/react';
|
||||
import { prettyDate, cleanBytesString } from '../../utils/formatting';
|
||||
import NotesTable from '../NotesTable';
|
||||
import LoadingButton from '../LoadingButton';
|
||||
|
||||
const FirmwareDetails = ({
|
||||
t,
|
||||
show,
|
||||
item,
|
||||
addNote,
|
||||
addNoteLoading,
|
||||
updateDescription,
|
||||
updateDescriptionLoading,
|
||||
}) => {
|
||||
const [description, setDescription] = useState('');
|
||||
|
||||
const saveDescription = () => {
|
||||
updateDescription(description, item.id);
|
||||
};
|
||||
|
||||
return (
|
||||
<CCollapse show={show}>
|
||||
<CCard className="mt-3 mx-3">
|
||||
<CCardHeader>{t('firmware.details_title', { image: item.image })}</CCardHeader>
|
||||
<CCardBody>
|
||||
<CRow>
|
||||
<CCol sm="1">Created</CCol>
|
||||
<CCol sm="5">{prettyDate(item.created)}</CCol>
|
||||
<CCol sm="1">Release</CCol>
|
||||
<CCol sm="5">{item.release}</CCol>
|
||||
</CRow>
|
||||
<CRow className="my-3">
|
||||
<CCol sm="1">Image</CCol>
|
||||
<CCol sm="5">{item.image}</CCol>
|
||||
<CCol sm="1">Image Date</CCol>
|
||||
<CCol sm="5">{prettyDate(item.imageDate)}</CCol>
|
||||
</CRow>
|
||||
<CRow className="my-3">
|
||||
<CCol sm="1">Revision</CCol>
|
||||
<CCol sm="5">{item.revision}</CCol>
|
||||
<CCol sm="1">Size</CCol>
|
||||
<CCol sm="5">{cleanBytesString(item.size)}</CCol>
|
||||
</CRow>
|
||||
<CRow className="my-3">
|
||||
<CCol sm="1">URI</CCol>
|
||||
<CCol sm="5">{item.uri}</CCol>
|
||||
<CCol sm="1">Owner</CCol>
|
||||
<CCol sm="5">{item.owner === '' ? t('common.unknown') : item.owner}</CCol>
|
||||
</CRow>
|
||||
<CRow className="my-3">
|
||||
<CCol sm="1" className="mt-2">
|
||||
Description
|
||||
</CCol>
|
||||
<CCol sm="4">
|
||||
<CInput
|
||||
id="description"
|
||||
defaultValue={item.description}
|
||||
maxLength="50"
|
||||
onChange={(e) => setDescription(e.target.value)}
|
||||
/>
|
||||
</CCol>
|
||||
<CCol sm="1">
|
||||
<LoadingButton
|
||||
label={t('common.save')}
|
||||
isLoadingLabel={t('common.saving')}
|
||||
isLoading={updateDescriptionLoading}
|
||||
action={saveDescription}
|
||||
disabled={updateDescriptionLoading}
|
||||
/>
|
||||
</CCol>
|
||||
<CCol>
|
||||
<NotesTable
|
||||
t={t}
|
||||
notes={item.notes}
|
||||
addNote={addNote}
|
||||
loading={addNoteLoading}
|
||||
extraFunctionParameter={item.id}
|
||||
/>
|
||||
</CCol>
|
||||
</CRow>
|
||||
</CCardBody>
|
||||
</CCard>
|
||||
</CCollapse>
|
||||
);
|
||||
};
|
||||
|
||||
FirmwareDetails.propTypes = {
|
||||
t: PropTypes.func.isRequired,
|
||||
show: PropTypes.bool.isRequired,
|
||||
item: PropTypes.instanceOf(Object).isRequired,
|
||||
addNoteLoading: PropTypes.bool.isRequired,
|
||||
addNote: PropTypes.func.isRequired,
|
||||
updateDescription: PropTypes.func.isRequired,
|
||||
updateDescriptionLoading: PropTypes.bool.isRequired,
|
||||
};
|
||||
export default React.memo(FirmwareDetails);
|
||||
63
src/components/FirmwareDetailsForm/index.js
Normal file
63
src/components/FirmwareDetailsForm/index.js
Normal file
@@ -0,0 +1,63 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { CCardBody, CCol, CInput, CRow } from '@coreui/react';
|
||||
import { prettyDate, cleanBytesString } from '../../utils/formatting';
|
||||
import NotesTable from '../NotesTable';
|
||||
|
||||
const FirmwareDetailsForm = ({ t, fields, updateFieldsWithId, addNote, editing }) => (
|
||||
<CCardBody className="p-1">
|
||||
<CRow>
|
||||
<CCol sm="2">Created</CCol>
|
||||
<CCol sm="4">{prettyDate(fields.created.value)}</CCol>
|
||||
<CCol sm="2">Release</CCol>
|
||||
<CCol sm="4">{fields.release.value}</CCol>
|
||||
</CRow>
|
||||
<CRow className="my-3">
|
||||
<CCol sm="2">Image</CCol>
|
||||
<CCol sm="4">{fields.image.value}</CCol>
|
||||
<CCol sm="2">Image Date</CCol>
|
||||
<CCol sm="4">{prettyDate(fields.imageDate.value)}</CCol>
|
||||
</CRow>
|
||||
<CRow className="my-3">
|
||||
<CCol sm="2">Revision</CCol>
|
||||
<CCol sm="4">{fields.revision.value}</CCol>
|
||||
<CCol sm="2">Size</CCol>
|
||||
<CCol sm="4">{cleanBytesString(fields.size.value)}</CCol>
|
||||
</CRow>
|
||||
<CRow className="my-3">
|
||||
<CCol sm="2">URI</CCol>
|
||||
<CCol sm="4">{fields.uri.value}</CCol>
|
||||
<CCol sm="2">Owner</CCol>
|
||||
<CCol sm="4">{fields.owner.value === '' ? t('common.unknown') : fields.owner.value}</CCol>
|
||||
</CRow>
|
||||
<CRow className="my-3">
|
||||
<CCol sm="2" className="mt-2">
|
||||
Description
|
||||
</CCol>
|
||||
<CCol sm="4">
|
||||
{editing ? (
|
||||
<CInput
|
||||
id="description"
|
||||
value={fields.description.value}
|
||||
onChange={updateFieldsWithId}
|
||||
maxLength="50"
|
||||
/>
|
||||
) : (
|
||||
<p className="mt-2 mb-0">{fields.description.value}</p>
|
||||
)}
|
||||
</CCol>
|
||||
<CCol>
|
||||
<NotesTable t={t} notes={fields.notes.value} addNote={addNote} editable={editing} />
|
||||
</CCol>
|
||||
</CRow>
|
||||
</CCardBody>
|
||||
);
|
||||
|
||||
FirmwareDetailsForm.propTypes = {
|
||||
t: PropTypes.func.isRequired,
|
||||
fields: PropTypes.instanceOf(Object).isRequired,
|
||||
updateFieldsWithId: PropTypes.func.isRequired,
|
||||
addNote: PropTypes.func.isRequired,
|
||||
editing: PropTypes.bool.isRequired,
|
||||
};
|
||||
export default FirmwareDetailsForm;
|
||||
@@ -12,7 +12,7 @@ const FirmwareHistoryModal = ({ t, loading, data }) => {
|
||||
|
||||
return (
|
||||
<CDataTable
|
||||
addTableClasses="ignore-overflow"
|
||||
addTableClasses="ignore-overflow table-sm"
|
||||
fields={columns}
|
||||
items={data}
|
||||
hover
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import ReactPaginate from 'react-paginate';
|
||||
import { v4 as createUuid } from 'uuid';
|
||||
@@ -12,8 +12,9 @@ import {
|
||||
CSelect,
|
||||
CSwitch,
|
||||
} from '@coreui/react';
|
||||
import CIcon from '@coreui/icons-react';
|
||||
import { cilSearch } from '@coreui/icons';
|
||||
import { prettyDate, cleanBytesString } from '../../utils/formatting';
|
||||
import FirmwareDetails from '../FirmwareDetails';
|
||||
import CopyToClipboardButton from '../CopyToClipboardButton';
|
||||
|
||||
const FirmwareList = ({
|
||||
@@ -23,19 +24,15 @@ const FirmwareList = ({
|
||||
pageCount,
|
||||
setPage,
|
||||
data,
|
||||
toggleEditModal,
|
||||
firmwarePerPage,
|
||||
setFirmwarePerPage,
|
||||
selectedDeviceType,
|
||||
deviceTypes,
|
||||
setSelectedDeviceType,
|
||||
addNote,
|
||||
addNoteLoading,
|
||||
updateDescription,
|
||||
updateDescriptionLoading,
|
||||
displayDev,
|
||||
toggleDevDisplay,
|
||||
}) => {
|
||||
const [detailsShown, setDetailsShown] = useState([]);
|
||||
const fields = [
|
||||
{ key: 'imageDate', label: t('firmware.image_date'), _style: { width: '1%' } },
|
||||
{ key: 'size', label: t('firmware.size'), _style: { width: '1%' } },
|
||||
@@ -44,18 +41,6 @@ const FirmwareList = ({
|
||||
{ key: 'show_details', label: '', _style: { width: '5%' } },
|
||||
];
|
||||
|
||||
const toggleDetails = (index) => {
|
||||
const position = detailsShown.indexOf(index);
|
||||
let newDetails = detailsShown.slice();
|
||||
|
||||
if (position !== -1) {
|
||||
newDetails.splice(position, 1);
|
||||
} else {
|
||||
newDetails = [...newDetails, index];
|
||||
}
|
||||
setDetailsShown(newDetails);
|
||||
};
|
||||
|
||||
const getShortRevision = (revision) => {
|
||||
if (revision.includes(' / ')) {
|
||||
return revision.split(' / ')[1];
|
||||
@@ -64,17 +49,12 @@ const FirmwareList = ({
|
||||
};
|
||||
|
||||
const changePage = (newValue) => {
|
||||
setDetailsShown([]);
|
||||
setPage(newValue);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setDetailsShown([]);
|
||||
}, [selectedDeviceType]);
|
||||
|
||||
return (
|
||||
<CCard>
|
||||
<CCardHeader className="py-2 px-3">
|
||||
<CCard className="m-0">
|
||||
<CCardHeader className="dark-header">
|
||||
<div className="d-flex flex-row-reverse">
|
||||
<div className="px-3">
|
||||
<CSwitch
|
||||
@@ -105,6 +85,7 @@ const FirmwareList = ({
|
||||
</CCardHeader>
|
||||
<CCardBody className="p-0">
|
||||
<CDataTable
|
||||
addTableClasses="table-sm"
|
||||
items={data}
|
||||
fields={fields}
|
||||
loading={loading}
|
||||
@@ -134,7 +115,7 @@ const FirmwareList = ({
|
||||
<td className="align-middle">
|
||||
<div style={{ width: 'calc(45vw)' }}>
|
||||
<div className="text-truncate align-middle">
|
||||
<CopyToClipboardButton key={item.uri} t={t} size="md" content={item.uri} />
|
||||
<CopyToClipboardButton key={item.uri} t={t} size="sm" content={item.uri} />
|
||||
<CPopover content={item.uri}>
|
||||
<span>{item.uri}</span>
|
||||
</CPopover>
|
||||
@@ -142,28 +123,18 @@ const FirmwareList = ({
|
||||
</div>
|
||||
</td>
|
||||
),
|
||||
show_details: (item, index) => (
|
||||
show_details: (item) => (
|
||||
<td className="text-center align-middle">
|
||||
<CButton
|
||||
size="sm"
|
||||
color="primary"
|
||||
variant={detailsShown.includes(index) ? '' : 'outline'}
|
||||
onClick={() => toggleDetails(index)}
|
||||
variant="outline"
|
||||
onClick={() => toggleEditModal(item.id)}
|
||||
>
|
||||
{detailsShown.includes(index) ? t('common.hide') : t('common.details')}
|
||||
<CIcon content={cilSearch} />
|
||||
</CButton>
|
||||
</td>
|
||||
),
|
||||
details: (item, index) => (
|
||||
<FirmwareDetails
|
||||
t={t}
|
||||
show={detailsShown.includes(index)}
|
||||
item={item}
|
||||
addNote={addNote}
|
||||
addNoteLoading={addNoteLoading}
|
||||
updateDescription={updateDescription}
|
||||
updateDescriptionLoading={updateDescriptionLoading}
|
||||
/>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
<div className="d-flex flex-row pl-3">
|
||||
@@ -217,12 +188,9 @@ FirmwareList.propTypes = {
|
||||
selectedDeviceType: PropTypes.string.isRequired,
|
||||
deviceTypes: PropTypes.instanceOf(Array).isRequired,
|
||||
setSelectedDeviceType: PropTypes.func.isRequired,
|
||||
addNote: PropTypes.func.isRequired,
|
||||
addNoteLoading: PropTypes.bool.isRequired,
|
||||
updateDescription: PropTypes.func.isRequired,
|
||||
updateDescriptionLoading: PropTypes.bool.isRequired,
|
||||
displayDev: PropTypes.bool.isRequired,
|
||||
toggleDevDisplay: PropTypes.func.isRequired,
|
||||
toggleEditModal: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default React.memo(FirmwareList);
|
||||
|
||||
@@ -21,7 +21,7 @@ const DeleteButton = ({ t, tag, deleteTag, hideTooltips }) => {
|
||||
variant="outline"
|
||||
shape="square"
|
||||
size="sm"
|
||||
className="mx-2"
|
||||
className="mx-1"
|
||||
data-tip
|
||||
data-for={tooltipId}
|
||||
data-event="click"
|
||||
|
||||
@@ -21,7 +21,7 @@ const UnassignButton = ({ t, tag, unassignTag, hideTooltips }) => {
|
||||
variant="outline"
|
||||
shape="square"
|
||||
size="sm"
|
||||
className="mx-2"
|
||||
className="mx-1"
|
||||
data-tip
|
||||
data-for={tooltipId}
|
||||
data-event="click"
|
||||
|
||||
@@ -2,7 +2,7 @@ import React, { useEffect, useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import ReactPaginate from 'react-paginate';
|
||||
import { CButton, CDataTable, CLink, CPopover, CButtonToolbar, CSelect } from '@coreui/react';
|
||||
import { cilPencil, cilPlus, cilRouter, cilSpreadsheet } from '@coreui/icons';
|
||||
import { cilMagnifyingGlass, cilPlus, cilRouter, cilSpreadsheet, cilZoomIn } from '@coreui/icons';
|
||||
import CIcon from '@coreui/icons-react';
|
||||
import ReactTooltip from 'react-tooltip';
|
||||
import DeleteButton from './DeleteButton';
|
||||
@@ -31,6 +31,7 @@ const InventoryTable = ({
|
||||
pushConfig,
|
||||
}) => {
|
||||
const [gwUi] = useState(localStorage.getItem('owgw-ui'));
|
||||
|
||||
const columns =
|
||||
onlyEntity || onlyUnassigned
|
||||
? [
|
||||
@@ -70,7 +71,7 @@ const InventoryTable = ({
|
||||
return (
|
||||
<>
|
||||
<CDataTable
|
||||
addTableClasses="ignore-overflow"
|
||||
addTableClasses="ignore-overflow table-sm"
|
||||
items={tags ?? []}
|
||||
fields={columns}
|
||||
hover
|
||||
@@ -79,15 +80,9 @@ const InventoryTable = ({
|
||||
scopedSlots={{
|
||||
serialNumber: (item) => (
|
||||
<td className="align-middle">
|
||||
<CLink
|
||||
className="c-subheader-nav-link align-self-center"
|
||||
aria-current="page"
|
||||
href={`${gwUi}/#/devices/${item.serialNumber}`}
|
||||
target="_blank"
|
||||
disabled={!gwUi || gwUi === ''}
|
||||
>
|
||||
<CButton color="link" onClick={() => toggleEditModal(item.serialNumber)}>
|
||||
{item.serialNumber}
|
||||
</CLink>
|
||||
</CButton>
|
||||
</td>
|
||||
),
|
||||
name: (item) => <td className="align-middle">{item.name}</td>,
|
||||
@@ -107,7 +102,7 @@ const InventoryTable = ({
|
||||
toggleAssociate({
|
||||
serialNumber: item.serialNumber,
|
||||
uuid: item.deviceConfiguration,
|
||||
value: item.deviceConfigurationName,
|
||||
value: item.extendedInfo?.deviceConfiguration?.name ?? '',
|
||||
})
|
||||
}
|
||||
>
|
||||
@@ -152,7 +147,7 @@ const InventoryTable = ({
|
||||
<CButtonToolbar
|
||||
role="group"
|
||||
className="justify-content-flex-end"
|
||||
style={{ width: '300px' }}
|
||||
style={{ width: '290px' }}
|
||||
>
|
||||
<CPopover content={t('inventory.assign_ent_ven')}>
|
||||
<div>
|
||||
@@ -162,7 +157,7 @@ const InventoryTable = ({
|
||||
variant="outline"
|
||||
shape="square"
|
||||
size="sm"
|
||||
className="mx-2"
|
||||
className="mx-1"
|
||||
onClick={() =>
|
||||
entity !== null
|
||||
? assignToEntity(item.serialNumber)
|
||||
@@ -187,7 +182,7 @@ const InventoryTable = ({
|
||||
variant="outline"
|
||||
shape="square"
|
||||
size="sm"
|
||||
className="mx-2"
|
||||
className="mx-1 d"
|
||||
onClick={() => pushConfig(item.serialNumber)}
|
||||
style={{ width: '33px', height: '30px' }}
|
||||
disabled={item.deviceConfigurationName === ''}
|
||||
@@ -201,24 +196,38 @@ const InventoryTable = ({
|
||||
variant="outline"
|
||||
shape="square"
|
||||
size="sm"
|
||||
className="mx-2"
|
||||
className="mx-1"
|
||||
onClick={() => toggleComputed(item.serialNumber)}
|
||||
style={{ width: '33px', height: '30px' }}
|
||||
>
|
||||
<CIcon name="cil-spreadsheet" content={cilSpreadsheet} size="sm" />
|
||||
</CButton>
|
||||
</CPopover>
|
||||
<CPopover content="Edit Tag">
|
||||
<CPopover content="View Tag">
|
||||
<CButton
|
||||
color="primary"
|
||||
variant="outline"
|
||||
shape="square"
|
||||
size="sm"
|
||||
className="mx-2"
|
||||
className="mx-1"
|
||||
onClick={() => toggleEditModal(item.serialNumber)}
|
||||
style={{ width: '33px', height: '30px' }}
|
||||
>
|
||||
<CIcon name="cil-pencil" content={cilPencil} size="sm" />
|
||||
<CIcon name="cil-magnifying-glass" content={cilMagnifyingGlass} size="sm" />
|
||||
</CButton>
|
||||
</CPopover>
|
||||
<CPopover content={t('inventory.view_in_gateway')}>
|
||||
<CButton
|
||||
color="primary"
|
||||
variant="outline"
|
||||
shape="square"
|
||||
size="sm"
|
||||
className="mx-1"
|
||||
onClick={() => window.open(`${gwUi}/#/devices/${item.serialNumber}`, '_blank')}
|
||||
disabled={!gwUi || gwUi === ''}
|
||||
style={{ width: '33px', height: '30px' }}
|
||||
>
|
||||
<CIcon content={cilZoomIn} />
|
||||
</CButton>
|
||||
</CPopover>
|
||||
</CButtonToolbar>
|
||||
|
||||
@@ -20,7 +20,7 @@ const DeleteButton = ({ t, location, deleteLocation, hideTooltips }) => {
|
||||
variant="outline"
|
||||
shape="square"
|
||||
size="sm"
|
||||
className="mx-2"
|
||||
className="mx-1"
|
||||
data-tip
|
||||
data-for={tooltipId}
|
||||
data-event="click"
|
||||
|
||||
@@ -55,7 +55,7 @@ const LocationTable = ({
|
||||
return (
|
||||
<>
|
||||
<CDataTable
|
||||
addTableClasses="ignore-overflow"
|
||||
addTableClasses="ignore-overflow table-sm"
|
||||
items={locations}
|
||||
fields={columns}
|
||||
hover
|
||||
@@ -94,7 +94,7 @@ const LocationTable = ({
|
||||
<CButtonToolbar
|
||||
role="group"
|
||||
className="justify-content-flex-end"
|
||||
style={{ width: '140px' }}
|
||||
style={{ width: '125px' }}
|
||||
>
|
||||
<CPopover content={t('inventory.assign_ent_ven')}>
|
||||
<div>
|
||||
@@ -104,7 +104,7 @@ const LocationTable = ({
|
||||
variant="outline"
|
||||
shape="square"
|
||||
size="sm"
|
||||
className="mx-2"
|
||||
className="mx-1"
|
||||
onClick={() => assignToEntity(item.id)}
|
||||
style={{ width: '33px', height: '30px' }}
|
||||
>
|
||||
@@ -124,7 +124,7 @@ const LocationTable = ({
|
||||
variant="outline"
|
||||
shape="square"
|
||||
size="sm"
|
||||
className="ml-2"
|
||||
className="mx-1"
|
||||
onClick={() => toggleEditModal(item.id)}
|
||||
style={{ width: '33px', height: '30px' }}
|
||||
>
|
||||
|
||||
@@ -56,9 +56,9 @@ const NotesTable = ({
|
||||
<CCol>
|
||||
<div className="overflow-auto" style={{ height: '200px' }}>
|
||||
<CDataTable
|
||||
striped
|
||||
responsive
|
||||
border
|
||||
addTableClasses="table-sm"
|
||||
loading={loading}
|
||||
fields={columns}
|
||||
items={notes || []}
|
||||
@@ -106,15 +106,14 @@ const NotesTable = ({
|
||||
/>
|
||||
</CCol>
|
||||
</CRow>
|
||||
<CRow className="pt-3">
|
||||
<CRow className="pt-1">
|
||||
<CCol sm="2" />
|
||||
<CCol>
|
||||
<div className="overflow-auto border" style={{ height: '200px' }}>
|
||||
<CDataTable
|
||||
striped
|
||||
responsive
|
||||
border
|
||||
addTableClasses="m-0 p-0"
|
||||
addTableClasses="m-0 p-0 table-sm"
|
||||
loading={loading}
|
||||
fields={columns}
|
||||
items={notes || []}
|
||||
@@ -146,10 +145,9 @@ const NotesTable = ({
|
||||
<CCol>
|
||||
<div className="overflow-auto border" style={{ height: '200px' }}>
|
||||
<CDataTable
|
||||
striped
|
||||
responsive
|
||||
border
|
||||
addTableClasses="m-0 p-0"
|
||||
addTableClasses="m-0 p-0 table-sm"
|
||||
loading={loading}
|
||||
fields={columns}
|
||||
items={notes || []}
|
||||
|
||||
@@ -20,6 +20,7 @@ const RadioAnalysisTable = ({ data, loading }) => {
|
||||
|
||||
return (
|
||||
<CDataTable
|
||||
addTableClasses="table-sm"
|
||||
fields={columns}
|
||||
items={data}
|
||||
hover
|
||||
|
||||
@@ -70,7 +70,7 @@ const UserListTable = ({
|
||||
return (
|
||||
<div>
|
||||
<CCard className="my-0 py-0">
|
||||
<CCardHeader className="my-0 p-1 text-light" style={{ backgroundColor: '#2f3d54' }}>
|
||||
<CCardHeader className="dark-header">
|
||||
<div style={{ fontWeight: '600' }} className=" text-value-lg float-left">
|
||||
{t('user.users')}
|
||||
</div>
|
||||
@@ -93,6 +93,7 @@ const UserListTable = ({
|
||||
</CCardHeader>
|
||||
<CCardBody className="p-0">
|
||||
<CDataTable
|
||||
addTableClasses="table-sm"
|
||||
items={users}
|
||||
fields={fields}
|
||||
loading={loading}
|
||||
|
||||
@@ -85,7 +85,7 @@ const VenueTable = ({
|
||||
</CCardHeader>
|
||||
<CCardBody className="p-0">
|
||||
<CDataTable
|
||||
addTableClasses="ignore-overflow"
|
||||
addTableClasses="ignore-overflow table-sm"
|
||||
items={venues ?? []}
|
||||
fields={columns}
|
||||
hover
|
||||
@@ -120,7 +120,7 @@ const VenueTable = ({
|
||||
<CButtonToolbar
|
||||
role="group"
|
||||
className="justify-content-flex-end pl-2"
|
||||
style={{ width: '100px' }}
|
||||
style={{ width: '90px' }}
|
||||
>
|
||||
<CPopover content="Edit Tag">
|
||||
<CButton
|
||||
@@ -128,7 +128,7 @@ const VenueTable = ({
|
||||
variant="outline"
|
||||
shape="square"
|
||||
size="sm"
|
||||
className="mx-1"
|
||||
className="mr-1"
|
||||
onClick={() => history.push(`/venue/${item.id}`)}
|
||||
style={{ width: '33px', height: '30px' }}
|
||||
>
|
||||
|
||||
@@ -61,7 +61,7 @@ const WifiAnalysisTable = ({ t, data, loading }) => {
|
||||
return (
|
||||
<div>
|
||||
<CDataTable
|
||||
addTableClasses="ignore-overflow mb-5"
|
||||
addTableClasses="ignore-overflow mb-5 table-sm"
|
||||
fields={columns}
|
||||
items={data}
|
||||
hover
|
||||
|
||||
@@ -47,12 +47,50 @@ export const EntityProvider = ({ axiosInstance, selectedEntity, children }) => {
|
||||
|
||||
const resetEntity = () => setEntity(null);
|
||||
|
||||
const setEntityId = async (entityId, isVenue) => {
|
||||
const newEntity = await getEntity(entityId, isVenue);
|
||||
if (newEntity && !_.isEqual(newEntity, entity)) {
|
||||
const newObj = {
|
||||
...newEntity,
|
||||
uuid: newEntity.id,
|
||||
name: newEntity.name,
|
||||
path: null,
|
||||
isVenue,
|
||||
childrenIds: newEntity.children,
|
||||
childrenVenues: newEntity.venues,
|
||||
extraData: newEntity,
|
||||
refreshId: createUuid(),
|
||||
};
|
||||
|
||||
setEntity({ ...newObj });
|
||||
}
|
||||
};
|
||||
|
||||
const setProviderEntity = async (entityToLoad) => {
|
||||
const newEntity = await getEntity(entityToLoad.uuid, entityToLoad.isVenue);
|
||||
if (newEntity) {
|
||||
const newObj = {
|
||||
...newEntity,
|
||||
uuid: newEntity.id,
|
||||
name: newEntity.name,
|
||||
path: null,
|
||||
isVenue: entityToLoad.isVenue,
|
||||
childrenIds: newEntity.children,
|
||||
childrenVenues: newEntity.venues,
|
||||
extraData: newEntity,
|
||||
refreshId: createUuid(),
|
||||
};
|
||||
|
||||
setEntity({ ...newObj });
|
||||
}
|
||||
};
|
||||
|
||||
const selectEntity = (uuid, name, path, isVenue, childrenEntities, childrenVenues, extraData) => {
|
||||
// If we have not yet gotten the information of this entity's children, we get them now
|
||||
if (childrenEntities || childrenVenues) {
|
||||
setEntityToRetrieve({ childrenEntities, childrenVenues, path, uuid, isVenue });
|
||||
}
|
||||
setEntity({
|
||||
setProviderEntity({
|
||||
uuid,
|
||||
name,
|
||||
isVenue,
|
||||
@@ -104,25 +142,6 @@ export const EntityProvider = ({ axiosInstance, selectedEntity, children }) => {
|
||||
});
|
||||
};
|
||||
|
||||
const setProviderEntity = async (id, isVenue) => {
|
||||
const newEntity = await getEntity(id, isVenue);
|
||||
if (newEntity && !_.isEqual(newEntity, entity)) {
|
||||
const newObj = {
|
||||
...newEntity,
|
||||
uuid: newEntity.id,
|
||||
name: newEntity.name,
|
||||
path: null,
|
||||
isVenue,
|
||||
childrenIds: newEntity.children,
|
||||
childrenVenues: newEntity.venues,
|
||||
extraData: newEntity,
|
||||
refreshId: createUuid(),
|
||||
};
|
||||
|
||||
setEntity({ ...newObj });
|
||||
}
|
||||
};
|
||||
|
||||
const getEntityChildren = async (parent) => {
|
||||
const loadedParents = parentsWithChildrenLoaded;
|
||||
const basePath = `${parent.path}._children.`;
|
||||
@@ -435,6 +454,7 @@ export const EntityProvider = ({ axiosInstance, selectedEntity, children }) => {
|
||||
deleteEntity,
|
||||
deviceTypes,
|
||||
resetEntity,
|
||||
setEntityId,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
||||
@@ -16,6 +16,7 @@ export { default as AddLocationForm } from './components/AddLocationForm';
|
||||
export { default as AddressEditor } from './components/AddressEditor';
|
||||
export { default as ApiStatusCard } from './components/ApiStatusCard';
|
||||
export { default as Avatar } from './components/Avatar';
|
||||
export { default as CompactNotesTable } from './components/CompactNotesTable';
|
||||
export { default as ConfigurationCustomMultiModal } from './components/Configuration/CustomMultiModal';
|
||||
export { default as ConfigurationElement } from './components/Configuration/ConfigurationElement';
|
||||
export { default as ConfigurationFileField } from './components/Configuration/FileField';
|
||||
@@ -32,6 +33,7 @@ export { default as ContactTable } from './components/ContactTable';
|
||||
export { default as CopyToClipboardButton } from './components/CopyToClipboardButton';
|
||||
export { default as CreateUserForm } from './components/CreateUserForm';
|
||||
export { default as ConfigurationTable } from './components/ConfigurationTable';
|
||||
export { default as DetailedNotesTable } from './components/DetailedNotesTable';
|
||||
export { default as DeviceDetails } from './components/DeviceDetails';
|
||||
export { default as DeviceFirmwareModal } from './components/DeviceFirmwareModal';
|
||||
export { default as DeviceListTable } from './components/DeviceListTable';
|
||||
@@ -48,6 +50,7 @@ export { default as EditUserModal } from './components/EditUserModal';
|
||||
export { default as EventQueueModal } from './components/EventQueueModal';
|
||||
export { default as InventoryTable } from './components/InventoryTable';
|
||||
export { default as FileToStringButton } from './components/FileToStringButton';
|
||||
export { default as FirmwareDetailsForm } from './components/FirmwareDetailsForm';
|
||||
export { default as FirmwareHistoryTable } from './components/FirmwareHistoryTable';
|
||||
export { default as FirmwareList } from './components/FirmwareList';
|
||||
export { default as FormattedDate } from './components/FormattedDate';
|
||||
|
||||
Reference in New Issue
Block a user