Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 21 additions & 11 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,35 @@ name: Run Unit Tests

on:
push:
branches: [master]
pull_request:
branches: [master]

permissions:
contents: read

jobs:
build:
runs-on: ubuntu-latest
runs-on: macos-latest

strategy:
matrix:
node-version: [18.x]
deno-version: [2.7]

steps:
- uses: actions/checkout@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
- uses: actions/checkout@v6
- name: Use Deno ${{ matrix.deno-version }}
uses: denoland/setup-deno@v2
with:
node-version: ${{ matrix.node-version }}
- run: npm ci --ignore-scripts
- run: npm run linter
- run: npm test
- run: npm run build
deno-version: ${{ matrix.deno-version }}
- name: Install Dependencies
run: deno install
- name: Format Check
run: deno task fmt:check
- name: Lint All
run: deno task lint:all
- name: Test All
run: deno task test:all
- name: Build App
run: deno task build:app
- name: Build Widgets
run: deno task build:widgets
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
22 changes: 18 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,16 @@ bower_components
# Editors
.idea
*.iml
.vscode
*.env
.vscode/launch.json

# OS metadata
.DS_Store
Thumbs.db

# Ignore built ts files
dist
_dist
build
.build
.serverless
Expand All @@ -51,7 +53,19 @@ yarn.lock
# ignore local files
*.LOCAL.*
*.local.*
.tago-lock.kickstarter.lock
*.lock
.tagoio
.tago-lock.tagoio init.lock
tagoconfig
.superpowers

# vite
.vite
.tago-lock.dev.lock

# E2E (Playwright)
e2e/test-results/
e2e/playwright-report/
e2e/playwright/.auth/

# Local tooling
.claude/
.tmp-test-screenshots/
1 change: 0 additions & 1 deletion .npmrc

This file was deleted.

7 changes: 7 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"recommendations": [
"editorconfig.editorconfig",
"denoland.vscode-deno",
"bradlc.vscode-tailwindcss"
]
}
27 changes: 27 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
// Deno LSP across the workspace (root deno.json lists all members)
"deno.enable": true,
"deno.lint": true,
"deno.codeLens.test": true,
"deno.codeLens.references": true,
// e2e/ is a Node project (Playwright + npm); let the built-in TS server handle it.
"deno.disablePaths": ["e2e"],

// deno fmt as the default formatter β€” stays in sync with CI's lint/fmt checks
"editor.formatOnSave": true,
"[typescript]": { "editor.defaultFormatter": "denoland.vscode-deno" },
"[typescriptreact]": { "editor.defaultFormatter": "denoland.vscode-deno" },
"[javascript]": { "editor.defaultFormatter": "denoland.vscode-deno" },
"[json]": { "editor.defaultFormatter": "denoland.vscode-deno" },
"[jsonc]": { "editor.defaultFormatter": "denoland.vscode-deno" },

// Tailwind v4 is CSS-first β€” point IntelliSense at each widget's styles.css.
// Add a new key per widget as you create them.
"tailwindCSS.experimental.configFile": {
"widgets/line-chart/styles.css": "widgets/line-chart/**"
},
"cSpell.words": [
"CHECKIN",
"sendgrid"
]
}
250 changes: 94 additions & 156 deletions README.MD
Original file line number Diff line number Diff line change
@@ -1,159 +1,97 @@
<br/>
<p align="center">
<img src="https://assets.tago.io/tagoio/analysis.png" width="200px" alt="TagoIO"></img>
</p>

# Kickstarter Application for TagoIO
This is a starter application to be used at TagoIO. It has main required features for an regular application to run, with a functionality to facilitate setting up new sensors within the application. You can use the scripts provided here to learn or to develop your own solution with it's foundations.

# Components
The application contains the following features:
* Two levels: Organization and Groups.
* Three access levels: Super Administrator, Organization Administrator and Guest User.
* Organization plans for managing SMS, email and data retetion.
* Setup alerts.
* Generate scheduled reports.
* Navigation between dashboards and Run Buttons enabled.

### Easy Installation
You can quickly install the application in your account by using the Import tool.
* Firstly, make sure your RUN is activated. Visit this [link](https://admin.tago.io/run/), click on "Start now" and then save the change.
* Go to your [profile settings](https://admin.tago.io/account/).
* Generate an Token in your profile, make sure to set **expire time** to never.
* Copy the Token.
* Access the Import tool by [clicking here](https://import-application.tago.run/dashboards/info/63e698562df1360009606d71?anonymousToken=00000000-5bbc-b03b-667d-7a002e56664b).
* Keep all entities selected, paste your token in the account token field.
* Add you account token to a new secret named: ACCOUNT_TOKEN, it is needed to allow Analysis to work.
* Press Import Application and you should receive notification in your account when it's done.
* To access the application using TagoRUN. Make sure to create a user using your TagoIO Developer account, adding the tag key **access** with the tag value **admin**.

### Easy Update
To easy update your application when new version is out, you can just repeat the previous step.
If you had made changes to the application, you can choose only the entities you want to update, like only analysis for example.

### Step-by-Step installation
You only want to follow this installation method, instead of the easy one, if you plan to have deep understading of how all TagoIO resources works and are used. I can't think of any other reason to go through this method.

* Generate an account-token in your profile settings.
* Create a Custom HTTPs device, to be used as a internal storage for the application. Make sure you have the tag key **device_type** with tag value **settings** on it.
* Get Analysis and Dashboard templates from [Analysis documentation](https://github.com/tago-io/analysis-kickstarter/blob/master/src/analysis/README.md).
* Create actions as described in the header documentation on each analysis file at [Analysis folder](https://github.com/tago-io/analysis-kickstarter/tree/master/src/analysis).
* Create policies for your Run Users (work in progress)
* Create the Run Buttons (work in progress)
* Follow the **Code Setup and Installation** instructions below, to make sure scripts are up-to-date.
* You're done!

### Code Setup and Installation
Using this repository, you will be able to change and update the analysis in your account. This step is not required unless you plan to make changes in the code.
* Install [Node.JS](https://help.tago.io/portal/en/kb/articles/464-node-js).
* Download the repository.
* Open your terminal and access the folder of the repository.
* Run `npm install`.
* Generate a account-profile token at TagoIO **My Settings** -> **Your Profile** -> **Tokens**. Make sure to generate a token with `Expire at` set to never.
* Open the `build.ts` and replace `Your-Account-Profile-Token` by a token of your profile.
* Go back to your terminal and run the template with `npm run start build`.
* It should take a few minutes for the script to build and import all the analysis and dashboards to your account.

### Code Update
* Make sure you have the `build.ts` with your account profile token.
* Update the repository with last version.
* Go back to your terminal and run the template with `npm run start build`.
* It should take a few minutes for the script to build and import all the analysis and dashboards to your account.

### How to use the application
The documentation on how to use the application is avaiable to download in the following link [analysis-kickstarter/docs/Kickstarter-Guide](https://github.com/tago-io/analysis-kickstarter/blob/master/docs/Kickstarter%20-%20Guide.pdf).

### How to learn from this code
You will notice three folders in the `src/` folder.
* **analysis**: contains each analysis that must be present in your account.
* **lib**: useful list of functions commonly used between the scripts.
* **services**: services folders that are used in the analysis. Each service is related

For additional informations on how to setup TagoIO with this code, and all the TagoIO resources used, check the Kickstarter Guide documentation at [analysis-kickstarter/docs/Kickstarter-Guide](https://github.com/tago-io/analysis-kickstarter/blob/master/docs/Kickstarter%20-%20Guide.pdf).

### User Permissions Diagram


```mermaid
graph LR
subgraph TagoIO KickStarter User Permission Diagram V1.0.0
subgraph Application
subgraph Entities
Organization(Organization)
Groups(Groups)
Sensors(Sensors)
end
subgraph Services
Plan(Plan System)
Alerts(Alerts)
Reports(Reports)
Indicators(System Indicators)
IndoorView(Indoor & Outdoor Plan)
end
end
style A fill:black,stroke:red,stroke-width:2px,color:#fff,stroke-dasharray: 5 5
A((Administrator))


A -- Can Invite --> O
A -- Can Manage --> Organization
A -- Can Manage --> Groups
A -- Can Manage --> Sensors
A -- Can Manage --> Plan
A -- Can Manage --> Alerts
A -- Can Manage --> Reports
A -- Can Manage --> Indicators
A -- Can Manage --> IndoorView

linkStyle 0 stroke-width:2px,fill:none,stroke:red;
linkStyle 1 stroke-width:2px,fill:none,stroke:red;
linkStyle 2 stroke-width:2px,fill:none,stroke:red;
linkStyle 3 stroke-width:2px,fill:none,stroke:red;
linkStyle 4 stroke-width:2px,fill:none,stroke:red;
linkStyle 5 stroke-width:2px,fill:none,stroke:red;
linkStyle 6 stroke-width:2px,fill:none,stroke:red;
linkStyle 7 stroke-width:2px,fill:none,stroke:red;
linkStyle 8 stroke-width:2px,fill:none,stroke:red;


style O fill:black,stroke-width:2px,color:#fff,stroke-dasharray: 5 5
O((Organization Admin))
O -- Can Invite --> G
O -- Can Manage *1 --> Groups
O -- Can Manage *1 --> Sensors
O -- Can Manage *1 --> Alerts
O -- Can Manage *1 --> Reports
O -- Can Monitor *1 --> Indicators
O -- Can Manage *1 --> IndoorView

linkStyle 9 stroke-width:2px,fill:none,stroke:white;
linkStyle 10 stroke-width:2px,fill:none,stroke:white;
linkStyle 11 stroke-width:2px,fill:none,stroke:white;
linkStyle 12 stroke-width:2px,fill:none,stroke:white;
linkStyle 13 stroke-width:2px,fill:none,stroke:white;
linkStyle 14 stroke-width:2px,fill:none,stroke:white;
linkStyle 15 stroke-width:2px,fill:none,stroke:white;

style G fill:black,stroke:green,stroke-width:2px,color:#fff,stroke-dasharray: 5 5
G((Guest))
G -- Can View Only *1 --> Groups
G -- Can View Only *1 --> Sensors
G -- Can View Only *1 --> IndoorView
G -- Will Receive Only *1 --> Reports
G -- Will Receive Only *1 --> Alerts
G -- Can Monitor *1 --> Indicators

linkStyle 16 stroke-width:2px,fill:none,stroke:green;
linkStyle 17 stroke-width:2px,fill:none,stroke:green;
linkStyle 18 stroke-width:2px,fill:none,stroke:green;
linkStyle 19 stroke-width:2px,fill:none,stroke:green;
linkStyle 20 stroke-width:2px,fill:none,stroke:green;
linkStyle 21 stroke-width:2px,fill:none,stroke:green;

test[1* Only those related to the User's Company]
end
# Kickstarter

Multi-tenant IoT template that runs on TagoIO. It ships the three things a complete TagoIO application needs: **Analyses** (Deno serverless handlers), **custom Dashboard Widgets**
(React iframes), and **dashboard helper docs** (the markdown rendered inside each dashboard's `Helper` tab in the application).

The runtime is Deno end-to-end. Widgets add a Vite/React toolchain on top for the browser bundle. Everything is wired as a Deno workspace so analyses and widgets can share types
without a publish step.

## Layout

```
analysis-kickstarter/
β”œβ”€β”€ app/ # Deno workspace β€” Analyses + bundle script
β”œβ”€β”€ widgets/ # Vite/React workspace β€” one subfolder per widget
β”œβ”€β”€ dashboard-helpers/ # Markdown files rendered inside each dashboard's Helper tab in the application
└── deno.json # Root workspace + top-level tasks
```

Detailed docs live next to the code:

- [`app/README.md`](./app/README.md) β€” analyses, triggers, AnalysisRouter, bundling
- [`widgets/README.md`](./widgets/README.md) β€” widget stack, dev server, multi custom widget build

## Application model

Two complementary views of the same thing. The TagoIO side (devices and tags) is what the analyses manipulate; the navigation side is what a user sees in the browser.

```
TagoIO resources User navigation (TagoRUN)
───────────────── ───────────────────────────
Settings device (settings_dev) Welcome
└── Organization device └── Organizations ──► Groups
(tag device_type=organization) β”œβ”€β”€ Map View └── Sensors (per group)
β”œβ”€β”€ Run users └── Create/Edit β”œβ”€β”€ Sensor List
β”‚ (Super Admin β”‚ Org Admin β”‚ Guest) β”œβ”€β”€ Sensor Detail
β”œβ”€β”€ Alert rows (stored on the org device) β”‚ (Temp gauge / Compressor / Door)
└── Group device └── All Devices (Admin)
(tag device_type=group) ──► Alerts (Sensor + Global)
└── Sensor device ──► Users (Org Admin / Guest)
(real device β€” tag device_type=device,
network, model, EUI)
```

The hierarchy is enforced through device tags: `organization_id` and `group_id` propagate down so TagoIO Access Policies isolate tenants automatically.

## Dashboards

Six dashboards, every one with a `Helper` tab that renders the matching file in [`dashboard-helpers/`](./dashboard-helpers).

| Dashboard | Tabs | CRUD analysis (in [`app/analysis/dashboard/`](./app/analysis/dashboard/)) | Custom widget |
| ------------- | --------------------------------------- | ------------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
| Organizations | Overview (List + Map) Β· Helper | `crud-organization.ts` | β€” |
| Groups | Cold Rooms Β· Overview Β· Helper | `crud-group.ts` | [`cold-room-card-data`](./widgets/cold-room-card-data) on the Cold Rooms tab |
| Sensors | Overview Β· All Devices (Admin) Β· Helper | `crud-sensor.ts` | [`sensor-status`](./widgets/sensor-status) on Overview |
| Sensor Detail | Overview Β· Helper | β€” | [`cold-room-monitor`](./widgets/cold-room-monitor) on Overview |
| Alerts | Overview Β· Global Alerts Β· Helper | `crud-alert.ts` | β€” |
| Users | Overview Β· All Users (Admin) Β· Helper | `crud-user.ts` | β€” |

Each CRUD analysis is dispatched by the SDK's `AnalysisRouter` based on the widget that fired the call (input form, custom button, or device-list action). The full mapping is
documented in [`app/README.md`](./app/README.md).

Three more analyses run outside of any dashboard:

- `actions/uplink-handler.ts` β€” Action-triggered. Turns each sensor uplink into the `cold_room_card_data` row that powers the Cold Rooms widget.
- `actions/alert-dispatcher.ts` β€” Action-triggered. Called by the per-alert Action created by `crud-alert.ts` whenever a condition is met.
- `scheduled/check-inactive-sensors.ts` β€” Scheduled (hourly). Flags sensors that haven't reported within the configured threshold and refreshes the connectivity summary shown on
the Sensors dashboard.

## Top-level tasks

Run from the repo root:

| Task | What it does |
| ------------------------- | --------------------------------------------------- |
| `deno task build:app` | Bundle every analysis into `build/app/*.tagoio.js` |
| `deno task build:widgets` | Build every widget into `widgets/_dist/<name>/` |
| `deno task dev:widgets` | Start the widget dev server (needs `WIDGET=<name>`) |
| `deno task test:all` | Run app tests |
| `deno task lint:all` | Lint app and widgets |
| `deno task fmt` | Format everything (`deno fmt`) |

Per-workspace task lists live in the folder READMEs.

## Prerequisites

- Deno (latest)
- TagoIO CLI β€” `npm install -g @tago-io/cli`, then `tagoio login`

## Conventions

- `kebab-case` for files and folders.
- Explicit block braces on every control structure β€” no single-line `if`/`for`/`while`.
- Analyses are ephemeral: no in-memory state between runs β€” persist via device data or entity records.
- Data queries always set `qty` explicitly; the SDK default (15) silently truncates.
- Buckets are deprecated β€” use device storage directly.

### Support
You can open an issue or question at [https://github.com/tago-io/analysis-kickstarter/issues](https://github.com/tago-io/analysis-kickstarter/issues).
Full guidance lives in [`CLAUDE.md`](./CLAUDE.md).
Loading
Loading