@powerhousedao/academy 4.1.0-dev.9 → 4.1.0-dev.90
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/.vscode/settings.json +1 -1
- package/CHANGELOG.md +672 -0
- package/README.md +3 -3
- package/babel.config.js +1 -1
- package/blog/BeyondCommunication-ABlueprintForDevelopment.md +25 -24
- package/blog/TheChallengeOfChange.md +21 -21
- package/docs/academy/01-GetStarted/00-ExploreDemoPackage.mdx +67 -30
- package/docs/academy/01-GetStarted/01-CreateNewPowerhouseProject.md +38 -21
- package/docs/academy/01-GetStarted/02-DefineToDoListDocumentModel.md +24 -19
- package/docs/academy/01-GetStarted/03-ImplementOperationReducers.md +44 -41
- package/docs/academy/01-GetStarted/04-BuildToDoListEditor.md +10 -10
- package/docs/academy/01-GetStarted/05-VetraStudio.md +164 -0
- package/docs/academy/01-GetStarted/06-ReactorMCP.md +58 -0
- package/docs/academy/01-GetStarted/home.mdx +185 -90
- package/docs/academy/01-GetStarted/images/Modules.png +0 -0
- package/docs/academy/01-GetStarted/images/VetraStudioDrive.png +0 -0
- package/docs/academy/01-GetStarted/styles.module.css +5 -5
- package/docs/academy/02-MasteryTrack/01-BuilderEnvironment/01-Prerequisites.md +46 -18
- package/docs/academy/02-MasteryTrack/01-BuilderEnvironment/02-StandardDocumentModelWorkflow.md +118 -68
- package/docs/academy/02-MasteryTrack/01-BuilderEnvironment/03-BuilderTools.md +75 -33
- package/docs/academy/02-MasteryTrack/01-BuilderEnvironment/_category_.json +6 -6
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/01-WhatIsADocumentModel.md +30 -21
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/02-SpecifyTheStateSchema.md +41 -37
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/03-SpecifyDocumentOperations.md +29 -25
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/04-UseTheDocumentModelGenerator.md +36 -37
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/05-ImplementDocumentReducers.md +128 -109
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/06-ImplementDocumentModelTests.md +95 -86
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/07-ExampleToDoListRepository.md +7 -9
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/_category_.json +6 -6
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/01-BuildingDocumentEditors.md +65 -47
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/02-ConfiguringDrives.md +77 -62
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/03-BuildingADriveExplorer.md +360 -349
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/06-DocumentTools/00-DocumentToolbar.mdx +16 -10
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/06-DocumentTools/01-OperationHistory.md +10 -7
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/06-DocumentTools/02-RevisionHistoryTimeline.md +25 -17
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/06-DocumentTools/_category_.json +6 -6
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/07-Authorization/01-RenownAuthenticationFlow.md +14 -7
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/07-Authorization/02-Authorization.md +0 -1
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/07-Authorization/_category_.json +5 -5
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/_category_.json +1 -1
- package/docs/academy/02-MasteryTrack/04-WorkWithData/01-GraphQLAtPowerhouse.md +45 -33
- package/docs/academy/02-MasteryTrack/04-WorkWithData/02-UsingTheAPI.mdx +61 -18
- package/docs/academy/02-MasteryTrack/04-WorkWithData/03-UsingSubgraphs.md +105 -456
- package/docs/academy/02-MasteryTrack/04-WorkWithData/04-analytics-processor.md +126 -110
- package/docs/academy/02-MasteryTrack/04-WorkWithData/05-RelationalDbProcessor.md +98 -65
- package/docs/academy/02-MasteryTrack/04-WorkWithData/06-Analytics Engine/GraphQL References/QueryingADocumentWithGraphQL.md +23 -21
- package/docs/academy/02-MasteryTrack/04-WorkWithData/06-Analytics Engine/best-practices.md +9 -9
- package/docs/academy/02-MasteryTrack/04-WorkWithData/06-Analytics Engine/graphql/index.md +11 -23
- package/docs/academy/02-MasteryTrack/04-WorkWithData/06-Analytics Engine/graphql/integration.md +25 -9
- package/docs/academy/02-MasteryTrack/04-WorkWithData/06-Analytics Engine/intro.md +10 -10
- package/docs/academy/02-MasteryTrack/04-WorkWithData/06-Analytics Engine/typescript/benchmarks.md +1 -1
- package/docs/academy/02-MasteryTrack/04-WorkWithData/06-Analytics Engine/typescript/index.md +16 -11
- package/docs/academy/02-MasteryTrack/04-WorkWithData/06-Analytics Engine/typescript/memory.md +6 -5
- package/docs/academy/02-MasteryTrack/04-WorkWithData/06-Analytics Engine/typescript/schema.md +2 -2
- package/docs/academy/02-MasteryTrack/04-WorkWithData/06-Analytics Engine/typescript/utilities.md +7 -5
- package/docs/academy/02-MasteryTrack/04-WorkWithData/06-Analytics Engine/use-cases/maker.md +32 -58
- package/docs/academy/02-MasteryTrack/04-WorkWithData/06-Analytics Engine/use-cases/processors.md +1 -1
- package/docs/academy/02-MasteryTrack/04-WorkWithData/07-drive-analytics.md +105 -71
- package/docs/academy/02-MasteryTrack/04-WorkWithData/_ARCHIVE-AnalyticsProcessorTutorial/_01-SetupBuilderEnvironment.md +22 -0
- package/docs/academy/02-MasteryTrack/04-WorkWithData/_ARCHIVE-AnalyticsProcessorTutorial/_02-CreateNewPowerhouseProject.md +9 -8
- package/docs/academy/02-MasteryTrack/04-WorkWithData/_ARCHIVE-AnalyticsProcessorTutorial/_03-GenerateAnAnalyticsProcessor.md +28 -32
- package/docs/academy/02-MasteryTrack/04-WorkWithData/_ARCHIVE-AnalyticsProcessorTutorial/_04-UpdateAnalyticsProcessor.md +25 -26
- package/docs/academy/02-MasteryTrack/04-WorkWithData/_ARCHIVE-AnalyticsProcessorTutorial/_category_.json +1 -1
- package/docs/academy/02-MasteryTrack/04-WorkWithData/_category_.json +7 -7
- package/docs/academy/02-MasteryTrack/05-Launch/01-IntroductionToPackages.md +3 -4
- package/docs/academy/02-MasteryTrack/05-Launch/02-PublishYourProject.md +69 -45
- package/docs/academy/02-MasteryTrack/05-Launch/03-SetupEnvironment.md +70 -40
- package/docs/academy/02-MasteryTrack/05-Launch/04-ConfigureEnvironment.md +1 -0
- package/docs/academy/02-MasteryTrack/05-Launch/_category_.json +7 -7
- package/docs/academy/02-MasteryTrack/_category_.json +6 -6
- package/docs/academy/03-ExampleUsecases/Chatroom/02-CreateNewPowerhouseProject.md +5 -3
- package/docs/academy/03-ExampleUsecases/Chatroom/03-DefineChatroomDocumentModel.md +38 -37
- package/docs/academy/03-ExampleUsecases/Chatroom/04-ImplementOperationReducers.md +45 -41
- package/docs/academy/03-ExampleUsecases/Chatroom/05-ImplementChatroomEditor.md +14 -14
- package/docs/academy/03-ExampleUsecases/Chatroom/06-LaunchALocalReactor.md +6 -6
- package/docs/academy/03-ExampleUsecases/Chatroom/_category_.json +1 -1
- package/docs/academy/04-APIReferences/00-PowerhouseCLI.md +142 -63
- package/docs/academy/04-APIReferences/01-ReactHooks.md +649 -141
- package/docs/academy/04-APIReferences/04-RelationalDatabase.md +121 -113
- package/docs/academy/04-APIReferences/05-PHDocumentMigrationGuide.md +48 -41
- package/docs/academy/04-APIReferences/_category_.json +6 -6
- package/docs/academy/05-Architecture/00-PowerhouseArchitecture.md +1 -2
- package/docs/academy/05-Architecture/01-WorkingWithTheReactor.md +11 -8
- package/docs/academy/05-Architecture/05-DocumentModelTheory/_category_.json +1 -1
- package/docs/academy/05-Architecture/_category_.json +6 -6
- package/docs/academy/06-ComponentLibrary/00-DocumentEngineering.md +25 -23
- package/docs/academy/06-ComponentLibrary/02-CreateCustomScalars.md +105 -93
- package/docs/academy/06-ComponentLibrary/03-IntegrateIntoAReactComponent.md +1 -0
- package/docs/academy/06-ComponentLibrary/_category_.json +7 -7
- package/docs/academy/07-Cookbook.md +268 -35
- package/docs/academy/08-Glossary.md +7 -1
- package/docs/bookofpowerhouse/01-Overview.md +2 -2
- package/docs/bookofpowerhouse/02-GeneralFrameworkAndPhilosophy.md +1 -7
- package/docs/bookofpowerhouse/03-PowerhouseSoftwareArchitecture.md +10 -7
- package/docs/bookofpowerhouse/04-DevelopmentApproaches.md +10 -4
- package/docs/bookofpowerhouse/05-SNOsandANewModelForOSSandPublicGoods.md +23 -30
- package/docs/bookofpowerhouse/06-SNOsInActionAndPlatformEconomies.md +0 -7
- package/docusaurus.config.ts +64 -66
- package/package.json +9 -7
- package/scripts/generate-combined-cli-docs.ts +43 -13
- package/sidebars.ts +2 -0
- package/src/components/HomepageFeatures/index.tsx +171 -78
- package/src/components/HomepageFeatures/styles.module.css +1 -2
- package/src/css/custom.css +89 -89
- package/src/pages/_archive-homepage.tsx +17 -16
- package/src/theme/DocCardList/index.tsx +9 -8
- package/static.json +6 -6
- package/tsconfig.tsbuildinfo +1 -0
|
@@ -152,9 +152,7 @@ const dimensions = {
|
|
|
152
152
|
asset: AnalyticsPath.fromString(
|
|
153
153
|
`sky/rwas/assets/t-bills/${fixedIncomeTransaction.assetId}`,
|
|
154
154
|
),
|
|
155
|
-
portfolio: AnalyticsPath.fromString(
|
|
156
|
-
`sky/rwas/portfolios/${documentId}`,
|
|
157
|
-
),
|
|
155
|
+
portfolio: AnalyticsPath.fromString(`sky/rwas/portfolios/${documentId}`),
|
|
158
156
|
};
|
|
159
157
|
|
|
160
158
|
// create the series values
|
|
@@ -202,9 +200,7 @@ With variables:
|
|
|
202
200
|
"granularity": "annual",
|
|
203
201
|
"start": "2024-01-01",
|
|
204
202
|
"end": "2025-01-01",
|
|
205
|
-
"metrics": [
|
|
206
|
-
"AssetBalance",
|
|
207
|
-
],
|
|
203
|
+
"metrics": ["AssetBalance"],
|
|
208
204
|
"dimensions": [
|
|
209
205
|
{
|
|
210
206
|
"name": "asset",
|
|
@@ -220,14 +216,17 @@ With variables:
|
|
|
220
216
|
|
|
221
217
|
The RWA processor example pulls information from operation _inputs_ to insert analytics data. Another use case might be to capture meta-analytics from the states themselves.
|
|
222
218
|
|
|
223
|
-
This processor listens to all documents of type `powerhouse/document-drive`, and since the `document-drive` is itself implemented on top of the document model core systems, this means that we can process all virtual file system operations.
|
|
219
|
+
This processor listens to all documents of type `powerhouse/document-drive`, and since the `document-drive` is itself implemented on top of the document model core systems, this means that we can process all virtual file system operations. This processor count basic usage metrics using document operations and states.
|
|
224
220
|
|
|
225
221
|
```typescript
|
|
226
222
|
import { IAnalyticsStore } from "@powerhousedao/reactor-api";
|
|
227
223
|
import { AnalyticsPath } from "@powerhousedao/reactor-api";
|
|
228
224
|
import { AnalyticsSeriesInput } from "@powerhousedao/reactor-api";
|
|
229
225
|
import { InternalTransmitterUpdate, IProcessor } from "document-drive";
|
|
230
|
-
import {
|
|
226
|
+
import {
|
|
227
|
+
AddFileInput,
|
|
228
|
+
DeleteNodeInput,
|
|
229
|
+
} from "document-drive/drive-document-model/gen/types";
|
|
231
230
|
import { PHDocument } from "document-model";
|
|
232
231
|
import { DateTime } from "luxon";
|
|
233
232
|
|
|
@@ -247,91 +246,103 @@ export class DriveProcessorProcessor implements IProcessor {
|
|
|
247
246
|
constructor(private readonly analyticsStore: IAnalyticsStore) {
|
|
248
247
|
//
|
|
249
248
|
}
|
|
250
|
-
|
|
249
|
+
|
|
251
250
|
async onStrands<TDocument extends PHDocument>(
|
|
252
|
-
strands: InternalTransmitterUpdate<TDocument>[]
|
|
251
|
+
strands: InternalTransmitterUpdate<TDocument>[],
|
|
253
252
|
): Promise<void> {
|
|
254
253
|
if (strands.length === 0) {
|
|
255
254
|
return;
|
|
256
255
|
}
|
|
257
256
|
|
|
258
|
-
const values:AnalyticsSeriesInput[] = [];
|
|
257
|
+
const values: AnalyticsSeriesInput[] = [];
|
|
259
258
|
|
|
260
259
|
for (const strand of strands) {
|
|
261
260
|
const operations = strand.operations;
|
|
262
|
-
await Promise.all(
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
// lookup node in state
|
|
279
|
-
const input = operation.input as AddFileInput;
|
|
280
|
-
const node = findNode(strand.state, input.id);
|
|
281
|
-
if (!node) {
|
|
282
|
-
return Promise.resolve();
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
dimensions["kind"] = AnalyticsPath.fromString(`document/kind/${node.kind}`);
|
|
286
|
-
|
|
287
|
-
// increment by adding a 1
|
|
288
|
-
values.push({
|
|
289
|
-
source,
|
|
290
|
-
start,
|
|
291
|
-
value: 1,
|
|
292
|
-
metric: "Count",
|
|
293
|
-
dimensions,
|
|
294
|
-
});
|
|
295
|
-
|
|
296
|
-
break;
|
|
297
|
-
}
|
|
298
|
-
case "ADD_FOLDER": {
|
|
299
|
-
dimensions["kind"] = AnalyticsPath.fromString("document/kind/folder");
|
|
300
|
-
|
|
301
|
-
// increment by adding a 1
|
|
302
|
-
values.push({
|
|
303
|
-
source,
|
|
304
|
-
start,
|
|
305
|
-
value: 1,
|
|
306
|
-
metric: "Count",
|
|
307
|
-
dimensions,
|
|
308
|
-
});
|
|
309
|
-
|
|
310
|
-
break;
|
|
261
|
+
await Promise.all(
|
|
262
|
+
operations.map((operation) => {
|
|
263
|
+
const source = AnalyticsPath.fromString(
|
|
264
|
+
`switchboard/default/${strand.driveId}`,
|
|
265
|
+
);
|
|
266
|
+
|
|
267
|
+
const start = DateTime.fromISO(operation.timestamp);
|
|
268
|
+
const dimensions: any = {
|
|
269
|
+
documentType: AnalyticsPath.fromString(
|
|
270
|
+
`document/type/powerhouse/document-drive`,
|
|
271
|
+
),
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
if (operation.index === 0) {
|
|
275
|
+
this.analyticsStore.clearSeriesBySource(source);
|
|
311
276
|
}
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
277
|
+
|
|
278
|
+
switch (operation.type) {
|
|
279
|
+
case "ADD_FILE": {
|
|
280
|
+
// count documents of each type (ADD_FILE, input.documentType)
|
|
281
|
+
|
|
282
|
+
// lookup node in state
|
|
283
|
+
const input = operation.input as AddFileInput;
|
|
284
|
+
const node = findNode(strand.state, input.id);
|
|
285
|
+
if (!node) {
|
|
286
|
+
return Promise.resolve();
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
dimensions["kind"] = AnalyticsPath.fromString(
|
|
290
|
+
`document/kind/${node.kind}`,
|
|
291
|
+
);
|
|
292
|
+
|
|
293
|
+
// increment by adding a 1
|
|
294
|
+
values.push({
|
|
295
|
+
source,
|
|
296
|
+
start,
|
|
297
|
+
value: 1,
|
|
298
|
+
metric: "Count",
|
|
299
|
+
dimensions,
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
break;
|
|
303
|
+
}
|
|
304
|
+
case "ADD_FOLDER": {
|
|
305
|
+
dimensions["kind"] = AnalyticsPath.fromString(
|
|
306
|
+
"document/kind/folder",
|
|
307
|
+
);
|
|
308
|
+
|
|
309
|
+
// increment by adding a 1
|
|
310
|
+
values.push({
|
|
311
|
+
source,
|
|
312
|
+
start,
|
|
313
|
+
value: 1,
|
|
314
|
+
metric: "Count",
|
|
315
|
+
dimensions,
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
break;
|
|
319
|
+
}
|
|
320
|
+
case "DELETE_NODE": {
|
|
321
|
+
// the operation only contains the id, so lookup deleted item type in previous state
|
|
322
|
+
const input = operation.input as DeleteNodeInput;
|
|
323
|
+
const node = findNode(operation.previousState, input.id);
|
|
324
|
+
if (!node) {
|
|
325
|
+
return Promise.resolve();
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
dimensions["kind"] = AnalyticsPath.fromString(
|
|
329
|
+
`document/kind/${node.kind}`,
|
|
330
|
+
);
|
|
331
|
+
|
|
332
|
+
// decrement by adding a -1
|
|
333
|
+
values.push({
|
|
334
|
+
source,
|
|
335
|
+
start,
|
|
336
|
+
value: -1,
|
|
337
|
+
metric: "Count",
|
|
338
|
+
dimensions,
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
break;
|
|
318
342
|
}
|
|
319
|
-
|
|
320
|
-
dimensions["kind"] = AnalyticsPath.fromString(`document/kind/${node.kind}`);
|
|
321
|
-
|
|
322
|
-
// decrement by adding a -1
|
|
323
|
-
values.push({
|
|
324
|
-
source,
|
|
325
|
-
start,
|
|
326
|
-
value: -1,
|
|
327
|
-
metric: "Count",
|
|
328
|
-
dimensions,
|
|
329
|
-
});
|
|
330
|
-
|
|
331
|
-
break;
|
|
332
343
|
}
|
|
333
|
-
}
|
|
334
|
-
|
|
344
|
+
}),
|
|
345
|
+
);
|
|
335
346
|
}
|
|
336
347
|
|
|
337
348
|
await this.analyticsStore.addSeriesValues(values);
|
|
@@ -462,9 +473,12 @@ Now, we can define the dimensions we want to group by. We can imagine that we wi
|
|
|
462
473
|
|
|
463
474
|
```ts
|
|
464
475
|
const totalSpendOnHeadcount = useAnalyticsQuery({
|
|
465
|
-
start,
|
|
476
|
+
start,
|
|
477
|
+
end,
|
|
478
|
+
granularity,
|
|
479
|
+
metrics,
|
|
466
480
|
select: {
|
|
467
|
-
contributor: "/billing-statement/contributor"
|
|
481
|
+
contributor: "/billing-statement/contributor",
|
|
468
482
|
},
|
|
469
483
|
lod: {
|
|
470
484
|
contributor: 3,
|
|
@@ -483,7 +497,7 @@ const totalSpend = useAnalyticsQuery({
|
|
|
483
497
|
granularity: "total", // <--- this means we'll get results for the entire time period
|
|
484
498
|
metrics: ["Cash", "Powt"],
|
|
485
499
|
select: {
|
|
486
|
-
budget: "/billing-statement"
|
|
500
|
+
budget: "/billing-statement",
|
|
487
501
|
},
|
|
488
502
|
lod: {
|
|
489
503
|
budget: 0, // <--- this means we'll get all results lumped together
|
|
@@ -496,7 +510,7 @@ const monthlySpendByBudget = useAnalyticsQuery({
|
|
|
496
510
|
granularity: "monthly", // <--- this means we'll get results grouped by month
|
|
497
511
|
metrics: ["Cash", "Powt"],
|
|
498
512
|
select: {
|
|
499
|
-
budget: "/billing-statement/budget"
|
|
513
|
+
budget: "/billing-statement/budget",
|
|
500
514
|
},
|
|
501
515
|
lod: {
|
|
502
516
|
budget: 3, // <--- this means we'll get results grouped by "/billing-statement/budget/budget1", "/billing-statement/budget/budget2", etc.
|
|
@@ -509,7 +523,7 @@ const monthlySpendByCategory = useAnalyticsQuery({
|
|
|
509
523
|
granularity: "monthly", // <--- this means we'll get results grouped by month
|
|
510
524
|
metrics: ["Cash", "Powt"],
|
|
511
525
|
select: {
|
|
512
|
-
category: "/billing-statement/category"
|
|
526
|
+
category: "/billing-statement/category",
|
|
513
527
|
},
|
|
514
528
|
lod: {
|
|
515
529
|
category: 3, // <--- this means we'll get results grouped by "/billing-statement/category/category1", "/billing-statement/category/category2", etc.
|
|
@@ -522,7 +536,7 @@ const yearlySpendByBudget = useAnalyticsQuery({
|
|
|
522
536
|
granularity: "yearly", // <--- this means we'll get results grouped by year
|
|
523
537
|
metrics: ["Cash", "Powt"],
|
|
524
538
|
select: {
|
|
525
|
-
budget: "/billing-statement/budget"
|
|
539
|
+
budget: "/billing-statement/budget",
|
|
526
540
|
},
|
|
527
541
|
lod: {
|
|
528
542
|
budget: 3, // <--- this means we'll get results grouped by "/billing-statement/budget/budget1", "/billing-statement/budget/budget2", etc.
|
|
@@ -535,7 +549,7 @@ const monthlySpendByBudget = useAnalyticsQuery({
|
|
|
535
549
|
granularity: "monthly", // <--- this means we'll get results grouped by month
|
|
536
550
|
metrics: ["Cash", "Powt"],
|
|
537
551
|
select: {
|
|
538
|
-
budget: "/billing-statement/budget"
|
|
552
|
+
budget: "/billing-statement/budget",
|
|
539
553
|
},
|
|
540
554
|
lod: {
|
|
541
555
|
budget: 3, // <--- this means we'll get results grouped by "/billing-statement/budget/budget1", "/billing-statement/budget/budget2", etc.
|
|
@@ -548,7 +562,7 @@ const last30DaysSpendByBudget = useAnalyticsQuery({
|
|
|
548
562
|
granularity: "day", // <--- this means we'll get results grouped by day
|
|
549
563
|
metrics: ["Cash", "Powt"],
|
|
550
564
|
select: {
|
|
551
|
-
budget: "/billing-statement/budget"
|
|
565
|
+
budget: "/billing-statement/budget",
|
|
552
566
|
},
|
|
553
567
|
lod: {
|
|
554
568
|
budget: 3, // <--- this means we'll get results grouped by "/billing-statement/budget/budget1", "/billing-statement/budget/budget2", etc.
|
|
@@ -568,10 +582,10 @@ For instance, say we take our monthly spend by category query:
|
|
|
568
582
|
const monthlySpendByCategory = useAnalyticsQuery({
|
|
569
583
|
start,
|
|
570
584
|
end,
|
|
571
|
-
granularity: "monthly",
|
|
585
|
+
granularity: "monthly",
|
|
572
586
|
metrics: ["Cash", "Powt"],
|
|
573
587
|
select: {
|
|
574
|
-
category: "/billing-statement/category"
|
|
588
|
+
category: "/billing-statement/category",
|
|
575
589
|
},
|
|
576
590
|
lod: {
|
|
577
591
|
category: 3,
|
|
@@ -583,31 +597,36 @@ This gives us the results we're looking for but, by design, there may be many di
|
|
|
583
597
|
|
|
584
598
|
```ts
|
|
585
599
|
// this source will match all analytics updates from any document in the drive
|
|
586
|
-
const driveSource = AnalyticsPath.fromString(
|
|
600
|
+
const driveSource = AnalyticsPath.fromString(
|
|
601
|
+
`billing-statement/${drive.header.id}`,
|
|
602
|
+
);
|
|
587
603
|
|
|
588
604
|
// this source will match all analytics updates from a specific document in a drive
|
|
589
|
-
const documentSource = AnalyticsPath.fromString(
|
|
605
|
+
const documentSource = AnalyticsPath.fromString(
|
|
606
|
+
`billing-statement/${drive.header.id}/${document.header.id}`,
|
|
607
|
+
);
|
|
590
608
|
```
|
|
591
609
|
|
|
592
610
|
```ts
|
|
593
611
|
const { state, data: drive } = useSelectedDrive();
|
|
594
612
|
|
|
595
|
-
const results = useAnalyticsQuery(
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
613
|
+
const results = useAnalyticsQuery(
|
|
614
|
+
{
|
|
615
|
+
start,
|
|
616
|
+
end,
|
|
617
|
+
granularity: "monthly",
|
|
618
|
+
metrics: ["Cash", "Powt"],
|
|
619
|
+
select: {
|
|
620
|
+
category: "/billing-statement/category",
|
|
621
|
+
},
|
|
622
|
+
lod: {
|
|
623
|
+
category: 3,
|
|
624
|
+
},
|
|
601
625
|
},
|
|
602
|
-
|
|
603
|
-
|
|
626
|
+
{
|
|
627
|
+
sources: [`/billing-statement/${drive.header.id}/`],
|
|
604
628
|
},
|
|
605
|
-
|
|
606
|
-
{
|
|
607
|
-
sources: [
|
|
608
|
-
`/billing-statement/${drive.header.id}/`
|
|
609
|
-
],
|
|
610
|
-
});
|
|
629
|
+
);
|
|
611
630
|
```
|
|
612
631
|
|
|
613
632
|
### `IProcessor`
|
|
@@ -617,6 +636,3 @@ Now that we have designed out our data, we can open up `line-item-processor/inde
|
|
|
617
636
|
```ts
|
|
618
637
|
|
|
619
638
|
```
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|