@conduction/nextcloud-vue 2.56.0-beta.7 → 2.56.0-beta.9
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/dist/esm/components/CnAppNav/CnAppNav.vue2.js +169 -1
- package/dist/esm/components/CnAppNav/CnAppNav.vue2.js.map +1 -1
- package/dist/esm/components/CnAppNav/CnAppNav.vue3.js.map +1 -1
- package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue2.js +88 -4
- package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue3.js +38 -25
- package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnBrandStripe/CnBrandStripe.vue2.js +21 -1
- package/dist/esm/components/CnBrandStripe/CnBrandStripe.vue2.js.map +1 -1
- package/dist/esm/components/CnBrandStripe/CnBrandStripe.vue3.js +4 -1
- package/dist/esm/components/CnBrandStripe/CnBrandStripe.vue3.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +40 -8
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js +40 -15
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js +2 -2
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js +6 -5
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
- package/dist/esm/components/CnHeaderWidget/CnHeaderWidget.vue2.js +3 -1
- package/dist/esm/components/CnHeaderWidget/CnHeaderWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnHeaderWidget/CnHeaderWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnLinkCardsPage/CnLinkCardsPage.vue.js +10 -0
- package/dist/esm/components/CnLinkCardsPage/CnLinkCardsPage.vue.js.map +1 -0
- package/dist/esm/components/CnLinkCardsPage/CnLinkCardsPage.vue2.js +316 -0
- package/dist/esm/components/CnLinkCardsPage/CnLinkCardsPage.vue2.js.map +1 -0
- package/dist/esm/components/CnLinkCardsPage/CnLinkCardsPage.vue3.js +105 -0
- package/dist/esm/components/CnLinkCardsPage/CnLinkCardsPage.vue3.js.map +1 -0
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js +53 -0
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js +22 -5
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js.map +1 -1
- package/dist/esm/components/CnPageRenderer/pageTypes.js +1 -0
- package/dist/esm/components/CnPageRenderer/pageTypes.js.map +1 -1
- package/dist/esm/components/CnReportsPage/CnReportsPage.vue2.js.map +1 -1
- package/dist/esm/components/CnReportsPage/CnReportsPage.vue3.js.map +1 -1
- package/dist/esm/components/CnStorePage/CnStorePage.vue2.js.map +1 -1
- package/dist/esm/components/CnStorePage/CnStorePage.vue3.js.map +1 -1
- package/dist/esm/components/CnWikiPage/CnWikiPage.vue2.js.map +1 -1
- package/dist/esm/components/CnWikiPage/CnWikiPage.vue3.js.map +1 -1
- package/dist/esm/index.js +6 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/l10n/en.json.js +6 -0
- package/dist/esm/l10n/en.json.js.map +1 -1
- package/dist/esm/l10n/nl.json.js +6 -0
- package/dist/esm/l10n/nl.json.js.map +1 -1
- package/dist/esm/nextcloud-vue.css +198 -9
- package/dist/esm/utils/headers.js +28 -2
- package/dist/esm/utils/headers.js.map +1 -1
- package/dist/esm/utils/validateManifestV2.compiled.js +2 -2
- package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
- package/dist/nextcloud-vue.cjs.js +9162 -8283
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +198 -9
- package/l10n/en.json +6 -0
- package/l10n/nl.json +6 -0
- package/package.json +3 -2
- package/scripts/.jsdoc-baselines.json +1 -0
- package/scripts/manifest-schema-hash.js +41 -0
- package/scripts/record-manifest-schema-hash.js +52 -0
- package/src/components/CnAppNav/CnAppNav.vue +169 -1
- package/src/components/CnBannerWidget/CnBannerWidget.vue +122 -4
- package/src/components/CnBrandStripe/CnBrandStripe.md +16 -0
- package/src/components/CnBrandStripe/CnBrandStripe.vue +58 -5
- package/src/components/CnDashboardPage/CnDashboardPage.vue +40 -8
- package/src/components/CnDataTable/CnDataTable.md +1 -1
- package/src/components/CnDataTable/CnDataTable.vue +42 -17
- package/src/components/CnDetailPage/CnDetailPage.vue +4 -1
- package/src/components/CnHeaderWidget/CnHeaderWidget.vue +3 -1
- package/src/components/CnLinkCardsPage/CnLinkCardsPage.vue +517 -0
- package/src/components/CnLinkCardsPage/index.js +4 -0
- package/src/components/CnObjectSidebar/CnFilesTab.vue +65 -0
- package/src/components/CnPageRenderer/pageTypes.js +1 -0
- package/src/components/CnReportsPage/CnReportsPage.vue +7 -0
- package/src/components/CnStorePage/CnStorePage.vue +7 -0
- package/src/components/CnWikiPage/CnWikiPage.vue +7 -0
- package/src/components/index.js +1 -0
- package/src/css/detail-page.css +10 -2
- package/src/css/table.css +1 -2
- package/src/index.js +7 -0
- package/src/public/index.js +5 -0
- package/src/schemas/app-manifest-v2.schema.json +45 -3
- package/src/types/manifest.d.ts +1 -1
- package/src/utils/headers.js +28 -2
- package/src/utils/validateManifestV2.compiled.js +2 -2
package/src/components/index.js
CHANGED
|
@@ -221,6 +221,7 @@ export { CnFlowEditorPage, CnFlowsPage } from './CnFlowsPage/index.js'
|
|
|
221
221
|
export { default as CnWidgetRefItem } from './CnWidgetRefItem/index.js'
|
|
222
222
|
export { CnReportsPage } from './CnReportsPage/index.js'
|
|
223
223
|
export { CnStorePage } from './CnStorePage/index.js'
|
|
224
|
+
export { CnLinkCardsPage } from './CnLinkCardsPage/index.js'
|
|
224
225
|
export { CnPageRenderer, defaultPageTypes } from './CnPageRenderer/index.js'
|
|
225
226
|
export { CnAppNav } from './CnAppNav/index.js'
|
|
226
227
|
export { CnAppLoading } from './CnAppLoading/index.js'
|
package/src/css/detail-page.css
CHANGED
|
@@ -73,9 +73,17 @@
|
|
|
73
73
|
font-weight: 700;
|
|
74
74
|
line-height: 1.3;
|
|
75
75
|
color: var(--color-main-text);
|
|
76
|
-
|
|
76
|
+
/* Two lines, then an ellipsis. One line cut a long case title short on a
|
|
77
|
+
page with room to spare, and the title is the one thing that says which
|
|
78
|
+
record this is. The element carries the full text as its `title`, so a
|
|
79
|
+
title cut after two lines is still reachable. `overflow-wrap` breaks a
|
|
80
|
+
word longer than the line, which nowrap used to hide. */
|
|
81
|
+
display: -webkit-box;
|
|
82
|
+
-webkit-box-orient: vertical;
|
|
83
|
+
-webkit-line-clamp: 2;
|
|
84
|
+
line-clamp: 2;
|
|
77
85
|
overflow: hidden;
|
|
78
|
-
|
|
86
|
+
overflow-wrap: anywhere;
|
|
79
87
|
}
|
|
80
88
|
|
|
81
89
|
.cn-detail-page__subtitle {
|
package/src/css/table.css
CHANGED
|
@@ -295,8 +295,7 @@
|
|
|
295
295
|
outline-offset: -2px;
|
|
296
296
|
}
|
|
297
297
|
|
|
298
|
-
/* Multi-column sort priority badge (1, 2, 3)
|
|
299
|
-
one sort key is active; a single active sort shows the arrow alone. */
|
|
298
|
+
/* Multi-column sort priority badge (1, 2, 3), rendered only when two or more rendered, sortable columns are sorted. */
|
|
300
299
|
.cn-table-sort-badge {
|
|
301
300
|
display: inline-flex;
|
|
302
301
|
align-items: center;
|
package/src/index.js
CHANGED
|
@@ -311,6 +311,13 @@ export { CnOpenBuildEditButton } from './components/index.js'
|
|
|
311
311
|
// control, and the brand stripe.
|
|
312
312
|
export { CnBrandStripe, CnSegmentedControl, CnStackedBarWidget, CnStackedBarWidgetForm, CnWeekStripWidget, CnWeekStripWidgetForm } from './components/index.js'
|
|
313
313
|
|
|
314
|
+
// Page components the page renderer mounts by `pages[].type` that were missing
|
|
315
|
+
// from this entry. A component reachable from a manifest but not importable
|
|
316
|
+
// here resolves to `undefined` in a host that mounts it by hand, and renders
|
|
317
|
+
// nothing without an error. tests/packaging/page-types-are-exported.spec.js
|
|
318
|
+
// keeps the two lists together.
|
|
319
|
+
export { CnFormPage, CnLinkCardsPage, CnMapPage, CnReportsPage, CnStorePage, CnWikiPage } from './components/index.js'
|
|
320
|
+
|
|
314
321
|
// AI Chat Companion component family
|
|
315
322
|
export {
|
|
316
323
|
CnAiAgentPicker,
|
package/src/public/index.js
CHANGED
|
@@ -40,6 +40,10 @@
|
|
|
40
40
|
* claiming purity is worth nothing; the check is in CI.
|
|
41
41
|
*/
|
|
42
42
|
|
|
43
|
+
// The brand stripe imports nothing at all, so it is public-safe as it is: a
|
|
44
|
+
// portal draws the organisation's motif under its header with the same
|
|
45
|
+
// component, and the same tokens, as a Nextcloud page (brand-motif-token).
|
|
46
|
+
import CnBrandStripe from '../components/CnBrandStripe/CnBrandStripe.vue'
|
|
43
47
|
import CnSiteCard from './components/CnSiteCard.vue'
|
|
44
48
|
import CnSiteCardGrid from './components/CnSiteCardGrid.vue'
|
|
45
49
|
import CnSiteEmptyState from './components/CnSiteEmptyState.vue'
|
|
@@ -50,6 +54,7 @@ import CnSiteSearch from './components/CnSiteSearch.vue'
|
|
|
50
54
|
import CnSiteSection from './components/CnSiteSection.vue'
|
|
51
55
|
|
|
52
56
|
export {
|
|
57
|
+
CnBrandStripe,
|
|
53
58
|
CnSiteCard,
|
|
54
59
|
CnSiteCardGrid,
|
|
55
60
|
CnSiteEmptyState,
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"$id": "https://raw.githubusercontent.com/ConductionNL/nextcloud-vue/main/src/schemas/app-manifest-v2.schema.json",
|
|
4
4
|
"title": "Conduction App Manifest v2",
|
|
5
5
|
"description": "v2 schema for the JSON-driven page and navigation manifest consumed by @conduction/nextcloud-vue. Introduces a uniform widgets[] array on every page type with a per-slot grid coordinate system, a typed actions[] discriminator, and the required $schema field for version detection. v1 manifests continue to validate against app-manifest.schema.json (unchanged).",
|
|
6
|
-
"version": "2.
|
|
6
|
+
"version": "2.43.0",
|
|
7
7
|
"type": "object",
|
|
8
8
|
"required": ["$schema", "version"],
|
|
9
9
|
"allOf": [
|
|
@@ -1328,6 +1328,29 @@
|
|
|
1328
1328
|
}
|
|
1329
1329
|
}
|
|
1330
1330
|
},
|
|
1331
|
+
"linkCard": {
|
|
1332
|
+
"type": "object",
|
|
1333
|
+
"required": ["id", "label"],
|
|
1334
|
+
"additionalProperties": false,
|
|
1335
|
+
"description": "One card on a type='links' page: a link to another page of the app, or to a URL. Same vocabulary as menuItem and navCardEntry.",
|
|
1336
|
+
"properties": {
|
|
1337
|
+
"id": { "type": "string", "minLength": 1, "description": "Unique within the page's cards." },
|
|
1338
|
+
"label": { "type": "string", "minLength": 1, "description": "i18n key / text of the card's title." },
|
|
1339
|
+
"description": { "type": "string", "description": "i18n key / one line under the title." },
|
|
1340
|
+
"icon": { "type": "string", "description": "MDI icon name (e.g. 'CashMultiple')." },
|
|
1341
|
+
"category": { "type": "string", "description": "Key in config.categories naming the group this card sits in. A card without one, or with an unknown one, renders first under no caption." },
|
|
1342
|
+
"route": { "type": "string", "minLength": 1, "description": "Route name (a pages[].id), or a router path when it starts with '/'. Resolved through the router, so it works with and without /index.php. Mutually exclusive with href." },
|
|
1343
|
+
"params": { "type": "object", "description": "Route params passed along with `route`.", "additionalProperties": { "type": ["string", "number"] } },
|
|
1344
|
+
"query": { "type": "object", "description": "Query passed along with `route`.", "additionalProperties": { "type": ["string", "number", "boolean"] } },
|
|
1345
|
+
"href": { "type": "string", "minLength": 1, "description": "External URL, opened in a new tab. Mutually exclusive with route." },
|
|
1346
|
+
"permission": { "type": "string", "description": "Permission the user must hold for the card to render. Same rule as menuItem.permission." },
|
|
1347
|
+
"visibleIf": { "$ref": "#/$defs/visibleIfCondition", "description": "Display condition, evaluated the way a menu entry's is." }
|
|
1348
|
+
},
|
|
1349
|
+
"allOf": [
|
|
1350
|
+
{ "not": { "required": ["route", "href"] } },
|
|
1351
|
+
{ "anyOf": [{ "required": ["route"] }, { "required": ["href"] }] }
|
|
1352
|
+
]
|
|
1353
|
+
},
|
|
1331
1354
|
"navCardEntry": {
|
|
1332
1355
|
"type": "object",
|
|
1333
1356
|
"required": ["id", "label"],
|
|
@@ -2858,8 +2881,8 @@
|
|
|
2858
2881
|
"type": {
|
|
2859
2882
|
"type": "string",
|
|
2860
2883
|
"enum": ["index", "detail", "dashboard", "logs", "settings", "chat", "files", "form", "map", "roadmap", "reports",
|
|
2861
|
-
"store", "search", "wiki", "flow", "flows", "flow-detail", "custom"],
|
|
2862
|
-
"description": "Page type. Closed enum of
|
|
2884
|
+
"links", "store", "search", "wiki", "flow", "flows", "flow-detail", "custom"],
|
|
2885
|
+
"description": "Page type. Closed enum of 18 supported types. 'links' mounts CnLinkCardsPage: a page of link cards grouped under captions, declared with config.categories + config.cards ($defs/linkCard). Use it for the pages a short menu leaves out; unlike 'reports' an app may have several. 'flow' opens ONE flow in the editor; the flow LIST is an ordinary 'index' with config.entitySource='flows'. 'flows' and 'flow-detail' are DEPRECATED aliases kept for migration — 'flows' predates named index sources and 'flow-detail' is the old name for 'flow'. 'roadmap' mounts CnFeaturesAndRoadmapPage (features + GitHub-issue-backed roadmap). 'search' mounts CnSearchPage (cross-schema query + facet sidebar + results list; consumers wire the actual search via @search). 'wiki' mounts CnWikiPage (manifest-declared markdown article + optional sidebar tree; MUST declare config.register + config.schema). 'flow' and the deprecated 'flow-detail' both mount CnFlowEditorPage (the shared node/edge canvas) and take config.app to scope to the owning app. A flow lives in OpenRegister's native flow store rather than a register/schema pair, so a single flow cannot be a 'detail' page — but the LIST is a plain 'index' once a named entitySource supplies it, which is why 'flows' is deprecated (ADR-110 Decision 4). 'custom' requires a _note field explaining why a standard type was not feasible."
|
|
2863
2886
|
},
|
|
2864
2887
|
"title": {
|
|
2865
2888
|
"type": "string",
|
|
@@ -3652,6 +3675,25 @@
|
|
|
3652
3675
|
"required": ["config"]
|
|
3653
3676
|
}
|
|
3654
3677
|
},
|
|
3678
|
+
{
|
|
3679
|
+
"description": "type='links' (CnLinkCardsPage) renders config.cards as link cards grouped by config.categories. It MUST declare a non-empty cards list, and every card is a $defs/linkCard, so a card that can go nowhere is refused here and not dropped in silence at render time (link-cards-page).",
|
|
3680
|
+
"if": { "properties": { "type": { "const": "links" } }, "required": ["type"] },
|
|
3681
|
+
"then": {
|
|
3682
|
+
"properties": {
|
|
3683
|
+
"config": {
|
|
3684
|
+
"type": "object",
|
|
3685
|
+
"required": ["cards"],
|
|
3686
|
+
"properties": {
|
|
3687
|
+
"description": { "type": "string" },
|
|
3688
|
+
"emptyLabel": { "type": "string" },
|
|
3689
|
+
"categories": { "type": "object", "additionalProperties": { "type": "string", "minLength": 1 } },
|
|
3690
|
+
"cards": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/linkCard" } }
|
|
3691
|
+
}
|
|
3692
|
+
}
|
|
3693
|
+
},
|
|
3694
|
+
"required": ["config"]
|
|
3695
|
+
}
|
|
3696
|
+
},
|
|
3655
3697
|
{
|
|
3656
3698
|
"description": "type='custom' requires _note documenting why decomposition into a standard page type was not feasible. Relaxed by ConductionNL/nextcloud-vue#315: when `component` matches the lib `Cn[A-Z]\\w+` pattern, the component name already documents the choice and _note is optional. When `component` is absent or non-Cn (host-app SFC), _note remains required.",
|
|
3657
3699
|
"if": {
|
package/src/types/manifest.d.ts
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
*/
|
|
28
28
|
export type TPageType =
|
|
29
29
|
| 'index' | 'detail' | 'dashboard' | 'logs' | 'settings' | 'chat'
|
|
30
|
-
| 'files' | 'form' | 'map' | 'roadmap' | 'reports' | 'store' | 'search' | 'wiki'
|
|
30
|
+
| 'files' | 'form' | 'map' | 'roadmap' | 'reports' | 'links' | 'store' | 'search' | 'wiki'
|
|
31
31
|
| 'flow'
|
|
32
32
|
/** @deprecated `flows` predates named index sources — use `index` with `config.source: 'flows'`. */
|
|
33
33
|
| 'flows'
|
package/src/utils/headers.js
CHANGED
|
@@ -130,10 +130,15 @@ export function capitalize(str) {
|
|
|
130
130
|
*
|
|
131
131
|
* Array values are serialized with PHP bracket notation (`key[]=a&key[]=b`)
|
|
132
132
|
* so the Nextcloud/OpenRegister backend parses them as an array — a plain
|
|
133
|
-
* repeated `key=a&key=b` collapses to the last value in PHP.
|
|
134
|
-
*
|
|
133
|
+
* repeated `key=a&key=b` collapses to the last value in PHP. A plain object
|
|
134
|
+
* under a filter key is a set of operators and goes out in bracket form
|
|
135
|
+
* (`{ deadline: { lt: 'x' } }` becomes `deadline[lt]=x`); a key already
|
|
136
|
+
* written that way (`'deadline[lt]'`) passes through unchanged. Reserved keys
|
|
137
|
+
* that start with `_` keep their JSON form (`_order`). Skips
|
|
135
138
|
* null/undefined/empty values.
|
|
136
139
|
*
|
|
140
|
+
* @spec openspec/changes/link-cards-page/specs/link-cards-page/spec.md#requirement-a-filter-operator-is-serialised-in-bracket-form
|
|
141
|
+
*
|
|
137
142
|
* @param {object} params Key-value pairs for query parameters
|
|
138
143
|
* @return {string} Query string including leading '?' or empty string
|
|
139
144
|
*/
|
|
@@ -159,6 +164,27 @@ export function buildQueryString(params = {}) {
|
|
|
159
164
|
queryParams.append(arrayKey, String(item))
|
|
160
165
|
}
|
|
161
166
|
}
|
|
167
|
+
} else if (typeof value === 'object' && !key.startsWith('_')) {
|
|
168
|
+
// A filter operator: `{ deadline: { lt: '2026-10-06' } }` goes out
|
|
169
|
+
// as `deadline[lt]=2026-10-06`, the form OpenRegister reads. As
|
|
170
|
+
// JSON it reached the database as the literal value and a date
|
|
171
|
+
// column answered 500. Reserved `_` keys (`_order`) keep JSON.
|
|
172
|
+
for (const [op, operand] of Object.entries(value)) {
|
|
173
|
+
if (operand === undefined || operand === null || operand === '') {
|
|
174
|
+
continue
|
|
175
|
+
}
|
|
176
|
+
if (Array.isArray(operand)) {
|
|
177
|
+
for (const item of operand) {
|
|
178
|
+
if (item !== undefined && item !== null && item !== '') {
|
|
179
|
+
queryParams.append(`${key}[${op}][]`, String(item))
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
} else if (typeof operand === 'object') {
|
|
183
|
+
queryParams.set(`${key}[${op}]`, JSON.stringify(operand))
|
|
184
|
+
} else {
|
|
185
|
+
queryParams.set(`${key}[${op}]`, String(operand))
|
|
186
|
+
}
|
|
187
|
+
}
|
|
162
188
|
} else if (typeof value === 'object') {
|
|
163
189
|
queryParams.set(key, JSON.stringify(value))
|
|
164
190
|
} else {
|