k2hr3-app
Version:
K2HR3 Web Application is K2hdkc based Resource and Roles and policy Rules
1,182 lines (1,077 loc) • 36 kB
JSX
/*
*
* K2HR3 Web Application
*
* Copyright 2017 Yahoo Japan Corporation.
*
* K2HR3 is K2hdkc based Resource and Roles and policy Rules, gathers
* common management information for the cloud.
* K2HR3 can dynamically manage information as "who", "what", "operate".
* These are stored as roles, resources, policies in K2hdkc, and the
* client system can dynamically read and modify these information.
*
* For the full copyright and license information, please view
* the license file that was distributed with this source code.
*
* AUTHOR: Takeshi Nakatani
* CREATE: Tue Nov 21 2017
* REVISION:
*
*/
import React from 'react';
import ReactDOM from 'react-dom'; // eslint-disable-line no-unused-vars
import PropTypes from 'prop-types';
import TextField from '@mui/material/TextField';
import Typography from '@mui/material/Typography';
import IconButton from '@mui/material/IconButton';
import Box from '@mui/material/Box';
import FormControlLabel from '@mui/material/FormControlLabel';
import RadioGroup from '@mui/material/RadioGroup';
import Radio from '@mui/material/Radio';
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableCell from '@mui/material/TableCell';
import TableHead from '@mui/material/TableHead';
import TablePagination from '@mui/material/TablePagination';
import TableRow from '@mui/material/TableRow';
import Tooltip from '@mui/material/Tooltip';
import DeleteIcon from '@mui/icons-material/ClearRounded';
import AddIcon from '@mui/icons-material/AddRounded';
import EditIcon from '@mui/icons-material/Edit';
import { r3Service } from './r3styles';
import R3FormButtons from './r3formbuttons'; // Buttons
import R3Message from '../util/r3message';
import R3CreateServiceDialog from './r3createservicedialog';
import R3PopupMsgDialog from './r3popupmsgdialog';
import { regYrnTenantPathPrefix, regYrnAnyTenantPath } from '../util/r3define';
import { getServiceResourceType, normalizeServiceReourceStaticObject } from '../util/r3verifyutil';
import { errorType, actionTypeValue, actionTypeDelete, actionTypeAdd, serviceResTypeUrl, serviceResTypeObject, serviceResTypeUnknown } from '../util/r3types';
import { r3DeepClone, r3DeepCompare, r3CompareCaseString, r3IsEmptyEntityObject, r3IsEmptyString, r3IsEmptyEntity, r3IsSafeTypedEntity, r3IsJSON, r3ConvertFromJSON } from '../util/r3util';
//
// Local variables
//
const tooltipValues = {
deleteTenantTooltip: 'deleteTenantTooltip',
addTenantTooltip: 'addTenantTooltip',
addResStaticObjTooltip: 'addResStaticObjTooltip',
nameResStaticObjTooltip: 'nameResStaticObjTooltip',
jsonResStaticObjTooltip: 'jsonResStaticObjTooltip',
delResStaticObjTooltip: 'delResStaticObjTooltip',
editResStaticObjTooltip: 'editResStaticObjTooltip'
};
const serviceComponentValues = {
serviceResourceTypeName: 'serviceResourceType',
verifyUrlResourceName: 'serviceVerifyUrlResource',
resStaticObjTextFieldName: 'resStaticObjTextField',
resUnknownTextFieldName: 'resUnknownTextField',
tenantTextFieldNamePrefix: 'tenantValue_',
tenantNewTextFieldName: 'tenantNew'
};
//
// Service Contents Class
//
export default class R3Service extends React.Component
{
static propTypes = {
r3provider: PropTypes.object.isRequired,
tenant: PropTypes.string.isRequired,
service: PropTypes.object.isRequired,
dispUnique: PropTypes.number.isRequired,
tableRawCount: PropTypes.number,
onSave: PropTypes.func.isRequired,
onUpdate: PropTypes.func.isRequired
};
static defaultProps = {
tableRawCount: 5
};
static orgServiceResource = {
serviceResType: null,
serviceResVerifyUrl: null,
serviceResStaticObject: null,
serviceResUnknown: null,
};
state = R3Service.createState(this.props.service, this.props.dispUnique);
constructor(props)
{
super(props);
// Binding(do not define handlers as arrow functions for performance)
this.handleSave = this.handleSave.bind(this);
this.handleCancel = this.handleCancel.bind(this);
this.handleConfirmDialogClose = this.handleConfirmDialogClose.bind(this);
this.handleMessageDialogClose = this.handleMessageDialogClose.bind(this);
this.handleVerifyChange = this.handleVerifyChange.bind(this);
this.handleTenantsChange = this.handleTenantsChange.bind(this);
this.handleAddTenantsChange = this.handleAddTenantsChange.bind(this);
this.handleResourceTypeChange = this.handleResourceTypeChange.bind(this);
this.handleResStaticObjPageChange = this.handleResStaticObjPageChange.bind(this);
this.handleNewStaticResourceObj = this.handleNewStaticResourceObj.bind(this);
this.handleDelStaticResourceObj = this.handleDelStaticResourceObj.bind(this);
this.handleEditStaticResourceObj = this.handleEditStaticResourceObj.bind(this);
this.handleCloseStaticResourceDialog = this.handleCloseStaticResourceDialog.bind(this);
this.handleCheckStaticResourceName = this.handleCheckStaticResourceName.bind(this);
// styles
this.sxClasses = r3Service(props.theme);
}
componentDidMount()
{
// update State
this.setState(R3Service.createState(this.props.service, this.props.dispUnique));
}
// [NOTE]
// Use getDerivedStateFromProps by deprecating componentWillReceiveProps in React 17.x.
// The only purpose is to set the state data from props when the dialog changes from hidden to visible.
//
static getDerivedStateFromProps(nextProps, prevState)
{
if(nextProps.dispUnique !== prevState.dispUnique){
// Switching content
return R3Service.createState(nextProps.service, nextProps.dispUnique);
}
return null; // Return null to indicate no change to state.
}
static createState(service, dispUnique)
{
// keep original analyzed verify data
R3Service.orgServiceResource.serviceResType = getServiceResourceType(service.verify);
R3Service.orgServiceResource.serviceResVerifyUrl = '';
R3Service.orgServiceResource.serviceResStaticObject = [];
R3Service.orgServiceResource.serviceResUnknown = '';
if(R3Service.orgServiceResource.serviceResType == serviceResTypeUrl){
R3Service.orgServiceResource.serviceResVerifyUrl = service.verify;
}else if(R3Service.orgServiceResource.serviceResType == serviceResTypeObject){
R3Service.orgServiceResource.serviceResStaticObject = normalizeServiceReourceStaticObject(service.verify);
}else{ // serviceResTypeUnknown
R3Service.orgServiceResource.serviceResUnknown = JSON.stringify(service.verify);
}
// new state
return {
dispUnique: dispUnique,
service: r3DeepClone(service),
serviceResType: R3Service.orgServiceResource.serviceResType,
serviceResVerifyUrl: R3Service.orgServiceResource.serviceResVerifyUrl,
serviceResStaticObject: R3Service.orgServiceResource.serviceResStaticObject,
serviceResUnknown: R3Service.orgServiceResource.serviceResUnknown,
serviceResStaticObjPageNum: 0,
addTenant: '',
changed: false,
staticResourceDialog: false,
staticResourceObjectPos: -1,
staticResourceObject: [],
confirmMessageObject: null,
messageDialogObject: null,
tooltips: {
deleteTenantTooltip: -1, // position
addTenantTooltip: false,
addResStaticObjTooltip: false,
nameResStaticObjTooltip: -1,
jsonResStaticObjTooltip: -1,
delResStaticObjTooltip: -1,
editResStaticObjTooltip: -1
}
};
}
//
// Check all state
//
isChangedState(newResType, newVerify, newTenants)
{
let is_changed = false;
// check verify
if(newResType != R3Service.orgServiceResource.serviceResType){
is_changed = true;
}else{
if(newResType == serviceResTypeUrl && newVerify != R3Service.orgServiceResource.serviceResVerifyUrl){
is_changed = true;
}else if(newResType == serviceResTypeObject){
if(!r3DeepCompare(newVerify, R3Service.orgServiceResource.serviceResStaticObject)){
is_changed = true;
}
}else if(newResType == serviceResTypeUnknown && newVerify != R3Service.orgServiceResource.serviceResUnknown){
is_changed = true;
}
}
// check tenants
if(r3IsSafeTypedEntity(newTenants, 'array')){
if(r3IsEmptyEntity(this.props.service) || !r3IsSafeTypedEntity(this.props.service.tenant, 'array')){
is_changed = true;
}else{
if(!r3DeepCompare(this.props.service.tenant, newTenants)){
is_changed = true;
}
}
}
return is_changed;
}
//
// Handle Form Button : Save
//
handleSave(event) // eslint-disable-line no-unused-vars
{
if(!this.state.changed){
// no change, nothing to do
return;
}
//
// Make new service
//
let newService = r3DeepClone(this.state.service);
//
// Check and Set service resource value to service
//
let errorMessage;
if(this.state.serviceResType == serviceResTypeUrl){
newService.verify = this.state.serviceResVerifyUrl;
errorMessage = this.props.r3provider.getErrorServiceResourceVerify(this.state.serviceResVerifyUrl);
}else if(this.state.serviceResType == serviceResTypeObject){
newService.verify = r3DeepClone(this.state.serviceResStaticObject);
errorMessage = this.props.r3provider.getErrorServiceResourceVerify(this.state.serviceResStaticObject);
}else{ // serviceResTypeUnknown
// block to set unknown type after changing resource
errorMessage = this.props.r3provider.getR3TextRes().eNewWrongVerifyObject;
}
if(null != errorMessage){
this.setState({
messageDialogObject: new R3Message(errorMessage, errorType)
});
return;
}
//
// Tenant
//
if(!r3IsSafeTypedEntity(newService.tenant, 'array')){
newService.tenant = [];
}
// check empty and yrn path by regex
let regTenantPath = new RegExp(regYrnAnyTenantPath);
let cnt;
let cnt2;
for(cnt = 0; cnt < newService.tenant.length; ++cnt){
newService.tenant[cnt] = newService.tenant[cnt].trim();
if('*' !== newService.tenant[cnt] && null === newService.tenant[cnt].match(regTenantPath)){
this.setState({
messageDialogObject: new R3Message(this.props.r3provider.getR3TextRes().eNotYRNTenant, errorType)
});
return;
}
}
// check same value
for(cnt = 0; cnt < newService.tenant.length; ++cnt){
for(cnt2 = (cnt + 1); cnt2 < newService.tenant.length; ++cnt2){
if(newService.tenant[cnt] === newService.tenant[cnt2]){
let tenantYrn = regYrnTenantPathPrefix + this.props.tenant;
this.setState({
messageDialogObject: new R3Message((tenantYrn === newService.tenant[cnt] ? this.props.r3provider.getR3TextRes().eTenantOwnerArray : this.props.r3provider.getR3TextRes().eTenantArray), errorType)
});
return;
}
}
}
//
// Check changed
//
if(!this.isChangedState(this.state.serviceResType, newService.verify, newService.tenant)){
this.setState({
messageDialogObject: new R3Message(this.props.r3provider.getR3TextRes().eNoChange, errorType)
});
return;
}
this.props.onSave(newService);
}
//
// Handle Form Button : Cancel
//
handleCancel(event) // eslint-disable-line no-unused-vars
{
if(this.state.changed){
this.setState({
confirmMessageObject: new R3Message(this.props.r3provider.getR3TextRes().cUpdatingCancel)
});
}
}
//
// Handle Confirm Dialog : Close( OK / Cancel )
//
handleConfirmDialogClose(event, reason, result)
{
if(result){
// case for 'cancel updating' to do
this.props.onUpdate(false);
// rewind State
this.setState(R3Service.createState(this.props.service, this.props.dispUnique));
}else{
// case for 'cancel updating' to cancel
this.setState({
confirmMessageObject: null
});
}
}
//
// Handle Message Dialog : Close
//
handleMessageDialogClose(event, reason, result) // eslint-disable-line no-unused-vars
{
this.setState({
messageDialogObject: null
});
}
//
// Handle Verify Value : Change
//
handleVerifyChange(event)
{
let newValue = r3IsEmptyEntityObject(event.target, 'value') ? null : event.target.value;
if(!r3IsSafeTypedEntity(newValue, 'string')){
console.warn('Changed verify new value is wrong.');
return;
}
if(newValue === this.state.serviceResVerifyUrl){
// nothing to update
return;
}
// set parent changed state
let changed = this.isChangedState(this.state.serviceResType, newValue, this.state.service.tenant);
this.props.onUpdate(changed);
// update state
this.setState({
serviceResVerifyUrl: newValue,
changed: changed
});
}
//
// Handle Tenants : Change
//
handleTenantsChange(event, type, pos)
{
let changedValue = r3IsEmptyEntityObject(event.target, 'value') ? null : event.target.value;
let newTenants = [];
if(r3IsSafeTypedEntity(this.state.service.tenant, 'array')){
newTenants = r3DeepClone(this.state.service.tenant);
}
let isClearNewValue = false;
if(actionTypeValue === type){
if(r3IsEmptyEntity(pos) || isNaN(pos) || pos < 0 || newTenants.length <= pos){
console.warn('unknown position(' + JSON.stringify(pos) + ') for tenants.');
return;
}
newTenants[pos] = changedValue.trim();
}else if(actionTypeDelete === type){
if(r3IsEmptyEntity(pos) || isNaN(pos) || pos < 0 || newTenants.length <= pos){
console.warn('unknown position(' + JSON.stringify(pos) + ') for tenants.');
return;
}
newTenants.splice(pos, 1);
}else if(actionTypeAdd === type){
if(r3IsEmptyString(this.state.addTenant, true)){
this.setState({
messageDialogObject: new R3Message(this.props.r3provider.getR3TextRes().eNewTenant, errorType)
});
return;
}
newTenants.push(this.state.addTenant.trim());
isClearNewValue = true;
}else{
console.warn('unknown action(' + JSON.stringify(type) + ') for tenants.');
return;
}
// make new resource object
let newService = r3DeepClone(this.state.service);
newService.tenant = newTenants;
// set parent changed state
let nowVerify;
if(this.state.serviceResType == serviceResTypeUrl){
nowVerify = this.state.serviceResVerifyUrl;
}else if(this.state.serviceResType == serviceResTypeObject){
nowVerify = this.state.serviceResStaticObject;
}else{ // serviceResTypeUnknown
nowVerify = this.state.serviceResUnknown;
}
let changed = this.isChangedState(this.state.serviceResType, nowVerify, newTenants);
this.props.onUpdate(changed);
// update state
this.setState({
service: newService,
changed: changed,
addTenant: (isClearNewValue ? '' : this.state.addTenant)
});
}
//
// Handle Add New Tenant : Change
//
handleAddTenantsChange(event)
{
// update state
this.setState({
addTenant: event.target.value
});
}
handTooltipChange = (event, type, extData) =>
{
if(tooltipValues.deleteTenantTooltip === type){
this.setState({
tooltips: {
deleteTenantTooltip: extData
}
});
}else if(tooltipValues.addTenantTooltip === type){
this.setState({
tooltips: {
addTenantTooltip: extData
}
});
}else if(tooltipValues.nameResStaticObjTooltip === type){
this.setState({
tooltips: {
nameResStaticObjTooltip: extData
}
});
}else if(tooltipValues.jsonResStaticObjTooltip === type){
this.setState({
tooltips: {
jsonResStaticObjTooltip: extData
}
});
}else if(tooltipValues.addResStaticObjTooltip === type){
this.setState({
tooltips: {
addResStaticObjTooltip: extData
}
});
}else if(tooltipValues.delResStaticObjTooltip === type){
this.setState({
tooltips: {
delResStaticObjTooltip: extData
}
});
}else if(tooltipValues.editResStaticObjTooltip === type){
this.setState({
tooltips: {
editResStaticObjTooltip: extData
}
});
}
};
getTenantsContents(items)
{
const { theme, r3provider } = this.props;
if(!r3IsSafeTypedEntity(items, 'array')){
return;
}
let tenantYrn = regYrnTenantPathPrefix + this.props.tenant;
return items.map( (item, pos) =>
{
if(r3CompareCaseString(tenantYrn, item)){
// item is owner tenant, this value could not change.
return;
}
let deleteButton = (
<Tooltip
title={ r3provider.getR3TextRes().tResServiceTenantDelTT }
open={ ((r3IsEmptyEntityObject(this.state, 'tooltips') || !r3IsSafeTypedEntity(this.state.tooltips.deleteTenantTooltip, 'number') || (this.state.tooltips.deleteTenantTooltip != pos)) ? false : true) }
>
<IconButton
onClick={ (event) => this.handleTenantsChange(event, actionTypeDelete, pos) }
onMouseEnter={ (event) => this.handTooltipChange(event, tooltipValues.deleteTenantTooltip, pos) }
onMouseLeave={ (event) => this.handTooltipChange(event, tooltipValues.deleteTenantTooltip, -1) }
{ ...theme.r3Service.deleteTenantButton }
sx={ this.sxClasses.deleteTenantButton }
size="large"
>
<DeleteIcon />
</IconButton>
</Tooltip>
);
return (
<Box
key={ pos }
sx={ this.sxClasses.enclosureElement }
>
<TextField
name={ serviceComponentValues.tenantTextFieldNamePrefix + String(pos) }
value={ item }
placeholder={ r3provider.getR3TextRes().tResServiceTenantHint }
onChange={ (event) => this.handleTenantsChange(event, actionTypeValue, pos) }
InputProps={{ sx: this.sxClasses.inputTextField }}
{ ...theme.r3Service.tenantTextField }
sx={ this.sxClasses.tenantTextField }
/>
{ deleteButton }
</Box>
);
});
}
getAddTenantsContents()
{
const { theme, r3provider } = this.props;
return (
<Box
sx={ this.sxClasses.enclosureElement }
>
<TextField
name={ serviceComponentValues.tenantNewTextFieldName }
value={ this.state.addTenant }
placeholder={ r3provider.getR3TextRes().tResServiceTenantHint }
onChange={ (event) => this.handleAddTenantsChange(event) }
InputProps={{ sx: this.sxClasses.inputTextField }}
{ ...theme.r3Service.tenantTextField }
sx={ this.sxClasses.tenantTextField }
/>
<Tooltip
title={ r3provider.getR3TextRes().tResServiceTenantAddTT }
open={ ((r3IsEmptyEntityObject(this.state, 'tooltips') || !r3IsSafeTypedEntity(this.state.tooltips.addTenantTooltip, 'boolean')) ? false : this.state.tooltips.addTenantTooltip) }
>
<IconButton
onClick={ (event) => this.handleTenantsChange(event, actionTypeAdd, 0) }
onMouseEnter={ (event) => this.handTooltipChange(event, tooltipValues.addTenantTooltip, true) }
onMouseLeave={ (event) => this.handTooltipChange(event, tooltipValues.addTenantTooltip, false) }
{ ...theme.r3Service.addTenantButton }
sx={ this.sxClasses.addTenantButton }
size="large"
>
<AddIcon />
</IconButton>
</Tooltip>
</Box>
);
}
//
// Handle Service resource type : Change
//
handleResourceTypeChange(event, type)
{
if(this.state.serviceResType === type){
console.warn('changed value type(' + JSON.stringify(type) + ') is something wrong.');
return;
}
let newResType = type;
let newVerify;
if(newResType == serviceResTypeUrl){
newVerify = this.state.serviceResVerifyUrl;
}else if(newResType == serviceResTypeObject){
newVerify = this.state.serviceResStaticObject;
}else{ // serviceResTypeUnknown
newVerify = this.state.serviceResUnknown;
}
// set parent changed state
let changed = this.isChangedState(newResType, newVerify, this.state.service.tenant);
this.props.onUpdate(changed);
// update state
this.setState({
serviceResType: newResType,
changed: changed
});
}
//
// Handle Add new static resource
//
handleNewStaticResourceObj(event) // eslint-disable-line no-unused-vars
{
// update state
this.setState({
staticResourceDialog: true,
staticResourceObjectPos: -1,
staticResourceObject: []
});
}
//
// Handle Delete static resource
//
handleDelStaticResourceObj(event, pos)
{
if(!r3IsSafeTypedEntity(this.state.serviceResStaticObject, 'array')){
return;
}
if(this.state.serviceResStaticObject.length <= pos){
return;
}
// remove resouce
let newStaticRes = this.state.serviceResStaticObject.filter( (item, itemPos) => itemPos !== pos);
// set parent changed state
let changed = this.isChangedState(this.state.serviceResType, newStaticRes, this.state.service.tenant);
this.props.onUpdate(changed);
// update state
this.setState({
serviceResStaticObject: newStaticRes,
changed: changed
});
}
//
// Handle Edit static resource
//
handleEditStaticResourceObj(event, pos)
{
if(!r3IsSafeTypedEntity(this.state.serviceResStaticObject, 'array')){
return;
}
if(this.state.serviceResStaticObject.length <= pos){
return;
}
let oneStaticRes = r3DeepClone(this.state.serviceResStaticObject[pos]);
// add data type
if(r3IsEmptyString(oneStaticRes.data)){
// data is empty(string or not) -> type: string
oneStaticRes.type = 'string';
oneStaticRes.editingObjectData = '';
oneStaticRes.editingStringData = '';
}else if(r3IsJSON(oneStaticRes.data)){
let tempobj = r3ConvertFromJSON(oneStaticRes.data);
if(r3IsSafeTypedEntity(tempobj, 'string')){
// data is JSON formatted, but it is string -> type: string
oneStaticRes.type = 'string';
oneStaticRes.editingObjectData = '';
oneStaticRes.editingStringData = tempobj;
}else if(r3IsSafeTypedEntity(tempobj, 'number')){
// data is JSON formatted, but it is number -> type: string
oneStaticRes.type = 'string';
oneStaticRes.editingObjectData = '';
oneStaticRes.editingStringData = String(tempobj);
}else{
// data is JSON formatted -> type: object
oneStaticRes.type = 'object';
oneStaticRes.editingObjectData = oneStaticRes.data;
oneStaticRes.editingStringData = '';
}
}else if(r3IsSafeTypedEntity(oneStaticRes.data, 'string')){
// data is string -> type: string
oneStaticRes.type = 'string';
oneStaticRes.editingObjectData = '';
oneStaticRes.editingStringData = oneStaticRes.data;
}else{
// data is other -> type: string
oneStaticRes.type = 'string';
oneStaticRes.editingObjectData = '';
oneStaticRes.editingStringData = JSON.stringify(oneStaticRes.data);
}
// update state
this.setState({
staticResourceDialog: true,
staticResourceObjectPos: pos,
staticResourceObject: [ oneStaticRes ]
});
}
//
// Handle Close static resource dialog
//
handleCloseStaticResourceDialog(event, reason, isAgree, newOneStaticRes)
{
if(!isAgree){
this.setState({
staticResourceDialog: false,
staticResourceObjectPos: -1,
staticResourceObject: []
});
return;
}
// add/edit new static resource
let newStaticRes = r3DeepClone(this.state.serviceResStaticObject);
if(0 <= this.state.staticResourceObjectPos && this.state.staticResourceObjectPos < newStaticRes.length){
newStaticRes[this.state.staticResourceObjectPos] = newOneStaticRes;
}else{
newStaticRes.push(newOneStaticRes);
}
// set parent changed state
let changed = this.isChangedState(this.state.serviceResType, newStaticRes, this.state.service.tenant);
this.props.onUpdate(changed);
// update state
this.setState({
serviceResStaticObject: newStaticRes,
changed: changed,
staticResourceDialog: false,
staticResourceObjectPos: -1,
staticResourceObject: []
});
}
//
// Handle Check conflict static resource name
//
handleCheckStaticResourceName(staticResName)
{
for(let cnt = 0; cnt < this.state.serviceResStaticObject.length; ++cnt){
if(cnt == this.state.staticResourceObjectPos){
continue;
}
if(this.state.serviceResStaticObject[cnt].name == staticResName){
return false;
}
}
return true;
}
//
// Handle Static resource object page : Change
//
handleResStaticObjPageChange(event, page)
{
this.setState({
serviceResStaticObjPageNum: page
});
}
//
// Render: Resource - Verify URL
//
renderServiceResourceVerifyUrl()
{
const { theme, r3provider } = this.props;
return (
<TextField
name={ serviceComponentValues.verifyUrlResourceName }
value={ this.state.serviceResVerifyUrl }
placeholder={ r3provider.getR3TextRes().tResServiceUrlResHint }
onChange={ (event) => this.handleVerifyChange(event) }
InputProps={{ sx: this.sxClasses.inputTextField }}
{ ...theme.r3Service.resourceTextField }
sx={ this.sxClasses.resourceTextField }
/>
);
}
//
// Render: Resource - Static resource object
//
getResStaticObjTableHead()
{
const { theme, r3provider } = this.props;
return (
<TableHead
sx={ this.sxClasses.tableHead }
>
<TableRow>
<TableCell
sx={ this.sxClasses.tableCell }
>
<Typography
{ ...theme.r3Service.textTableHead }
sx={ this.sxClasses.textTableHead }
>
{ r3provider.getR3TextRes().tResServiceNameTableHead }
</Typography>
</TableCell>
<TableCell
sx={ this.sxClasses.tableCell }
>
<Typography
{ ...theme.r3Service.textTableHead }
sx={ this.sxClasses.textTableHead }
>
{ r3provider.getR3TextRes().tResServiceJsonTableHead }
</Typography>
</TableCell>
<TableCell
sx={ this.sxClasses.tableCell }
>
<Tooltip
title={ r3provider.getR3TextRes().tResServiceAddStaticResTT }
open={ ((r3IsEmptyEntityObject(this.state, 'tooltips') || !r3IsSafeTypedEntity(this.state.tooltips.addResStaticObjTooltip, 'boolean')) ? false : this.state.tooltips.addResStaticObjTooltip) }
>
<IconButton
onClick={ this.handleNewStaticResourceObj }
onMouseEnter={ (event) => this.handTooltipChange(event, tooltipValues.addResStaticObjTooltip, true) }
onMouseLeave={ (event) => this.handTooltipChange(event, tooltipValues.addResStaticObjTooltip, false) }
{ ...theme.r3Service.addResStaticObjButton }
sx={ this.sxClasses.addResStaticObjButton }
size="large"
>
<AddIcon />
</IconButton>
</Tooltip>
</TableCell>
</TableRow>
</TableHead>
);
}
getResStaticObjTableBody()
{
const { theme, r3provider } = this.props;
if(!r3IsSafeTypedEntity(this.state.serviceResStaticObject, 'array')){
return;
}
let resources = this.state.serviceResStaticObject;
return (
<TableBody>
{resources.map( (item, pos) => {
if(pos < (this.state.serviceResStaticObjPageNum * this.props.tableRawCount) || ((this.state.serviceResStaticObjPageNum + 1) * this.props.tableRawCount) <= pos){
return;
}
let orgName = item.name;
let stripName = orgName;
if(13 < stripName.length){
stripName = stripName.slice(0, 10) + '...';
}
let orgJson = JSON.stringify(item);
let stripJson = orgJson;
if(53 < stripJson.length){
stripJson = stripJson.slice(0, 50) + '...';
}
return (
<TableRow
hover={ false }
key={ pos }
selected={ false }
>
<TableCell
sx={ this.sxClasses.tableCell }
>
<Tooltip
title={ orgName }
open={ ((r3IsEmptyEntityObject(this.state, 'tooltips') || !r3IsSafeTypedEntity(this.state.tooltips.nameResStaticObjTooltip, 'number') || (this.state.tooltips.nameResStaticObjTooltip != pos)) ? false : true) }
>
<Typography
onMouseEnter={ (event) => this.handTooltipChange(event, tooltipValues.nameResStaticObjTooltip, pos) }
onMouseLeave={ (event) => this.handTooltipChange(event, tooltipValues.nameResStaticObjTooltip, -1) }
{ ...theme.r3Service.textTableContent }
sx={ this.sxClasses.textTableContent }
>
{ stripName }
</Typography>
</Tooltip>
</TableCell>
<TableCell
sx={ this.sxClasses.tableCell }
>
<Tooltip
title={ orgJson }
open={ ((r3IsEmptyEntityObject(this.state, 'tooltips') || !r3IsSafeTypedEntity(this.state.tooltips.jsonResStaticObjTooltip, 'number') || (this.state.tooltips.jsonResStaticObjTooltip != pos)) ? false : true) }
>
<Typography
onMouseEnter={ (event) => this.handTooltipChange(event, tooltipValues.jsonResStaticObjTooltip, pos) }
onMouseLeave={ (event) => this.handTooltipChange(event, tooltipValues.jsonResStaticObjTooltip, -1) }
{ ...theme.r3Service.textTableContent }
sx={ this.sxClasses.textTableContent }
>
{ stripJson }
</Typography>
</Tooltip>
</TableCell>
<TableCell
sx={ this.sxClasses.tableCell }
>
<Tooltip
title={ r3provider.getR3TextRes().tResServiceDelStaticResTT }
open={ ((r3IsEmptyEntityObject(this.state, 'tooltips') || !r3IsSafeTypedEntity(this.state.tooltips.delResStaticObjTooltip, 'number') || (this.state.tooltips.delResStaticObjTooltip != pos)) ? false : true) }
>
<IconButton
onClick={ (event) => this.handleDelStaticResourceObj(event, pos) }
onMouseEnter={ (event) => this.handTooltipChange(event, tooltipValues.delResStaticObjTooltip, pos) }
onMouseLeave={ (event) => this.handTooltipChange(event, tooltipValues.delResStaticObjTooltip, -1) }
{ ...theme.r3Service.delResStaticObjButton }
sx={ this.sxClasses.delResStaticObjButton }
size="large"
>
<DeleteIcon />
</IconButton>
</Tooltip>
<Tooltip
title={ r3provider.getR3TextRes().tResServiceEditStaticResTT }
open={ ((r3IsEmptyEntityObject(this.state, 'tooltips') || !r3IsSafeTypedEntity(this.state.tooltips.editResStaticObjTooltip, 'number') || (this.state.tooltips.editResStaticObjTooltip != pos)) ? false : true) }
>
<IconButton
onClick={ (event) => this.handleEditStaticResourceObj(event, pos) }
onMouseEnter={ (event) => this.handTooltipChange(event, tooltipValues.editResStaticObjTooltip, pos) }
onMouseLeave={ (event) => this.handTooltipChange(event, tooltipValues.editResStaticObjTooltip, -1) }
{ ...theme.r3Service.editResStaticObjButton }
sx={ this.sxClasses.editResStaticObjButton }
size="large"
>
<EditIcon />
</IconButton>
</Tooltip>
</TableCell>
</TableRow>
);
})}
</TableBody>
);
}
renderServiceResourceStaticObj()
{
const { theme, r3provider } = this.props;
if(!r3IsSafeTypedEntity(this.state.serviceResStaticObject, 'array')){
return;
}
let tablehead = this.getResStaticObjTableHead();
let tablebody = this.getResStaticObjTableBody();
let textValue = JSON.stringify(this.state.serviceResStaticObject);
return (
<Box
sx={ this.sxClasses.tableBox }
>
<Table
{ ...theme.r3Service.table }
sx={ this.sxClasses.table }
>
{ tablehead }
{ tablebody }
</Table>
<TablePagination
component={ 'div' }
count={ this.state.serviceResStaticObject.length }
rowsPerPage={ this.props.tableRawCount }
page={ this.state.serviceResStaticObjPageNum }
rowsPerPageOptions={ [] }
onPageChange={ (event) => this.handleResStaticObjPageChange(event) }
/>
<TextField
name={ serviceComponentValues.resStaticObjTextFieldName }
value={ textValue }
disabled={ true }
placeholder={ r3provider.getR3TextRes().tResServiceStaticObjHint }
InputProps={{ sx: this.sxClasses.inputTextField }}
{ ...theme.r3Service.resourceTextField }
sx={ this.sxClasses.staticResourceTextField }
/>
</Box>
);
}
//
// Render: Resource - Unknown
//
renderServiceResourceUnknown()
{
const { theme, r3provider } = this.props;
return (
<React.Fragment>
<Typography
{ ...theme.r3Service.unknownMessage }
sx={ this.sxClasses.unknownMessage }
>
{ r3provider.getR3TextRes().tResServiceUnknownType }
</Typography>
<TextField
name={ serviceComponentValues.resUnknownTextFieldName }
value={ this.state.serviceResUnknown }
disabled={ true }
InputProps={{ sx: this.sxClasses.inputTextField }}
{ ...theme.r3Service.resourceTextField }
sx={ this.sxClasses.resourceTextField }
/>
</React.Fragment>
);
}
//
// Render: Resource all
//
renderServiceResourceGroup()
{
const { theme, r3provider } = this.props;
let leftTypeSelectLabel = (
<Typography
{ ...theme.r3Resource.valueFormControlLabel }
>
{ r3provider.getR3TextRes().tResServiceResTypeUrl }
</Typography>
);
let rightTypeSelectLabel = (
<Typography
{ ...theme.r3Resource.valueFormControlLabel }
>
{ r3provider.getR3TextRes().tResServiceResTypeStatic }
</Typography>
);
let radioValue;
let serviceResource;
if(serviceResTypeUrl == this.state.serviceResType){
radioValue = serviceResTypeUrl;
serviceResource = this.renderServiceResourceVerifyUrl();
}else if(serviceResTypeObject == this.state.serviceResType){
radioValue = serviceResTypeObject;
serviceResource = this.renderServiceResourceStaticObj();
}else{ // unknown
radioValue = serviceResTypeUnknown;
serviceResource = this.renderServiceResourceUnknown();
}
return (
<React.Fragment>
<RadioGroup
name={ serviceComponentValues.serviceResourceTypeName }
value={ radioValue }
onChange={ (event) => this.handleResourceTypeChange(event) }
{ ...theme.r3Service.valueRadioGroup }
sx={ this.sxClasses.valueRadioGroup }
>
<FormControlLabel
value={ serviceResTypeUrl }
label={ leftTypeSelectLabel }
disabled={ false }
control={ <Radio /> }
{ ...theme.r3Service.valueLeftFormControlLabel }
sx={ this.sxClasses.valueLeftFormControlLabel }
/>
<FormControlLabel
value={ serviceResTypeObject }
label={ rightTypeSelectLabel }
disabled={ false }
control={ <Radio /> }
{ ...theme.r3Service.valueRightFormControlLabel }
sx={ this.sxClasses.valueRightFormControlLabel }
/>
</RadioGroup>
{ serviceResource }
</React.Fragment>
);
}
//
// Render: main
//
render()
{
console.log('CALL: service::render()');
const { theme, r3provider } = this.props;
let serviceResourceGroup = this.renderServiceResourceGroup();
return (
<Box
sx={ this.sxClasses.root }
>
<Typography
{ ...theme.r3Service.subTitle }
sx={ this.sxClasses.subTitleTop }
>
{ r3provider.getR3TextRes().tResServiceUrlResSubTitle }
</Typography>
{ serviceResourceGroup }
<Typography
{ ...theme.r3Service.subTitle }
sx={ this.sxClasses.subTitle }
>
{ r3provider.getR3TextRes().tResServiceTenantsSubTitle }
</Typography>
{ this.getTenantsContents(this.state.service.tenant) }
{ this.getAddTenantsContents() }
<R3FormButtons
theme={ theme }
r3provider={ this.props.r3provider }
status={ this.state.changed }
onSave={ (event) => this.handleSave(event) }
onCancel={ (event) => this.handleCancel(event) }
/>
<R3CreateServiceDialog
theme={ theme }
r3provider={ this.props.r3provider }
open={ this.state.staticResourceDialog }
createMode={ false }
newStaticRes={ this.state.staticResourceObject }
onCheckConflictName={ this.handleCheckStaticResourceName }
onClose={ this.handleCloseStaticResourceDialog }
/>
<R3PopupMsgDialog
theme={ theme }
r3provider={ this.props.r3provider }
title={ this.props.r3provider.getR3TextRes().cUpdatingTitle }
r3Message={ this.state.confirmMessageObject }
twoButton={ true }
onClose={ this.handleConfirmDialogClose }
/>
<R3PopupMsgDialog
theme={ theme }
r3provider={ this.props.r3provider }
r3Message={ this.state.messageDialogObject }
onClose={ this.handleMessageDialogClose }
/>
</Box>
);
}
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noexpandtab sw=4 ts=4 fdm=marker
* vim<600: noexpandtab sw=4 ts=4
*/