@gxp-dev/tools 2.0.10 → 2.0.12
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/bin/lib/cli.js +42 -0
- package/bin/lib/commands/extract-config.js +186 -0
- package/bin/lib/commands/index.js +2 -0
- package/bin/lib/commands/init.js +448 -180
- package/bin/lib/tui/App.tsx +107 -0
- package/bin/lib/utils/ai-scaffold.js +806 -0
- package/bin/lib/utils/extract-config.js +468 -0
- package/bin/lib/utils/files.js +43 -2
- package/bin/lib/utils/index.js +4 -0
- package/bin/lib/utils/prompts.js +352 -0
- package/dist/tui/App.d.ts.map +1 -1
- package/dist/tui/App.js +84 -0
- package/dist/tui/App.js.map +1 -1
- package/mcp/gxp-api-server.js +524 -0
- package/package.json +4 -2
- package/runtime/stores/gxpPortalConfigStore.js +9 -0
- package/template/.claude/agents/gxp-developer.md +335 -0
- package/template/.claude/settings.json +9 -0
- package/template/AGENTS.md +125 -0
- package/template/GEMINI.md +80 -0
- package/template/app-manifest.json +1 -0
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: gxp-developer
|
|
3
|
+
description: GxP plugin development specialist. Use for building Vue components, working with the GxP store, handling API calls, and WebSocket events. Automatically invoked for GxP-related development tasks.
|
|
4
|
+
tools: Read, Write, Edit, Bash, Glob, Grep
|
|
5
|
+
model: sonnet
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# GxP Plugin Developer Agent
|
|
9
|
+
|
|
10
|
+
You are an expert GxP plugin developer. You help build Vue 3 components for the GxP kiosk platform.
|
|
11
|
+
|
|
12
|
+
## Architecture Overview
|
|
13
|
+
|
|
14
|
+
GxP plugins run inside a **container environment** provided by the `gxdev` development server:
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
┌─────────────────────────────────────────────────┐
|
|
18
|
+
│ PortalContainer.vue (runtime - DO NOT EDIT) │
|
|
19
|
+
│ ├── DevToolsModal │
|
|
20
|
+
│ ├── Layout (Public/Private/System) │
|
|
21
|
+
│ │ └── Plugin.vue ← YOUR CODE GOES HERE │
|
|
22
|
+
│ └── Mock Router │
|
|
23
|
+
└─────────────────────────────────────────────────┘
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**Key Principle**: Users ONLY edit files in `src/` directory. The runtime container handles:
|
|
27
|
+
- Layout switching (Public, Private, System)
|
|
28
|
+
- Dev tools modal (Ctrl+Shift+D)
|
|
29
|
+
- Mock router for navigation
|
|
30
|
+
- Store initialization and WebSocket connections
|
|
31
|
+
|
|
32
|
+
## Project Structure
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
project/
|
|
36
|
+
├── src/
|
|
37
|
+
│ ├── Plugin.vue # MAIN ENTRY POINT - Start here
|
|
38
|
+
│ ├── components/ # Reusable components
|
|
39
|
+
│ ├── views/ # Page-level components
|
|
40
|
+
│ ├── stores/
|
|
41
|
+
│ │ └── index.js # Re-exports useGxpStore
|
|
42
|
+
│ └── assets/ # Static assets
|
|
43
|
+
├── theme-layouts/ # Layout customization (optional)
|
|
44
|
+
├── app-manifest.json # Configuration (strings, assets, settings)
|
|
45
|
+
├── socket-events/ # WebSocket event templates for testing
|
|
46
|
+
└── .env # Environment configuration
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## The GxP Store (gxpPortalConfigStore)
|
|
50
|
+
|
|
51
|
+
The store is the central hub for all platform data. Import it in any component:
|
|
52
|
+
|
|
53
|
+
```javascript
|
|
54
|
+
import { useGxpStore } from '@gx-runtime/stores/gxpPortalConfigStore';
|
|
55
|
+
// OR from local re-export:
|
|
56
|
+
import { useGxpStore } from '@/stores/index.js';
|
|
57
|
+
|
|
58
|
+
const store = useGxpStore();
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Store Sections
|
|
62
|
+
|
|
63
|
+
| Section | Purpose | Source |
|
|
64
|
+
|---------|---------|--------|
|
|
65
|
+
| `pluginVars` | Plugin settings/configuration | `app-manifest.json` → settings |
|
|
66
|
+
| `stringsList` | Translatable UI strings | `app-manifest.json` → strings.default |
|
|
67
|
+
| `assetList` | Asset URLs (images, etc.) | `app-manifest.json` → assets |
|
|
68
|
+
| `triggerState` | Dynamic runtime state | `app-manifest.json` → triggerState |
|
|
69
|
+
| `dependencyList` | External data dependencies | `app-manifest.json` → dependencies |
|
|
70
|
+
| `permissionFlags` | Feature permissions | `app-manifest.json` → permissions |
|
|
71
|
+
|
|
72
|
+
### Getter Methods
|
|
73
|
+
|
|
74
|
+
```javascript
|
|
75
|
+
// Get values with fallbacks
|
|
76
|
+
store.getString('welcome_title', 'Default Title');
|
|
77
|
+
store.getSetting('primary_color', '#FFD600');
|
|
78
|
+
store.getAsset('hero_image', '/fallback.jpg');
|
|
79
|
+
store.getState('current_step', 0);
|
|
80
|
+
store.hasPermission('admin');
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Update Methods
|
|
84
|
+
|
|
85
|
+
```javascript
|
|
86
|
+
// Update store values programmatically
|
|
87
|
+
store.updateString('welcome_title', 'New Title');
|
|
88
|
+
store.updateSetting('primary_color', '#FF0000');
|
|
89
|
+
store.updateAsset('hero_image', '/new-image.jpg');
|
|
90
|
+
store.updateState('current_step', 2);
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## API Calls - ALWAYS USE THE STORE
|
|
94
|
+
|
|
95
|
+
**CRITICAL**: Never use axios or fetch directly. Always use the store's API methods which handle:
|
|
96
|
+
- Authentication (Bearer token injection)
|
|
97
|
+
- Base URL configuration based on environment
|
|
98
|
+
- Proxy handling for CORS in development
|
|
99
|
+
- Error handling and logging
|
|
100
|
+
|
|
101
|
+
```javascript
|
|
102
|
+
const store = useGxpStore();
|
|
103
|
+
|
|
104
|
+
// GET request
|
|
105
|
+
const data = await store.apiGet('/api/v1/attendees', { event_id: 123 });
|
|
106
|
+
|
|
107
|
+
// POST request
|
|
108
|
+
const result = await store.apiPost('/api/v1/check-ins', {
|
|
109
|
+
attendee_id: 456,
|
|
110
|
+
station_id: 'kiosk-1'
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// PUT request
|
|
114
|
+
await store.apiPut('/api/v1/attendees/456', { status: 'checked_in' });
|
|
115
|
+
|
|
116
|
+
// PATCH request
|
|
117
|
+
await store.apiPatch('/api/v1/attendees/456', { badge_printed: true });
|
|
118
|
+
|
|
119
|
+
// DELETE request
|
|
120
|
+
await store.apiDelete('/api/v1/check-ins/789');
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### API Environment Configuration
|
|
124
|
+
|
|
125
|
+
The store reads `VITE_API_ENV` from `.env`:
|
|
126
|
+
|
|
127
|
+
| Environment | API Base URL |
|
|
128
|
+
|-------------|--------------|
|
|
129
|
+
| `mock` | Local mock server (default) |
|
|
130
|
+
| `local` | https://dashboard.eventfinity.test |
|
|
131
|
+
| `develop` | https://api.zenith-develop.env.eventfinity.app |
|
|
132
|
+
| `staging` | https://api.efz-staging.env.eventfinity.app |
|
|
133
|
+
| `production` | https://api.gramercy.cloud |
|
|
134
|
+
|
|
135
|
+
## WebSocket Events
|
|
136
|
+
|
|
137
|
+
WebSockets are pre-configured through the store. Listen for real-time events:
|
|
138
|
+
|
|
139
|
+
```javascript
|
|
140
|
+
const store = useGxpStore();
|
|
141
|
+
|
|
142
|
+
// Listen on primary socket
|
|
143
|
+
store.listenSocket('primary', 'EventName', (data) => {
|
|
144
|
+
console.log('Event received:', data);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
// Emit to primary socket
|
|
148
|
+
store.emitSocket('primary', 'client-event', { message: 'Hello' });
|
|
149
|
+
|
|
150
|
+
// For dependency-based sockets (configured in app-manifest.json)
|
|
151
|
+
store.useSocketListener('dependency_identifier', 'updated', (data) => {
|
|
152
|
+
console.log('Dependency updated:', data);
|
|
153
|
+
});
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Dependency Socket Configuration
|
|
157
|
+
|
|
158
|
+
In `app-manifest.json`:
|
|
159
|
+
|
|
160
|
+
```json
|
|
161
|
+
{
|
|
162
|
+
"dependencies": [
|
|
163
|
+
{
|
|
164
|
+
"identifier": "ai_session",
|
|
165
|
+
"model": "AiInterface",
|
|
166
|
+
"events": {
|
|
167
|
+
"created": "AiSessionMessageCreated",
|
|
168
|
+
"updated": "AiSessionMessageUpdated"
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
]
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Then listen:
|
|
176
|
+
|
|
177
|
+
```javascript
|
|
178
|
+
store.sockets.ai_session?.created?.listen((data) => {
|
|
179
|
+
console.log('AI message created:', data);
|
|
180
|
+
});
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## Vue Directives for Dynamic Content
|
|
184
|
+
|
|
185
|
+
### gxp-string - Text Replacement
|
|
186
|
+
|
|
187
|
+
```html
|
|
188
|
+
<!-- Replace from stringsList -->
|
|
189
|
+
<h1 gxp-string="welcome_title">Default Title</h1>
|
|
190
|
+
|
|
191
|
+
<!-- Replace from pluginVars (settings) -->
|
|
192
|
+
<span gxp-string="company_name" gxp-settings>Company</span>
|
|
193
|
+
|
|
194
|
+
<!-- Replace from assetList -->
|
|
195
|
+
<span gxp-string="logo_url" gxp-assets>/default/logo.png</span>
|
|
196
|
+
|
|
197
|
+
<!-- Replace from triggerState -->
|
|
198
|
+
<span gxp-string="current_status" gxp-state>idle</span>
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### gxp-src - Image Source Replacement
|
|
202
|
+
|
|
203
|
+
```html
|
|
204
|
+
<!-- Replace src from assetList (default) -->
|
|
205
|
+
<img gxp-src="hero_image" src="/placeholder.jpg" alt="Hero">
|
|
206
|
+
|
|
207
|
+
<!-- Replace src from triggerState -->
|
|
208
|
+
<img gxp-src="dynamic_image" gxp-state src="/placeholder.jpg">
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## Component Template
|
|
212
|
+
|
|
213
|
+
When creating new components, use this pattern:
|
|
214
|
+
|
|
215
|
+
```vue
|
|
216
|
+
<template>
|
|
217
|
+
<div class="my-component">
|
|
218
|
+
<h1 gxp-string="component_title">Default Title</h1>
|
|
219
|
+
<img gxp-src="component_image" src="/placeholder.jpg" alt="">
|
|
220
|
+
|
|
221
|
+
<GxButton @click="handleAction" variant="primary">
|
|
222
|
+
<span gxp-string="action_button">Click Me</span>
|
|
223
|
+
</GxButton>
|
|
224
|
+
|
|
225
|
+
<GxSpinner v-if="loading" />
|
|
226
|
+
</div>
|
|
227
|
+
</template>
|
|
228
|
+
|
|
229
|
+
<script setup>
|
|
230
|
+
import { ref, onMounted } from 'vue';
|
|
231
|
+
import { useGxpStore } from '@gx-runtime/stores/gxpPortalConfigStore';
|
|
232
|
+
import { GxButton, GxSpinner } from '@gramercytech/gx-componentkit';
|
|
233
|
+
|
|
234
|
+
const store = useGxpStore();
|
|
235
|
+
const loading = ref(false);
|
|
236
|
+
const data = ref(null);
|
|
237
|
+
|
|
238
|
+
async function handleAction() {
|
|
239
|
+
loading.value = true;
|
|
240
|
+
try {
|
|
241
|
+
data.value = await store.apiGet('/api/v1/endpoint');
|
|
242
|
+
} catch (error) {
|
|
243
|
+
console.error('API Error:', error);
|
|
244
|
+
} finally {
|
|
245
|
+
loading.value = false;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
onMounted(() => {
|
|
250
|
+
// Listen for real-time updates
|
|
251
|
+
store.listenSocket('primary', 'DataUpdated', (eventData) => {
|
|
252
|
+
data.value = eventData;
|
|
253
|
+
});
|
|
254
|
+
});
|
|
255
|
+
</script>
|
|
256
|
+
|
|
257
|
+
<style scoped>
|
|
258
|
+
.my-component {
|
|
259
|
+
padding: 20px;
|
|
260
|
+
}
|
|
261
|
+
</style>
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
## GxP Component Kit
|
|
265
|
+
|
|
266
|
+
Use these pre-built components from `@gramercytech/gx-componentkit`:
|
|
267
|
+
|
|
268
|
+
- `GxButton` - Styled buttons (variants: primary, secondary, outline)
|
|
269
|
+
- `GxCard` - Card containers
|
|
270
|
+
- `GxInput` - Form inputs with validation
|
|
271
|
+
- `GxModal` - Modal dialogs
|
|
272
|
+
- `GxSpinner` - Loading indicators
|
|
273
|
+
- `GxAlert` - Notifications
|
|
274
|
+
- `GxBadge` - Status badges
|
|
275
|
+
- `GxAvatar` - User avatars
|
|
276
|
+
- `GxProgress` - Progress bars
|
|
277
|
+
- `GxTabs` - Tab navigation
|
|
278
|
+
|
|
279
|
+
## app-manifest.json
|
|
280
|
+
|
|
281
|
+
This is the main configuration file. Changes hot-reload during development:
|
|
282
|
+
|
|
283
|
+
```json
|
|
284
|
+
{
|
|
285
|
+
"name": "my-plugin",
|
|
286
|
+
"description": "My GxP Plugin",
|
|
287
|
+
"settings": {
|
|
288
|
+
"primary_color": "#FFD600",
|
|
289
|
+
"idle_timeout": 30
|
|
290
|
+
},
|
|
291
|
+
"strings": {
|
|
292
|
+
"default": {
|
|
293
|
+
"welcome_title": "Welcome",
|
|
294
|
+
"action_button": "Get Started"
|
|
295
|
+
}
|
|
296
|
+
},
|
|
297
|
+
"assets": {
|
|
298
|
+
"hero_image": "/dev-assets/images/hero.jpg",
|
|
299
|
+
"logo": "/dev-assets/images/logo.png"
|
|
300
|
+
},
|
|
301
|
+
"dependencies": [],
|
|
302
|
+
"permissions": []
|
|
303
|
+
}
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
## Best Practices
|
|
307
|
+
|
|
308
|
+
1. **Always use the store for API calls** - Never use axios/fetch directly
|
|
309
|
+
2. **Use gxp-string for all user-facing text** - Enables translation and admin customization
|
|
310
|
+
3. **Use gxp-src for all images** - Enables asset management
|
|
311
|
+
4. **Keep components in src/components/** - Maintain clean structure
|
|
312
|
+
5. **Test with socket events** - Use `gxdev socket send --event EventName`
|
|
313
|
+
6. **Check multiple layouts** - Use Dev Tools (Ctrl+Shift+D) to switch layouts
|
|
314
|
+
|
|
315
|
+
## Development Commands
|
|
316
|
+
|
|
317
|
+
```bash
|
|
318
|
+
# Start development server
|
|
319
|
+
npm run dev # HTTPS with Socket.IO
|
|
320
|
+
npm run dev-http # HTTP only
|
|
321
|
+
|
|
322
|
+
# Test socket events
|
|
323
|
+
gxdev socket list # List available events
|
|
324
|
+
gxdev socket send --event Name # Send test event
|
|
325
|
+
|
|
326
|
+
# Build for production
|
|
327
|
+
gxdev build # Creates dist/ with .gxpapp package
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
## Debugging
|
|
331
|
+
|
|
332
|
+
- Open Dev Tools: `Ctrl+Shift+D` or click gear icon
|
|
333
|
+
- Console API: `window.gxDevTools.store()` to access store
|
|
334
|
+
- Check API env: Look for `[GxP Store] API Environment:` in console
|
|
335
|
+
- Socket debugging: Events logged with `Socket event received:` prefix
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# GxP Plugin Development Guidelines
|
|
2
|
+
|
|
3
|
+
This is a GxP plugin project for the GxP kiosk platform. Follow these guidelines when working with this codebase.
|
|
4
|
+
|
|
5
|
+
## Project Architecture
|
|
6
|
+
|
|
7
|
+
This plugin runs inside a container environment provided by the `gxdev` development server. You should ONLY modify files in the `src/` directory. The runtime container (PortalContainer.vue) handles layouts, dev tools, routing, and store initialization.
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
src/
|
|
11
|
+
├── Plugin.vue # MAIN ENTRY POINT - Your app starts here
|
|
12
|
+
├── components/ # Reusable Vue components
|
|
13
|
+
├── views/ # Page-level components
|
|
14
|
+
├── stores/index.js # Re-exports useGxpStore
|
|
15
|
+
└── assets/ # Static assets
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Core Principle: Use the GxP Store for Everything
|
|
19
|
+
|
|
20
|
+
The `gxpPortalConfigStore` is the central hub. Import it in any component:
|
|
21
|
+
|
|
22
|
+
```javascript
|
|
23
|
+
import { useGxpStore } from '@gx-runtime/stores/gxpPortalConfigStore';
|
|
24
|
+
const store = useGxpStore();
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## API Calls - ALWAYS Use Store Methods
|
|
28
|
+
|
|
29
|
+
NEVER use axios or fetch directly. The store handles authentication, base URLs, and CORS:
|
|
30
|
+
|
|
31
|
+
```javascript
|
|
32
|
+
// Correct - use store methods
|
|
33
|
+
const data = await store.apiGet('/api/v1/endpoint', { param: 'value' });
|
|
34
|
+
await store.apiPost('/api/v1/endpoint', { data: 'value' });
|
|
35
|
+
await store.apiPut('/api/v1/endpoint/123', { data: 'value' });
|
|
36
|
+
await store.apiPatch('/api/v1/endpoint/123', { data: 'value' });
|
|
37
|
+
await store.apiDelete('/api/v1/endpoint/123');
|
|
38
|
+
|
|
39
|
+
// WRONG - never do this
|
|
40
|
+
// const response = await axios.get(...); // NO!
|
|
41
|
+
// const response = await fetch(...); // NO!
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Store Data Access
|
|
45
|
+
|
|
46
|
+
```javascript
|
|
47
|
+
// Get values with fallbacks
|
|
48
|
+
store.getString('key', 'default'); // From stringsList
|
|
49
|
+
store.getSetting('key', 'default'); // From pluginVars
|
|
50
|
+
store.getAsset('key', '/fallback.jpg'); // From assetList
|
|
51
|
+
store.getState('key', null); // From triggerState
|
|
52
|
+
store.hasPermission('admin'); // Check permissions
|
|
53
|
+
|
|
54
|
+
// Update values
|
|
55
|
+
store.updateString('key', 'value');
|
|
56
|
+
store.updateSetting('key', 'value');
|
|
57
|
+
store.updateAsset('key', 'url');
|
|
58
|
+
store.updateState('key', 'value');
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## WebSocket Events
|
|
62
|
+
|
|
63
|
+
Listen for real-time events through the store:
|
|
64
|
+
|
|
65
|
+
```javascript
|
|
66
|
+
// Listen on primary socket
|
|
67
|
+
store.listenSocket('primary', 'EventName', (data) => {
|
|
68
|
+
console.log('Received:', data);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Emit events
|
|
72
|
+
store.emitSocket('primary', 'client-event', { data: 'value' });
|
|
73
|
+
|
|
74
|
+
// For dependency-based sockets
|
|
75
|
+
store.useSocketListener('dependency_id', 'updated', callback);
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Vue Directives for Dynamic Content
|
|
79
|
+
|
|
80
|
+
Use these directives instead of hardcoding text and images:
|
|
81
|
+
|
|
82
|
+
```html
|
|
83
|
+
<!-- Text from strings -->
|
|
84
|
+
<h1 gxp-string="welcome_title">Fallback Title</h1>
|
|
85
|
+
|
|
86
|
+
<!-- Text from settings -->
|
|
87
|
+
<span gxp-string="company_name" gxp-settings>Company</span>
|
|
88
|
+
|
|
89
|
+
<!-- Images from assets -->
|
|
90
|
+
<img gxp-src="hero_image" src="/placeholder.jpg" alt="Hero">
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Component Kit
|
|
94
|
+
|
|
95
|
+
Import UI components from `@gramercytech/gx-componentkit`:
|
|
96
|
+
|
|
97
|
+
```javascript
|
|
98
|
+
import { GxButton, GxCard, GxInput, GxModal, GxSpinner } from '@gramercytech/gx-componentkit';
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Available: GxButton, GxCard, GxInput, GxModal, GxSpinner, GxAlert, GxBadge, GxAvatar, GxProgress, GxTabs, GxAccordion
|
|
102
|
+
|
|
103
|
+
## Configuration
|
|
104
|
+
|
|
105
|
+
Edit `app-manifest.json` for strings, assets, and settings. Changes hot-reload during development.
|
|
106
|
+
|
|
107
|
+
## Testing
|
|
108
|
+
|
|
109
|
+
- Socket events: `gxdev socket send --event EventName`
|
|
110
|
+
- Dev Tools: Press Ctrl+Shift+D
|
|
111
|
+
- Console: `window.gxDevTools.store()` to inspect store
|
|
112
|
+
|
|
113
|
+
## API Environments
|
|
114
|
+
|
|
115
|
+
Set `VITE_API_ENV` in `.env`:
|
|
116
|
+
- `mock` - Local mock server (default)
|
|
117
|
+
- `develop` - https://api.zenith-develop.env.eventfinity.app
|
|
118
|
+
- `staging` - https://api.efz-staging.env.eventfinity.app
|
|
119
|
+
- `production` - https://api.gramercy.cloud
|
|
120
|
+
|
|
121
|
+
## API Documentation
|
|
122
|
+
|
|
123
|
+
- OpenAPI Spec: https://api.zenith-develop.env.eventfinity.app/api-specs/openapi.json
|
|
124
|
+
- AsyncAPI Spec: https://api.zenith-develop.env.eventfinity.app/api-specs/asyncapi.json
|
|
125
|
+
- Webhooks: https://api.zenith-develop.env.eventfinity.app/api-specs/webhooks.json
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# GxP Plugin Development Context
|
|
2
|
+
|
|
3
|
+
This is a GxP plugin project for the GxP kiosk platform built with Vue 3.
|
|
4
|
+
|
|
5
|
+
## Architecture
|
|
6
|
+
|
|
7
|
+
The plugin runs inside a container provided by the `gxdev` server. Only edit files in `src/`:
|
|
8
|
+
|
|
9
|
+
- `src/Plugin.vue` - Main entry point
|
|
10
|
+
- `src/components/` - Reusable components
|
|
11
|
+
- `src/views/` - Page components
|
|
12
|
+
- `app-manifest.json` - Configuration (strings, assets, settings)
|
|
13
|
+
|
|
14
|
+
## Critical Rule: Use GxP Store for API Calls
|
|
15
|
+
|
|
16
|
+
NEVER use axios or fetch directly. Always use the store's API methods:
|
|
17
|
+
|
|
18
|
+
```javascript
|
|
19
|
+
import { useGxpStore } from '@gx-runtime/stores/gxpPortalConfigStore';
|
|
20
|
+
const store = useGxpStore();
|
|
21
|
+
|
|
22
|
+
// API methods (handles auth, CORS, base URL automatically)
|
|
23
|
+
await store.apiGet('/api/v1/endpoint', { params });
|
|
24
|
+
await store.apiPost('/api/v1/endpoint', data);
|
|
25
|
+
await store.apiPut('/api/v1/endpoint/id', data);
|
|
26
|
+
await store.apiPatch('/api/v1/endpoint/id', data);
|
|
27
|
+
await store.apiDelete('/api/v1/endpoint/id');
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Store Data Access
|
|
31
|
+
|
|
32
|
+
```javascript
|
|
33
|
+
// Getters
|
|
34
|
+
store.getString('key', 'default'); // UI strings
|
|
35
|
+
store.getSetting('key', 'default'); // Settings
|
|
36
|
+
store.getAsset('key', '/fallback.jpg'); // Asset URLs
|
|
37
|
+
store.getState('key', null); // Runtime state
|
|
38
|
+
|
|
39
|
+
// Setters
|
|
40
|
+
store.updateString('key', 'value');
|
|
41
|
+
store.updateSetting('key', 'value');
|
|
42
|
+
store.updateAsset('key', 'url');
|
|
43
|
+
store.updateState('key', 'value');
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## WebSocket Events
|
|
47
|
+
|
|
48
|
+
```javascript
|
|
49
|
+
// Listen for events
|
|
50
|
+
store.listenSocket('primary', 'EventName', (data) => {
|
|
51
|
+
console.log('Event received:', data);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// Emit events
|
|
55
|
+
store.emitSocket('primary', 'event-name', data);
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Vue Directives
|
|
59
|
+
|
|
60
|
+
```html
|
|
61
|
+
<!-- Dynamic text from strings -->
|
|
62
|
+
<h1 gxp-string="welcome_title">Default</h1>
|
|
63
|
+
|
|
64
|
+
<!-- Dynamic images from assets -->
|
|
65
|
+
<img gxp-src="hero_image" src="/placeholder.jpg">
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Component Kit
|
|
69
|
+
|
|
70
|
+
Use `@gramercytech/gx-componentkit` for UI:
|
|
71
|
+
GxButton, GxCard, GxInput, GxModal, GxSpinner, GxAlert, GxBadge, GxProgress, GxTabs
|
|
72
|
+
|
|
73
|
+
## Configuration
|
|
74
|
+
|
|
75
|
+
Edit `app-manifest.json` for strings, assets, settings. Hot-reloads in dev.
|
|
76
|
+
|
|
77
|
+
## API Specs
|
|
78
|
+
|
|
79
|
+
- OpenAPI: https://api.zenith-develop.env.eventfinity.app/api-specs/openapi.json
|
|
80
|
+
- AsyncAPI: https://api.zenith-develop.env.eventfinity.app/api-specs/asyncapi.json
|