Skip to content

Commit 96ae18c

Browse files
committed
feat(providence): improve dashboard
1 parent 5d27520 commit 96ae18c

File tree

17 files changed

+332
-209
lines changed

17 files changed

+332
-209
lines changed

.changeset/giant-ears-try.md

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
'providence-analytics': minor
3+
---
4+
5+
Improved dashboard:
6+
7+
- allows to configure categories in `providence.conf.(m)js`that show up in dashboard
8+
- exposes dashboard in cli: `npx providence dashboard`
9+
10+
BREAKING CHANGES:
11+
12+
- `providence.conf.(m)js` must be in ESM format.

.editorconfig

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ trim_trailing_whitespace = true
1212
indent_size = unset
1313
trim_trailing_whitespace = false
1414

15-
[*.{html,js,md,mdx}]
15+
[*.{html,js,mjs,md,mdx}]
1616
block_comment_start = /**
1717
block_comment = *
1818
block_comment_end = */
@@ -23,4 +23,4 @@ indent_style = unset
2323
indent_size = unset
2424
end_of_line = unset
2525
insert_final_newline = unset
26-
trim_trailing_whitespace = unset
26+
trim_trailing_whitespace = unset

docs/docs/node-tools/providence-analytics/LocalConfiguration.md

+10-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
# Node Tools >> Providence Analytics >> Local configuration ||40
22

3-
The file `providence.conf.js` is read by providence cli and by the dashboard to get all
4-
default configurations.
3+
The Providence configuration file is read by providence cli (optional) and by the dashboard (required).
4+
It has a few requirements:
5+
6+
- it must be called `providence.conf.js` or `providence.conf.mjs`
7+
- it must be in ESM format
8+
- it must be located in the root of a repository (under `process.cwd()`)
59

610
## Meta data
711

@@ -11,6 +15,7 @@ Based on the filePath of a result, a category can be added.
1115
For example:
1216

1317
```js
18+
export default {
1419
metaConfig: {
1520
categoryConfig: [
1621
{
@@ -29,6 +34,7 @@ For example:
2934
},
3035
],
3136
},
37+
}
3238
```
3339

3440
> N.B. category info is regarded as subjective, therefore it's advised to move this away from
@@ -38,7 +44,7 @@ For example:
3844

3945
### referenceCollections
4046

41-
A list of file system paths. They can be defined relative from the current project root (`process.cwd()`) or they can be full paths.
47+
A list of file system paths. They can be defined relative from the current project root or they can be full paths.
4248
When a [MatchAnalyzer](../../../docs/node-tools/providence-analytics/analyzer.md) like `match-imports` or `match-subclasses` is used, the default reference(s) can be configured here. For instance: ['/path/to/@lion/form']
4349

4450
An example:
@@ -57,6 +63,6 @@ An example:
5763
### searchTargetCollections
5864

5965
A list of file system paths. They can be defined relative from the current project root
60-
(`process.cwd()`) or they can be full paths.
66+
or they can be full paths.
6167
When not defined, the current project will be the search target (this is most common when
6268
providence is used as a dev dependency).

docs/docs/node-tools/providence-analytics/dashboard.md

+2-4
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,17 @@ application.
66

77
## Run
88

9-
Start the dashboard via `npm run dashboard` to automatically open the browser and start the dashboard.
9+
Start the dashboard via `providence dashboard` to automatically open the browser and start the dashboard.
1010

1111
## Interface
1212

1313
- Select all reference projects
1414
- Select all target projects
1515

16-
Press `show table` to see the result based on the updated configuration.
17-
1816
### Generate csv
1917

2018
When `get csv` is pressed, a `.csv` will be downloaded that can be loaded into Excel.
2119

2220
## Analyzer support
2321

24-
Currently, only the `match-imports` is supported, more analyzers will be added in the future.
22+
Currently, `match-imports` and `match-subclasses` are supported, more analyzers will be added in the future.

docs/docs/node-tools/providence-analytics/overview.md

+15-11
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,11 @@ npm i --save-dev providence-analytics
3838

3939
```json
4040
"scripts": {
41-
"providence": "providence analyze match-imports -r 'node_modules/@lion/*'",
41+
"providence:match-imports": "providence analyze match-imports -r 'node_modules/@lion/*'",
4242
}
4343
```
4444

45-
> The example above illustrates how to run the "match-imports" analyzer for reference project 'lion-based-ui'. Note that it is possible to run other analyzers and configurations supported by providence as well. For a full overview of cli options, run `providence --help`. All supported analyzers will be viewed when running `providence analyze`
45+
> The example above illustrates how to run the "match-imports" analyzer for reference project 'lion-based-ui'. Note that it is possible to run other analyzers and configurations supported by providence as well. For a full overview of cli options, run `npx providence --help`. All supported analyzers will be viewed when running `npx providence analyze`
4646
4747
You are now ready to use providence in your project. All
4848
data will be stored in json files in the folder `./providence-output`
@@ -57,20 +57,21 @@ data will be stored in json files in the folder `./providence-output`
5757
...
5858
"scripts": {
5959
...
60-
"providence:dashboard": "node node_modules/providence/dashboard/src/server.js"
60+
"providence:dashboard": "providence dashboard"
6161
}
6262
```
6363

6464
### Add providence.conf.js
6565

6666
```js
67-
const providenceConfig = {
67+
export default {
6868
referenceCollections: {
69-
'lion-based-ui collection': ['./node_modules/lion-based-ui'],
69+
'lion-based-ui-collection': [
70+
'./node_modules/lion-based-ui/packages/x',
71+
'./node_modules/lion-based-ui/packages/y',
72+
],
7073
},
7174
};
72-
73-
module.exports = providenceConfig;
7475
```
7576

7677
Run `npm run providence:dashboard`
@@ -124,16 +125,16 @@ Providence requires a queries as input.
124125
Queries are defined as objects and can be of two types:
125126

126127
- feature-query
127-
- analyzer
128+
- ast-analyzer
128129

129-
A `queryConfig` is required as input to run the `providenceMain` function.
130+
A `QueryConfig` is required as input to run the `providenceMain` function.
130131
This object specifies the type of query and contains the relevant meta
131132
information that will later be outputted in the `QueryResult` (the JSON object that
132133
the `providenceMain` function returns.)
133134

134135
## Analyzer Query
135136

136-
Analyzers queries are also created via `queryConfig`s.
137+
Analyzer queries are also created via `QueryConfig`s.
137138

138139
Analyzers can be described as predefined queries that use AST traversal.
139140

@@ -147,12 +148,14 @@ Now you will get a list of all predefined analyzers:
147148

148149
- find-imports
149150
- find-exports
151+
- find-classes
150152
- match-imports
151-
- find-subclasses
153+
- match-subclasses
152154
- etc...
153155

154156
![Analyzer query](./assets/analyzer-query.gif 'Analyzer query')
155157

158+
<!--
156159
## Running providence from its own repo
157160
158161
### How to add a new search target project
@@ -186,3 +189,4 @@ Please run:
186189
```bash
187190
sh ./rm-submodule.sh <path/to/submodule>
188191
```
192+
-->

packages-node/providence-analytics/dashboard/src/app/p-board.js

+43-26
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* eslint-disable lit-a11y/no-invalid-change-handler */
12
/* eslint-disable max-classes-per-file */
23
import { LitElement, html, css } from 'lit-element';
34
import { tooltip as tooltipStyles } from './styles/tooltip.css.js';
@@ -15,6 +16,31 @@ PTable.decorateStyles(tableDecoration);
1516

1617
customElements.define('p-table', PTable);
1718

19+
/**
20+
*
21+
* @param {{ project:string, filePath:string, name:string }} specifierRes
22+
* @param {{ categoryConfig:object }} metaConfig
23+
* @returns {string[]}
24+
*/
25+
function getCategoriesForMatchedSpecifier(specifierRes, { metaConfig }) {
26+
const resultCats = [];
27+
28+
if (metaConfig && metaConfig.categoryConfig) {
29+
const { project, filePath, name } = specifierRes.exportSpecifier;
30+
// First of all, do we have a matching project?
31+
// TODO: we should allow different configs for different (major) versions
32+
const match = metaConfig.categoryConfig.find(cat => cat.project === project);
33+
if (match) {
34+
Object.entries(match.categories).forEach(([categoryName, matchFn]) => {
35+
if (matchFn(filePath, name)) {
36+
resultCats.push(categoryName);
37+
}
38+
});
39+
}
40+
}
41+
return resultCats;
42+
}
43+
1844
function checkedValues(checkboxOrNodeList) {
1945
if (!checkboxOrNodeList.length) {
2046
return checkboxOrNodeList.checked && checkboxOrNodeList.value;
@@ -148,14 +174,18 @@ class PBoard extends DecorateMixin(LitElement) {
148174

149175
_activeAnalyzerSelectTemplate() {
150176
return html`
151-
<select id="active-analyzer">
177+
<select id="active-analyzer" @change="${this._onActiveAnalyzerChanged}">
152178
${Object.keys(this.__resultFiles).map(
153179
analyzerName => html` <option value="${analyzerName}">${analyzerName}</option> `,
154180
)}
155181
</select>
156182
`;
157183
}
158184

185+
_onActiveAnalyzerChanged() {
186+
this._aggregateResults();
187+
}
188+
159189
get _selectionMenuFormNode() {
160190
return this.shadowRoot.getElementById('selection-menu-form');
161191
}
@@ -228,7 +258,7 @@ class PBoard extends DecorateMixin(LitElement) {
228258
async __init() {
229259
await this.__fetchMenuData();
230260
await this.__fetchResults();
231-
// await this.__fetchProvidenceConf();
261+
await this.__fetchProvidenceConf();
232262
this._enrichMenuData();
233263
}
234264

@@ -258,36 +288,20 @@ class PBoard extends DecorateMixin(LitElement) {
258288
const activeRepos = [...new Set(checkedValues(repos))];
259289
const activeAnalyzer = this._activeAnalyzerNode.value;
260290
const totalQueryOutput = this.__aggregateResultData(activeRefs, activeRepos, activeAnalyzer);
261-
// function addCategories(specifierRes, metaConfig) {
262-
// const resultCats = [];
263-
// if (metaConfig.categoryConfig) {
264-
// const { project, filePath, name } = specifierRes.exportSpecifier;
265-
// // First of all, do we have a matching project?
266-
// // TODO: we should allow different configs for different (major) versions
267-
// const match = metaConfig.categoryConfig.find(cat => cat.project === project);
268-
// console.log('match', match);
269-
// if (match) {
270-
// Object.entries(match.categories, ([categoryName, matchFn]) => {
271-
// if (matchFn(filePath, name)) {
272-
// resultCats.push(categoryName);
273-
// }
274-
// });
275-
// }
276-
// }
277-
// console.log('resultCats', resultCats, metaConfig);
278-
279-
// return resultCats;
280-
// }
281291

282292
// Prepare viewData
283293
const dataResult = [];
284294
// When we support more analyzers than match-imports and match-subclasses, make a switch
285295
// here
296+
286297
totalQueryOutput.forEach((specifierRes, i) => {
287298
dataResult[i] = {};
288299
dataResult[i].specifier = specifierRes.exportSpecifier;
289300
dataResult[i].sourceProject = specifierRes.exportSpecifier.project;
290-
// dataResult[i].categories = undefined; // addCategories(specifierRes, this.__providenceConf);
301+
dataResult[i].categories = getCategoriesForMatchedSpecifier(
302+
specifierRes,
303+
this.__providenceConf,
304+
);
291305
dataResult[i].type = specifierRes.exportSpecifier.name === '[file]' ? 'file' : 'specifier';
292306
dataResult[i].count = specifierRes.matchesPerProject
293307
.map(mpp => mpp.files)
@@ -299,6 +313,7 @@ class PBoard extends DecorateMixin(LitElement) {
299313

300314
__aggregateResultData(activeRefs, activeRepos, activeAnalyzer) {
301315
const jsonResultsActiveFilter = [];
316+
302317
activeRefs.forEach(ref => {
303318
const refSearch = `_${ref.replace('#', '_')}_`;
304319
activeRepos.forEach(dep => {
@@ -419,13 +434,15 @@ class PBoard extends DecorateMixin(LitElement) {
419434
}
420435

421436
async __fetchMenuData() {
422-
// Derived from providence.conf.js
437+
// Derived from providence.conf.js, generated in server.mjs
423438
this.__initialMenuData = await fetch('/menu-data').then(response => response.json());
424439
}
425440

426441
async __fetchProvidenceConf() {
427-
// Gets an
428-
this.__providenceConf = await fetch('/providence.conf.js').then(response => response.json());
442+
// Gets the providence conf as defined by the end user in providence-conf.(m)js
443+
// @ts-ignore
444+
// eslint-disable-next-line import/no-absolute-path
445+
this.__providenceConf = (await import('/providence-conf.js')).default;
429446
}
430447

431448
async __fetchResults() {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// @ts-ignore
2+
const { LogService } = require('../../src/program/services/LogService.js');
3+
4+
LogService.warn(
5+
'Running via "dashboard/src/server.js" is deprecated. Please run "providence dashboard" instead.',
6+
);
7+
8+
// @ts-ignore
9+
import('./server.mjs');

0 commit comments

Comments
 (0)