@ledvance/ui-biz-bundle 1.0.0

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/.babelrc ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "presets": ["module:metro-react-native-babel-preset"],
3
+ "plugins": [
4
+ ["@babel/plugin-proposal-decorators", { "legacy": true }],
5
+ ["module-resolver", {
6
+ "cwd": "babelrc",
7
+ "root": ["./src"],
8
+ "extensions": [
9
+ ".ts",
10
+ ".tsx",
11
+ ".js",
12
+ ".jsx",
13
+ ".json"
14
+ ],
15
+ "alias": {
16
+ "@api": "./src/api",
17
+ "@components": "./src/components",
18
+ "@config": "./src/config",
19
+ "@i18n": "./src/i18n",
20
+ "@models": "./src/models",
21
+ "@res": "./src/res",
22
+ "@utils": "./src/utils"
23
+ }
24
+ }]
25
+ ],
26
+ "env": {
27
+ "production": {
28
+ "plugins": ["transform-remove-console"]
29
+ }
30
+ }
31
+ }
package/.eslintignore ADDED
@@ -0,0 +1,6 @@
1
+ node_modules
2
+ __tests__
3
+ src
4
+ index.js
5
+ index.ios.js
6
+ index.android.js
package/.eslintrc.js ADDED
@@ -0,0 +1,27 @@
1
+ const path = require('path');
2
+
3
+ module.exports = {
4
+ root: true,
5
+ extends: ['tuya/react-native'],
6
+ rules: {
7
+ 'one-var': 0,
8
+ '@typescript-eslint/no-unused-vars': 0,
9
+ 'react/jsx-props-no-spreading': 0,
10
+ },
11
+ settings: {
12
+ 'import/resolver': {
13
+ alias: {
14
+ map: [
15
+ ['@api', path.resolve(__dirname, './src/api')],
16
+ ['@components', path.resolve(__dirname, './src/components')],
17
+ ['@config', path.resolve(__dirname, './src/config')],
18
+ ['@i18n', path.resolve(__dirname, './src/i18n')],
19
+ ['@models', path.resolve(__dirname, './src/models')],
20
+ ['@res', path.resolve(__dirname, './src/res')],
21
+ ['@utils', path.resolve(__dirname, './src/utils')],
22
+ ],
23
+ extensions: ['.ts', '.tsx', '.js', '.jsx', '.json'],
24
+ },
25
+ },
26
+ },
27
+ };
File without changes
package/.prettierrc.js ADDED
@@ -0,0 +1 @@
1
+ module.exports = require('eslint-config-tuya/.prettierrc.js');
package/.versionrc ADDED
@@ -0,0 +1,5 @@
1
+ {
2
+ "commitUrlFormat": "https://github.com/tuya/tuya-panel-demo/commit/{{hash}}",
3
+ "releaseCommitMessageFormat": "chore(release): @template/basic-ts-navigation {{currentTag}}",
4
+ "path": "."
5
+ }
package/package.json ADDED
@@ -0,0 +1,72 @@
1
+ {
2
+ "rnVersion": "5.30",
3
+ "license": "MIT",
4
+ "name": "@ledvance/ui-biz-bundle",
5
+ "pid": [],
6
+ "uiid": "",
7
+ "version": "1.0.0",
8
+ "scripts": {},
9
+ "dependencies": {
10
+ "@ledvance/base": "^1.x",
11
+ "@reduxjs/toolkit": "^1.8.6",
12
+ "@tuya/tuya-panel-api": "^1.12.0",
13
+ "ahooks": "^2.x",
14
+ "buffer": "^6.0.3",
15
+ "dayjs": "^1.11.5",
16
+ "events": "^1.1.1",
17
+ "lodash": "^4.17.19",
18
+ "moment": "^2.20.1",
19
+ "prop-types": "^15.6.1",
20
+ "react": "16.8.3",
21
+ "react-addons-shallow-compare": "^15.6.2",
22
+ "react-native": "0.59.10",
23
+ "react-native-render-html": "^6.3.4",
24
+ "react-native-svg": "5.5.1",
25
+ "react-redux": "^7.2.1",
26
+ "redux": "^4.0.0",
27
+ "redux-actions": "^2.6.1",
28
+ "redux-logger": "^3.0.6",
29
+ "redux-observable": "^1.0.0",
30
+ "redux-thunk": "^2.3.0",
31
+ "rxjs": "^6.3.1",
32
+ "rxjs-compat": "^6.3.1",
33
+ "style-equal": "^1.0.0",
34
+ "tuya-panel-kit": "^4.9.4"
35
+ },
36
+ "devDependencies": {
37
+ "@babel/plugin-proposal-decorators": "^7.12.1",
38
+ "@commitlint/cli": "^11.0.0",
39
+ "@tuya/tuya-panel-patches": "^0.59.10",
40
+ "@types/lodash": "^4.14.137",
41
+ "@types/react": "^16.0.4",
42
+ "@types/react-native": "^0.60.0",
43
+ "@types/react-redux": "^7.1.2",
44
+ "@types/redux": "^3.6.0",
45
+ "@types/redux-actions": "^2.6.1",
46
+ "@types/redux-logger": "^3.0.7",
47
+ "@types/tuya-panel-kit": "^4.7.3",
48
+ "babel-jest": "^22.1.0",
49
+ "babel-plugin-import": "^1.11.0",
50
+ "babel-plugin-module-resolver": "^4.0.0",
51
+ "babel-plugin-transform-decorators-legacy": "^1.3.4",
52
+ "babel-plugin-transform-remove-console": "^6.9.4",
53
+ "commitizen": "^4.2.2",
54
+ "commitlint-config-cz": "^0.13.2",
55
+ "cz-customizable": "^6.3.0",
56
+ "eslint-config-airbnb": "^18.2.1",
57
+ "eslint-config-tuya": "^1.0.0",
58
+ "eslint-import-resolver-alias": "^1.1.2",
59
+ "eslint-import-resolver-react-native": "^0.2.0",
60
+ "eslint-plugin-react-native": "^3.10.0",
61
+ "husky": "^4.3.0",
62
+ "jest": "^22.1.1",
63
+ "metro-react-native-babel-preset": "^0.63.0",
64
+ "react-native-typescript-transformer": "^1.2.13",
65
+ "react-test-renderer": "^16.2.0",
66
+ "standard-version": "^9.0.0",
67
+ "typescript": "^4.1.2"
68
+ },
69
+ "jest": {
70
+ "preset": "react-native"
71
+ }
72
+ }
@@ -0,0 +1,8 @@
1
+ module.exports = {
2
+ getTransformModulePath() {
3
+ return require.resolve('react-native-typescript-transformer');
4
+ },
5
+ getSourceExts() {
6
+ return ['ts', 'tsx'];
7
+ },
8
+ };
@@ -0,0 +1,2 @@
1
+ declare const SwitchHistoryPage: () => JSX.Element;
2
+ export default SwitchHistoryPage;
@@ -0,0 +1,255 @@
1
+ import Page from '@ledvance/base/src/components/Page'
2
+ import {useDeviceInfo} from '@ledvance/base/src/models/modules/NativePropsSlice'
3
+ import React, {useCallback, useEffect} from 'react'
4
+ import I18n from '@ledvance/base/src/i18n'
5
+ import {getSwitchHistoryData, SwitchHistoryUIItemData} from './SwitchHistoryPageActions'
6
+ import res from '@ledvance/base/src/res'
7
+ import {Utils} from 'tuya-panel-kit'
8
+ import {useReactive} from 'ahooks'
9
+ import {FlatList, Image, StyleSheet, Text, View} from 'react-native'
10
+ import Spacer from '@ledvance/base/src/components/Spacer'
11
+ import {RouteProp, useRoute} from '@react-navigation/core'
12
+ import { isEmpty } from 'lodash'
13
+ import Tag from "@ledvance/base/src/components/Tag"
14
+
15
+ const cx = Utils.RatioUtils.convertX
16
+
17
+ type SwitchHistoryPageRouteParams = {
18
+ params: { dpIds: string[], tags?: object }
19
+ }
20
+
21
+ type Props = {
22
+ route: RouteProp<SwitchHistoryPageRouteParams, 'params'>
23
+ }
24
+
25
+ const SwitchHistoryPage = () => {
26
+ const deviceInfo = useDeviceInfo()
27
+ const { dpIds, tags } = useRoute<Props['route']>().params
28
+
29
+ const state = useReactive<SwitchHistoryPageState>({
30
+ refreshing: true,
31
+ refreshType: 'refresh',
32
+ onRefresh: Symbol(),
33
+ data: [],
34
+ dataOffset: 0,
35
+ hasNext: true,
36
+ filterTags: tags ? Object.keys(tags).reduce((pre, cur)=> {
37
+ pre[cur] = false
38
+ return pre
39
+ }, {}) : {}
40
+ })
41
+
42
+ const loadData: (refreshType: RefreshType) => void = useCallback(async refreshType => {
43
+ state.refreshType = refreshType
44
+ if (state.refreshType === 'refresh') {
45
+ state.dataOffset = 0
46
+ state.onRefresh = Symbol()
47
+ } else if (state.hasNext) {
48
+ state.onRefresh = Symbol()
49
+ }
50
+ }, [])
51
+
52
+ const changeFilter = useCallback((v:boolean, tag: string) =>{
53
+ state.filterTags = {
54
+ ...state.filterTags,
55
+ [tag]: v
56
+ }
57
+ }, [])
58
+
59
+ const getRequestIds = useCallback(() =>{
60
+ const tagValue = Object.values(state.filterTags)
61
+ const isAllData = tagValue.every(tag => tag) || tagValue.every(tag => !tag)
62
+ const checkedTags = Object.keys(state.filterTags).reduce((pre:string[], cur) => {
63
+ if(state.filterTags[cur]) pre.push(cur)
64
+ return pre
65
+ }, [])
66
+ return isAllData ? dpIds : checkedTags
67
+ }, [state.filterTags])
68
+
69
+
70
+ useEffect(() => {
71
+ getSwitchHistoryData(deviceInfo.devId, getRequestIds(), state.dataOffset)
72
+ .then(res => {
73
+ state.refreshing = false
74
+ state.data = res.data
75
+ state.dataOffset = res.currentOffset
76
+ state.hasNext = res.hasNext
77
+ })
78
+ }, [state.onRefresh, state.filterTags])
79
+
80
+ return (
81
+ <Page
82
+ backText={deviceInfo.name}
83
+ headlineText={I18n.getLang('history_socket_headline_text')}
84
+ headlineIcon={res.rn_ic_download}>
85
+ <View style={styles.content}>
86
+ <Text style={styles.titleText}>{I18n.getLang('history_contact_sensor_description_text')}</Text>
87
+ <Spacer/>
88
+ {!isEmpty(state.filterTags) && !!state.data.length &&
89
+ <View style={{
90
+ display: 'flex',
91
+ flexDirection: 'row',
92
+ flexWrap: 'wrap',
93
+ marginHorizontal: cx(24),
94
+ marginBottom: cx(12),
95
+ alignSelf: 'flex-start'
96
+ }}>
97
+ {
98
+ Object.keys(state.filterTags)?.map((tag) => {
99
+ return <Tag
100
+ key={tag}
101
+ text={tags && tags[tag]}
102
+ checked={state.filterTags[tag]}
103
+ onCheckedChange={(v) => changeFilter(v, tag)}
104
+ style={{ marginTop: cx(5), marginHorizontal: cx(5) }}
105
+ />
106
+ })
107
+ }
108
+ </View>
109
+ }
110
+ <FlatList
111
+ data={state.data}
112
+ style={styles.list}
113
+ renderItem={({item}) => <SwitchHistoryItem {...{itemData :item, tags}}/>}
114
+ keyExtractor={(_, index) => `${index}`}
115
+ ListFooterComponent={<Spacer/>}
116
+ ListEmptyComponent={(
117
+ <View style={styles.listEmptyView}>
118
+ <Spacer height={cx(26)}/>
119
+ <Image
120
+ style={styles.listEmptyImage}
121
+ source={{uri: res.ldv_timer_empty}}/>
122
+ <Spacer height={cx(14)}/>
123
+ <View style={{flexDirection: 'row', alignItems: 'center'}}>
124
+ <Image style={styles.listEmptyTextIcon} source={{uri: res.ic_info}}/>
125
+ <Spacer width={cx(4)} height={0}/>
126
+ <Text style={styles.listEmptyText}>{I18n.getLang('history_overview_empty_information_text')}</Text>
127
+ </View>
128
+ </View>
129
+ )}
130
+ refreshing={state.refreshing}
131
+ onEndReachedThreshold={.1}
132
+ onRefresh={async () => {
133
+ await loadData('refresh')
134
+ }}
135
+ onEndReached={async () => {
136
+ await loadData('loadMore')
137
+ }}/>
138
+ </View>
139
+ </Page>
140
+ )
141
+ }
142
+
143
+ interface SwitchHistoryItemBean {
144
+ itemData: SwitchHistoryUIItemData
145
+ tags?: object
146
+ }
147
+
148
+ const SwitchHistoryItem = (props: SwitchHistoryItemBean) => {
149
+ const { itemData, tags} = props
150
+ return (
151
+ <View style={styles.switchHistoryItem}>
152
+ <Text style={styles.switchHistoryItemTitle}>{itemData.title}</Text>
153
+ <Spacer height={cx(10)}/>
154
+ {itemData.actions.map((actionData, index) => (
155
+ <View style={styles.switchHistoryItemActionItem} key={`${index}`}>
156
+ <View style={styles.switchHistoryItemActionItemLineGroup}>
157
+ <View style={styles.switchHistoryItemActionItemLine}/>
158
+ <View style={styles.switchHistoryItemActionItemPoint}/>
159
+ <View style={styles.switchHistoryItemActionItemLine}/>
160
+ </View>
161
+ <Spacer width={cx(20)} height={0}/>
162
+ <Text style={styles.switchHistoryItemActionItemText}>{`${actionData.time}`}</Text>
163
+ <Spacer width={cx(20)} height={0}/>
164
+ <Text style={styles.switchHistoryItemActionItemText}>{`${actionData.action}`}</Text>
165
+ {!!tags && <Text style={styles.switchHistoryItemTag}>{tags[actionData.dpId]}</Text>}
166
+ </View>
167
+ ))}
168
+ <Spacer/>
169
+ </View>
170
+ )
171
+ }
172
+
173
+ const styles = StyleSheet.create({
174
+ content: {
175
+ flex: 1,
176
+ },
177
+ list: {
178
+ flex: 1,
179
+ },
180
+ listEmptyView: {
181
+ alignItems: 'center',
182
+ },
183
+ listEmptyImage: {
184
+ width: cx(200),
185
+ height: cx(200),
186
+ },
187
+ listEmptyTextIcon: {
188
+ width: cx(16),
189
+ height: cx(16),
190
+ tintColor: '#000',
191
+ },
192
+ listEmptyText: {
193
+ color: '#000',
194
+ fontSize: cx(12),
195
+ fontFamily: 'helvetica_neue_lt_std_roman',
196
+ },
197
+ titleText: {
198
+ marginHorizontal: cx(24),
199
+ color: '#000',
200
+ fontSize: cx(16),
201
+ fontFamily: 'helvetica_neue_lt_std_roman',
202
+ },
203
+ switchHistoryItem: {
204
+ marginHorizontal: cx(24),
205
+ },
206
+ switchHistoryItemTitle: {
207
+ color: '#000',
208
+ fontSize: cx(18),
209
+ fontFamily: 'helvetica_neue_lt_std_bd',
210
+ },
211
+ switchHistoryItemActionItem: {
212
+ flexDirection: 'row',
213
+ alignItems: 'center',
214
+ },
215
+ switchHistoryItemActionItemLineGroup: {
216
+ alignItems: 'center',
217
+ },
218
+ switchHistoryItemActionItemLine: {
219
+ width: cx(1),
220
+ height: cx(11.5),
221
+ backgroundColor: '#E6E7E8',
222
+ },
223
+ switchHistoryItemActionItemPoint: {
224
+ width: cx(7),
225
+ height: cx(7),
226
+ backgroundColor: '#f60',
227
+ borderRadius: cx(4),
228
+ },
229
+ switchHistoryItemActionItemText: {
230
+ color: '#000',
231
+ fontSize: cx(16),
232
+ fontFamily: 'helvetica_neue_lt_std_roman',
233
+ },
234
+ switchHistoryItemTag:{
235
+ paddingHorizontal: cx(10),
236
+ borderRadius: cx(10),
237
+ backgroundColor: '#cbcbcb',
238
+ marginLeft: cx(5)
239
+ }
240
+ })
241
+
242
+ export default SwitchHistoryPage
243
+
244
+ type RefreshType = 'refresh' | 'loadMore'
245
+
246
+
247
+ interface SwitchHistoryPageState {
248
+ refreshing: boolean
249
+ refreshType: RefreshType
250
+ onRefresh: symbol
251
+ data: SwitchHistoryUIItemData[]
252
+ hasNext: boolean
253
+ dataOffset: number
254
+ filterTags: object
255
+ }
@@ -0,0 +1,13 @@
1
+ import { PagingResult } from '@ledvance/base/src/models/TuyaApi';
2
+ export interface SwitchHistoryUIItemData {
3
+ title: string;
4
+ actions: SwitchHistoryUIItemActionData[];
5
+ }
6
+ export interface SwitchHistoryUIItemActionData {
7
+ date: string;
8
+ time: string;
9
+ action: string;
10
+ }
11
+ declare type getSwitchHistoryDataFunType = (deviceId: string, dpIds: string[], offset: number, limit?: number) => Promise<PagingResult<SwitchHistoryUIItemData[]>>;
12
+ export declare const getSwitchHistoryData: getSwitchHistoryDataFunType;
13
+ export {};
@@ -0,0 +1,54 @@
1
+ import { getDpReportSataData, PagingResult } from '@ledvance/base/src/models/TuyaApi'
2
+ import { groupBy, isEqual, uniqWith } from 'lodash'
3
+ import dayjs from 'dayjs'
4
+ import I18n from '@ledvance/base/src/i18n'
5
+ export interface SwitchHistoryUIItemData {
6
+ title: string
7
+ actions: SwitchHistoryUIItemActionData[]
8
+ }
9
+
10
+ const weekList = {
11
+ Sun: I18n.getLang('timeschedule_add_schedule_weekday7_text'),
12
+ Mon: I18n.getLang('timeschedule_add_schedule_weekday1_text'),
13
+ Tue: I18n.getLang('timeschedule_add_schedule_weekday2_text'),
14
+ Wed: I18n.getLang('timeschedule_add_schedule_weekday3_text'),
15
+ Thu: I18n.getLang('timeschedule_add_schedule_weekday4_text'),
16
+ Fri: I18n.getLang('timeschedule_add_schedule_weekday5_text'),
17
+ Sat: I18n.getLang('timeschedule_add_schedule_weekday6_text'),
18
+ }
19
+
20
+ export interface SwitchHistoryUIItemActionData {
21
+ date: string
22
+ time: string
23
+ action: string
24
+ dpId: string
25
+ }
26
+
27
+ type getSwitchHistoryDataFunType = (deviceId: string, dpIds: string[], offset: number, limit?: number) => Promise<PagingResult<SwitchHistoryUIItemData[]>>
28
+
29
+ export const getSwitchHistoryData: getSwitchHistoryDataFunType = async (deviceId: string, dpIds: string[], offset: number, limit: number = 100) => {
30
+ const res = await getDpReportSataData(deviceId, dpIds, 0, offset + limit)
31
+ const uniqData = uniqWith(res.dps, isEqual)
32
+ const dateActionsMap = groupBy(uniqData.map(dpData => {
33
+ const dayjsDate = dayjs(dpData.timeStr)
34
+ return {
35
+ date: `${dayjsDate.format('DD/MM/YYYY')} (${weekList[dayjsDate.format('ddd')]})`,
36
+ time: dayjsDate.format('HH:mm:ss'),
37
+ action: I18n.formatValue(dpData.value === 'true' ? 'history_powerstrip_field1_text' : 'history_powerstrip_field1_text2', '', ''),
38
+ dpId: dpData.dpId,
39
+ }
40
+ }), 'date')
41
+ const data: SwitchHistoryUIItemData[] = Object.keys(dateActionsMap).map(key => {
42
+ return {
43
+ title: key,
44
+ actions: dateActionsMap[key],
45
+ }
46
+ })
47
+ const result: PagingResult<SwitchHistoryUIItemData[]> = {
48
+ data: data,
49
+ hasNext: res.hasNext,
50
+ currentOffset: res.dps.length,
51
+ }
52
+ console.log(result)
53
+ return result
54
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "compilerOptions": {
3
+ /* Basic Options */
4
+ "target": "ES2017",
5
+ /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */
6
+ "module": "commonjs",
7
+ /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
8
+ "jsx": "react",
9
+ /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
10
+
11
+ /* Strict Type-Checking Options */
12
+ /* "strict": true /* Enable all strict type-checking options. */
13
+ "noImplicitAny": false,
14
+ /* Raise error on expressions and declarations with an implied 'any' type. */
15
+ "strictNullChecks": true,
16
+ /* Enable strict null checks. */
17
+
18
+ /* Additional Checks */
19
+ "noUnusedLocals": true,
20
+ /* Report errors on unused locals. */
21
+ "noUnusedParameters": true,
22
+ /* Report errors on unused parameters. */
23
+
24
+ /* .d.ts config */
25
+ "declaration": true,
26
+ "emitDeclarationOnly": true,
27
+
28
+ /* Module Resolution Options */
29
+ "moduleResolution": "node",
30
+ /* Specify module resolution strategy: 'node' (Node.js) or 'classic' */
31
+ "types": ["react", "react-native"],
32
+ /* Type declaration files to be included in compilation. */
33
+ "typeRoots": ["@types/*.d.ts"],
34
+ "allowSyntheticDefaultImports": true,
35
+ /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
36
+ "esModuleInterop": true,
37
+ /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
38
+ "baseUrl": "./src",
39
+ "paths": {
40
+ "@api": ["./api"],
41
+ "@components": ["./components"],
42
+ "@config": ["./config"],
43
+ "@i18n": ["./i18n"],
44
+ "@models": ["./models"],
45
+ "@res": ["./res"],
46
+ "@utils": ["./utils"]
47
+ }
48
+ },
49
+ "include": ["src/**/*.ts","src/**/*.tsx"],
50
+ "exclude": ["node_modules",".yalc"]
51
+ }