@iobroker/adapter-react-v5 0.0.2

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.
Files changed (264) hide show
  1. package/Components/404.js +155 -0
  2. package/Components/404.js.map +1 -0
  3. package/Components/ColorPicker.js +313 -0
  4. package/Components/ColorPicker.js.map +1 -0
  5. package/Components/ComplexCron.js +606 -0
  6. package/Components/ComplexCron.js.map +1 -0
  7. package/Components/FileBrowser.js +2147 -0
  8. package/Components/FileBrowser.js.map +1 -0
  9. package/Components/FileViewer.js +245 -0
  10. package/Components/FileViewer.js.map +1 -0
  11. package/Components/Icon.js +234 -0
  12. package/Components/Icon.js.map +1 -0
  13. package/Components/IconPicker.js +188 -0
  14. package/Components/IconPicker.js.map +1 -0
  15. package/Components/IconSelector.js +337 -0
  16. package/Components/IconSelector.js.map +1 -0
  17. package/Components/Image.js +215 -0
  18. package/Components/Image.js.map +1 -0
  19. package/Components/Loader.js +134 -0
  20. package/Components/Loader.js.map +1 -0
  21. package/Components/Loaders/PT.css +109 -0
  22. package/Components/Loaders/PT.js +104 -0
  23. package/Components/Loaders/PT.js.map +1 -0
  24. package/Components/Loaders/Vendor.css +13 -0
  25. package/Components/Loaders/Vendor.js +108 -0
  26. package/Components/Loaders/Vendor.js.map +1 -0
  27. package/Components/Logo.js +230 -0
  28. package/Components/Logo.js.map +1 -0
  29. package/Components/MDUtils.js +141 -0
  30. package/Components/MDUtils.js.map +1 -0
  31. package/Components/ObjectBrowser.js +6119 -0
  32. package/Components/ObjectBrowser.js.map +1 -0
  33. package/Components/Router.js +152 -0
  34. package/Components/Router.js.map +1 -0
  35. package/Components/SaveCloseButtons.js +177 -0
  36. package/Components/SaveCloseButtons.js.map +1 -0
  37. package/Components/Schedule.js +1891 -0
  38. package/Components/Schedule.js.map +1 -0
  39. package/Components/SelectWithIcon.js +235 -0
  40. package/Components/SelectWithIcon.js.map +1 -0
  41. package/Components/SimpleCron/cron2text.js +563 -0
  42. package/Components/SimpleCron/cron2text.js.map +1 -0
  43. package/Components/SimpleCron/cronText.js +60 -0
  44. package/Components/SimpleCron/cronText.js.map +1 -0
  45. package/Components/SimpleCron/index.js +861 -0
  46. package/Components/SimpleCron/index.js.map +1 -0
  47. package/Components/SimpleCron/jquery.cron.locale.js +322 -0
  48. package/Components/SimpleCron/jquery.cron.locale.js.map +1 -0
  49. package/Components/TabContainer.js +108 -0
  50. package/Components/TabContainer.js.map +1 -0
  51. package/Components/TabContent.js +96 -0
  52. package/Components/TabContent.js.map +1 -0
  53. package/Components/TabHeader.js +72 -0
  54. package/Components/TabHeader.js.map +1 -0
  55. package/Components/TextWithIcon.js +148 -0
  56. package/Components/TextWithIcon.js.map +1 -0
  57. package/Components/ToggleThemeMenu.js +49 -0
  58. package/Components/ToggleThemeMenu.js.map +1 -0
  59. package/Components/TreeTable.js +1030 -0
  60. package/Components/TreeTable.js.map +1 -0
  61. package/Components/Utils.js +1763 -0
  62. package/Components/Utils.js.map +1 -0
  63. package/Components/copy-to-clipboard.js +183 -0
  64. package/Components/copy-to-clipboard.js.map +1 -0
  65. package/Components/loader.css +222 -0
  66. package/Components/types.d.ts +121 -0
  67. package/Connection.js +3334 -0
  68. package/Connection.js.map +1 -0
  69. package/Dialogs/ComplexCron.js +193 -0
  70. package/Dialogs/ComplexCron.js.map +1 -0
  71. package/Dialogs/Confirm.js +211 -0
  72. package/Dialogs/Confirm.js.map +1 -0
  73. package/Dialogs/Cron.js +254 -0
  74. package/Dialogs/Cron.js.map +1 -0
  75. package/Dialogs/Error.js +137 -0
  76. package/Dialogs/Error.js.map +1 -0
  77. package/Dialogs/Message.js +118 -0
  78. package/Dialogs/Message.js.map +1 -0
  79. package/Dialogs/SelectID.js +313 -0
  80. package/Dialogs/SelectID.js.map +1 -0
  81. package/Dialogs/SimpleCron.js +177 -0
  82. package/Dialogs/SimpleCron.js.map +1 -0
  83. package/Dialogs/TextInput.js +194 -0
  84. package/Dialogs/TextInput.js.map +1 -0
  85. package/GenericApp.js +1022 -0
  86. package/GenericApp.js.map +1 -0
  87. package/LICENSE +22 -0
  88. package/Prompt.js +21 -0
  89. package/Prompt.js.map +1 -0
  90. package/README.md +645 -0
  91. package/Theme.js +422 -0
  92. package/Theme.js.map +1 -0
  93. package/assets/devices/Alarm Systems.svg +19 -0
  94. package/assets/devices/Amplifier.svg +22 -0
  95. package/assets/devices/Awnings.svg +5 -0
  96. package/assets/devices/Battery Status.svg +5 -0
  97. package/assets/devices/Ceiling Spotlights.svg +16 -0
  98. package/assets/devices/Chandelier.svg +7 -0
  99. package/assets/devices/Climate.svg +12 -0
  100. package/assets/devices/Coffee Makers.svg +6 -0
  101. package/assets/devices/Cold Water.svg +31 -0
  102. package/assets/devices/Computer.svg +21 -0
  103. package/assets/devices/Consumption.svg +8 -0
  104. package/assets/devices/Curtains.svg +43 -0
  105. package/assets/devices/Dishwashers.svg +12 -0
  106. package/assets/devices/Doors.svg +6 -0
  107. package/assets/devices/Doorstep.svg +35 -0
  108. package/assets/devices/Dryer.svg +14 -0
  109. package/assets/devices/Fan.svg +20 -0
  110. package/assets/devices/Floor Lamps.svg +5 -0
  111. package/assets/devices/Garage Doors.svg +9 -0
  112. package/assets/devices/Gates.svg +32 -0
  113. package/assets/devices/Hairdryer.svg +23 -0
  114. package/assets/devices/Handle.svg +6 -0
  115. package/assets/devices/Hanging Lamps.svg +9 -0
  116. package/assets/devices/Heater.svg +44 -0
  117. package/assets/devices/Hoods.svg +12 -0
  118. package/assets/devices/Hot Water.svg +10 -0
  119. package/assets/devices/Humidity.svg +41 -0
  120. package/assets/devices/Iron.svg +5 -0
  121. package/assets/devices/Irrigation.svg +42 -0
  122. package/assets/devices/Led Strip.svg +31 -0
  123. package/assets/devices/Light.svg +30 -0
  124. package/assets/devices/Lightings.svg +46 -0
  125. package/assets/devices/Lock.svg +19 -0
  126. package/assets/devices/Louvre.svg +7 -0
  127. package/assets/devices/Mowing Machine.svg +9 -0
  128. package/assets/devices/Music.svg +13 -0
  129. package/assets/devices/Outdoor Blinds.svg +7 -0
  130. package/assets/devices/People.svg +19 -0
  131. package/assets/devices/Pool.svg +8 -0
  132. package/assets/devices/Power Consumption.svg +13 -0
  133. package/assets/devices/Printer.svg +10 -0
  134. package/assets/devices/Pump.svg +10 -0
  135. package/assets/devices/Receiver.svg +19 -0
  136. package/assets/devices/Sconces.svg +10 -0
  137. package/assets/devices/Security.svg +34 -0
  138. package/assets/devices/Shading.svg +5 -0
  139. package/assets/devices/Shutters.svg +11 -0
  140. package/assets/devices/SmokeDetector.svg +13 -0
  141. package/assets/devices/Sockets.svg +13 -0
  142. package/assets/devices/Speaker.svg +35 -0
  143. package/assets/devices/Stove.svg +12 -0
  144. package/assets/devices/Table Lamps.svg +12 -0
  145. package/assets/devices/Temperature Sensors.svg +28 -0
  146. package/assets/devices/Tv.svg +8 -0
  147. package/assets/devices/Vacuum Cleaner.svg +16 -0
  148. package/assets/devices/Ventilation.svg +12 -0
  149. package/assets/devices/Washing Machines.svg +16 -0
  150. package/assets/devices/Water Consumption.svg +6 -0
  151. package/assets/devices/Water Heater.svg +8 -0
  152. package/assets/devices/Water.svg +40 -0
  153. package/assets/devices/Weather.svg +28 -0
  154. package/assets/devices/Window.svg +8 -0
  155. package/assets/devices/list.json +994 -0
  156. package/assets/devices/names.txt +63 -0
  157. package/assets/devices/parseNames.js +34 -0
  158. package/assets/lamp_ceiling.svg +9 -0
  159. package/assets/lamp_table.svg +8 -0
  160. package/assets/no_icon.svg +9 -0
  161. package/assets/rooms/Anteroom.svg +53 -0
  162. package/assets/rooms/Attic.svg +21 -0
  163. package/assets/rooms/Balcony.svg +13 -0
  164. package/assets/rooms/Barn.svg +6 -0
  165. package/assets/rooms/Basement.svg +5 -0
  166. package/assets/rooms/Bathroom.svg +38 -0
  167. package/assets/rooms/Bedroom.svg +5 -0
  168. package/assets/rooms/Boiler Room.svg +13 -0
  169. package/assets/rooms/Carport.svg +17 -0
  170. package/assets/rooms/Cellar.svg +89 -0
  171. package/assets/rooms/Chamber.svg +9 -0
  172. package/assets/rooms/Corridor.svg +53 -0
  173. package/assets/rooms/Dining Area.svg +37 -0
  174. package/assets/rooms/Dining Room.svg +37 -0
  175. package/assets/rooms/Dining.svg +37 -0
  176. package/assets/rooms/Dressing Room.svg +5 -0
  177. package/assets/rooms/Driveway.svg +15 -0
  178. package/assets/rooms/Entrance.svg +44 -0
  179. package/assets/rooms/Equipment Room.svg +15 -0
  180. package/assets/rooms/Front Yard.svg +64 -0
  181. package/assets/rooms/Gallery.svg +14 -0
  182. package/assets/rooms/Garage.svg +20 -0
  183. package/assets/rooms/Garden.svg +13 -0
  184. package/assets/rooms/Ground Floor.svg +95 -0
  185. package/assets/rooms/Guest Bathroom.svg +33 -0
  186. package/assets/rooms/Guest Room.svg +5 -0
  187. package/assets/rooms/Gym.svg +5 -0
  188. package/assets/rooms/Hall.svg +19 -0
  189. package/assets/rooms/Home Theater.svg +8 -0
  190. package/assets/rooms/Kitchen.svg +18 -0
  191. package/assets/rooms/Laundry Room.svg +12 -0
  192. package/assets/rooms/Living Area.svg +11 -0
  193. package/assets/rooms/Living Room.svg +10 -0
  194. package/assets/rooms/Locker Room.svg +17 -0
  195. package/assets/rooms/Nursery.svg +5 -0
  196. package/assets/rooms/Office.svg +8 -0
  197. package/assets/rooms/Outdoors.svg +7 -0
  198. package/assets/rooms/Playroom.svg +6 -0
  199. package/assets/rooms/Pool.svg +8 -0
  200. package/assets/rooms/Rear Wall.svg +30 -0
  201. package/assets/rooms/Second Floor.svg +95 -0
  202. package/assets/rooms/Shed.svg +16 -0
  203. package/assets/rooms/Sleeping Area.svg +22 -0
  204. package/assets/rooms/Stairway.svg +5 -0
  205. package/assets/rooms/Stairwell.svg +15 -0
  206. package/assets/rooms/Storeroom.svg +5 -0
  207. package/assets/rooms/Summer House.svg +27 -0
  208. package/assets/rooms/Swimming Pool.svg +21 -0
  209. package/assets/rooms/Terrace.svg +7 -0
  210. package/assets/rooms/Toilet.svg +10 -0
  211. package/assets/rooms/Upstairs.svg +6 -0
  212. package/assets/rooms/Wardrobe.svg +60 -0
  213. package/assets/rooms/Washroom.svg +20 -0
  214. package/assets/rooms/Wc.svg +10 -0
  215. package/assets/rooms/Windscreen.svg +60 -0
  216. package/assets/rooms/Workshop.svg +23 -0
  217. package/assets/rooms/Workspace.svg +8 -0
  218. package/assets/rooms/list.json +946 -0
  219. package/assets/rooms/names.txt +60 -0
  220. package/assets/rooms/parseNames.js +34 -0
  221. package/gulpfile.js +113 -0
  222. package/i18n/de.json +280 -0
  223. package/i18n/en.json +280 -0
  224. package/i18n/es.json +267 -0
  225. package/i18n/fr.json +267 -0
  226. package/i18n/it.json +267 -0
  227. package/i18n/nl.json +267 -0
  228. package/i18n/pl.json +267 -0
  229. package/i18n/pt.json +267 -0
  230. package/i18n/ru.json +280 -0
  231. package/i18n/zh-cn.json +267 -0
  232. package/i18n.js +171 -0
  233. package/i18n.js.map +1 -0
  234. package/icons/IconAdapter.js +39 -0
  235. package/icons/IconAdapter.js.map +1 -0
  236. package/icons/IconAlias.js +39 -0
  237. package/icons/IconAlias.js.map +1 -0
  238. package/icons/IconChannel.js +80 -0
  239. package/icons/IconChannel.js.map +1 -0
  240. package/icons/IconClearFilter.js +41 -0
  241. package/icons/IconClearFilter.js.map +1 -0
  242. package/icons/IconClosed.js +39 -0
  243. package/icons/IconClosed.js.map +1 -0
  244. package/icons/IconCopy.js +48 -0
  245. package/icons/IconCopy.js.map +1 -0
  246. package/icons/IconDevice.js +147 -0
  247. package/icons/IconDevice.js.map +1 -0
  248. package/icons/IconDocument.js +39 -0
  249. package/icons/IconDocument.js.map +1 -0
  250. package/icons/IconExpert.js +50 -0
  251. package/icons/IconExpert.js.map +1 -0
  252. package/icons/IconFx.js +39 -0
  253. package/icons/IconFx.js.map +1 -0
  254. package/icons/IconInstance.js +39 -0
  255. package/icons/IconInstance.js.map +1 -0
  256. package/icons/IconLogout.js +50 -0
  257. package/icons/IconLogout.js.map +1 -0
  258. package/icons/IconOpen.js +39 -0
  259. package/icons/IconOpen.js.map +1 -0
  260. package/icons/IconState.js +58 -0
  261. package/icons/IconState.js.map +1 -0
  262. package/index.css +55 -0
  263. package/package.json +42 -0
  264. package/types.d.ts +84 -0
package/README.md ADDED
@@ -0,0 +1,645 @@
1
+ # Help ReactJS classes for adapter config
2
+ ## Getting started
3
+ If you want to create the configuration page with react:
4
+ 1. Create github repo for adapter.
5
+ 2. execute `npx create-react-app src` . It will take a while.
6
+ 3. `cd src`
7
+ 4. Modify package.json file in src directory:
8
+ - Change `name` from `src` to `ADAPTERNAME-admin` (Of course replace `ADAPTERNAME` with yours)
9
+ - Add to devDependencies:
10
+ ```
11
+ "@iobroker/adapter-react": "^1.5.5",
12
+ ```
13
+ Versions can be higher.
14
+ So your src/package.json should look like:
15
+ ```
16
+ {
17
+ "name": "ADAPTERNAME-admin",
18
+ "version": "0.1.0",
19
+ "private": true,
20
+ "dependencies": {
21
+ "clsx": "^1.1.0",
22
+ "react": "^16.13.1",
23
+ "react-dom": "^16.13.1",
24
+ "react-icons": "^3.10.0",
25
+ "react-scripts": "^3.4.4",
26
+ "@iobroker/adapter-react": "^1.5.6",
27
+ "del": "^6.0.0",
28
+ "gulp": "^4.0.2"
29
+ },
30
+ "scripts": {
31
+ "start": "react-scripts start",
32
+ "build": "react-scripts build",
33
+ "test": "react-scripts test",
34
+ "eject": "react-scripts eject"
35
+ },
36
+ "eslintConfig": {
37
+ "extends": "react-app"
38
+ },
39
+ "homepage": ".",
40
+ "browserslist": [
41
+ ">0.2%",
42
+ "not dead",
43
+ "not ie <= 11",
44
+ "not op_mini all"
45
+ ]
46
+ }
47
+ ```
48
+ 5. Call in `src`: `npm install`
49
+ 6. Copy gulpfile.js into `src`: `cp node_modules/@iobroker/adapter-react/gulpfile.js gulpfile.js`
50
+ 7. Start your dummy application `npm run start` for developing or build with `npm run build` and
51
+ copy files in `build` directory to `www` or to `admin`. In the admin you must rename `index.html` to `index_m.html`.
52
+ 8. You can do that with `gulp` tasks: `gulp build`, `gulp copy`, `gulp renameIndex` or `gulp renameTab`
53
+
54
+ ## Development
55
+ 1. Add `socket.io` to `public/index.html`.
56
+ After
57
+
58
+ ```
59
+ <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
60
+ ```
61
+
62
+ insert
63
+
64
+ ```
65
+ <script>
66
+ var script = document.createElement('script');
67
+ window.registerSocketOnLoad = function (cb) {
68
+ window.socketLoadedHandler = cb;
69
+ };
70
+ const parts = (window.location.search || '').replace(/^\?/, '').split('&');
71
+ const query = {};
72
+ parts.forEach(item => {
73
+ const [name, val] = item.split('=');
74
+ query[decodeURIComponent(name)] = val !== undefined ? decodeURIComponent(val) : true;
75
+ });
76
+ script.onload = function () { typeof window.socketLoadedHandler === 'function' && window.socketLoadedHandler(); };
77
+ script.src = window.location.port === '3000' ? window.location.protocol + '//' + (query.host || window.location.hostname) + ':' + (query.port || 8081) + '/lib/js/socket.io.js' : '%PUBLIC_URL%/../../lib/js/socket.io.js';
78
+
79
+ document.head.appendChild(script);
80
+ </script>
81
+ ```
82
+
83
+ 3. Add to App.js constructor initialization for I18n:
84
+ ```
85
+ class App extends GenericApp {
86
+ constructor(props) {
87
+ const extendedProps = {...props};
88
+ extendedProps.encryptedFields = ['pass']; // this parameter will be encrypted and decrypted automatically
89
+ extendedProps.translations = {
90
+ 'en': require('./i18n/en'),
91
+ 'de': require('./i18n/de'),
92
+ 'ru': require('./i18n/ru'),
93
+ 'pt': require('./i18n/pt'),
94
+ 'nl': require('./i18n/nl'),
95
+ 'fr': require('./i18n/fr'),
96
+ 'it': require('./i18n/it'),
97
+ 'es': require('./i18n/es'),
98
+ 'pl': require('./i18n/pl'),
99
+ 'zh-cn': require('./i18n/zh-cn'),
100
+ };
101
+ // get actual admin port
102
+ extendedProps.socket = {port: parseInt(window.location.port, 10)};
103
+
104
+ // Only if close, save buttons are not required at the bottom (e.g. if admin tab)
105
+ // extendedProps.bottomButtons = false;
106
+
107
+ // only for debug purposes
108
+ if (extendedProps.socket.port === 3000) {
109
+ extendedProps.socket.port = 8081;
110
+ }
111
+
112
+ // allow to manage GenericApp the sentry initialisation or do not set the sentryDSN if no sentry available
113
+ extendedProps.sentryDSN = 'https://yyy@sentry.iobroker.net/xx';
114
+
115
+ super(extendedProps);
116
+ }
117
+ ...
118
+ }
119
+ ```
120
+
121
+ 4. Replace `index.js` with following code to support themes:
122
+ ```
123
+ import React from 'react';
124
+ import ReactDOM from 'react-dom';
125
+ import { MuiThemeProvider} from '@material-ui/core/styles';
126
+ import * as serviceWorker from './serviceWorker';
127
+
128
+ import './index.css';
129
+ import App from './App';
130
+ import { version } from '../package.json';
131
+
132
+ import theme from '@iobroker/adapter-react/Theme';
133
+
134
+ console.log('iobroker.scenes@' + version);
135
+ let themeName = window.localStorage ? window.localStorage.getItem('App.theme') || 'light' : 'light';
136
+
137
+ function build() {
138
+ return ReactDOM.render(<MuiThemeProvider theme={ theme(themeName) }>
139
+ <App onThemeChange={_theme => {
140
+ themeName = _theme;
141
+ build();
142
+ }}/>
143
+ </MuiThemeProvider>, document.getElementById('root'));
144
+ }
145
+
146
+ build();
147
+
148
+ // If you want your app to work offline and load faster, you can change
149
+ // unregister() to register() below. Note this comes with some pitfalls.
150
+ // Learn more about service workers: http://bit.ly/CRA-PWA
151
+ serviceWorker.unregister();
152
+ ```
153
+
154
+ 5. Add to App.js encoding and decoding of values:
155
+ ```
156
+ class App extend GenericApp {
157
+ ...
158
+ onPrepareLoad(settings) {
159
+ settings.pass = this.decode(settings.pass);
160
+ }
161
+ onPrepareSave(settings) {
162
+ settings.pass = this.encode(settings.pass);
163
+ }
164
+ }
165
+ ```
166
+
167
+ 6. The optional step to validate the data to be saved:
168
+ ```
169
+ onPrepareSave(settings) {
170
+ super.onPrepareSave(settings);
171
+ if (DATA_INVALID) {
172
+ return false; // configuration will not be saved
173
+ } else {
174
+ return true;
175
+ }
176
+ }
177
+ ```
178
+
179
+ ## Components
180
+
181
+ ### Connection.js
182
+ This is non-react class to provide the communication for socket connection with server.
183
+
184
+ ### GenericApp.js
185
+
186
+ ### i18n.js
187
+
188
+ ### Theme.js
189
+
190
+ ### Dialogs
191
+ Some dialogs are predefined and could be used out of the box.
192
+
193
+ #### Confirm.js
194
+ <!-- TODO: Provide screenshot here -->
195
+
196
+ Usage:
197
+ ```
198
+ import React from 'react';
199
+ import ConfirmDialog from '@iobroker/adapter-react/Dialogs/Confirm'
200
+ import I18n from '@iobroker/adapter-react/i18n';
201
+
202
+ class ExportImportDialog extends React.Component {
203
+ constructor(props) {
204
+ super(props);
205
+
206
+ this.state = {
207
+ confirmDialog: false,
208
+ };
209
+ }
210
+
211
+ renderConfirmDialog() {
212
+ if (!this.state.confirmDialog) {
213
+ return null;
214
+ }
215
+ return <ConfirmDialog
216
+ title={ I18n.t('Scene will be overwritten.') }
217
+ text={ I18n.t('All data will be lost. Confirm?') }
218
+ ok={ I18n.t('Yes') }
219
+ cancel={ I18n.t('Cancel') }
220
+ suppressQuestionMinutes={5}
221
+ dialogName="myConfirmDialogThatCouldBeSuppressed"
222
+ suppressText={I18n.t('Suppress question for next %s minutes', 5)}
223
+ onClose={isYes => {
224
+ this.setState({ confirmDialog: false} );
225
+ }}
226
+ />;
227
+ }
228
+ render() {
229
+ return <div>
230
+ <Button onClick={ () => this.setState({confirmDialog: true}) }>Click</Button>
231
+ { this.renderConfirmDialog() }
232
+ </div>
233
+ }
234
+ }
235
+
236
+ export default ExportImportDialog;
237
+ ```
238
+
239
+ #### Error.js
240
+ <!-- TODO: Provide screenshot here -->
241
+
242
+ #### Message.js
243
+ <!-- TODO: Provide screenshot here -->
244
+ ```
245
+ renderMessage() {
246
+ if (this.state.showMessage) {
247
+ return <Message
248
+ text={this.state.showMessage}
249
+ onClose={() => this.setState({showMessage: false})}
250
+ />;
251
+ } else {
252
+ return null;
253
+ }
254
+ }
255
+ ```
256
+
257
+ #### SelectID.js
258
+ ![Logo](img/selectID.png)
259
+ ```
260
+ import DialogSelectID from '@iobroker/adapter-react/Dialogs/SelectID';
261
+
262
+ class MyComponent extends Component {
263
+ constructor(props) {
264
+ super(props);
265
+ this.state = {
266
+ showSelectId: false,
267
+ };
268
+ }
269
+
270
+ renderSelectIdDialog() {
271
+ if (this.state.showSelectId) {
272
+ return <DialogSelectID
273
+ key="tableSelect"
274
+ imagePrefix="../.."
275
+ dialogName={this.props.adapterName}
276
+ themeType={this.props.themeType}
277
+ socket={this.props.socket}
278
+ statesOnly={true}
279
+ selected={this.state.selectIdValue}
280
+ onClose={() => this.setState({showSelectId: false})}
281
+ onOk={(selected, name) => {
282
+ this.setState({showSelectId: false, selectIdValue: selected});
283
+ }}
284
+ />;
285
+ } else {
286
+ return null;
287
+ }
288
+ }
289
+ render() {
290
+ return renderSelectIdDialog();
291
+ }
292
+ }
293
+ ```
294
+
295
+ #### Cron
296
+ Include `"react-text-mask": "^5.4.3",` in package.json.
297
+
298
+ <!-- TODO: Provide screenshot here -->
299
+
300
+ ```
301
+ function renderCron() {
302
+ if (!showCron) {
303
+ return null;
304
+ } else {
305
+ return <DialogCron
306
+ key="dialogCron1"
307
+ cron={this.state.cronValue || '* * * * *'}
308
+ onClose={() => this.setState({ showCron: false })}
309
+ onOk={cronValue => {
310
+ this.setState({ cronValue })
311
+ }}
312
+ />;
313
+ }
314
+ }
315
+ ```
316
+
317
+ ### Components
318
+
319
+ #### Utils.js
320
+ ##### getObjectNameFromObj
321
+ `getObjectNameFromObj(obj, settings, options, isDesc)`
322
+
323
+ Get object name from single object.
324
+
325
+ Usage: `Utils.getObjectNameFromObj(this.objects[id], null, {language: I18n.getLanguage()})`
326
+
327
+ ##### getObjectIcon
328
+ `getObjectIcon(id, obj)`
329
+
330
+ Get icon from the object.
331
+
332
+ Usage:
333
+ ```
334
+ const icon = Utils.getObjectIcon(id, this.objects[id]);
335
+ return (<img src={icon}/>);
336
+ ```
337
+
338
+ ##### isUseBright
339
+ `isUseBright(color, defaultValue)`
340
+
341
+ Usage: `
342
+
343
+ #### Loader.js
344
+ ![Logo](img/loader.png)
345
+
346
+ ```
347
+ render() {
348
+ if (!this.state.loaded) {
349
+ return <MuiThemeProvider theme={this.state.theme}>
350
+ <Loader theme={this.state.themeType}/>
351
+ </MuiThemeProvider>;
352
+ }
353
+ // render loaded data
354
+ }
355
+
356
+ ```
357
+
358
+ #### Logo.js
359
+ ![Logo](img/logo.png)
360
+
361
+ ```
362
+ render() {
363
+ return <form className={this.props.classes.tab}>
364
+ <Logo
365
+ instance={this.props.instance}
366
+ common={this.props.common}
367
+ native={this.props.native}
368
+ onError={text => this.setState({errorText: text})}
369
+ onLoad={this.props.onLoad}
370
+ />
371
+ ...
372
+ </form>;
373
+ }
374
+ ```
375
+
376
+ #### Router.js
377
+
378
+ #### ObjectBrowser.js
379
+ It is better to use `Dialog/SelectID`, but if you want:
380
+
381
+ ![Logo](img/objectBrowser.png)
382
+
383
+ ```
384
+ <ObjectBrowser
385
+ foldersFirst={ this.props.foldersFirst }
386
+ imagePrefix={ this.props.imagePrefix || this.props.prefix } // prefix is for back compatibility
387
+ defaultFilters={ this.filters }
388
+ dialogName={this.dialogName}
389
+ showExpertButton={ this.props.showExpertButton !== undefined ? this.props.showExpertButton : true }
390
+ style={ {width: '100%', height: '100%'} }
391
+ columns={ this.props.columns || ['name', 'type', 'role', 'room', 'func', 'val'] }
392
+ types={ this.props.types || ['state'] }
393
+ t={ I18n.t }
394
+ lang={ this.props.lang || I18n.getLanguage() }
395
+ socket={ this.props.socket }
396
+ selected={ this.state.selected }
397
+ multiSelect={ this.props.multiSelect }
398
+ notEditable={ this.props.notEditable === undefined ? true : this.props.notEditable }
399
+ name={ this.state.name }
400
+ themeName={ this.props.themeName }
401
+ themeType={ this.props.themeType }
402
+ customFilter={ this.props.customFilter }
403
+ onFilterChanged={ filterConfig => {
404
+ this.filters = filterConfig;
405
+ window.localStorage.setItem(this.dialogName, JSON.stringify(filterConfig));
406
+ } }
407
+ onSelect={ (selected, name, isDouble) => {
408
+ if (JSON.stringify(selected) !== JSON.stringify(this.state.selected)) {
409
+ this.setState({selected, name}, () =>
410
+ isDouble && this.handleOk());
411
+ } else if (isDouble) {
412
+ this.handleOk();
413
+ }
414
+ } }
415
+ />
416
+ ```
417
+
418
+ #### TreeTable.js
419
+ ![Logo](img/tableTree.png)
420
+
421
+ ```
422
+ // STYLES
423
+ const styles = theme => ({
424
+ tableDiv: {
425
+ width: '100%',
426
+ overflow: 'hidden',
427
+ height: 'calc(100% - 48px)',
428
+ },
429
+ });
430
+ class MyComponent extends Component {
431
+ constructor(props) {
432
+ super(props);
433
+
434
+ this.state = {
435
+ data: [
436
+ {
437
+ id: 'UniqueID1' // required
438
+ fieldIdInData: 'Name1',
439
+ myType: 'number',
440
+ },
441
+ {
442
+ id: 'UniqueID2' // required
443
+ fieldIdInData: 'Name12',
444
+ myType: 'string',
445
+ },
446
+ ],
447
+ };
448
+
449
+ this.columns = [
450
+ {
451
+ title: 'Name of field', // required, else it will be "field"
452
+ field: 'fieldIdInData', // required
453
+ editable: false, // or true [default - true]
454
+ cellStyle: { // CSS style - // optional
455
+ maxWidth: '12rem',
456
+ overflow: 'hidden',
457
+ wordBreak: 'break-word'
458
+ },
459
+ lookup: { // optional => edit will be automatically "SELECT"
460
+ 'value1': 'text1',
461
+ 'value2': 'text2',
462
+ }
463
+ },
464
+ {
465
+ title: 'Type', // required, else it will be "field"
466
+ field: 'myType', // required
467
+ editable: true, // or true [default - true]
468
+ lookup: { // optional => edit will be automatically "SELECT"
469
+ 'number': 'Number',
470
+ 'string': 'String',
471
+ 'boolean': 'Boolean',
472
+ },
473
+ type: 'number/string/color/oid/icon/boolean', // oid=ObjectID,icon=base64-icon
474
+ editComponent: props =>
475
+ <div>Prefix&#123; <br/>
476
+ <textarea
477
+ rows={4}
478
+ style={{width: '100%', resize: 'vertical'}}
479
+ value={props.value}
480
+ onChange={e => props.onChange(e.target.value)}
481
+ />
482
+ Suffix
483
+ </div>,
484
+ },
485
+ ];
486
+ }
487
+ // renderTable
488
+ render() {
489
+ return <div className={this.props.classes.tableDiv}>
490
+ <TreeTable
491
+ columns={this.columns}
492
+ data={this.state.data}
493
+ onUpdate={(newData, oldData) => {
494
+ const data = JSON.parse(JSON.stringify(this.state.data));
495
+
496
+ // Added new line
497
+ if (newData === true) {
498
+ // find unique ID
499
+ let i = 1;
500
+ let id = 'line_' + i;
501
+
502
+ // eslint-disable-next-line
503
+ while(this.state.data.find(item => item.id === id)) {
504
+ i++;
505
+ id = 'line_' + i;
506
+ }
507
+
508
+ data.push({
509
+ id,
510
+ name: I18n.t('New resource') + '_' + i,
511
+ color: '',
512
+ icon: '',
513
+ unit: '',
514
+ price: 0,
515
+ });
516
+ } else {
517
+ // existing line was modifed
518
+ const pos = this.state.data.indexOf(oldData);
519
+ if (pos !== -1) {
520
+ Object.keys(newData).forEach(attr => data[pos][attr] = newData[attr]);
521
+ }
522
+ }
523
+
524
+ this.setState({data});
525
+ }}
526
+ onDelete={oldData => {
527
+ console.log('Delete: ' + JSON.stringify(oldData));
528
+ const pos = this.state.data.indexOf(oldData);
529
+ if (pos !== -1) {
530
+ const data = JSON.parse(JSON.stringify(this.state.data));
531
+ data.splice(pos, 1);
532
+ this.setState({data});
533
+ }
534
+ }}
535
+ />
536
+ </div>;
537
+ }
538
+ }
539
+ ```
540
+
541
+ #### Toast
542
+ <!-- TODO: Provide screenshot here -->
543
+
544
+ Toast is not a part of `adapter-react` but it is an example how to use toast in application:
545
+
546
+ ```
547
+ import Snackbar from '@material-ui/core/Snackbar';
548
+
549
+ class MyComponent {
550
+ constructor(props) {
551
+ super(props);
552
+ this.state = {
553
+ // ....
554
+ toast: '',
555
+ };
556
+ }
557
+ // ...
558
+ renderToast() {
559
+ if (!this.state.toast) {
560
+ return null;
561
+ }
562
+ return <Snackbar
563
+ anchorOrigin={{
564
+ vertical: 'bottom',
565
+ horizontal: 'left',
566
+ }}
567
+ open={true}
568
+ autoHideDuration={6000}
569
+ onClose={() => this.setState({toast: ''})}
570
+ ContentProps={{'aria-describedby': 'message-id'}}
571
+ message={<span id="message-id">{this.state.toast}</span>}
572
+ action={[
573
+ <IconButton
574
+ key="close"
575
+ aria-label="Close"
576
+ color="inherit"
577
+ className={this.props.classes.close}
578
+ onClick={() => this.setState({toast: ''})}
579
+ >
580
+ <IconClose />
581
+ </IconButton>,
582
+ ]}
583
+ />;
584
+ }
585
+ render() {
586
+ return <div>
587
+ {this.renderToast()}
588
+ </div>;
589
+ }
590
+ }
591
+ ```
592
+
593
+ ## List of adapters, that uses adapter-react
594
+ - Admin
595
+ - iot
596
+ - echarts
597
+ - text2command
598
+ - scenes
599
+ - javascript
600
+ - devices
601
+ - eventlist
602
+
603
+ ## Usability
604
+ In dialogs the OK button is first (on the left) and the cancel button is last (on the right)
605
+
606
+ ## Used icons
607
+ This project uses icons from [Flaticon](https://www.flaticon.com/).
608
+
609
+ ioBroker GmbH has a valid license for all of used icons.
610
+ The icons may not be reused in other projects without the proper flaticon license or flaticon subscription.
611
+
612
+ <!--
613
+ Placeholder for the next version (at the beginning of the line):
614
+ ### __WORK IN PROGRESS__
615
+ -->
616
+
617
+ ## Changelog
618
+ ### 0.0.2 (2022-02-24)
619
+ * (bluefox) try to publish first version
620
+
621
+ ### 0.0.1 (2022-02-24)
622
+ * initial commit
623
+
624
+ ## License
625
+ The MIT License (MIT)
626
+
627
+ Copyright (c) 2019-2022 bluefox <dogafox@gmail.com>
628
+
629
+ Permission is hereby granted, free of charge, to any person obtaining a copy
630
+ of this software and associated documentation files (the "Software"), to deal
631
+ in the Software without restriction, including without limitation the rights
632
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
633
+ copies of the Software, and to permit persons to whom the Software is
634
+ furnished to do so, subject to the following conditions:
635
+
636
+ The above copyright notice and this permission notice shall be included in all
637
+ copies or substantial portions of the Software.
638
+
639
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
640
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
641
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
642
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
643
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
644
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
645
+ SOFTWARE.