nayota-show-sdk 1.3.80 → 1.3.82
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/package.json +1 -1
- package/utils/iot-module-specs.js +70 -14
- package/utils/iot-module-specs.test.js +72 -0
package/package.json
CHANGED
|
@@ -90,7 +90,20 @@ function mapAreaToIotQuery(query = {}) {
|
|
|
90
90
|
return next
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
function
|
|
93
|
+
function resolveOptionalLegacyReference(data, primaryKey, legacyKey) {
|
|
94
|
+
if (hasOwn(data, primaryKey)) {
|
|
95
|
+
return data[primaryKey]
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (hasOwn(data, legacyKey)) {
|
|
99
|
+
return resolveLegacyReference(data[legacyKey])
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return undefined
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function mapAreaToIotBody(data = {}, options = {}) {
|
|
106
|
+
const isPartial = options.partial === true
|
|
94
107
|
const metadata = mergeMetadata(data.metadata, {
|
|
95
108
|
legacyType: data.type
|
|
96
109
|
})
|
|
@@ -108,13 +121,13 @@ function mapAreaToIotBody(data = {}) {
|
|
|
108
121
|
'relationInfo',
|
|
109
122
|
'centerCoordinate'
|
|
110
123
|
]),
|
|
111
|
-
code: data.code || fallbackCode(data.name || data._id, 'SPACE'),
|
|
112
|
-
spaceType: data.spaceType || 'zone',
|
|
124
|
+
code: data.code || (isPartial ? undefined : fallbackCode(data.name || data._id, 'SPACE')),
|
|
125
|
+
spaceType: data.spaceType || (isPartial ? undefined : 'zone'),
|
|
113
126
|
hierarchyId: data.hierarchyId || data.depart,
|
|
114
127
|
isVisible: data.isVisible != null ? data.isVisible : data.visible,
|
|
115
128
|
area: data.area != null ? data.area : data.areaSize,
|
|
116
|
-
areaClassId: data
|
|
117
|
-
targetHierarchyId: data
|
|
129
|
+
areaClassId: resolveOptionalLegacyReference(data, 'areaClassId', 'areaClass'),
|
|
130
|
+
targetHierarchyId: resolveOptionalLegacyReference(data, 'targetHierarchyId', 'targetDepartId'),
|
|
118
131
|
centerPoint: normalizeAreaCenterPoint(data),
|
|
119
132
|
floorPlan: normalizeAreaFloorPlan(data),
|
|
120
133
|
statisticsJson: parseLegacyJson(data.statisticsJson),
|
|
@@ -739,6 +752,35 @@ function mapIotDeviceClassToLegacy(item = {}) {
|
|
|
739
752
|
})
|
|
740
753
|
}
|
|
741
754
|
|
|
755
|
+
const LEGACY_CAMERA_DEVICE_CLASS = Object.freeze({
|
|
756
|
+
_id: 'camera',
|
|
757
|
+
id: 'camera',
|
|
758
|
+
name: '摄像头',
|
|
759
|
+
icon: '摄像头监控',
|
|
760
|
+
type: 'camera'
|
|
761
|
+
})
|
|
762
|
+
|
|
763
|
+
function appendLegacyCameraDeviceClass(response = {}) {
|
|
764
|
+
const rows = Array.isArray(response?.data?.rows) ? response.data.rows : []
|
|
765
|
+
const hasCameraType = rows.some(item => getLegacyId(item) === LEGACY_CAMERA_DEVICE_CLASS._id)
|
|
766
|
+
|
|
767
|
+
if (hasCameraType) {
|
|
768
|
+
return response
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
return {
|
|
772
|
+
...response,
|
|
773
|
+
data: {
|
|
774
|
+
...response.data,
|
|
775
|
+
total: Number(response?.data?.total ?? rows.length) + 1,
|
|
776
|
+
rows: [
|
|
777
|
+
...rows,
|
|
778
|
+
{ ...LEGACY_CAMERA_DEVICE_CLASS }
|
|
779
|
+
]
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
|
|
742
784
|
function createBasicCrudOperations({
|
|
743
785
|
resource,
|
|
744
786
|
mapListQuery = query => query,
|
|
@@ -764,7 +806,7 @@ function createBasicCrudOperations({
|
|
|
764
806
|
return {
|
|
765
807
|
url: resource,
|
|
766
808
|
method: 'post',
|
|
767
|
-
data: mapWritePayload(data)
|
|
809
|
+
data: mapWritePayload(data, { partial: false, action: 'create' })
|
|
768
810
|
}
|
|
769
811
|
},
|
|
770
812
|
fromResponse(response) {
|
|
@@ -787,7 +829,7 @@ function createBasicCrudOperations({
|
|
|
787
829
|
return {
|
|
788
830
|
url: `${resource}/${getLegacyId(data)}`,
|
|
789
831
|
method: 'patch',
|
|
790
|
-
data: omitKeys(mapWritePayload(data), ['id', '_id'])
|
|
832
|
+
data: omitKeys(mapWritePayload(data, { partial: true, action: 'updateOne' }), ['id', '_id'])
|
|
791
833
|
}
|
|
792
834
|
},
|
|
793
835
|
fromResponse(response) {
|
|
@@ -830,6 +872,26 @@ function createBasicCrudOperations({
|
|
|
830
872
|
return operations
|
|
831
873
|
}
|
|
832
874
|
|
|
875
|
+
function createDeviceClassOperations() {
|
|
876
|
+
const operations = createBasicCrudOperations({
|
|
877
|
+
resource: '/digital-twin-types',
|
|
878
|
+
mapListQuery: mapDeviceClassToIotQuery,
|
|
879
|
+
mapWritePayload: mapDeviceClassToIotBody,
|
|
880
|
+
mapItem: mapIotDeviceClassToLegacy,
|
|
881
|
+
enableDeleteMany: true
|
|
882
|
+
})
|
|
883
|
+
const fromListResponse = operations.list.fromResponse
|
|
884
|
+
|
|
885
|
+
operations.list = {
|
|
886
|
+
...operations.list,
|
|
887
|
+
fromResponse(response) {
|
|
888
|
+
return appendLegacyCameraDeviceClass(fromListResponse(response))
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
return operations
|
|
893
|
+
}
|
|
894
|
+
|
|
833
895
|
export const iotModuleSpecs = {
|
|
834
896
|
area: {
|
|
835
897
|
operations: createBasicCrudOperations({
|
|
@@ -925,13 +987,7 @@ export const iotModuleSpecs = {
|
|
|
925
987
|
}
|
|
926
988
|
},
|
|
927
989
|
deviceClass: {
|
|
928
|
-
operations:
|
|
929
|
-
resource: '/digital-twin-types',
|
|
930
|
-
mapListQuery: mapDeviceClassToIotQuery,
|
|
931
|
-
mapWritePayload: mapDeviceClassToIotBody,
|
|
932
|
-
mapItem: mapIotDeviceClassToLegacy,
|
|
933
|
-
enableDeleteMany: true
|
|
934
|
-
})
|
|
990
|
+
operations: createDeviceClassOperations()
|
|
935
991
|
}
|
|
936
992
|
}
|
|
937
993
|
|
|
@@ -119,6 +119,52 @@ describe('iotModuleSpecs deviceClass UI compatibility', () => {
|
|
|
119
119
|
|
|
120
120
|
expect(response.data.rows[0].icon).toBe('tabler-current-panel')
|
|
121
121
|
})
|
|
122
|
+
|
|
123
|
+
test('appends legacy virtual camera device class to v2 list responses', () => {
|
|
124
|
+
const response = deviceClass.list.fromResponse({
|
|
125
|
+
code: 0,
|
|
126
|
+
data: {
|
|
127
|
+
total: 1,
|
|
128
|
+
items: [
|
|
129
|
+
{
|
|
130
|
+
id: 'type-1',
|
|
131
|
+
typeCode: 'LIGHT',
|
|
132
|
+
name: '照明'
|
|
133
|
+
}
|
|
134
|
+
]
|
|
135
|
+
}
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
expect(response.data.total).toBe(2)
|
|
139
|
+
expect(response.data.rows).toContainEqual({
|
|
140
|
+
_id: 'camera',
|
|
141
|
+
id: 'camera',
|
|
142
|
+
name: '摄像头',
|
|
143
|
+
icon: '摄像头监控',
|
|
144
|
+
type: 'camera'
|
|
145
|
+
})
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
test('does not duplicate legacy virtual camera device class when backend already returns it', () => {
|
|
149
|
+
const response = deviceClass.list.fromResponse({
|
|
150
|
+
code: 0,
|
|
151
|
+
data: {
|
|
152
|
+
total: 1,
|
|
153
|
+
items: [
|
|
154
|
+
{
|
|
155
|
+
id: 'camera',
|
|
156
|
+
name: '摄像头',
|
|
157
|
+
type: 'camera'
|
|
158
|
+
}
|
|
159
|
+
]
|
|
160
|
+
}
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
const cameraRows = response.data.rows.filter(item => item._id === 'camera')
|
|
164
|
+
|
|
165
|
+
expect(response.data.total).toBe(1)
|
|
166
|
+
expect(cameraRows).toHaveLength(1)
|
|
167
|
+
})
|
|
122
168
|
})
|
|
123
169
|
|
|
124
170
|
describe('iotModuleSpecs departs hierarchy compatibility', () => {
|
|
@@ -189,6 +235,32 @@ describe('iotModuleSpecs area space compatibility', () => {
|
|
|
189
235
|
|
|
190
236
|
expect(response.data.rows[0].centerCoordinate).toEqual([12, 34])
|
|
191
237
|
})
|
|
238
|
+
|
|
239
|
+
test('does not clear areaClassId on partial statistics sync updates', () => {
|
|
240
|
+
const request = area.updateOne.toRequest({
|
|
241
|
+
_id: '4f168184-9ef0-4068-b494-2ee861db0c08',
|
|
242
|
+
statisticsJson: '[{"componentName":"WeeklyEnergyConsumptionTrend"}]'
|
|
243
|
+
})
|
|
244
|
+
|
|
245
|
+
expect(request.url).toBe('/spaces/4f168184-9ef0-4068-b494-2ee861db0c08')
|
|
246
|
+
expect(request.method).toBe('patch')
|
|
247
|
+
expect(request.data.statisticsJson).toEqual([
|
|
248
|
+
{ componentName: 'WeeklyEnergyConsumptionTrend' }
|
|
249
|
+
])
|
|
250
|
+
expect(request.data.areaClassId).toBeUndefined()
|
|
251
|
+
expect(request.data.targetHierarchyId).toBeUndefined()
|
|
252
|
+
expect(request.data.code).toBeUndefined()
|
|
253
|
+
expect(request.data.spaceType).toBeUndefined()
|
|
254
|
+
})
|
|
255
|
+
|
|
256
|
+
test('keeps explicit areaClass clear on area updates', () => {
|
|
257
|
+
const request = area.updateOne.toRequest({
|
|
258
|
+
_id: '4f168184-9ef0-4068-b494-2ee861db0c08',
|
|
259
|
+
areaClass: ''
|
|
260
|
+
})
|
|
261
|
+
|
|
262
|
+
expect(request.data.areaClassId).toBeNull()
|
|
263
|
+
})
|
|
192
264
|
})
|
|
193
265
|
|
|
194
266
|
describe('iotModuleSpecs devices write compatibility', () => {
|