@conduction/nextcloud-vue 2.76.0 → 2.77.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/dist/esm/components/CnAppNav/CnAppNav.vue2.js +18 -3
- package/dist/esm/components/CnAppNav/CnAppNav.vue2.js.map +1 -1
- package/dist/esm/components/CnAppNav/CnAppNav.vue3.js +49 -3
- package/dist/esm/components/CnAppNav/CnAppNav.vue3.js.map +1 -1
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js +42 -1
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js.map +1 -1
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js +228 -203
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js.map +1 -1
- package/dist/esm/components/CnCellRenderer/CnGroupNameCell.vue.js +9 -0
- package/dist/esm/components/CnCellRenderer/CnGroupNameCell.vue.js.map +1 -0
- package/dist/esm/components/CnCellRenderer/CnGroupNameCell.vue2.js +50 -0
- package/dist/esm/components/CnCellRenderer/CnGroupNameCell.vue2.js.map +1 -0
- package/dist/esm/components/CnCellRenderer/CnGroupNameCell.vue3.js +13 -0
- package/dist/esm/components/CnCellRenderer/CnGroupNameCell.vue3.js.map +1 -0
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js +41 -4
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js +90 -51
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +16 -28
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js +12 -24
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
- package/dist/esm/components/CnFavouriteToggle/CnFavouriteToggle.vue2.js +7 -2
- package/dist/esm/components/CnFavouriteToggle/CnFavouriteToggle.vue2.js.map +1 -1
- package/dist/esm/components/CnFavouriteToggle/CnFavouriteToggle.vue3.js.map +1 -1
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js +114 -1
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js.map +1 -1
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js +115 -62
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js.map +1 -1
- package/dist/esm/components/CnFollowToggle/CnFollowToggle.vue2.js +89 -7
- package/dist/esm/components/CnFollowToggle/CnFollowToggle.vue2.js.map +1 -1
- package/dist/esm/components/CnFollowToggle/CnFollowToggle.vue3.js +62 -30
- package/dist/esm/components/CnFollowToggle/CnFollowToggle.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +98 -13
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +13 -9
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue2.js +199 -7
- package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue3.js +155 -119
- package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js +6 -0
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js +4 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js.map +1 -1
- package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js +13 -0
- package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js.map +1 -1
- package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue3.js.map +1 -1
- package/dist/esm/composables/useListView.js +4 -0
- package/dist/esm/composables/useListView.js.map +1 -1
- package/dist/esm/index.js +2 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/l10n/en.json.js +25 -1
- package/dist/esm/l10n/en.json.js.map +1 -1
- package/dist/esm/l10n/nl.json.js +25 -1
- package/dist/esm/l10n/nl.json.js.map +1 -1
- package/dist/esm/nextcloud-vue.css +288 -74
- package/dist/esm/store/plugins/interactions.js +20 -10
- package/dist/esm/store/plugins/interactions.js.map +1 -1
- package/dist/esm/store/useObjectStore.js +17 -0
- package/dist/esm/store/useObjectStore.js.map +1 -1
- package/dist/esm/utils/builtInFormatters.js +15 -7
- package/dist/esm/utils/builtInFormatters.js.map +1 -1
- package/dist/esm/utils/groupAutocomplete.js +63 -1
- package/dist/esm/utils/groupAutocomplete.js.map +1 -1
- package/dist/esm/utils/lensAvailability.js +90 -0
- package/dist/esm/utils/lensAvailability.js.map +1 -0
- package/dist/esm/utils/personalLenses.js +13 -6
- package/dist/esm/utils/personalLenses.js.map +1 -1
- package/dist/esm/utils/recordInteractions.js +31 -13
- package/dist/esm/utils/recordInteractions.js.map +1 -1
- package/dist/esm/utils/resolveFilterTokens.js +46 -3
- package/dist/esm/utils/resolveFilterTokens.js.map +1 -1
- package/dist/esm/utils/schema.js +1 -1
- package/dist/esm/utils/schema.js.map +1 -1
- package/dist/esm/utils/sentinelTokens.js +4 -4
- package/dist/esm/utils/sentinelTokens.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/esm/utils/widgetVisibility.js +46 -1
- package/dist/esm/utils/widgetVisibility.js.map +1 -1
- package/dist/nextcloud-vue.cjs.js +3873 -2674
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +288 -74
- package/l10n/en.json +25 -1
- package/l10n/nl.json +25 -1
- package/package.json +1 -1
- package/src/components/CnAppNav/CnAppNav.vue +44 -5
- package/src/components/CnCellRenderer/CnCellRenderer.vue +56 -1
- package/src/components/CnCellRenderer/CnGroupNameCell.vue +61 -0
- package/src/components/CnDataTable/CnDataTable.md +9 -0
- package/src/components/CnDataTable/CnDataTable.vue +80 -20
- package/src/components/CnDetailPage/CnDetailPage.vue +10 -27
- package/src/components/CnFavouriteToggle/CnFavouriteToggle.vue +7 -2
- package/src/components/CnFilesBrowser/CnFilesBrowser.vue +204 -5
- package/src/components/CnFollowToggle/CnFollowToggle.vue +118 -13
- package/src/components/CnIndexPage/CnIndexPage.md +36 -0
- package/src/components/CnIndexPage/CnIndexPage.vue +106 -19
- package/src/components/CnObjectDataWidget/CnObjectDataWidget.vue +226 -2
- package/src/components/CnObjectSidebar/CnFilesTab.vue +9 -0
- package/src/components/CnWidgetObjectTable/CnWidgetObjectTable.vue +13 -0
- package/src/composables/useListView.js +4 -0
- package/src/css/look-board-detail.css +40 -2
- package/src/css/table.css +82 -17
- package/src/index.js +2 -1
- package/src/schemas/app-manifest-v2.schema.json +11 -7
- package/src/store/plugins/interactions.js +20 -10
- package/src/store/useObjectStore.js +17 -0
- package/src/utils/builtInFormatters.js +15 -7
- package/src/utils/groupAutocomplete.js +75 -0
- package/src/utils/index.js +1 -1
- package/src/utils/lensAvailability.js +86 -0
- package/src/utils/personalLenses.js +13 -6
- package/src/utils/recordInteractions.js +31 -13
- package/src/utils/resolveFilterTokens.js +45 -2
- package/src/utils/schema.js +1 -1
- package/src/utils/sentinelTokens.js +4 -4
- package/src/utils/validateManifestV2.compiled.js +2 -2
- package/src/utils/widgetVisibility.js +45 -0
|
@@ -2198,9 +2198,64 @@
|
|
|
2198
2198
|
background-color: var(--color-background-hover);
|
|
2199
2199
|
}
|
|
2200
2200
|
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2201
|
+
/* The sort control: a real button that looks like the header text, the label
|
|
2202
|
+
followed by a 14px chevron 4px after it (the "Wettelijke termijn" header on
|
|
2203
|
+
the DqWooVerzoeken board). Selector scoped under the table so it outranks
|
|
2204
|
+
Nextcloud's own `button` rule, which would otherwise give it a border, a
|
|
2205
|
+
fill, a 34px min-height and a margin. */
|
|
2206
|
+
.cn-data-table th .cn-table-header__sort {
|
|
2207
|
+
display: inline-flex;
|
|
2208
|
+
align-items: center;
|
|
2209
|
+
gap: 4px;
|
|
2210
|
+
max-width: 100%;
|
|
2211
|
+
min-width: 0;
|
|
2212
|
+
min-height: 0;
|
|
2213
|
+
margin: 0;
|
|
2214
|
+
padding: 0;
|
|
2215
|
+
border: 0;
|
|
2216
|
+
border-radius: var(--border-radius, 4px);
|
|
2217
|
+
background: transparent;
|
|
2218
|
+
color: inherit;
|
|
2219
|
+
font: inherit;
|
|
2220
|
+
font-weight: inherit;
|
|
2221
|
+
text-align: start;
|
|
2222
|
+
vertical-align: middle;
|
|
2223
|
+
cursor: pointer;
|
|
2224
|
+
}
|
|
2225
|
+
|
|
2226
|
+
.cn-data-table th .cn-table-header__sort:hover,
|
|
2227
|
+
.cn-data-table th .cn-table-header__sort:focus {
|
|
2228
|
+
background: transparent;
|
|
2229
|
+
}
|
|
2230
|
+
|
|
2231
|
+
.cn-data-table th .cn-table-header__sort:focus-visible {
|
|
2232
|
+
outline: 2px solid var(--color-main-text);
|
|
2233
|
+
outline-offset: 2px;
|
|
2234
|
+
}
|
|
2235
|
+
|
|
2236
|
+
.cn-data-table th .cn-table-header__sort > :first-child {
|
|
2237
|
+
min-width: 0;
|
|
2238
|
+
overflow: hidden;
|
|
2239
|
+
text-overflow: ellipsis;
|
|
2240
|
+
}
|
|
2241
|
+
|
|
2242
|
+
/* The chevron. Unsorted columns show a pale down chevron, so every sortable
|
|
2243
|
+
column says it sorts; the sorted column shows the direction at full text
|
|
2244
|
+
colour. The direction is also in the header's `aria-sort`. */
|
|
2245
|
+
.cn-table-header__chevron {
|
|
2246
|
+
display: inline-flex;
|
|
2247
|
+
flex: none;
|
|
2248
|
+
color: var(--color-main-text);
|
|
2249
|
+
}
|
|
2250
|
+
|
|
2251
|
+
.cn-table-header__chevron--idle {
|
|
2252
|
+
color: var(--color-text-maxcontrast);
|
|
2253
|
+
opacity: 0.5;
|
|
2254
|
+
}
|
|
2255
|
+
|
|
2256
|
+
.cn-data-table th.cn-table-header--sortable:hover .cn-table-header__chevron--idle,
|
|
2257
|
+
.cn-data-table th .cn-table-header__sort:focus-visible .cn-table-header__chevron--idle {
|
|
2258
|
+
opacity: 1;
|
|
2204
2259
|
}
|
|
2205
2260
|
|
|
2206
2261
|
/* A column carrying a `description` gets a dotted underline — the long-standing
|
|
@@ -2216,15 +2271,12 @@
|
|
|
2216
2271
|
cursor: help;
|
|
2217
2272
|
}
|
|
2218
2273
|
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
16px icon; the filled icon plus the primary colour marks an active filter,
|
|
2226
|
-
so the state never rests on colour alone. */
|
|
2227
|
-
.cn-table-header__filter {
|
|
2274
|
+
/* Header filter button (CnDataTable `filterable`): a 14px funnel directly
|
|
2275
|
+
after the sort chevron, in a 24px hit area. Muted with no filter set; with
|
|
2276
|
+
a filter set it takes the dark primary and a dot, so the state never rests
|
|
2277
|
+
on colour alone. */
|
|
2278
|
+
.cn-data-table th .cn-table-header__filter {
|
|
2279
|
+
position: relative;
|
|
2228
2280
|
display: inline-flex;
|
|
2229
2281
|
align-items: center;
|
|
2230
2282
|
justify-content: center;
|
|
@@ -2232,7 +2284,7 @@
|
|
|
2232
2284
|
min-width: 24px;
|
|
2233
2285
|
height: 24px;
|
|
2234
2286
|
min-height: 24px;
|
|
2235
|
-
margin: 0 0 0
|
|
2287
|
+
margin: 0 0 0 2px;
|
|
2236
2288
|
padding: 0;
|
|
2237
2289
|
border: none;
|
|
2238
2290
|
border-radius: var(--border-radius, 4px);
|
|
@@ -2242,18 +2294,31 @@
|
|
|
2242
2294
|
cursor: pointer;
|
|
2243
2295
|
}
|
|
2244
2296
|
|
|
2245
|
-
.cn-table-header__filter:hover {
|
|
2297
|
+
.cn-data-table th .cn-table-header__filter:hover {
|
|
2246
2298
|
background-color: var(--color-background-hover);
|
|
2247
2299
|
color: var(--color-main-text);
|
|
2248
2300
|
}
|
|
2249
2301
|
|
|
2250
|
-
.cn-table-header__filter:focus-visible {
|
|
2302
|
+
.cn-data-table th .cn-table-header__filter:focus-visible {
|
|
2251
2303
|
outline: 2px solid var(--color-main-text);
|
|
2252
2304
|
outline-offset: 0;
|
|
2253
2305
|
}
|
|
2254
2306
|
|
|
2255
|
-
.cn-table-header__filter--active
|
|
2256
|
-
|
|
2307
|
+
.cn-data-table th .cn-table-header__filter--active,
|
|
2308
|
+
.cn-data-table th .cn-table-header__filter--active:hover {
|
|
2309
|
+
color: var(--color-primary-element-light-text, var(--color-primary-element));
|
|
2310
|
+
}
|
|
2311
|
+
|
|
2312
|
+
/* The active-filter dot, on the funnel's top right. */
|
|
2313
|
+
.cn-table-header__filter-dot {
|
|
2314
|
+
position: absolute;
|
|
2315
|
+
inset-block-start: 3px;
|
|
2316
|
+
inset-inline-end: 3px;
|
|
2317
|
+
width: 6px;
|
|
2318
|
+
height: 6px;
|
|
2319
|
+
border-radius: 50%;
|
|
2320
|
+
background-color: var(--color-primary-element);
|
|
2321
|
+
pointer-events: none;
|
|
2257
2322
|
}
|
|
2258
2323
|
|
|
2259
2324
|
/* Active header filters above the table, one removable chip each. */
|
|
@@ -5503,12 +5568,26 @@ a.cn-kpi-card--stacked:focus-visible {
|
|
|
5503
5568
|
|
|
5504
5569
|
/* ---- Folder tabs ------------------------------------------------------- */
|
|
5505
5570
|
|
|
5571
|
+
/* The strip draws no line of its own (design-system pull request 147). The card under it
|
|
5572
|
+
carries its full border, top included, so the top-right corner is the
|
|
5573
|
+
card's own rounded corner instead of a strip rule running straight past it.
|
|
5574
|
+
The open tab overlaps that top border by 1px (the nav's -1px margin) and
|
|
5575
|
+
paints over it, so it flows into the card as a folder tab. */
|
|
5506
5576
|
.cn-look-board .cn-tabs--board .cn-tabs__bar {
|
|
5507
|
-
border-bottom:
|
|
5577
|
+
border-bottom: none;
|
|
5508
5578
|
gap: 4px;
|
|
5579
|
+
position: relative;
|
|
5509
5580
|
}
|
|
5510
5581
|
|
|
5582
|
+
.cn-look-board .cn-tabs.cn-tabs--board .cn-tabs__bar::after {
|
|
5583
|
+
content: none;
|
|
5584
|
+
}
|
|
5585
|
+
|
|
5586
|
+
/* Tabs sit on the card's top edge; only the open tab reaches 1px further
|
|
5587
|
+
down (min-height 35px below), over the card's top border. Top-aligned so
|
|
5588
|
+
the inactive tabs do not stretch to the open tab's height. */
|
|
5511
5589
|
.cn-look-board .cn-tabs--board .cn-tabs__nav {
|
|
5590
|
+
align-items: flex-start;
|
|
5512
5591
|
gap: 4px;
|
|
5513
5592
|
}
|
|
5514
5593
|
|
|
@@ -5529,7 +5608,11 @@ a.cn-kpi-card--stacked:focus-visible {
|
|
|
5529
5608
|
border-bottom: 1px solid var(--color-main-background);
|
|
5530
5609
|
border-top: 1px solid var(--color-border-dark);
|
|
5531
5610
|
font-weight: 700;
|
|
5611
|
+
min-height: 35px;
|
|
5612
|
+
padding-bottom: 9px;
|
|
5532
5613
|
padding-top: 8px;
|
|
5614
|
+
position: relative;
|
|
5615
|
+
z-index: 1;
|
|
5533
5616
|
}
|
|
5534
5617
|
|
|
5535
5618
|
/* The count: a grey, borderless 20px badge 8px after the label. */
|
|
@@ -5566,10 +5649,30 @@ a.cn-kpi-card--stacked:focus-visible {
|
|
|
5566
5649
|
.cn-look-board .cn-tabs--board .cn-tabs__content > .cn-tab > :first-child .cn-widget-wrapper,
|
|
5567
5650
|
.cn-look-board .cn-tabs--board .cn-tabs__content > .cn-tab > .cn-widget-wrapper,
|
|
5568
5651
|
.cn-look-board .cn-tabs--board .cn-tabs__content > .cn-tab > .cn-detail-card {
|
|
5569
|
-
border-top:
|
|
5652
|
+
border-top: 1px solid var(--color-border);
|
|
5653
|
+
border-radius: 0 12px 12px 12px;
|
|
5654
|
+
}
|
|
5655
|
+
|
|
5656
|
+
/* A CnTabsWidget panel is the card itself: the same full border, so it joins
|
|
5657
|
+
the open tab the same way. The top-left stays square under the first tab. */
|
|
5658
|
+
.cn-look-board .cn-tabs--board.cn-tabs-widget__tabs .cn-tabs__content {
|
|
5659
|
+
border: 1px solid var(--color-border);
|
|
5570
5660
|
border-radius: 0 12px 12px 12px;
|
|
5571
5661
|
}
|
|
5572
5662
|
|
|
5663
|
+
/* A panel of CnTabsWidget is the content block itself: the open tab flows
|
|
5664
|
+
straight into it. The widget in the panel renders chromeless, but the board
|
|
5665
|
+
card rule below (and the first-card rule above) used to give its wrapper a
|
|
5666
|
+
border and a 12px radius again, so a second card sat inside the panel. Its
|
|
5667
|
+
left edge ran down from the open tab and its rounded top-right drew a line
|
|
5668
|
+
across the top right of the content block, where DqZaak shows one sheet.
|
|
5669
|
+
Same specificity as the first-card rule and later, so it wins on order. */
|
|
5670
|
+
.cn-look-board .cn-tabs--board.cn-tabs-widget__tabs .cn-tabs__content .cn-widget-wrapper.cn-widget-wrapper--chromeless {
|
|
5671
|
+
background: transparent;
|
|
5672
|
+
border: 0;
|
|
5673
|
+
border-radius: 0;
|
|
5674
|
+
}
|
|
5675
|
+
|
|
5573
5676
|
/* ---- Body cards and side cards ----------------------------------------- */
|
|
5574
5677
|
|
|
5575
5678
|
.cn-look-board .cn-detail-page .cn-widget-wrapper,
|
|
@@ -9356,9 +9459,64 @@ svg.leaflet-image-layer.leaflet-interactive path {
|
|
|
9356
9459
|
background-color: var(--color-background-hover);
|
|
9357
9460
|
}
|
|
9358
9461
|
|
|
9359
|
-
|
|
9360
|
-
|
|
9361
|
-
|
|
9462
|
+
/* The sort control: a real button that looks like the header text, the label
|
|
9463
|
+
followed by a 14px chevron 4px after it (the "Wettelijke termijn" header on
|
|
9464
|
+
the DqWooVerzoeken board). Selector scoped under the table so it outranks
|
|
9465
|
+
Nextcloud's own `button` rule, which would otherwise give it a border, a
|
|
9466
|
+
fill, a 34px min-height and a margin. */
|
|
9467
|
+
.cn-data-table th .cn-table-header__sort {
|
|
9468
|
+
display: inline-flex;
|
|
9469
|
+
align-items: center;
|
|
9470
|
+
gap: 4px;
|
|
9471
|
+
max-width: 100%;
|
|
9472
|
+
min-width: 0;
|
|
9473
|
+
min-height: 0;
|
|
9474
|
+
margin: 0;
|
|
9475
|
+
padding: 0;
|
|
9476
|
+
border: 0;
|
|
9477
|
+
border-radius: var(--border-radius, 4px);
|
|
9478
|
+
background: transparent;
|
|
9479
|
+
color: inherit;
|
|
9480
|
+
font: inherit;
|
|
9481
|
+
font-weight: inherit;
|
|
9482
|
+
text-align: start;
|
|
9483
|
+
vertical-align: middle;
|
|
9484
|
+
cursor: pointer;
|
|
9485
|
+
}
|
|
9486
|
+
|
|
9487
|
+
.cn-data-table th .cn-table-header__sort:hover,
|
|
9488
|
+
.cn-data-table th .cn-table-header__sort:focus {
|
|
9489
|
+
background: transparent;
|
|
9490
|
+
}
|
|
9491
|
+
|
|
9492
|
+
.cn-data-table th .cn-table-header__sort:focus-visible {
|
|
9493
|
+
outline: 2px solid var(--color-main-text);
|
|
9494
|
+
outline-offset: 2px;
|
|
9495
|
+
}
|
|
9496
|
+
|
|
9497
|
+
.cn-data-table th .cn-table-header__sort > :first-child {
|
|
9498
|
+
min-width: 0;
|
|
9499
|
+
overflow: hidden;
|
|
9500
|
+
text-overflow: ellipsis;
|
|
9501
|
+
}
|
|
9502
|
+
|
|
9503
|
+
/* The chevron. Unsorted columns show a pale down chevron, so every sortable
|
|
9504
|
+
column says it sorts; the sorted column shows the direction at full text
|
|
9505
|
+
colour. The direction is also in the header's `aria-sort`. */
|
|
9506
|
+
.cn-table-header__chevron {
|
|
9507
|
+
display: inline-flex;
|
|
9508
|
+
flex: none;
|
|
9509
|
+
color: var(--color-main-text);
|
|
9510
|
+
}
|
|
9511
|
+
|
|
9512
|
+
.cn-table-header__chevron--idle {
|
|
9513
|
+
color: var(--color-text-maxcontrast);
|
|
9514
|
+
opacity: 0.5;
|
|
9515
|
+
}
|
|
9516
|
+
|
|
9517
|
+
.cn-data-table th.cn-table-header--sortable:hover .cn-table-header__chevron--idle,
|
|
9518
|
+
.cn-data-table th .cn-table-header__sort:focus-visible .cn-table-header__chevron--idle {
|
|
9519
|
+
opacity: 1;
|
|
9362
9520
|
}
|
|
9363
9521
|
|
|
9364
9522
|
/* A column carrying a `description` gets a dotted underline — the long-standing
|
|
@@ -9374,15 +9532,12 @@ svg.leaflet-image-layer.leaflet-interactive path {
|
|
|
9374
9532
|
cursor: help;
|
|
9375
9533
|
}
|
|
9376
9534
|
|
|
9377
|
-
|
|
9378
|
-
|
|
9379
|
-
|
|
9380
|
-
|
|
9381
|
-
|
|
9382
|
-
|
|
9383
|
-
16px icon; the filled icon plus the primary colour marks an active filter,
|
|
9384
|
-
so the state never rests on colour alone. */
|
|
9385
|
-
.cn-table-header__filter {
|
|
9535
|
+
/* Header filter button (CnDataTable `filterable`): a 14px funnel directly
|
|
9536
|
+
after the sort chevron, in a 24px hit area. Muted with no filter set; with
|
|
9537
|
+
a filter set it takes the dark primary and a dot, so the state never rests
|
|
9538
|
+
on colour alone. */
|
|
9539
|
+
.cn-data-table th .cn-table-header__filter {
|
|
9540
|
+
position: relative;
|
|
9386
9541
|
display: inline-flex;
|
|
9387
9542
|
align-items: center;
|
|
9388
9543
|
justify-content: center;
|
|
@@ -9390,7 +9545,7 @@ svg.leaflet-image-layer.leaflet-interactive path {
|
|
|
9390
9545
|
min-width: 24px;
|
|
9391
9546
|
height: 24px;
|
|
9392
9547
|
min-height: 24px;
|
|
9393
|
-
margin: 0 0 0
|
|
9548
|
+
margin: 0 0 0 2px;
|
|
9394
9549
|
padding: 0;
|
|
9395
9550
|
border: none;
|
|
9396
9551
|
border-radius: var(--border-radius, 4px);
|
|
@@ -9400,18 +9555,31 @@ svg.leaflet-image-layer.leaflet-interactive path {
|
|
|
9400
9555
|
cursor: pointer;
|
|
9401
9556
|
}
|
|
9402
9557
|
|
|
9403
|
-
.cn-table-header__filter:hover {
|
|
9558
|
+
.cn-data-table th .cn-table-header__filter:hover {
|
|
9404
9559
|
background-color: var(--color-background-hover);
|
|
9405
9560
|
color: var(--color-main-text);
|
|
9406
9561
|
}
|
|
9407
9562
|
|
|
9408
|
-
.cn-table-header__filter:focus-visible {
|
|
9563
|
+
.cn-data-table th .cn-table-header__filter:focus-visible {
|
|
9409
9564
|
outline: 2px solid var(--color-main-text);
|
|
9410
9565
|
outline-offset: 0;
|
|
9411
9566
|
}
|
|
9412
9567
|
|
|
9413
|
-
.cn-table-header__filter--active
|
|
9414
|
-
|
|
9568
|
+
.cn-data-table th .cn-table-header__filter--active,
|
|
9569
|
+
.cn-data-table th .cn-table-header__filter--active:hover {
|
|
9570
|
+
color: var(--color-primary-element-light-text, var(--color-primary-element));
|
|
9571
|
+
}
|
|
9572
|
+
|
|
9573
|
+
/* The active-filter dot, on the funnel's top right. */
|
|
9574
|
+
.cn-table-header__filter-dot {
|
|
9575
|
+
position: absolute;
|
|
9576
|
+
inset-block-start: 3px;
|
|
9577
|
+
inset-inline-end: 3px;
|
|
9578
|
+
width: 6px;
|
|
9579
|
+
height: 6px;
|
|
9580
|
+
border-radius: 50%;
|
|
9581
|
+
background-color: var(--color-primary-element);
|
|
9582
|
+
pointer-events: none;
|
|
9415
9583
|
}
|
|
9416
9584
|
|
|
9417
9585
|
/* Active header filters above the table, one removable chip each. */
|
|
@@ -14188,12 +14356,55 @@ button.cn-files-card__open[data-v-46f7e3c9]:hover {
|
|
|
14188
14356
|
flex-direction: column;
|
|
14189
14357
|
gap: 8px;
|
|
14190
14358
|
min-width: 0;
|
|
14359
|
+
position: relative;
|
|
14191
14360
|
border-radius: var(--border-radius-large, 8px);
|
|
14192
14361
|
}
|
|
14193
14362
|
.cn-files-browser--dragging[data-v-f5bdd9e2] {
|
|
14194
14363
|
outline: 2px dashed var(--color-primary-element);
|
|
14195
14364
|
outline-offset: 4px;
|
|
14196
14365
|
}
|
|
14366
|
+
.cn-files-browser__drop-overlay[data-v-f5bdd9e2] {
|
|
14367
|
+
position: absolute;
|
|
14368
|
+
inset: 0;
|
|
14369
|
+
z-index: 2;
|
|
14370
|
+
display: flex;
|
|
14371
|
+
flex-direction: column;
|
|
14372
|
+
align-items: center;
|
|
14373
|
+
justify-content: center;
|
|
14374
|
+
gap: 10px;
|
|
14375
|
+
padding: 24px;
|
|
14376
|
+
box-sizing: border-box;
|
|
14377
|
+
border: 2px dashed var(--color-primary-element);
|
|
14378
|
+
border-radius: var(--border-radius-large, 8px);
|
|
14379
|
+
background: var(--color-primary-element-light);
|
|
14380
|
+
color: var(--color-primary-element-light-text, var(--color-main-text));
|
|
14381
|
+
text-align: center;
|
|
14382
|
+
pointer-events: none;
|
|
14383
|
+
}
|
|
14384
|
+
.cn-files-browser__drop-icon[data-v-f5bdd9e2] {
|
|
14385
|
+
display: flex;
|
|
14386
|
+
align-items: center;
|
|
14387
|
+
justify-content: center;
|
|
14388
|
+
width: 56px;
|
|
14389
|
+
height: 56px;
|
|
14390
|
+
border-radius: 50%;
|
|
14391
|
+
background: var(--color-main-background);
|
|
14392
|
+
color: var(--color-primary-element);
|
|
14393
|
+
}
|
|
14394
|
+
.cn-files-browser__drop-label[data-v-f5bdd9e2] {
|
|
14395
|
+
font-size: 20px;
|
|
14396
|
+
font-weight: 700;
|
|
14397
|
+
}
|
|
14398
|
+
.cn-files-browser__drop-hint[data-v-f5bdd9e2] {
|
|
14399
|
+
display: flex;
|
|
14400
|
+
align-items: center;
|
|
14401
|
+
gap: 8px;
|
|
14402
|
+
margin: 0;
|
|
14403
|
+
padding-top: 12px;
|
|
14404
|
+
border-top: 1px solid var(--color-border);
|
|
14405
|
+
font-size: 13px;
|
|
14406
|
+
color: var(--color-text-maxcontrast);
|
|
14407
|
+
}
|
|
14197
14408
|
.cn-files-browser__bar[data-v-f5bdd9e2] {
|
|
14198
14409
|
display: flex;
|
|
14199
14410
|
align-items: center;
|
|
@@ -32093,8 +32304,42 @@ button.cn-object-calendar__overflow[data-v-bea31862] {
|
|
|
32093
32304
|
}
|
|
32094
32305
|
|
|
32095
32306
|
|
|
32096
|
-
.cn-
|
|
32097
|
-
|
|
32307
|
+
.cn-follow-toggle[data-v-eec896e2] {
|
|
32308
|
+
display: inline-flex;
|
|
32309
|
+
align-items: center;
|
|
32310
|
+
gap: 4px;
|
|
32311
|
+
}
|
|
32312
|
+
.cn-follow-toggle__on[data-v-eec896e2] {
|
|
32313
|
+
color: var(--color-primary-element);
|
|
32314
|
+
}
|
|
32315
|
+
.cn-follow-toggle__popover[data-v-eec896e2] {
|
|
32316
|
+
min-width: 260px;
|
|
32317
|
+
padding: 12px;
|
|
32318
|
+
}
|
|
32319
|
+
.cn-follow-toggle__list[data-v-eec896e2] {
|
|
32320
|
+
list-style: none;
|
|
32321
|
+
margin: 0 0 8px;
|
|
32322
|
+
padding: 0;
|
|
32323
|
+
}
|
|
32324
|
+
.cn-follow-toggle__row[data-v-eec896e2] {
|
|
32325
|
+
display: flex;
|
|
32326
|
+
align-items: center;
|
|
32327
|
+
gap: 8px;
|
|
32328
|
+
padding: 4px 0;
|
|
32329
|
+
}
|
|
32330
|
+
.cn-follow-toggle__who[data-v-eec896e2] {
|
|
32331
|
+
display: flex;
|
|
32332
|
+
flex-direction: column;
|
|
32333
|
+
flex: 1 1 auto;
|
|
32334
|
+
min-width: 0;
|
|
32335
|
+
}
|
|
32336
|
+
.cn-follow-toggle__since[data-v-eec896e2] {
|
|
32337
|
+
color: var(--color-text-maxcontrast);
|
|
32338
|
+
font-size: var(--font-size-small, 13px);
|
|
32339
|
+
}
|
|
32340
|
+
.cn-follow-toggle__error[data-v-eec896e2] {
|
|
32341
|
+
margin: 8px 0 0;
|
|
32342
|
+
color: var(--color-error-text);
|
|
32098
32343
|
}
|
|
32099
32344
|
|
|
32100
32345
|
|
|
@@ -34239,42 +34484,6 @@ button.cn-object-calendar__overflow[data-v-bea31862] {
|
|
|
34239
34484
|
}
|
|
34240
34485
|
|
|
34241
34486
|
|
|
34242
|
-
.cn-follow-toggle[data-v-eec896e2] {
|
|
34243
|
-
display: inline-flex;
|
|
34244
|
-
align-items: center;
|
|
34245
|
-
gap: 4px;
|
|
34246
|
-
}
|
|
34247
|
-
.cn-follow-toggle__popover[data-v-eec896e2] {
|
|
34248
|
-
min-width: 260px;
|
|
34249
|
-
padding: 12px;
|
|
34250
|
-
}
|
|
34251
|
-
.cn-follow-toggle__list[data-v-eec896e2] {
|
|
34252
|
-
list-style: none;
|
|
34253
|
-
margin: 0 0 8px;
|
|
34254
|
-
padding: 0;
|
|
34255
|
-
}
|
|
34256
|
-
.cn-follow-toggle__row[data-v-eec896e2] {
|
|
34257
|
-
display: flex;
|
|
34258
|
-
align-items: center;
|
|
34259
|
-
gap: 8px;
|
|
34260
|
-
padding: 4px 0;
|
|
34261
|
-
}
|
|
34262
|
-
.cn-follow-toggle__who[data-v-eec896e2] {
|
|
34263
|
-
display: flex;
|
|
34264
|
-
flex-direction: column;
|
|
34265
|
-
flex: 1 1 auto;
|
|
34266
|
-
min-width: 0;
|
|
34267
|
-
}
|
|
34268
|
-
.cn-follow-toggle__since[data-v-eec896e2] {
|
|
34269
|
-
color: var(--color-text-maxcontrast);
|
|
34270
|
-
font-size: var(--font-size-small, 13px);
|
|
34271
|
-
}
|
|
34272
|
-
.cn-follow-toggle__error[data-v-eec896e2] {
|
|
34273
|
-
margin: 8px 0 0;
|
|
34274
|
-
color: var(--color-error-text);
|
|
34275
|
-
}
|
|
34276
|
-
|
|
34277
|
-
|
|
34278
34487
|
.cn-lifecycle-actions[data-v-a62ad362] {
|
|
34279
34488
|
display: flex;
|
|
34280
34489
|
flex-wrap: wrap;
|
|
@@ -35948,6 +36157,11 @@ button.cn-object-calendar__overflow[data-v-bea31862] {
|
|
|
35948
36157
|
}
|
|
35949
36158
|
|
|
35950
36159
|
|
|
36160
|
+
.cn-favourite-toggle__star[data-v-836dad16] {
|
|
36161
|
+
color: var(--color-warning);
|
|
36162
|
+
}
|
|
36163
|
+
|
|
36164
|
+
|
|
35951
36165
|
.cn-journey-review-list__items[data-v-d3c04832] {
|
|
35952
36166
|
list-style: none;
|
|
35953
36167
|
margin: 8px 0 0;
|
|
@@ -3,7 +3,8 @@ import { setFavourite, setReadState, setWatching, listWatchers, setWatcher } fro
|
|
|
3
3
|
/**
|
|
4
4
|
* Interactions plugin for the object store.
|
|
5
5
|
*
|
|
6
|
-
* Per-user interaction calls on a record:
|
|
6
|
+
* Per-user interaction calls on a record: follow (watch, with its
|
|
7
|
+
* notifications switch), the deprecated favourite (a quiet follow), and the
|
|
7
8
|
* followers list. Each write puts the server's answer into the stored object's
|
|
8
9
|
* `@self`, so a list showing the same object agrees with the toggle.
|
|
9
10
|
*
|
|
@@ -55,7 +56,10 @@ function interactionsPlugin() {
|
|
|
55
56
|
},
|
|
56
57
|
|
|
57
58
|
/**
|
|
58
|
-
* Star a record.
|
|
59
|
+
* Star a record: a quiet follow on the server.
|
|
60
|
+
*
|
|
61
|
+
* @deprecated A favourite is a follow with notifications off since
|
|
62
|
+
* OpenRegister's `merge-follow-and-favourites`; use `watch(type, id, { notify: false })`.
|
|
59
63
|
*
|
|
60
64
|
* @param {string} type The registered object type slug
|
|
61
65
|
* @param {string} objectId The object ID
|
|
@@ -65,13 +69,15 @@ function interactionsPlugin() {
|
|
|
65
69
|
const { register, schema } = this._interactionTarget(type);
|
|
66
70
|
const result = await setFavourite(register, schema, objectId, true);
|
|
67
71
|
if (result.ok) {
|
|
68
|
-
this._patchSelf(type, objectId, { favourite: true });
|
|
72
|
+
this._patchSelf(type, objectId, { favourite: true, watching: true });
|
|
69
73
|
}
|
|
70
74
|
return result
|
|
71
75
|
},
|
|
72
76
|
|
|
73
77
|
/**
|
|
74
|
-
* Unstar a record.
|
|
78
|
+
* Unstar a record: unfollow it.
|
|
79
|
+
*
|
|
80
|
+
* @deprecated Use `unwatch`.
|
|
75
81
|
*
|
|
76
82
|
* @param {string} type The registered object type slug
|
|
77
83
|
* @param {string} objectId The object ID
|
|
@@ -81,7 +87,7 @@ function interactionsPlugin() {
|
|
|
81
87
|
const { register, schema } = this._interactionTarget(type);
|
|
82
88
|
const result = await setFavourite(register, schema, objectId, false);
|
|
83
89
|
if (result.ok) {
|
|
84
|
-
this._patchSelf(type, objectId, { favourite: false });
|
|
90
|
+
this._patchSelf(type, objectId, { favourite: false, watching: false, watchNotify: undefined });
|
|
85
91
|
}
|
|
86
92
|
return result
|
|
87
93
|
},
|
|
@@ -119,17 +125,21 @@ function interactionsPlugin() {
|
|
|
119
125
|
},
|
|
120
126
|
|
|
121
127
|
/**
|
|
122
|
-
* Follow a record.
|
|
128
|
+
* Follow a record, optionally setting its notifications switch.
|
|
123
129
|
*
|
|
124
130
|
* @param {string} type The registered object type slug
|
|
125
131
|
* @param {string} objectId The object ID
|
|
132
|
+
* @param {object} [options] Options
|
|
133
|
+
* @param {boolean} [options.notify] The notifications switch; left out, a new follow notifies
|
|
126
134
|
* @return {Promise<object>} The outcome
|
|
135
|
+
* @spec openspec/changes/one-follow-control/specs/record-follow/spec.md#requirement-one-follow-control-with-a-notifications-switch
|
|
127
136
|
*/
|
|
128
|
-
async watch(type, objectId) {
|
|
137
|
+
async watch(type, objectId, options = {}) {
|
|
129
138
|
const { register, schema } = this._interactionTarget(type);
|
|
130
|
-
const result = await setWatching(register, schema, objectId, true);
|
|
139
|
+
const result = await setWatching(register, schema, objectId, true, options);
|
|
131
140
|
if (result.ok) {
|
|
132
|
-
|
|
141
|
+
const notify = result.data && typeof result.data.notify === 'boolean' ? result.data.notify : true;
|
|
142
|
+
this._patchSelf(type, objectId, { watching: true, favourite: true, watchNotify: notify });
|
|
133
143
|
}
|
|
134
144
|
return result
|
|
135
145
|
},
|
|
@@ -145,7 +155,7 @@ function interactionsPlugin() {
|
|
|
145
155
|
const { register, schema } = this._interactionTarget(type);
|
|
146
156
|
const result = await setWatching(register, schema, objectId, false);
|
|
147
157
|
if (result.ok) {
|
|
148
|
-
this._patchSelf(type, objectId, { watching: false });
|
|
158
|
+
this._patchSelf(type, objectId, { watching: false, favourite: false, watchNotify: undefined });
|
|
149
159
|
}
|
|
150
160
|
return result
|
|
151
161
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interactions.js","sources":["../../../../src/store/plugins/interactions.js"],"sourcesContent":["import { listWatchers, setFavourite, setReadState, setWatcher, setWatching } from '../../utils/recordInteractions.js'\n\n/**\n * Interactions plugin for the object store.\n *\n * Per-user interaction calls on a record: favourite, follow (watch) and the\n * followers list. Each write puts the server's answer into the stored object's\n * `@self`, so a list showing the same object agrees with the toggle.\n *\n * Actions: favourite, unfavourite, watch, unwatch, fetchWatchers, addWatcher, removeWatcher, markRead, markUnread.\n * Each returns the outcome `{ ok, status, data, message }` and never throws.\n *\n * @return {object} The plugin definition (name, state, getters, actions)\n *\n * @example\n * const useStore = createObjectStore('object', { plugins: [interactionsPlugin()] })\n * const store = useStore()\n * await store.watch('case', caseId)\n * const { data } = await store.fetchWatchers('case', caseId)\n */\nexport function interactionsPlugin() {\n\treturn {\n\t\tname: 'Interactions',\n\n\t\tstate: () => ({}),\n\n\t\tgetters: {},\n\n\t\tactions: {\n\t\t\t/**\n\t\t\t * Merge a patch into the stored object's `@self`.\n\t\t\t *\n\t\t\t * @param {string} type The registered object type slug\n\t\t\t * @param {string} objectId The object ID\n\t\t\t * @param {object} patch Keys to merge into `@self`\n\t\t\t */\n\t\t\t_patchSelf(type, objectId, patch) {\n\t\t\t\tconst stored = this.objects && this.objects[type] && this.objects[type][objectId]\n\t\t\t\tif (!stored) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tconst next = { ...stored, '@self': { ...(stored['@self'] || {}), ...patch } }\n\t\t\t\tthis.objects = { ...this.objects, [type]: { ...this.objects[type], [objectId]: next } }\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Resolve a type slug to its register and schema.\n\t\t\t *\n\t\t\t * @param {string} type The registered object type slug\n\t\t\t * @return {{register: string, schema: string}} The path segments\n\t\t\t */\n\t\t\t_interactionTarget(type) {\n\t\t\t\tconst config = this._getTypeConfig(type)\n\t\t\t\treturn { register: config.register, schema: config.schema }\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Star a record.\n\t\t\t *\n\t\t\t * @param {string} type The registered object type slug\n\t\t\t * @param {string} objectId The object ID\n\t\t\t * @return {Promise<object>} The outcome\n\t\t\t */\n\t\t\tasync favourite(type, objectId) {\n\t\t\t\tconst { register, schema } = this._interactionTarget(type)\n\t\t\t\tconst result = await setFavourite(register, schema, objectId, true)\n\t\t\t\tif (result.ok) {\n\t\t\t\t\tthis._patchSelf(type, objectId, { favourite: true })\n\t\t\t\t}\n\t\t\t\treturn result\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Unstar a record.\n\t\t\t *\n\t\t\t * @param {string} type The registered object type slug\n\t\t\t * @param {string} objectId The object ID\n\t\t\t * @return {Promise<object>} The outcome\n\t\t\t */\n\t\t\tasync unfavourite(type, objectId) {\n\t\t\t\tconst { register, schema } = this._interactionTarget(type)\n\t\t\t\tconst result = await setFavourite(register, schema, objectId, false)\n\t\t\t\tif (result.ok) {\n\t\t\t\t\tthis._patchSelf(type, objectId, { favourite: false })\n\t\t\t\t}\n\t\t\t\treturn result\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Mark a record read (`PUT .../read-state`).\n\t\t\t *\n\t\t\t * @param {string} type The registered object type slug\n\t\t\t * @param {string} objectId The object ID\n\t\t\t * @return {Promise<object>} The outcome\n\t\t\t */\n\t\t\tasync markRead(type, objectId) {\n\t\t\t\tconst { register, schema } = this._interactionTarget(type)\n\t\t\t\tconst result = await setReadState(register, schema, objectId, true)\n\t\t\t\tif (result.ok) {\n\t\t\t\t\tthis._patchSelf(type, objectId, { unread: false })\n\t\t\t\t}\n\t\t\t\treturn result\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Mark a record unread (`DELETE .../read-state`).\n\t\t\t *\n\t\t\t * @param {string} type The registered object type slug\n\t\t\t * @param {string} objectId The object ID\n\t\t\t * @return {Promise<object>} The outcome\n\t\t\t */\n\t\t\tasync markUnread(type, objectId) {\n\t\t\t\tconst { register, schema } = this._interactionTarget(type)\n\t\t\t\tconst result = await setReadState(register, schema, objectId, false)\n\t\t\t\tif (result.ok) {\n\t\t\t\t\tthis._patchSelf(type, objectId, { unread: true })\n\t\t\t\t}\n\t\t\t\treturn result\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Follow a record.\n\t\t\t *\n\t\t\t * @param {string} type The registered object type slug\n\t\t\t * @param {string} objectId The object ID\n\t\t\t * @return {Promise<object>} The outcome\n\t\t\t */\n\t\t\tasync watch(type, objectId) {\n\t\t\t\tconst { register, schema } = this._interactionTarget(type)\n\t\t\t\tconst result = await setWatching(register, schema, objectId, true)\n\t\t\t\tif (result.ok) {\n\t\t\t\t\tthis._patchSelf(type, objectId, { watching: true })\n\t\t\t\t}\n\t\t\t\treturn result\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Unfollow a record.\n\t\t\t *\n\t\t\t * @param {string} type The registered object type slug\n\t\t\t * @param {string} objectId The object ID\n\t\t\t * @return {Promise<object>} The outcome\n\t\t\t */\n\t\t\tasync unwatch(type, objectId) {\n\t\t\t\tconst { register, schema } = this._interactionTarget(type)\n\t\t\t\tconst result = await setWatching(register, schema, objectId, false)\n\t\t\t\tif (result.ok) {\n\t\t\t\t\tthis._patchSelf(type, objectId, { watching: false })\n\t\t\t\t}\n\t\t\t\treturn result\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * List the followers of a record (needs `update` on it).\n\t\t\t *\n\t\t\t * @param {string} type The registered object type slug\n\t\t\t * @param {string} objectId The object ID\n\t\t\t * @return {Promise<object>} The outcome; `data` is `{ results, total }`\n\t\t\t */\n\t\t\tasync fetchWatchers(type, objectId) {\n\t\t\t\tconst { register, schema } = this._interactionTarget(type)\n\t\t\t\treturn listWatchers(register, schema, objectId)\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Add a colleague as a follower (needs `manage`).\n\t\t\t *\n\t\t\t * @param {string} type The registered object type slug\n\t\t\t * @param {string} objectId The object ID\n\t\t\t * @param {string} userId The colleague's user id\n\t\t\t * @return {Promise<object>} The outcome\n\t\t\t */\n\t\t\tasync addWatcher(type, objectId, userId) {\n\t\t\t\tconst { register, schema } = this._interactionTarget(type)\n\t\t\t\treturn setWatcher(register, schema, objectId, userId, true)\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Remove a follower (needs `manage`, or be the user yourself).\n\t\t\t *\n\t\t\t * @param {string} type The registered object type slug\n\t\t\t * @param {string} objectId The object ID\n\t\t\t * @param {string} userId The follower's user id\n\t\t\t * @return {Promise<object>} The outcome\n\t\t\t */\n\t\t\tasync removeWatcher(type, objectId, userId) {\n\t\t\t\tconst { register, schema } = this._interactionTarget(type)\n\t\t\t\treturn setWatcher(register, schema, objectId, userId, false)\n\t\t\t},\n\t\t},\n\t}\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"interactions.js","sources":["../../../../src/store/plugins/interactions.js"],"sourcesContent":["import { listWatchers, setFavourite, setReadState, setWatcher, setWatching } from '../../utils/recordInteractions.js'\n\n/**\n * Interactions plugin for the object store.\n *\n * Per-user interaction calls on a record: follow (watch, with its\n * notifications switch), the deprecated favourite (a quiet follow), and the\n * followers list. Each write puts the server's answer into the stored object's\n * `@self`, so a list showing the same object agrees with the toggle.\n *\n * Actions: favourite, unfavourite, watch, unwatch, fetchWatchers, addWatcher, removeWatcher, markRead, markUnread.\n * Each returns the outcome `{ ok, status, data, message }` and never throws.\n *\n * @return {object} The plugin definition (name, state, getters, actions)\n *\n * @example\n * const useStore = createObjectStore('object', { plugins: [interactionsPlugin()] })\n * const store = useStore()\n * await store.watch('case', caseId)\n * const { data } = await store.fetchWatchers('case', caseId)\n */\nexport function interactionsPlugin() {\n\treturn {\n\t\tname: 'Interactions',\n\n\t\tstate: () => ({}),\n\n\t\tgetters: {},\n\n\t\tactions: {\n\t\t\t/**\n\t\t\t * Merge a patch into the stored object's `@self`.\n\t\t\t *\n\t\t\t * @param {string} type The registered object type slug\n\t\t\t * @param {string} objectId The object ID\n\t\t\t * @param {object} patch Keys to merge into `@self`\n\t\t\t */\n\t\t\t_patchSelf(type, objectId, patch) {\n\t\t\t\tconst stored = this.objects && this.objects[type] && this.objects[type][objectId]\n\t\t\t\tif (!stored) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tconst next = { ...stored, '@self': { ...(stored['@self'] || {}), ...patch } }\n\t\t\t\tthis.objects = { ...this.objects, [type]: { ...this.objects[type], [objectId]: next } }\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Resolve a type slug to its register and schema.\n\t\t\t *\n\t\t\t * @param {string} type The registered object type slug\n\t\t\t * @return {{register: string, schema: string}} The path segments\n\t\t\t */\n\t\t\t_interactionTarget(type) {\n\t\t\t\tconst config = this._getTypeConfig(type)\n\t\t\t\treturn { register: config.register, schema: config.schema }\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Star a record: a quiet follow on the server.\n\t\t\t *\n\t\t\t * @deprecated A favourite is a follow with notifications off since\n\t\t\t * OpenRegister's `merge-follow-and-favourites`; use `watch(type, id, { notify: false })`.\n\t\t\t *\n\t\t\t * @param {string} type The registered object type slug\n\t\t\t * @param {string} objectId The object ID\n\t\t\t * @return {Promise<object>} The outcome\n\t\t\t */\n\t\t\tasync favourite(type, objectId) {\n\t\t\t\tconst { register, schema } = this._interactionTarget(type)\n\t\t\t\tconst result = await setFavourite(register, schema, objectId, true)\n\t\t\t\tif (result.ok) {\n\t\t\t\t\tthis._patchSelf(type, objectId, { favourite: true, watching: true })\n\t\t\t\t}\n\t\t\t\treturn result\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Unstar a record: unfollow it.\n\t\t\t *\n\t\t\t * @deprecated Use `unwatch`.\n\t\t\t *\n\t\t\t * @param {string} type The registered object type slug\n\t\t\t * @param {string} objectId The object ID\n\t\t\t * @return {Promise<object>} The outcome\n\t\t\t */\n\t\t\tasync unfavourite(type, objectId) {\n\t\t\t\tconst { register, schema } = this._interactionTarget(type)\n\t\t\t\tconst result = await setFavourite(register, schema, objectId, false)\n\t\t\t\tif (result.ok) {\n\t\t\t\t\tthis._patchSelf(type, objectId, { favourite: false, watching: false, watchNotify: undefined })\n\t\t\t\t}\n\t\t\t\treturn result\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Mark a record read (`PUT .../read-state`).\n\t\t\t *\n\t\t\t * @param {string} type The registered object type slug\n\t\t\t * @param {string} objectId The object ID\n\t\t\t * @return {Promise<object>} The outcome\n\t\t\t */\n\t\t\tasync markRead(type, objectId) {\n\t\t\t\tconst { register, schema } = this._interactionTarget(type)\n\t\t\t\tconst result = await setReadState(register, schema, objectId, true)\n\t\t\t\tif (result.ok) {\n\t\t\t\t\tthis._patchSelf(type, objectId, { unread: false })\n\t\t\t\t}\n\t\t\t\treturn result\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Mark a record unread (`DELETE .../read-state`).\n\t\t\t *\n\t\t\t * @param {string} type The registered object type slug\n\t\t\t * @param {string} objectId The object ID\n\t\t\t * @return {Promise<object>} The outcome\n\t\t\t */\n\t\t\tasync markUnread(type, objectId) {\n\t\t\t\tconst { register, schema } = this._interactionTarget(type)\n\t\t\t\tconst result = await setReadState(register, schema, objectId, false)\n\t\t\t\tif (result.ok) {\n\t\t\t\t\tthis._patchSelf(type, objectId, { unread: true })\n\t\t\t\t}\n\t\t\t\treturn result\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Follow a record, optionally setting its notifications switch.\n\t\t\t *\n\t\t\t * @param {string} type The registered object type slug\n\t\t\t * @param {string} objectId The object ID\n\t\t\t * @param {object} [options] Options\n\t\t\t * @param {boolean} [options.notify] The notifications switch; left out, a new follow notifies\n\t\t\t * @return {Promise<object>} The outcome\n\t\t\t * @spec openspec/changes/one-follow-control/specs/record-follow/spec.md#requirement-one-follow-control-with-a-notifications-switch\n\t\t\t */\n\t\t\tasync watch(type, objectId, options = {}) {\n\t\t\t\tconst { register, schema } = this._interactionTarget(type)\n\t\t\t\tconst result = await setWatching(register, schema, objectId, true, options)\n\t\t\t\tif (result.ok) {\n\t\t\t\t\tconst notify = result.data && typeof result.data.notify === 'boolean' ? result.data.notify : true\n\t\t\t\t\tthis._patchSelf(type, objectId, { watching: true, favourite: true, watchNotify: notify })\n\t\t\t\t}\n\t\t\t\treturn result\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Unfollow a record.\n\t\t\t *\n\t\t\t * @param {string} type The registered object type slug\n\t\t\t * @param {string} objectId The object ID\n\t\t\t * @return {Promise<object>} The outcome\n\t\t\t */\n\t\t\tasync unwatch(type, objectId) {\n\t\t\t\tconst { register, schema } = this._interactionTarget(type)\n\t\t\t\tconst result = await setWatching(register, schema, objectId, false)\n\t\t\t\tif (result.ok) {\n\t\t\t\t\tthis._patchSelf(type, objectId, { watching: false, favourite: false, watchNotify: undefined })\n\t\t\t\t}\n\t\t\t\treturn result\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * List the followers of a record (needs `update` on it).\n\t\t\t *\n\t\t\t * @param {string} type The registered object type slug\n\t\t\t * @param {string} objectId The object ID\n\t\t\t * @return {Promise<object>} The outcome; `data` is `{ results, total }`\n\t\t\t */\n\t\t\tasync fetchWatchers(type, objectId) {\n\t\t\t\tconst { register, schema } = this._interactionTarget(type)\n\t\t\t\treturn listWatchers(register, schema, objectId)\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Add a colleague as a follower (needs `manage`).\n\t\t\t *\n\t\t\t * @param {string} type The registered object type slug\n\t\t\t * @param {string} objectId The object ID\n\t\t\t * @param {string} userId The colleague's user id\n\t\t\t * @return {Promise<object>} The outcome\n\t\t\t */\n\t\t\tasync addWatcher(type, objectId, userId) {\n\t\t\t\tconst { register, schema } = this._interactionTarget(type)\n\t\t\t\treturn setWatcher(register, schema, objectId, userId, true)\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Remove a follower (needs `manage`, or be the user yourself).\n\t\t\t *\n\t\t\t * @param {string} type The registered object type slug\n\t\t\t * @param {string} objectId The object ID\n\t\t\t * @param {string} userId The follower's user id\n\t\t\t * @return {Promise<object>} The outcome\n\t\t\t */\n\t\t\tasync removeWatcher(type, objectId, userId) {\n\t\t\t\tconst { register, schema } = this._interactionTarget(type)\n\t\t\t\treturn setWatcher(register, schema, objectId, userId, false)\n\t\t\t},\n\t\t},\n\t}\n}\n"],"names":[],"mappings":"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"}
|