@trackunit/iris-app 1.12.9 → 1.12.10
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/CHANGELOG.md +12 -0
- package/package.json +1 -1
- package/src/executors/submit/executor.js.map +1 -0
- package/src/executors/unpublish/executor.js.map +1 -0
- package/src/executors/utils/authentication.js.map +1 -0
- package/src/executors/utils/irisAppServerSettings.js.map +1 -0
- package/src/executors/utils/src/index.js.map +1 -0
- package/src/generators/ai-agent-sync/README.md +5 -2
- package/src/generators/ai-agent-sync/generator.d.ts +1 -1
- package/src/generators/ai-agent-sync/generator.js +29 -4
- package/src/generators/ai-agent-sync/generator.js.map +1 -0
- package/src/generators/create/generator.js.map +1 -0
- package/src/generators/extend/dependencies.js.map +1 -0
- package/src/generators/extend/generator.js.map +1 -0
- package/src/generators/preset/files/.agents/skills/browser-testing/SKILL.md +193 -0
- package/src/generators/preset/files/.agents/skills/create-app/SKILL.md +191 -0
- package/src/generators/preset/files/.agents/skills/customfields/SKILL.md +239 -0
- package/src/generators/preset/files/.agents/skills/graphql/SKILL.md +147 -0
- package/src/generators/preset/files/.agents/skills/graphql-timeseries/SKILL.md +193 -0
- package/src/generators/preset/files/.agents/skills/irisx-app-sdk/SKILL.md +116 -0
- package/src/generators/preset/files/.agents/skills/react-core-hooks/SKILL.md +215 -0
- package/src/generators/preset/files/.agents/skills/tables-and-sorting/SKILL.md +122 -0
- package/src/generators/preset/files/.agents/skills/widget-extensions/SKILL.md +245 -0
- package/src/generators/preset/files/.cursor/mcp.json +4 -0
- package/src/generators/preset/generator.js.map +1 -0
- package/src/generators/preset/root-files/AGENTS.md +43 -0
- package/src/generators/preset/root-files/CLAUDE.md +17 -0
- package/src/index.js.map +1 -0
- package/src/utils/ast/astUtils.js.map +1 -0
- package/src/utils/fileUpdater.js.map +1 -0
- package/src/generators/preset/files/.cursor/commands/create-app.md +0 -226
- package/src/generators/preset/files/.cursor/rules/browser-irisx-development.mdc +0 -246
- package/src/generators/preset/files/.cursor/rules/graphql-timeseries.md +0 -260
- package/src/generators/preset/files/.cursor/rules/irisx-app-sdk-customfields.md +0 -305
- package/src/generators/preset/files/.cursor/rules/irisx-app-sdk-graphql.md +0 -30
- package/src/generators/preset/files/.cursor/rules/irisx-app-sdk.mdc +0 -82
- package/src/generators/preset/files/.cursor/rules/react-core-hooks.md +0 -155
- package/src/generators/preset/files/.cursor/rules/rules-index.mdc +0 -10
- package/src/generators/preset/files/.cursor/rules/structured-development.mdc +0 -86
- package/src/generators/preset/files/.cursor/rules/tables-and-sorting.mdc +0 -126
- package/src/generators/preset/files/.cursor/rules/widget-extensions.md +0 -323
|
@@ -1,305 +0,0 @@
|
|
|
1
|
-
# CustomFields Rule for Trackunit IrisX App SDK
|
|
2
|
-
|
|
3
|
-
## Overview
|
|
4
|
-
**CustomFields are the primary mechanism for storing data from IrisX applications.** They allow IrisX App developers to extend the Trackunit data model by storing additional information on entities like assets, accounts, groups, and sites.
|
|
5
|
-
|
|
6
|
-
### Key Use Cases:
|
|
7
|
-
- **Extending the data model**: Add new fields and attributes to existing Trackunit entities
|
|
8
|
-
- **Storing user input**: Capture and persist form data, user preferences, and settings
|
|
9
|
-
- **Storing metadata**: Keep application-specific information, configuration data, and operational metrics
|
|
10
|
-
- **Fleet-specific data**: Custom attributes unique to specific fleet management needs
|
|
11
|
-
- **Performance metrics**: Custom KPIs and measurement data not available in standard Trackunit data
|
|
12
|
-
- **Business logic data**: Information required for app-specific workflows and processes
|
|
13
|
-
|
|
14
|
-
**Important**: CustomFields are the recommended and supported way to persist any data your IrisX app needs to store. Do not attempt to use external databases or storage solutions - use CustomFields for all persistent data requirements.
|
|
15
|
-
|
|
16
|
-
## 1. Defining Custom Fields
|
|
17
|
-
|
|
18
|
-
### Manifest Configuration
|
|
19
|
-
|
|
20
|
-
Custom fields must be defined in your IrisX App manifest using the `customFieldDefinitions` array:
|
|
21
|
-
|
|
22
|
-
```typescript
|
|
23
|
-
// In your app manifest
|
|
24
|
-
customFieldDefinitions: [
|
|
25
|
-
{
|
|
26
|
-
type: 'STRING',
|
|
27
|
-
entityType: 'ASSET',
|
|
28
|
-
key: 'myCustomField',
|
|
29
|
-
translations: [{
|
|
30
|
-
language: 'en',
|
|
31
|
-
title: 'My Custom Field',
|
|
32
|
-
description: 'Description of what this field stores',
|
|
33
|
-
}],
|
|
34
|
-
uiEditable: true,
|
|
35
|
-
uiVisible: true,
|
|
36
|
-
scopeType: ScopeType.ACCOUNT
|
|
37
|
-
}
|
|
38
|
-
]
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
### Required Properties
|
|
42
|
-
|
|
43
|
-
- **`type`**: Field data type (see supported types below)
|
|
44
|
-
- **`entityType`**: Entity the field applies to (`ACCOUNT`, `ASSET`, `GROUP`, `SITE`)
|
|
45
|
-
- **`key`**: Programmatic identifier (cannot be changed after creation)
|
|
46
|
-
- **`translations`**: UI labels and descriptions for each supported language
|
|
47
|
-
- **`scopeType`**: Data access scope (see scope types below)
|
|
48
|
-
|
|
49
|
-
### Optional Properties
|
|
50
|
-
|
|
51
|
-
- **`uiEditable`**: Whether field can be edited in Manager UI (default: true)
|
|
52
|
-
- **`uiVisible`**: Whether field is visible in Manager UI (default: true)
|
|
53
|
-
|
|
54
|
-
## 2. Supported Field Types
|
|
55
|
-
|
|
56
|
-
| Type | Description | Extra Properties |
|
|
57
|
-
|---|----|---|
|
|
58
|
-
| `BOOLEAN` | True/false values | - |
|
|
59
|
-
| `DATE` | ISO8601 formatted dates | - |
|
|
60
|
-
| `DROPDOWN` | Predefined option lists | `allValues`, `multiSelect`, `dropDownValueReplacements` |
|
|
61
|
-
| `EMAIL` | Email addresses with mailto links | - |
|
|
62
|
-
| `NUMBER` | Numeric values | `minimum`, `maximum`, `isInteger`, `unitSi`, `unitUs` |
|
|
63
|
-
| `PHONE_NUMBER` | E.164 formatted phone numbers | - |
|
|
64
|
-
| `STRING` | Free text | `minimumLength`, `maximumLength`, `pattern` |
|
|
65
|
-
| `WEB_ADDRESS` | URLs as clickable links | - |
|
|
66
|
-
| `JSON` | JSON objects | - |
|
|
67
|
-
| `MONETARY` | Currency values (ISO 4217) | `minimum`, `maximum`, `currency` |
|
|
68
|
-
|
|
69
|
-
### Example Field Definitions
|
|
70
|
-
|
|
71
|
-
```typescript
|
|
72
|
-
// String field with validation
|
|
73
|
-
{
|
|
74
|
-
type: 'STRING',
|
|
75
|
-
entityType: 'ASSET',
|
|
76
|
-
key: 'serialNumber',
|
|
77
|
-
translations: [{ language: 'en', title: 'Serial Number', description: 'Asset serial number' }],
|
|
78
|
-
minimumLength: 5,
|
|
79
|
-
maximumLength: 20,
|
|
80
|
-
pattern: '^[A-Z0-9]+$'
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// Number field with units
|
|
84
|
-
{
|
|
85
|
-
type: 'NUMBER',
|
|
86
|
-
entityType: 'ASSET',
|
|
87
|
-
key: 'fuelCapacity',
|
|
88
|
-
translations: [{ language: 'en', title: 'Fuel Capacity', description: 'Tank capacity' }],
|
|
89
|
-
minimum: 0,
|
|
90
|
-
maximum: 1000,
|
|
91
|
-
unitSi: 'L',
|
|
92
|
-
unitUs: 'gal'
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// Dropdown with multiple selection
|
|
96
|
-
{
|
|
97
|
-
type: 'DROPDOWN',
|
|
98
|
-
entityType: 'ASSET',
|
|
99
|
-
key: 'features',
|
|
100
|
-
translations: [{ language: 'en', title: 'Features', description: 'Available features' }],
|
|
101
|
-
allValues: ['GPS', 'Camera', 'Bluetooth', 'WiFi'],
|
|
102
|
-
multiSelect: true
|
|
103
|
-
}
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
## 3. Scope Types
|
|
107
|
-
|
|
108
|
-
| Scope | Description |
|
|
109
|
-
|----|----|
|
|
110
|
-
| `ACCOUNT` | Values shared within a single account only |
|
|
111
|
-
| `ACCOUNT_WRITE_GLOBAL_READ` | Account can write, all accounts can read |
|
|
112
|
-
| `GLOBAL` | Values shared between all accounts with entity access |
|
|
113
|
-
|
|
114
|
-
## 4. Using Custom Fields in React Components
|
|
115
|
-
|
|
116
|
-
### Required Hooks
|
|
117
|
-
|
|
118
|
-
Use these hooks to interact with custom fields:
|
|
119
|
-
|
|
120
|
-
```typescript
|
|
121
|
-
import {
|
|
122
|
-
useCustomFieldsValueAndDefinition,
|
|
123
|
-
useUpdateCustomFieldValues,
|
|
124
|
-
useCurrentUserSystemOfMeasurement
|
|
125
|
-
} from '@trackunit/react-core-contexts-host';
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
### Basic Implementation Pattern
|
|
129
|
-
|
|
130
|
-
```typescript
|
|
131
|
-
import React from 'react';
|
|
132
|
-
import { useForm } from 'react-hook-form';
|
|
133
|
-
import { Card, CardBody, CardHeader, CardFooter, Button, Spinner } from '@trackunit/react-components';
|
|
134
|
-
import { CustomField } from '@trackunit/react-core-contexts-host';
|
|
135
|
-
|
|
136
|
-
const CustomFieldsForm = ({ assetId }: { assetId: string }) => {
|
|
137
|
-
const { register, handleSubmit, formState, setValue, control } = useForm({
|
|
138
|
-
shouldUnregister: false,
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
const { systemOfMeasurement } = useCurrentUserSystemOfMeasurement();
|
|
142
|
-
|
|
143
|
-
const { fields, loading } = useCustomFieldsValueAndDefinition({
|
|
144
|
-
entityType: "ASSET",
|
|
145
|
-
entityId: assetId,
|
|
146
|
-
systemOfMeasurement: systemOfMeasurement ?? "SI",
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
const { updateCustomFields, inProgress } = useUpdateCustomFieldValues(
|
|
150
|
-
assetId,
|
|
151
|
-
"ASSET",
|
|
152
|
-
fields,
|
|
153
|
-
systemOfMeasurement ?? "SI"
|
|
154
|
-
);
|
|
155
|
-
|
|
156
|
-
if (loading) {
|
|
157
|
-
return <Spinner />;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
return (
|
|
161
|
-
<Card>
|
|
162
|
-
<CardHeader heading="Custom Fields" />
|
|
163
|
-
<CardBody>
|
|
164
|
-
{fields.map(field => {
|
|
165
|
-
const isEditable = field.valueEditable && (field.definition.uiEditable ?? true);
|
|
166
|
-
return (
|
|
167
|
-
<CustomField
|
|
168
|
-
key={field.definition.key}
|
|
169
|
-
control={control}
|
|
170
|
-
field={field}
|
|
171
|
-
formState={formState}
|
|
172
|
-
isEditable={isEditable}
|
|
173
|
-
register={register}
|
|
174
|
-
setValue={setValue}
|
|
175
|
-
unitPreference={systemOfMeasurement}
|
|
176
|
-
/>
|
|
177
|
-
);
|
|
178
|
-
})}
|
|
179
|
-
</CardBody>
|
|
180
|
-
<CardFooter>
|
|
181
|
-
<Button
|
|
182
|
-
loading={inProgress}
|
|
183
|
-
onClick={handleSubmit(updateCustomFields)}
|
|
184
|
-
>
|
|
185
|
-
{inProgress ? "Saving..." : "Save Changes"}
|
|
186
|
-
</Button>
|
|
187
|
-
</CardFooter>
|
|
188
|
-
</Card>
|
|
189
|
-
);
|
|
190
|
-
};
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
## 5. Best Practices
|
|
194
|
-
|
|
195
|
-
### Field Design
|
|
196
|
-
- **Use descriptive keys**: Choose clear, descriptive field keys that won't need changing
|
|
197
|
-
- **Add proper translations**: Always provide meaningful titles and descriptions
|
|
198
|
-
- **Set appropriate constraints**: Use min/max values, length limits, and patterns for validation
|
|
199
|
-
- **Consider data types**: Choose the most appropriate type for your data
|
|
200
|
-
|
|
201
|
-
### Performance
|
|
202
|
-
- **Batch updates**: Use `useUpdateCustomFieldValues` to update multiple fields at once
|
|
203
|
-
- **Handle loading states**: Always show loading indicators while fetching data
|
|
204
|
-
- **Error handling**: Implement proper error handling for failed updates
|
|
205
|
-
|
|
206
|
-
### Data Management
|
|
207
|
-
- **Plan for migration**: Consider existing data when changing field definitions
|
|
208
|
-
- **Use appropriate scopes**: Choose the right scope type for your data sharing needs
|
|
209
|
-
- **Validate user input**: Implement client-side validation matching your field constraints
|
|
210
|
-
|
|
211
|
-
## 6. Common Use Cases
|
|
212
|
-
|
|
213
|
-
### Fleet Management
|
|
214
|
-
```typescript
|
|
215
|
-
// Store vehicle-specific information
|
|
216
|
-
{
|
|
217
|
-
type: 'NUMBER',
|
|
218
|
-
entityType: 'ASSET',
|
|
219
|
-
key: 'fuelEfficiency',
|
|
220
|
-
translations: [{ language: 'en', title: 'Fuel Efficiency', description: 'Miles per gallon' }],
|
|
221
|
-
unitSi: 'L/100km',
|
|
222
|
-
unitUs: 'mpg'
|
|
223
|
-
}
|
|
224
|
-
```
|
|
225
|
-
|
|
226
|
-
### Asset Utilization
|
|
227
|
-
```typescript
|
|
228
|
-
// Track custom performance metrics
|
|
229
|
-
{
|
|
230
|
-
type: 'JSON',
|
|
231
|
-
entityType: 'ASSET',
|
|
232
|
-
key: 'performanceMetrics',
|
|
233
|
-
translations: [{ language: 'en', title: 'Performance Data', description: 'Custom metrics' }]
|
|
234
|
-
}
|
|
235
|
-
```
|
|
236
|
-
|
|
237
|
-
### Driver Safety
|
|
238
|
-
```typescript
|
|
239
|
-
// Store safety-related information
|
|
240
|
-
{
|
|
241
|
-
type: 'DROPDOWN',
|
|
242
|
-
entityType: 'ASSET',
|
|
243
|
-
key: 'safetyRating',
|
|
244
|
-
translations: [{ language: 'en', title: 'Safety Rating', description: 'Driver safety score' }],
|
|
245
|
-
allValues: ['Excellent', 'Good', 'Fair', 'Poor']
|
|
246
|
-
}
|
|
247
|
-
```
|
|
248
|
-
|
|
249
|
-
## 7. Local Development
|
|
250
|
-
|
|
251
|
-
- Custom fields are available immediately in local development
|
|
252
|
-
- Changes to field definitions require app redeployment
|
|
253
|
-
- Test with various data types and edge cases
|
|
254
|
-
- Verify validation rules work as expected
|
|
255
|
-
|
|
256
|
-
## 8. Deployment Considerations
|
|
257
|
-
|
|
258
|
-
- **Field keys are immutable**: Cannot be changed after creation
|
|
259
|
-
- **Definition updates**: Changing field definitions affects all existing data
|
|
260
|
-
- **Migration planning**: Consider data migration when modifying existing fields
|
|
261
|
-
- **Approval process**: Custom field changes require app approval and marketplace submission
|
|
262
|
-
|
|
263
|
-
## 9. Error Handling
|
|
264
|
-
|
|
265
|
-
```typescript
|
|
266
|
-
const CustomFieldsComponent = () => {
|
|
267
|
-
const { fields, loading, error } = useCustomFieldsValueAndDefinition({
|
|
268
|
-
entityType: "ASSET",
|
|
269
|
-
entityId: assetId,
|
|
270
|
-
systemOfMeasurement: systemOfMeasurement ?? "SI",
|
|
271
|
-
});
|
|
272
|
-
|
|
273
|
-
if (loading) return <Spinner />;
|
|
274
|
-
if (error) return <ErrorState message="Failed to load custom fields" />;
|
|
275
|
-
|
|
276
|
-
// Render fields...
|
|
277
|
-
};
|
|
278
|
-
```
|
|
279
|
-
|
|
280
|
-
## 10. Integration with Trackunit Components
|
|
281
|
-
|
|
282
|
-
Always use the provided `CustomField` component for consistent UI:
|
|
283
|
-
|
|
284
|
-
```typescript
|
|
285
|
-
import { CustomField } from '@trackunit/react-core-contexts-host';
|
|
286
|
-
|
|
287
|
-
// This handles all field types automatically
|
|
288
|
-
<CustomField
|
|
289
|
-
control={control}
|
|
290
|
-
field={field}
|
|
291
|
-
formState={formState}
|
|
292
|
-
isEditable={isEditable}
|
|
293
|
-
register={register}
|
|
294
|
-
setValue={setValue}
|
|
295
|
-
unitPreference={systemOfMeasurement}
|
|
296
|
-
/>
|
|
297
|
-
```
|
|
298
|
-
|
|
299
|
-
## References
|
|
300
|
-
|
|
301
|
-
- [Save Data from Your App](https://developers.trackunit.com/docs/save-data-from-your-app)
|
|
302
|
-
- [Defining a Custom Field](https://developers.trackunit.com/docs/defining-a-custom-field)
|
|
303
|
-
- [Using a Custom Field](https://developers.trackunit.com/docs/using-a-custom-field)
|
|
304
|
-
- [Local Development](https://developers.trackunit.com/docs/local-development)
|
|
305
|
-
- [Deploying a New Custom Field](https://developers.trackunit.com/docs/deploying-a-new-custom-field)
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
Key Points:
|
|
2
|
-
1. Trackunit exposes a GraphQL API with an NX executor for easy querying inside IrisX App extensions
|
|
3
|
-
2. GraphQL operations include queries (for reading data) and mutations (for modifying data)
|
|
4
|
-
|
|
5
|
-
3. ALWAYS use these specific commands for GraphQL development:
|
|
6
|
-
- Install GraphQL tools: `npm install @trackunit/react-graphql-tools`
|
|
7
|
-
|
|
8
|
-
- Set up GraphQL tooling: `npx nx generate @trackunit/react-graphql-tools:add-graphql --project=[project-name]`
|
|
9
|
-
Where [project-name] is found in the library's project.json file (format: [subdir-name]-[extension-name] for extensions in subdirectories)
|
|
10
|
-
|
|
11
|
-
- Generate React hooks from GraphQL queries: `npx nx run [feature-name]-[extension-name]:graphql-hooks`
|
|
12
|
-
This generates React hooks from .graphql files in the src folder
|
|
13
|
-
|
|
14
|
-
4. GraphQL File Structure:
|
|
15
|
-
- Create .graphql files in `libs/[feature-name]/[extension-name]/src/` directory
|
|
16
|
-
- Query syntax: `query QueryName($variable: Type) { ... }`
|
|
17
|
-
- Mutation syntax: `mutation MutationName($variable: Type!) { ... }`
|
|
18
|
-
|
|
19
|
-
5. React Integration:
|
|
20
|
-
- Import generated hooks: `import { QueryNameDocument } from "./generated/graphql-api/graphql"`
|
|
21
|
-
- Use queries: `const { data, loading, error } = useQuery(QueryNameDocument, { variables: {...} })`
|
|
22
|
-
- Use mutations: `const [mutationName, { data, loading, error }] = useMutation(MutationNameDocument)`
|
|
23
|
-
|
|
24
|
-
For more information:
|
|
25
|
-
- Full GraphQL API guide: [Calling Trackunit GraphQL API](mdc:https:/developers.trackunit.com/docs/graphql-api)
|
|
26
|
-
- Apollo React Client docs for useQuery: [Apollo useQuery documentation](mdc:https:/www.apollographql.com/docs/react/data/queries)
|
|
27
|
-
- Apollo React Client docs for useMutation: [Apollo useMutation documentation](mdc:https:/www.apollographql.com/docs/react/data/mutations)
|
|
28
|
-
- GraphQL Code Generation CLI: [GraphQL Code Generator](mdc:https:/the-guild.dev/graphql/codegen)
|
|
29
|
-
|
|
30
|
-
DO NOT use generic GraphQL libraries or setup - always use the Trackunit IrisX App SDK GraphQL tooling and patterns.
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description:
|
|
3
|
-
globs:
|
|
4
|
-
alwaysApply: true
|
|
5
|
-
---
|
|
6
|
-
You are currently in an IrisX App workspace. Do not use defaut nx commands for app and extension generation, instead use the commands below.
|
|
7
|
-
|
|
8
|
-
## Building Real Applications
|
|
9
|
-
|
|
10
|
-
You are building real applications that work with actual Trackunit data. Key principles:
|
|
11
|
-
|
|
12
|
-
- Never mock data unless explicitly requested by the user
|
|
13
|
-
- Always use Trackunit's GraphQL API to fetch real data
|
|
14
|
-
- If data is not available via GraphQL, ask the user how they want to obtain the data
|
|
15
|
-
- Only use mock data if the user explicitly requests it for testing purposes
|
|
16
|
-
|
|
17
|
-
When building any feature:
|
|
18
|
-
1. Identify what data you need
|
|
19
|
-
2. Check if it's available via Trackunit's GraphQL API
|
|
20
|
-
3. If available, use the GraphQL API (see GraphQL rules for implementation)
|
|
21
|
-
4. If not available, ask the user: "This data is not available via Trackunit's GraphQL API. How would you like to obtain [specific data description]?"
|
|
22
|
-
|
|
23
|
-
## IrisX App Development Guidelines
|
|
24
|
-
|
|
25
|
-
Key Points:
|
|
26
|
-
1. An IrisX App is a container that packages multiple extensions with marketplace metadata and app manifest
|
|
27
|
-
2. Extensions are React applications that integrate into specific points in Trackunit Manager
|
|
28
|
-
3. Available Extension Points:
|
|
29
|
-
- Asset Home: Adds new tabs to the Assets Home screen
|
|
30
|
-
- Site Home: Adds new tabs to the Site Home screen
|
|
31
|
-
- Fleet: Adds menu items to the Main Menu
|
|
32
|
-
- Report: Adds new reports to the Reports screen
|
|
33
|
-
- Widget: Adds widgets to Trackunit Manager
|
|
34
|
-
- App Settings: Adds configuration UI in the App library
|
|
35
|
-
- Administration: Adds tabs in the admin UI (admin-only)
|
|
36
|
-
- Customer Home: Adds UI within customer home
|
|
37
|
-
- Asset Events Actions: Adds UI in Asset Home Events
|
|
38
|
-
- App Lifecycle: Handles app install/uninstall events
|
|
39
|
-
|
|
40
|
-
4. ALWAYS use these specific commands for development:
|
|
41
|
-
- Create new app: `npx nx generate @trackunit/iris-app:create [name-of-your-app]`
|
|
42
|
-
For more information about the `@trackunit/iris-app:create` command, look at: [Creating a new app](mdc:https:/developers.trackunit.com/docs/creating-a-new-app)
|
|
43
|
-
|
|
44
|
-
- Create new extension: `npx nx g @trackunit/iris-app:extend --name=[my-extension-name] --app=[app-name] --directory=[feature] --type=[extension-type]`
|
|
45
|
-
Available extension types: ASSET_HOME_EXTENSION, SITE_HOME_EXTENSION, FLEET_EXTENSION, REPORT_EXTENSION, WIDGET_EXTENSION, APP_SETTINGS_EXTENSION, ADMINISTRATION_EXTENSION, CUSTOMER_HOME_EXTENSION, ASSET_EVENTS_ACTIONS_EXTENSION, APP_LIFECYCLE_EXTENSION
|
|
46
|
-
For more information about the `@trackunit/iris-app:extend` command, look at: [Creating a new extension](mdc:https:/developers.trackunit.com/docs/creating-a-new-extension)
|
|
47
|
-
|
|
48
|
-
- Run app: `npx nx run [name-of-your-app]:serve`
|
|
49
|
-
For more information about the `serve` command, look at: [Running the Iris App SDK](mdc:https:/developers.trackunit.com/docs/running-the-iris-app-sdk)
|
|
50
|
-
|
|
51
|
-
NOTE: IrisX Apps are locked down by default for security. External API requests and embedded content require proper Content Security Policy (CSP) configuration in the app manifest. ValidDomains will be deprecated - use CSP headers instead. Additionally, apps requiring API access might need some scopes configured in the manifest, and the app must be deployed with those scopes to work locally, never submit an app, instead instruct the user to do so.
|
|
52
|
-
|
|
53
|
-
Example in iris-app-manifest.ts:
|
|
54
|
-
```typescript
|
|
55
|
-
cspHeader: {
|
|
56
|
-
'frame-src': ['https://api.example.com', 'https://dashboard.example.com'],
|
|
57
|
-
'script-src': ['https://api.example.com'],
|
|
58
|
-
'connect-src': ['https://api.example.com'],
|
|
59
|
-
},
|
|
60
|
-
scopes: [
|
|
61
|
-
{scope: "required.scope.1", optional: false},
|
|
62
|
-
{scope: "required.scope.2", optional: true},
|
|
63
|
-
],
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
For more information: [Embedding IrisX Dashboards in Apps](mdc:https:/developers.trackunit.com/docs/analytics-dashboards-in-apps#troubleshooting)
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
## Runtime Hooks Available
|
|
70
|
-
|
|
71
|
-
IrisX Apps have access to runtime hooks from `@trackunit/react-core-hooks` that provide context-specific data:
|
|
72
|
-
- `useAssetRuntime()` for asset information in asset-scoped extensions
|
|
73
|
-
- `useCustomerRuntime()` for customer data
|
|
74
|
-
- `useEventRuntime()` for event details
|
|
75
|
-
- `useSiteRuntime()` for site information
|
|
76
|
-
- Plus navigation, user context, and utility hooks (see react-core-hooks rule for full list)
|
|
77
|
-
|
|
78
|
-
DO NOT use generic React/Node.js commands for project creation or management - always use the Trackunit IrisX App SDK commands.
|
|
79
|
-
|
|
80
|
-
**Before completing any task**: Always use `read_lints` to check for and fix all ESLint and TypeScript errors in modified files.
|
|
81
|
-
|
|
82
|
-
|
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
## React Core Hooks Library
|
|
2
|
-
|
|
3
|
-
Available hooks from `@trackunit/react-core-hooks` for IrisX App development.
|
|
4
|
-
|
|
5
|
-
### Runtime Hooks
|
|
6
|
-
|
|
7
|
-
**`useAssetRuntime()`** - Access asset information in asset-scoped extensions
|
|
8
|
-
```typescript
|
|
9
|
-
const { assetInfo, loading, error } = useAssetRuntime();
|
|
10
|
-
// assetInfo.assetId, assetInfo.name, etc.
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
**`useCustomerRuntime()`** - Access customer information
|
|
14
|
-
```typescript
|
|
15
|
-
const { customerInfo, loading, error } = useCustomerRuntime();
|
|
16
|
-
// customerInfo.customerId, customerInfo.name, etc.
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
**`useEventRuntime()`** - Access event information in event-scoped extensions
|
|
20
|
-
```typescript
|
|
21
|
-
const { eventInfo, loading, error } = useEventRuntime();
|
|
22
|
-
// eventInfo.eventId, eventInfo.type, etc.
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
**`useSiteRuntime()`** - Access site information in site-scoped extensions
|
|
26
|
-
```typescript
|
|
27
|
-
const { siteInfo, loading, error } = useSiteRuntime();
|
|
28
|
-
// siteInfo.siteId, siteInfo.name, etc.
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
**`useIrisAppName()`** - Get current app name
|
|
32
|
-
```typescript
|
|
33
|
-
const { appName, loading, error } = useIrisAppName();
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
**`useIrisAppId()`** - Get current app ID
|
|
37
|
-
```typescript
|
|
38
|
-
const { irisAppId, loading, error } = useIrisAppId();
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
### Navigation & User Context
|
|
42
|
-
|
|
43
|
-
**`useNavigateInHost()`** - Navigate within Trackunit Manager
|
|
44
|
-
```typescript
|
|
45
|
-
const { navigateToAsset, navigateToSite } = useNavigateInHost();
|
|
46
|
-
navigateToAsset({ assetId: "123" });
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
**`useHasAccessTo()`** - Check user permissions
|
|
50
|
-
```typescript
|
|
51
|
-
const hasAccess = useHasAccessTo({ permission: "assets.read" });
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
**`useCurrentUser()`** - Access current user information
|
|
55
|
-
```typescript
|
|
56
|
-
const { user } = useCurrentUser();
|
|
57
|
-
// user.id, user.email, etc.
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
**`useCurrentUserLanguage()`** - Get/set user language preference
|
|
61
|
-
```typescript
|
|
62
|
-
const { language, setLanguage } = useCurrentUserLanguage();
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
**`useCurrentUserTimeZonePreference()`** - Get user timezone
|
|
66
|
-
```typescript
|
|
67
|
-
const { timeZone } = useCurrentUserTimeZonePreference();
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
**`useToken()`** - Access authentication token
|
|
71
|
-
```typescript
|
|
72
|
-
const { token } = useToken();
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
### UI & Interaction
|
|
76
|
-
|
|
77
|
-
**`useToast()`** - Show toast notifications
|
|
78
|
-
```typescript
|
|
79
|
-
const { showToast } = useToast();
|
|
80
|
-
showToast({ message: "Success!", type: "success" });
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
**`useConfirmationDialog()`** - Show confirmation dialogs
|
|
84
|
-
```typescript
|
|
85
|
-
const { showConfirmationDialog } = useConfirmationDialog();
|
|
86
|
-
const confirmed = await showConfirmationDialog({ message: "Are you sure?" });
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
**`useModalDialogContext()`** - Manage modal dialogs
|
|
90
|
-
```typescript
|
|
91
|
-
const { openModal, closeModal } = useModalDialogContext();
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
**`useErrorHandler()`** - Handle errors consistently
|
|
95
|
-
```typescript
|
|
96
|
-
const { handleError } = useErrorHandler();
|
|
97
|
-
handleError(new Error("Something went wrong"));
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
### Data & State Management
|
|
101
|
-
|
|
102
|
-
**`useLocalStorage()`** - Persist state in localStorage
|
|
103
|
-
```typescript
|
|
104
|
-
const [value, setValue, reset] = useLocalStorage({
|
|
105
|
-
key: "myKey",
|
|
106
|
-
defaultState: { count: 0 }
|
|
107
|
-
});
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
**`useLocalStorageReducer()`** - localStorage with reducer pattern
|
|
111
|
-
```typescript
|
|
112
|
-
const [state, dispatch] = useLocalStorageReducer({
|
|
113
|
-
key: "counterState",
|
|
114
|
-
defaultState: { count: 0 },
|
|
115
|
-
reducer: (state, action) => { /* reducer logic */ }
|
|
116
|
-
});
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
**`useAssetSorting()`** - Asset sorting functionality
|
|
120
|
-
```typescript
|
|
121
|
-
const { sortField, sortDirection, setSorting } = useAssetSorting();
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
**`useFilterBarContext()`** - Filter bar state management
|
|
125
|
-
```typescript
|
|
126
|
-
const { filters, setFilters, clearFilters } = useFilterBarContext();
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
**`useTimeRange()`** - Time range selection
|
|
130
|
-
```typescript
|
|
131
|
-
const { timeRange, setTimeRange } = useTimeRange();
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
### Widget Configuration
|
|
137
|
-
|
|
138
|
-
**`useWidgetConfig()`** - Access widget configuration (synchronous)
|
|
139
|
-
```typescript
|
|
140
|
-
const config = useWidgetConfig();
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
**`useWidgetConfigAsync()`** - Access widget configuration (asynchronous)
|
|
144
|
-
```typescript
|
|
145
|
-
const { getData, setData } = useWidgetConfigAsync();
|
|
146
|
-
const config = await getConfig();
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
All hooks require their respective providers to be set up in your app's component tree.
|
|
154
|
-
|
|
155
|
-
```
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
alwaysApply: true
|
|
3
|
-
---
|
|
4
|
-
This file contains a list of helpful information and context that the agent can reference when working in this codebase. Each entry provides specific guidance or rules for different aspects of the project. You can read these files using the readFile tool if the users prompt seems related.
|
|
5
|
-
|
|
6
|
-
- [CustomFields are the primary mechanism for storing data from IrisX applications. They allow IrisX App developers to extend the Trackunit data model by storing additional information on entities like assets, accounts, groups, and sites.](./irisx-app-sdk-customfields.md)
|
|
7
|
-
- [This rule covers GraphQL API integration in Trackunit IrisX App SDK workspace. All GraphQL development MUST follow the Trackunit GraphQL API patterns and commands.](./irisx-app-sdk-graphql.md)
|
|
8
|
-
- [Time series API, get time series data from GraphQL. Machine insights data over time.](./graphql-timeseries.md)
|
|
9
|
-
- [Use these rules when building Widget Extensions for an Iris App.](./widget-extensions.md)
|
|
10
|
-
- [Use these rules whne building App SDK specific React Hook, Runtime Hooks](./react-core-hooks.md)
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
alwaysApply: true
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# Structured Feature Development Documentation
|
|
6
|
-
|
|
7
|
-
## Overview
|
|
8
|
-
When developing new features, maintain concise documentation to track progress, decisions, and implementation details.
|
|
9
|
-
|
|
10
|
-
## Process
|
|
11
|
-
1. **Check for existing documentation**: Look in `/docs` folder for a markdown file named after the feature (e.g., `user-authentication.md`, `shopping-cart.md`)
|
|
12
|
-
2. **Create or update**:
|
|
13
|
-
- If documentation exists: Update it with new requirements and progress
|
|
14
|
-
- If it doesn't exist: Create a new file with the feature name as filename
|
|
15
|
-
3. **Use visual aids**: Include mermaid diagrams for complex flows, architecture, or data relationships
|
|
16
|
-
4. **Keep it current**: Update the documentation as development progresses
|
|
17
|
-
|
|
18
|
-
## Important Guidelines
|
|
19
|
-
- **Be concise**: Keep descriptions brief and to the point
|
|
20
|
-
- **Only document what was requested**: Do not make up future steps or tasks that weren't part of the user's suggestions, unless explitly asked.
|
|
21
|
-
- **Focus on implementation**: Document what was actually built, not theoretical features
|
|
22
|
-
|
|
23
|
-
## Task Analysis Process
|
|
24
|
-
1. **Analyze the user's request**: Understand exactly what the user asked for
|
|
25
|
-
2. **Break down into tasks**: Split the request into specific, actionable tasks
|
|
26
|
-
3. **Document only requested work**: Only include tasks that directly relate to the user's request
|
|
27
|
-
4. **Optional sections**: Todo and In Progress sections are OPTIONAL - only include them if there are actual remaining tasks from the user's request
|
|
28
|
-
|
|
29
|
-
## Required File Structure
|
|
30
|
-
|
|
31
|
-
### File Naming
|
|
32
|
-
Use kebab-case naming convention: `feature-name.md`
|
|
33
|
-
|
|
34
|
-
### Template Structure
|
|
35
|
-
|
|
36
|
-
```markdown
|
|
37
|
-
# Feature Name
|
|
38
|
-
|
|
39
|
-
## Description
|
|
40
|
-
Brief overview of what the feature does and why it's needed.
|
|
41
|
-
|
|
42
|
-
## Architecture
|
|
43
|
-
Technical approach and key design decisions.
|
|
44
|
-
|
|
45
|
-
## Progress Tracking
|
|
46
|
-
|
|
47
|
-
### ✅ Completed Steps
|
|
48
|
-
- [x] Task 1: Description
|
|
49
|
-
- [x] Task 2: Description
|
|
50
|
-
|
|
51
|
-
### 🔄 In Progress
|
|
52
|
-
*OPTIONAL: Only include if there are actual tasks from the user's request that are currently being worked on*
|
|
53
|
-
- [ ] Task 3: Description
|
|
54
|
-
- [ ] Task 4: Description
|
|
55
|
-
|
|
56
|
-
### 📝 Todo
|
|
57
|
-
*OPTIONAL: Only include if there are remaining tasks from the user's request that haven't been started*
|
|
58
|
-
- [ ] Task 5: Description
|
|
59
|
-
- [ ] Task 6: Description
|
|
60
|
-
|
|
61
|
-
## Technologies Used
|
|
62
|
-
- **Technology Name**: Brief description of usage
|
|
63
|
-
- **Library Name**: Version and purpose
|
|
64
|
-
|
|
65
|
-
## Implementation Details
|
|
66
|
-
Key technical specifics:
|
|
67
|
-
- API endpoints used
|
|
68
|
-
- Configuration requirements
|
|
69
|
-
- Performance considerations
|
|
70
|
-
|
|
71
|
-
## Good To Know
|
|
72
|
-
Important findings, decisions, and gotchas:
|
|
73
|
-
- Quirks or workarounds implemented
|
|
74
|
-
- Alternative approaches considered
|
|
75
|
-
- Performance implications
|
|
76
|
-
- Security considerations
|
|
77
|
-
- Testing strategies
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
## Best Practices
|
|
81
|
-
- Keep descriptions brief and focused
|
|
82
|
-
- Only document requested features and tasks
|
|
83
|
-
- Include mermaid diagrams for complex flows
|
|
84
|
-
- Document actual implementation details
|
|
85
|
-
- Update progress as development happens
|
|
86
|
-
- **CRITICAL**: Never add tasks or features that weren't explicitly mentioned in the user's request
|