Skip to content

Commit

Permalink
Merge pull request #12 from CrowdStrike/remove-remaining-deprecated-apis
Browse files Browse the repository at this point in the history
Remove remaining deprecated apis
  • Loading branch information
NullVoxPopuli authored Oct 21, 2022
2 parents 907b9bc + 38c1d9f commit 6ba902f
Show file tree
Hide file tree
Showing 22 changed files with 1,285 additions and 89 deletions.
7 changes: 7 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,10 @@

* `cd docs-app`
* `pnpm start` – starts the test app and tests are available at `/tests`

## Notes, Caveats, and Bugs

Until [this pnpm issue#4965](https://github.com/pnpm/pnpm/issues/4965) is fixed,
with the peer-dependency requirements of this repo, every time you re-build the addon,
you'll need to re-run `pnpm install` to re-create the links in the local `node_modules/.pnpm` store.
Thankfully, this is pretty fast.
12 changes: 6 additions & 6 deletions docs-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@
"@embroider/webpack": "^1.9.0",
"@glimmer/component": "^1.1.2",
"@glimmer/tracking": "^1.1.2",
"@glint/core": "^0.9.5",
"@glint/environment-ember-loose": "^0.9.5",
"@glint/environment-ember-template-imports": "^0.9.5",
"@glint/template": "^0.9.5",
"@glint/core": "^0.9.6",
"@glint/environment-ember-loose": "^0.9.6",
"@glint/environment-ember-template-imports": "^0.9.6",
"@glint/template": "^0.9.6",
"@html-next/vertical-collection": "^4.0.0",
"@nullvoxpopuli/eslint-configs": "^2.2.59",
"@tailwindcss/typography": "^0.5.7",
Expand Down Expand Up @@ -114,13 +114,13 @@
"edition": "octane"
},
"dependencies": {
"@crowdstrike/ember-oss-docs": "^1.0.29",
"@crowdstrike/ember-oss-docs": "^1.1.0",
"@ember/test-waiters": "^3.0.2",
"@embroider/router": "^1.9.0",
"dompurify": "^2.4.0",
"ember-browser-services": "^4.0.3",
"ember-cached-decorator-polyfill": "^1.0.1",
"ember-headless-table": "workspace:*",
"ember-headless-table": "workspace:../ember-headless-table",
"ember-modifier": "^3.2.7",
"ember-resources": "^5.4.0",
"highlight.js": "^11.6.0",
Expand Down
12 changes: 12 additions & 0 deletions docs/demos/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
categoryOrder: 3
---

# Demos and examples

While each plugin has its own demo for how to use the plugin (and in combination with other plugins),
there are common behaviors and patterns that can be acheived with the plugin system (with the existing plugins)
that fit more in to a "kitchen-sink" style collection of demos.

If you have an idea for a demo, please [open an issue](https://github.com/CrowdStrike/ember-headless-table/issues)
requesting the demo, or even better, submit a pull request adding your demo.
295 changes: 295 additions & 0 deletions docs/demos/lots-of-data-no-virtualization/demo/demo-a.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,295 @@
```hbs template
FPS: {{this.fps}}<br>
<div data-container class="h-full overflow-auto" {{this.table.modifiers.container}}>
<table>
<thead>
<tr>
{{#each this.table.columns as |column|}}
<th {{this.table.modifiers.columnHeader column}}>
{{column.name}}
</th>
{{/each}}
</tr>
</thead>
<tbody>
{{#each this.table.rows as |row|}}
<tr class="{{row.countClassName}}">
{{#each this.table.columns as |column|}}
<td>
{{#if column.Cell}}
<column.Cell @row={{row}} @column={{column}} />
{{else}}
{{column.getValueForRow row}}
{{/if}}
</td>
{{/each}}
</tr>
{{/each}}
</tbody>
</table>
</div>
<style>
[data-container] {
height: 500px;
overflow: scroll;
position: relative;
}
[data-container] thead {
position: sticky;
top: 0;
background: var(--basement);
}
[data-container] .label {
padding: 0.2rem 0.6rem 0.3rem;
font-size: 75%;
color: white;
border-radius: 0.25rem;
}
[data-container] th {
/* styling the table isn't the focus of this demo (perf is the focus) */
width: calc(100% / 7);
}
[data-container] th:first-child {
min-width: 190px;
}
[data-container] .label-success { background-color: #5cb85c; }
[data-container] .label-warning { background-color:#f0ad4e; }
[data-container] .label-danger { background-color:#d9534f; }
</style>
```
```js component
import Component from '@glimmer/component';
import { tracked, cached } from '@glimmer/tracking';
import { cell, use, resource, resourceFactory } from 'ember-resources';
import { map } from 'ember-resources/util/map';

import { headlessTable } from 'ember-headless-table';

export default class extends Component {
table = headlessTable(this, {
columns: () => [
{ name: 'dbname', key: 'db.id' },
{ name: 'query count', key: 'queries.length', Cell: QueryStatus },
{ name: '', key: 'topFiveQueries.0.elapsed' },
{ name: '', key: 'topFiveQueries.1.elapsed' },
{ name: '', key: 'topFiveQueries.2.elapsed' },
{ name: '', key: 'topFiveQueries.3.elapsed' },
{ name: '', key: 'topFiveQueries.4.elapsed' },
],
data: () => this.data,
});

@use dbData = DBMonitor;

@use fps = FPS.of(() => this.dbData.databases);

get data() {
return this.mappedData.values();
}

mappedData = map(this, {
data: () => this.dbData.databases,
map: (databaseData) => new Database(databaseData),
})
}

const FPS = {
of: resourceFactory((ofWhat) => {
let updateInterval = 500; // ms
let multiplier = 1000 / updateInterval;
let framesSinceUpdate = 0;

return resource(({ on }) => {
let value = cell(0);
let interval = setInterval(() => {
value.current = framesSinceUpdate * multiplier;
framesSinceUpdate = 0;
}, updateInterval);

on.cleanup(() => clearInterval(interval));

return () => {
ofWhat();
framesSinceUpdate++;

return value.current;
}
});
})
}

const DBMonitor = resource(({ on }) => {
let value = cell(getData(20));
let frame;
let generateData = () => {
// simulate receiving data as fast as possible
frame = requestAnimationFrame(() => {
value.current = getData(20);
generateData();
});
}

on.cleanup(() => cancelAnimationFrame(frame));

// Start the infinite requestAnimationFrame chain
generateData();

return () => value.current;
});

class Database {
constructor(db) {
this.db = db;
}

get queries() {
return this.db.queries;
}

@cached
get topFiveQueries() {
let queries = this.queries || [];
let topFiveQueries = queries.slice(0, 5);

while (topFiveQueries.length < 5) {
topFiveQueries.push({ query: '' });
}

return topFiveQueries.map(function(query, index) {
return {
key: String(index),
query: query.query,
elapsed: query.elapsed ? formatElapsed(query.elapsed) : '',
className: elapsedClass(query.elapsed)
};
});
}

@cached
get countClassName() {
let queries = this.queries || [];
let countClassName = 'label';

if (queries.length >= 20) {
countClassName += ' label-important';
} else if (queries.length >= 10) {
countClassName += ' label-warning';
} else {
countClassName += ' label-success';
}

return countClassName;
}


}

function elapsedClass(elapsed) {
if (elapsed >= 10.0) {
return 'elapsed warn_long';
} else if (elapsed >= 1.0) {
return 'elapsed warn';
} else {
return 'elapsed short';
}
}

function leftPad(str, padding, toLength) {
return padding.repeat((toLength - str.length) / padding.length).concat(str);
};

function formatElapsed(value) {
let str = parseFloat(value).toFixed(2);

if (value > 60) {
const minutes = Math.floor(value / 60);
const comps = (value % 60).toFixed(2).split('.');
const seconds = leftPad(comps[0], '0', 2);
str = `${minutes}:${seconds}.${comps[1]}`;
}

return str;
}

/**
* Temporary work-around because docfy.dev doesn't support gjs
*/
import { setComponentTemplate } from '@ember/component';
import templateOnly from '@ember/component/template-only';
import { hbs } from 'ember-cli-htmlbars';

const QueryStatus = templateOnly();
setComponentTemplate(hbs`
<td>
<span class="{{@row.data.countClassName}}">
{{@row.data.queries.length}}
</span>
</td>
`, QueryStatus);

/**
* dbmon code copied from
* https://github.com/html-next/vertical-collection/blob/master/tests/dummy/app/lib/get-data.js
*/
const DEFAULT_ROWS = 20;

function getData(ROWS) {
ROWS = ROWS || DEFAULT_ROWS;

// generate some dummy data
const data = {
start_at: new Date().getTime() / 1000,
databases: []
};

for (let i = 1; i <= ROWS; i++) {

data.databases.push({
id: `cluster${i}`,
queries: []
});

data.databases.push({
id: ` ↳ cluster${i}-secondary`,
queries: []
});

}

data.databases.forEach(function(info) {
const r = Math.floor((Math.random() * 10) + 1);

for (let i = 0; i < r; i++) {
const q = {
canvas_action: null,
canvas_context_id: null,
canvas_controller: null,
canvas_hostname: null,
canvas_job_tag: null,
canvas_pid: null,
elapsed: Math.random() * 15,
query: 'SELECT blah FROM something',
waiting: Math.random() < 0.5
};

if (Math.random() < 0.2) {
q.query = '<IDLE> in transaction';
}

if (Math.random() < 0.1) {
q.query = 'vacuum';
}

info.queries.push(q);
}

info.queries = info.queries.sort(function(a, b) {
return b.elapsed - a.elapsed;
});
});

return data;
}
```

9 changes: 9 additions & 0 deletions docs/demos/lots-of-data-no-virtualization/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Lots of data (no virtualization)

This demo is the same as "[Lots of Data](/docs/demos/lots-of-data)",
but without virtualization and no use of [@html-next/vertical-collection][gh-vc]

[gh-vc]: https://github.com/html-next/vertical-collection

In this demo, 6 columns x 40 rows are updating as quickly as requestAnimationFrame allows.

Loading

0 comments on commit 6ba902f

Please sign in to comment.