@formicoidea/labre-core 1.0.0 → 2.0.0
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/architecture/code.c4 +48 -44
- package/architecture/likec4.config.json +3 -3
- package/dist/_pkgs/affine-block-root/configs/toolbar.d.ts +1 -1
- package/dist/_pkgs/affine-block-root/configs/toolbar.js +4 -2
- package/dist/_pkgs/affine-block-surface/extensions/reading-toolbar.js +12 -12
- package/dist/_pkgs/affine-components/context-menu/menu-all.d.ts +1 -0
- package/dist/_pkgs/affine-components/context-menu/menu-renderer.d.ts +3 -1
- package/dist/_pkgs/affine-components/context-menu/menu-renderer.js +9 -1
- package/dist/_pkgs/affine-components/context-menu/menu.d.ts +7 -0
- package/dist/_pkgs/affine-components/context-menu/menu.js +5 -0
- package/dist/_pkgs/affine-components/context-menu/sub-menu.d.ts +19 -1
- package/dist/_pkgs/affine-components/context-menu/sub-menu.js +46 -7
- package/dist/_pkgs/affine-components/highlight-dropdown-menu/highlight-duotone-icon.js +8 -8
- package/dist/_pkgs/affine-components/highlight-dropdown-menu/text-duotone-icon.js +11 -11
- package/dist/_pkgs/affine-database-block/configs/slash-menu.d.ts +24 -0
- package/dist/_pkgs/affine-database-block/configs/slash-menu.js +52 -37
- package/dist/_pkgs/affine-database-block/creation-menu.d.ts +6 -0
- package/dist/_pkgs/affine-database-block/data-source.d.ts +6 -0
- package/dist/_pkgs/affine-database-block/data-source.js +16 -0
- package/dist/_pkgs/affine-database-block/database-block-styles.js +4 -3
- package/dist/_pkgs/affine-database-block/database-block.d.ts +23 -0
- package/dist/_pkgs/affine-database-block/database-block.js +129 -19
- package/dist/_pkgs/affine-database-block/database-dnd-preview-block.js +5 -1
- package/dist/_pkgs/affine-database-block/detail-panel/block-renderer.js +5 -2
- package/dist/_pkgs/affine-database-block/detail-panel/note-renderer.js +3 -2
- package/dist/_pkgs/affine-database-block/external-data-source.d.ts +17 -0
- package/dist/_pkgs/affine-database-block/external-data-source.js +54 -4
- package/dist/_pkgs/affine-database-block/index.d.ts +3 -0
- package/dist/_pkgs/affine-database-block/index.js +5 -0
- package/dist/_pkgs/affine-database-block/linked-view.d.ts +59 -0
- package/dist/_pkgs/affine-database-block/linked-view.js +131 -1
- package/dist/_pkgs/affine-database-block/properties/created-time/define.js +3 -1
- package/dist/_pkgs/affine-database-block/properties/link/cell-renderer.js +3 -2
- package/dist/_pkgs/affine-database-block/properties/link/define.js +3 -1
- package/dist/_pkgs/affine-database-block/properties/rich-text/define.js +3 -1
- package/dist/_pkgs/affine-database-block/properties/text/hosted.js +1 -0
- package/dist/_pkgs/affine-database-block/properties/title/define.js +3 -1
- package/dist/_pkgs/affine-database-block/properties/title/hosted.js +1 -0
- package/dist/_pkgs/affine-database-block/service/new-row-menu.d.ts +1 -1
- package/dist/_pkgs/affine-database-block/service/new-row-menu.js +1 -1
- package/dist/_pkgs/affine-database-block/translations.d.ts +29 -0
- package/dist/_pkgs/affine-database-block/translations.js +104 -0
- package/dist/_pkgs/affine-database-block/turn-into-source.d.ts +38 -0
- package/dist/_pkgs/affine-database-block/turn-into-source.js +187 -0
- package/dist/_pkgs/affine-database-block/view-deletion.d.ts +15 -0
- package/dist/_pkgs/affine-database-block/view-deletion.js +113 -0
- package/dist/_pkgs/affine-database-block/views/index.d.ts +7 -9
- package/dist/_pkgs/affine-database-block/views/index.js +7 -10
- package/dist/_pkgs/affine-database-engine/core/common/properties.js +7 -7
- package/dist/_pkgs/affine-database-engine/core/common/property-menu.d.ts +18 -2
- package/dist/_pkgs/affine-database-engine/core/common/property-menu.js +78 -27
- package/dist/_pkgs/affine-database-engine/core/data-source/base.d.ts +11 -0
- package/dist/_pkgs/affine-database-engine/core/data-source/base.js +3 -0
- package/dist/_pkgs/affine-database-engine/core/detail/detail.js +8 -5
- package/dist/_pkgs/affine-database-engine/core/detail/field.js +14 -7
- package/dist/_pkgs/affine-database-engine/core/filter/add-filter.js +4 -2
- package/dist/_pkgs/affine-database-engine/core/filter/filter-fn/boolean.js +7 -4
- package/dist/_pkgs/affine-database-engine/core/filter/filter-fn/create.d.ts +9 -1
- package/dist/_pkgs/affine-database-engine/core/filter/filter-fn/create.js +2 -0
- package/dist/_pkgs/affine-database-engine/core/filter/filter-fn/date.js +7 -4
- package/dist/_pkgs/affine-database-engine/core/filter/filter-fn/multi-tag.js +17 -8
- package/dist/_pkgs/affine-database-engine/core/filter/filter-fn/number.js +6 -6
- package/dist/_pkgs/affine-database-engine/core/filter/filter-fn/string.js +19 -12
- package/dist/_pkgs/affine-database-engine/core/filter/filter-fn/tag.js +9 -4
- package/dist/_pkgs/affine-database-engine/core/filter/filter-fn/unknown.js +7 -4
- package/dist/_pkgs/affine-database-engine/core/filter/literal/define.js +6 -4
- package/dist/_pkgs/affine-database-engine/core/filter/literal/matcher.d.ts +2 -1
- package/dist/_pkgs/affine-database-engine/core/filter/literal/matcher.js +3 -2
- package/dist/_pkgs/affine-database-engine/core/filter/literal/types.d.ts +4 -1
- package/dist/_pkgs/affine-database-engine/core/filter/literal/types.js +1 -1
- package/dist/_pkgs/affine-database-engine/core/group-by/define.js +11 -9
- package/dist/_pkgs/affine-database-engine/core/group-by/group-title.js +16 -6
- package/dist/_pkgs/affine-database-engine/core/group-by/locate-row.d.ts +16 -0
- package/dist/_pkgs/affine-database-engine/core/group-by/locate-row.js +32 -0
- package/dist/_pkgs/affine-database-engine/core/group-by/renderer/date-group.js +10 -3
- package/dist/_pkgs/affine-database-engine/core/group-by/setting.d.ts +2 -0
- package/dist/_pkgs/affine-database-engine/core/group-by/setting.js +40 -28
- package/dist/_pkgs/affine-database-engine/core/group-by/trait.d.ts +3 -0
- package/dist/_pkgs/affine-database-engine/core/group-by/trait.js +8 -0
- package/dist/_pkgs/affine-database-engine/core/group-by/types.d.ts +3 -1
- package/dist/_pkgs/affine-database-engine/core/group-by/types.js +1 -1
- package/dist/_pkgs/affine-database-engine/core/property/types.d.ts +7 -0
- package/dist/_pkgs/affine-database-engine/core/property/types.js +1 -1
- package/dist/_pkgs/affine-database-engine/core/sort/add-sort.js +3 -1
- package/dist/_pkgs/affine-database-engine/core/statistics/any.js +43 -21
- package/dist/_pkgs/affine-database-engine/core/statistics/checkbox.js +29 -14
- package/dist/_pkgs/affine-database-engine/core/statistics/number.js +54 -31
- package/dist/_pkgs/affine-database-engine/core/statistics/types.d.ts +8 -0
- package/dist/_pkgs/affine-database-engine/core/statistics/types.js +2 -1
- package/dist/_pkgs/affine-database-engine/core/utils/wording.d.ts +20 -1
- package/dist/_pkgs/affine-database-engine/core/utils/wording.js +24 -0
- package/dist/_pkgs/affine-database-engine/core/view-manager/property.d.ts +7 -0
- package/dist/_pkgs/affine-database-engine/core/view-manager/property.js +29 -5
- package/dist/_pkgs/affine-database-engine/core/view-manager/single-view.d.ts +14 -0
- package/dist/_pkgs/affine-database-engine/core/view-manager/single-view.js +11 -0
- package/dist/_pkgs/affine-database-engine/property-presets/checkbox/define.js +3 -1
- package/dist/_pkgs/affine-database-engine/property-presets/date/define.js +3 -1
- package/dist/_pkgs/affine-database-engine/property-presets/multi-select/define.js +3 -1
- package/dist/_pkgs/affine-database-engine/property-presets/number/define.js +3 -1
- package/dist/_pkgs/affine-database-engine/property-presets/number/utils/formats.d.ts +3 -0
- package/dist/_pkgs/affine-database-engine/property-presets/number/utils/formats.js +56 -9
- package/dist/_pkgs/affine-database-engine/property-presets/progress/define.js +3 -1
- package/dist/_pkgs/affine-database-engine/property-presets/select/define.js +3 -1
- package/dist/_pkgs/affine-database-engine/property-presets/text/define.js +3 -1
- package/dist/_pkgs/affine-database-engine/translations.d.ts +133 -5
- package/dist/_pkgs/affine-database-engine/translations.js +625 -9
- package/dist/_pkgs/affine-database-engine/view-presets/convert.js +0 -28
- package/dist/_pkgs/affine-database-engine/view-presets/effect.js +0 -2
- package/dist/_pkgs/affine-database-engine/view-presets/flat/flat-converts.js +2 -4
- package/dist/_pkgs/affine-database-engine/view-presets/flat/flat-view-ui.d.ts +57 -0
- package/dist/_pkgs/affine-database-engine/view-presets/flat/flat-view-ui.js +113 -4
- package/dist/_pkgs/affine-database-engine/view-presets/gallery/gallery-view.js +2 -1
- package/dist/_pkgs/affine-database-engine/view-presets/index.d.ts +0 -2
- package/dist/_pkgs/affine-database-engine/view-presets/index.js +0 -3
- package/dist/_pkgs/affine-database-engine/view-presets/kanban/kanban-view-manager.js +2 -0
- package/dist/_pkgs/affine-database-engine/view-presets/kanban/mobile/group.js +7 -5
- package/dist/_pkgs/affine-database-engine/view-presets/kanban/mobile/kanban-view-ui-logic.d.ts +5 -0
- package/dist/_pkgs/affine-database-engine/view-presets/kanban/mobile/kanban-view-ui-logic.js +25 -3
- package/dist/_pkgs/affine-database-engine/view-presets/kanban/mobile/menu.js +12 -6
- package/dist/_pkgs/affine-database-engine/view-presets/kanban/pc/controller/selection.d.ts +8 -0
- package/dist/_pkgs/affine-database-engine/view-presets/kanban/pc/controller/selection.js +35 -12
- package/dist/_pkgs/affine-database-engine/view-presets/kanban/pc/group.js +7 -5
- package/dist/_pkgs/affine-database-engine/view-presets/kanban/pc/header.js +5 -1
- package/dist/_pkgs/affine-database-engine/view-presets/kanban/pc/kanban-view-ui-logic.d.ts +5 -0
- package/dist/_pkgs/affine-database-engine/view-presets/kanban/pc/kanban-view-ui-logic.js +8 -4
- package/dist/_pkgs/affine-database-engine/view-presets/kanban/pc/menu.js +12 -6
- package/dist/_pkgs/affine-database-engine/view-presets/list/list-view.js +2 -1
- package/dist/_pkgs/affine-database-engine/view-presets/table/mobile/column-header.js +6 -4
- package/dist/_pkgs/affine-database-engine/view-presets/table/mobile/group.js +6 -5
- package/dist/_pkgs/affine-database-engine/view-presets/table/mobile/header.js +2 -2
- package/dist/_pkgs/affine-database-engine/view-presets/table/mobile/table-view-ui-logic.d.ts +4 -3
- package/dist/_pkgs/affine-database-engine/view-presets/table/mobile/table-view-ui-logic.js +29 -5
- package/dist/_pkgs/affine-database-engine/view-presets/table/pc/controller/clipboard.js +6 -2
- package/dist/_pkgs/affine-database-engine/view-presets/table/pc/controller/selection.js +2 -0
- package/dist/_pkgs/affine-database-engine/view-presets/table/pc/group.js +6 -5
- package/dist/_pkgs/affine-database-engine/view-presets/table/pc/header/column-header.js +11 -7
- package/dist/_pkgs/affine-database-engine/view-presets/table/pc/header/database-header-column.js +16 -12
- package/dist/_pkgs/affine-database-engine/view-presets/table/pc/header/number-format-bar.js +4 -2
- package/dist/_pkgs/affine-database-engine/view-presets/table/pc/menu.js +9 -6
- package/dist/_pkgs/affine-database-engine/view-presets/table/pc/table-view-ui-logic.d.ts +8 -1
- package/dist/_pkgs/affine-database-engine/view-presets/table/pc/table-view-ui-logic.js +29 -7
- package/dist/_pkgs/affine-database-engine/view-presets/table/pc-virtual/controller/clipboard.js +6 -2
- package/dist/_pkgs/affine-database-engine/view-presets/table/pc-virtual/controller/selection.js +2 -0
- package/dist/_pkgs/affine-database-engine/view-presets/table/pc-virtual/group/bottom/group-footer.js +5 -2
- package/dist/_pkgs/affine-database-engine/view-presets/table/pc-virtual/group/bottom/stats/column-stats-column.d.ts +1 -1
- package/dist/_pkgs/affine-database-engine/view-presets/table/pc-virtual/group/bottom/stats/column-stats-column.js +14 -6
- package/dist/_pkgs/affine-database-engine/view-presets/table/pc-virtual/group/top/group-header.js +5 -2
- package/dist/_pkgs/affine-database-engine/view-presets/table/pc-virtual/group/top/group-title.js +5 -3
- package/dist/_pkgs/affine-database-engine/view-presets/table/pc-virtual/group/top/header/column-header.js +17 -10
- package/dist/_pkgs/affine-database-engine/view-presets/table/pc-virtual/group/top/header/number-format-bar.js +4 -2
- package/dist/_pkgs/affine-database-engine/view-presets/table/pc-virtual/group/top/header/single-column-header.js +20 -14
- package/dist/_pkgs/affine-database-engine/view-presets/table/pc-virtual/row/menu.js +9 -6
- package/dist/_pkgs/affine-database-engine/view-presets/table/pc-virtual/table-view-ui-logic.d.ts +6 -1
- package/dist/_pkgs/affine-database-engine/view-presets/table/pc-virtual/table-view-ui-logic.js +30 -3
- package/dist/_pkgs/affine-database-engine/view-presets/table/stats/column-stats-column.d.ts +1 -1
- package/dist/_pkgs/affine-database-engine/view-presets/table/stats/column-stats-column.js +14 -6
- package/dist/_pkgs/affine-database-engine/view-presets/table/table-view-manager.js +2 -0
- package/dist/_pkgs/affine-database-engine/widget-presets/quick-setting-bar/filter/condition-view.d.ts +2 -0
- package/dist/_pkgs/affine-database-engine/widget-presets/quick-setting-bar/filter/condition-view.js +13 -6
- package/dist/_pkgs/affine-database-engine/widget-presets/quick-setting-bar/filter/group-panel-view.js +20 -13
- package/dist/_pkgs/affine-database-engine/widget-presets/quick-setting-bar/filter/root-panel-view.js +10 -5
- package/dist/_pkgs/affine-database-engine/widget-presets/quick-setting-bar/sort/root-panel.js +8 -5
- package/dist/_pkgs/affine-database-engine/widget-presets/tools/presets/search/search.js +2 -2
- package/dist/_pkgs/affine-database-engine/widget-presets/tools/presets/table-add-row/add-row.d.ts +6 -0
- package/dist/_pkgs/affine-database-engine/widget-presets/tools/presets/table-add-row/add-row.js +49 -4
- package/dist/_pkgs/affine-database-engine/widget-presets/tools/presets/view-options/view-settings.d.ts +3 -3
- package/dist/_pkgs/affine-database-engine/widget-presets/tools/presets/view-options/view-settings.js +3 -3
- package/dist/_pkgs/affine-database-engine/widget-presets/views-bar/views-view.js +5 -0
- package/dist/_pkgs/affine-database-view-block/configs/slash-menu.js +6 -3
- package/dist/_pkgs/affine-database-view-block/data-view-block.js +5 -4
- package/dist/_pkgs/affine-fragment-doc-title/doc-title.d.ts +3 -2
- package/dist/_pkgs/affine-fragment-doc-title/doc-title.js +3 -2
- package/dist/_pkgs/affine-shared/services/data-source-picker-service.d.ts +130 -1
- package/dist/_pkgs/affine-widget-edgeless-zoom-toolbar/index.js +26 -26
- package/dist/_pkgs/affine-widget-keyboard-toolbar/config.js +10 -21
- package/dist/_pkgs/affine-widget-keyboard-toolbar/icons.js +98 -98
- package/dist/_pkgs/affine-widget-page-dragging-area/index.js +10 -10
- package/dist/_pkgs/affine-widget-viewport-overlay/index.js +13 -13
- package/package.json +1 -1
- package/dist/_pkgs/affine-database-engine/view-presets/calendar/calendar-view-manager.d.ts +0 -70
- package/dist/_pkgs/affine-database-engine/view-presets/calendar/calendar-view-manager.js +0 -449
- package/dist/_pkgs/affine-database-engine/view-presets/calendar/define.d.ts +0 -10
- package/dist/_pkgs/affine-database-engine/view-presets/calendar/define.js +0 -29
- package/dist/_pkgs/affine-database-engine/view-presets/calendar/effect.d.ts +0 -1
- package/dist/_pkgs/affine-database-engine/view-presets/calendar/effect.js +0 -4
- package/dist/_pkgs/affine-database-engine/view-presets/calendar/index.d.ts +0 -6
- package/dist/_pkgs/affine-database-engine/view-presets/calendar/index.js +0 -6
- package/dist/_pkgs/affine-database-engine/view-presets/calendar/layout.d.ts +0 -37
- package/dist/_pkgs/affine-database-engine/view-presets/calendar/layout.js +0 -138
- package/dist/_pkgs/affine-database-engine/view-presets/calendar/pc/actions.d.ts +0 -7
- package/dist/_pkgs/affine-database-engine/view-presets/calendar/pc/actions.js +0 -64
- package/dist/_pkgs/affine-database-engine/view-presets/calendar/pc/dnd.d.ts +0 -32
- package/dist/_pkgs/affine-database-engine/view-presets/calendar/pc/dnd.js +0 -159
- package/dist/_pkgs/affine-database-engine/view-presets/calendar/pc/effect.d.ts +0 -1
- package/dist/_pkgs/affine-database-engine/view-presets/calendar/pc/effect.js +0 -7
- package/dist/_pkgs/affine-database-engine/view-presets/calendar/pc/hit-test.d.ts +0 -1
- package/dist/_pkgs/affine-database-engine/view-presets/calendar/pc/hit-test.js +0 -28
- package/dist/_pkgs/affine-database-engine/view-presets/calendar/pc/styles.d.ts +0 -1
- package/dist/_pkgs/affine-database-engine/view-presets/calendar/pc/styles.js +0 -707
- package/dist/_pkgs/affine-database-engine/view-presets/calendar/pc/view.d.ts +0 -89
- package/dist/_pkgs/affine-database-engine/view-presets/calendar/pc/view.js +0 -849
- package/dist/_pkgs/affine-database-engine/view-presets/calendar/renderer.d.ts +0 -2
- package/dist/_pkgs/affine-database-engine/view-presets/calendar/renderer.js +0 -8
- package/dist/_pkgs/affine-database-engine/view-presets/calendar/source.d.ts +0 -8
- package/dist/_pkgs/affine-database-engine/view-presets/calendar/source.js +0 -3
- package/dist/_pkgs/affine-database-engine/view-presets/calendar/types.d.ts +0 -79
- package/dist/_pkgs/affine-database-engine/view-presets/calendar/types.js +0 -1
|
@@ -7,12 +7,14 @@ import { insertDatabaseBlockCommand } from '../commands.js';
|
|
|
7
7
|
import { DatabaseCreationMenuIdentifier } from '../creation-menu.js';
|
|
8
8
|
import { createHostedDatabaseView } from '../linked-view.js';
|
|
9
9
|
import { KanbanViewTooltip, TableViewTooltip } from './tooltips.js';
|
|
10
|
+
import { DATABASE_SLASH_KANBAN_DESCRIPTION, DATABASE_SLASH_TABLE_DESCRIPTION, } from '../translations.js';
|
|
11
|
+
import { VIEW_NAME_TABLE, VIEW_NAME_KANBAN, } from '../../affine-database-engine/translations.js';
|
|
10
12
|
/**
|
|
11
13
|
* With a data-source picker the host owns database creation (ADR 0035 §5):
|
|
12
14
|
* its `createDatabase` is the only way in, and without it no entry creates
|
|
13
15
|
* one. Without a picker, a native inline database, as in 0.48.
|
|
14
16
|
*/
|
|
15
|
-
function canCreateDatabase(std) {
|
|
17
|
+
export function canCreateDatabase(std) {
|
|
16
18
|
const picker = std.getOptional(DataSourcePickerProvider);
|
|
17
19
|
return !picker || !!picker.createDatabase;
|
|
18
20
|
}
|
|
@@ -55,38 +57,45 @@ function insertNativeDatabase(std, viewType, initialRows) {
|
|
|
55
57
|
* - a picker alone (a core-only host): the host's `createDatabase` first,
|
|
56
58
|
* then a view of its first source, as in 0.61;
|
|
57
59
|
* - no picker: a native inline database with 3 rows, as in 0.48.
|
|
60
|
+
*
|
|
61
|
+
* The one creation gesture: the slash entries and the mobile keyboard
|
|
62
|
+
* toolbar's "Table view" / "Kanban view" both run it (ADR 0035 amendment of
|
|
63
|
+
* 2026-10-29), so neither inserts native rows a host's picker would not see.
|
|
58
64
|
*/
|
|
59
|
-
function
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
createHostedDatabaseView(std, picker, {
|
|
73
|
-
after,
|
|
74
|
-
viewType,
|
|
75
|
-
removeEmptyLine: true,
|
|
76
|
-
}).catch(console.error);
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
const blockId = insertNativeDatabase(std, viewType, 0);
|
|
80
|
-
if (!blockId)
|
|
65
|
+
export function createDatabaseByGesture(std, viewType) {
|
|
66
|
+
if (!canCreateDatabase(std))
|
|
67
|
+
return;
|
|
68
|
+
const picker = std.getOptional(DataSourcePickerProvider);
|
|
69
|
+
if (!picker) {
|
|
70
|
+
insertNativeDatabase(std, viewType);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const menu = std.getOptional(DatabaseCreationMenuIdentifier);
|
|
74
|
+
if (!menu) {
|
|
75
|
+
const [, { selectedModels }] = std.command.exec(getSelectedModelsCommand);
|
|
76
|
+
const after = selectedModels?.at(-1);
|
|
77
|
+
if (!after)
|
|
81
78
|
return;
|
|
82
|
-
std
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
79
|
+
createHostedDatabaseView(std, picker, {
|
|
80
|
+
after,
|
|
81
|
+
viewType,
|
|
82
|
+
removeEmptyLine: true,
|
|
83
|
+
}).catch(console.error);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
const blockId = insertNativeDatabase(std, viewType, 0);
|
|
87
|
+
if (!blockId)
|
|
88
|
+
return;
|
|
89
|
+
std.host.updateComplete
|
|
90
|
+
.then(() => {
|
|
91
|
+
const anchor = std.view.getBlock(blockId);
|
|
92
|
+
if (anchor)
|
|
93
|
+
menu.open({ std, blockId, anchor });
|
|
94
|
+
})
|
|
95
|
+
.catch(console.error);
|
|
96
|
+
}
|
|
97
|
+
function createDatabaseAction(viewType) {
|
|
98
|
+
return ({ std }) => createDatabaseByGesture(std, viewType);
|
|
90
99
|
}
|
|
91
100
|
/**
|
|
92
101
|
* The slash entries that CREATE a database, registered by the gated
|
|
@@ -97,13 +106,16 @@ export const databaseSlashMenuConfig = {
|
|
|
97
106
|
disableWhen: ({ model }) => model.flavour === 'affine:database',
|
|
98
107
|
items: [
|
|
99
108
|
{
|
|
100
|
-
name:
|
|
101
|
-
|
|
109
|
+
name: VIEW_NAME_TABLE[1],
|
|
110
|
+
nameWording: VIEW_NAME_TABLE,
|
|
111
|
+
description: DATABASE_SLASH_TABLE_DESCRIPTION[1],
|
|
112
|
+
descriptionWording: DATABASE_SLASH_TABLE_DESCRIPTION,
|
|
102
113
|
searchAlias: ['database'],
|
|
103
114
|
icon: DatabaseTableViewIcon(),
|
|
104
115
|
tooltip: {
|
|
105
116
|
figure: TableViewTooltip,
|
|
106
|
-
caption:
|
|
117
|
+
caption: VIEW_NAME_TABLE[1],
|
|
118
|
+
captionWording: VIEW_NAME_TABLE,
|
|
107
119
|
},
|
|
108
120
|
group: '7_Database@0',
|
|
109
121
|
when: ({ model, std }) => !isInsideBlockByFlavour(model.store, model, 'affine:edgeless-text') &&
|
|
@@ -111,13 +123,16 @@ export const databaseSlashMenuConfig = {
|
|
|
111
123
|
action: createDatabaseAction(viewPresets.tableViewMeta.type),
|
|
112
124
|
},
|
|
113
125
|
{
|
|
114
|
-
name:
|
|
115
|
-
|
|
126
|
+
name: VIEW_NAME_KANBAN[1],
|
|
127
|
+
nameWording: VIEW_NAME_KANBAN,
|
|
128
|
+
description: DATABASE_SLASH_KANBAN_DESCRIPTION[1],
|
|
129
|
+
descriptionWording: DATABASE_SLASH_KANBAN_DESCRIPTION,
|
|
116
130
|
searchAlias: ['database'],
|
|
117
131
|
icon: DatabaseKanbanViewIcon(),
|
|
118
132
|
tooltip: {
|
|
119
133
|
figure: KanbanViewTooltip,
|
|
120
|
-
caption:
|
|
134
|
+
caption: VIEW_NAME_KANBAN[1],
|
|
135
|
+
captionWording: VIEW_NAME_KANBAN,
|
|
121
136
|
},
|
|
122
137
|
group: '7_Database@2',
|
|
123
138
|
when: ({ model, std }) => !isInsideBlockByFlavour(model.store, model, 'affine:edgeless-text') &&
|
|
@@ -7,6 +7,12 @@ export interface DatabaseCreationRequest {
|
|
|
7
7
|
blockId: string;
|
|
8
8
|
/** The block's element, to hang the menu from. */
|
|
9
9
|
anchor: HTMLElement;
|
|
10
|
+
/**
|
|
11
|
+
* The view to connect, when the block already has a source the host no
|
|
12
|
+
* longer resolves ("Connect a source" of its empty view, ADR 0035
|
|
13
|
+
* amendment of 2026-10-29). Absent: the block's first view.
|
|
14
|
+
*/
|
|
15
|
+
viewId?: string;
|
|
10
16
|
}
|
|
11
17
|
/**
|
|
12
18
|
* What a database creation entry opens over the block it just inserted
|
|
@@ -86,5 +86,11 @@ export declare class DatabaseBlockDataSource extends HostedDataSourceBase {
|
|
|
86
86
|
* to be chosen (the creation popover, ADR 0035 amendment of 2026-10-28).
|
|
87
87
|
*/
|
|
88
88
|
export declare const databaseViewInitTemplate: (datasource: DatabaseBlockDataSource, viewType: string, std?: BlockStdScope, rows?: number) => void;
|
|
89
|
+
/**
|
|
90
|
+
* "Create Table": the selected blocks become a database's rows. Under a host
|
|
91
|
+
* that requires a source they become a source of the host's instead
|
|
92
|
+
* (`turnBlocksIntoSource`, ADR 0035 amendment of 2026-10-29), never a
|
|
93
|
+
* native database it would show read-only.
|
|
94
|
+
*/
|
|
89
95
|
export declare const convertToDatabase: (host: EditorHost, viewType: string) => void;
|
|
90
96
|
export {};
|
|
@@ -7,6 +7,7 @@ import { computed, signal } from '@preact/signals-core';
|
|
|
7
7
|
import { getIcon } from './block-icons.js';
|
|
8
8
|
import { HostedDataSourceBase } from './external-data-source.js';
|
|
9
9
|
import { databaseBlockProperties, databasePropertyConverts, } from './properties/index.js';
|
|
10
|
+
import { canTurnIntoSource, turnBlocksIntoSource } from './turn-into-source.js';
|
|
10
11
|
import { addProperty, copyCellsByProperty, deleteRows, getCell, getProperty, updateCell, updateCells, updateProperty, } from './utils/block-utils.js';
|
|
11
12
|
/**
|
|
12
13
|
* The inline blob source: rows are the block's children, cells/columns live in
|
|
@@ -405,6 +406,12 @@ export const databaseViewInitTemplate = (datasource, viewType, std, rows = 3) =>
|
|
|
405
406
|
});
|
|
406
407
|
datasource.viewManager.viewAdd(viewType, viewDefaultName(datasource.viewMetaGet(viewType), std));
|
|
407
408
|
};
|
|
409
|
+
/**
|
|
410
|
+
* "Create Table": the selected blocks become a database's rows. Under a host
|
|
411
|
+
* that requires a source they become a source of the host's instead
|
|
412
|
+
* (`turnBlocksIntoSource`, ADR 0035 amendment of 2026-10-29), never a
|
|
413
|
+
* native database it would show read-only.
|
|
414
|
+
*/
|
|
408
415
|
export const convertToDatabase = (host, viewType) => {
|
|
409
416
|
const [_, ctx] = host.std.command.exec(getSelectedModelsCommand, {
|
|
410
417
|
types: ['block', 'text'],
|
|
@@ -413,6 +420,15 @@ export const convertToDatabase = (host, viewType) => {
|
|
|
413
420
|
const firstModel = selectedModels?.[0];
|
|
414
421
|
if (!firstModel)
|
|
415
422
|
return;
|
|
423
|
+
if (canTurnIntoSource(host.std)) {
|
|
424
|
+
turnBlocksIntoSource(host.std, selectedModels, viewType)
|
|
425
|
+
.then(written => {
|
|
426
|
+
if (written)
|
|
427
|
+
host.selection.clear();
|
|
428
|
+
})
|
|
429
|
+
.catch(console.error);
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
416
432
|
host.store.captureSync();
|
|
417
433
|
const parentModel = host.store.getParent(firstModel);
|
|
418
434
|
if (!parentModel) {
|
|
@@ -50,11 +50,12 @@ export const databaseHeaderContainerStyles = css({
|
|
|
50
50
|
display: 'flex',
|
|
51
51
|
flexDirection: 'column',
|
|
52
52
|
// Drawn as the page, which scrolls sideways under a wide table: the view
|
|
53
|
-
// bar stays in view, a viewport wide
|
|
53
|
+
// bar stays in view, a viewport wide, inside the inset the full page's
|
|
54
|
+
// root sets to keep it under the centred heading (0 elsewhere).
|
|
54
55
|
'affine-database[data-standalone] &': {
|
|
55
56
|
position: 'sticky',
|
|
56
|
-
left: 'var(--affine-editor-side-padding, 24px)',
|
|
57
|
-
width: 'calc(100cqw - 2 * var(--affine-editor-side-padding, 24px))',
|
|
57
|
+
left: 'calc(var(--affine-editor-side-padding, 24px) + var(--affine-database-page-inset, 0px))',
|
|
58
|
+
width: 'calc(100cqw - 2 * var(--affine-editor-side-padding, 24px) - 2 * var(--affine-database-page-inset, 0px))',
|
|
58
59
|
},
|
|
59
60
|
});
|
|
60
61
|
export const databaseTitleRowStyles = css({
|
|
@@ -60,6 +60,29 @@ export declare class DatabaseBlockComponent extends CaptionedBlockComponent<Data
|
|
|
60
60
|
get isCommentHighlighted(): boolean;
|
|
61
61
|
get topContenteditableElement(): BlockComponent<import("../store/index.js").BlockModel<object>, import("../std/index.js").BlockService, string> | null;
|
|
62
62
|
private readonly renderSourceMissing;
|
|
63
|
+
/**
|
|
64
|
+
* A database a host that requires a source must connect first
|
|
65
|
+
* (`sourceRequirement` is `'connect'`, ADR 0035 amendment of 2026-10-29):
|
|
66
|
+
* no source and no row, or a hosted source the host no longer resolves.
|
|
67
|
+
* Drawn in place of the tools and the body: no row, no "New", no cell to
|
|
68
|
+
* type or paste into, so nothing is written. A hosted block keeps its view
|
|
69
|
+
* bar, since another of its views may still read a source. The button
|
|
70
|
+
* reopens the creation popover over the block, for the current view; a
|
|
71
|
+
* read-only document, or a host without the bundle's creation menu, gets
|
|
72
|
+
* the notice alone. Takes precedence over "Source not found" (§7).
|
|
73
|
+
*/
|
|
74
|
+
private readonly renderSourceRequired;
|
|
75
|
+
/** "Move into a database" is waiting for the host: one call at a time. */
|
|
76
|
+
private readonly moving$;
|
|
77
|
+
private readonly moveIntoSource;
|
|
78
|
+
/**
|
|
79
|
+
* Native rows under a host that requires a source (`sourceRequirement` is
|
|
80
|
+
* `'read-only'`): the rows render, locked (`locked$`), with this notice and,
|
|
81
|
+
* where the host turns content into a source (`createDatabaseFrom`) and
|
|
82
|
+
* the document is writable, "Move into a database"; a spinner while the
|
|
83
|
+
* host answers.
|
|
84
|
+
*/
|
|
85
|
+
private renderReadOnlyNotice;
|
|
63
86
|
private renderDatabaseOps;
|
|
64
87
|
connectedCallback(): void;
|
|
65
88
|
disconnectedCallback(): void;
|
|
@@ -2,13 +2,13 @@ import { CaptionedBlockComponent } from '../affine-components/caption/index.js';
|
|
|
2
2
|
import { menu, popMenu, popupTargetFromElement, } from '../affine-components/context-menu/index.js';
|
|
3
3
|
import { DropIndicator } from '../affine-components/drop-indicator/index.js';
|
|
4
4
|
import { PeekViewProvider } from '../affine-components/peek/index.js';
|
|
5
|
+
import { LoadingIcon } from '../affine-components/icons/index.js';
|
|
5
6
|
import { toast } from '../affine-components/toast/index.js';
|
|
6
7
|
import { EDGELESS_TOP_CONTENTEDITABLE_SELECTOR } from '../affine-shared/consts/index.js';
|
|
7
8
|
import { getScrollContainer } from '../affine-shared/utils/index.js';
|
|
8
|
-
import { BlockCommentManager, CommentProviderIdentifier, DocModeProvider, NotificationProvider, PropertiesPanelProvider, TelemetryProvider, TOAST_COPIED_TO_CLIPBOARD, translateKey, } from '../affine-shared/services/index.js';
|
|
9
|
+
import { BlockCommentManager, CommentProviderIdentifier, DataSourcePickerProvider, DocModeProvider, NotificationProvider, PropertiesPanelProvider, TelemetryProvider, TOAST_COPIED_TO_CLIPBOARD, translateKey, TOOLBAR_COPY, TOOLBAR_COMMENT, } from '../affine-shared/services/index.js';
|
|
9
10
|
import { getDropResult } from '../affine-widget-drag-handle/index.js';
|
|
10
11
|
import { createRecordDetail, createUniComponentFromWebComponent, DataViewRootUILogic, DataViewEventTraceKey, defineUniComponent, ExternalGroupByConfigProvider, NewRowMenuOpenerKey, PageLayoutKey, PropertiesPanelOpenerKey, renderUniLit, traceViewEvent, uniMap, ViewCreationOffKey, } from '../affine-database-engine/index.js';
|
|
11
|
-
import { CalendarExternalSourceProvider } from '../affine-database-engine/view-presets/index.js';
|
|
12
12
|
import { widgetPresets } from '../affine-database-engine/widget-presets/index.js';
|
|
13
13
|
import { Rect } from '../global/gfx/index.js';
|
|
14
14
|
import { CommentIcon, CopyIcon, DeleteIcon, MoreHorizontalIcon, } from '@blocksuite/icons/lit';
|
|
@@ -21,16 +21,19 @@ import { html, nothing } from 'lit';
|
|
|
21
21
|
import { keyed } from 'lit/directives/keyed.js';
|
|
22
22
|
import { popSideDetail } from './components/layout.js';
|
|
23
23
|
import { DatabaseConfigExtension } from './config.js';
|
|
24
|
+
import { DatabaseCreationMenuIdentifier } from './creation-menu.js';
|
|
24
25
|
import { EditorHostKey } from './context/host-context.js';
|
|
25
26
|
import { DatabaseBlockDataSource } from './data-source.js';
|
|
26
27
|
import { HostedDataSourceBase } from './external-data-source.js';
|
|
27
28
|
import { databaseBlockStyles, databaseContentStyles, databaseHeaderBarStyles, databaseHeaderContainerStyles, databaseOpsStyles, databaseSourceMissingHintStyles, databaseSourceMissingStyles, databaseTitleRowStyles, databaseTitleStyles, databaseToolbarRowStyles, databaseViewBarContainerStyles, } from './database-block-styles.js';
|
|
28
29
|
import { BlockRenderer } from './detail-panel/block-renderer.js';
|
|
29
30
|
import { NoteRenderer } from './detail-panel/note-renderer.js';
|
|
31
|
+
import { sourceRequirement } from './linked-view.js';
|
|
30
32
|
import { DatabaseSelection } from './selection.js';
|
|
31
33
|
import { isStandaloneDatabase } from './standalone-layout.js';
|
|
32
34
|
import { databaseOpenRowRequest, DatabaseDataSourceProvider, DatabaseInitialViewProvider, DatabaseNewRowMenuProvider, DatabaseOpenRowProvider, openDatabasePropertiesPanel, rowOpenedParams, } from './service/index.js';
|
|
33
|
-
import { DATABASE_NEW_RECORD_MORE, DATABASE_SOURCE_MISSING, DATABASE_SOURCE_MISSING_HINT, } from './translations.js';
|
|
35
|
+
import { DATABASE_CREATION_TITLE, DATABASE_MOVE_INTO_SOURCE, DATABASE_NEW_RECORD_MORE, DATABASE_SOURCE_MISSING, DATABASE_SOURCE_MISSING_HINT, DATABASE_SOURCE_REQUIRED, DATABASE_SOURCE_REQUIRED_HINT, DATABASE_SOURCE_REQUIRED_READ_ONLY, DATABASE_DELETE, DATABASE_TITLE_LABEL, } from './translations.js';
|
|
36
|
+
import { canTurnIntoSource, moveDatabaseRowsIntoSource, } from './turn-into-source.js';
|
|
34
37
|
import { currentViewStorage, initialViewId } from './utils/current-view.js';
|
|
35
38
|
import { getSingleDocIdFromText } from './utils/title-doc.js';
|
|
36
39
|
import { DatabaseViewCreationIdentifier } from './view-creation.js';
|
|
@@ -42,14 +45,14 @@ export class DatabaseBlockComponent extends CaptionedBlockComponent {
|
|
|
42
45
|
items: [
|
|
43
46
|
menu.input({
|
|
44
47
|
initialValue: this.model.props.title.toString(),
|
|
45
|
-
placeholder:
|
|
48
|
+
placeholder: translateKey(this.std, ...DATABASE_TITLE_LABEL),
|
|
46
49
|
onChange: text => {
|
|
47
50
|
this.model.props.title.replace(0, this.model.props.title.length, text);
|
|
48
51
|
},
|
|
49
52
|
}),
|
|
50
53
|
menu.action({
|
|
51
54
|
prefix: CommentIcon(),
|
|
52
|
-
name:
|
|
55
|
+
name: translateKey(this.std, ...TOOLBAR_COMMENT),
|
|
53
56
|
hide: () => !this.std.getOptional(CommentProviderIdentifier),
|
|
54
57
|
select: () => {
|
|
55
58
|
this.std.getOptional(CommentProviderIdentifier)?.addComment([
|
|
@@ -61,7 +64,7 @@ export class DatabaseBlockComponent extends CaptionedBlockComponent {
|
|
|
61
64
|
}),
|
|
62
65
|
menu.action({
|
|
63
66
|
prefix: CopyIcon(),
|
|
64
|
-
name:
|
|
67
|
+
name: translateKey(this.std, ...TOOLBAR_COPY),
|
|
65
68
|
select: () => {
|
|
66
69
|
const slice = Slice.fromModels(this.store, [this.model]);
|
|
67
70
|
this.std.clipboard
|
|
@@ -79,7 +82,7 @@ export class DatabaseBlockComponent extends CaptionedBlockComponent {
|
|
|
79
82
|
class: {
|
|
80
83
|
'delete-item': true,
|
|
81
84
|
},
|
|
82
|
-
name:
|
|
85
|
+
name: translateKey(this.std, ...DATABASE_DELETE),
|
|
83
86
|
select: () => {
|
|
84
87
|
this.model.children.slice().forEach(block => {
|
|
85
88
|
this.store.deleteBlock(block);
|
|
@@ -146,6 +149,7 @@ export class DatabaseBlockComponent extends CaptionedBlockComponent {
|
|
|
146
149
|
${renderUniLit(this.toolsWidget, props)}
|
|
147
150
|
</div>
|
|
148
151
|
${renderUniLit(widgetPresets.quickSettingBar, props)}
|
|
152
|
+
${this.renderReadOnlyNotice()}
|
|
149
153
|
<affine-database-values-banner
|
|
150
154
|
.dataSource="${this.dataSource}"
|
|
151
155
|
.std="${this.std}"
|
|
@@ -210,12 +214,6 @@ export class DatabaseBlockComponent extends CaptionedBlockComponent {
|
|
|
210
214
|
widgetPresets.tools.viewOptions,
|
|
211
215
|
widgetPresets.tools.tableAddRow,
|
|
212
216
|
],
|
|
213
|
-
calendar: [
|
|
214
|
-
widgetPresets.tools.filter,
|
|
215
|
-
widgetPresets.tools.search,
|
|
216
|
-
widgetPresets.tools.viewOptions,
|
|
217
|
-
widgetPresets.tools.tableAddRow,
|
|
218
|
-
],
|
|
219
217
|
gallery: [
|
|
220
218
|
widgetPresets.tools.filter,
|
|
221
219
|
widgetPresets.tools.sort,
|
|
@@ -277,6 +275,77 @@ export class DatabaseBlockComponent extends CaptionedBlockComponent {
|
|
|
277
275
|
</div>
|
|
278
276
|
</div>`;
|
|
279
277
|
};
|
|
278
|
+
/**
|
|
279
|
+
* A database a host that requires a source must connect first
|
|
280
|
+
* (`sourceRequirement` is `'connect'`, ADR 0035 amendment of 2026-10-29):
|
|
281
|
+
* no source and no row, or a hosted source the host no longer resolves.
|
|
282
|
+
* Drawn in place of the tools and the body: no row, no "New", no cell to
|
|
283
|
+
* type or paste into, so nothing is written. A hosted block keeps its view
|
|
284
|
+
* bar, since another of its views may still read a source. The button
|
|
285
|
+
* reopens the creation popover over the block, for the current view; a
|
|
286
|
+
* read-only document, or a host without the bundle's creation menu, gets
|
|
287
|
+
* the notice alone. Takes precedence over "Source not found" (§7).
|
|
288
|
+
*/
|
|
289
|
+
this.renderSourceRequired = (dataViewLogic) => {
|
|
290
|
+
const dataSource = this.dataSource;
|
|
291
|
+
const sourceMissing = dataSource instanceof HostedDataSourceBase &&
|
|
292
|
+
dataSource.sourceMissing$.value;
|
|
293
|
+
if (sourceRequirement(this.std, this.model, sourceMissing) !== 'connect') {
|
|
294
|
+
return undefined;
|
|
295
|
+
}
|
|
296
|
+
const hosted = this.model.props.externalSourceId !== undefined;
|
|
297
|
+
const creationMenu = this.std.getOptional(DatabaseCreationMenuIdentifier);
|
|
298
|
+
const connect = creationMenu && !this.store.readonly$.value
|
|
299
|
+
? () => creationMenu.open({
|
|
300
|
+
std: this.std,
|
|
301
|
+
blockId: this.blockId,
|
|
302
|
+
anchor: this,
|
|
303
|
+
viewId: dataViewLogic.view.id,
|
|
304
|
+
})
|
|
305
|
+
: undefined;
|
|
306
|
+
return html `<div class="${databaseHeaderContainerStyles}">
|
|
307
|
+
<div class="${databaseTitleRowStyles}">
|
|
308
|
+
${this.renderTitle(dataViewLogic)}
|
|
309
|
+
</div>
|
|
310
|
+
${hosted
|
|
311
|
+
? html `<div
|
|
312
|
+
class="${databaseToolbarRowStyles} ${databaseHeaderBarStyles}"
|
|
313
|
+
>
|
|
314
|
+
${this.renderViewBar({ dataViewLogic })}
|
|
315
|
+
</div>`
|
|
316
|
+
: nothing}
|
|
317
|
+
</div>
|
|
318
|
+
<div
|
|
319
|
+
class="${databaseSourceMissingStyles}"
|
|
320
|
+
data-testid="database-source-required"
|
|
321
|
+
role="status"
|
|
322
|
+
>
|
|
323
|
+
<div>${translateKey(this.std, ...DATABASE_SOURCE_REQUIRED)}</div>
|
|
324
|
+
<div class="${databaseSourceMissingHintStyles}">
|
|
325
|
+
${translateKey(this.std, ...DATABASE_SOURCE_REQUIRED_HINT)}
|
|
326
|
+
</div>
|
|
327
|
+
${connect
|
|
328
|
+
? html `<data-view-component-button
|
|
329
|
+
data-testid="database-source-required-connect"
|
|
330
|
+
hoverType="border"
|
|
331
|
+
.onClick="${connect}"
|
|
332
|
+
.text="${translateKey(this.std, ...DATABASE_CREATION_TITLE)}"
|
|
333
|
+
></data-view-component-button>`
|
|
334
|
+
: nothing}
|
|
335
|
+
</div>`;
|
|
336
|
+
};
|
|
337
|
+
/** "Move into a database" is waiting for the host: one call at a time. */
|
|
338
|
+
this.moving$ = signal(false);
|
|
339
|
+
this.moveIntoSource = () => {
|
|
340
|
+
if (this.moving$.peek())
|
|
341
|
+
return;
|
|
342
|
+
this.moving$.value = true;
|
|
343
|
+
moveDatabaseRowsIntoSource(this.std, this.model)
|
|
344
|
+
.catch(console.error)
|
|
345
|
+
.finally(() => {
|
|
346
|
+
this.moving$.value = false;
|
|
347
|
+
});
|
|
348
|
+
};
|
|
280
349
|
this.#useZeroWidth_accessor_storage = true;
|
|
281
350
|
}
|
|
282
351
|
_buildDataSource() {
|
|
@@ -303,6 +372,12 @@ export class DatabaseBlockComponent extends CaptionedBlockComponent {
|
|
|
303
372
|
},
|
|
304
373
|
});
|
|
305
374
|
}
|
|
375
|
+
// A view of a host database is deleted through the host's request
|
|
376
|
+
// (`deleteView`, ADR 0035 amendment of 2026-10-29); the data source
|
|
377
|
+
// reads the picker from its own scope, below the editor's.
|
|
378
|
+
const picker = this.std.getOptional(DataSourcePickerProvider);
|
|
379
|
+
if (picker)
|
|
380
|
+
dataSource.serviceSet(DataSourcePickerProvider, picker);
|
|
306
381
|
// `{ database: false }` takes view creation away, never the views.
|
|
307
382
|
if (!this.std.getOptional(DatabaseViewCreationIdentifier)) {
|
|
308
383
|
dataSource.serviceSet(ViewCreationOffKey, true);
|
|
@@ -312,11 +387,6 @@ export class DatabaseBlockComponent extends CaptionedBlockComponent {
|
|
|
312
387
|
.forEach(config => {
|
|
313
388
|
dataSource.serviceSet(ExternalGroupByConfigProvider(config.name), config);
|
|
314
389
|
});
|
|
315
|
-
this.std.provider
|
|
316
|
-
.getAll(CalendarExternalSourceProvider)
|
|
317
|
-
.forEach(source => {
|
|
318
|
-
dataSource.serviceSet(CalendarExternalSourceProvider(source.id), source);
|
|
319
|
-
});
|
|
320
390
|
};
|
|
321
391
|
const provider = this.std.getOptional(DatabaseDataSourceProvider);
|
|
322
392
|
const dataSource = provider && this.model.props.externalSourceId
|
|
@@ -325,6 +395,12 @@ export class DatabaseBlockComponent extends CaptionedBlockComponent {
|
|
|
325
395
|
const id = initialViewId(this.model.id, viewId => dataSource.viewManager.viewGet(viewId) != null, this.std.getOptional(DatabaseInitialViewProvider));
|
|
326
396
|
if (id)
|
|
327
397
|
dataSource.viewManager.setCurrentView(id);
|
|
398
|
+
// A native database under a host that requires a source is never edited
|
|
399
|
+
// natively, whatever its row count (`sourceRequirement`).
|
|
400
|
+
if (dataSource instanceof DatabaseBlockDataSource &&
|
|
401
|
+
sourceRequirement(this.std, this.model) !== 'none') {
|
|
402
|
+
dataSource.locked$.value = true;
|
|
403
|
+
}
|
|
328
404
|
return dataSource;
|
|
329
405
|
}
|
|
330
406
|
get dataSource() {
|
|
@@ -429,6 +505,40 @@ export class DatabaseBlockComponent extends CaptionedBlockComponent {
|
|
|
429
505
|
}
|
|
430
506
|
return this.rootComponent;
|
|
431
507
|
}
|
|
508
|
+
/**
|
|
509
|
+
* Native rows under a host that requires a source (`sourceRequirement` is
|
|
510
|
+
* `'read-only'`): the rows render, locked (`locked$`), with this notice and,
|
|
511
|
+
* where the host turns content into a source (`createDatabaseFrom`) and
|
|
512
|
+
* the document is writable, "Move into a database"; a spinner while the
|
|
513
|
+
* host answers.
|
|
514
|
+
*/
|
|
515
|
+
renderReadOnlyNotice() {
|
|
516
|
+
if (sourceRequirement(this.std, this.model) !== 'read-only') {
|
|
517
|
+
return nothing;
|
|
518
|
+
}
|
|
519
|
+
const canMove = canTurnIntoSource(this.std) && !this.store.readonly$.value;
|
|
520
|
+
const moving = this.moving$.value;
|
|
521
|
+
return html `<div
|
|
522
|
+
class="${databaseSourceMissingStyles}"
|
|
523
|
+
data-testid="database-source-required-read-only"
|
|
524
|
+
role="status"
|
|
525
|
+
>
|
|
526
|
+
<div>${translateKey(this.std, ...DATABASE_SOURCE_REQUIRED)}</div>
|
|
527
|
+
<div class="${databaseSourceMissingHintStyles}">
|
|
528
|
+
${translateKey(this.std, ...DATABASE_SOURCE_REQUIRED_READ_ONLY)}
|
|
529
|
+
</div>
|
|
530
|
+
${canMove
|
|
531
|
+
? html `<data-view-component-button
|
|
532
|
+
data-testid="database-source-required-move"
|
|
533
|
+
hoverType="border"
|
|
534
|
+
aria-busy="${moving}"
|
|
535
|
+
.icon="${moving ? LoadingIcon() : undefined}"
|
|
536
|
+
.onClick="${this.moveIntoSource}"
|
|
537
|
+
.text="${translateKey(this.std, ...DATABASE_MOVE_INTO_SOURCE)}"
|
|
538
|
+
></data-view-component-button>`
|
|
539
|
+
: nothing}
|
|
540
|
+
</div>`;
|
|
541
|
+
}
|
|
432
542
|
renderDatabaseOps() {
|
|
433
543
|
if (this.dataSource.readonly$.value) {
|
|
434
544
|
return nothing;
|
|
@@ -509,7 +619,7 @@ export class DatabaseBlockComponent extends CaptionedBlockComponent {
|
|
|
509
619
|
setSelection: this.setSelection,
|
|
510
620
|
dataSource: this.dataSource,
|
|
511
621
|
headerWidget: this.headerWidget,
|
|
512
|
-
viewPlaceholder: this.renderSourceMissing,
|
|
622
|
+
viewPlaceholder: logic => this.renderSourceRequired(logic) ?? this.renderSourceMissing(logic),
|
|
513
623
|
onDrag: this.onDrag,
|
|
514
624
|
clipboard: this.std.clipboard,
|
|
515
625
|
dnd: this.std.dnd,
|
|
@@ -2,6 +2,8 @@ import { unsafeCSSVarV2 } from '../affine-shared/theme/index.js';
|
|
|
2
2
|
import { DatabaseListViewIcon } from '@blocksuite/icons/lit';
|
|
3
3
|
import { BlockComponent } from '../std/index.js';
|
|
4
4
|
import { css, html } from 'lit';
|
|
5
|
+
import { translateKey } from '../affine-shared/services/index.js';
|
|
6
|
+
import { DATABASE_DRAG_PREVIEW } from './translations.js';
|
|
5
7
|
export class DatabaseDndPreviewBlockComponent extends BlockComponent {
|
|
6
8
|
static { this.styles = css `
|
|
7
9
|
.affine-database-preview-container {
|
|
@@ -39,7 +41,9 @@ export class DatabaseDndPreviewBlockComponent extends BlockComponent {
|
|
|
39
41
|
>
|
|
40
42
|
<div class="database-preview-content">
|
|
41
43
|
${DatabaseListViewIcon({ width: '24px', height: '24px' })}
|
|
42
|
-
<span class="text"
|
|
44
|
+
<span class="text"
|
|
45
|
+
>${translateKey(this.std, ...DATABASE_DRAG_PREVIEW)}</span
|
|
46
|
+
>
|
|
43
47
|
</div>
|
|
44
48
|
</div>`;
|
|
45
49
|
}
|
|
@@ -38,6 +38,7 @@ import { ShadowlessElement } from '../../std/index.js';
|
|
|
38
38
|
import { cssVarV2 } from '@toeverything/theme/v2';
|
|
39
39
|
import { css, html, unsafeCSS } from 'lit';
|
|
40
40
|
import { property } from 'lit/decorators.js';
|
|
41
|
+
import { DOC_UNTITLED, translateKey } from '../../affine-shared/services/index.js';
|
|
41
42
|
let BlockRenderer = (() => {
|
|
42
43
|
let _classSuper = WithDisposable(ShadowlessElement);
|
|
43
44
|
let _host_decorators;
|
|
@@ -87,8 +88,8 @@ let BlockRenderer = (() => {
|
|
|
87
88
|
line-height: 24px;
|
|
88
89
|
}
|
|
89
90
|
|
|
90
|
-
database-datasource-block-renderer.empty rich-text::before {
|
|
91
|
-
content:
|
|
91
|
+
database-datasource-block-renderer.empty[data-untitled] rich-text::before {
|
|
92
|
+
content: attr(data-untitled);
|
|
92
93
|
position: absolute;
|
|
93
94
|
color: var(--affine-text-disable-color);
|
|
94
95
|
font-size: 15px;
|
|
@@ -159,6 +160,8 @@ let BlockRenderer = (() => {
|
|
|
159
160
|
if (!model) {
|
|
160
161
|
return;
|
|
161
162
|
}
|
|
163
|
+
// Read by the empty title's placeholder (`::before`), in the host's words.
|
|
164
|
+
this.dataset.untitled = translateKey(this.host.std, ...DOC_UNTITLED);
|
|
162
165
|
return html `
|
|
163
166
|
${this.renderIcon()}
|
|
164
167
|
<rich-text
|
|
@@ -34,7 +34,7 @@ var __runInitializers = (this && this.__runInitializers) || function (thisArg, i
|
|
|
34
34
|
};
|
|
35
35
|
import { CodeBlockModel, ListBlockModel, ParagraphBlockModel, } from '../../affine-model/index.js';
|
|
36
36
|
import { REFERENCE_NODE } from '../../affine-shared/consts/index.js';
|
|
37
|
-
import { TelemetryProvider } from '../../affine-shared/services/index.js';
|
|
37
|
+
import { TelemetryProvider, translateKey } from '../../affine-shared/services/index.js';
|
|
38
38
|
import { createDefaultDoc, matchModels } from '../../affine-shared/utils/index.js';
|
|
39
39
|
import { SignalWatcher, WithDisposable } from '../../global/lit/index.js';
|
|
40
40
|
import { ShadowlessElement } from '../../std/index.js';
|
|
@@ -43,6 +43,7 @@ import { cssVarV2 } from '@toeverything/theme/v2';
|
|
|
43
43
|
import { css, html, unsafeCSS } from 'lit';
|
|
44
44
|
import { property } from 'lit/decorators.js';
|
|
45
45
|
import { isPureText } from '../utils/title-doc.js';
|
|
46
|
+
import { DATABASE_DETAIL_EMPTY_HINT } from '../translations.js';
|
|
46
47
|
let NoteRenderer = (() => {
|
|
47
48
|
let _classSuper = SignalWatcher(WithDisposable(ShadowlessElement));
|
|
48
49
|
let _rowId_decorators;
|
|
@@ -138,7 +139,7 @@ let NoteRenderer = (() => {
|
|
|
138
139
|
@click="${this.addNote}"
|
|
139
140
|
style="max-width: var(--affine-editor-width);margin: auto;cursor: pointer;color: var(--affine-text-disable-color)"
|
|
140
141
|
>
|
|
141
|
-
|
|
142
|
+
${translateKey(this.host.std, ...DATABASE_DETAIL_EMPTY_HINT)}
|
|
142
143
|
</div>
|
|
143
144
|
</div>`;
|
|
144
145
|
}
|
|
@@ -114,6 +114,23 @@ export declare abstract class HostedDataSourceBase extends DataSourceBase {
|
|
|
114
114
|
propertyDataGet(propertyId: string): Record<string, unknown>;
|
|
115
115
|
propertyDataTypeGet(propertyId: string): TypeInstance | undefined;
|
|
116
116
|
featureFlags$: ReadonlySignal<DatabaseFlags>;
|
|
117
|
+
/**
|
|
118
|
+
* Refuses every edit on a writable store: a database with no source, under
|
|
119
|
+
* a host that requires one, shows its native rows read-only (ADR 0035
|
|
120
|
+
* amendment of 2026-10-29). Every write path of the view layer reads
|
|
121
|
+
* `readonly$` (cells, paste, drag, "New", view and property menus).
|
|
122
|
+
*/
|
|
123
|
+
readonly locked$: import("@preact/signals-core").Signal<boolean>;
|
|
124
|
+
/**
|
|
125
|
+
* The host's lock on the current view's source (`sourcePolicy` of the
|
|
126
|
+
* picker, ADR 0035 amendment of 2026-10-29), asked again only when the
|
|
127
|
+
* block's database or the view's source changes; the host's signal then
|
|
128
|
+
* carries every flip to the open views. `null`: nothing locked (a native
|
|
129
|
+
* database, no picker, no `sourcePolicy`, or a host that threw).
|
|
130
|
+
*/
|
|
131
|
+
private readonly hostPolicy$;
|
|
132
|
+
readonly propertiesLocked$: ReadonlySignal<boolean>;
|
|
133
|
+
readonly rowsLocked$: ReadonlySignal<boolean>;
|
|
117
134
|
readonly$: ReadonlySignal<boolean>;
|
|
118
135
|
viewConverts: import("./index.js").ViewConvertConfig[];
|
|
119
136
|
viewMetas: ViewMeta[];
|