@conduction/nextcloud-vue 2.120.0 → 2.122.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/CnIndexPage/CnIndexPage.vue2.js +53 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +546 -523
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/useNamedSource.js +9 -0
- package/dist/esm/components/CnIndexPage/useNamedSource.js.map +1 -1
- package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue3.js +1 -0
- package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue3.js.map +1 -1
- package/dist/esm/components/CnReadinessChecklist/CnReadinessChecklist.vue.js +9 -0
- package/dist/esm/components/CnReadinessChecklist/CnReadinessChecklist.vue.js.map +1 -0
- package/dist/esm/components/CnReadinessChecklist/CnReadinessChecklist.vue2.js +214 -0
- package/dist/esm/components/CnReadinessChecklist/CnReadinessChecklist.vue2.js.map +1 -0
- package/dist/esm/components/CnReadinessChecklist/CnReadinessChecklist.vue3.js +125 -0
- package/dist/esm/components/CnReadinessChecklist/CnReadinessChecklist.vue3.js.map +1 -0
- package/dist/esm/components/CnSchemaRulesWidget/CnSchemaRulesWidget.vue.js +9 -0
- package/dist/esm/components/CnSchemaRulesWidget/CnSchemaRulesWidget.vue.js.map +1 -0
- package/dist/esm/components/CnSchemaRulesWidget/CnSchemaRulesWidget.vue2.js +163 -0
- package/dist/esm/components/CnSchemaRulesWidget/CnSchemaRulesWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnSchemaRulesWidget/CnSchemaRulesWidget.vue3.js +131 -0
- package/dist/esm/components/CnSchemaRulesWidget/CnSchemaRulesWidget.vue3.js.map +1 -0
- package/dist/esm/components/CnSchemaRulesWidget/schemaRules.js +127 -0
- package/dist/esm/components/CnSchemaRulesWidget/schemaRules.js.map +1 -0
- package/dist/esm/components/CnSearchIndexStatus/CnSearchIndexStatus.vue.js +9 -0
- package/dist/esm/components/CnSearchIndexStatus/CnSearchIndexStatus.vue.js.map +1 -0
- package/dist/esm/components/CnSearchIndexStatus/CnSearchIndexStatus.vue2.js +82 -0
- package/dist/esm/components/CnSearchIndexStatus/CnSearchIndexStatus.vue2.js.map +1 -0
- package/dist/esm/components/CnSearchIndexStatus/CnSearchIndexStatus.vue3.js +61 -0
- package/dist/esm/components/CnSearchIndexStatus/CnSearchIndexStatus.vue3.js.map +1 -0
- package/dist/esm/components/CnSearchIndexStatus/searchIndexStatus.js +60 -0
- package/dist/esm/components/CnSearchIndexStatus/searchIndexStatus.js.map +1 -0
- package/dist/esm/components/CnShippedConfigurationSection/CnShippedConfigurationSection.vue.js +10 -0
- package/dist/esm/components/CnShippedConfigurationSection/CnShippedConfigurationSection.vue.js.map +1 -0
- package/dist/esm/components/CnShippedConfigurationSection/CnShippedConfigurationSection.vue2.js +226 -0
- package/dist/esm/components/CnShippedConfigurationSection/CnShippedConfigurationSection.vue2.js.map +1 -0
- package/dist/esm/components/CnShippedConfigurationSection/CnShippedConfigurationSection.vue3.js +126 -0
- package/dist/esm/components/CnShippedConfigurationSection/CnShippedConfigurationSection.vue3.js.map +1 -0
- package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js +42 -32
- package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js.map +1 -1
- package/dist/esm/composables/indexSources.js +116 -16
- package/dist/esm/composables/indexSources.js.map +1 -1
- package/dist/esm/index.js +4 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/l10n/en.json.js +42 -1
- package/dist/esm/l10n/en.json.js.map +1 -1
- package/dist/esm/l10n/nl.json.js +42 -1
- package/dist/esm/l10n/nl.json.js.map +1 -1
- package/dist/esm/library-style.js +1 -1
- package/dist/esm/nextcloud-vue.css +309 -13
- package/dist/esm/utils/libraryWidgetKeys.js +1 -0
- package/dist/esm/utils/libraryWidgetKeys.js.map +1 -1
- package/dist/nextcloud-vue.cjs.js +14136 -12578
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +309 -13
- package/l10n/en.json +42 -1
- package/l10n/nl.json +42 -1
- package/package.json +1 -1
- package/src/components/CnIndexPage/CnIndexPage.vue +74 -3
- package/src/components/CnIndexPage/useNamedSource.js +9 -0
- package/src/components/CnIndexSidebar/CnIndexSidebar.vue +1 -0
- package/src/components/CnReadinessChecklist/CnReadinessChecklist.vue +335 -0
- package/src/components/CnReadinessChecklist/index.js +9 -0
- package/src/components/CnSchemaRulesWidget/CnSchemaRulesWidget.vue +300 -0
- package/src/components/CnSchemaRulesWidget/index.js +10 -0
- package/src/components/CnSchemaRulesWidget/schemaRules.js +123 -0
- package/src/components/CnSearchIndexStatus/CnSearchIndexStatus.vue +160 -0
- package/src/components/CnSearchIndexStatus/index.js +10 -0
- package/src/components/CnSearchIndexStatus/searchIndexStatus.js +56 -0
- package/src/components/CnShippedConfigurationSection/CnShippedConfigurationSection.vue +328 -0
- package/src/components/CnShippedConfigurationSection/index.js +9 -0
- package/src/components/CnWidgetGrid/registerDashboardWidgets.js +10 -0
- package/src/components/index.js +4 -0
- package/src/composables/indexSources.js +116 -16
- package/src/css/index-page.css +7 -0
- package/src/css/look-board-detail.css +27 -0
- package/src/css/look-board-index.css +108 -12
- package/src/css/look-board.css +27 -1
- package/src/index.js +4 -0
- package/src/utils/libraryWidgetKeys.js +1 -0
|
@@ -37,6 +37,7 @@ import CnRelatedObjectsWidgetForm from '../CnRelatedObjectsWidgetForm/CnRelatedO
|
|
|
37
37
|
import CnRetentionWidget from '../CnRetentionWidget/CnRetentionWidget.vue'
|
|
38
38
|
import CnSavedViewWidget2 from '../CnSavedViewWidget/CnSavedViewWidget.vue'
|
|
39
39
|
import CnSavedViewWidgetForm2 from '../CnSavedViewWidgetForm/CnSavedViewWidgetForm.vue'
|
|
40
|
+
import CnSchemaRulesWidget from '../CnSchemaRulesWidget/CnSchemaRulesWidget.vue'
|
|
40
41
|
import CnStackedBarWidget from '../CnStackedBarWidget/CnStackedBarWidget.vue'
|
|
41
42
|
import CnStackedBarWidgetForm from '../CnStackedBarWidgetForm/CnStackedBarWidgetForm.vue'
|
|
42
43
|
import CnStagesWidget from '../CnStagesWidget/CnStagesWidget.vue'
|
|
@@ -311,6 +312,15 @@ registerDashboardWidget('retention', {
|
|
|
311
312
|
ownsTitle: true,
|
|
312
313
|
})
|
|
313
314
|
|
|
315
|
+
registerDashboardWidget('schema-rules', {
|
|
316
|
+
renderer: CnSchemaRulesWidget,
|
|
317
|
+
form: null,
|
|
318
|
+
defaultContent: { register: '', schema: '', objectId: '' },
|
|
319
|
+
displayName: 'Schema rules',
|
|
320
|
+
icon: 'ScaleBalance',
|
|
321
|
+
surfaces: ['detail-page'],
|
|
322
|
+
})
|
|
323
|
+
|
|
314
324
|
registerDashboardWidget('plan', {
|
|
315
325
|
renderer: CnPlanWidget,
|
|
316
326
|
form: null,
|
package/src/components/index.js
CHANGED
|
@@ -464,3 +464,7 @@ export { CnBrandStripe } from './CnBrandStripe/index.js'
|
|
|
464
464
|
export { CnDuplicateWarning } from './CnDuplicateWarning/index.js'
|
|
465
465
|
export { CnEndpointNotice } from './CnEndpointNotice/index.js'
|
|
466
466
|
export { CnCountTablesReport } from './CnCountTablesReport/index.js'
|
|
467
|
+
export { CnShippedConfigurationSection } from './CnShippedConfigurationSection/index.js'
|
|
468
|
+
export { CnSearchIndexStatus } from './CnSearchIndexStatus/index.js'
|
|
469
|
+
export { CnSchemaRulesWidget } from './CnSchemaRulesWidget/index.js'
|
|
470
|
+
export { CnReadinessChecklist } from './CnReadinessChecklist/index.js'
|
|
@@ -737,6 +737,14 @@ function readRowsPath(body, path) {
|
|
|
737
737
|
return String(path).split('.').reduce((value, key) => (value && typeof value === 'object' ? value[key] : undefined), body)
|
|
738
738
|
}
|
|
739
739
|
|
|
740
|
+
/**
|
|
741
|
+
* The `sourceConfig` keys the endpoint source reads itself; every other key
|
|
742
|
+
* goes along as a query parameter.
|
|
743
|
+
*
|
|
744
|
+
* @type {Array<string>}
|
|
745
|
+
*/
|
|
746
|
+
const ENDPOINT_SOURCE_KEYS = ['url', 'rowsPath', 'totalPath', 'searchParam', 'searchFields', 'notePath', 'noteText', 'refusedText']
|
|
747
|
+
|
|
740
748
|
/**
|
|
741
749
|
* The endpoint source: rows from an app's own endpoint
|
|
742
750
|
* (`entitySource: "endpoint"`), for a list that is not OpenRegister objects,
|
|
@@ -759,25 +767,46 @@ function readRowsPath(body, path) {
|
|
|
759
767
|
* request with that tab's filter, its total read at `sourceConfig.totalPath`
|
|
760
768
|
* (`total` by default), else the number of rows the answer holds.
|
|
761
769
|
*
|
|
770
|
+
* Three more keys shape what the page says around the rows:
|
|
771
|
+
* - `searchParam`: the page's search box sends its term as this parameter
|
|
772
|
+
* (`sender`), so the endpoint does the searching.
|
|
773
|
+
* - `notePath` and `noteText`: a value read off the answer (`filterOrder`) and
|
|
774
|
+
* the sentence it is said in ("Filters run in this order: {order}", its one
|
|
775
|
+
* placeholder taking the value); a list
|
|
776
|
+
* is joined with commas. Shown above the rows.
|
|
777
|
+
* - `refusedText`: what a refused load (403) says when the endpoint gave no
|
|
778
|
+
* `message` of its own. A refusal is not an empty list, so the page shows it
|
|
779
|
+
* instead of the rows, and a failed load is not one either.
|
|
780
|
+
* - `searchFields`: the filters the endpoint takes, in the same shape a
|
|
781
|
+
* registered source declares them (`{ status: { param: 'status', single:
|
|
782
|
+
* true } }`), so a filter strip or sidebar on the page narrows the
|
|
783
|
+
* endpoint's query.
|
|
784
|
+
*
|
|
785
|
+
* @param {object} [declared] The page's `sourceConfig`, for `searchParam` and `searchFields`.
|
|
786
|
+
* @param {object} [context] The page's helpers; `translate` is the app's catalogue.
|
|
762
787
|
* @return {object} The source adapter.
|
|
763
788
|
* @spec openspec/changes/index-endpoint-source/specs/index-page/spec.md#requirement-an-index-page-can-list-rows-from-an-app-endpoint
|
|
764
789
|
*/
|
|
765
|
-
function endpointSource() {
|
|
766
|
-
const state = reactive({ rows: [], loading: false })
|
|
790
|
+
function endpointSource(declared = {}, context = {}) {
|
|
791
|
+
const state = reactive({ rows: [], loading: false, refusal: '', failed: false, note: '' })
|
|
792
|
+
const translate = typeof context.translate === 'function' ? context.translate : (text) => text
|
|
793
|
+
const searchParam = typeof declared.searchParam === 'string' && declared.searchParam !== '' ? declared.searchParam : null
|
|
794
|
+
const searchFields = declared.searchFields && typeof declared.searchFields === 'object' && !Array.isArray(declared.searchFields) ? declared.searchFields : null
|
|
767
795
|
let seq = 0
|
|
768
796
|
let warned = false
|
|
769
797
|
|
|
770
798
|
/**
|
|
771
|
-
* The query parameters for a config: every key but the
|
|
772
|
-
* empty values left out, a list joined by
|
|
799
|
+
* The query parameters for a config: every key but the source's own
|
|
800
|
+
* (`url`, the paths, the texts), empty values left out, a list joined by
|
|
801
|
+
* commas.
|
|
773
802
|
*
|
|
774
|
-
* @param {object}
|
|
803
|
+
* @param {object} config The config.
|
|
775
804
|
* @return {object} The parameters.
|
|
776
805
|
*/
|
|
777
|
-
const paramsOf = (
|
|
806
|
+
const paramsOf = (config) => {
|
|
778
807
|
const params = {}
|
|
779
|
-
for (const [key, value] of Object.entries(
|
|
780
|
-
if (value === undefined || value === null || value === '') {
|
|
808
|
+
for (const [key, value] of Object.entries(config)) {
|
|
809
|
+
if (ENDPOINT_SOURCE_KEYS.includes(key) || value === undefined || value === null || value === '') {
|
|
781
810
|
continue
|
|
782
811
|
}
|
|
783
812
|
params[key] = Array.isArray(value) ? value.join(',') : (typeof value === 'object' ? JSON.stringify(value) : value)
|
|
@@ -797,15 +826,61 @@ function endpointSource() {
|
|
|
797
826
|
return typeof url === 'string' && url !== '' && !Object.hasOwn(config, 'entitySource')
|
|
798
827
|
}
|
|
799
828
|
|
|
829
|
+
/**
|
|
830
|
+
* The note read off an answer, in the page's sentence.
|
|
831
|
+
*
|
|
832
|
+
* @param {object} body The response body.
|
|
833
|
+
* @param {string} [path] Where the value sits.
|
|
834
|
+
* @param {string} [text] The sentence, with one `{placeholder}` where the value goes.
|
|
835
|
+
* @return {string} The note, or '' when there is nothing to say.
|
|
836
|
+
*/
|
|
837
|
+
const noteOf = (body, path, text) => {
|
|
838
|
+
if (!path || !body || typeof body !== 'object' || Array.isArray(body)) {
|
|
839
|
+
return ''
|
|
840
|
+
}
|
|
841
|
+
const raw = readRowsPath(body, path)
|
|
842
|
+
const value = Array.isArray(raw) ? raw.filter((v) => v !== null && v !== undefined && v !== '').join(', ') : (raw === null || raw === undefined ? '' : String(raw))
|
|
843
|
+
if (value === '') {
|
|
844
|
+
return ''
|
|
845
|
+
}
|
|
846
|
+
return text ? translate(text).replace(/\{\w+\}/, value) : value
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
/**
|
|
850
|
+
* The sentence a refused load is said in: the endpoint's own, else the
|
|
851
|
+
* page's, else the library's.
|
|
852
|
+
*
|
|
853
|
+
* @param {object} body The refusal's body.
|
|
854
|
+
* @param {string} [text] The page's `refusedText`.
|
|
855
|
+
* @return {string} The sentence.
|
|
856
|
+
*/
|
|
857
|
+
const refusalOf = (body, text) => {
|
|
858
|
+
if (body && typeof body.message === 'string' && body.message.trim() !== '') {
|
|
859
|
+
return body.message
|
|
860
|
+
}
|
|
861
|
+
return text ? translate(text) : t('nextcloud-vue', 'You may not read this list.')
|
|
862
|
+
}
|
|
863
|
+
|
|
800
864
|
return {
|
|
865
|
+
/**
|
|
866
|
+
* The parameter the page's search term is sent as, or null when this
|
|
867
|
+
* endpoint takes no search.
|
|
868
|
+
*/
|
|
869
|
+
searchParam,
|
|
870
|
+
|
|
871
|
+
/**
|
|
872
|
+
* The page filters this endpoint takes, and the parameter each becomes.
|
|
873
|
+
*/
|
|
874
|
+
searchFields,
|
|
875
|
+
|
|
801
876
|
/**
|
|
802
877
|
* Fetch the rows.
|
|
803
878
|
*
|
|
804
879
|
* @param {object} config The page's source config with the tab filter merged in.
|
|
805
|
-
* @return {Promise<void>} Resolves when loaded; a failed request leaves no rows and rethrows.
|
|
880
|
+
* @return {Promise<void>} Resolves when loaded or refused; a failed request leaves no rows and rethrows.
|
|
806
881
|
*/
|
|
807
882
|
load: async (config) => {
|
|
808
|
-
const { url, rowsPath,
|
|
883
|
+
const { url, rowsPath, notePath, noteText, refusedText } = config || {}
|
|
809
884
|
const mine = ++seq
|
|
810
885
|
if (!requestable(config)) {
|
|
811
886
|
state.rows = []
|
|
@@ -817,7 +892,7 @@ function endpointSource() {
|
|
|
817
892
|
}
|
|
818
893
|
return
|
|
819
894
|
}
|
|
820
|
-
const params = paramsOf(
|
|
895
|
+
const params = paramsOf(config)
|
|
821
896
|
state.loading = true
|
|
822
897
|
try {
|
|
823
898
|
const { default: axios } = await import('@nextcloud/axios')
|
|
@@ -826,12 +901,22 @@ function endpointSource() {
|
|
|
826
901
|
const rows = Array.isArray(body) ? body : readRowsPath(body, rowsPath || 'results')
|
|
827
902
|
if (mine === seq) {
|
|
828
903
|
state.rows = Array.isArray(rows) ? rows : []
|
|
904
|
+
state.refusal = ''
|
|
905
|
+
state.failed = false
|
|
906
|
+
state.note = noteOf(body, notePath, noteText)
|
|
829
907
|
}
|
|
830
908
|
} catch (error) {
|
|
831
|
-
if (mine
|
|
832
|
-
|
|
909
|
+
if (mine !== seq) {
|
|
910
|
+
return
|
|
911
|
+
}
|
|
912
|
+
state.rows = []
|
|
913
|
+
state.note = ''
|
|
914
|
+
const refused = error && error.response && error.response.status === 403
|
|
915
|
+
state.refusal = refused ? refusalOf(error.response.data, refusedText) : ''
|
|
916
|
+
state.failed = !refused
|
|
917
|
+
if (!refused) {
|
|
918
|
+
throw error
|
|
833
919
|
}
|
|
834
|
-
throw error
|
|
835
920
|
} finally {
|
|
836
921
|
if (mine === seq) {
|
|
837
922
|
state.loading = false
|
|
@@ -850,9 +935,9 @@ function endpointSource() {
|
|
|
850
935
|
if (!requestable(config)) {
|
|
851
936
|
return Number.NaN
|
|
852
937
|
}
|
|
853
|
-
const { url, rowsPath, totalPath
|
|
938
|
+
const { url, rowsPath, totalPath } = config
|
|
854
939
|
const { default: axios } = await import('@nextcloud/axios')
|
|
855
|
-
const res = await axios.get(generateUrl(url), { params: paramsOf(
|
|
940
|
+
const res = await axios.get(generateUrl(url), { params: paramsOf(config) })
|
|
856
941
|
const body = res ? res.data : null
|
|
857
942
|
const total = body && typeof body === 'object' && !Array.isArray(body) ? readRowsPath(body, totalPath || 'total') : undefined
|
|
858
943
|
if (typeof total === 'number' && Number.isFinite(total)) {
|
|
@@ -871,6 +956,21 @@ function endpointSource() {
|
|
|
871
956
|
* @return {boolean} Whether a load is in flight.
|
|
872
957
|
*/
|
|
873
958
|
loading: () => state.loading,
|
|
959
|
+
|
|
960
|
+
/**
|
|
961
|
+
* @return {string} The sentence the last load was refused with, or ''.
|
|
962
|
+
*/
|
|
963
|
+
refusal: () => state.refusal,
|
|
964
|
+
|
|
965
|
+
/**
|
|
966
|
+
* @return {boolean} Whether the last load failed for another reason than a refusal.
|
|
967
|
+
*/
|
|
968
|
+
failed: () => state.failed,
|
|
969
|
+
|
|
970
|
+
/**
|
|
971
|
+
* @return {string} The note read off the last answer, or ''.
|
|
972
|
+
*/
|
|
973
|
+
note: () => state.note,
|
|
874
974
|
}
|
|
875
975
|
}
|
|
876
976
|
|
package/src/css/index-page.css
CHANGED
|
@@ -222,6 +222,13 @@
|
|
|
222
222
|
color: var(--color-text-maxcontrast);
|
|
223
223
|
}
|
|
224
224
|
|
|
225
|
+
/* A note the named source read off its answer, above the rows. */
|
|
226
|
+
.cn-index-page__source-note {
|
|
227
|
+
margin: 0 0 8px;
|
|
228
|
+
color: var(--color-text-maxcontrast);
|
|
229
|
+
font-size: 0.9em;
|
|
230
|
+
}
|
|
231
|
+
|
|
225
232
|
.cn-index-page__scope-heading {
|
|
226
233
|
display: flex;
|
|
227
234
|
flex-direction: column;
|
|
@@ -974,3 +974,30 @@
|
|
|
974
974
|
.cn-look-board .cn-tasks-widget .cn-tasks-widget__cell-actions .button-vue .button-vue__text.button-vue__text {
|
|
975
975
|
padding-inline: 0;
|
|
976
976
|
}
|
|
977
|
+
|
|
978
|
+
/* ---- Grouped cards (CnGroupedCardsWidget, DqZaaktype "Fasen en taken") --- */
|
|
979
|
+
/* Groups 14px apart, each padded 14px with a 10px radius and a bold title; a
|
|
980
|
+
card in a group is padded 9px 12px with the 8px control radius, its title
|
|
981
|
+
15px. The doubled class outranks the widget's scoped rules.
|
|
982
|
+
@spec openspec/changes/board-grouped-cards/specs/board-grouped-cards/spec.md#requirement-board-grouped-cards-take-the-boards-group-and-card-shape */
|
|
983
|
+
.cn-look-board .cn-grouped-cards__grid.cn-grouped-cards__grid {
|
|
984
|
+
gap: 14px;
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
.cn-look-board .cn-grouped-cards__group.cn-grouped-cards__group {
|
|
988
|
+
padding: 14px;
|
|
989
|
+
border-radius: 10px;
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
.cn-look-board .cn-grouped-cards__group-title.cn-grouped-cards__group-title {
|
|
993
|
+
font-weight: 700;
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
.cn-look-board .cn-grouped-cards__item.cn-grouped-cards__item {
|
|
997
|
+
padding: 9px 12px;
|
|
998
|
+
border-radius: var(--cn-board-control-radius, 8px);
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
.cn-look-board .cn-grouped-cards__item-title.cn-grouped-cards__item-title {
|
|
1002
|
+
font-size: 15px;
|
|
1003
|
+
}
|
|
@@ -634,16 +634,36 @@
|
|
|
634
634
|
width: 18%;
|
|
635
635
|
}
|
|
636
636
|
|
|
637
|
-
/*
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
637
|
+
/* An index table pads every cell 16px at the sides (DqZaken). The plain-title
|
|
638
|
+
table (`rowTitle: "plain"`: PqTickets, OcPublicaties) sets its data cells
|
|
639
|
+
12px apart and its title column 18px from the selection column; the
|
|
640
|
+
selection and menu columns keep 16px. The title column is left out of the
|
|
641
|
+
12px rule, which would otherwise outrank the 18px one.
|
|
642
|
+
@spec openspec/changes/board-table-density/specs/board-table-density/spec.md#requirement-a-board-table-pads-its-cells-as-the-boards-draw-them */
|
|
643
|
+
.cn-look-board .cn-index-page__main--table .cn-table-container--board.cn-table-container--title-plain .cn-data-table th:not(.cn-table-col--checkbox):not(.cn-table-col--actions):not(.cn-table-col--icon):not(.cn-table-head--title),
|
|
644
|
+
.cn-look-board .cn-index-page__main--table .cn-table-container--board.cn-table-container--title-plain .cn-data-table td:not(.cn-table-col--checkbox):not(.cn-table-col--actions):not(.cn-table-col--icon):not(.cn-table-col--title) {
|
|
641
645
|
padding-inline: 12px;
|
|
642
646
|
}
|
|
643
647
|
|
|
644
|
-
.cn-look-board .cn-index-page__main--table .cn-table-container--board .cn-data-table th.cn-table-head--title,
|
|
645
|
-
.cn-look-board .cn-index-page__main--table .cn-table-container--board .cn-data-table td.cn-table-col--title {
|
|
646
|
-
padding-inline
|
|
648
|
+
.cn-look-board .cn-index-page__main--table .cn-table-container--board.cn-table-container--title-plain .cn-data-table th.cn-table-head--title,
|
|
649
|
+
.cn-look-board .cn-index-page__main--table .cn-table-container--board.cn-table-container--title-plain .cn-data-table td.cn-table-col--title {
|
|
650
|
+
padding-inline: 18px 12px;
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
/* A table that is not an index page's main list sits in a card and is the
|
|
654
|
+
compact one: 10px 12px in the header, 11px 12px in the cells
|
|
655
|
+
(DqInstellingen, DqVthInstellingen, DqZaaktype, DqTermijnen). The selection
|
|
656
|
+
column keeps its 16px, so it stays 60px wide. */
|
|
657
|
+
.cn-look-board .cn-table-container--board:not(.cn-index-page__main--table > *) .cn-data-table th {
|
|
658
|
+
padding: 10px 12px;
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
.cn-look-board .cn-table-container--board:not(.cn-index-page__main--table > *) .cn-data-table td {
|
|
662
|
+
padding: 11px 12px;
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
.cn-look-board .cn-table-container--board:not(.cn-index-page__main--table > *) .cn-data-table .cn-table-col--checkbox {
|
|
666
|
+
padding-inline: 16px;
|
|
647
667
|
}
|
|
648
668
|
|
|
649
669
|
.cn-look-board .cn-index-page__main--table .cn-table-container--board .cn-data-table td > .cn-cell-renderer {
|
|
@@ -873,12 +893,15 @@
|
|
|
873
893
|
}
|
|
874
894
|
|
|
875
895
|
/* A page link is a <button>: Nextcloud's `button` rule sets it bold, the
|
|
876
|
-
boards set the links at the regular weight and only the current page at 600.
|
|
896
|
+
boards set the links at the regular weight and only the current page at 600.
|
|
897
|
+
The boards size a link's content box at 34px, so a bordered link is 36px
|
|
898
|
+
and the borderless current page 34px (DqZaken "2", "Volgende", "1").
|
|
899
|
+
@spec openspec/changes/board-pagination-links/specs/board-pagination-links/spec.md#requirement-a-board-page-link-is-sized-as-the-boards-draw-it */
|
|
877
900
|
.cn-look-board .cn-pagination--board .cn-pagination__board-link {
|
|
878
901
|
box-sizing: border-box;
|
|
879
|
-
min-width:
|
|
880
|
-
height:
|
|
881
|
-
min-height:
|
|
902
|
+
min-width: 36px;
|
|
903
|
+
height: 36px;
|
|
904
|
+
min-height: 36px;
|
|
882
905
|
margin: 0;
|
|
883
906
|
padding: 0 8px;
|
|
884
907
|
border: 1px solid var(--color-border);
|
|
@@ -903,7 +926,10 @@
|
|
|
903
926
|
}
|
|
904
927
|
|
|
905
928
|
.cn-look-board .cn-pagination--board .cn-pagination__board-link--current {
|
|
906
|
-
|
|
929
|
+
min-width: 34px;
|
|
930
|
+
height: 34px;
|
|
931
|
+
min-height: 34px;
|
|
932
|
+
border: 0;
|
|
907
933
|
background: var(--color-primary-element);
|
|
908
934
|
color: var(--color-primary-element-text);
|
|
909
935
|
font-weight: 600;
|
|
@@ -1406,3 +1432,73 @@
|
|
|
1406
1432
|
border-bottom: none;
|
|
1407
1433
|
padding-block: 2px;
|
|
1408
1434
|
}
|
|
1435
|
+
|
|
1436
|
+
/* ---- The index side panel (CnIndexSidebar, board IndexZijpaneel) -------- */
|
|
1437
|
+
/* The panel's title is 20px bold without the schema icon, and its tabs are
|
|
1438
|
+
one row of 40px labels, 14px weight 600 in the soft ink, the open one in
|
|
1439
|
+
the deep primary ink and underlined 2px in the primary colour on the
|
|
1440
|
+
strip's rule (DqFilterBeheren). NcAppSidebar stacks the icon over the
|
|
1441
|
+
label in a 54px tile with a highlight bar; the board does neither. The
|
|
1442
|
+
header rule repeats NcAppSidebar's own chain to outrank it.
|
|
1443
|
+
@spec openspec/changes/board-index-sidebar-tabs/specs/board-index-sidebar-tabs/spec.md#requirement-the-board-index-side-panel-draws-the-boards-header-and-tab-row */
|
|
1444
|
+
.cn-look-board .cn-index-sidebar-panel .app-sidebar-header__desc .app-sidebar-header__name-container .app-sidebar-header__mainname-container h2.app-sidebar-header__mainname {
|
|
1445
|
+
font-size: 20px;
|
|
1446
|
+
font-weight: 700;
|
|
1447
|
+
line-height: 1.2;
|
|
1448
|
+
min-height: 0;
|
|
1449
|
+
}
|
|
1450
|
+
|
|
1451
|
+
.cn-look-board .cn-index-sidebar-panel .app-sidebar-header__figure:has(> .cn-index-sidebar__header-icon) {
|
|
1452
|
+
display: none;
|
|
1453
|
+
}
|
|
1454
|
+
|
|
1455
|
+
.cn-look-board .cn-index-sidebar-panel .app-sidebar-tabs__nav[role="tablist"] {
|
|
1456
|
+
justify-content: flex-start;
|
|
1457
|
+
gap: 4px;
|
|
1458
|
+
margin: 0;
|
|
1459
|
+
padding: 14px 12px 0;
|
|
1460
|
+
border-bottom: 1px solid var(--color-border);
|
|
1461
|
+
}
|
|
1462
|
+
|
|
1463
|
+
.cn-look-board .cn-index-sidebar-panel .app-sidebar-tabs__highlight {
|
|
1464
|
+
display: none;
|
|
1465
|
+
}
|
|
1466
|
+
|
|
1467
|
+
.cn-look-board .cn-index-sidebar-panel .app-sidebar-tabs__tab[role="tab"] {
|
|
1468
|
+
flex: 0 0 auto;
|
|
1469
|
+
flex-direction: row;
|
|
1470
|
+
align-items: center;
|
|
1471
|
+
gap: 6px;
|
|
1472
|
+
box-sizing: border-box;
|
|
1473
|
+
height: 40px;
|
|
1474
|
+
min-height: 40px;
|
|
1475
|
+
margin: 0 0 -1px;
|
|
1476
|
+
padding: 0 10px;
|
|
1477
|
+
border: 0;
|
|
1478
|
+
border-bottom: 2px solid transparent;
|
|
1479
|
+
border-radius: 0;
|
|
1480
|
+
background: transparent;
|
|
1481
|
+
color: var(--cn-board-text-soft);
|
|
1482
|
+
font-size: 14px;
|
|
1483
|
+
font-weight: 600;
|
|
1484
|
+
}
|
|
1485
|
+
|
|
1486
|
+
.cn-look-board .cn-index-sidebar-panel .app-sidebar-tabs__tab[role="tab"] * {
|
|
1487
|
+
font-weight: inherit;
|
|
1488
|
+
}
|
|
1489
|
+
|
|
1490
|
+
.cn-look-board .cn-index-sidebar-panel .app-sidebar-tabs__tab[role="tab"]::after {
|
|
1491
|
+
content: none;
|
|
1492
|
+
}
|
|
1493
|
+
|
|
1494
|
+
.cn-look-board .cn-index-sidebar-panel .app-sidebar-tabs__tab[role="tab"]:hover {
|
|
1495
|
+
background: transparent;
|
|
1496
|
+
border-bottom-color: var(--color-border-dark);
|
|
1497
|
+
color: var(--color-main-text);
|
|
1498
|
+
}
|
|
1499
|
+
|
|
1500
|
+
.cn-look-board .cn-index-sidebar-panel .app-sidebar-tabs__tab[role="tab"][aria-selected="true"] {
|
|
1501
|
+
background: transparent;
|
|
1502
|
+
border-bottom-color: var(--color-primary-element);
|
|
1503
|
+
color: var(--color-primary-element-light-text);
|
|
1504
|
+
}
|
package/src/css/look-board.css
CHANGED
|
@@ -228,9 +228,15 @@
|
|
|
228
228
|
look sets 600 on each button, so every NcButton on a board page draws the
|
|
229
229
|
board's weight without a rule per surface. Breadcrumb buttons keep the
|
|
230
230
|
crumb weight.
|
|
231
|
-
|
|
231
|
+
The boards also draw a button's text at 14px, against Nextcloud's 15px.
|
|
232
|
+
NcButton reads its size from --default-font-size, so the look sets that
|
|
233
|
+
variable on the button: a surface that sets its own `font-size` (the next
|
|
234
|
+
step card's 15px) keeps it.
|
|
235
|
+
@spec openspec/changes/board-button-weight/specs/board-button-weight/spec.md#requirement-a-board-button-draws-at-600
|
|
236
|
+
@spec openspec/changes/board-control-text/specs/board-control-text/spec.md#requirement-a-board-button-draws-its-text-at-14px */
|
|
232
237
|
.cn-look-board .button-vue:not(.cn-look-nextcloud *):not(.vue-crumb *) {
|
|
233
238
|
--font-weight-element: 600;
|
|
239
|
+
--default-font-size: 14px;
|
|
234
240
|
}
|
|
235
241
|
|
|
236
242
|
/* ---- A button with an icon and a label --------------------------------- */
|
|
@@ -393,6 +399,26 @@
|
|
|
393
399
|
background: var(--color-background-hover);
|
|
394
400
|
}
|
|
395
401
|
|
|
402
|
+
/* ---- A secondary button --------------------------------------------------- */
|
|
403
|
+
/* The boards draw every secondary button neutral: the main background, a 1px
|
|
404
|
+
control border, the main text, the hover ground on hover (DqFlow "Testen
|
|
405
|
+
met een zaak", DqFunctionaliteiten "Documentatie", DqTaak "Afronden").
|
|
406
|
+
NcButton draws its secondary from the primary-light variables, on a 2px
|
|
407
|
+
bottom edge; the look points those variables at the neutral colours on the
|
|
408
|
+
button itself. The selector weighs (0,3,0): it outranks NcButton's border
|
|
409
|
+
(0,2,0), and a surface rule of the same weight later in the cascade (a
|
|
410
|
+
dialog's cancel) still decides for its surface.
|
|
411
|
+
@spec openspec/changes/board-secondary-neutral/specs/board-secondary-neutral/spec.md#requirement-a-board-secondary-button-is-neutral */
|
|
412
|
+
.cn-look-board .button-vue.button-vue--secondary:where(:not(.cn-look-nextcloud *):not(.vue-crumb *)),
|
|
413
|
+
.cn-look-board .button-vue.button-vue--vue-secondary:where(:not(.cn-look-nextcloud *):not(.vue-crumb *)) {
|
|
414
|
+
--color-primary-element-light: var(--color-main-background);
|
|
415
|
+
--color-primary-element-light-hover: var(--color-background-hover);
|
|
416
|
+
--color-primary-element-light-text: var(--color-main-text);
|
|
417
|
+
--nldesign-color-on-surface: var(--color-main-text);
|
|
418
|
+
border: 1px solid var(--cn-board-control-border);
|
|
419
|
+
color: var(--color-main-text);
|
|
420
|
+
}
|
|
421
|
+
|
|
396
422
|
/* ---- Header action buttons (CnActionButtons) ----------------------------- */
|
|
397
423
|
/* The board draws a page's secondary actions as neutral 40px buttons: the
|
|
398
424
|
main background, a grey border, the main text at 600 (DqZaak "Bericht",
|
package/src/index.js
CHANGED
|
@@ -275,6 +275,7 @@ export {
|
|
|
275
275
|
CnQuicklinksWidget,
|
|
276
276
|
CnQuicklinksWidgetForm,
|
|
277
277
|
CnRadioCardsWidget,
|
|
278
|
+
CnReadinessChecklist,
|
|
278
279
|
CnRecordListWidget,
|
|
279
280
|
CnRedactionEditor,
|
|
280
281
|
CnReferencePreview,
|
|
@@ -304,6 +305,8 @@ export {
|
|
|
304
305
|
CnSavedViewWidgetForm,
|
|
305
306
|
CnSaveViewDialog,
|
|
306
307
|
CnSchemaFormDialog,
|
|
308
|
+
CnSchemaRulesWidget,
|
|
309
|
+
CnSearchIndexStatus,
|
|
307
310
|
CnSearchPage,
|
|
308
311
|
CnSearchSelect,
|
|
309
312
|
CnSectionsWidget,
|
|
@@ -315,6 +318,7 @@ export {
|
|
|
315
318
|
CnSettingsPage,
|
|
316
319
|
CnSettingsSection,
|
|
317
320
|
CnSetupWizard,
|
|
321
|
+
CnShippedConfigurationSection,
|
|
318
322
|
CnSignatureCapture,
|
|
319
323
|
CnSpendAnalyticsWidget,
|
|
320
324
|
CnSpendAnalyticsWidgetForm,
|