@svgrid/enterprise 2.0.4 → 2.2.1
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 +18 -6
- package/dist/cdn/svgrid-enterprise.svelte-external.js +14035 -6842
- package/dist/node/studio.js +7888 -2459
- package/package.json +9 -4
- package/src/SvGridMasterDetail.svelte +24 -3
- package/src/SvGridScheduler.svelte +4410 -0
- package/src/SvPivotDesigner.svelte +1990 -1045
- package/src/SvSchemaChart.svelte +10 -9
- package/src/ai.test.ts +522 -522
- package/src/ai.ts +202 -2
- package/src/export.ts +7 -1
- package/src/index.ts +409 -384
- package/src/install.ts +10 -0
- package/src/pivot-chart.test.ts +86 -0
- package/src/pivot-chart.ts +112 -0
- package/src/scheduler.ts +37 -0
- package/src/scheduling.test.ts +194 -0
- package/src/scheduling.ts +293 -0
- package/src/sources/filters.ts +6 -0
- package/src/studio/HANDLERS-DESIGN.md +142 -0
- package/src/studio/cli.ts +7 -2
- package/src/studio/emit-project.test.ts +1447 -13
- package/src/studio/emit-project.ts +3995 -1273
- package/src/studio/emit-schema.ts +146 -29
- package/src/studio/index.ts +320 -195
- package/src/studio/project.test.ts +370 -0
- package/src/studio/project.ts +1146 -26
- package/src/studio/sample-data.ts +4 -1
- package/src/studio/samples/ats.ts +2 -2
- package/src/studio/samples/clinic.ts +4 -2
- package/src/studio/samples/crm.ts +16 -8
- package/src/studio/samples/events.ts +4 -2
- package/src/studio/samples/fleet.ts +4 -2
- package/src/studio/samples/gym.ts +4 -2
- package/src/studio/samples/hr.ts +3 -1
- package/src/studio/samples/live-data.ts +308 -308
- package/src/studio/samples/projects.ts +2 -2
- package/src/studio/samples/restaurant.ts +4 -2
- package/src/studio/samples/samples.test.ts +13 -5
- package/src/studio/samples/shared.ts +346 -305
- package/src/studio/samples/support.ts +3 -1
- package/src/studio/scaffold.test.ts +15 -1
- package/src/studio/scaffold.ts +16 -0
- package/src/studio/themes.ts +7 -0
- package/src/studio/ui-components.ts +472 -0
- package/src/sveltekit/transport.test.ts +26 -0
- package/src/sveltekit/transport.ts +50 -5
- package/dist/designer/assets/index-Dp44bTid.js +0 -939
- package/dist/designer/assets/index-RJp6x8tw.css +0 -1
- package/dist/designer/assets/jszip.min-CjMo-QGg.js +0 -2
- package/dist/designer/index.html +0 -13
|
@@ -97,7 +97,10 @@ function isoDate(offsetDays: number, withTime: boolean): string {
|
|
|
97
97
|
const day = Math.max(1, Math.min(28, (((dayOfYear % 30) + 30) % 30) + 1))
|
|
98
98
|
const mm = String(month + 1).padStart(2, '0')
|
|
99
99
|
const dd = String(day).padStart(2, '0')
|
|
100
|
-
|
|
100
|
+
// Minutes must land in 00-59 even when offsetDays is negative (JS `%` keeps the
|
|
101
|
+
// sign, which would emit an invalid "T09:-2:00Z"). Normalise to a positive range.
|
|
102
|
+
const minute = 10 + ((((offsetDays % 40) + 40) % 40))
|
|
103
|
+
return withTime ? `${BASE_YEAR}-${mm}-${dd}T09:${String(minute).padStart(2, '0')}:00Z` : `${BASE_YEAR}-${mm}-${dd}`
|
|
101
104
|
}
|
|
102
105
|
|
|
103
106
|
// --- the generator ----------------------------------------------------------
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { EntitySchema } from '../../schema.js'
|
|
2
2
|
import type { FormatRule } from '../project.js'
|
|
3
|
-
import { screen, formScreen, boardScreen,
|
|
3
|
+
import { screen, formScreen, boardScreen, schedulerScreen, project, dashScreen, detailScreen, statusPills, pad, ids, type SampleApp } from './shared.js'
|
|
4
4
|
|
|
5
5
|
const jobs: EntitySchema = {
|
|
6
6
|
name: 'jobs',
|
|
@@ -195,7 +195,7 @@ export const ats: SampleApp = {
|
|
|
195
195
|
formScreen(candidates, { id: 'candidates', title: 'Candidates', order: 6 }, undefined, { format: candidateFormats, summaries: true, rowActions: [{ kind: 'edit' }] }, ['source']),
|
|
196
196
|
// Interview schedule: applications placed on a month calendar by their
|
|
197
197
|
// scheduled interview slot (card title resolves to the candidate name).
|
|
198
|
-
|
|
198
|
+
schedulerScreen(applications, { id: 'interviews', title: 'Interviews', order: 7 }, { startField: 'interviewAt', titleField: 'candidateId', colorField: 'stage', initialView: 'week' }),
|
|
199
199
|
],
|
|
200
200
|
})
|
|
201
201
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { EntitySchema } from '../../schema.js'
|
|
2
2
|
import type { FormatRule } from '../project.js'
|
|
3
|
-
import { screen, formScreen,
|
|
3
|
+
import { screen, formScreen, schedulerScreen, detailScreen, project, dashScreen, statusPills, pad, ids, type SampleApp } from './shared.js'
|
|
4
4
|
|
|
5
5
|
const doctors: EntitySchema = {
|
|
6
6
|
name: 'doctors',
|
|
@@ -161,7 +161,9 @@ export const clinic: SampleApp = {
|
|
|
161
161
|
{ filter: ['specialty'], span: 3 },
|
|
162
162
|
{ grid: true, format: statusPills(doctors, 'specialty'), summaries: true, span: 3 },
|
|
163
163
|
]),
|
|
164
|
-
|
|
164
|
+
// Resource scheduler: a column per doctor, appointments placed by time + tinted
|
|
165
|
+
// by status, drag-to-reschedule + a detail drawer (day view). Was a month calendar.
|
|
166
|
+
schedulerScreen(appointments, { id: 'schedule', title: 'Schedule', order: 2 }, { startField: 'scheduledAt', titleField: 'patientId', colorField: 'status', resourceField: 'doctorId', initialView: 'day' }),
|
|
165
167
|
// Patient 360: chart header (blood-type pill) with a visit-history timeline -
|
|
166
168
|
// each appointment titled by its doctor (relation resolved), colored by status.
|
|
167
169
|
detailScreen(patients, { id: 'patient-360', title: 'Patient 360', order: 3 }, {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { EntitySchema } from '../../schema.js'
|
|
2
2
|
import type { FormatRule } from '../project.js'
|
|
3
|
-
import { screen, formScreen, boardScreen, detailScreen, project, dashScreen, statusPills, pad, ids, type SampleApp } from './shared.js'
|
|
3
|
+
import { screen, formScreen, boardScreen, schedulerScreen, workspaceScreen, detailScreen, project, dashScreen, statusPills, pad, ids, type SampleApp } from './shared.js'
|
|
4
4
|
|
|
5
5
|
// A fixed sales-rep pool, shared by deals + activities so leaderboards, pivots
|
|
6
6
|
// and owner pills stay clean (padded rows cycle these instead of random names).
|
|
@@ -195,10 +195,14 @@ export const crm: SampleApp = {
|
|
|
195
195
|
// Pipeline board: deals as draggable cards in stage columns (drag a card to
|
|
196
196
|
// change its stage). The signature "real app" view.
|
|
197
197
|
boardScreen(deals, { id: 'pipeline', title: 'Pipeline', order: 1 }, { groupBy: 'stage', titleField: 'title', badgeField: 'value', subtitleField: 'owner', filter: ['owner', 'companyId'], openScreen: 'deal-360' }),
|
|
198
|
+
// Deal desk: a docking-manager console (split panes) - filter deals on the
|
|
199
|
+
// left, the pipeline grid centre, and the selected deal's record on the right.
|
|
200
|
+
// Resize the panes; click a row to load it. Showcases screen layout: 'split'.
|
|
201
|
+
workspaceScreen(deals, { id: 'deal-desk', title: 'Deal desk', order: 2 }, { filter: ['stage', 'owner'], mode: 'split' }),
|
|
198
202
|
// Deal 360: a full record page - header (title + company + stage pill), value /
|
|
199
203
|
// probability metric tiles, an Overview of deal + account fields, and an
|
|
200
204
|
// Activities timeline of the tasks logged against the deal.
|
|
201
|
-
detailScreen(deals, { id: 'deal-360', title: 'Deal 360', order:
|
|
205
|
+
detailScreen(deals, { id: 'deal-360', title: 'Deal 360', order: 3 }, {
|
|
202
206
|
titleField: 'title', subtitleField: 'companyId', statusField: 'stage',
|
|
203
207
|
metricFields: ['value', 'probability'],
|
|
204
208
|
sections: [
|
|
@@ -209,7 +213,7 @@ export const crm: SampleApp = {
|
|
|
209
213
|
}),
|
|
210
214
|
// Forecast: value KPIs, a value-over-time area trend, and a pivot of value by
|
|
211
215
|
// owner (rows) x stage (columns).
|
|
212
|
-
dashScreen(deals, { id: 'forecast', title: 'Forecast', order:
|
|
216
|
+
dashScreen(deals, { id: 'forecast', title: 'Forecast', order: 4 }, [
|
|
213
217
|
{ kpi: 'Pipeline value', measure: 'value', reduce: 'sum', format: 'currency', span: 1 },
|
|
214
218
|
{ kpi: 'Avg deal size', measure: 'value', reduce: 'avg', format: 'currency', span: 1 },
|
|
215
219
|
{ kpi: 'Largest deal', measure: 'value', reduce: 'max', format: 'currency', span: 1 },
|
|
@@ -219,7 +223,7 @@ export const crm: SampleApp = {
|
|
|
219
223
|
// Accounts dashboard: headcount KPIs (compact-formatted), an account-health
|
|
220
224
|
// gauge (avg rating 0-5), industry breakdowns, and a company grid that drills
|
|
221
225
|
// into the account's deals.
|
|
222
|
-
dashScreen(companies, { id: 'accounts', title: 'Accounts', order:
|
|
226
|
+
dashScreen(companies, { id: 'accounts', title: 'Accounts', order: 5 }, [
|
|
223
227
|
{ kpi: 'Companies', reduce: 'count', span: 1 },
|
|
224
228
|
{ kpi: 'Total headcount', measure: 'employees', reduce: 'sum', format: 'compact', span: 1 },
|
|
225
229
|
{ kpi: 'Avg headcount', measure: 'employees', reduce: 'avg', span: 1 },
|
|
@@ -231,7 +235,7 @@ export const crm: SampleApp = {
|
|
|
231
235
|
]),
|
|
232
236
|
// Activity board: task KPIs, a duration gauge, type/owner breakdowns, a filter,
|
|
233
237
|
// and a grid with type + priority pills and inline edit actions.
|
|
234
|
-
dashScreen(activities, { id: 'activities', title: 'Activities', order:
|
|
238
|
+
dashScreen(activities, { id: 'activities', title: 'Activities', order: 6 }, [
|
|
235
239
|
{ kpi: 'Activities', reduce: 'count', span: 1 },
|
|
236
240
|
{ kpi: 'Logged minutes', measure: 'durationMins', reduce: 'sum', format: 'compact', span: 1 },
|
|
237
241
|
{ kpi: 'Avg duration', measure: 'durationMins', reduce: 'avg', span: 1 },
|
|
@@ -241,9 +245,13 @@ export const crm: SampleApp = {
|
|
|
241
245
|
{ filter: ['type', 'priority', 'owner', 'completed'], span: 3 },
|
|
242
246
|
{ grid: true, format: [...statusPills(activities, 'type'), ...statusPills(activities, 'priority'), ...statusPills(activities, 'owner')], summaries: true, rowActions: [{ kind: 'edit' }], span: 3 },
|
|
243
247
|
]),
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
248
|
+
// Activity schedule: the activities grid rendered as a resource scheduler -
|
|
249
|
+
// a column per owner (rep), tasks placed by due date and tinted by type, with
|
|
250
|
+
// drag-to-reschedule + a detail drawer. Showcases the grid's scheduler view.
|
|
251
|
+
schedulerScreen(activities, { id: 'activity-cal', title: 'Schedule', order: 7 }, { startField: 'dueDate', titleField: 'subject', colorField: 'type', resourceField: 'owner', initialView: 'week' }),
|
|
252
|
+
screen(companies, 'master-detail', { id: 'companies', title: 'Companies', order: 8, child: contacts, foreignKey: 'companyId' }),
|
|
253
|
+
formScreen(contacts, { id: 'contacts', title: 'Contacts', order: 9 }, undefined, {}, ['companyId', 'tags', 'active']),
|
|
254
|
+
formScreen(deals, { id: 'deals', title: 'Deals', order: 10 }, undefined, { format: dealFormats, summaries: true, rowActions: [{ kind: 'edit' }], rowLink: { screen: 'deal-360', sourceField: 'id', targetField: 'id' } }, ['stage', 'owner', 'companyId']),
|
|
247
255
|
],
|
|
248
256
|
})
|
|
249
257
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { EntitySchema } from '../../schema.js'
|
|
2
2
|
import type { FormatRule } from '../project.js'
|
|
3
|
-
import { screen, formScreen,
|
|
3
|
+
import { screen, formScreen, schedulerScreen, project, dashScreen, detailScreen, statusPills, pad, ids, type SampleApp } from './shared.js'
|
|
4
4
|
|
|
5
5
|
const eventsEntity: EntitySchema = {
|
|
6
6
|
name: 'events',
|
|
@@ -183,7 +183,9 @@ export const events: SampleApp = {
|
|
|
183
183
|
]),
|
|
184
184
|
// Schedule: a month calendar placing every event on its start date, tinted
|
|
185
185
|
// by category. The signature "real app" scheduling view.
|
|
186
|
-
|
|
186
|
+
// Scheduler: events laid out on a week/day timeline by start time + tinted by
|
|
187
|
+
// category, with drag-to-reschedule + a detail drawer. Was a month calendar.
|
|
188
|
+
schedulerScreen(eventsEntity, { id: 'schedule', title: 'Schedule', order: 2 }, { startField: 'startAt', titleField: 'name', colorField: 'category', initialView: 'week' }),
|
|
187
189
|
// Event 360: a full record page for one event - header with status pill and
|
|
188
190
|
// capacity / price tiles, a tabbed overview, and a registrations timeline.
|
|
189
191
|
detailScreen(eventsEntity, { id: 'event-detail', title: 'Event detail', order: 3 }, {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { EntitySchema } from '../../schema.js'
|
|
2
2
|
import type { FormatRule } from '../project.js'
|
|
3
|
-
import { screen, formScreen,
|
|
3
|
+
import { screen, formScreen, schedulerScreen, detailScreen, project, dashScreen, statusPills, pad, ids, type SampleApp } from './shared.js'
|
|
4
4
|
|
|
5
5
|
const drivers: EntitySchema = {
|
|
6
6
|
name: 'drivers',
|
|
@@ -168,7 +168,9 @@ export const fleet: SampleApp = {
|
|
|
168
168
|
{ filter: ['status', 'vehicleId', 'driverId'], span: 3 },
|
|
169
169
|
{ grid: true, format: tripFormats, summaries: true, rowActions: [{ kind: 'edit' }], span: 3 },
|
|
170
170
|
]),
|
|
171
|
-
|
|
171
|
+
// Resource scheduler: a column per vehicle, trips placed by time + tinted by status,
|
|
172
|
+
// drag-to-reassign a vehicle + a detail drawer (week view). Was a month calendar.
|
|
173
|
+
schedulerScreen(trips, { id: 'dispatch', title: 'Dispatch', order: 2 }, { startField: 'startAt', titleField: 'driverId', colorField: 'status', resourceField: 'vehicleId', initialView: 'week' }),
|
|
172
174
|
// Vehicle detail: asset header (status pill) + mileage / fuel tiles with a
|
|
173
175
|
// trip-history timeline (each trip titled by its driver, colored by status).
|
|
174
176
|
detailScreen(vehicles, { id: 'vehicle-detail', title: 'Vehicle detail', order: 3 }, {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { EntitySchema } from '../../schema.js'
|
|
2
2
|
import type { FormatRule } from '../project.js'
|
|
3
|
-
import { screen, formScreen,
|
|
3
|
+
import { screen, formScreen, schedulerScreen, detailScreen, project, dashScreen, statusPills, pad, ids, type SampleApp } from './shared.js'
|
|
4
4
|
|
|
5
5
|
const classes: EntitySchema = {
|
|
6
6
|
name: 'classes',
|
|
@@ -198,7 +198,9 @@ export const gym: SampleApp = {
|
|
|
198
198
|
{ filter: ['status'], span: 3 },
|
|
199
199
|
{ grid: true, format: bookingFormats, summaries: true, rowActions: [{ kind: 'edit' }], span: 3 },
|
|
200
200
|
]),
|
|
201
|
-
|
|
201
|
+
// Resource scheduler: a column per class, bookings placed by time (who's in each
|
|
202
|
+
// class), tinted by status, with drag-to-reschedule (week view). Was a month calendar.
|
|
203
|
+
schedulerScreen(bookings, { id: 'schedule-cal', title: 'Schedule', order: 3 }, { startField: 'bookedAt', titleField: 'memberId', colorField: 'status', resourceField: 'classId', initialView: 'week' }),
|
|
202
204
|
detailScreen(members, { id: 'member-360', title: 'Member 360', order: 4 }, {
|
|
203
205
|
titleField: 'name', subtitleField: 'email', statusField: 'status',
|
|
204
206
|
metricFields: ['monthlyFee'],
|
package/src/studio/samples/hr.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { EntitySchema } from '../../schema.js'
|
|
2
2
|
import type { FormatRule } from '../project.js'
|
|
3
|
-
import { screen, formScreen, project, dashScreen, detailScreen, statusPills, pad, ids, type SampleApp } from './shared.js'
|
|
3
|
+
import { screen, formScreen, schedulerScreen, project, dashScreen, detailScreen, statusPills, pad, ids, type SampleApp } from './shared.js'
|
|
4
4
|
|
|
5
5
|
const departments: EntitySchema = {
|
|
6
6
|
name: 'departments',
|
|
@@ -187,6 +187,8 @@ export const hr: SampleApp = {
|
|
|
187
187
|
{ tree: { labelField: 'name', parentField: 'parentId' }, span: 3 },
|
|
188
188
|
{ grid: true, summaries: true, span: 3 },
|
|
189
189
|
]),
|
|
190
|
+
// Leave calendar: time-off as a per-employee resource scheduler (drag to reschedule).
|
|
191
|
+
schedulerScreen(timeOff, { id: 'leave-calendar', title: 'Leave calendar', order: 7 }, { startField: 'startDate', endField: 'endDate', titleField: 'type', colorField: 'status', resourceField: 'employeeId', initialView: 'week' }),
|
|
190
192
|
],
|
|
191
193
|
})
|
|
192
194
|
},
|