@adaptabletools/adaptable-plugin-openfin 22.0.0-canary.0 → 22.0.0-canary.10
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/README.md +3 -3
- package/package.json +1 -1
- package/src/Module/OpenFinModule.d.ts +1 -1
- package/src/Module/OpenFinModule.js +25 -15
- package/src/OpenFinApiImpl.d.ts +1 -1
- package/src/OpenFinApiImpl.js +2 -1
- package/src/OpenFinHelper.js +1 -3
- package/src/Utilities/Services/OpenFinService.js +103 -98
- package/src/Utilities/Services/setup.js +9 -9
- package/src/View/OpenFinViewPanel.js +7 -7
- package/src/excel-service/ExcelApi.js +2 -2
- package/src/excel-service/ExcelApplication.js +3 -3
- package/src/excel-service/ExcelRtd.js +2 -2
- package/src/excel-service/RpcDispatcher.js +1 -1
- package/src/index.d.ts +1 -1
- package/src/index.js +41 -42
package/README.md
CHANGED
|
@@ -10,12 +10,12 @@ This plugin allows users to take advantage of some additional functionality cour
|
|
|
10
10
|
|
|
11
11
|
## Documentation & Demos
|
|
12
12
|
|
|
13
|
-
Full details of how to install, configure and use the OpenFin plugin can be found at [AdapTable OpenFin Documentation](https://
|
|
13
|
+
Full details of how to install, configure and use the OpenFin plugin can be found at [AdapTable OpenFin Documentation](https://www.adaptabletools.com/docs/integrations-openfin)
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
## Help
|
|
17
17
|
|
|
18
|
-
Developers can learn how to access AdapTable programmatically at [AdapTable Documentation](https://
|
|
18
|
+
Developers can learn how to access AdapTable programmatically at [AdapTable Documentation](https://www.adaptabletools.com/docs).
|
|
19
19
|
|
|
20
20
|
## Other AdapTable Resources
|
|
21
21
|
|
|
@@ -27,4 +27,4 @@ For all support enquiries please email [`support@adaptabletools.com`](mailto:sup
|
|
|
27
27
|
|
|
28
28
|
## Licences
|
|
29
29
|
|
|
30
|
-
Information on AdapTable Licences can be found at [Licensing AdapTable for AG Grid](https://
|
|
30
|
+
Information on AdapTable Licences can be found at [Licensing AdapTable for AG Grid](https://www.adaptabletools.com/buy/buying-adaptable-licensing).
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@ import { AdaptableModuleBase } from '@adaptabletools/adaptable/src/Strategy/Adap
|
|
|
2
2
|
import { IOpenFinModule } from './Interface/IOpenFinModule';
|
|
3
3
|
import { OpenFinApi } from '@adaptabletools/adaptable/src/Api/OpenFinApi';
|
|
4
4
|
import { OpenFinReport } from '@adaptabletools/adaptable/src/AdaptableState/InternalState';
|
|
5
|
-
import { AdaptableApi, AccessLevel } from '@adaptabletools/adaptable
|
|
5
|
+
import { AdaptableApi, AccessLevel } from '@adaptabletools/adaptable';
|
|
6
6
|
export declare const EXCEL_VALIDATION_FAILED = "excelValidationFailed";
|
|
7
7
|
export declare class OpenFinModule extends AdaptableModuleBase implements IOpenFinModule {
|
|
8
8
|
private isSendingData;
|
|
@@ -4,13 +4,20 @@ import throttle from 'lodash/throttle';
|
|
|
4
4
|
import { DEFAULT_LIVE_REPORT_THROTTLE_TIME, ALL_DATA_REPORT, SELECTED_DATA_REPORT, } from '@adaptabletools/adaptable/src/Utilities/Constants/GeneralConstants';
|
|
5
5
|
export const EXCEL_VALIDATION_FAILED = 'excelValidationFailed';
|
|
6
6
|
export class OpenFinModule extends AdaptableModuleBase {
|
|
7
|
+
isSendingData = false;
|
|
8
|
+
openFinService = null;
|
|
9
|
+
adaptable;
|
|
10
|
+
throttledRecomputeAndSendLiveDataEvent;
|
|
11
|
+
liveTimeoutId;
|
|
12
|
+
removeDataChangedListener;
|
|
13
|
+
removeGridRefreshedListener;
|
|
14
|
+
removeGridFilteredListener;
|
|
15
|
+
removeCellSelectionChangedListener;
|
|
16
|
+
removeRowSelectionChangedListener;
|
|
17
|
+
removeSheetChangedListener;
|
|
18
|
+
currentReportData;
|
|
7
19
|
constructor(api) {
|
|
8
20
|
super(ModuleConstants.OpenFinModuleId, ModuleConstants.OpenFinFriendlyName, 'download', null, 'Integrate AdapTable with the OpenFin container', api);
|
|
9
|
-
this.isSendingData = false;
|
|
10
|
-
this.openFinService = null;
|
|
11
|
-
this.getCurrentReportColumns = () => {
|
|
12
|
-
return this.currentReportData ? this.currentReportData.columns : [];
|
|
13
|
-
};
|
|
14
21
|
this.adaptable = api.internalApi.getAdaptableInstance();
|
|
15
22
|
this.throttledRecomputeAndSendLiveDataEvent = throttle(() => this.sendInitialLiveData(), this.getThrottleTimeFromState());
|
|
16
23
|
}
|
|
@@ -54,24 +61,26 @@ export class OpenFinModule extends AdaptableModuleBase {
|
|
|
54
61
|
throw new Error('Invalid report data format');
|
|
55
62
|
})
|
|
56
63
|
.then(() => {
|
|
57
|
-
this.adaptable.logger.success('
|
|
64
|
+
this.adaptable.logger.success('Live report data sent successfully.');
|
|
58
65
|
this.isSendingData = false;
|
|
59
66
|
return this.api.exportApi.internalApi.publishLiveLiveDataChangedEvent('OpenFin', 'LiveDataUpdated', currentLiveOpenFinReport);
|
|
60
67
|
})
|
|
61
68
|
.catch((reason) => {
|
|
62
69
|
this.isSendingData = false;
|
|
63
|
-
this.adaptable.logger.warn(
|
|
70
|
+
this.adaptable.logger.warn(`Failed to send data to OpenFin for report "${currentLiveOpenFinReport.ReportName}".`, reason);
|
|
64
71
|
this.getOpenFinApi().stopLiveData();
|
|
65
|
-
let errorMessage = 'Export
|
|
72
|
+
let errorMessage = 'Export failed';
|
|
66
73
|
if (reason) {
|
|
67
74
|
errorMessage += ': ' + reason;
|
|
68
75
|
}
|
|
69
|
-
errorMessage += '.
|
|
70
|
-
this.api.alertApi.showAlertError('OpenFin Export
|
|
71
|
-
this.adaptable.logger.warn('Failed to send data');
|
|
76
|
+
errorMessage += '. The live export has been cancelled.';
|
|
77
|
+
this.api.alertApi.showAlertError('OpenFin Export', errorMessage);
|
|
72
78
|
});
|
|
73
79
|
}
|
|
74
80
|
}
|
|
81
|
+
getCurrentReportColumns = () => {
|
|
82
|
+
return this.currentReportData ? this.currentReportData.columns : [];
|
|
83
|
+
};
|
|
75
84
|
startLiveData(iOpenFinReport) {
|
|
76
85
|
this.cleanup(); // just in case the previous report has not been stopped
|
|
77
86
|
this.liveTimeoutId = setTimeout(() => {
|
|
@@ -175,11 +184,11 @@ export class OpenFinModule extends AdaptableModuleBase {
|
|
|
175
184
|
return resolve({ ignore: true });
|
|
176
185
|
}
|
|
177
186
|
if (columnIsPrimaryKey) {
|
|
178
|
-
return reject(
|
|
187
|
+
return reject('Cannot edit a primary key column.');
|
|
179
188
|
// return resolve({ ignore: true });
|
|
180
189
|
}
|
|
181
190
|
if (this.api.columnApi.getColumnWithColumnId(columnId).readOnly) {
|
|
182
|
-
const msg = `
|
|
191
|
+
const msg = `Cannot update column "${columnId}" — it is read-only.`;
|
|
183
192
|
this.adaptable.logger.warn(msg);
|
|
184
193
|
return reject(msg);
|
|
185
194
|
// return resolve({ ignore: true });
|
|
@@ -283,6 +292,7 @@ export class OpenFinModule extends AdaptableModuleBase {
|
|
|
283
292
|
alertType: 'cellChanged',
|
|
284
293
|
cellDataChangedInfo: info,
|
|
285
294
|
alertDefinition: {
|
|
295
|
+
Name: 'Excel Validation Failed',
|
|
286
296
|
AlertProperties: {
|
|
287
297
|
DisplayNotification: true,
|
|
288
298
|
},
|
|
@@ -295,14 +305,14 @@ export class OpenFinModule extends AdaptableModuleBase {
|
|
|
295
305
|
Buttons: pluginOptions.onValidationFailureInExcel === 'show-undo-notification'
|
|
296
306
|
? [
|
|
297
307
|
{
|
|
298
|
-
Label: 'Undo
|
|
308
|
+
Label: 'Undo Change',
|
|
299
309
|
Command: 'openfin-plugin:excel-undo',
|
|
300
310
|
},
|
|
301
311
|
]
|
|
302
312
|
: [],
|
|
303
313
|
},
|
|
304
314
|
},
|
|
305
|
-
header: 'Excel Validation
|
|
315
|
+
header: 'Excel Validation Failed',
|
|
306
316
|
message: textPredicate,
|
|
307
317
|
});
|
|
308
318
|
}
|
package/src/OpenFinApiImpl.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ApiBase } from '@adaptabletools/adaptable/src/Api/Implementation/ApiBase';
|
|
2
2
|
import { OpenFinApi } from '@adaptabletools/adaptable/src/Api/OpenFinApi';
|
|
3
3
|
import { OpenFinPluginOptions } from '@adaptabletools/adaptable/src/AdaptableOptions/OpenFinPluginOptions';
|
|
4
|
-
import { AdaptableAlert } from '@adaptabletools/adaptable
|
|
4
|
+
import { AdaptableAlert } from '@adaptabletools/adaptable';
|
|
5
5
|
import { OpenFinReport, OpenFinSchedule, OpenFinState } from '@adaptabletools/adaptable/src/AdaptableState/OpenFinState';
|
|
6
6
|
import { IAdaptable } from '@adaptabletools/adaptable/src/AdaptableInterfaces/IAdaptable';
|
|
7
7
|
export declare class OpenFinApiImpl extends ApiBase implements OpenFinApi {
|
package/src/OpenFinApiImpl.js
CHANGED
|
@@ -16,9 +16,10 @@ if (typeof window !== 'undefined' && window.document) {
|
|
|
16
16
|
}
|
|
17
17
|
const CLICK_ALERT_BUTTON = 'adaptable-click-alert-button';
|
|
18
18
|
export class OpenFinApiImpl extends ApiBase {
|
|
19
|
+
options;
|
|
20
|
+
OpenFinService = null;
|
|
19
21
|
constructor(_adaptable, options) {
|
|
20
22
|
super(_adaptable);
|
|
21
|
-
this.OpenFinService = null;
|
|
22
23
|
this.options = options;
|
|
23
24
|
if (isRunningInOpenfin()) {
|
|
24
25
|
addEventListener('notification-action', (event) => {
|
package/src/OpenFinHelper.js
CHANGED
|
@@ -2,9 +2,7 @@
|
|
|
2
2
|
// putting this here as we dont use it elswhere - so keeping it here until we redo the OpenFin one day...
|
|
3
3
|
import { AdaptableLogger } from '@adaptabletools/adaptable/src/agGrid/AdaptableLogger';
|
|
4
4
|
export class EventDispatcher {
|
|
5
|
-
|
|
6
|
-
this._subscriptions = new Array();
|
|
7
|
-
}
|
|
5
|
+
_subscriptions = new Array();
|
|
8
6
|
Subscribe(fn) {
|
|
9
7
|
if (fn) {
|
|
10
8
|
this._subscriptions.push(fn);
|
|
@@ -10,9 +10,41 @@ export function isExcelOpenfinLoaded() {
|
|
|
10
10
|
return isRunningInOpenfin() && 'Excel' in fin.desktop;
|
|
11
11
|
}
|
|
12
12
|
export class OpenFinService {
|
|
13
|
+
adaptable;
|
|
14
|
+
options;
|
|
15
|
+
workbookName;
|
|
16
|
+
excelConnected = false;
|
|
17
|
+
connectedCallbacks = [];
|
|
18
|
+
activeWorksheet;
|
|
19
|
+
emitter;
|
|
13
20
|
getOpenFinApi() {
|
|
14
21
|
return this.adaptable.api.pluginsApi.getOpenFinPluginApi();
|
|
15
22
|
}
|
|
23
|
+
onWorkbookRemoved = (event) => {
|
|
24
|
+
event.workbook.removeEventListener('workbookActivated', this.onWorkbookActivated);
|
|
25
|
+
const { workbook } = event;
|
|
26
|
+
this.adaptable.logger.info(`Workbook closed: "${workbook.name}". Stopping OpenFin Live Excel.`);
|
|
27
|
+
this.getOpenFinApi().stopLiveData();
|
|
28
|
+
};
|
|
29
|
+
onWorkbookSaved = (event) => {
|
|
30
|
+
const NewName = event.workbook.name;
|
|
31
|
+
this.adaptable.logger.info('Workbook saved.', NewName);
|
|
32
|
+
//saving adds an extension, but the name does not have that
|
|
33
|
+
// however, not adding the extension will not find the workbook when we do getWorkBookByName
|
|
34
|
+
// and will crash the app
|
|
35
|
+
this.workbookName = NewName;
|
|
36
|
+
};
|
|
37
|
+
onWorkbookActivated = (event) => {
|
|
38
|
+
this.adaptable.logger.info('Workbook activated: ' + event.target.name);
|
|
39
|
+
event.target.getWorksheets((ack) => {
|
|
40
|
+
this.adaptable.logger.info('Retrieved worksheets.', ack);
|
|
41
|
+
});
|
|
42
|
+
};
|
|
43
|
+
onWorkbookAdded = (event) => {
|
|
44
|
+
this.adaptable.logger.success('Workbook added: ' + event.workbook.name);
|
|
45
|
+
let workbook = event.workbook;
|
|
46
|
+
workbook.addEventListener('workbookActivated', this.onWorkbookActivated);
|
|
47
|
+
};
|
|
16
48
|
getCurrentWorkbook(skipRetry) {
|
|
17
49
|
if (!this.workbookName) {
|
|
18
50
|
return this.waitForExcel().then(() => {
|
|
@@ -20,7 +52,7 @@ export class OpenFinService {
|
|
|
20
52
|
// since getWorkbookByName only works after getWorkbooks was called
|
|
21
53
|
return fin.desktop.Excel.getWorkbooks().then(() => {
|
|
22
54
|
this.workbookName = workbook.name;
|
|
23
|
-
this.adaptable.logger.info('
|
|
55
|
+
this.adaptable.logger.info('Workbook created.', this.workbookName);
|
|
24
56
|
return workbook;
|
|
25
57
|
});
|
|
26
58
|
});
|
|
@@ -59,6 +91,21 @@ export class OpenFinService {
|
|
|
59
91
|
});
|
|
60
92
|
});
|
|
61
93
|
}
|
|
94
|
+
onSheetChanged = (event) => {
|
|
95
|
+
this.emit('sheetchanged', event);
|
|
96
|
+
};
|
|
97
|
+
getRowContents = (rowIndex, columnCount) => {
|
|
98
|
+
return new Promise((resolve, reject) => {
|
|
99
|
+
try {
|
|
100
|
+
this.activeWorksheet.getRow('A' + rowIndex, columnCount, (row) => {
|
|
101
|
+
return resolve(row.map((x) => x.value));
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
reject(err);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
};
|
|
62
109
|
doPushData(data, { address, clear }) {
|
|
63
110
|
const OpenFinApi = this.getOpenFinApi();
|
|
64
111
|
if (!OpenFinApi || !this.options || !isRunningInOpenfin()) {
|
|
@@ -75,13 +122,13 @@ export class OpenFinService {
|
|
|
75
122
|
const workBookName = workbook.name;
|
|
76
123
|
let workBook = fin.desktop.Excel.getWorkbookByName(workBookName);
|
|
77
124
|
if (!workBook) {
|
|
78
|
-
this.adaptable.logger.error('Cannot find workbook:' + workBookName);
|
|
79
|
-
reject('Cannot find workbook:' + workBookName);
|
|
125
|
+
this.adaptable.logger.error('Cannot find workbook: ' + workBookName);
|
|
126
|
+
reject('Cannot find workbook: ' + workBookName);
|
|
80
127
|
return;
|
|
81
128
|
}
|
|
82
129
|
this.getActiveWorksheet()
|
|
83
130
|
.then((worksheet) => {
|
|
84
|
-
this.adaptable.logger.info('
|
|
131
|
+
this.adaptable.logger.info('Active worksheet retrieved.', worksheet);
|
|
85
132
|
this.onWorksheetSetData(worksheet, result);
|
|
86
133
|
if (clear) {
|
|
87
134
|
worksheet.clearAllCells(() => {
|
|
@@ -110,6 +157,30 @@ export class OpenFinService {
|
|
|
110
157
|
}));
|
|
111
158
|
});
|
|
112
159
|
}
|
|
160
|
+
onExcelConnected = () => {
|
|
161
|
+
this.excelConnected = true;
|
|
162
|
+
this.connectedCallbacks.forEach((fn) => fn());
|
|
163
|
+
this.connectedCallbacks.length = 0;
|
|
164
|
+
this.adaptable.logger.success('Excel connected.');
|
|
165
|
+
fin.desktop.Excel.addEventListener('workbookClosed', this.onWorkbookRemoved);
|
|
166
|
+
fin.desktop.Excel.addEventListener('workbookSaved', this.onWorkbookSaved);
|
|
167
|
+
fin.desktop.Excel.addEventListener('workbookAdded', this.onWorkbookAdded);
|
|
168
|
+
};
|
|
169
|
+
onExcelDisconnected = () => {
|
|
170
|
+
this.adaptable.logger.info('Excel disconnected.');
|
|
171
|
+
this.excelConnected = false;
|
|
172
|
+
this.initialisingExcel = null;
|
|
173
|
+
this.workbookName = undefined;
|
|
174
|
+
this.activeWorksheet = null;
|
|
175
|
+
fin.desktop.Excel.removeEventListener('workbookClosed', this.onWorkbookRemoved);
|
|
176
|
+
fin.desktop.Excel.removeEventListener('workbookSaved', this.onWorkbookSaved);
|
|
177
|
+
fin.desktop.Excel.removeEventListener('workbookAdded', this.onWorkbookAdded);
|
|
178
|
+
fin.desktop.ExcelService.removeEventListener('excelConnected', this.onExcelConnected);
|
|
179
|
+
fin.desktop.ExcelService.removeEventListener('excelDisconnected', this.onExcelDisconnected);
|
|
180
|
+
this.adaptable.logger.info('Excel closed. Stopping all Live Excel connections.');
|
|
181
|
+
this.getOpenFinApi().stopLiveData();
|
|
182
|
+
};
|
|
183
|
+
initialisingExcel = null;
|
|
113
184
|
initOpenFinExcel(callback) {
|
|
114
185
|
if (this.excelConnected) {
|
|
115
186
|
callback();
|
|
@@ -126,13 +197,13 @@ export class OpenFinService {
|
|
|
126
197
|
return fin.desktop.ExcelService.init();
|
|
127
198
|
})
|
|
128
199
|
.then(() => {
|
|
129
|
-
this.adaptable.logger.success('Excel initialized
|
|
200
|
+
this.adaptable.logger.success('Excel initialized. Connecting...');
|
|
130
201
|
fin.desktop.Excel.run();
|
|
131
202
|
return true;
|
|
132
203
|
})
|
|
133
204
|
.then(() => {
|
|
134
205
|
return fin.desktop.Excel.getConnectionStatus().then((connected) => {
|
|
135
|
-
this.adaptable.logger.success('Excel status', {
|
|
206
|
+
this.adaptable.logger.success('Excel connection status:', {
|
|
136
207
|
initialized: fin.desktop.ExcelService.initialized,
|
|
137
208
|
connected,
|
|
138
209
|
});
|
|
@@ -146,102 +217,36 @@ export class OpenFinService {
|
|
|
146
217
|
});
|
|
147
218
|
return this.initialisingExcel;
|
|
148
219
|
}
|
|
220
|
+
waitForExcel = () => {
|
|
221
|
+
let startTime = Date.now();
|
|
222
|
+
const poolForExcel = (callback) => {
|
|
223
|
+
if (Date.now() - startTime > 20000) {
|
|
224
|
+
console.error('Could not find any Excel instance within timeout.');
|
|
225
|
+
return callback();
|
|
226
|
+
}
|
|
227
|
+
if (!fin.desktop.Excel || !fin.desktop.Excel.getWorkbooks) {
|
|
228
|
+
requestAnimationFrame(() => {
|
|
229
|
+
poolForExcel(callback);
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
callback();
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
return new Promise((resolve) => {
|
|
237
|
+
poolForExcel(() => resolve(''));
|
|
238
|
+
});
|
|
239
|
+
};
|
|
149
240
|
constructor(adaptable, options) {
|
|
150
241
|
this.adaptable = adaptable;
|
|
151
|
-
this.excelConnected = false;
|
|
152
|
-
this.connectedCallbacks = [];
|
|
153
|
-
this.onWorkbookRemoved = (event) => {
|
|
154
|
-
event.workbook.removeEventListener('workbookActivated', this.onWorkbookActivated);
|
|
155
|
-
const { workbook } = event;
|
|
156
|
-
this.adaptable.logger.info('Workbook closed:' + workbook.name + ', Stopping Openfin Live Excel');
|
|
157
|
-
this.getOpenFinApi().stopLiveData();
|
|
158
|
-
};
|
|
159
|
-
this.onWorkbookSaved = (event) => {
|
|
160
|
-
const NewName = event.workbook.name;
|
|
161
|
-
this.adaptable.logger.info('workbook saved', NewName);
|
|
162
|
-
//saving adds an extension, but the name does not have that
|
|
163
|
-
// however, not adding the extension will not find the workbook when we do getWorkBookByName
|
|
164
|
-
// and will crash the app
|
|
165
|
-
this.workbookName = NewName;
|
|
166
|
-
};
|
|
167
|
-
this.onWorkbookActivated = (event) => {
|
|
168
|
-
this.adaptable.logger.info('Workbook Activated: ' + event.target.name);
|
|
169
|
-
event.target.getWorksheets((ack) => {
|
|
170
|
-
this.adaptable.logger.info('getWorksheets:', ack);
|
|
171
|
-
});
|
|
172
|
-
};
|
|
173
|
-
this.onWorkbookAdded = (event) => {
|
|
174
|
-
this.adaptable.logger.success('Workbook Added: ' + event.workbook.name);
|
|
175
|
-
let workbook = event.workbook;
|
|
176
|
-
workbook.addEventListener('workbookActivated', this.onWorkbookActivated);
|
|
177
|
-
};
|
|
178
|
-
this.onSheetChanged = (event) => {
|
|
179
|
-
this.emit('sheetchanged', event);
|
|
180
|
-
};
|
|
181
|
-
this.getRowContents = (rowIndex, columnCount) => {
|
|
182
|
-
return new Promise((resolve, reject) => {
|
|
183
|
-
try {
|
|
184
|
-
this.activeWorksheet.getRow('A' + rowIndex, columnCount, (row) => {
|
|
185
|
-
return resolve(row.map((x) => x.value));
|
|
186
|
-
});
|
|
187
|
-
}
|
|
188
|
-
catch (err) {
|
|
189
|
-
reject(err);
|
|
190
|
-
}
|
|
191
|
-
});
|
|
192
|
-
};
|
|
193
|
-
this.onExcelConnected = () => {
|
|
194
|
-
this.excelConnected = true;
|
|
195
|
-
this.connectedCallbacks.forEach((fn) => fn());
|
|
196
|
-
this.connectedCallbacks.length = 0;
|
|
197
|
-
this.adaptable.logger.success('Excel Connected');
|
|
198
|
-
fin.desktop.Excel.addEventListener('workbookClosed', this.onWorkbookRemoved);
|
|
199
|
-
fin.desktop.Excel.addEventListener('workbookSaved', this.onWorkbookSaved);
|
|
200
|
-
fin.desktop.Excel.addEventListener('workbookAdded', this.onWorkbookAdded);
|
|
201
|
-
};
|
|
202
|
-
this.onExcelDisconnected = () => {
|
|
203
|
-
this.adaptable.logger.info('Excel Disconnected');
|
|
204
|
-
this.excelConnected = false;
|
|
205
|
-
this.initialisingExcel = null;
|
|
206
|
-
this.workbookName = undefined;
|
|
207
|
-
this.activeWorksheet = null;
|
|
208
|
-
fin.desktop.Excel.removeEventListener('workbookClosed', this.onWorkbookRemoved);
|
|
209
|
-
fin.desktop.Excel.removeEventListener('workbookSaved', this.onWorkbookSaved);
|
|
210
|
-
fin.desktop.Excel.removeEventListener('workbookAdded', this.onWorkbookAdded);
|
|
211
|
-
fin.desktop.ExcelService.removeEventListener('excelConnected', this.onExcelConnected);
|
|
212
|
-
fin.desktop.ExcelService.removeEventListener('excelDisconnected', this.onExcelDisconnected);
|
|
213
|
-
this.adaptable.logger.info('Excel closed stopping all Live Excel');
|
|
214
|
-
this.getOpenFinApi().stopLiveData();
|
|
215
|
-
};
|
|
216
|
-
this.initialisingExcel = null;
|
|
217
|
-
this.waitForExcel = () => {
|
|
218
|
-
let startTime = Date.now();
|
|
219
|
-
const poolForExcel = (callback) => {
|
|
220
|
-
if (Date.now() - startTime > 20000) {
|
|
221
|
-
console.error(`Could not find any Excel instance.`);
|
|
222
|
-
return callback();
|
|
223
|
-
}
|
|
224
|
-
if (!fin.desktop.Excel || !fin.desktop.Excel.getWorkbooks) {
|
|
225
|
-
requestAnimationFrame(() => {
|
|
226
|
-
poolForExcel(callback);
|
|
227
|
-
});
|
|
228
|
-
}
|
|
229
|
-
else {
|
|
230
|
-
callback();
|
|
231
|
-
}
|
|
232
|
-
};
|
|
233
|
-
return new Promise((resolve) => {
|
|
234
|
-
poolForExcel(() => resolve(''));
|
|
235
|
-
});
|
|
236
|
-
};
|
|
237
|
-
this.on = (eventName, callback) => {
|
|
238
|
-
return this.emitter.on(eventName, callback);
|
|
239
|
-
};
|
|
240
|
-
this.emit = (eventName, data) => {
|
|
241
|
-
return this.emitter.emit(eventName, data);
|
|
242
|
-
};
|
|
243
242
|
this.adaptable = adaptable;
|
|
244
243
|
this.options = options;
|
|
245
244
|
this.emitter = new Emitter();
|
|
246
245
|
}
|
|
246
|
+
on = (eventName, callback) => {
|
|
247
|
+
return this.emitter.on(eventName, callback);
|
|
248
|
+
};
|
|
249
|
+
emit = (eventName, data) => {
|
|
250
|
+
return this.emitter.emit(eventName, data);
|
|
251
|
+
};
|
|
247
252
|
}
|
|
@@ -9,11 +9,11 @@ export const setup = async () => {
|
|
|
9
9
|
let serviceIsRunning = await isServiceRunning();
|
|
10
10
|
let assetInfo = await getAppAssetInfo();
|
|
11
11
|
if (serviceIsRunning) {
|
|
12
|
-
AdaptableLogger.consoleLogBase('
|
|
12
|
+
AdaptableLogger.consoleLogBase('Excel service already running. Skipping deployment and registration.');
|
|
13
13
|
return;
|
|
14
14
|
}
|
|
15
15
|
if (assetInfo.version === localStorage.installedAssetVersion && !assetInfo.forceDownload) {
|
|
16
|
-
AdaptableLogger.consoleLogBase('Current Add-In version
|
|
16
|
+
AdaptableLogger.consoleLogBase('Current Add-In version already installed. Skipping deployment and registration.');
|
|
17
17
|
}
|
|
18
18
|
else {
|
|
19
19
|
await deploySharedAssets();
|
|
@@ -55,10 +55,10 @@ export const setup = async () => {
|
|
|
55
55
|
target: servicePath,
|
|
56
56
|
arguments: `-d "${installFolder}" -c ${manifest.runtime.version}`,
|
|
57
57
|
listener: (result) => {
|
|
58
|
-
AdaptableLogger.consoleLogBase(`Asset
|
|
58
|
+
AdaptableLogger.consoleLogBase(`Asset deployment completed (exit code: ${result.exitCode}).`);
|
|
59
59
|
resolve();
|
|
60
60
|
},
|
|
61
|
-
}, () => console.log('Deploying
|
|
61
|
+
}, () => console.log('Deploying shared assets...'), (err) => reject(err));
|
|
62
62
|
});
|
|
63
63
|
});
|
|
64
64
|
}
|
|
@@ -69,14 +69,14 @@ export const setup = async () => {
|
|
|
69
69
|
arguments: `-i "${installFolder}"`,
|
|
70
70
|
listener: (result) => {
|
|
71
71
|
if (result.exitCode === 0) {
|
|
72
|
-
AdaptableLogger.consoleLogBase('Add-In
|
|
72
|
+
AdaptableLogger.consoleLogBase('Add-In installed successfully.');
|
|
73
73
|
}
|
|
74
74
|
else {
|
|
75
|
-
AdaptableLogger.consoleWarnBase(`
|
|
75
|
+
AdaptableLogger.consoleWarnBase(`Add-In installation failed (exit code: ${result.exitCode}).`);
|
|
76
76
|
}
|
|
77
77
|
resolve();
|
|
78
78
|
},
|
|
79
|
-
}, () => AdaptableLogger.consoleLogBase('Installing Add-In'), (err) => reject(err));
|
|
79
|
+
}, () => AdaptableLogger.consoleLogBase('Installing Add-In...'), (err) => reject(err));
|
|
80
80
|
});
|
|
81
81
|
}
|
|
82
82
|
function startExcelService() {
|
|
@@ -95,9 +95,9 @@ export const setup = async () => {
|
|
|
95
95
|
arguments: '-p ' + details.port,
|
|
96
96
|
uuid: excelServiceUuid,
|
|
97
97
|
}, (process) => {
|
|
98
|
-
AdaptableLogger.consoleLogBase('
|
|
98
|
+
AdaptableLogger.consoleLogBase('Excel service launched: ' + process.uuid);
|
|
99
99
|
}, (error) => {
|
|
100
|
-
reject('
|
|
100
|
+
reject('Failed to start Excel service.');
|
|
101
101
|
});
|
|
102
102
|
});
|
|
103
103
|
});
|
|
@@ -17,13 +17,6 @@ const IS_OPENFIN = isRunningInOpenfin();
|
|
|
17
17
|
class OpenFinViewPanelComponent extends React.Component {
|
|
18
18
|
constructor(props) {
|
|
19
19
|
super(props);
|
|
20
|
-
this.onLiveDataChanged = (liveDataChangedInfo) => {
|
|
21
|
-
if (liveDataChangedInfo.reportDestination == 'OpenFin' &&
|
|
22
|
-
(liveDataChangedInfo.liveDataTrigger == 'Connected' ||
|
|
23
|
-
liveDataChangedInfo.liveDataTrigger == 'Disconnected')) {
|
|
24
|
-
this.forceUpdate();
|
|
25
|
-
}
|
|
26
|
-
};
|
|
27
20
|
}
|
|
28
21
|
componentDidMount() {
|
|
29
22
|
this.props.api.eventApi.on('LiveDataChanged', this.onLiveDataChanged);
|
|
@@ -31,6 +24,13 @@ class OpenFinViewPanelComponent extends React.Component {
|
|
|
31
24
|
componentWillUnmount() {
|
|
32
25
|
this.props.api.eventApi.off('LiveDataChanged', this.onLiveDataChanged);
|
|
33
26
|
}
|
|
27
|
+
onLiveDataChanged = (liveDataChangedInfo) => {
|
|
28
|
+
if (liveDataChangedInfo.reportDestination == 'OpenFin' &&
|
|
29
|
+
(liveDataChangedInfo.liveDataTrigger == 'Connected' ||
|
|
30
|
+
liveDataChangedInfo.liveDataTrigger == 'Disconnected')) {
|
|
31
|
+
this.forceUpdate();
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
34
|
getOpenFinApi() {
|
|
35
35
|
return this.props.api.pluginsApi.getOpenFinPluginApi();
|
|
36
36
|
}
|
|
@@ -156,7 +156,7 @@ class ExcelService extends RpcDispatcher_1.RpcDispatcher {
|
|
|
156
156
|
}
|
|
157
157
|
}
|
|
158
158
|
}
|
|
159
|
-
this.logger.info(this.loggerName + ':
|
|
159
|
+
this.logger.info(this.loggerName + ': Initialize called.');
|
|
160
160
|
this.logger.debug(this.loggerName + ': Subscribing to Service Messages.');
|
|
161
161
|
yield this.subscribeToServiceMessages();
|
|
162
162
|
this.logger.debug(
|
|
@@ -181,7 +181,7 @@ class ExcelService extends RpcDispatcher_1.RpcDispatcher {
|
|
|
181
181
|
}
|
|
182
182
|
this.logger.warn(
|
|
183
183
|
this.loggerName +
|
|
184
|
-
':
|
|
184
|
+
': Failed to connect to or fetch version from provider. The provider version may be older than the script version.',
|
|
185
185
|
errorMessage
|
|
186
186
|
);
|
|
187
187
|
}
|
|
@@ -237,11 +237,11 @@ class ExcelApplication extends RpcDispatcher_1.RpcDispatcher {
|
|
|
237
237
|
return __awaiter(this, void 0, void 0, function* () {
|
|
238
238
|
this.logger.info(this.loggerName + ': Init called.');
|
|
239
239
|
if (!this.initialized) {
|
|
240
|
-
this.logger.info(this.loggerName + ': Not
|
|
240
|
+
this.logger.info(this.loggerName + ': Not initialized. Initializing...');
|
|
241
241
|
yield this.subscribeToExcelMessages();
|
|
242
242
|
yield this.monitorDisconnect();
|
|
243
243
|
this.initialized = true;
|
|
244
|
-
this.logger.info(this.loggerName + ':
|
|
244
|
+
this.logger.info(this.loggerName + ': Initialized.');
|
|
245
245
|
}
|
|
246
246
|
return;
|
|
247
247
|
});
|
|
@@ -250,7 +250,7 @@ class ExcelApplication extends RpcDispatcher_1.RpcDispatcher {
|
|
|
250
250
|
return __awaiter(this, void 0, void 0, function* () {
|
|
251
251
|
this.logger.info(this.loggerName + ': Release called.');
|
|
252
252
|
if (this.initialized) {
|
|
253
|
-
this.logger.info(this.loggerName + ':
|
|
253
|
+
this.logger.info(this.loggerName + ': Unsubscribing from Excel messages.');
|
|
254
254
|
yield this.unsubscribeToExcelMessages();
|
|
255
255
|
//TODO: Provide external means to stop monitoring disconnect
|
|
256
256
|
}
|
|
@@ -72,7 +72,7 @@ class ExcelRtd extends EventEmitter_1.EventEmitter {
|
|
|
72
72
|
} catch (err) {
|
|
73
73
|
this.logger.warn(
|
|
74
74
|
this.loggerName +
|
|
75
|
-
`: The excelRtd/${this.providerName} channel already exists.
|
|
75
|
+
`: The excelRtd/${this.providerName} channel already exists. Only one connection instance per provider is allowed. Another window or application may have created a provider with the same name.`,
|
|
76
76
|
err
|
|
77
77
|
);
|
|
78
78
|
return;
|
|
@@ -133,7 +133,7 @@ class ExcelRtd extends EventEmitter_1.EventEmitter {
|
|
|
133
133
|
// without a catch the rest of the initialisation would be broken
|
|
134
134
|
this.logger.warn(
|
|
135
135
|
this.loggerName +
|
|
136
|
-
`:
|
|
136
|
+
`: Failed to destroy excelRtd/${this.providerName} channel during cleanup.`,
|
|
137
137
|
err
|
|
138
138
|
);
|
|
139
139
|
}
|
|
@@ -77,7 +77,7 @@ class RpcDispatcher extends EventEmitter_1.EventEmitter {
|
|
|
77
77
|
return result;
|
|
78
78
|
})
|
|
79
79
|
.catch((err) => {
|
|
80
|
-
this.logger.error('
|
|
80
|
+
this.logger.error('Failed to apply callback to promise.', err);
|
|
81
81
|
});
|
|
82
82
|
promise = undefined;
|
|
83
83
|
}
|
package/src/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AdaptablePlugin } from '@adaptabletools/adaptable
|
|
1
|
+
import { AdaptablePlugin } from '@adaptabletools/adaptable';
|
|
2
2
|
import * as Redux from 'redux';
|
|
3
3
|
import { InternalState } from '@adaptabletools/adaptable/src/AdaptableState/InternalState';
|
|
4
4
|
import { OpenFinApi } from '@adaptabletools/adaptable/src/Api/OpenFinApi';
|
package/src/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AdaptablePlugin } from '@adaptabletools/adaptable
|
|
1
|
+
import { AdaptablePlugin } from '@adaptabletools/adaptable';
|
|
2
2
|
import packageJson from '../package.json';
|
|
3
3
|
import adaptableCorePackageJson from '@adaptabletools/adaptable/package.json';
|
|
4
4
|
import * as ModuleConstants from '@adaptabletools/adaptable/src/Utilities/Constants/ModuleConstants';
|
|
@@ -16,11 +16,7 @@ const { version, name } = packageJson;
|
|
|
16
16
|
const { version: coreVersion } = adaptableCorePackageJson;
|
|
17
17
|
const suffix = name.endsWith('-cjs') ? '-cjs' : '';
|
|
18
18
|
if (version !== coreVersion) {
|
|
19
|
-
console.warn(`
|
|
20
|
-
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
21
|
-
!!!!!!! "@adaptabletools/adaptable-plugin-openfin${suffix}" (v @${version}) and "@adaptabletools/adaptable${suffix}" (v @${coreVersion}) have different versions - they should have the exact same version.
|
|
22
|
-
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
23
|
-
`);
|
|
19
|
+
console.warn(`Version mismatch: "@adaptabletools/adaptable-plugin-openfin${suffix}" (v${version}) and "@adaptabletools/adaptable${suffix}" (v${coreVersion}) have different versions. They should be the exact same version.`);
|
|
24
20
|
}
|
|
25
21
|
const defaultOptions = {
|
|
26
22
|
throttleTime: 2000,
|
|
@@ -30,44 +26,12 @@ const defaultOptions = {
|
|
|
30
26
|
onValidationFailureInExcel: 'show-undo-notification',
|
|
31
27
|
};
|
|
32
28
|
class OpenFinPlugin extends AdaptablePlugin {
|
|
29
|
+
pluginId = 'openfin';
|
|
30
|
+
openFinApi;
|
|
31
|
+
OpenFinService;
|
|
32
|
+
openFinModule;
|
|
33
33
|
constructor(options) {
|
|
34
34
|
super(options);
|
|
35
|
-
this.pluginId = 'openfin';
|
|
36
|
-
this.rootReducer = (rootReducer) => {
|
|
37
|
-
return {
|
|
38
|
-
System: (state, action) => {
|
|
39
|
-
let augmentedState = rootReducer.System(state, action);
|
|
40
|
-
if (!state) {
|
|
41
|
-
// required for store initialization
|
|
42
|
-
// (idiomatic way of default parameter value in reducer is not feasible because the passed argument is already initialized by the System reducer)
|
|
43
|
-
augmentedState = Object.assign({}, augmentedState, initialOpenFinState);
|
|
44
|
-
}
|
|
45
|
-
return OpenFinReducer(augmentedState, action);
|
|
46
|
-
},
|
|
47
|
-
};
|
|
48
|
-
};
|
|
49
|
-
this.reduxMiddleware = (adaptable) => (middlewareAPI) => {
|
|
50
|
-
return (next) => {
|
|
51
|
-
return (action) => {
|
|
52
|
-
switch (action.type) {
|
|
53
|
-
case OPENFIN_START_LIVE_DATA: {
|
|
54
|
-
const actionTyped = action;
|
|
55
|
-
this.openFinModule.startLiveData(actionTyped.openFinReport);
|
|
56
|
-
middlewareAPI.dispatch(PopupRedux.PopupHideScreen());
|
|
57
|
-
return next(action);
|
|
58
|
-
}
|
|
59
|
-
case OPENFIN_STOP_LIVE_DATA: {
|
|
60
|
-
const actionTyped = action;
|
|
61
|
-
this.openFinModule.stopLiveData(actionTyped.openFinReport);
|
|
62
|
-
return next(action);
|
|
63
|
-
}
|
|
64
|
-
default: {
|
|
65
|
-
return next(action);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
};
|
|
69
|
-
};
|
|
70
|
-
};
|
|
71
35
|
this.options = {
|
|
72
36
|
...defaultOptions,
|
|
73
37
|
...options,
|
|
@@ -93,6 +57,41 @@ class OpenFinPlugin extends AdaptablePlugin {
|
|
|
93
57
|
this.registerProperty('api', () => this.openFinApi);
|
|
94
58
|
this.registerProperty('service', () => this.OpenFinService);
|
|
95
59
|
}
|
|
60
|
+
rootReducer = (rootReducer) => {
|
|
61
|
+
return {
|
|
62
|
+
System: (state, action) => {
|
|
63
|
+
let augmentedState = rootReducer.System(state, action);
|
|
64
|
+
if (!state) {
|
|
65
|
+
// required for store initialization
|
|
66
|
+
// (idiomatic way of default parameter value in reducer is not feasible because the passed argument is already initialized by the System reducer)
|
|
67
|
+
augmentedState = Object.assign({}, augmentedState, initialOpenFinState);
|
|
68
|
+
}
|
|
69
|
+
return OpenFinReducer(augmentedState, action);
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
reduxMiddleware = (adaptable) => (middlewareAPI) => {
|
|
74
|
+
return (next) => {
|
|
75
|
+
return (action) => {
|
|
76
|
+
switch (action.type) {
|
|
77
|
+
case OPENFIN_START_LIVE_DATA: {
|
|
78
|
+
const actionTyped = action;
|
|
79
|
+
this.openFinModule.startLiveData(actionTyped.openFinReport);
|
|
80
|
+
middlewareAPI.dispatch(PopupRedux.PopupHideScreen());
|
|
81
|
+
return next(action);
|
|
82
|
+
}
|
|
83
|
+
case OPENFIN_STOP_LIVE_DATA: {
|
|
84
|
+
const actionTyped = action;
|
|
85
|
+
this.openFinModule.stopLiveData(actionTyped.openFinReport);
|
|
86
|
+
return next(action);
|
|
87
|
+
}
|
|
88
|
+
default: {
|
|
89
|
+
return next(action);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
};
|
|
94
|
+
};
|
|
96
95
|
afterInitStore(adaptable) {
|
|
97
96
|
adaptable.adaptableModules.set(OpenFinModuleId, new OpenFinModule(adaptable.api));
|
|
98
97
|
AdaptableViewPanelFactory.set(OpenFinModuleId, OpenFinViewPanelControl);
|