@adcops/autocore-react 3.0.28 → 3.0.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/FileList.d.ts +6 -0
- package/dist/components/FileList.js +1 -1
- package/dist/components/FileSelect.d.ts +2 -0
- package/dist/components/FileSelect.js +1 -1
- package/dist/components/IndicatorRect.d.ts +87 -0
- package/dist/components/IndicatorRect.js +1 -0
- package/package.json +1 -1
- package/src/components/FileList.tsx +9 -4
- package/src/components/FileSelect.tsx +14 -2
- package/src/components/IndicatorRect.tsx +172 -0
|
@@ -55,6 +55,12 @@ type FileListProps = {
|
|
|
55
55
|
* The component uses the `EventEmitterContext` to make API calls to a backend to list, download, and delete files.
|
|
56
56
|
* It dynamically handles file operations based on the `domain` prop which determines the API endpoints for these actions.
|
|
57
57
|
*
|
|
58
|
+
* Requires
|
|
59
|
+
* ```tsx
|
|
60
|
+
* <ConfirmPopup />
|
|
61
|
+
* ```
|
|
62
|
+
* somewhere in a top-level page.
|
|
63
|
+
*
|
|
58
64
|
* Props:
|
|
59
65
|
* - `domain` (string): The domain name assigned to the DATASTORE servelet containing the data.
|
|
60
66
|
* Default: "DATASTORE"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as _jsx,jsxs as _jsxs,Fragment as _Fragment}from"react/jsx-runtime";import React,{useState,useContext,useEffect}from"react";import{DataTable}from"primereact/datatable";import{Column}from"primereact/column";import{Toolbar}from"primereact/toolbar";import{Button}from"primereact/button";import{
|
|
1
|
+
import{jsx as _jsx,jsxs as _jsxs,Fragment as _Fragment}from"react/jsx-runtime";import React,{useState,useContext,useEffect}from"react";import{DataTable}from"primereact/datatable";import{Column}from"primereact/column";import{Toolbar}from"primereact/toolbar";import{Button}from"primereact/button";import{confirmPopup}from"primereact/confirmpopup";import{FileUpload}from"primereact/fileupload";import{EventEmitterContext}from"../core/EventEmitterContext";export const FileList=({domain:e="DATASTORE",enableUpload:t=!1,subdir:o,filter:a=".json",onSuccess:n,onError:i})=>{const[r,l]=useState(0),{invoke:s}=useContext(EventEmitterContext),[c,d]=useState(),m=e=>null!==e?void 0!==o?`${o}/${e}`:e:"",p=async()=>{try{const t=void 0!==o?{subdir:o}:{};let a=await s(e,"list_files",t),n=[];for(let e=0;e<a.data.length;++e){const t=a.data[e];n.push({id:e+1,name:t})}d(n)}catch(e){i&&i(`Failed to upload file list: ${e}`)}};const u=()=>{l((e=>e+1))},f=`File Listing [/${void 0!==o?o:""}]`,x=_jsx(React.Fragment,{children:_jsx("span",{style:{fontWeight:600},children:f})}),b=_jsxs(React.Fragment,{children:[t&&_jsx(FileUpload,{customUpload:!0,auto:!0,uploadHandler:async t=>{const o=t.files[0];let a=m(o.name);const r=new FileReader;r.onload=async t=>{const r=t.target?.result,l=function c(e){let t="",o=new Uint8Array(e),a=o.byteLength;for(let e=0;e<a;e++)t+=String.fromCharCode(o[e]);return window.btoa(t)}(r);try{await s(e,"write_file",{file_name:a,value:l,options:{base64:!0}}),n&&n(`Uploaded file ${o.name}`),p()}catch(e){i&&i(`Failed to upload file: ${e}`)}u()},r.onerror=e=>{i&&i(`Error reading file: ${e}`)},r.readAsArrayBuffer(o)},accept:a,maxFileSize:25e3,mode:"basic",chooseLabel:"",chooseOptions:{icon:"pi pi-upload",className:"p-button-icon-only p-button-text p-button-rounded p-mr-2"}},r),_jsx(Button,{icon:"pi pi-refresh",onClick:()=>{p()},className:"p-button-rounded p-mr-2","aria-label":"Refresh",size:"small",rounded:!0,text:!0})]}),h=(t,o)=>{confirmPopup({target:o.currentTarget,message:`Are you want to delete file ${t.name}?\nWARNING: This cannot be undone.`,icon:"pi pi-info-circle",defaultFocus:"reject",acceptClassName:"p-button-danger",accept:()=>(async t=>{let o=m(t);try{await s(e,"delete_file",{file_name:o}),n&&n(`Deleted file: ${t}`),p()}catch(e){i&&i(`Failed to delete file: ${e}`)}p()})(t.name)})};return useEffect((()=>(p(),()=>{})),[e,t]),_jsxs("div",{children:[_jsx(Toolbar,{start:x,end:b,style:{padding:"1mm"}}),_jsxs(DataTable,{value:c,children:[_jsx(Column,{field:"name",header:"Name"}),_jsx(Column,{body:t=>_jsxs(_Fragment,{children:[_jsx(Button,{icon:"pi pi-download",onClick:()=>(async t=>{let o=m(t.name);try{await s(e,"download_file",{file_name:o}),n&&n(`Downloaded file: ${t.name}`)}catch(e){i&&i(`Failed downloading file: ${e}`)}})(t),className:"p-button-rounded p-button-success p-mr-2",style:{marginRight:"2mm"},size:"small"}),_jsx(Button,{icon:"pi pi-trash",onClick:e=>h(t,e),className:"p-button-rounded p-button-danger",size:"small"})]}),header:"Actions"})]})]})};export default FileList;
|
|
@@ -2,6 +2,8 @@ import React from 'react';
|
|
|
2
2
|
type FileSelectProps = {
|
|
3
3
|
domain?: string;
|
|
4
4
|
subdir?: string;
|
|
5
|
+
/** Filter results using unix-style patterns. */
|
|
6
|
+
filter?: string | null;
|
|
5
7
|
onFileSelected?: (fileName: string) => void;
|
|
6
8
|
onAccept?: (fileName: string) => void;
|
|
7
9
|
onCancel?: () => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import{useState,useContext,useEffect}from"react";import{DataTable}from"primereact/datatable";import{Column}from"primereact/column";import{Button}from"primereact/button";import{EventEmitterContext}from"../core/EventEmitterContext";export const FileSelect=({domain:e="DATASTORE",subdir:t,
|
|
1
|
+
import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import{useState,useContext,useEffect}from"react";import{DataTable}from"primereact/datatable";import{Column}from"primereact/column";import{Button}from"primereact/button";import{EventEmitterContext}from"../core/EventEmitterContext";export const FileSelect=({domain:e="DATASTORE",subdir:t,filter:n,onFileSelected:l,onAccept:i,onCancel:o})=>{const{invoke:a}=useContext(EventEmitterContext),[s,c]=useState([]),[r,m]=useState(null),u=e=>{m(e),l&&l(e.name)};return useEffect((()=>{(async()=>{try{let l;l=null!=n?t?{subdir:t,options:{filter:n}}:{options:{filter:n}}:t?{subdir:t}:{};const i=(await a(e,"list_files",l)).data.map(((e,t)=>({id:t+1,name:e})));c(i)}catch(e){}})()}),[e,t]),_jsxs("div",{children:[_jsxs(DataTable,{value:s,selectionMode:"single",selection:r,onSelectionChange:e=>u(e.value),children:[_jsx(Column,{field:"name",header:"File Name"}),_jsx(Column,{body:e=>_jsx(Button,{label:r?.name===e.name?"Selected":"Select",icon:r?.name===e.name?"pi pi-check-circle":"pi pi-circle-off",onClick:()=>u(e),className:"p-button-rounded "+(r?.name===e.name?"p-button-success":"p-button-outlined"),"aria-label":"Select",size:"small"}),header:"Select"})]}),_jsxs("div",{style:{display:"flex",justifyContent:"flex-end",marginTop:"10px"},children:[_jsx(Button,{label:"Cancel",icon:"pi pi-times",className:"p-button-text",onClick:o}),_jsx(Button,{label:"Accept",icon:"pi pi-check",className:"p-button",onClick:()=>{void 0!==i&&null!==r&&i(null!==r?void 0!==t?`${t}/${r.name}`:r.name:"")},disabled:!r})]})]})};export default FileSelect;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { Component } from 'react';
|
|
2
|
+
import { EventEmitterContextType } from '../core/EventEmitterContext';
|
|
3
|
+
import { IndicatorColor } from "../core/IndicatorColor";
|
|
4
|
+
export { IndicatorColor };
|
|
5
|
+
/**
|
|
6
|
+
* Common properties for an indicator rectangle component.
|
|
7
|
+
* This component is used for displaying states and is not interactive.
|
|
8
|
+
* It is commonly used in industrial HMIs for visual indication purposes.
|
|
9
|
+
*
|
|
10
|
+
* These properties support displaying values of boolean, number, and string states.
|
|
11
|
+
*
|
|
12
|
+
* Available boolean states: **on**, **off**, and **not available**:
|
|
13
|
+
*
|
|
14
|
+
* * `true` is treated as **on**
|
|
15
|
+
* * `false` is treated as **off**
|
|
16
|
+
* * `undefined` is treated as **not available**
|
|
17
|
+
*
|
|
18
|
+
* Numeric values can be used. When there are 2 or fewer possible states,
|
|
19
|
+
* 0 will be considered false (OFF), anything else will be considered true (ON).
|
|
20
|
+
* Undefined will be treated as "not available."
|
|
21
|
+
*
|
|
22
|
+
* When the indicator contains more than 2 states, the number will be matched
|
|
23
|
+
* to the available state, in order. More than two states requires usage of the
|
|
24
|
+
* `options` field and declaring more than two states there.
|
|
25
|
+
*
|
|
26
|
+
* If a string state is used, it will be matched exactly to the corresponding
|
|
27
|
+
* label in the `options` field.
|
|
28
|
+
*/
|
|
29
|
+
export interface IndicatorRectProps {
|
|
30
|
+
/**
|
|
31
|
+
* Topic name to monitor for state indication.
|
|
32
|
+
*/
|
|
33
|
+
topic?: string;
|
|
34
|
+
/**
|
|
35
|
+
* State to be displayed.
|
|
36
|
+
*/
|
|
37
|
+
value?: boolean | number | string;
|
|
38
|
+
/**
|
|
39
|
+
* Color for the rectangle when the state is TRUE.
|
|
40
|
+
*/
|
|
41
|
+
onColor?: IndicatorColor;
|
|
42
|
+
/**
|
|
43
|
+
* Color for the rectangle when the state is FALSE.
|
|
44
|
+
*/
|
|
45
|
+
offColor?: IndicatorColor;
|
|
46
|
+
/**
|
|
47
|
+
* An array of string labels to display as the available options.
|
|
48
|
+
*
|
|
49
|
+
* For items with 2 states or less:
|
|
50
|
+
* Index 0 is the label when value is OFF.
|
|
51
|
+
* Index 1 is the label when value is ON.
|
|
52
|
+
*
|
|
53
|
+
* If only one value is given (Index 0), then that value is used for all states.
|
|
54
|
+
*/
|
|
55
|
+
options?: string[];
|
|
56
|
+
/**
|
|
57
|
+
* Additional CSS class name to apply to the rectangle.
|
|
58
|
+
*/
|
|
59
|
+
className?: string;
|
|
60
|
+
/**
|
|
61
|
+
* Additional inline styles to apply to the rectangle.
|
|
62
|
+
*/
|
|
63
|
+
style?: React.CSSProperties;
|
|
64
|
+
}
|
|
65
|
+
interface IndicatorRectState {
|
|
66
|
+
currentValue?: boolean | number | string;
|
|
67
|
+
}
|
|
68
|
+
export declare class IndicatorRect extends Component<IndicatorRectProps, IndicatorRectState> {
|
|
69
|
+
static contextType: import("react").Context<EventEmitterContextType>;
|
|
70
|
+
static defaultProps: {
|
|
71
|
+
onColor: IndicatorColor;
|
|
72
|
+
offColor: string;
|
|
73
|
+
};
|
|
74
|
+
constructor(props: IndicatorRectProps);
|
|
75
|
+
componentDidMount(): void;
|
|
76
|
+
componentWillUnmount(): void;
|
|
77
|
+
/**
|
|
78
|
+
* Sets up subscriptions based on the provided topic.
|
|
79
|
+
*/
|
|
80
|
+
private setupSubscriptions;
|
|
81
|
+
/**
|
|
82
|
+
* Handles updates for the main topic.
|
|
83
|
+
*/
|
|
84
|
+
private handleTopicUpdate;
|
|
85
|
+
render(): import("react/jsx-runtime").JSX.Element;
|
|
86
|
+
}
|
|
87
|
+
export default IndicatorRect;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsx as _jsx}from"react/jsx-runtime";import{Component}from"react";import{EventEmitterContext}from"../core/EventEmitterContext";import{IndicatorColor}from"../core/IndicatorColor";export{IndicatorColor};export class IndicatorRect extends Component{constructor(t){super(t),Object.defineProperty(this,"handleTopicUpdate",{enumerable:!0,configurable:!0,writable:!0,value:t=>{this.setState({currentValue:t})}}),this.state={currentValue:void 0}}componentDidMount(){this.setupSubscriptions()}componentWillUnmount(){}setupSubscriptions(){const{topic:t}=this.props,{subscribe:e}=this.context;t&&e(t,this.handleTopicUpdate)}render(){const{currentValue:t}=this.state,{className:e,style:o,value:r,onColor:n,offColor:i,options:c}=this.props;let a,l=t;void 0!==r&&(l=r),void 0!==c&&c.length>0&&(a=l?c[1]:c[0]);let s=l?n:i;return void 0===l&&(s=IndicatorColor.IndicatorInvalid),_jsx("div",{className:`indicator-rect ${e||""}`,style:{backgroundColor:s,color:"white",width:"100px",height:"100px",display:"flex",alignItems:"center",justifyContent:"center",...o},children:a})}}Object.defineProperty(IndicatorRect,"contextType",{enumerable:!0,configurable:!0,writable:!0,value:EventEmitterContext}),Object.defineProperty(IndicatorRect,"defaultProps",{enumerable:!0,configurable:!0,writable:!0,value:{onColor:IndicatorColor.IndicatorGreen,offColor:"gray"}});export default IndicatorRect;
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Copyright (C) 2024 Automated Design Corp.. All Rights Reserved.
|
|
3
3
|
* Created Date: 2024-04-24 16:01:53
|
|
4
4
|
* -----
|
|
5
|
-
* Last Modified:
|
|
5
|
+
* Last Modified: 2025-01-20 19:15:50
|
|
6
6
|
* -----
|
|
7
7
|
*
|
|
8
8
|
*/
|
|
@@ -20,7 +20,7 @@ import { DataTable } from 'primereact/datatable';
|
|
|
20
20
|
import { Column } from 'primereact/column';
|
|
21
21
|
import { Toolbar } from 'primereact/toolbar';
|
|
22
22
|
import { Button } from 'primereact/button';
|
|
23
|
-
import {
|
|
23
|
+
import { confirmPopup } from 'primereact/confirmpopup';
|
|
24
24
|
import { FileUpload, FileUploadHandlerEvent} from 'primereact/fileupload';
|
|
25
25
|
|
|
26
26
|
import { EventEmitterContext } from '../core/EventEmitterContext';
|
|
@@ -95,6 +95,12 @@ type FileItem = {
|
|
|
95
95
|
* The component uses the `EventEmitterContext` to make API calls to a backend to list, download, and delete files.
|
|
96
96
|
* It dynamically handles file operations based on the `domain` prop which determines the API endpoints for these actions.
|
|
97
97
|
*
|
|
98
|
+
* Requires
|
|
99
|
+
* ```tsx
|
|
100
|
+
* <ConfirmPopup />
|
|
101
|
+
* ```
|
|
102
|
+
* somewhere in a top-level page.
|
|
103
|
+
*
|
|
98
104
|
* Props:
|
|
99
105
|
* - `domain` (string): The domain name assigned to the DATASTORE servelet containing the data.
|
|
100
106
|
* Default: "DATASTORE"
|
|
@@ -354,8 +360,7 @@ export const FileList: React.FC<FileListProps> = ({
|
|
|
354
360
|
return (
|
|
355
361
|
|
|
356
362
|
<div>
|
|
357
|
-
<Toolbar start={toolbarStartContents} end={toolbarEndContents} style={{ padding: "1mm" }} />
|
|
358
|
-
<ConfirmPopup />
|
|
363
|
+
<Toolbar start={toolbarStartContents} end={toolbarEndContents} style={{ padding: "1mm" }} />
|
|
359
364
|
<DataTable value={files}>
|
|
360
365
|
<Column field="name" header="Name"></Column>
|
|
361
366
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Copyright (C) 2024 Automated Design Corp.. All Rights Reserved.
|
|
3
3
|
* Created Date: 2024-04-28 16:06:59
|
|
4
4
|
* -----
|
|
5
|
-
* Last Modified: 2024-
|
|
5
|
+
* Last Modified: 2024-06-12 14:40:20
|
|
6
6
|
* -----
|
|
7
7
|
*
|
|
8
8
|
*/
|
|
@@ -18,6 +18,8 @@ import { EventEmitterContext } from "../core/EventEmitterContext";
|
|
|
18
18
|
type FileSelectProps = {
|
|
19
19
|
domain?: string,
|
|
20
20
|
subdir?: string,
|
|
21
|
+
/** Filter results using unix-style patterns. */
|
|
22
|
+
filter?: string | null,
|
|
21
23
|
onFileSelected?: (fileName: string) => void,
|
|
22
24
|
onAccept?: (fileName: string) => void,
|
|
23
25
|
onCancel?: () => void
|
|
@@ -31,6 +33,7 @@ type FileItem = {
|
|
|
31
33
|
export const FileSelect: React.FC<FileSelectProps> = ({
|
|
32
34
|
domain = "DATASTORE",
|
|
33
35
|
subdir,
|
|
36
|
+
filter,
|
|
34
37
|
onFileSelected,
|
|
35
38
|
onAccept,
|
|
36
39
|
onCancel
|
|
@@ -41,7 +44,16 @@ export const FileSelect: React.FC<FileSelectProps> = ({
|
|
|
41
44
|
|
|
42
45
|
const listFiles = async () => {
|
|
43
46
|
try {
|
|
44
|
-
|
|
47
|
+
|
|
48
|
+
let args;
|
|
49
|
+
|
|
50
|
+
if (filter !== undefined && filter !== null) {
|
|
51
|
+
args = subdir ? { "subdir": subdir, options : {"filter" : filter }} : {options : {"filter" : filter }};
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
args = subdir ? { "subdir": subdir } : {};
|
|
55
|
+
}
|
|
56
|
+
|
|
45
57
|
const res = await invoke(domain, "list_files", args);
|
|
46
58
|
const items = res.data.map((item: string, index: number) => ({
|
|
47
59
|
id: index + 1,
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (C) 2025 Automated Design Corp.. All Rights Reserved.
|
|
3
|
+
* Created Date: 2025-01-20 15:09:55
|
|
4
|
+
* -----
|
|
5
|
+
* Last Modified: 2025-01-20 15:10:06
|
|
6
|
+
* -----
|
|
7
|
+
*
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { Component } from 'react';
|
|
11
|
+
import { EventEmitterContext, EventEmitterContextType } from '../core/EventEmitterContext';
|
|
12
|
+
import { IndicatorColor } from "../core/IndicatorColor";
|
|
13
|
+
export { IndicatorColor };
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Common properties for an indicator rectangle component.
|
|
17
|
+
* This component is used for displaying states and is not interactive.
|
|
18
|
+
* It is commonly used in industrial HMIs for visual indication purposes.
|
|
19
|
+
*
|
|
20
|
+
* These properties support displaying values of boolean, number, and string states.
|
|
21
|
+
*
|
|
22
|
+
* Available boolean states: **on**, **off**, and **not available**:
|
|
23
|
+
*
|
|
24
|
+
* * `true` is treated as **on**
|
|
25
|
+
* * `false` is treated as **off**
|
|
26
|
+
* * `undefined` is treated as **not available**
|
|
27
|
+
*
|
|
28
|
+
* Numeric values can be used. When there are 2 or fewer possible states,
|
|
29
|
+
* 0 will be considered false (OFF), anything else will be considered true (ON).
|
|
30
|
+
* Undefined will be treated as "not available."
|
|
31
|
+
*
|
|
32
|
+
* When the indicator contains more than 2 states, the number will be matched
|
|
33
|
+
* to the available state, in order. More than two states requires usage of the
|
|
34
|
+
* `options` field and declaring more than two states there.
|
|
35
|
+
*
|
|
36
|
+
* If a string state is used, it will be matched exactly to the corresponding
|
|
37
|
+
* label in the `options` field.
|
|
38
|
+
*/
|
|
39
|
+
export interface IndicatorRectProps {
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Topic name to monitor for state indication.
|
|
43
|
+
*/
|
|
44
|
+
topic?: string;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* State to be displayed.
|
|
48
|
+
*/
|
|
49
|
+
value?: boolean | number | string;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Color for the rectangle when the state is TRUE.
|
|
53
|
+
*/
|
|
54
|
+
onColor?: IndicatorColor;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Color for the rectangle when the state is FALSE.
|
|
58
|
+
*/
|
|
59
|
+
offColor?: IndicatorColor;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* An array of string labels to display as the available options.
|
|
63
|
+
*
|
|
64
|
+
* For items with 2 states or less:
|
|
65
|
+
* Index 0 is the label when value is OFF.
|
|
66
|
+
* Index 1 is the label when value is ON.
|
|
67
|
+
*
|
|
68
|
+
* If only one value is given (Index 0), then that value is used for all states.
|
|
69
|
+
*/
|
|
70
|
+
options?: string[];
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Additional CSS class name to apply to the rectangle.
|
|
74
|
+
*/
|
|
75
|
+
className?: string;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Additional inline styles to apply to the rectangle.
|
|
79
|
+
*/
|
|
80
|
+
style?: React.CSSProperties;
|
|
81
|
+
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
interface IndicatorRectState {
|
|
85
|
+
currentValue?: boolean | number | string;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export class IndicatorRect extends Component<IndicatorRectProps, IndicatorRectState> {
|
|
89
|
+
static contextType = EventEmitterContext;
|
|
90
|
+
|
|
91
|
+
// Define default props
|
|
92
|
+
static defaultProps = {
|
|
93
|
+
onColor: IndicatorColor.IndicatorGreen,
|
|
94
|
+
offColor: "gray", // Default offColor
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
constructor(props: IndicatorRectProps) {
|
|
98
|
+
super(props);
|
|
99
|
+
this.state = {
|
|
100
|
+
currentValue: undefined,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
componentDidMount() {
|
|
105
|
+
this.setupSubscriptions();
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
componentWillUnmount() {
|
|
109
|
+
// Unsubscribe logic if needed
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Sets up subscriptions based on the provided topic.
|
|
114
|
+
*/
|
|
115
|
+
private setupSubscriptions() {
|
|
116
|
+
const { topic } = this.props;
|
|
117
|
+
const { subscribe } = this.context as EventEmitterContextType;
|
|
118
|
+
|
|
119
|
+
if (topic) {
|
|
120
|
+
subscribe(topic, this.handleTopicUpdate);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Handles updates for the main topic.
|
|
126
|
+
*/
|
|
127
|
+
private handleTopicUpdate = (value: boolean | number | string) => {
|
|
128
|
+
this.setState({ currentValue: value });
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
render() {
|
|
132
|
+
const { currentValue } = this.state;
|
|
133
|
+
const { className, style, value, onColor, offColor, options } = this.props;
|
|
134
|
+
|
|
135
|
+
// Load the value from the proper source
|
|
136
|
+
let displayValue = currentValue;
|
|
137
|
+
if (value !== undefined) {
|
|
138
|
+
displayValue = value;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Determine the label and color based on the current state
|
|
142
|
+
let rectLabel = undefined;
|
|
143
|
+
if (options !== undefined && options.length > 0) {
|
|
144
|
+
rectLabel = displayValue ? options[1] : options[0];
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
let color = displayValue ? onColor : offColor;
|
|
148
|
+
if (displayValue === undefined) {
|
|
149
|
+
color = IndicatorColor.IndicatorInvalid;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return (
|
|
153
|
+
<div
|
|
154
|
+
className={`indicator-rect ${className || ""}`}
|
|
155
|
+
style={{
|
|
156
|
+
backgroundColor: color,
|
|
157
|
+
color: "white",
|
|
158
|
+
width: "100px",
|
|
159
|
+
height: "100px",
|
|
160
|
+
display: "flex",
|
|
161
|
+
alignItems: "center",
|
|
162
|
+
justifyContent: "center",
|
|
163
|
+
...style,
|
|
164
|
+
}}
|
|
165
|
+
>
|
|
166
|
+
{rectLabel}
|
|
167
|
+
</div>
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export default IndicatorRect;
|