Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GH-43: z-wave: Support of user credential cc #43

Draft
wants to merge 18 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions applications/dev_ui/dev_gui/src/App.tsx
Expand Up @@ -33,6 +33,7 @@ import Scene from './pages/scenes/scene/scene';
import EpScenes from './pages/scenes/ep-scenes/ep-scenes';
import { CommissionableDevices } from './pages/commissionable-devices/commissionable-devices';
import { Button, Modal, Spinner } from 'react-bootstrap';
import UserCredential from './pages/user-credential/user-credential';

class App extends Component<{}, AppState> {
constructor(props: {}) {
Expand Down Expand Up @@ -278,6 +279,7 @@ class App extends Component<{}, AppState> {
<Route path='/networkmanagement' exact render={() => <NetworkManagement ref={this.changeNodes} {...baseProps} NodeList={this.state.NodeList} />} />
<Route path='/measurements' exact render={() => <Measurements {...baseProps} NodeList={this.state.NodeList} />} />
<Route path='/commissionabledevices' exact render={() => <CommissionableDevices {...baseProps} List={this.state.CommissionableDevices} />} />
<Route path='/usercredential' exact render={() => <UserCredential ref={this.changeConfParams} {...baseProps} NodeList={this.state.NodeList} />} />
<Redirect from="/" exact to="/nodes" />
{Object.keys(ClusterTypes).map((type, index) =>
<Route key={index} path={NavbarItems.find(i => i.name === type)?.path} render={() =>
Expand Down
Expand Up @@ -10,7 +10,7 @@ import { ClusterTypes } from '../../cluster-types/cluster-types';
import { ClusterViewOverride } from './base-cluster-types';
import { Link } from 'react-router-dom';
import { Tooltip } from '@mui/material';
import { Button } from 'react-bootstrap';
import { Button, Badge } from 'react-bootstrap';

//Here you can find icons that can be used to customize you page: https://react-icons.github.io/react-icons/
//Don`t forgot to check licence if you use something that is not in Licence.txt
Expand Down Expand Up @@ -769,4 +769,23 @@ export let ClusterViewOverrides = {
} as NavbarItem,
IsExpandable: true
} as ClusterViewOverride,

UserCredential: {
NodesTooltip: (endpoint: string) =>
<Tooltip title={`Endpoint ${endpoint}: User Credential`}>
<span className="cursor-default">
<Link to={`/usercredential`}>
<RiIcons.RiUserSettingsFill color="#212529" />
</Link>
</span>
</Tooltip>,
NavbarItem: {
name: "User Credential",
title: 'User Credential',
path: '/usercredential',
icon: <RiIcons.RiUserSettingsFill />,
cName: 'nav-text',
subMenu: SideMenu.Actuators
} as NavbarItem
} as ClusterViewOverride,
}
@@ -0,0 +1,10 @@
export type UserDlgState = {
Command: any,
Unid: any,
ShowModal: boolean,
UserCredential: any
}

export type UserDlgProps = {
SocketServer: WebSocket
}
@@ -0,0 +1,110 @@
import * as React from 'react';
import { Button, Modal } from 'react-bootstrap';
import { UserDlgProps, UserDlgState } from './cred-dlg-types';
import UserCredentialAttrs from '../user-credential-attrs/user-credential-attrs';


class CredDlg extends React.Component<UserDlgProps, UserDlgState> {
constructor(props: UserDlgProps) {
super(props);
this.sendCommand = this.sendCommand.bind(this);
this.toggleModal = this.toggleModal.bind(this);
this.state = {
Command: {},
Unid: "",
ShowModal: false,
UserCredential: {}
};
this.changeCommandAttrs = React.createRef();
}
changeCommandAttrs: any;

toggleModal(value: boolean) {
this.setState({ ShowModal: value });
}

getDefinedUserIDs(userCredential: any) {
var users = userCredential.User
if (!users) {
return [];
}
return Object.keys(users).map(user_id => {
return { label: user_id, id: parseInt(user_id) }
});
}

getSupportedEnum(enumData: any, supportedEnumField: any) {
if (!supportedEnumField) {
return enumData;
}
return enumData.filter((enumItem:any) => supportedEnumField[enumItem.name]);
}

updateState(unid: string, command: any, showModal: boolean, userCredential: any) {
let updatedCommand = structuredClone(command);

updatedCommand.fields = command.fields.map( (field: any) => {
switch (field.name) {
case "UserUniqueID":
field.values = this.getDefinedUserIDs(userCredential);
if (field.values.length !== 0) {
field.defaultValue = field.values[0];
field.default = field.values[0].id;
}
break;
case "CredentialType":
field.enum = this.getSupportedEnum(field.enum, userCredential.SupportedCredentialTypes?.Reported);
break;
}
return field;
});


updatedCommand.UserList = userCredential.User;
updatedCommand.UserCredential = userCredential;

this.setState({ Unid: unid, Command: updatedCommand, ShowModal: showModal, UserCredential: userCredential },
() => {
this.changeCommandAttrs.current.updateState(this.state.Command)
});

}

sendCommand() {
if (this.state.UserCredential !== undefined)
this.props.SocketServer.send(JSON.stringify(
{
type: "run-cluster-command",
data: {
Unid: this.state.Unid,
ClusterType: "UserCredential",
Cmd: this.state.Command.name,
Payload: this.changeCommandAttrs.current.state.Payload
}
}));
}


render() {
return (
<Modal show={this.state.ShowModal} size="lg" onHide={() => this.toggleModal(false)}>
<Modal.Header closeButton>
<Modal.Title>{this.state.Command.name}</Modal.Title>
</Modal.Header>
<Modal.Body>
<UserCredentialAttrs ref={this.changeCommandAttrs} />
</Modal.Body>
<Modal.Footer>
<Button variant="primary" onClick={() => { this.sendCommand(); this.toggleModal(false); }}>
Send
</Button>
<Button variant="outline-primary" onClick={() => this.toggleModal(false)}>
Cancel
</Button>
</Modal.Footer>
</Modal>
);
}
}

export default CredDlg