+
+
+
+
+
diff --git a/src/modules/grid/gridLayout.js b/src/modules/grid/gridLayout.js
index 7e7c04282a..dff8f1f2df 100644
--- a/src/modules/grid/gridLayout.js
+++ b/src/modules/grid/gridLayout.js
@@ -3,6 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
+import { translate as t } from '@nextcloud/l10n'
import { NODE_TYPE_TABLE, NODE_TYPE_VIEW } from '../../shared/constants.ts'
/** Number of columns of a grid page. */
@@ -43,6 +44,16 @@ export function findWidgetType(widgetTypes, type) {
return widgetTypes.find(widgetType => widgetType.type === type) ?? null
}
+/**
+ * The settings a new widget of this type starts with: every setting at its default.
+ *
+ * @param {object|null} widgetType a type from the server
+ * @return {object} the settings
+ */
+export function defaultSettings(widgetType) {
+ return Object.fromEntries(Object.entries(widgetType?.settings ?? {}).map(([name, setting]) => [name, copy(setting.default)]))
+}
+
/**
* Deep copy of a grid so edits never touch the stored page until saved.
*
@@ -146,6 +157,31 @@ export function widgetTarget(widget, nodes) {
return { type: nodeType === NODE_TYPE_VIEW ? 'view' : 'table', id: parseInt(node.node_id) }
}
+/**
+ * The tables and views of the application a data widget can show, with their titles.
+ *
+ * @param {object} nodes the nodes of the application by relation id
+ * @param {Array} tables tables known to the store
+ * @param {Array} views views known to the store
+ * @return {Array<{id: number, label: string}>} one option per node relation, by relation id
+ */
+export function applicationNodeOptions(nodes, tables, views) {
+ return Object.values(nodes ?? {}).map(node => {
+ const nodeType = parseInt(node.node_type)
+ const nodeId = parseInt(node.node_id)
+ const element = nodeType === NODE_TYPE_VIEW
+ ? views.find(view => view.id === nodeId)
+ : tables.find(table => table.id === nodeId)
+ const title = element ? (element.emoji ? element.emoji + ' ' : '') + element.title : '#' + nodeId
+ return {
+ id: parseInt(node.id),
+ label: nodeType === NODE_TYPE_VIEW
+ ? t('tables', '{title} (view)', { title }, undefined, { escape: false })
+ : title,
+ }
+ })
+}
+
/**
* The widgets of a grid as the API saves them. A saved widget keeps its id; a widget of
* a type with a source names the node relation it shows, or null.
diff --git a/src/modules/modals/AddWidget.vue b/src/modules/modals/AddWidget.vue
new file mode 100644
index 0000000000..7d17aaaca4
--- /dev/null
+++ b/src/modules/modals/AddWidget.vue
@@ -0,0 +1,227 @@
+
+
+
+