kempo-inventory 0.3.0 → 0.3.2
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 +4 -0
- package/admin/nav.global.html +1 -1
- package/kempo-config.json +16 -0
- package/package.json +1 -1
- package/public/components/StockWidget.js +71 -0
package/README.md
CHANGED
|
@@ -446,3 +446,7 @@ All routes require a session holding the permission above.
|
|
|
446
446
|
## Development
|
|
447
447
|
|
|
448
448
|
The documentation site is written in `docs-src/` and built into `docs/` (served by GitHub Pages from the `docs` folder). Edit `docs-src/`, never `docs/`, then run `npm run docs:build`; `npm run docs:dev` serves it on port 4050. Screenshots come in pairs: write `<img src="./media/name.png" ...>` in a page, and put `name-light.png` and `name-dark.png` in `docs-src/media`. The build turns the tag into both images and the site shows the one matching the visitor's theme.
|
|
449
|
+
|
|
450
|
+
## Dashboard widget
|
|
451
|
+
|
|
452
|
+
Adds a **Inventory** widget to the kempo admin dashboard showing item, unit and out-of-stock counts and the latest stock movements, with a **New item** button. It is declared in `widgets` in `kempo-config.json` and registered when the extension is installed or updated; people only see it if they hold its permission, and can hide, reorder or resize it from the dashboard's Customize dialog. Needs a kempo with the dashboard (see kempo's `docs/dashboard.md`); on an older kempo the entry is ignored.
|
package/admin/nav.global.html
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
<content id="kempo-inventory-nav" name="Inventory" owner="kempo-inventory" enabled="true" locked="true" location="admin-nav-extensions" priority="
|
|
1
|
+
<content id="kempo-inventory-nav" name="Inventory" owner="kempo-inventory" enabled="true" locked="true" location="admin-nav-extensions" priority="30">
|
|
2
2
|
<k-aside-item icon="archive" group="Commerce" href="/admin/extension/kempo-inventory/" no-expand>Inventory</k-aside-item>
|
|
3
3
|
</content>
|
package/kempo-config.json
CHANGED
|
@@ -1,6 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"public-scope": "inventory",
|
|
3
3
|
"schema": "./server/db/schema.js",
|
|
4
|
+
"widgets": [
|
|
5
|
+
{
|
|
6
|
+
"key": "stock",
|
|
7
|
+
"title": "Inventory",
|
|
8
|
+
"description": "Item and unit counts, what is out of stock and the latest stock movements.",
|
|
9
|
+
"icon": "archive",
|
|
10
|
+
"element": "k-inv-widget",
|
|
11
|
+
"module": "/inventory/components/StockWidget.js",
|
|
12
|
+
"defaultWidth": 2,
|
|
13
|
+
"defaultHeight": 2,
|
|
14
|
+
"minWidth": 1,
|
|
15
|
+
"minHeight": 2,
|
|
16
|
+
"permission": "kempo-inventory:items:read",
|
|
17
|
+
"priority": 100
|
|
18
|
+
}
|
|
19
|
+
],
|
|
4
20
|
"permissions": [
|
|
5
21
|
{
|
|
6
22
|
"name": "kempo-inventory:items:read",
|
package/package.json
CHANGED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import DashboardWidget from '/kempo/components/DashboardWidget.js';
|
|
2
|
+
import { html, nothing } from '/kempo-ui/lit-all.min.js';
|
|
3
|
+
import { getItems, getMovements } from '/inventory/sdk.js';
|
|
4
|
+
const stat = (value, label, classes = '') => html`<div class="flex"><div class="h2 m0 ${classes}">${value}</div><div class="small tc-muted">${label}</div></div>`;
|
|
5
|
+
|
|
6
|
+
/*
|
|
7
|
+
Stock at a glance. Unit and out-of-stock figures are shown only when the page fetched holds every
|
|
8
|
+
item, so they are never an under-count.
|
|
9
|
+
*/
|
|
10
|
+
export default class StockWidget extends DashboardWidget {
|
|
11
|
+
static properties = {
|
|
12
|
+
...DashboardWidget.properties,
|
|
13
|
+
total: { state: true },
|
|
14
|
+
units: { state: true },
|
|
15
|
+
outOfStock: { state: true },
|
|
16
|
+
movements: { state: true },
|
|
17
|
+
names: { state: true }
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
constructor(){
|
|
21
|
+
super();
|
|
22
|
+
this.total = 0;
|
|
23
|
+
this.units = null;
|
|
24
|
+
this.outOfStock = null;
|
|
25
|
+
this.movements = [];
|
|
26
|
+
this.names = {};
|
|
27
|
+
this.cta = { label: 'New item', icon: 'add', href: '/admin/extension/kempo-inventory/new', permission: 'kempo-inventory:items:create' };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/*
|
|
31
|
+
Public Methods
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
load = async () => {
|
|
35
|
+
const [items, movements] = await Promise.all([
|
|
36
|
+
this.unwrap(getItems({ limit: 500 })),
|
|
37
|
+
this.unwrap(getMovements({ limit: 9 }))
|
|
38
|
+
]);
|
|
39
|
+
const complete = items.items.length >= items.total;
|
|
40
|
+
this.total = items.total;
|
|
41
|
+
this.units = complete ? items.items.reduce((sum, item) => sum + item.quantity, 0) : null;
|
|
42
|
+
this.outOfStock = complete ? items.items.filter(item => item.quantity <= 0).length : null;
|
|
43
|
+
this.names = Object.fromEntries(items.items.map(item => [item.id, item.name]));
|
|
44
|
+
this.movements = movements.movements;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/*
|
|
48
|
+
Rendering
|
|
49
|
+
*/
|
|
50
|
+
|
|
51
|
+
renderContent(){
|
|
52
|
+
if(!this.total) return html`<p class="tc-muted">No items yet.</p>`;
|
|
53
|
+
return html`
|
|
54
|
+
<div class="d-f mb">
|
|
55
|
+
${stat(this.total, 'Items')}
|
|
56
|
+
${stat(this.units ?? '\u2014', 'Units')}
|
|
57
|
+
${stat(this.outOfStock ?? '\u2014', 'Out of stock', this.outOfStock ? 'tc-danger' : '')}
|
|
58
|
+
</div>
|
|
59
|
+
${this.movements.length ? html`<div class="small tc-muted mbq">Latest movements</div>` : nothing}
|
|
60
|
+
${this.movements.slice(0, this.height * 2).map(movement => html`
|
|
61
|
+
<div class="d-f pyq bb">
|
|
62
|
+
<span class="flex">${this.names[movement.itemId] || movement.itemId}</span>
|
|
63
|
+
<strong class=${movement.delta < 0 ? 'tc-danger' : ''}>${movement.delta > 0 ? '+' : ''}${movement.delta}</strong>
|
|
64
|
+
<span class="small tc-muted ml">${movement.reason}</span>
|
|
65
|
+
</div>
|
|
66
|
+
`)}
|
|
67
|
+
`;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
customElements.define('k-inv-widget', StockWidget);
|