Skip to content
Draft
Show file tree
Hide file tree
Changes from 106 commits
Commits
Show all changes
108 commits
Select commit Hold shift + click to select a range
2970c39
feat(builder): add editor model, types and block catalogue
Jakob1999 Jun 26, 2026
ed91387
feat(builder): add drag-and-drop canvas and widget palette
Jakob1999 Jun 26, 2026
2228635
feat(builder): add builder plugin with preview mode and register it
Jakob1999 Jun 26, 2026
3731d31
fix(builder): harden placement and emit valid runtime view configs
Jakob1999 Jun 26, 2026
9368c45
test(builder): add unit tests for the editor model
Jakob1999 Jun 26, 2026
2e32b55
docs(builder): document the plugin and mark phase 0 completed
Jakob1999 Jun 26, 2026
8ca42b9
feat(builder): add move/resize/duplicate model transforms and grid me…
Jakob1999 Jun 26, 2026
a34a515
feat(builder): drag-to-move, resize handles and duplicate on the canvas
Jakob1999 Jun 26, 2026
212b86d
fix(builder): address review of canvas move/resize/duplicate
Jakob1999 Jun 26, 2026
60a366f
test(builder): cover move/resize/duplicate transforms and grid metrics
Jakob1999 Jun 26, 2026
27bf88b
docs(builder): document phase 1 completed
Jakob1999 Jun 26, 2026
297763f
feat(builder): add property inspector panel for selected widgets
Jakob1999 Jun 26, 2026
37fc902
fix(builder): make inspector fields runtime-faithful and crash-safe
Jakob1999 Jun 26, 2026
235d100
test(builder): cover property setters and default config seeding
Jakob1999 Jun 26, 2026
5b8a350
docs(builder): document phase 2 completed
Jakob1999 Jun 26, 2026
4877b55
feat(builder): nested sections with drill-in editing
Jakob1999 Jun 26, 2026
14111c3
feat(builder): starter templates and device-width preview
Jakob1999 Jun 26, 2026
a542e2e
fix(builder): only drill into genuine container items when resolving …
Jakob1999 Jun 26, 2026
4e20498
test(builder): cover nested-grid helpers and starter templates
Jakob1999 Jun 26, 2026
24cbf71
docs(builder): document phase 3 completed
Jakob1999 Jun 26, 2026
7d30099
feat(builder): undo/redo history with keyboard shortcuts
Jakob1999 Jun 26, 2026
7f0e155
feat(builder): toast notifications and guardrail feedback
Jakob1999 Jun 26, 2026
b1038f8
feat(builder): copy, paste and keyboard editing shortcuts
Jakob1999 Jun 26, 2026
f96e759
feat(builder): outline panel for selecting and navigating widgets
Jakob1999 Jun 26, 2026
12f9c0d
feat(builder): dirty-state indicator with autosave and unload guard
Jakob1999 Jun 26, 2026
b3ae1cc
fix(builder): keep navigation and edits valid after undo/redo
Jakob1999 Jun 26, 2026
eb4b9dc
test(builder): cover undo/redo history, insertWidgetItem and clampPath
Jakob1999 Jun 26, 2026
9b235b5
docs(builder): document phase 4 completed
Jakob1999 Jun 26, 2026
a575dd7
feat(builder): serialize nested section grids recursively
Jakob1999 Jun 29, 2026
83995d6
feat(builder): add example page entry and config blueprint
Jakob1999 Jun 29, 2026
8dfc3ae
docs(builder): document phase 5 completed
Jakob1999 Jun 29, 2026
7e6ed8b
fix(builder): make example page render reliably
Jakob1999 Jun 29, 2026
166c658
fix(builder): add uiRecipes to example page recipe link
Jakob1999 Jun 29, 2026
f2280de
fix(builder): declare example recipe folder as a package
Jakob1999 Jun 29, 2026
dc0527d
fix(builder): type itemBorder so example recipe imports
Jakob1999 Jun 29, 2026
6bcf9b3
fix(builder): stop drag from swallowing widget action clicks
Jakob1999 Jun 29, 2026
ae5420f
feat(builder): per-widget style controls (size, align, bold, color, p…
Jakob1999 Jun 29, 2026
762c1c0
feat(builder): inline text content + separate title/body styling
Jakob1999 Jun 29, 2026
3b96b72
docs(builder): add demo cover/contact/team fields so image/table/form…
Jakob1999 Jun 29, 2026
1668baa
fix(media-viewer): show placeholder instead of crashing when no file …
Jakob1999 Jun 29, 2026
389a19a
fix(builder): use relative cover image reference so import resolves
Jakob1999 Jun 29, 2026
1d142e8
feat(builder): upload images from your computer for Image widget
Jakob1999 Jun 29, 2026
158d8b0
fix(builder): store file extension as filetype so uploads preview
Jakob1999 Jun 29, 2026
31c3c94
feat(builder): upload CSV/Excel to fill Table widget
Jakob1999 Jun 29, 2026
a9350a7
feat(builder): paginated Table widget for large CSV/Excel uploads
Jakob1999 Jun 29, 2026
bbdc130
feat(builder): tighter grid with density zoom
Jakob1999 Jun 29, 2026
c29e76a
feat(builder): nestable nav sidebar for multi-page sites
Jakob1999 Jun 29, 2026
8781b1c
feat(builder): static content widgets and widget alignment controls
Jakob1999 Jun 30, 2026
c9c4d41
feat(builder): customizable full-width top navbar
Jakob1999 Jun 30, 2026
8e2087e
feat(builder): markdown table conversion helpers
Jakob1999 Jun 30, 2026
a78b5c8
feat(builder): write tables by hand or import a file
Jakob1999 Jun 30, 2026
43393e9
feat(builder): add Job widget to run and monitor jobs
Jakob1999 Jun 30, 2026
74668a4
feat(builder): numeric aggregation helpers
Jakob1999 Jun 30, 2026
103811c
feat(builder): add Metric KPI widget
Jakob1999 Jun 30, 2026
ddd70fd
feat(builder): add SVG Chart widget
Jakob1999 Jun 30, 2026
6118e84
fix(builder): clip Metric overflow
Jakob1999 Jun 30, 2026
e7e8420
refactor(builder): single-file widget registry
Jakob1999 Jul 1, 2026
1a31d52
docs(builder): add-a-widget guide + Date picker example
Jakob1999 Jul 1, 2026
19e1388
test(builder): group all tests in a tests/ folder
Jakob1999 Jul 1, 2026
9f344d6
feat(builder): surface scope-bound standard plugins as widgets
Jakob1999 Jul 1, 2026
eab7649
feat(builder): keep only authorable content widgets
Jakob1999 Jul 1, 2026
cd55dc7
docs(builder): drop references to removed data widgets
Jakob1999 Jul 1, 2026
4235767
feat(builder): add Site/Page/Navbar blueprints + schemaVersion
Jakob1999 Jul 2, 2026
89db7b7
test(builder): blueprint conformance + schemaVersion round-trip
Jakob1999 Jul 2, 2026
b93fc16
fix(builder): harden layout hydration against corrupt saved data
Jakob1999 Jul 2, 2026
faabfa0
feat(builder): add read-only site viewer mode
Jakob1999 Jul 2, 2026
35201c6
feat(builder): role-gate editing via editorRoles config
Jakob1999 Jul 2, 2026
028545e
test(builder): add component/interaction tests (RTL)
Jakob1999 Jul 2, 2026
54e525a
test(builder): add Playwright E2E smoke for the builder plugin
Jakob1999 Jul 2, 2026
d43b06b
fix(builder): make the navbar settings popover accessible
Jakob1999 Jul 2, 2026
5a113eb
feat(plugins): add grid public barrel and use it from builder
Jakob1999 Jul 2, 2026
69d13ee
feat(plugins): expose builder public API surface
Jakob1999 Jul 2, 2026
9b14d8a
docs(builder): document internal embedding & hosting
Jakob1999 Jul 2, 2026
28243cc
docs(builder): add end-user "Build & publish a website" guide
Jakob1999 Jul 3, 2026
15e0561
feat(builder): add Site directory to browse & create sites
Jakob1999 Jul 6, 2026
e30b31b
docs(builder): document the Site directory
Jakob1999 Jul 6, 2026
772abef
feat(builder): first-class site documents + directory fixes
Jakob1999 Jul 6, 2026
93c218b
feat(builder): open freshly created sites in the editor
Jakob1999 Jul 6, 2026
fd79623
feat(example): browsable Sites directory with demo websites
Jakob1999 Jul 6, 2026
42fdb34
refactor(example): seed demo websites via the DMSS API
Jakob1999 Jul 6, 2026
d109b5e
fix(builder): render saved sites without DMSS attribute resolution
Jakob1999 Jul 6, 2026
a11920c
fix(example): seed demo websites with stable ids (no duplicates on re…
Jakob1999 Jul 6, 2026
339dfdd
fix(builder): make image upload work and persist edits
Jakob1999 Jul 6, 2026
f1a8f63
feat(builder): add site publish flag and display name
Jakob1999 Jul 6, 2026
bb88ef9
feat(builder): redesign site directory cards
Jakob1999 Jul 6, 2026
4bf5e9a
feat(builder): add delete website button to directory cards
Jakob1999 Jul 6, 2026
b136825
feat(builder): replace two-step delete with a centered confirmation m…
Jakob1999 Jul 6, 2026
209d74d
refactor(builder): migrate all UI to Equinor Design System tokens
Jakob1999 Jul 6, 2026
f7a6b3a
fix(builder): delete error feedback, dialog spacing, and back navigation
Jakob1999 Jul 7, 2026
f6b6062
fix(builder): make sites with widgets deletable
Jakob1999 Jul 7, 2026
3790c00
refactor(builder): group files into a clear folder structure
Jakob1999 Jul 7, 2026
95ae82a
refactor(builder): extract SiteCard and directory styles
Jakob1999 Jul 7, 2026
e1b4fbf
refactor(builder): split BuilderPlugin and extract inline styles
Jakob1999 Jul 7, 2026
023f60d
docs(builder): update README file map for new folder structure
Jakob1999 Jul 7, 2026
b9e1be0
docs(builder): update ADDING_WIDGETS for styled-components convention
Jakob1999 Jul 7, 2026
4017a9e
feat(builder): add Live table widget for viewer-editable tabular data
Jakob1999 Jul 8, 2026
6e1a281
fix: fix live table, add, remove and edit rows and columns.
Jakob1999 Jul 8, 2026
701f458
fix: remvoe resize animation on graph
Jakob1999 Jul 8, 2026
8f34fff
fix: change text on buttons in delete modal
Jakob1999 Jul 9, 2026
175cc30
fix: update lock-file
Jakob1999 Jul 9, 2026
694615b
fix(tests): fix SiteDirectory tests failing in CI
Jakob1999 Jul 9, 2026
4ccb071
fix(e2e): reload after save in dimensional scalar 'Edit without any o…
Jakob1999 Jul 9, 2026
0f2bbd0
fix: resolve comments from Co-Pilot
Jakob1999 Jul 9, 2026
c69126a
fix: resolve comments from Copilot
Jakob1999 Jul 9, 2026
0b83cdd
fix(e2e): check for error toast instead of any alert after submit
Jakob1999 Jul 9, 2026
60212c8
fix: resolve copilot comments on PR
Jakob1999 Jul 10, 2026
b4c5729
fix: resolve copilot comments
Jakob1999 Jul 10, 2026
ecedbe3
Created outline for tablet and phone sizes
henrikaburmann Jul 13, 2026
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
38 changes: 38 additions & 0 deletions e2e/tests/plugin-builder-website.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { expect, test } from '@playwright/test'

// Smoke test for the drag-and-drop website builder plugin. Loads the seeded
// example page, verifies the editor mounts, then switches to Preview and
// verifies the published site renders without the editing chrome.
test.beforeEach(async ({ page }) => {
await page.goto(
'http://localhost:3000/view/?documentId=dmss://DemoDataSource/$builderPageExample'
)
})

test('mounts the builder editor with its toolbar and palette', async ({
page,
}) => {
await expect(page.getByText('Website builder')).toBeVisible()
// The widget palette is only present in edit mode.
await expect(page.getByText('Widgets')).toBeVisible()
// The pages sidebar is present with an add-page affordance.
await expect(page.getByRole('button', { name: 'Add page' })).toBeVisible()
})

test('switches to the read-only preview and hides the editing chrome', async ({
page,
}) => {
await expect(page.getByText('Widgets')).toBeVisible()

await page.getByRole('button', { name: 'Preview', exact: true }).click()

// Palette and page-editing affordances disappear in preview.
await expect(page.getByText('Widgets')).toBeHidden()
await expect(page.getByRole('button', { name: 'Add page' })).toBeHidden()
// The published navigation menu renders instead.
await expect(page.getByText('Menu')).toBeVisible()

// Returning to edit restores the palette.
await page.getByRole('button', { name: 'Edit', exact: true }).click()
await expect(page.getByText('Widgets')).toBeVisible()
})
6 changes: 3 additions & 3 deletions e2e/tests/plugin-form-dimensional_scalar.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ test('Dimensional scalar', async ({ page }) => {
.getByLabel('label (optional)')
.fill('Should not show as config overrides')
await page.getByRole('button', { name: 'Submit' }).click()
await expect(page.getByRole('alert')).not.toBeVisible()
await expect(page.locator('.Toastify__toast--error')).not.toBeVisible()
await page.getByRole('button', { name: 'waveForm' }).click()
await expect(page.getByText('significantWaveHeight (config)')).toBeVisible()
await expect(
Expand All @@ -87,8 +87,8 @@ test('Dimensional scalar', async ({ page }) => {
await page.getByLabel('label (optional)').fill('New Maximum')
await page.getByLabel('unit (optional)').fill('€')
await page.getByRole('button', { name: 'Submit' }).click()
await expect(page.getByRole('alert')).not.toBeVisible()
await page.getByRole('button', { name: 'waveForm' }).click()
await expect(page.locator('.Toastify__toast--error')).not.toBeVisible()
await navigate()
await expect(
page.getByTestId('maximumWaveHeight').getByRole('spinbutton')
).toHaveValue('88888')
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "Member",
"type": "dmss://system/SIMOS/Blueprint",
"attributes": [
{
"name": "type",
"type": "dmss://system/SIMOS/BlueprintAttribute",
"attributeType": "string"
},
{
"name": "name",
"type": "CORE:BlueprintAttribute",
"attributeType": "string"
},
{
"name": "role",
"type": "CORE:BlueprintAttribute",
"attributeType": "string",
"optional": true
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
"name": "Page",
"type": "dmss://system/SIMOS/Blueprint",
"attributes": [
{
"name": "type",
"type": "dmss://system/SIMOS/BlueprintAttribute",
"attributeType": "string"
},
{
"name": "name",
"type": "dmss://system/SIMOS/BlueprintAttribute",
"attributeType": "string"
},
{
"name": "title",
"type": "CORE:BlueprintAttribute",
"attributeType": "string",
"optional": true
},
{
"name": "layout",
"type": "CORE:BlueprintAttribute",
"attributeType": "object",
"optional": true
},
{
"name": "cover",
"type": "CORE:BlueprintAttribute",
"attributeType": "CORE:File",
"contained": false,
"optional": true
},
{
"name": "contact",
"type": "CORE:BlueprintAttribute",
"attributeType": "./Member",
"optional": true
},
{
"name": "team",
"type": "CORE:BlueprintAttribute",
"attributeType": "./Member",
"dimensions": "*",
"optional": true
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"_id": "builderPageExample",
"name": "BuilderPageExample",
"type": "./blueprints/Page",
"title": "My first page",
"cover": {
"type": "dmss://system/SIMOS/Reference",
"address": "../../media_viewer/assets/beauty",
"referenceType": "link"
},
"contact": {
"type": "./blueprints/Member",
"name": "Ada Lovelace",
"role": "Owner"
},
"team": [
{
"type": "./blueprints/Member",
"name": "Ada Lovelace",
"role": "Owner"
},
{
"type": "./blueprints/Member",
"name": "Alan Turing",
"role": "Engineer"
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "SiteDirectory",
"type": "dmss://system/SIMOS/Blueprint",
"description": "A landing entity whose recipe mounts the Site directory plugin: a gallery of saved websites.",
"extends": ["CORE:NamedEntity"],
"attributes": []
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "Website",
"type": "dmss://system/SIMOS/Blueprint",
"description": "A saved website built with the drag-and-drop builder. Extends the builder Site (navbar + pages) and adds a human-friendly name shown in the site directory.",
"extends": ["PLUGINS:dm-core-plugins/builder/Site"],
"attributes": [
{
"name": "name",
"type": "CORE:BlueprintAttribute",
"attributeType": "string",
"description": "Display name of the website, shown as the card title in the directory.",
"optional": true
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"_id": "siteDirectory",
"name": "SiteDirectory",
"type": "./blueprints/SiteDirectory"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"name": "example",
"type": "CORE:Package",
"isRoot": false,
"_meta_": {
"type": "CORE:Meta",
"version": "0.0.1"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
{
"type": "CORE:RecipeLink",
"_blueprintPath_": "/plugins/builder/example/blueprints/Page",
"initialUiRecipe": {
"name": "Builder",
"type": "CORE:UiRecipe",
"plugin": "@development-framework/dm-core-plugins/builder",
"config": {
"type": "PLUGINS:dm-core-plugins/builder/BuilderPluginConfig",
"mode": "edit",
"initialConfig": {
"type": "PLUGINS:dm-core-plugins/grid/GridPluginConfig",
"size": {
"type": "PLUGINS:dm-core-plugins/grid/GridSize",
"columns": 12,
"rows": 8,
"rowGap": "16px",
"columnGap": "16px"
},
"items": [
{
"type": "PLUGINS:dm-core-plugins/grid/GridItem",
"title": "Heading",
"gridArea": {
"type": "PLUGINS:dm-core-plugins/grid/GridArea",
"rowStart": 1,
"columnStart": 1,
"rowEnd": 1,
"columnEnd": 12
},
"viewConfig": {
"type": "CORE:InlineRecipeViewConfig",
"recipe": {
"name": "form",
"type": "CORE:UiRecipe",
"plugin": "@development-framework/dm-core-plugins/form"
}
}
},
{
"type": "PLUGINS:dm-core-plugins/grid/GridItem",
"title": "Section",
"gridArea": {
"type": "PLUGINS:dm-core-plugins/grid/GridArea",
"rowStart": 2,
"columnStart": 1,
"rowEnd": 6,
"columnEnd": 6
},
"viewConfig": {
"type": "CORE:InlineRecipeViewConfig",
"recipe": {
"name": "Section",
"type": "CORE:UiRecipe",
"plugin": "@development-framework/dm-core-plugins/grid",
"config": {
"type": "PLUGINS:dm-core-plugins/grid/GridPluginConfig",
"size": {
"type": "PLUGINS:dm-core-plugins/grid/GridSize",
"columns": 6,
"rows": 4,
"rowGap": "16px",
"columnGap": "16px"
},
"items": [
{
"type": "PLUGINS:dm-core-plugins/grid/GridItem",
"title": "Edit page",
"gridArea": {
"type": "PLUGINS:dm-core-plugins/grid/GridArea",
"rowStart": 1,
"columnStart": 1,
"rowEnd": 3,
"columnEnd": 6
},
"viewConfig": {
"type": "CORE:InlineRecipeViewConfig",
"recipe": {
"name": "form",
"type": "CORE:UiRecipe",
"plugin": "@development-framework/dm-core-plugins/form"
}
}
}
],
"itemBorder": {
"type": "PLUGINS:dm-core-plugins/grid/GridBorder",
"size": "1px",
"style": "solid",
"color": "#bbb",
"radius": "5px"
},
"showItemBorders": false
}
}
}
}
],
"itemBorder": {
"type": "PLUGINS:dm-core-plugins/grid/GridBorder",
"size": "1px",
"style": "solid",
"color": "#bbb",
"radius": "5px"
},
"showItemBorders": false
}
}
},
"uiRecipes": [
{
"name": "Edit",
"type": "CORE:UiRecipe",
"category": "edit",
"plugin": "@development-framework/dm-core-plugins/form"
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"type": "CORE:RecipeLink",
"_blueprintPath_": "/plugins/builder/sites/blueprints/SiteDirectory",
"initialUiRecipe": {
"name": "Directory",
"type": "CORE:UiRecipe",
"plugin": "@development-framework/dm-core-plugins/builder/directory",
"config": {
"type": "PLUGINS:dm-core-plugins/builder/SiteDirectoryConfig",
"heading": "Websites",
"entityType": "dmss://DemoDataSource/plugins/builder/sites/blueprints/Website",
"dataSources": ["Sites"],
"targetDataSource": "Sites",
"viewUrlTemplate": "/view?documentId=dmss://{dataSource}/${id}",
"newSiteUrlTemplate": "/view?documentId=dmss://{dataSource}/${id}&recipe=Edit",
"newSiteName": "New_site",
"allowCreate": true
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"name": "sites",
"type": "CORE:Package",
"isRoot": false,
"_meta_": {
"type": "CORE:Meta",
"version": "0.0.1"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"type": "CORE:RecipeLink",
"_blueprintPath_": "/plugins/builder/sites/blueprints/Website",
"initialUiRecipe": {
"name": "View",
"type": "CORE:UiRecipe",
"plugin": "@development-framework/dm-core-plugins/builder",
"config": {
"type": "PLUGINS:dm-core-plugins/builder/BuilderPluginConfig",
"readOnly": true
}
},
"uiRecipes": [
{
"name": "Edit",
"type": "CORE:UiRecipe",
"category": "edit",
"plugin": "@development-framework/dm-core-plugins/builder",
"config": {
"type": "PLUGINS:dm-core-plugins/builder/BuilderPluginConfig",
"mode": "edit",
"directoryUrl": "/view?documentId=dmss://DemoDataSource/$siteDirectory"
}
}
]
}
16 changes: 16 additions & 0 deletions example/app/data_source_templates/Sites.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "Sites",
"repositories": {
"sitesRepo": {
"type": "mongo-db",
"collection": "default",
"data_types": ["blob"],
"database": "Sites",
"host": "db",
"password": "maf",
"port": 27017,
"tls": false,
"username": "maf"
}
}
}
Loading
Loading