@conduction/nextcloud-vue 2.103.0 → 2.104.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/CnActionsBar/CnActionsBar.vue2.js +23 -0
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue2.js.map +1 -1
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js +94 -72
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js.map +1 -1
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js +18 -1
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js.map +1 -1
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js +3 -3
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js +39 -2
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js +14 -0
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +40 -2
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +159 -3
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +105 -85
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/useSelfFetchList.js +7 -2
- package/dist/esm/components/CnIndexPage/useSelfFetchList.js.map +1 -1
- package/dist/esm/components/CnObjectRow/CnObjectRow.vue.js +1 -1
- package/dist/esm/components/CnObjectRow/CnObjectRow.vue2.js +57 -5
- package/dist/esm/components/CnObjectRow/CnObjectRow.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectRow/CnObjectRow.vue3.js +37 -4
- package/dist/esm/components/CnObjectRow/CnObjectRow.vue3.js.map +1 -1
- package/dist/esm/components/CnUserSettingsDialog/CnUserSettingsDialog.vue.js +1 -1
- package/dist/esm/components/CnUserSettingsDialog/CnUserSettingsDialog.vue2.js.map +1 -1
- package/dist/esm/components/CnUserSettingsDialog/CnUserSettingsDialog.vue3.js.map +1 -1
- package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue.js +1 -1
- package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js +18 -2
- 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/indexSources.js +7 -7
- package/dist/esm/composables/indexSources.js.map +1 -1
- package/dist/esm/l10n/en.json.js +4 -0
- package/dist/esm/l10n/en.json.js.map +1 -1
- package/dist/esm/l10n/nl.json.js +4 -0
- package/dist/esm/l10n/nl.json.js.map +1 -1
- package/dist/esm/library-style.js +1 -1
- package/dist/esm/nextcloud-vue.css +114 -33
- package/dist/esm/utils/nextcloudDirectory.js +18 -1
- package/dist/esm/utils/nextcloudDirectory.js.map +1 -1
- package/dist/esm/utils/sortOrder.js +61 -0
- package/dist/esm/utils/sortOrder.js.map +1 -0
- package/dist/esm/utils/validateManifestV2.compiled.js +3 -3
- package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
- package/dist/nextcloud-vue.cjs.js +4172 -3662
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +114 -33
- package/l10n/en.json +4 -0
- package/l10n/nl.json +4 -0
- package/package.json +1 -1
- package/src/components/CnActionsBar/CnActionsBar.md +1 -0
- package/src/components/CnActionsBar/CnActionsBar.vue +39 -2
- package/src/components/CnAppRoot/CnAppRoot.md +1 -1
- package/src/components/CnAppRoot/CnAppRoot.vue +21 -4
- package/src/components/CnDataTable/CnDataTable.md +1 -0
- package/src/components/CnDataTable/CnDataTable.vue +49 -0
- package/src/components/CnDetailPage/CnDetailPage.md +1 -0
- package/src/components/CnDetailPage/CnDetailPage.vue +40 -2
- package/src/components/CnIndexPage/CnIndexPage.md +4 -2
- package/src/components/CnIndexPage/CnIndexPage.vue +174 -8
- package/src/components/CnIndexPage/useSelfFetchList.js +6 -1
- package/src/components/CnObjectRow/CnObjectRow.vue +95 -1
- package/src/components/CnUserSettingsDialog/CnUserSettingsDialog.vue +7 -2
- package/src/components/CnWidgetObjectTable/CnWidgetObjectTable.vue +18 -2
- package/src/composables/indexSources.js +7 -7
- package/src/css/index-page.css +19 -0
- package/src/css/look-board-index.css +48 -0
- package/src/schemas/app-manifest-v2.schema.json +23 -1
- package/src/utils/nextcloudDirectory.js +17 -0
- package/src/utils/sortOrder.js +58 -0
- package/src/utils/validateManifestV2.compiled.js +3 -3
|
@@ -2645,6 +2645,17 @@
|
|
|
2645
2645
|
cursor: not-allowed;
|
|
2646
2646
|
}
|
|
2647
2647
|
|
|
2648
|
+
/* `searchPlacement: "toolbar"`: the search field on row 1 takes the room
|
|
2649
|
+
before Filter and the view switch, which keep the end of the row. */
|
|
2650
|
+
.cn-look-board .cn-actions-bar--board > .cn-actions-bar__row--views > .cn-actions-bar__search--toolbar {
|
|
2651
|
+
flex: 1 1 220px;
|
|
2652
|
+
min-width: 180px;
|
|
2653
|
+
}
|
|
2654
|
+
|
|
2655
|
+
.cn-look-board .cn-actions-bar--board > .cn-actions-bar__row--views > .cn-actions-bar__search--toolbar ~ .cn-actions-bar__view-controls {
|
|
2656
|
+
margin-inline-start: 0;
|
|
2657
|
+
}
|
|
2658
|
+
|
|
2648
2659
|
/* The search field: 40px, radius 8, not a pill. */
|
|
2649
2660
|
.cn-look-board .cn-actions-bar--board .cn-actions-bar__search {
|
|
2650
2661
|
flex: 1 1 260px;
|
|
@@ -3381,6 +3392,43 @@
|
|
|
3381
3392
|
.cn-look-board:has(.cn-index-page) > .app-sidebar__toggle {
|
|
3382
3393
|
display: none;
|
|
3383
3394
|
}
|
|
3395
|
+
|
|
3396
|
+
/* The folder pane as a card (DqAfdelingen): 280px, a hairline border, 12px
|
|
3397
|
+
corners, with each folder's count in a grey pill. */
|
|
3398
|
+
.cn-look-board .cn-index-page__folder-pane {
|
|
3399
|
+
flex: 0 0 280px;
|
|
3400
|
+
align-self: flex-start;
|
|
3401
|
+
margin-inline-end: 20px;
|
|
3402
|
+
padding: 14px;
|
|
3403
|
+
border: 1px solid var(--cn-board-hairline);
|
|
3404
|
+
border-radius: var(--cn-board-card-radius, 12px);
|
|
3405
|
+
background: var(--color-main-background);
|
|
3406
|
+
}
|
|
3407
|
+
|
|
3408
|
+
.cn-look-board .cn-index-page__folder-pane .cn-folder-tree__count {
|
|
3409
|
+
display: inline-flex;
|
|
3410
|
+
align-items: center;
|
|
3411
|
+
justify-content: center;
|
|
3412
|
+
min-width: 20px;
|
|
3413
|
+
height: 20px;
|
|
3414
|
+
padding: 0 6px;
|
|
3415
|
+
box-sizing: border-box;
|
|
3416
|
+
border-radius: 10px;
|
|
3417
|
+
background: var(--color-background-dark);
|
|
3418
|
+
color: var(--color-main-text);
|
|
3419
|
+
font-size: 12px;
|
|
3420
|
+
font-weight: 600;
|
|
3421
|
+
}
|
|
3422
|
+
|
|
3423
|
+
/* The selected folder's heading above the list: a 20px title over a soft line. */
|
|
3424
|
+
.cn-look-board .cn-index-page__scope-heading {
|
|
3425
|
+
margin-bottom: 16px;
|
|
3426
|
+
}
|
|
3427
|
+
|
|
3428
|
+
.cn-look-board .cn-index-page__scope-title {
|
|
3429
|
+
font-size: 20px;
|
|
3430
|
+
font-weight: 700;
|
|
3431
|
+
}
|
|
3384
3432
|
/* ========================================
|
|
3385
3433
|
@conduction/nextcloud-vue — Table Styles
|
|
3386
3434
|
======================================== */
|
|
@@ -6193,6 +6241,25 @@ a.cn-kpi-card--board * {
|
|
|
6193
6241
|
font-size: 14px;
|
|
6194
6242
|
}
|
|
6195
6243
|
|
|
6244
|
+
/* The selected folder's heading above the list. */
|
|
6245
|
+
.cn-index-page__scope-heading {
|
|
6246
|
+
display: flex;
|
|
6247
|
+
flex-direction: column;
|
|
6248
|
+
gap: 4px;
|
|
6249
|
+
margin-bottom: 12px;
|
|
6250
|
+
}
|
|
6251
|
+
|
|
6252
|
+
.cn-index-page__scope-title {
|
|
6253
|
+
margin: 0;
|
|
6254
|
+
font-size: 1.25em;
|
|
6255
|
+
font-weight: 700;
|
|
6256
|
+
}
|
|
6257
|
+
|
|
6258
|
+
.cn-index-page__scope-subtitle {
|
|
6259
|
+
font-size: 14px;
|
|
6260
|
+
color: var(--color-text-maxcontrast);
|
|
6261
|
+
}
|
|
6262
|
+
|
|
6196
6263
|
/* Opt-in folder navigation pane (left of the list). */
|
|
6197
6264
|
.cn-index-page__folder-pane {
|
|
6198
6265
|
flex: 0 0 240px;
|
|
@@ -26771,16 +26838,16 @@ button.cn-stepper__step[data-v-776581d4] {
|
|
|
26771
26838
|
}
|
|
26772
26839
|
|
|
26773
26840
|
|
|
26774
|
-
.cn-widget-object-table[data-v-
|
|
26841
|
+
.cn-widget-object-table[data-v-d628ab02] {
|
|
26775
26842
|
width: 100%;
|
|
26776
26843
|
}
|
|
26777
|
-
.cn-widget-object-table__footer[data-v-
|
|
26844
|
+
.cn-widget-object-table__footer[data-v-d628ab02] {
|
|
26778
26845
|
display: flex;
|
|
26779
26846
|
gap: 4px;
|
|
26780
26847
|
padding: 4px 8px;
|
|
26781
26848
|
border-top: 1px solid var(--color-border);
|
|
26782
26849
|
}
|
|
26783
|
-
.cn-widget-object-table__error[data-v-
|
|
26850
|
+
.cn-widget-object-table__error[data-v-d628ab02] {
|
|
26784
26851
|
color: var(--color-text-error, var(--color-error-text));
|
|
26785
26852
|
font-size: 0.85em;
|
|
26786
26853
|
margin: 4px 8px 0;
|
|
@@ -38455,7 +38522,7 @@ to {
|
|
|
38455
38522
|
color: var(--color-text-maxcontrast);
|
|
38456
38523
|
}
|
|
38457
38524
|
|
|
38458
|
-
.cn-object-row[data-v-
|
|
38525
|
+
.cn-object-row[data-v-6e2b35c2] {
|
|
38459
38526
|
display: flex;
|
|
38460
38527
|
align-items: center;
|
|
38461
38528
|
gap: 12px;
|
|
@@ -38463,18 +38530,26 @@ to {
|
|
|
38463
38530
|
border-bottom: 1px solid var(--color-border);
|
|
38464
38531
|
cursor: pointer;
|
|
38465
38532
|
}
|
|
38466
|
-
.cn-object-row[data-v-
|
|
38533
|
+
.cn-object-row[data-v-6e2b35c2]:hover {
|
|
38467
38534
|
background-color: var(--color-background-hover);
|
|
38468
38535
|
}
|
|
38469
|
-
.cn-object-row--selected[data-v-
|
|
38536
|
+
.cn-object-row--selected[data-v-6e2b35c2] {
|
|
38470
38537
|
/* Inset accent — never border-left (would shift cell content). */
|
|
38471
38538
|
box-shadow: inset 3px 0 0 0 var(--color-primary-element);
|
|
38472
38539
|
background-color: var(--color-primary-element-light);
|
|
38473
38540
|
}
|
|
38474
|
-
.cn-object-
|
|
38541
|
+
.cn-object-row__lead[data-v-6e2b35c2],
|
|
38542
|
+
.cn-object-row__trail[data-v-6e2b35c2] {
|
|
38543
|
+
flex: 0 0 auto;
|
|
38544
|
+
min-width: 0;
|
|
38545
|
+
}
|
|
38546
|
+
.cn-object-row__lead[data-v-6e2b35c2] {
|
|
38547
|
+
font-weight: 600;
|
|
38548
|
+
}
|
|
38549
|
+
.cn-object-row__checkbox[data-v-6e2b35c2] {
|
|
38475
38550
|
flex-shrink: 0;
|
|
38476
38551
|
}
|
|
38477
|
-
.cn-object-row__icon[data-v-
|
|
38552
|
+
.cn-object-row__icon[data-v-6e2b35c2] {
|
|
38478
38553
|
flex-shrink: 0;
|
|
38479
38554
|
display: flex;
|
|
38480
38555
|
align-items: center;
|
|
@@ -38483,38 +38558,38 @@ to {
|
|
|
38483
38558
|
height: 24px;
|
|
38484
38559
|
color: var(--color-text-maxcontrast);
|
|
38485
38560
|
}
|
|
38486
|
-
.cn-object-row__image[data-v-
|
|
38561
|
+
.cn-object-row__image[data-v-6e2b35c2] {
|
|
38487
38562
|
width: 24px;
|
|
38488
38563
|
height: 24px;
|
|
38489
38564
|
object-fit: contain;
|
|
38490
38565
|
border-radius: var(--border-radius);
|
|
38491
38566
|
}
|
|
38492
|
-
.cn-object-row__main[data-v-
|
|
38567
|
+
.cn-object-row__main[data-v-6e2b35c2] {
|
|
38493
38568
|
display: flex;
|
|
38494
38569
|
flex-direction: column;
|
|
38495
38570
|
min-width: 0;
|
|
38496
38571
|
flex: 1;
|
|
38497
38572
|
}
|
|
38498
|
-
.cn-object-row__title[data-v-
|
|
38573
|
+
.cn-object-row__title[data-v-6e2b35c2] {
|
|
38499
38574
|
font-weight: 600;
|
|
38500
38575
|
overflow: hidden;
|
|
38501
38576
|
text-overflow: ellipsis;
|
|
38502
38577
|
white-space: nowrap;
|
|
38503
38578
|
}
|
|
38504
|
-
.cn-object-row__subtitle[data-v-
|
|
38579
|
+
.cn-object-row__subtitle[data-v-6e2b35c2] {
|
|
38505
38580
|
font-size: 13px;
|
|
38506
38581
|
color: var(--color-text-maxcontrast);
|
|
38507
38582
|
overflow: hidden;
|
|
38508
38583
|
text-overflow: ellipsis;
|
|
38509
38584
|
white-space: nowrap;
|
|
38510
38585
|
}
|
|
38511
|
-
.cn-object-row__badges[data-v-
|
|
38586
|
+
.cn-object-row__badges[data-v-6e2b35c2] {
|
|
38512
38587
|
flex-shrink: 0;
|
|
38513
38588
|
display: flex;
|
|
38514
38589
|
align-items: center;
|
|
38515
38590
|
gap: 6px;
|
|
38516
38591
|
}
|
|
38517
|
-
.cn-object-row__actions[data-v-
|
|
38592
|
+
.cn-object-row__actions[data-v-6e2b35c2] {
|
|
38518
38593
|
flex-shrink: 0;
|
|
38519
38594
|
display: flex;
|
|
38520
38595
|
align-items: center;
|
|
@@ -46285,17 +46360,17 @@ a.cn-integration-card__title[data-v-093a874d]:hover {
|
|
|
46285
46360
|
}
|
|
46286
46361
|
|
|
46287
46362
|
|
|
46288
|
-
.cn-user-settings-dialog__body[data-v-
|
|
46363
|
+
.cn-user-settings-dialog__body[data-v-6d3e749e] {
|
|
46289
46364
|
display: flex;
|
|
46290
46365
|
flex-wrap: wrap;
|
|
46291
46366
|
gap: 0 24px;
|
|
46292
46367
|
}
|
|
46293
|
-
.cn-user-settings-dialog__nav[data-v-
|
|
46368
|
+
.cn-user-settings-dialog__nav[data-v-6d3e749e] {
|
|
46294
46369
|
flex: 0 0 200px;
|
|
46295
46370
|
width: 200px;
|
|
46296
46371
|
padding-top: 18px;
|
|
46297
46372
|
}
|
|
46298
|
-
.cn-user-settings-dialog__nav ul[data-v-
|
|
46373
|
+
.cn-user-settings-dialog__nav ul[data-v-6d3e749e] {
|
|
46299
46374
|
display: flex;
|
|
46300
46375
|
flex-direction: column;
|
|
46301
46376
|
gap: 2px;
|
|
@@ -46303,7 +46378,12 @@ a.cn-integration-card__title[data-v-093a874d]:hover {
|
|
|
46303
46378
|
padding: 0;
|
|
46304
46379
|
list-style: none;
|
|
46305
46380
|
}
|
|
46306
|
-
|
|
46381
|
+
|
|
46382
|
+
/* A navigation entry, not a link in running text: no underline, also not
|
|
46383
|
+
on hover. `!important` because a theme's `a { text-decoration }` carries
|
|
46384
|
+
it (thematiq), and a bare `a` with `!important` beats any class. */
|
|
46385
|
+
.cn-user-settings-dialog__nav-link[data-v-6d3e749e],
|
|
46386
|
+
.cn-user-settings-dialog__nav-link[data-v-6d3e749e]:visited {
|
|
46307
46387
|
display: flex;
|
|
46308
46388
|
align-items: center;
|
|
46309
46389
|
gap: 10px;
|
|
@@ -46312,22 +46392,23 @@ a.cn-integration-card__title[data-v-093a874d]:hover {
|
|
|
46312
46392
|
border-radius: var(--border-radius-element, 8px);
|
|
46313
46393
|
font-size: 15px;
|
|
46314
46394
|
color: var(--color-main-text);
|
|
46315
|
-
text-decoration: none;
|
|
46395
|
+
text-decoration: none !important;
|
|
46316
46396
|
}
|
|
46317
|
-
.cn-user-settings-dialog__nav-link[data-v-
|
|
46397
|
+
.cn-user-settings-dialog__nav-link[data-v-6d3e749e]:hover {
|
|
46318
46398
|
background: var(--color-background-hover);
|
|
46399
|
+
text-decoration: none !important;
|
|
46319
46400
|
}
|
|
46320
|
-
.cn-user-settings-dialog__nav-link[data-v-
|
|
46401
|
+
.cn-user-settings-dialog__nav-link[data-v-6d3e749e]:focus-visible {
|
|
46321
46402
|
outline: 2px solid var(--color-primary-element);
|
|
46322
46403
|
outline-offset: 2px;
|
|
46323
46404
|
}
|
|
46324
|
-
.cn-user-settings-dialog__nav-link--active[data-v-
|
|
46325
|
-
.cn-user-settings-dialog__nav-link--active[data-v-
|
|
46405
|
+
.cn-user-settings-dialog__nav-link--active[data-v-6d3e749e],
|
|
46406
|
+
.cn-user-settings-dialog__nav-link--active[data-v-6d3e749e]:hover {
|
|
46326
46407
|
background: var(--color-primary-element-light);
|
|
46327
46408
|
color: var(--color-primary-element-light-text);
|
|
46328
46409
|
font-weight: 600;
|
|
46329
46410
|
}
|
|
46330
|
-
.cn-user-settings-dialog__nav-icon[data-v-
|
|
46411
|
+
.cn-user-settings-dialog__nav-icon[data-v-6d3e749e] {
|
|
46331
46412
|
display: inline-flex;
|
|
46332
46413
|
flex: none;
|
|
46333
46414
|
width: 18px;
|
|
@@ -46335,18 +46416,18 @@ a.cn-integration-card__title[data-v-093a874d]:hover {
|
|
|
46335
46416
|
align-items: center;
|
|
46336
46417
|
justify-content: center;
|
|
46337
46418
|
}
|
|
46338
|
-
.cn-user-settings-dialog__sections[data-v-
|
|
46419
|
+
.cn-user-settings-dialog__sections[data-v-6d3e749e] {
|
|
46339
46420
|
display: flex;
|
|
46340
46421
|
flex: 1 1 380px;
|
|
46341
46422
|
flex-direction: column;
|
|
46342
46423
|
min-width: 0;
|
|
46343
46424
|
}
|
|
46344
|
-
.cn-user-settings-dialog__sections[data-v-
|
|
46425
|
+
.cn-user-settings-dialog__sections[data-v-6d3e749e] .app-settings-section {
|
|
46345
46426
|
margin: 0;
|
|
46346
46427
|
padding: 18px 0;
|
|
46347
46428
|
border-top: 1px solid var(--color-border);
|
|
46348
46429
|
}
|
|
46349
|
-
.cn-user-settings-dialog__sections[data-v-
|
|
46430
|
+
.cn-user-settings-dialog__sections[data-v-6d3e749e] .app-settings-section__name {
|
|
46350
46431
|
margin: 0 0 12px;
|
|
46351
46432
|
font-size: 17px;
|
|
46352
46433
|
font-weight: 700;
|
|
@@ -46354,33 +46435,33 @@ a.cn-integration-card__title[data-v-093a874d]:hover {
|
|
|
46354
46435
|
align-items: center;
|
|
46355
46436
|
gap: 10px;
|
|
46356
46437
|
}
|
|
46357
|
-
.cn-user-settings-dialog__note[data-v-
|
|
46438
|
+
.cn-user-settings-dialog__note[data-v-6d3e749e] {
|
|
46358
46439
|
flex: 1 1 auto;
|
|
46359
46440
|
margin: 0;
|
|
46360
46441
|
font-size: 14px;
|
|
46361
46442
|
color: var(--color-text-maxcontrast);
|
|
46362
46443
|
}
|
|
46363
|
-
.cn-user-settings-dialog__nc-links[data-v-
|
|
46444
|
+
.cn-user-settings-dialog__nc-links[data-v-6d3e749e] {
|
|
46364
46445
|
margin-bottom: 2px;
|
|
46365
46446
|
}
|
|
46366
|
-
.cn-user-settings-dialog__group[data-v-
|
|
46447
|
+
.cn-user-settings-dialog__group[data-v-6d3e749e] {
|
|
46367
46448
|
margin: 10px 0 2px;
|
|
46368
46449
|
padding: 0 12px;
|
|
46369
46450
|
font-size: 15px;
|
|
46370
46451
|
font-weight: 600;
|
|
46371
46452
|
color: var(--color-main-text);
|
|
46372
46453
|
}
|
|
46373
|
-
.cn-user-settings-dialog__group-sections[data-v-
|
|
46454
|
+
.cn-user-settings-dialog__group-sections[data-v-6d3e749e] {
|
|
46374
46455
|
padding-inline-start: 12px;
|
|
46375
46456
|
}
|
|
46376
|
-
.cn-user-settings-dialog__heading-icon[data-v-
|
|
46457
|
+
.cn-user-settings-dialog__heading-icon[data-v-6d3e749e] {
|
|
46377
46458
|
display: inline-flex;
|
|
46378
46459
|
order: -1;
|
|
46379
46460
|
color: var(--color-text-maxcontrast);
|
|
46380
46461
|
}
|
|
46381
46462
|
|
|
46382
46463
|
/* One section at a time: the others are mounted but hidden. */
|
|
46383
|
-
.cn-user-settings-dialog__sections[data-v-
|
|
46464
|
+
.cn-user-settings-dialog__sections[data-v-6d3e749e] .app-settings-section[hidden] {
|
|
46384
46465
|
display: none;
|
|
46385
46466
|
}
|
|
46386
46467
|
|
|
@@ -65,6 +65,23 @@ async function fetchGroupMembers(axios, groupId) {
|
|
|
65
65
|
return Array.isArray(users) ? users : Object.values(users)
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
/**
|
|
69
|
+
* Every user the reader may list, with their details: all users for an
|
|
70
|
+
* admin, the users of their groups for a sub-admin. Refused for others.
|
|
71
|
+
*
|
|
72
|
+
* @param {object} axios The axios instance.
|
|
73
|
+
* @param {{limit?: number}} [options] How many to read.
|
|
74
|
+
* @return {Promise<Array<object>>} Nextcloud's user details, one per user.
|
|
75
|
+
*/
|
|
76
|
+
async function fetchUsers(axios, options = {}) {
|
|
77
|
+
const res = await axios.get(generateOcsUrl('cloud/users/details'), {
|
|
78
|
+
params: { limit: options.limit || 500, format: 'json' },
|
|
79
|
+
headers: OCS_HEADERS,
|
|
80
|
+
});
|
|
81
|
+
const users = (ocsData(res) && ocsData(res).users) || {};
|
|
82
|
+
return Array.isArray(users) ? users : Object.values(users)
|
|
83
|
+
}
|
|
84
|
+
|
|
68
85
|
/**
|
|
69
86
|
* Whether a user is in today: an out-of-office period that runs now (the
|
|
70
87
|
* dav app's absence, Nextcloud 28 and later), else their user status.
|
|
@@ -117,5 +134,5 @@ async function fetchStatuses(axios) {
|
|
|
117
134
|
}
|
|
118
135
|
}
|
|
119
136
|
|
|
120
|
-
export { fetchGroupMembers, fetchGroups, fetchPresence, fetchStatuses };
|
|
137
|
+
export { fetchGroupMembers, fetchGroups, fetchPresence, fetchStatuses, fetchUsers };
|
|
121
138
|
//# sourceMappingURL=nextcloudDirectory.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nextcloudDirectory.js","sources":["../../../src/utils/nextcloudDirectory.js"],"sourcesContent":["/**\n * SPDX-FileCopyrightText: 2026 Conduction B.V.\n * SPDX-License-Identifier: EUPL-1.2\n */\n\nimport { generateOcsUrl } from '@nextcloud/router'\n\n/**\n * Nextcloud's own directory: groups, the users in a group, and whether a\n * user is in today. Read through the OCS API with the reader's session, so\n * Nextcloud decides what the reader may see (listing a group's members needs\n * an admin or the group's sub-admin).\n *\n * @module utils/nextcloudDirectory\n */\n\nconst OCS_HEADERS = { 'OCS-APIRequest': 'true' }\n\n/**\n * The `ocs.data` of an OCS response, or null.\n *\n * @param {object} res An axios response.\n * @return {object|null}\n */\nfunction ocsData(res) {\n\treturn (res && res.data && res.data.ocs && res.data.ocs.data) || null\n}\n\n/**\n * The groups, with their member counts.\n *\n * @param {object} axios The axios instance.\n * @param {{search?: string, limit?: number}} [options] Narrowing.\n * @return {Promise<Array<{id: string, name: string, count: number}>>}\n * @spec openspec/changes/index-groups-users-source/specs/index-page/spec.md#requirement-an-index-page-can-list-nextcloud-groups-and-their-members\n */\nexport async function fetchGroups(axios, options = {}) {\n\tconst res = await axios.get(generateOcsUrl('cloud/groups/details'), {\n\t\tparams: { search: options.search || '', limit: options.limit || 200, format: 'json' },\n\t\theaders: OCS_HEADERS,\n\t})\n\tconst groups = (ocsData(res) && ocsData(res).groups) || []\n\treturn groups.map((group) => ({\n\t\tid: String(group.id),\n\t\tname: group.displayname || String(group.id),\n\t\tcount: Number(group.usercount) || 0,\n\t}))\n}\n\n/**\n * The members of one group, with their details.\n *\n * @param {object} axios The axios instance.\n * @param {string} groupId The group id.\n * @return {Promise<Array<object>>} Nextcloud's user details, one per member.\n * @spec openspec/changes/index-groups-users-source/specs/index-page/spec.md#requirement-an-index-page-can-list-nextcloud-groups-and-their-members\n */\nexport async function fetchGroupMembers(axios, groupId) {\n\tconst res = await axios.get(generateOcsUrl('cloud/groups/{groupId}/users/details', { groupId }), {\n\t\tparams: { format: 'json' },\n\t\theaders: OCS_HEADERS,\n\t})\n\tconst users = (ocsData(res) && ocsData(res).users) || {}\n\treturn Array.isArray(users) ? users : Object.values(users)\n}\n\n/**\n * Whether a user is in today: an out-of-office period that runs now (the\n * dav app's absence, Nextcloud 28 and later), else their user status.\n *\n * @param {object} axios The axios instance.\n * @param {string} userId The user id.\n * @param {object|null} status The user's entry from the user status list, or null.\n * @return {Promise<{state: string, until: (string|null), message: string}>}\n * `state` is `absent` (with `until`, an ISO date), `away`, `present` or `unknown`.\n * @spec openspec/changes/index-groups-users-source/specs/index-page/spec.md#requirement-an-index-page-can-list-nextcloud-groups-and-their-members\n */\nexport async function fetchPresence(axios, userId, status) {\n\ttry {\n\t\tconst res = await axios.get(generateOcsUrl('apps/dav/api/v1/outOfOffice/{userId}/now', { userId }), { params: { format: 'json' }, headers: OCS_HEADERS })\n\t\tconst ooo = ocsData(res)\n\t\tif (ooo && ooo.endDate) {\n\t\t\tconst end = typeof ooo.endDate === 'number' ? new Date(ooo.endDate * 1000) : new Date(ooo.endDate)\n\t\t\treturn { state: 'absent', until: Number.isNaN(end.getTime()) ? null : end.toISOString().slice(0, 10), message: ooo.shortMessage || '' }\n\t\t}\n\t} catch {\n\t\t// 404: no absence now, or an instance without the absence API.\n\t}\n\tif (status && typeof status === 'object') {\n\t\tconst message = typeof status.message === 'string' ? status.message : ''\n\t\tif (status.status === 'online') {\n\t\t\treturn { state: 'present', until: null, message }\n\t\t}\n\t\tif (status.status === 'away' || status.status === 'dnd') {\n\t\t\treturn { state: 'away', until: null, message }\n\t\t}\n\t}\n\treturn { state: 'unknown', until: null, message: '' }\n}\n\n/**\n * The user statuses Nextcloud shares with the reader, by user id. Empty when\n * the user status app is off.\n *\n * @param {object} axios The axios instance.\n * @return {Promise<Record<string, object>>}\n * @spec openspec/changes/index-groups-users-source/specs/index-page/spec.md#requirement-an-index-page-can-list-nextcloud-groups-and-their-members\n */\nexport async function fetchStatuses(axios) {\n\ttry {\n\t\tconst res = await axios.get(generateOcsUrl('apps/user_status/api/v1/statuses'), { params: { limit: 500, format: 'json' }, headers: OCS_HEADERS })\n\t\tconst list = ocsData(res) || []\n\t\treturn Object.fromEntries((Array.isArray(list) ? list : []).map((entry) => [entry.userId, entry]))\n\t} catch {\n\t\treturn {}\n\t}\n}\n"],"names":[],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,WAAW,GAAG,EAAE,gBAAgB,EAAE,MAAM,GAAE;AAChD;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,OAAO,CAAC,GAAG,EAAE;AACtB,CAAC,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,KAAK,IAAI;AACtE,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,eAAe,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,EAAE,EAAE;AACvD,CAAC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,sBAAsB,CAAC,EAAE;AACrE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE;AACvF,EAAE,OAAO,EAAE,WAAW;AACtB,EAAE,EAAC;AACH,CAAC,MAAM,MAAM,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,KAAK,GAAE;AAC3D,CAAC,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,MAAM;AAC/B,EAAE,EAAE,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;AACtB,EAAE,IAAI,EAAE,KAAK,CAAC,WAAW,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;AAC7C,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC;AACrC,EAAE,CAAC,CAAC;AACJ,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,eAAe,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE;AACxD,CAAC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,sCAAsC,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE;AAClG,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE;AAC5B,EAAE,OAAO,EAAE,WAAW;AACtB,EAAE,EAAC;AACH,CAAC,MAAM,KAAK,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,KAAK,GAAE;AACzD,CAAC,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;AAC3D,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,eAAe,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE;AAC3D,CAAC,IAAI;AACL,EAAE,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,0CAA0C,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,EAAC;AAC3J,EAAE,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAC;AAC1B,EAAE,IAAI,GAAG,IAAI,GAAG,CAAC,OAAO,EAAE;AAC1B,GAAG,MAAM,GAAG,GAAG,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAC;AACrG,GAAG,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,GAAG,IAAI,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,YAAY,IAAI,EAAE,EAAE;AAC1I,GAAG;AACH,EAAE,CAAC,MAAM;AACT;AACA,EAAE;AACF,CAAC,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE;AAC3C,EAAE,MAAM,OAAO,GAAG,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ,GAAG,MAAM,CAAC,OAAO,GAAG,GAAE;AAC1E,EAAE,IAAI,MAAM,CAAC,MAAM,KAAK,QAAQ,EAAE;AAClC,GAAG,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE;AACpD,GAAG;AACH,EAAE,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,KAAK,EAAE;AAC3D,GAAG,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE;AACjD,GAAG;AACH,EAAE;AACF,CAAC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE;AACtD,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,eAAe,aAAa,CAAC,KAAK,EAAE;AAC3C,CAAC,IAAI;AACL,EAAE,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,kCAAkC,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,EAAC;AACnJ,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,GAAE;AACjC,EAAE,OAAO,MAAM,CAAC,WAAW,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,EAAE,EAAE,GAAG,CAAC,CAAC,KAAK,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;AACpG,EAAE,CAAC,MAAM;AACT,EAAE,OAAO,EAAE;AACX,EAAE;AACF;;;;"}
|
|
1
|
+
{"version":3,"file":"nextcloudDirectory.js","sources":["../../../src/utils/nextcloudDirectory.js"],"sourcesContent":["/**\n * SPDX-FileCopyrightText: 2026 Conduction B.V.\n * SPDX-License-Identifier: EUPL-1.2\n */\n\nimport { generateOcsUrl } from '@nextcloud/router'\n\n/**\n * Nextcloud's own directory: groups, the users in a group, and whether a\n * user is in today. Read through the OCS API with the reader's session, so\n * Nextcloud decides what the reader may see (listing a group's members needs\n * an admin or the group's sub-admin).\n *\n * @module utils/nextcloudDirectory\n */\n\nconst OCS_HEADERS = { 'OCS-APIRequest': 'true' }\n\n/**\n * The `ocs.data` of an OCS response, or null.\n *\n * @param {object} res An axios response.\n * @return {object|null}\n */\nfunction ocsData(res) {\n\treturn (res && res.data && res.data.ocs && res.data.ocs.data) || null\n}\n\n/**\n * The groups, with their member counts.\n *\n * @param {object} axios The axios instance.\n * @param {{search?: string, limit?: number}} [options] Narrowing.\n * @return {Promise<Array<{id: string, name: string, count: number}>>}\n * @spec openspec/changes/index-groups-users-source/specs/index-page/spec.md#requirement-an-index-page-can-list-nextcloud-groups-and-their-members\n */\nexport async function fetchGroups(axios, options = {}) {\n\tconst res = await axios.get(generateOcsUrl('cloud/groups/details'), {\n\t\tparams: { search: options.search || '', limit: options.limit || 200, format: 'json' },\n\t\theaders: OCS_HEADERS,\n\t})\n\tconst groups = (ocsData(res) && ocsData(res).groups) || []\n\treturn groups.map((group) => ({\n\t\tid: String(group.id),\n\t\tname: group.displayname || String(group.id),\n\t\tcount: Number(group.usercount) || 0,\n\t}))\n}\n\n/**\n * The members of one group, with their details.\n *\n * @param {object} axios The axios instance.\n * @param {string} groupId The group id.\n * @return {Promise<Array<object>>} Nextcloud's user details, one per member.\n * @spec openspec/changes/index-groups-users-source/specs/index-page/spec.md#requirement-an-index-page-can-list-nextcloud-groups-and-their-members\n */\nexport async function fetchGroupMembers(axios, groupId) {\n\tconst res = await axios.get(generateOcsUrl('cloud/groups/{groupId}/users/details', { groupId }), {\n\t\tparams: { format: 'json' },\n\t\theaders: OCS_HEADERS,\n\t})\n\tconst users = (ocsData(res) && ocsData(res).users) || {}\n\treturn Array.isArray(users) ? users : Object.values(users)\n}\n\n/**\n * Every user the reader may list, with their details: all users for an\n * admin, the users of their groups for a sub-admin. Refused for others.\n *\n * @param {object} axios The axios instance.\n * @param {{limit?: number}} [options] How many to read.\n * @return {Promise<Array<object>>} Nextcloud's user details, one per user.\n */\nexport async function fetchUsers(axios, options = {}) {\n\tconst res = await axios.get(generateOcsUrl('cloud/users/details'), {\n\t\tparams: { limit: options.limit || 500, format: 'json' },\n\t\theaders: OCS_HEADERS,\n\t})\n\tconst users = (ocsData(res) && ocsData(res).users) || {}\n\treturn Array.isArray(users) ? users : Object.values(users)\n}\n\n/**\n * Whether a user is in today: an out-of-office period that runs now (the\n * dav app's absence, Nextcloud 28 and later), else their user status.\n *\n * @param {object} axios The axios instance.\n * @param {string} userId The user id.\n * @param {object|null} status The user's entry from the user status list, or null.\n * @return {Promise<{state: string, until: (string|null), message: string}>}\n * `state` is `absent` (with `until`, an ISO date), `away`, `present` or `unknown`.\n * @spec openspec/changes/index-groups-users-source/specs/index-page/spec.md#requirement-an-index-page-can-list-nextcloud-groups-and-their-members\n */\nexport async function fetchPresence(axios, userId, status) {\n\ttry {\n\t\tconst res = await axios.get(generateOcsUrl('apps/dav/api/v1/outOfOffice/{userId}/now', { userId }), { params: { format: 'json' }, headers: OCS_HEADERS })\n\t\tconst ooo = ocsData(res)\n\t\tif (ooo && ooo.endDate) {\n\t\t\tconst end = typeof ooo.endDate === 'number' ? new Date(ooo.endDate * 1000) : new Date(ooo.endDate)\n\t\t\treturn { state: 'absent', until: Number.isNaN(end.getTime()) ? null : end.toISOString().slice(0, 10), message: ooo.shortMessage || '' }\n\t\t}\n\t} catch {\n\t\t// 404: no absence now, or an instance without the absence API.\n\t}\n\tif (status && typeof status === 'object') {\n\t\tconst message = typeof status.message === 'string' ? status.message : ''\n\t\tif (status.status === 'online') {\n\t\t\treturn { state: 'present', until: null, message }\n\t\t}\n\t\tif (status.status === 'away' || status.status === 'dnd') {\n\t\t\treturn { state: 'away', until: null, message }\n\t\t}\n\t}\n\treturn { state: 'unknown', until: null, message: '' }\n}\n\n/**\n * The user statuses Nextcloud shares with the reader, by user id. Empty when\n * the user status app is off.\n *\n * @param {object} axios The axios instance.\n * @return {Promise<Record<string, object>>}\n * @spec openspec/changes/index-groups-users-source/specs/index-page/spec.md#requirement-an-index-page-can-list-nextcloud-groups-and-their-members\n */\nexport async function fetchStatuses(axios) {\n\ttry {\n\t\tconst res = await axios.get(generateOcsUrl('apps/user_status/api/v1/statuses'), { params: { limit: 500, format: 'json' }, headers: OCS_HEADERS })\n\t\tconst list = ocsData(res) || []\n\t\treturn Object.fromEntries((Array.isArray(list) ? list : []).map((entry) => [entry.userId, entry]))\n\t} catch {\n\t\treturn {}\n\t}\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SPDX-FileCopyrightText: 2026 Conduction B.V.
|
|
3
|
+
* SPDX-License-Identifier: EUPL-1.2
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Read an order a manifest writes into the `[{ key, order }]` list a self-fetch
|
|
8
|
+
* index page sorts by. Accepted forms:
|
|
9
|
+
*
|
|
10
|
+
* - `"title"` ascending, `"-createdAt"` descending, `"priority:desc"`;
|
|
11
|
+
* - several of those, comma separated, in priority order (`"-priority,title"`);
|
|
12
|
+
* - an OpenRegister `_order` map, `{ "priority": "desc", "title": "asc" }`;
|
|
13
|
+
* - a `[{ key, order? }]` list.
|
|
14
|
+
*
|
|
15
|
+
* @param {string|object|Array|null|undefined} value The order.
|
|
16
|
+
* @return {Array<{key: string, order: 'asc'|'desc'}>} The sort keys, possibly empty.
|
|
17
|
+
*/
|
|
18
|
+
function orderToSortKeys(value) {
|
|
19
|
+
const direction = (order) => (String(order || '').toLowerCase() === 'desc' ? 'desc' : 'asc');
|
|
20
|
+
if (Array.isArray(value)) {
|
|
21
|
+
return value
|
|
22
|
+
.filter((entry) => entry && typeof entry.key === 'string' && entry.key !== '')
|
|
23
|
+
.map((entry) => ({ key: entry.key, order: direction(entry.order) }))
|
|
24
|
+
}
|
|
25
|
+
if (value && typeof value === 'object') {
|
|
26
|
+
return Object.entries(value)
|
|
27
|
+
.filter(([key]) => key !== '')
|
|
28
|
+
.map(([key, order]) => ({ key, order: direction(order) }))
|
|
29
|
+
}
|
|
30
|
+
if (typeof value !== 'string') {
|
|
31
|
+
return []
|
|
32
|
+
}
|
|
33
|
+
return value.split(',')
|
|
34
|
+
.map((part) => part.trim())
|
|
35
|
+
.filter(Boolean)
|
|
36
|
+
.map((part) => {
|
|
37
|
+
if (part.startsWith('-')) {
|
|
38
|
+
return { key: part.slice(1), order: 'desc' }
|
|
39
|
+
}
|
|
40
|
+
const [key, order] = part.split(':');
|
|
41
|
+
return { key, order: direction(order) }
|
|
42
|
+
})
|
|
43
|
+
.filter((entry) => entry.key !== '')
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Whether two sort key lists order the same way.
|
|
48
|
+
*
|
|
49
|
+
* @param {Array<{key: string, order: string}>} a One list.
|
|
50
|
+
* @param {Array<{key: string, order: string}>} b The other.
|
|
51
|
+
* @return {boolean} True when they name the same keys, directions and priority.
|
|
52
|
+
*/
|
|
53
|
+
function sameSortKeys(a, b) {
|
|
54
|
+
const left = Array.isArray(a) ? a : [];
|
|
55
|
+
const right = Array.isArray(b) ? b : [];
|
|
56
|
+
return left.length === right.length
|
|
57
|
+
&& left.every((entry, index) => entry.key === right[index].key && (entry.order || 'asc') === (right[index].order || 'asc'))
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export { orderToSortKeys, sameSortKeys };
|
|
61
|
+
//# sourceMappingURL=sortOrder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sortOrder.js","sources":["../../../src/utils/sortOrder.js"],"sourcesContent":["/**\n * SPDX-FileCopyrightText: 2026 Conduction B.V.\n * SPDX-License-Identifier: EUPL-1.2\n */\n\n/**\n * Read an order a manifest writes into the `[{ key, order }]` list a self-fetch\n * index page sorts by. Accepted forms:\n *\n * - `\"title\"` ascending, `\"-createdAt\"` descending, `\"priority:desc\"`;\n * - several of those, comma separated, in priority order (`\"-priority,title\"`);\n * - an OpenRegister `_order` map, `{ \"priority\": \"desc\", \"title\": \"asc\" }`;\n * - a `[{ key, order? }]` list.\n *\n * @param {string|object|Array|null|undefined} value The order.\n * @return {Array<{key: string, order: 'asc'|'desc'}>} The sort keys, possibly empty.\n */\nexport function orderToSortKeys(value) {\n\tconst direction = (order) => (String(order || '').toLowerCase() === 'desc' ? 'desc' : 'asc')\n\tif (Array.isArray(value)) {\n\t\treturn value\n\t\t\t.filter((entry) => entry && typeof entry.key === 'string' && entry.key !== '')\n\t\t\t.map((entry) => ({ key: entry.key, order: direction(entry.order) }))\n\t}\n\tif (value && typeof value === 'object') {\n\t\treturn Object.entries(value)\n\t\t\t.filter(([key]) => key !== '')\n\t\t\t.map(([key, order]) => ({ key, order: direction(order) }))\n\t}\n\tif (typeof value !== 'string') {\n\t\treturn []\n\t}\n\treturn value.split(',')\n\t\t.map((part) => part.trim())\n\t\t.filter(Boolean)\n\t\t.map((part) => {\n\t\t\tif (part.startsWith('-')) {\n\t\t\t\treturn { key: part.slice(1), order: 'desc' }\n\t\t\t}\n\t\t\tconst [key, order] = part.split(':')\n\t\t\treturn { key, order: direction(order) }\n\t\t})\n\t\t.filter((entry) => entry.key !== '')\n}\n\n/**\n * Whether two sort key lists order the same way.\n *\n * @param {Array<{key: string, order: string}>} a One list.\n * @param {Array<{key: string, order: string}>} b The other.\n * @return {boolean} True when they name the same keys, directions and priority.\n */\nexport function sameSortKeys(a, b) {\n\tconst left = Array.isArray(a) ? a : []\n\tconst right = Array.isArray(b) ? b : []\n\treturn left.length === right.length\n\t\t&& left.every((entry, index) => entry.key === right[index].key && (entry.order || 'asc') === (right[index].order || 'asc'))\n}\n"],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,eAAe,CAAC,KAAK,EAAE;AACvC,CAAC,MAAM,SAAS,GAAG,CAAC,KAAK,MAAM,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,KAAK,MAAM,GAAG,MAAM,GAAG,KAAK,EAAC;AAC7F,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;AAC3B,EAAE,OAAO,KAAK;AACd,IAAI,MAAM,CAAC,CAAC,KAAK,KAAK,KAAK,IAAI,OAAO,KAAK,CAAC,GAAG,KAAK,QAAQ,IAAI,KAAK,CAAC,GAAG,KAAK,EAAE,CAAC;AACjF,IAAI,GAAG,CAAC,CAAC,KAAK,MAAM,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AACvE,EAAE;AACF,CAAC,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;AACzC,EAAE,OAAO,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;AAC9B,IAAI,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,GAAG,KAAK,EAAE,CAAC;AACjC,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AAC7D,EAAE;AACF,CAAC,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;AAChC,EAAE,OAAO,EAAE;AACX,EAAE;AACF,CAAC,OAAO,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC;AACxB,GAAG,GAAG,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC;AAC7B,GAAG,MAAM,CAAC,OAAO,CAAC;AAClB,GAAG,GAAG,CAAC,CAAC,IAAI,KAAK;AACjB,GAAG,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE;AAC7B,IAAI,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE;AAChD,IAAI;AACJ,GAAG,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,EAAC;AACvC,GAAG,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,CAAC,EAAE;AAC1C,GAAG,CAAC;AACJ,GAAG,MAAM,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,GAAG,KAAK,EAAE,CAAC;AACtC,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE;AACnC,CAAC,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,GAAE;AACvC,CAAC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,GAAE;AACxC,CAAC,OAAO,IAAI,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM;AACpC,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,KAAK,CAAC,GAAG,KAAK,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,KAAK,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,KAAK,IAAI,KAAK,CAAC,CAAC;AAC7H;;;;"}
|