@@ -40,7 +40,7 @@ export abstract class DataClient {
40
40
41
41
abstract invalidateCache ( ) ;
42
42
43
- abstract createApplication ( app : IApplication , blob : Blob ) : Promise < string | number > ;
43
+ abstract createApplication ( app : IApplication , blob ? : Blob ) : Promise < string | number > ;
44
44
abstract createManagedObject ( managedObject : IManagedObject ) : Promise < string | number > ;
45
45
abstract createSimulator ( simulatorConfig : Partial < ISimulatorConfig > ) : Promise < { simulatorId : string , deviceIds : ( string | number ) [ ] } > ;
46
46
abstract createSmartRule ( smartRuleConfig : ISmartRuleConfig ) : Promise < string | number > ;
@@ -57,7 +57,7 @@ export abstract class DataClient {
57
57
}
58
58
) : Promise < void > ;
59
59
60
- abstract updateApplication ( app : IApplication , blob : Blob ) : Promise < string | number > ;
60
+ abstract updateApplication ( app : IApplication , blob ? : Blob ) : Promise < string | number > ;
61
61
abstract updateBinary ( binary : IManagedObject , blob : Blob ) : Promise < string | number > ;
62
62
abstract updateManagedObject ( managedObject : IManagedObject ) : Promise < string | number > ;
63
63
abstract updateSimulator ( simulatorConfig : Partial < ISimulatorConfig > ) : Promise < { simulatorId : string , deviceIds : ( string | number ) [ ] } > ;
@@ -111,100 +111,112 @@ export abstract class DataClient {
111
111
}
112
112
113
113
async findLinkedDashboardsFromApplication ( app : IApplication & { id : string | number ; binary : IManagedObject } , onDownloadProgress ?: ( progress : number ) => any ) : Promise < IManagedObject [ ] > {
114
- const blob = await this . getApplicationBlob ( app , onDownloadProgress ) ;
115
- let zip ;
116
- try {
117
- zip = await JSZip . loadAsync ( blob ) ;
118
- } catch ( e ) {
119
- console . debug ( 'Not a zip file' ) ;
120
- return [ ] ;
121
- }
114
+ // App builder apps include a list of dashboards in a custom field "applicationBuilder.dashboards"
115
+ if ( ( app as any ) . applicationBuilder ) {
116
+ const dashboardIds = ( ( app as any ) . applicationBuilder . dashboards || [ ] ) . map ( dashboard => dashboard . id ) ;
117
+ const dashboardManagedObjects = await this . getDashboards ( ) ;
118
+ return dashboardManagedObjects . filter ( dashboard => dashboardIds . includes ( dashboard . id ) ) ;
119
+ // Other apps might have a zip file containing some js and html files that indicate which dashboards to use
120
+ } else {
121
+ const blob = await this . getApplicationBlob ( app , onDownloadProgress ) ;
122
+
123
+ // If there's no blob then the app has no binary
124
+ if ( blob == undefined ) return [ ] ;
125
+
126
+ let zip ;
127
+ try {
128
+ zip = await JSZip . loadAsync ( blob ) ;
129
+ } catch ( e ) {
130
+ console . debug ( 'Not a zip file' ) ;
131
+ return [ ] ;
132
+ }
133
+
134
+ const files = zip . file ( / .* \. ( j s | h t m l ) / ) ;
135
+
136
+ const names = [ ] ;
137
+ const partialNames = [ ] ;
138
+ const ids = [ ] ;
139
+
140
+ await Promise . all (
141
+ files . map ( async ( file ) => {
142
+ const text = await file . async ( 'text' ) ;
143
+ let matches ;
144
+ const nameRegex = / < c 8 y - d a s h b o a r d - g r i d s t a c k [ ^ > ] + ?n a m e = ( [ " ' ] ) ( ( \w | - ) + ?) \1.* ?> / g;
145
+ // noinspection JSAssignmentUsedAsCondition
146
+ while ( matches = nameRegex . exec ( text ) ) {
147
+ names . push ( matches [ 2 ] ) ;
148
+ }
122
149
123
- const files = zip . file ( / .* \. ( j s | h t m l ) / ) ;
124
-
125
- const names = [ ] ;
126
- const partialNames = [ ] ;
127
- const ids = [ ] ;
128
-
129
- await Promise . all (
130
- files . map ( async ( file ) => {
131
- const text = await file . async ( 'text' ) ;
132
- let matches ;
133
- const nameRegex = / < c 8 y - d a s h b o a r d - g r i d s t a c k [ ^ > ] + ?n a m e = ( [ " ' ] ) ( ( \w | - ) + ?) \1.* ?> / g;
134
- // noinspection JSAssignmentUsedAsCondition
135
- while ( matches = nameRegex . exec ( text ) ) {
136
- names . push ( matches [ 2 ] ) ;
137
- }
138
-
139
- const nameCtrlRegex = / d a s h b o a r d [ - _ ] ? [ n N ] a m e = ( [ " ' ] ) ( ( \w | - ) + ?) \1/ g;
140
- // noinspection JSAssignmentUsedAsCondition
141
- while ( matches = nameCtrlRegex . exec ( text ) ) {
142
- partialNames . push ( matches [ 2 ] + '*' ) ;
143
- }
144
-
145
- const nameJsRegex = / c 8 y _ D a s h b o a r d ! n a m e ! ( ( \w | - ) + ) / g;
146
- // noinspection JSAssignmentUsedAsCondition
147
- while ( matches = nameJsRegex . exec ( text ) ) {
148
- partialNames . push ( matches [ 1 ] + '*' ) ;
149
- }
150
-
151
- // If the dashboard name is some combinations of a string and some templates, eg: 'mydashboard-{{vm.dashboardNumber}}' we might be able to guess all of the allGroups associated with an app by finding all 'mydashboard-*'
152
- const partialNameRegex = / < c 8 y - d a s h b o a r d - g r i d s t a c k [ ^ > ] + ?n a m e = ( [ " ' ] ) ( .+ ?) \1.* ?> / g;
153
- // noinspection JSAssignmentUsedAsCondition
154
- while ( matches = partialNameRegex . exec ( text ) ) {
155
- if ( ! nameRegex . test ( matches [ 0 ] ) ) {
156
- const partialName = matches [ 2 ]
157
- . trim ( )
158
- . replace ( / { { .* ?} } / g, '*' ) ; // replace angularjs template string with wildcard matcher
159
- // If the whole expression starts with '::' then it's a single run angular expression so ignore it (we can't find a dashboard from that)
160
- // If the expression has enough (3 or more) non-special characters then we'll assume it might be unique enough to find a dashboard
161
- if ( ! partialName . startsWith ( '::' ) && partialName . replace ( / [ - * _ . : ] / g, '' ) . length >= 3 ) {
162
- partialNames . push ( partialName ) ;
150
+ const nameCtrlRegex = / d a s h b o a r d [ - _ ] ? [ n N ] a m e = ( [ " ' ] ) ( ( \w | - ) + ?) \1/ g;
151
+ // noinspection JSAssignmentUsedAsCondition
152
+ while ( matches = nameCtrlRegex . exec ( text ) ) {
153
+ partialNames . push ( matches [ 2 ] + '*' ) ;
154
+ }
155
+
156
+ const nameJsRegex = / c 8 y _ D a s h b o a r d ! n a m e ! ( ( \w | - ) + ) / g;
157
+ // noinspection JSAssignmentUsedAsCondition
158
+ while ( matches = nameJsRegex . exec ( text ) ) {
159
+ partialNames . push ( matches [ 1 ] + '*' ) ;
160
+ }
161
+
162
+ // If the dashboard name is some combinations of a string and some templates, eg: 'mydashboard-{{vm.dashboardNumber}}' we might be able to guess all of the allGroups associated with an app by finding all 'mydashboard-*'
163
+ const partialNameRegex = / < c 8 y - d a s h b o a r d - g r i d s t a c k [ ^ > ] + ?n a m e = ( [ " ' ] ) ( .+ ?) \1.* ?> / g;
164
+ // noinspection JSAssignmentUsedAsCondition
165
+ while ( matches = partialNameRegex . exec ( text ) ) {
166
+ if ( ! nameRegex . test ( matches [ 0 ] ) ) {
167
+ const partialName = matches [ 2 ]
168
+ . trim ( )
169
+ . replace ( / { { .* ?} } / g, '*' ) ; // replace angularjs template string with wildcard matcher
170
+ // If the whole expression starts with '::' then it's a single run angular expression so ignore it (we can't find a dashboard from that)
171
+ // If the expression has enough (3 or more) non-special characters then we'll assume it might be unique enough to find a dashboard
172
+ if ( ! partialName . startsWith ( '::' ) && partialName . replace ( / [ - * _ . : ] / g, '' ) . length >= 3 ) {
173
+ partialNames . push ( partialName ) ;
174
+ }
163
175
}
164
176
}
165
- }
166
- const idRegex = / < c 8 y - d a s h b o a r d - g r i d s t a c k [ ^ > ] + ? i d = ( [ " ' ] ) ( ( \w | - ) + ? ) \1. * ? > / g ;
167
- // noinspection JSAssignmentUsedAsCondition
168
- while ( matches = idRegex . exec ( text ) ) {
169
- ids . push ( matches [ 2 ] ) ;
170
- }
171
- } ) ) ;
172
-
173
- const dashboardManagedObjects = await this . getDashboards ( ) ;
174
-
175
- return _ . uniqBy ( [
176
- ... _ . flatMap ( names , name => {
177
- const matchingManagedObject = dashboardManagedObjects . find ( mo => mo [ `c8y_Dashboard!name! ${ name } ` ] !== undefined ) ;
178
- if ( matchingManagedObject ) {
179
- console . log ( 'Found dashboard with name' , name , matchingManagedObject ) ;
180
- return [ matchingManagedObject ] ;
181
- } else {
182
- console . error ( 'Unable to find dashboard with name' , name ) ;
183
- return [ ] ;
184
- }
185
- } ) ,
186
- ... _ . flatMap ( ids , id => {
187
- const matchingManagedObject = dashboardManagedObjects . find ( mo => mo . id . toString ( ) === id . toString ( ) ) ;
188
- if ( matchingManagedObject ) {
189
- console . log ( 'Found dashboard with id' , id , matchingManagedObject ) ;
190
- return [ matchingManagedObject ] ;
191
- } else {
192
- console . error ( 'Unable to find dashboard with id' , id ) ;
193
- return [ ] ;
194
- }
195
- } ) ,
196
- ... _ . flatMap ( partialNames , wildCardName => {
197
- const wildCardRegex = RegExp ( '^c8y_Dashboard!name!' + wildCardName . split ( '*' ) . map ( expressionPart => _ . escapeRegExp ( expressionPart ) ) . join ( '.*' ) + '$' ) ;
198
- const matchingManagedObjects = dashboardManagedObjects . filter ( mo => Object . keys ( mo ) . find ( key => wildCardRegex . test ( key ) ) !== undefined ) ;
199
- if ( matchingManagedObjects . length > 0 ) {
200
- console . log ( 'Found allGroups with wild-card name' , wildCardName , matchingManagedObjects ) ;
201
- return matchingManagedObjects ;
202
- } else {
203
- console . error ( 'Unable to find dashboard with wild-card name' , wildCardName ) ;
204
- return [ ] ;
205
- }
206
- } ) ,
207
- ] , dashboard => dashboard . id ) ;
177
+ const idRegex = / < c 8 y - d a s h b o a r d - g r i d s t a c k [ ^ > ] + ? i d = ( [ " ' ] ) ( ( \w | - ) + ? ) \1. * ? > / g ;
178
+ // noinspection JSAssignmentUsedAsCondition
179
+ while ( matches = idRegex . exec ( text ) ) {
180
+ ids . push ( matches [ 2 ] ) ;
181
+ }
182
+ } ) ) ;
183
+
184
+ const dashboardManagedObjects = await this . getDashboards ( ) ;
185
+
186
+ return _ . uniqBy ( [
187
+ ... _ . flatMap ( names , name => {
188
+ const matchingManagedObject = dashboardManagedObjects . find ( mo => mo [ `c8y_Dashboard!name! ${ name } ` ] !== undefined ) ;
189
+ if ( matchingManagedObject ) {
190
+ console . log ( 'Found dashboard with name' , name , matchingManagedObject ) ;
191
+ return [ matchingManagedObject ] ;
192
+ } else {
193
+ console . error ( 'Unable to find dashboard with name' , name ) ;
194
+ return [ ] ;
195
+ }
196
+ } ) ,
197
+ ... _ . flatMap ( ids , id => {
198
+ const matchingManagedObject = dashboardManagedObjects . find ( mo => mo . id . toString ( ) === id . toString ( ) ) ;
199
+ if ( matchingManagedObject ) {
200
+ console . log ( 'Found dashboard with id' , id , matchingManagedObject ) ;
201
+ return [ matchingManagedObject ] ;
202
+ } else {
203
+ console . error ( 'Unable to find dashboard with id' , id ) ;
204
+ return [ ] ;
205
+ }
206
+ } ) ,
207
+ ... _ . flatMap ( partialNames , wildCardName => {
208
+ const wildCardRegex = RegExp ( '^c8y_Dashboard!name!' + wildCardName . split ( '*' ) . map ( expressionPart => _ . escapeRegExp ( expressionPart ) ) . join ( '.*' ) + '$' ) ;
209
+ const matchingManagedObjects = dashboardManagedObjects . filter ( mo => Object . keys ( mo ) . find ( key => wildCardRegex . test ( key ) ) !== undefined ) ;
210
+ if ( matchingManagedObjects . length > 0 ) {
211
+ console . log ( 'Found allGroups with wild-card name' , wildCardName , matchingManagedObjects ) ;
212
+ return matchingManagedObjects ;
213
+ } else {
214
+ console . error ( 'Unable to find dashboard with wild-card name' , wildCardName ) ;
215
+ return [ ] ;
216
+ }
217
+ } ) ,
218
+ ] , dashboard => dashboard . id ) ;
219
+ }
208
220
} ;
209
221
210
222
async findLinkedFromDashboard ( dashboard : IManagedObject ) :
0 commit comments