@mindline/sync 1.0.106 → 1.0.108
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/.vs/VSWorkspaceState.json +0 -1
- package/.vs/slnx.sqlite +0 -0
- package/.vs/sync/CopilotIndices/17.14.260.54502/CodeChunks.db +0 -0
- package/.vs/sync/CopilotIndices/17.14.260.54502/SemanticSymbols.db +0 -0
- package/.vs/sync/FileContentIndex/0a490c4d-e4ea-4e8d-8989-720009d15f9d.vsidx +0 -0
- package/.vs/sync/FileContentIndex/173d280f-33b3-451d-8054-08fc6c991498.vsidx +0 -0
- package/.vs/sync/FileContentIndex/e27fae98-55a0-4376-b1eb-e2efa630b10b.vsidx +0 -0
- package/.vs/sync/FileContentIndex/fae8821f-9f13-46f5-91ef-05b837e2f35a.vsidx +0 -0
- package/.vs/sync/v17/.wsuo +0 -0
- package/.vs/sync/v17/DocumentLayout.backup.json +87 -28
- package/.vs/sync/v17/DocumentLayout.json +81 -15
- package/.vs/sync.slnx/FileContentIndex/13d6a28d-932f-4eb6-818c-efea35f24838.vsidx +0 -0
- package/.vs/sync.slnx/FileContentIndex/46af7fa0-1a65-4634-9faa-600623e92173.vsidx +0 -0
- package/.vs/sync.slnx/FileContentIndex/75bd0095-9fc3-4f35-90e9-f4022b8e4b55.vsidx +0 -0
- package/.vs/sync.slnx/FileContentIndex/92b75297-fe76-448d-80d4-cbf5ef4fcd60.vsidx +0 -0
- package/.vs/sync.slnx/FileContentIndex/eb2f80ef-22e0-4cc0-a8fb-f7837f87af2d.vsidx +0 -0
- package/.vs/sync.slnx/config/applicationhost.config +1011 -0
- package/.vs/sync.slnx/v18/.wsuo +0 -0
- package/.vs/sync.slnx/v18/DocumentLayout.backup.json +104 -0
- package/.vs/sync.slnx/v18/DocumentLayout.json +87 -0
- package/dist/src/index.d.ts +9 -5
- package/dist/sync.es.js +849 -789
- package/dist/sync.es.js.map +1 -1
- package/dist/sync.umd.js +25 -21
- package/dist/sync.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/index.d.ts +14 -14
- package/src/index.ts +231 -60
- package/.vs/sync/FileContentIndex/0d08f64f-8fd9-4bd4-90fc-8322cb33dd00.vsidx +0 -0
- package/.vs/sync/FileContentIndex/5d404a65-c534-43ee-beba-a5efbe6a49b0.vsidx +0 -0
- package/.vs/sync/FileContentIndex/63524bf8-437e-4a1c-951f-7a78da75a1bc.vsidx +0 -0
- package/.vs/sync/FileContentIndex/f95b6302-8444-443b-9e3b-a41d3483c73a.vsidx +0 -0
- /package/.vs/sync/FileContentIndex/{db560492-d007-4291-a6b3-50ccdcbd66b4.vsidx → 72fe2c03-a5ac-417e-b6be-5d2e18aa7d59.vsidx} +0 -0
package/src/index.ts
CHANGED
|
@@ -25,12 +25,12 @@ export function getSyncVersion(): string {
|
|
|
25
25
|
// injected at build time
|
|
26
26
|
return __SYNC_VERSION__;
|
|
27
27
|
}
|
|
28
|
-
export class APIResult {
|
|
28
|
+
export class APIResult<T = any> {
|
|
29
29
|
result: boolean;
|
|
30
30
|
status: number;
|
|
31
31
|
error: string;
|
|
32
32
|
version: string;
|
|
33
|
-
array: Array<
|
|
33
|
+
array: Array<T> | null;
|
|
34
34
|
constructor() { this.result = true; this.status = 200; this.error = ""; this.version = getSyncVersion(); this.array = null; }
|
|
35
35
|
}
|
|
36
36
|
export class azureConfig {
|
|
@@ -93,6 +93,9 @@ export class mindlineConfig {
|
|
|
93
93
|
static signalREndpoint(): string {
|
|
94
94
|
return `https://${mindlineConfig.environmentTag}-signalrdispatcher-westus.azurewebsites.net/statsHub`;
|
|
95
95
|
};
|
|
96
|
+
static statsEndpoint(): string {
|
|
97
|
+
return `https://${mindlineConfig.environmentTag}-signalrdispatcher-westus.azurewebsites.net/api/stats`;
|
|
98
|
+
}
|
|
96
99
|
}
|
|
97
100
|
export class graphConfig {
|
|
98
101
|
// graph API predicates
|
|
@@ -785,7 +788,7 @@ export class MilestoneArray {
|
|
|
785
788
|
let result = localStorage.getItem("syncmilestones");
|
|
786
789
|
if (result != null && typeof result === "string" && result !== "") {
|
|
787
790
|
let milestonesString: string = result;
|
|
788
|
-
let milestones: Object
|
|
791
|
+
let milestones: Object[] = JSON.parse(milestonesString);
|
|
789
792
|
if (milestones.length !== 0) {
|
|
790
793
|
if (bClearLocalStorage) {
|
|
791
794
|
localStorage.removeItem("syncmilestones");
|
|
@@ -812,7 +815,7 @@ export class MilestoneArray {
|
|
|
812
815
|
if (this.milestones == null || this.milestones.length < 1) { debugger; return; }
|
|
813
816
|
let currentRun: number = Number(this.milestones[0].Run);
|
|
814
817
|
// create a new milestone and prepend to front of array
|
|
815
|
-
let newMilestone: Milestone = new Milestone(currentRun+1);
|
|
818
|
+
let newMilestone: Milestone = new Milestone(currentRun + 1);
|
|
816
819
|
this.milestones.unshift(newMilestone);
|
|
817
820
|
// re-define milestone array to trigger render
|
|
818
821
|
this.milestones = this.milestones.map((ms: Milestone) => {
|
|
@@ -1027,7 +1030,9 @@ export class BatchArray {
|
|
|
1027
1030
|
this.pb_total = 0;
|
|
1028
1031
|
this.pb_timer = setInterval(() => {
|
|
1029
1032
|
// if signalR has finished the sync, stop the timer
|
|
1030
|
-
|
|
1033
|
+
console.log("this.tenantNodes", this.tenantNodes)
|
|
1034
|
+
let isCompletedOrNothingToSync = this.tenantNodes.map((tn: TenantNode) => tn.targets.map((ta) => ta.status === "complete" || tn.nothingtosync).reduce((prev, next) => prev && next)).reduce((prev, next) => prev && next);
|
|
1035
|
+
if (isCompletedOrNothingToSync) {
|
|
1031
1036
|
clearInterval(this.pb_timer!);
|
|
1032
1037
|
this.pb_timer = null;
|
|
1033
1038
|
this.pb_progress = 100;
|
|
@@ -1074,12 +1079,15 @@ export class BatchArray {
|
|
|
1074
1079
|
batchIdArray: Array<Object>,
|
|
1075
1080
|
setRefreshDeltaTrigger: (workspace: string) => void,
|
|
1076
1081
|
setReadersTotal: (readersTotal: number) => void,
|
|
1082
|
+
setReadersExcluded: (readersExcluded: number) => void,
|
|
1077
1083
|
setReadersCurrent: (readersCurrent: number) => void,
|
|
1078
1084
|
setWritersTotal: (writersTotal: number) => void,
|
|
1079
|
-
|
|
1085
|
+
setWritersExcluded: (writersExcluded: number) => void,
|
|
1086
|
+
setWritersCurrent: (writersCurrent: number) => void,
|
|
1080
1087
|
setMilestones: (milestones: Milestone[]) => void,
|
|
1081
1088
|
setConfigSyncResult: (result: string) => void,
|
|
1082
|
-
bClearLocalStorage: boolean
|
|
1089
|
+
bClearLocalStorage: boolean,
|
|
1090
|
+
message: string
|
|
1083
1091
|
): void {
|
|
1084
1092
|
bClearLocalStorage = bClearLocalStorage;
|
|
1085
1093
|
// we have just completed a successful POST to startSync
|
|
@@ -1088,7 +1096,7 @@ export class BatchArray {
|
|
|
1088
1096
|
// re-initialize batch array with Configuration updated by the succcessful POST to startSync
|
|
1089
1097
|
this.init(config, syncPortalGlobalState, false);
|
|
1090
1098
|
// define newMessage handler that can access *this*
|
|
1091
|
-
let handler = (message: string) => {
|
|
1099
|
+
let handler = (connection: signalR.HubConnection) => (message: string) => {
|
|
1092
1100
|
console.log(message);
|
|
1093
1101
|
let item = JSON.parse(message);
|
|
1094
1102
|
// reset the countdown timer every time we get a message
|
|
@@ -1117,12 +1125,29 @@ export class BatchArray {
|
|
|
1117
1125
|
for (let j = 0; j < statskeys.length; j++) {
|
|
1118
1126
|
let bTotalCount = statskeys[j].endsWith("TotalCount");
|
|
1119
1127
|
let bCurrentCount = statskeys[j].endsWith("CurrentCount");
|
|
1128
|
+
let bExcludedCount = statskeys[j].endsWith("ExtCount");
|
|
1120
1129
|
let bDeferredCount = statskeys[j].endsWith("DeferredCount");
|
|
1121
1130
|
let bRescheduledCount = statskeys[j].endsWith("RescheduledCount");
|
|
1131
|
+
if (bExcludedCount) {
|
|
1132
|
+
tenantNode.excluded = Math.max(Number(statsvalues[j]), tenantNode.excluded);
|
|
1133
|
+
tenantNode.targets.map(writerNode => {
|
|
1134
|
+
writerNode.excluded = tenantNode.excluded;
|
|
1135
|
+
writerNode.update(writerNode.total, writerNode.read, writerNode.excluded, writerNode.written, writerNode.deferred);
|
|
1136
|
+
})
|
|
1137
|
+
}
|
|
1138
|
+
if (bTotalCount) {
|
|
1139
|
+
bTotalCountZero = Number(statsvalues[j]) == 0;
|
|
1140
|
+
tenantNode.total = Math.max(Number(statsvalues[j]), tenantNode.total);
|
|
1141
|
+
tenantNode.targets.map(writerNode => {
|
|
1142
|
+
writerNode.total = tenantNode.total;
|
|
1143
|
+
writerNode.update(writerNode.total, writerNode.read, writerNode.excluded, writerNode.written, writerNode.deferred);
|
|
1144
|
+
})
|
|
1145
|
+
}
|
|
1122
1146
|
if (statskeys[j].startsWith("Reader")) {
|
|
1123
1147
|
// parse tid from Reader key
|
|
1124
1148
|
let tidRegexp = /Reader\/TID:(.+)\/TotalCount/;
|
|
1125
1149
|
if (bCurrentCount) tidRegexp = /Reader\/TID:(.+)\/CurrentCount/;
|
|
1150
|
+
if (bExcludedCount) tidRegexp = /Reader\/TID:(.+)\/ExtCount/;
|
|
1126
1151
|
if (bDeferredCount) tidRegexp = /Reader\/TID:(.+)\/DeferredCount/;
|
|
1127
1152
|
if (bRescheduledCount) tidRegexp = /Reader\/TID:(.+)\/RescheduledCount/;
|
|
1128
1153
|
let matchTID = statskeys[j].match(tidRegexp);
|
|
@@ -1139,15 +1164,21 @@ export class BatchArray {
|
|
|
1139
1164
|
}
|
|
1140
1165
|
else {
|
|
1141
1166
|
bCurrentCountZero = Number(statsvalues[j]) == 0;
|
|
1142
|
-
|
|
1143
|
-
|
|
1167
|
+
if (bCurrentCount) {
|
|
1168
|
+
tenantNode.read = Math.max(Number(statsvalues[j]), tenantNode.read);
|
|
1169
|
+
console.log(`----- ${tenantNode.name} Currently Read: ${tenantNode.read}`);
|
|
1170
|
+
} else if (bDeferredCount) {
|
|
1171
|
+
tenantNode.deferred = Math.max(Number(statsvalues[j]), tenantNode.deferred);
|
|
1172
|
+
console.log(`----- ${tenantNode.name} Deferred: ${tenantNode.deferred}`);
|
|
1173
|
+
}
|
|
1144
1174
|
}
|
|
1145
1175
|
}
|
|
1146
1176
|
tenantNode.nothingtosync = bTotalCountZero && bCurrentCountZero;
|
|
1147
1177
|
if (statskeys[j].startsWith("Writer")) {
|
|
1148
1178
|
// parse tid from Writer key
|
|
1149
|
-
let tidRegexp = /
|
|
1179
|
+
let tidRegexp = /Reader\/TID:(.+)\/TotalCount/;
|
|
1150
1180
|
if (bCurrentCount) tidRegexp = /Writer\/TID:(.+)\/CurrentCount/;
|
|
1181
|
+
if (bExcludedCount) tidRegexp = /Writer\/TID:(.+)\/ExtCount/;
|
|
1151
1182
|
if (bDeferredCount) tidRegexp = /Writer\/TID:(.+)\/DeferredCount/;
|
|
1152
1183
|
if (bRescheduledCount) tidRegexp = /Writer\/TID:(.+)\/RescheduledCount/;
|
|
1153
1184
|
let matchTID: RegExpMatchArray | null = statskeys[j].match(tidRegexp);
|
|
@@ -1163,9 +1194,11 @@ export class BatchArray {
|
|
|
1163
1194
|
debugger;
|
|
1164
1195
|
return;
|
|
1165
1196
|
}
|
|
1197
|
+
writerNode.total = Math.max(Number(tenantNode.total), writerNode.total);
|
|
1198
|
+
writerNode.total = Math.max(Number(tenantNode.total), writerNode.total);
|
|
1166
1199
|
writerNode.batchId = matchingPair.BatchId;
|
|
1167
1200
|
if (bTotalCount) {
|
|
1168
|
-
writerNode.total = Math.max(Number(
|
|
1201
|
+
writerNode.total = Math.max(Number(bTotalCount), writerNode.total);
|
|
1169
1202
|
console.log(`----- ${writerNode.name} TID: ${writerNode.tid} batchId: ${writerNode.batchId}`);
|
|
1170
1203
|
console.log(`----- ${writerNode.name} Total To Write: ${writerNode.total}`);
|
|
1171
1204
|
}
|
|
@@ -1182,11 +1215,12 @@ export class BatchArray {
|
|
|
1182
1215
|
debugger;
|
|
1183
1216
|
return;
|
|
1184
1217
|
}
|
|
1185
|
-
writerNode.update(writerNode.total, writerNode.read, writerNode.written, writerNode.deferred);
|
|
1218
|
+
writerNode.update(writerNode.total, writerNode.read, writerNode.excluded, writerNode.written, writerNode.deferred);
|
|
1186
1219
|
}
|
|
1187
1220
|
}
|
|
1188
1221
|
// update status based on all updates in this message
|
|
1189
|
-
tenantNode.update(tenantNode.total, tenantNode.read, tenantNode.written, tenantNode.deferred);
|
|
1222
|
+
tenantNode.update(tenantNode.total, tenantNode.read, tenantNode.excluded, tenantNode.written, tenantNode.deferred);
|
|
1223
|
+
|
|
1190
1224
|
// for each message, enumerate nodes to assess completion state
|
|
1191
1225
|
let bReadingComplete: boolean = true;
|
|
1192
1226
|
let bWritingComplete: boolean = true;
|
|
@@ -1194,34 +1228,41 @@ export class BatchArray {
|
|
|
1194
1228
|
let bNothingToSync: boolean = true;
|
|
1195
1229
|
let readerTotal: number = 0;
|
|
1196
1230
|
let readerCurrent: number = 0;
|
|
1231
|
+
let readerExcluded: number = 0;
|
|
1197
1232
|
let writerTotal: number = 0;
|
|
1198
1233
|
let writerCurrent: number = 0;
|
|
1234
|
+
let writerExcluded: number = 0;
|
|
1199
1235
|
this.tenantNodes.map((sourceTenantNode: TenantNode) => {
|
|
1200
1236
|
sourceTenantNode.targets.map((writerNode: TenantNode) => {
|
|
1201
1237
|
bWritingComplete &&= (writerNode.status == "complete" || writerNode.status == "failed");
|
|
1202
1238
|
bWritingStarted ||= (writerNode.total > 0 || writerNode.status != "not started");
|
|
1203
1239
|
writerTotal += Math.max(writerNode.total, sourceTenantNode.total);
|
|
1204
1240
|
writerCurrent += writerNode.written;
|
|
1241
|
+
writerExcluded += writerNode.excluded;
|
|
1205
1242
|
});
|
|
1206
1243
|
bNothingToSync &&= sourceTenantNode.nothingtosync;
|
|
1207
1244
|
bReadingComplete &&= (sourceTenantNode.status == "complete" || sourceTenantNode.status == "failed");
|
|
1208
1245
|
readerTotal += sourceTenantNode.total;
|
|
1209
1246
|
readerCurrent += sourceTenantNode.read;
|
|
1247
|
+
readerExcluded += sourceTenantNode.excluded;
|
|
1210
1248
|
});
|
|
1211
1249
|
// set linear gauge max and current values
|
|
1212
1250
|
setReadersTotal(readerTotal);
|
|
1213
1251
|
setReadersCurrent(readerCurrent);
|
|
1252
|
+
setReadersExcluded(readerExcluded);
|
|
1214
1253
|
setWritersTotal(Math.max(writerTotal, readerTotal));
|
|
1215
1254
|
setWritersCurrent(writerCurrent);
|
|
1255
|
+
setWritersExcluded(writerExcluded);
|
|
1216
1256
|
// check to see if there was nothing to sync
|
|
1217
1257
|
if (bNothingToSync) {
|
|
1218
1258
|
this.milestoneArray.write(setMilestones);
|
|
1259
|
+
connection.stop();
|
|
1219
1260
|
setConfigSyncResult("nothing to sync");
|
|
1220
1261
|
console.log(`Setting config sync result: "nothing to sync"`);
|
|
1221
1262
|
}
|
|
1222
1263
|
else {
|
|
1223
1264
|
// because it is an important milestone, we always check if we have *just* completed reading
|
|
1224
|
-
if (bReadingComplete
|
|
1265
|
+
if (bReadingComplete) {
|
|
1225
1266
|
this.milestoneArray.read(setMilestones);
|
|
1226
1267
|
setConfigSyncResult("reading complete");
|
|
1227
1268
|
console.log(`Setting config sync result: "reading complete"`);
|
|
@@ -1238,6 +1279,7 @@ export class BatchArray {
|
|
|
1238
1279
|
// with that out of the way, is writing complete?
|
|
1239
1280
|
if (bWritingComplete) {
|
|
1240
1281
|
this.milestoneArray.write(setMilestones);
|
|
1282
|
+
connection.stop();
|
|
1241
1283
|
setConfigSyncResult("sync complete");
|
|
1242
1284
|
console.log(`Setting config sync result: "complete"`);
|
|
1243
1285
|
}
|
|
@@ -1253,6 +1295,7 @@ export class BatchArray {
|
|
|
1253
1295
|
}
|
|
1254
1296
|
}
|
|
1255
1297
|
}
|
|
1298
|
+
|
|
1256
1299
|
// start SignalR connection based on each batchId
|
|
1257
1300
|
batchIdArray.map((batchPair: any) => {
|
|
1258
1301
|
const endpoint: string = mindlineConfig.signalREndpoint();
|
|
@@ -1265,7 +1308,10 @@ export class BatchArray {
|
|
|
1265
1308
|
.configureLogging(signalR.LogLevel.Information)
|
|
1266
1309
|
.build();
|
|
1267
1310
|
// when you get a message, process the message
|
|
1268
|
-
|
|
1311
|
+
if (!!message && JSON.parse(message).TargetID === batchPair.BatchId) {
|
|
1312
|
+
handler(connection)(message)
|
|
1313
|
+
}
|
|
1314
|
+
connection.on("newMessage", handler(connection));
|
|
1269
1315
|
connection.onreconnecting(error => {
|
|
1270
1316
|
console.assert(connection.state === signalR.HubConnectionState.Reconnecting);
|
|
1271
1317
|
console.log(`Connection lost due to error "${error}". Reconnecting.`);
|
|
@@ -1284,8 +1330,7 @@ export class BatchArray {
|
|
|
1284
1330
|
});
|
|
1285
1331
|
}
|
|
1286
1332
|
// start a sync cycle
|
|
1287
|
-
async startSync(instance: IPublicClientApplication, authorizedUser: User | null | undefined, config: SyncConfig | null | undefined): Promise<APIResult>
|
|
1288
|
-
{
|
|
1333
|
+
async startSync(instance: IPublicClientApplication, authorizedUser: User | null | undefined, config: SyncConfig | null | undefined): Promise<APIResult> {
|
|
1289
1334
|
let result: APIResult = new APIResult();
|
|
1290
1335
|
if (this.tenantNodes == null || this.tenantNodes.length == 0) {
|
|
1291
1336
|
// we should not have an empty batch array for a test
|
|
@@ -1308,8 +1353,9 @@ export class TenantNode {
|
|
|
1308
1353
|
batchId: string;
|
|
1309
1354
|
total: number = 0;
|
|
1310
1355
|
read: number = 0;
|
|
1356
|
+
excluded: number = 0;
|
|
1311
1357
|
written: number = 0;
|
|
1312
|
-
deferred: number =0
|
|
1358
|
+
deferred: number = 0;
|
|
1313
1359
|
nothingtosync: boolean;
|
|
1314
1360
|
targets: TenantNode[];
|
|
1315
1361
|
constructor(tid: string, name: string, batchId: string) {
|
|
@@ -1319,22 +1365,23 @@ export class TenantNode {
|
|
|
1319
1365
|
this.batchId = batchId;
|
|
1320
1366
|
this.nothingtosync = false;
|
|
1321
1367
|
this.targets = new Array<TenantNode>();
|
|
1322
|
-
this.update(0, 0, 0, 0);
|
|
1368
|
+
this.update(0, 0, 0, 0, 0);
|
|
1323
1369
|
}
|
|
1324
|
-
update(total: number, read: number, written: number, deferred: number): void {
|
|
1370
|
+
update(total: number, read: number, excluded: number, written: number, deferred: number): void {
|
|
1325
1371
|
this.total = total;
|
|
1326
1372
|
this.read = read;
|
|
1373
|
+
this.excluded = excluded;
|
|
1327
1374
|
this.written = written;
|
|
1328
1375
|
this.deferred = deferred;
|
|
1329
1376
|
if (this.read === 0 && this.written === 0) this.status = "not started";
|
|
1330
1377
|
if (this.read > 0) {
|
|
1331
|
-
if (this.read < this.total) this.status = "in progress";
|
|
1332
|
-
else if (this.read === this.total) this.status = "complete";
|
|
1378
|
+
if (this.read + this.excluded < this.total) this.status = "in progress";
|
|
1379
|
+
else if (this.read + this.excluded === this.total) this.status = "complete";
|
|
1333
1380
|
}
|
|
1334
1381
|
else if (this.written > 0) {
|
|
1335
|
-
if (this.written + this.deferred < this.total) this.status = "in progress";
|
|
1336
|
-
else if (this.written === this.total) this.status = "complete";
|
|
1337
|
-
else if (this.written + this.deferred >= this.total) this.status = "failed";
|
|
1382
|
+
if (this.written + this.deferred + this.excluded < this.total) this.status = "in progress";
|
|
1383
|
+
else if (this.written + this.deferred + this.excluded === this.total) this.status = "complete";
|
|
1384
|
+
else if (this.written + this.deferred + this.excluded >= this.total) this.status = "failed";
|
|
1338
1385
|
}
|
|
1339
1386
|
}
|
|
1340
1387
|
}
|
|
@@ -1549,7 +1596,7 @@ export async function groupsGet(instance: IPublicClientApplication, user: User |
|
|
|
1549
1596
|
return { groups: [], error: `Exception: ${error}` };
|
|
1550
1597
|
}
|
|
1551
1598
|
}
|
|
1552
|
-
export async function oauth2PermissionGrantsGet(options: RequestInit, user: User, spid: string, oid: string): Promise<{ grants: string|null, id: string|null, error: string }> {
|
|
1599
|
+
export async function oauth2PermissionGrantsGet(options: RequestInit, user: User, spid: string, oid: string): Promise<{ grants: string | null, id: string | null, error: string }> {
|
|
1553
1600
|
try {
|
|
1554
1601
|
// make /oauth2PermissionGrants endpoint call
|
|
1555
1602
|
let spurl: string = getGraphEndpoint(user.authority) + graphConfig.graphOauth2PermissionGrantsPredicate;
|
|
@@ -1730,7 +1777,7 @@ export function signInIncrementally(user: User, scope: string): void {
|
|
|
1730
1777
|
url.searchParams.append("loginHint", user.mail);
|
|
1731
1778
|
window.location.assign(url.href);
|
|
1732
1779
|
}
|
|
1733
|
-
export async function signOut(user: User): Promise<boolean>{
|
|
1780
|
+
export async function signOut(user: User): Promise<boolean> {
|
|
1734
1781
|
if (user.oid == "1") return false;
|
|
1735
1782
|
// set logout_hint in the .NET session for streamlined logout
|
|
1736
1783
|
let userEndpoint: string = window.location.href;
|
|
@@ -1941,7 +1988,7 @@ export async function tenantUnauthenticatedLookup(tenant: Tenant, debug: boolean
|
|
|
1941
1988
|
}
|
|
1942
1989
|
return false; // failed, no need for UX to re-render
|
|
1943
1990
|
}
|
|
1944
|
-
export async function userDelegatedScopesGet(instance: IPublicClientApplication, loggedInUser: User, tenant: Tenant): Promise<{ scopes: string|null, id: string|null, error: string }> {
|
|
1991
|
+
export async function userDelegatedScopesGet(instance: IPublicClientApplication, loggedInUser: User, tenant: Tenant): Promise<{ scopes: string | null, id: string | null, error: string }> {
|
|
1945
1992
|
// need a logged in user and valid tenant to query graph
|
|
1946
1993
|
if (loggedInUser == null || loggedInUser.spacode == "" || tenant == null) {
|
|
1947
1994
|
debugger;
|
|
@@ -2053,13 +2100,18 @@ export async function configEdit(
|
|
|
2053
2100
|
setSelectedConfigs: (selectedConfigs: { [id: string]: boolean | number[] }) => void,
|
|
2054
2101
|
workspace: Workspace,
|
|
2055
2102
|
ii: InitInfo,
|
|
2056
|
-
debug: boolean): Promise<APIResult>
|
|
2057
|
-
{
|
|
2103
|
+
debug: boolean): Promise<APIResult> {
|
|
2058
2104
|
let result: APIResult = new APIResult();
|
|
2059
2105
|
if (config.id === "1") {
|
|
2060
2106
|
result = await configPost(instance, authorizedUser, config, workspace.id, debug);
|
|
2061
2107
|
if (result.result) {
|
|
2062
2108
|
// config id was updated from "1"
|
|
2109
|
+
// Update all TCI configIds to reference the new config ID
|
|
2110
|
+
config.tenants.forEach((tci) => {
|
|
2111
|
+
if (tci.configId === "1" || tci.configId === "") {
|
|
2112
|
+
tci.configId = config.id;
|
|
2113
|
+
}
|
|
2114
|
+
});
|
|
2063
2115
|
if (setConfigId) {
|
|
2064
2116
|
setConfigId(config.id);
|
|
2065
2117
|
}
|
|
@@ -2098,7 +2150,7 @@ export async function configConsentForRead(instance: IPublicClientApplication, a
|
|
|
2098
2150
|
export async function configConsentForWrite(instance: IPublicClientApplication, authorizedUser: User, configId: string, tid: string, consent: boolean): Promise<APIResult> {
|
|
2099
2151
|
return configConsentWritePut(instance, authorizedUser, configId, tid, consent);
|
|
2100
2152
|
}
|
|
2101
|
-
export async function configsRefresh(instance: IPublicClientApplication, authorizedUser: User, workspaceId: string, ii: InitInfo, debug: boolean): Promise<APIResult> {
|
|
2153
|
+
export async function configsRefresh(instance: IPublicClientApplication, authorizedUser: User, workspaceId: string, ii: InitInfo, debug: boolean, currentConfig: SyncConfig): Promise<APIResult> {
|
|
2102
2154
|
let result: APIResult = new APIResult();
|
|
2103
2155
|
if (debug) debugger;
|
|
2104
2156
|
try {
|
|
@@ -2107,26 +2159,35 @@ export async function configsRefresh(instance: IPublicClientApplication, authori
|
|
|
2107
2159
|
// clear SyncConfig associations as we are about to reset
|
|
2108
2160
|
workspace.associatedConfigs.length = 0;
|
|
2109
2161
|
// GET configs associated with this workspace
|
|
2110
|
-
let result: APIResult = await
|
|
2162
|
+
let result: APIResult = await configGet(instance, authorizedUser, currentConfig, workspace.id, debug);
|
|
2111
2163
|
if (!result.result) return result;
|
|
2112
2164
|
// process returned workspace components
|
|
2113
|
-
let configSelectedId: string = "";
|
|
2114
|
-
for (let cid of workspace.associatedConfigs) {
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2165
|
+
// let configSelectedId: string = "";
|
|
2166
|
+
// for (let cid of workspace.associatedConfigs) {
|
|
2167
|
+
// let config = ii.cs.find((c: SyncConfig) => c.id === cid);
|
|
2168
|
+
// if (config != null && config.sel) {
|
|
2169
|
+
// ii.cs.find((c: SyncConfig) => c.id === cid) ??
|
|
2170
|
+
// ii.acs.find((a: AuditConfig) => a.id === cid);
|
|
2119
2171
|
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2172
|
+
// if (config && config.sel) {
|
|
2173
|
+
// configSelectedId = config.id;
|
|
2174
|
+
// }
|
|
2175
|
+
// }
|
|
2124
2176
|
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2177
|
+
// // Pass combined list to processor
|
|
2178
|
+
// processReturnedConfigs(workspace, ii, result.array!, currentConfig.id);
|
|
2179
|
+
// console.log("Init Info-----------", ii)
|
|
2180
|
+
// console.log("Init Info-----------", configSelectedId)
|
|
2181
|
+
// // tag components with workspaceIDs
|
|
2182
|
+
// ii.tagWithWorkspaces();
|
|
2183
|
+
// localStorage.setItem("BatchIdArray", "{}");
|
|
2184
|
+
// }
|
|
2185
|
+
// processReturnedConfigs(workspace, ii, result.array!, currentConfig.id);
|
|
2186
|
+
// console.log("Init Info-----------", ii)
|
|
2187
|
+
// console.log("Init Info-----------", currentConfig.id)
|
|
2188
|
+
// tag components with workspaceIDs
|
|
2189
|
+
ii.tagWithWorkspaces();
|
|
2190
|
+
localStorage.setItem("BatchIdArray", "{}");
|
|
2130
2191
|
return result;
|
|
2131
2192
|
} else {
|
|
2132
2193
|
// workspace not found
|
|
@@ -2200,8 +2261,7 @@ export async function userAdd(instance: IPublicClientApplication, authorizedUser
|
|
|
2200
2261
|
export async function userRemove(instance: IPublicClientApplication, authorizedUser: User, user: User, workspaceId: string): Promise<APIResult> {
|
|
2201
2262
|
return adminDelete(instance, authorizedUser, user, workspaceId);
|
|
2202
2263
|
}
|
|
2203
|
-
export async function workspaceEdit(instance: IPublicClientApplication, authorizedUser: User, workspaceId: string, workspaceName: string): Promise<APIResult>
|
|
2204
|
-
{
|
|
2264
|
+
export async function workspaceEdit(instance: IPublicClientApplication, authorizedUser: User, workspaceId: string, workspaceName: string): Promise<APIResult> {
|
|
2205
2265
|
return await workspacePut(instance, authorizedUser, workspaceId, workspaceName);
|
|
2206
2266
|
}
|
|
2207
2267
|
// retrieve Workspace(s), User(s), Tenant(s), SyncConfig(s) given newly logged in user
|
|
@@ -2359,6 +2419,7 @@ function processReturnedConfigs(workspace: Workspace, ii: InitInfo, returnedConf
|
|
|
2359
2419
|
let idx = workspace.associatedConfigs.findIndex((c) => c === item.id);
|
|
2360
2420
|
if (idx == -1) workspace.associatedConfigs.push(item.id);
|
|
2361
2421
|
});
|
|
2422
|
+
console.log("--------------ii-----------", ii)
|
|
2362
2423
|
ii.save();
|
|
2363
2424
|
}
|
|
2364
2425
|
async function workspaceInfoGet(instance: IPublicClientApplication, user: User, ii: InitInfo, debug: boolean): Promise<APIResult> {
|
|
@@ -2463,9 +2524,9 @@ export async function getPowerBIAccessToken(
|
|
|
2463
2524
|
}
|
|
2464
2525
|
let response: AuthenticationResult = await instance.acquireTokenSilent({
|
|
2465
2526
|
scopes: ["https://analysis.windows.net/powerbi/api/App.Read.All",
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2527
|
+
"https://analysis.windows.net/powerbi/api/Dataset.ReadWrite.All",
|
|
2528
|
+
"https://analysis.windows.net/powerbi/api/Report.ReadWrite.All",
|
|
2529
|
+
"https://analysis.windows.net/powerbi/api/Workspace.ReadWrite.All"
|
|
2469
2530
|
],
|
|
2470
2531
|
account: account!
|
|
2471
2532
|
});
|
|
@@ -2586,7 +2647,7 @@ export async function elevateGlobalAdminToUserAccessAdmin(instance: IPublicClien
|
|
|
2586
2647
|
console.log(error);
|
|
2587
2648
|
return false;
|
|
2588
2649
|
}
|
|
2589
|
-
return true;
|
|
2650
|
+
return true;
|
|
2590
2651
|
}
|
|
2591
2652
|
async function readResources(instance: IPublicClientApplication, user: User): Promise<ResourceNode[]> {
|
|
2592
2653
|
// need a logged in user to call Azure REST API
|
|
@@ -3256,6 +3317,56 @@ export async function configConsentWritePut(instance: IPublicClientApplication,
|
|
|
3256
3317
|
return result;
|
|
3257
3318
|
}
|
|
3258
3319
|
//configDelete
|
|
3320
|
+
export async function configGet(
|
|
3321
|
+
instance: IPublicClientApplication,
|
|
3322
|
+
authorizedUser: User,
|
|
3323
|
+
config: SyncConfig,
|
|
3324
|
+
workspaceId: string,
|
|
3325
|
+
debug: boolean
|
|
3326
|
+
): Promise<APIResult> {
|
|
3327
|
+
debug = debug;
|
|
3328
|
+
let result: APIResult = new APIResult();
|
|
3329
|
+
if (config.id === "" || workspaceId == "") {
|
|
3330
|
+
result.result = false;
|
|
3331
|
+
result.error = "configGet: invalid config ID";
|
|
3332
|
+
result.status = 500;
|
|
3333
|
+
return result;
|
|
3334
|
+
}
|
|
3335
|
+
let url: URL | null = null;
|
|
3336
|
+
url = new URL(mindlineConfig.configEndpoint());
|
|
3337
|
+
// create headers
|
|
3338
|
+
const headers = await mindlineDefineHeaders(instance, authorizedUser);
|
|
3339
|
+
// make endpoint call
|
|
3340
|
+
let options = { method: "GET", headers: headers };
|
|
3341
|
+
try {
|
|
3342
|
+
console.log("Attempting GET from /config: " + url.href);
|
|
3343
|
+
let response = await fetch(`${url.href}/${config.id}`, options);
|
|
3344
|
+
if (response.status === 200 && response.statusText === "OK") {
|
|
3345
|
+
console.log(`Successful GET from /config`);
|
|
3346
|
+
let data = await response.json()
|
|
3347
|
+
return {
|
|
3348
|
+
...result,
|
|
3349
|
+
array: [data]
|
|
3350
|
+
};
|
|
3351
|
+
}
|
|
3352
|
+
else {
|
|
3353
|
+
result.error = await processErrors(response);
|
|
3354
|
+
console.log(`Failed GET from ${url.href}`);
|
|
3355
|
+
console.log(result.error);
|
|
3356
|
+
result.status = 500;
|
|
3357
|
+
result.result = false;
|
|
3358
|
+
return result;
|
|
3359
|
+
}
|
|
3360
|
+
}
|
|
3361
|
+
catch (error: any) {
|
|
3362
|
+
result.error = error.message;
|
|
3363
|
+
result.status = 500;
|
|
3364
|
+
result.result = false;
|
|
3365
|
+
console.log(error.message);
|
|
3366
|
+
}
|
|
3367
|
+
return result;
|
|
3368
|
+
}
|
|
3369
|
+
//configDelete
|
|
3259
3370
|
export async function configDelete(
|
|
3260
3371
|
instance: IPublicClientApplication,
|
|
3261
3372
|
authorizedUser: User,
|
|
@@ -3393,7 +3504,9 @@ export async function configPost(
|
|
|
3393
3504
|
"sourceGroupName": ${sourceGroupName},
|
|
3394
3505
|
"targetGroupId": ${targetGroupId},
|
|
3395
3506
|
"targetGroupName": ${targetGroupName},
|
|
3396
|
-
"configurationTenantType": "${tci.configurationTenantType}"
|
|
3507
|
+
"configurationTenantType": "${tci.configurationTenantType}",
|
|
3508
|
+
"isReadPermissionConsented": ${tci.isReadPermissionConsented},
|
|
3509
|
+
"isWritePermissionConsented": ${tci.isWritePermissionConsented}
|
|
3397
3510
|
}`;
|
|
3398
3511
|
});
|
|
3399
3512
|
configBody += `]}`;
|
|
@@ -3405,9 +3518,10 @@ export async function configPost(
|
|
|
3405
3518
|
let response = await fetch(endpoint, options);
|
|
3406
3519
|
if (response.status === 200 && response.statusText === "OK") {
|
|
3407
3520
|
let data = await response.json();
|
|
3408
|
-
|
|
3521
|
+
// API returns an object {id: "..."} or just the ID string directly
|
|
3522
|
+
config.id = (typeof data === 'object' && data !== null && data.id) ? data.id : data;
|
|
3409
3523
|
console.log(
|
|
3410
|
-
`Successful ConfigID: ${
|
|
3524
|
+
`Successful ConfigID: ${config.id} from POST to /config: ${configBody}`
|
|
3411
3525
|
);
|
|
3412
3526
|
return result;
|
|
3413
3527
|
}
|
|
@@ -3470,7 +3584,9 @@ export async function configPut(
|
|
|
3470
3584
|
"targetGroupId": ${targetGroupId},
|
|
3471
3585
|
"targetGroupName": ${targetGroupName},
|
|
3472
3586
|
"configurationTenantType": "${tci.configurationTenantType}",
|
|
3473
|
-
"deltaToken": "${tci.deltaToken}"
|
|
3587
|
+
"deltaToken": "${tci.deltaToken}",
|
|
3588
|
+
"isReadPermissionConsented": ${tci.isReadPermissionConsented},
|
|
3589
|
+
"isWritePermissionConsented": ${tci.isWritePermissionConsented}
|
|
3474
3590
|
}`;
|
|
3475
3591
|
});
|
|
3476
3592
|
configBody += `]}`;
|
|
@@ -3482,7 +3598,11 @@ export async function configPut(
|
|
|
3482
3598
|
let response = await fetch(url.href, options);
|
|
3483
3599
|
if (response.status === 200 && response.statusText === "OK") {
|
|
3484
3600
|
console.log(`Successful PUT to ${url.href}: ${configBody}`);
|
|
3485
|
-
|
|
3601
|
+
let data = await response.json();
|
|
3602
|
+
return {
|
|
3603
|
+
...result,
|
|
3604
|
+
array: [data]
|
|
3605
|
+
};
|
|
3486
3606
|
}
|
|
3487
3607
|
else {
|
|
3488
3608
|
result.error = await processErrors(response);
|
|
@@ -3609,7 +3729,7 @@ export async function workspaceConfigsGet(
|
|
|
3609
3729
|
}));
|
|
3610
3730
|
|
|
3611
3731
|
console.log(
|
|
3612
|
-
`workspaceConfigsGet: found ${result.array.length} configs.`
|
|
3732
|
+
`workspaceConfigsGet: found ${result.array.length} configs.`
|
|
3613
3733
|
);
|
|
3614
3734
|
return result;
|
|
3615
3735
|
} else {
|
|
@@ -4005,4 +4125,55 @@ export async function readerPost(
|
|
|
4005
4125
|
console.log(error.message);
|
|
4006
4126
|
}
|
|
4007
4127
|
return result;
|
|
4128
|
+
}
|
|
4129
|
+
//readStats
|
|
4130
|
+
export async function readerStats(
|
|
4131
|
+
instance: IPublicClientApplication,
|
|
4132
|
+
authorizedUser: User,
|
|
4133
|
+
tenantId: String
|
|
4134
|
+
): Promise<APIResult> {
|
|
4135
|
+
let result: APIResult = new APIResult();
|
|
4136
|
+
if (instance == null || authorizedUser == null) {
|
|
4137
|
+
result.result = false;
|
|
4138
|
+
result.error = "readerPost: invalid parameters";
|
|
4139
|
+
result.status = 500;
|
|
4140
|
+
return result;
|
|
4141
|
+
}
|
|
4142
|
+
// create reader endpoint
|
|
4143
|
+
let stasEndpoint: string = mindlineConfig.statsEndpoint();
|
|
4144
|
+
let url: URL = new URL(`${stasEndpoint}/${tenantId}`);
|
|
4145
|
+
// create headers
|
|
4146
|
+
const headers = await mindlineDefineHeaders(instance, authorizedUser);
|
|
4147
|
+
// make reader endpoint call
|
|
4148
|
+
let options = { method: "GET", headers: headers };
|
|
4149
|
+
try {
|
|
4150
|
+
console.log("Attempting GET to /stats: " + url.href);
|
|
4151
|
+
let response = await fetch(url.href, options);
|
|
4152
|
+
if (response.status === 200 && response.statusText === "OK") {
|
|
4153
|
+
console.log(`Successful GET to /stats: ${stasEndpoint}`);
|
|
4154
|
+
let jsonResponse = await response.json();
|
|
4155
|
+
result.array = [jsonResponse];
|
|
4156
|
+
return result;
|
|
4157
|
+
} else if (response.status === 204) {
|
|
4158
|
+
result.error = await processErrors(response);
|
|
4159
|
+
console.log(`Failed GET to /stats: ${stasEndpoint}`);
|
|
4160
|
+
console.log(result.error);
|
|
4161
|
+
result.status = 204;
|
|
4162
|
+
result.result = false;
|
|
4163
|
+
return result;
|
|
4164
|
+
} else {
|
|
4165
|
+
result.error = await processErrors(response);
|
|
4166
|
+
console.log(`Failed GET to /stats: ${stasEndpoint}`);
|
|
4167
|
+
console.log(result.error);
|
|
4168
|
+
result.status = 500;
|
|
4169
|
+
result.result = false;
|
|
4170
|
+
return result;
|
|
4171
|
+
}
|
|
4172
|
+
} catch (error: any) {
|
|
4173
|
+
result.error = error.message;
|
|
4174
|
+
result.status = 500;
|
|
4175
|
+
result.result = false;
|
|
4176
|
+
console.log(error.message);
|
|
4177
|
+
}
|
|
4178
|
+
return result;
|
|
4008
4179
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|