From d252555967036602c8b4a97fe8c1fcd15dc6d19b Mon Sep 17 00:00:00 2001 From: "C. Lucas" Date: Tue, 16 Jan 2024 14:26:36 +0100 Subject: [PATCH 001/143] XWIKI-21785: Bullets are displayed next to flag icons in the Languages List in Drawer (#2784) * Added back style lost when removing the drawer dependency * Removed some useless style * Increased specificity for the padding-left of the submenu items so that they would be correctly offset --- .../src/main/resources/flamingo/less/drawer.less | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-resources/src/main/resources/flamingo/less/drawer.less b/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-resources/src/main/resources/flamingo/less/drawer.less index 976a06e7028b..d8991e715ad6 100644 --- a/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-resources/src/main/resources/flamingo/less/drawer.less +++ b/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-resources/src/main/resources/flamingo/less/drawer.less @@ -147,12 +147,12 @@ // Sub Item ============================================================= .drawer-dropdown-menu { - &.collapsing { - /* Overwrite display:none from drawer.js in order to enable the collapse transition. */ - display: block; - } + box-sizing: border-box; + width: 100%; + margin: 0; + padding: 0; - a { + a.drawer-menu-item { padding-left: @xwiki-drawer-menu-subitem-indent; } } From 3f8f843ff4c6b93ce97885b72218834dda04d43b Mon Sep 17 00:00:00 2001 From: "C. Lucas" Date: Tue, 16 Jan 2024 14:34:11 +0100 Subject: [PATCH 002/143] XWIKI-21784: Long names cause avatar to disappear from Drawer and the 'Close the drawer' button to be shifted out of view (#2783) * Removed the max-width set on the avatar that allowed it to get squished down --- .../src/main/resources/flamingo/less/drawer.less | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-resources/src/main/resources/flamingo/less/drawer.less b/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-resources/src/main/resources/flamingo/less/drawer.less index d8991e715ad6..a753cecee31d 100644 --- a/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-resources/src/main/resources/flamingo/less/drawer.less +++ b/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-resources/src/main/resources/flamingo/less/drawer.less @@ -100,6 +100,8 @@ border-radius: 50%; height: 50px; width: 50px; + // Overwrite the default for img and avoid squishing down the avatar when the account name is too large + max-width: unset; } .brand-links { @@ -121,6 +123,8 @@ .brand-user { color: @xwiki-drawer-brand-user-color; font-weight: 400; + // Make sure we wrap the name whatever its length. + overflow-wrap: anywhere; } } } From ad53b39850c25ee62308cae1dd9c4d04d5c42dcf Mon Sep 17 00:00:00 2001 From: Nikita Petrenko Date: Sun, 14 Jan 2024 18:28:45 +0000 Subject: [PATCH 003/143] Translated using Weblate (Ukrainian) Currently translated at 100.0% (4484 of 4484 strings) Translation: XWiki Platform/XWiki Core Resources Translate-URL: https://l10n.xwiki.org/projects/xwiki-platform/xwiki-core-resources/uk/ --- .../src/main/resources/ApplicationResources_uk.properties | 1 + 1 file changed, 1 insertion(+) diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/ApplicationResources_uk.properties b/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/ApplicationResources_uk.properties index 10421e56415e..74412c49a984 100644 --- a/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/ApplicationResources_uk.properties +++ b/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/ApplicationResources_uk.properties @@ -1207,6 +1207,7 @@ platform.web.editors.object.pageTitle=\u0420\u0435\u0434\u0430\u0433\u0443\u0432 platform.web.editors.class.pageTitle=\u0420\u0435\u0434\u0430\u0433\u0443\u0432\u0430\u043D\u043D\u044F \u043A\u043B\u0430\u0441\u0443 {0} platform.web.editors.rights.pageTitle=\u0420\u0435\u0434\u0430\u0433\u0443\u0432\u0430\u043D\u043D\u044F \u043F\u0440\u0430\u0432 \u0434\u043E\u0441\u0442\u0443\u043F\u0443 \u0434\u043B\u044F {0} platform.web.editors.unknown.pageTitle=\u0420\u0435\u0434\u0430\u0433\u0443\u0432\u0430\u043D\u043D\u044F {0} +core.editors.content.title=\u0420\u0435\u0434\u0430\u0433\u0443\u0432\u0430\u043D\u043D\u044F \u043D\u0430\u0437\u0432\u0438 \u0442\u0430 \u0432\u043C\u0456\u0441\u0442\u0443 {0} core.editors.content.parentField.label=\u0411\u0430\u0442\u044C\u043A\u043E core.editors.content.parentField.edit=(\u0440\u0435\u0434\u0430\u0433\u0443\u0432\u0430\u0442\u0438) core.editors.content.parentField.edit.title=\u0420\u0435\u0434\u0430\u0433\u0443\u0432\u0430\u0442\u0438 \u0431\u0430\u0442\u044C\u043A\u0430 From cc864bed599f8e4d7035708f8abcc5144c134c63 Mon Sep 17 00:00:00 2001 From: "C. Lucas" Date: Tue, 16 Jan 2024 16:33:09 +0100 Subject: [PATCH 004/143] XWIKI-21009: LiveData alternative to drag controls (#2475) * Improved architecture of the headers * Updated drag and resize handles to support keyboard interactions * Use column titles as drag handles * Added a keyboard alternative for resetting column sizes * Fixed CSS organization * Added a new translation key for non-sortable columns --- .../resources/ApplicationResources.properties | 41 +++- .../ApplicationResources_de.properties | 37 ++- .../ApplicationResources_fr.properties | 37 ++- .../ApplicationResources_ja.properties | 37 ++- .../ApplicationResources_ru.properties | 37 ++- .../ApplicationResources_uk.properties | 37 ++- .../layouts/table/LayoutTableHeaderNames.vue | 216 ++++++++++-------- 7 files changed, 339 insertions(+), 103 deletions(-) diff --git a/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-macro/src/main/resources/ApplicationResources.properties b/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-macro/src/main/resources/ApplicationResources.properties index eac1c73b6cb1..7e5a8f25b6e0 100644 --- a/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-macro/src/main/resources/ApplicationResources.properties +++ b/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-macro/src/main/resources/ApplicationResources.properties @@ -18,6 +18,30 @@ # 02110-1301 USA, or see the FSF site: http://www.fsf.org. # --------------------------------------------------------------------------- +############################################################################### +# XWiki Core localization +# +# This contains the translations of the module in the default language +# (generally English). +# +# See https://dev.xwiki.org/xwiki/bin/view/Community/L10N/Conventions/ for more details about about +# translation key naming. +# +# Comments: it's possible to add some detail about a key to make easier to +# translate it by adding a comment before it. To make sure a comment is not +# assigned to the following key use at least three sharps (###) for the comment +# or after it. +# +# Deprecated keys: +# * when deleting a key it should be moved to deprecated section at the end +# of the file (between #@deprecatedstart and #@deprecatedend) and associated to the +# first version in which it started to be deprecated +# * when renaming a key, it should be moved to the same deprecated section +# and a comment should be added with the following syntax: +# #@deprecated new.key.name +# old.key.name=Some translation +############################################################################### + # # Translation keys for the rendering macro. # @@ -91,8 +115,9 @@ livedata.pagination.last=Last page livedata.action.refresh=Refresh livedata.action.addEntry=Add entry -livedata.action.reorder.hint=Drag to reorder -livedata.action.resizeColumn.hint=Drag to resize. Double click to reset. +livedata.action.columnName.default.hint=Drag or use arrow keys to reorder this property. +livedata.action.columnName.sortable.hint=Click to sort the entries based on this property. Drag or use arrow keys to reorder. +livedata.action.resizeColumn.hint=Drag or use arrow keys to resize. Double click or press escape to reset. livedata.panel.filter.title=Filter livedata.panel.filter.noneFilterable=None of the displayed properties is filterable. @@ -136,3 +161,15 @@ livedata.footnotes.propertyNotViewable=Displayed when some entries require speci livedata.bottombar.noEntries=(No entries) livedata.error.updateEntriesFailed=Updating the entries failed for an unknown reason. + +## Used to indicate where deprecated keys start +#@deprecatedstart + +####################################### +## until 16.0.0 +####################################### +#@deprecated livedata.action.columnName.default.hint +livedata.action.reorder.hint=Drag to reorder + +## Used to indicate where deprecated keys end +#@deprecatedend diff --git a/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-macro/src/main/resources/ApplicationResources_de.properties b/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-macro/src/main/resources/ApplicationResources_de.properties index e3788dfda44b..aa47f2516201 100644 --- a/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-macro/src/main/resources/ApplicationResources_de.properties +++ b/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-macro/src/main/resources/ApplicationResources_de.properties @@ -18,6 +18,30 @@ # 02110-1301 USA, or see the FSF site: http://www.fsf.org. # --------------------------------------------------------------------------- +############################################################################### +# XWiki Core localization +# +# This contains the translations of the module in the default language +# (generally English). +# +# See https://dev.xwiki.org/xwiki/bin/view/Community/L10N/Conventions/ for more details about about +# translation key naming. +# +# Comments: it's possible to add some detail about a key to make easier to +# translate it by adding a comment before it. To make sure a comment is not +# assigned to the following key use at least three sharps (###) for the comment +# or after it. +# +# Deprecated keys: +# * when deleting a key it should be moved to deprecated section at the end +# of the file (between #@deprecatedstart and #@deprecatedend) and associated to the +# first version in which it started to be deprecated +# * when renaming a key, it should be moved to the same deprecated section +# and a comment should be added with the following syntax: +# #@deprecated new.key.name +# old.key.name=Some translation +############################################################################### + # # Translation keys for the rendering macro. # @@ -76,7 +100,6 @@ livedata.pagination.next=N\u00E4chste Seite livedata.pagination.last=Letzte Seite livedata.action.refresh=Aktualisieren livedata.action.addEntry=Eintrag hinzuf\u00FCgen -livedata.action.reorder.hint=Ziehen zum Neuanordnen livedata.action.resizeColumn.hint=Zum \u00C4ndern der Gr\u00F6\u00DFe ziehen. Zum Zur\u00FCcksetzen doppelklicken. livedata.panel.filter.title=Filter livedata.panel.filter.noneFilterable=Keine der angezeigten Eigenschaften ist filterbar. @@ -109,3 +132,15 @@ livedata.footnotes.computedTitle=Einige Seiten haben einen berechneten Titel. Da livedata.footnotes.propertyNotViewable=Wird angezeigt, wenn einige Eintr\u00E4ge spezielle Rechte erfordern, um angezeigt zu werden, und daher Felder nicht aus ihnen extrahiert werden k\u00F6nnen. livedata.bottombar.noEntries=(Keine Eintr\u00E4ge) livedata.error.updateEntriesFailed=Das Aktualisieren der Eintr\u00E4ge ist aus einem unbekannten Grund fehlgeschlagen. + +## Used to indicate where deprecated keys start +#@deprecatedstart + +####################################### +## until 16.0.0 +####################################### +#@deprecated livedata.action.columnName.default.hint +livedata.action.reorder.hint=Ziehen zum Neuanordnen + +## Used to indicate where deprecated keys end +#@deprecatedend diff --git a/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-macro/src/main/resources/ApplicationResources_fr.properties b/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-macro/src/main/resources/ApplicationResources_fr.properties index d33a9282f12b..f05705edf079 100644 --- a/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-macro/src/main/resources/ApplicationResources_fr.properties +++ b/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-macro/src/main/resources/ApplicationResources_fr.properties @@ -18,6 +18,30 @@ # 02110-1301 USA, or see the FSF site: http://www.fsf.org. # --------------------------------------------------------------------------- +############################################################################### +# XWiki Core localization +# +# This contains the translations of the module in the default language +# (generally English). +# +# See https://dev.xwiki.org/xwiki/bin/view/Community/L10N/Conventions/ for more details about about +# translation key naming. +# +# Comments: it's possible to add some detail about a key to make easier to +# translate it by adding a comment before it. To make sure a comment is not +# assigned to the following key use at least three sharps (###) for the comment +# or after it. +# +# Deprecated keys: +# * when deleting a key it should be moved to deprecated section at the end +# of the file (between #@deprecatedstart and #@deprecatedend) and associated to the +# first version in which it started to be deprecated +# * when renaming a key, it should be moved to the same deprecated section +# and a comment should be added with the following syntax: +# #@deprecated new.key.name +# old.key.name=Some translation +############################################################################### + # # Translation keys for the rendering macro. # @@ -72,7 +96,6 @@ livedata.pagination.next=Page suivante livedata.pagination.last=Derni\u00E8re page livedata.action.refresh=Actualiser livedata.action.addEntry=Ajouter un \u00E9l\u00E9ment -livedata.action.reorder.hint=Glisser pour r\u00E9organiser livedata.action.resizeColumn.hint=Glisser pour redimensionner. Double-clic pour r\u00E9initialiser. livedata.panel.filter.title=Filtrer livedata.panel.filter.noneFilterable=Aucun des \u00E9l\u00E9ments affich\u00E9s ne peut \u00EAtre filtr\u00E9. @@ -100,3 +123,15 @@ livedata.footnotes.computedTitle=Le titre de certaines pages est calcul\u00E9. F ### Missing: livedata.footnotes.propertyNotViewable=Displayed when some entries require special rights to be viewed and thus fields cannot be extracted from them. livedata.bottombar.noEntries=(Aucun \u00E9l\u00E9ment) livedata.error.updateEntriesFailed=La mise \u00E0 jour des \u00E9l\u00E9ments a \u00E9chou\u00E9 pour une raison inconnue. + +## Used to indicate where deprecated keys start +#@deprecatedstart + +####################################### +## until 16.0.0 +####################################### +#@deprecated livedata.action.columnName.default.hint +livedata.action.reorder.hint=Glisser pour r\u00E9organiser + +## Used to indicate where deprecated keys end +#@deprecatedend diff --git a/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-macro/src/main/resources/ApplicationResources_ja.properties b/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-macro/src/main/resources/ApplicationResources_ja.properties index 9ea08bcb740e..55e670d050d8 100644 --- a/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-macro/src/main/resources/ApplicationResources_ja.properties +++ b/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-macro/src/main/resources/ApplicationResources_ja.properties @@ -18,6 +18,30 @@ # 02110-1301 USA, or see the FSF site: http://www.fsf.org. # --------------------------------------------------------------------------- +############################################################################### +# XWiki Core localization +# +# This contains the translations of the module in the default language +# (generally English). +# +# See https://dev.xwiki.org/xwiki/bin/view/Community/L10N/Conventions/ for more details about about +# translation key naming. +# +# Comments: it's possible to add some detail about a key to make easier to +# translate it by adding a comment before it. To make sure a comment is not +# assigned to the following key use at least three sharps (###) for the comment +# or after it. +# +# Deprecated keys: +# * when deleting a key it should be moved to deprecated section at the end +# of the file (between #@deprecatedstart and #@deprecatedend) and associated to the +# first version in which it started to be deprecated +# * when renaming a key, it should be moved to the same deprecated section +# and a comment should be added with the following syntax: +# #@deprecated new.key.name +# old.key.name=Some translation +############################################################################### + # # Translation keys for the rendering macro. # @@ -72,7 +96,6 @@ livedata.pagination.next=\u6B21\u306E\u30DA\u30FC\u30B8 livedata.pagination.last=\u6700\u5F8C\u306E\u30DA\u30FC\u30B8 livedata.action.refresh=\u518D\u8AAD\u307F\u8FBC\u307F livedata.action.addEntry=\u30A8\u30F3\u30C8\u30EA\u30FC\u3092\u8FFD\u52A0 -livedata.action.reorder.hint=\u30C9\u30E9\u30C3\u30B0\u3057\u3066\u4E26\u3079\u66FF\u3048 livedata.action.resizeColumn.hint=\u30C9\u30E9\u30C3\u30B0\u3067\u30B5\u30A4\u30BA\u3092\u5909\u66F4\u3002\u30C0\u30D6\u30EB\u30AF\u30EA\u30C3\u30AF\u3067\u30EA\u30BB\u30C3\u30C8\u3057\u307E\u3059\u3002 livedata.panel.filter.title=\u30D5\u30A3\u30EB\u30BF\u30FC livedata.panel.filter.noneFilterable=\u8868\u793A\u3055\u308C\u3066\u3044\u308B\u30D7\u30ED\u30D1\u30C6\u30A3\u30FC\u306E\u3044\u305A\u308C\u3082\u30D5\u30A3\u30EB\u30BF\u30EA\u30F3\u30B0\u3067\u304D\u307E\u305B\u3093\u3002 @@ -100,3 +123,15 @@ livedata.footnotes.computedTitle=\u3044\u304F\u3064\u304B\u306E\u30DA\u30FC\u30B livedata.footnotes.propertyNotViewable=\u3044\u304F\u3064\u304B\u306E\u30A8\u30F3\u30C8\u30EA\u30FC\u3092\u95B2\u89A7\u306B\u7279\u6B8A\u306A\u6A29\u9650\u3092\u5FC5\u8981\u3068\u3059\u308B\u969B\u306B\u8868\u793A\u3057\u305F\u305F\u3081\u3001\u30A8\u30F3\u30C8\u30EA\u30FC\u304B\u3089\u30D5\u30A3\u30FC\u30EB\u30C9\u3092\u62BD\u51FA\u3067\u304D\u307E\u305B\u3093\u3002 livedata.bottombar.noEntries=\uFF08\u30A8\u30F3\u30C8\u30EA\u30FC\u304C\u3042\u308A\u307E\u305B\u3093\uFF09 livedata.error.updateEntriesFailed=\u30A8\u30F3\u30C8\u30EA\u30FC\u3092\u66F4\u65B0\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u7406\u7531\u306F\u4E0D\u660E\u3067\u3059\u3002 + +## Used to indicate where deprecated keys start +#@deprecatedstart + +####################################### +## until 16.0.0 +####################################### +#@deprecated livedata.action.columnName.default.hint +livedata.action.reorder.hint=\u30C9\u30E9\u30C3\u30B0\u3057\u3066\u4E26\u3079\u66FF\u3048 + +## Used to indicate where deprecated keys end +#@deprecatedend diff --git a/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-macro/src/main/resources/ApplicationResources_ru.properties b/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-macro/src/main/resources/ApplicationResources_ru.properties index 84bb15d182bb..19d1ebe3eff0 100644 --- a/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-macro/src/main/resources/ApplicationResources_ru.properties +++ b/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-macro/src/main/resources/ApplicationResources_ru.properties @@ -18,6 +18,30 @@ # 02110-1301 USA, or see the FSF site: http://www.fsf.org. # --------------------------------------------------------------------------- +############################################################################### +# XWiki Core localization +# +# This contains the translations of the module in the default language +# (generally English). +# +# See https://dev.xwiki.org/xwiki/bin/view/Community/L10N/Conventions/ for more details about about +# translation key naming. +# +# Comments: it's possible to add some detail about a key to make easier to +# translate it by adding a comment before it. To make sure a comment is not +# assigned to the following key use at least three sharps (###) for the comment +# or after it. +# +# Deprecated keys: +# * when deleting a key it should be moved to deprecated section at the end +# of the file (between #@deprecatedstart and #@deprecatedend) and associated to the +# first version in which it started to be deprecated +# * when renaming a key, it should be moved to the same deprecated section +# and a comment should be added with the following syntax: +# #@deprecated new.key.name +# old.key.name=Some translation +############################################################################### + # # Translation keys for the rendering macro. # @@ -76,7 +100,6 @@ livedata.pagination.next=\u0421\u043B\u0435\u0434\u0443\u044E\u0449\u0430\u044F livedata.pagination.last=\u041F\u043E\u0441\u043B\u0435\u0434\u043D\u044F\u044F \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0430 livedata.action.refresh=\u041E\u0431\u043D\u043E\u0432\u0438\u0442\u044C livedata.action.addEntry=\u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0437\u0430\u043F\u0438\u0441\u044C -livedata.action.reorder.hint=\u041F\u0435\u0440\u0435\u0442\u0430\u0449\u0438\u0442\u0435, \u0447\u0442\u043E\u0431\u044B \u0438\u0437\u043C\u0435\u043D\u0438\u0442\u044C \u043F\u043E\u0440\u044F\u0434\u043E\u043A livedata.action.resizeColumn.hint=\u041F\u0435\u0440\u0435\u0442\u0430\u0449\u0438\u0442\u0435, \u0447\u0442\u043E\u0431\u044B \u0438\u0437\u043C\u0435\u043D\u0438\u0442\u044C \u0440\u0430\u0437\u043C\u0435\u0440. \u0414\u0432\u0430\u0436\u0434\u044B \u0449\u0435\u043B\u043A\u043D\u0438\u0442\u0435 \u0434\u043B\u044F \u0441\u0431\u0440\u043E\u0441\u0430. livedata.panel.filter.title=\u0424\u0438\u043B\u044C\u0442\u0440 livedata.panel.filter.noneFilterable=\u041D\u0438 \u043E\u0434\u043D\u043E \u0438\u0437 \u043E\u0442\u043E\u0431\u0440\u0430\u0436\u0430\u0435\u043C\u044B\u0445 \u0441\u0432\u043E\u0439\u0441\u0442\u0432 \u043D\u0435 \u0444\u0438\u043B\u044C\u0442\u0440\u0443\u0435\u0442\u0441\u044F. @@ -109,3 +132,15 @@ livedata.footnotes.computedTitle=\u041D\u0435\u043A\u043E\u0442\u043E\u0440\u044 livedata.footnotes.propertyNotViewable=\u041E\u0442\u043E\u0431\u0440\u0430\u0436\u0430\u0435\u0442\u0441\u044F, \u043A\u043E\u0433\u0434\u0430 \u043D\u0435\u043A\u043E\u0442\u043E\u0440\u044B\u0435 \u0437\u0430\u043F\u0438\u0441\u0438 \u0442\u0440\u0435\u0431\u0443\u044E\u0442 \u0441\u043F\u0435\u0446\u0438\u0430\u043B\u044C\u043D\u044B\u0445 \u043F\u0440\u0430\u0432 \u0434\u043B\u044F \u043F\u0440\u043E\u0441\u043C\u043E\u0442\u0440\u0430 \u0438 \u043F\u043E\u044D\u0442\u043E\u043C\u0443 \u0438\u0437 \u043D\u0438\u0445 \u043D\u0435\u0432\u043E\u0437\u043C\u043E\u0436\u043D\u043E \u0438\u0437\u0432\u043B\u0435\u0447\u044C \u043F\u043E\u043B\u044F. livedata.bottombar.noEntries=(\u041D\u0435\u0442 \u0437\u0430\u043F\u0438\u0441\u0435\u0439) livedata.error.updateEntriesFailed=\u041D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C \u043E\u0431\u043D\u043E\u0432\u0438\u0442\u044C \u0437\u0430\u043F\u0438\u0441\u0438 \u043F\u043E \u043D\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043D\u043E\u0439 \u043F\u0440\u0438\u0447\u0438\u043D\u0435. + +## Used to indicate where deprecated keys start +#@deprecatedstart + +####################################### +## until 16.0.0 +####################################### +#@deprecated livedata.action.columnName.default.hint +livedata.action.reorder.hint=\u041F\u0435\u0440\u0435\u0442\u0430\u0449\u0438\u0442\u0435, \u0447\u0442\u043E\u0431\u044B \u0438\u0437\u043C\u0435\u043D\u0438\u0442\u044C \u043F\u043E\u0440\u044F\u0434\u043E\u043A + +## Used to indicate where deprecated keys end +#@deprecatedend diff --git a/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-macro/src/main/resources/ApplicationResources_uk.properties b/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-macro/src/main/resources/ApplicationResources_uk.properties index f32a878fe56e..a961224dde16 100644 --- a/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-macro/src/main/resources/ApplicationResources_uk.properties +++ b/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-macro/src/main/resources/ApplicationResources_uk.properties @@ -18,6 +18,30 @@ # 02110-1301 USA, or see the FSF site: http://www.fsf.org. # --------------------------------------------------------------------------- +############################################################################### +# XWiki Core localization +# +# This contains the translations of the module in the default language +# (generally English). +# +# See https://dev.xwiki.org/xwiki/bin/view/Community/L10N/Conventions/ for more details about about +# translation key naming. +# +# Comments: it's possible to add some detail about a key to make easier to +# translate it by adding a comment before it. To make sure a comment is not +# assigned to the following key use at least three sharps (###) for the comment +# or after it. +# +# Deprecated keys: +# * when deleting a key it should be moved to deprecated section at the end +# of the file (between #@deprecatedstart and #@deprecatedend) and associated to the +# first version in which it started to be deprecated +# * when renaming a key, it should be moved to the same deprecated section +# and a comment should be added with the following syntax: +# #@deprecated new.key.name +# old.key.name=Some translation +############################################################################### + # # Translation keys for the rendering macro. # @@ -76,7 +100,6 @@ livedata.pagination.next=\u041D\u0430\u0441\u0442\u0443\u043F\u043D\u0430 \u0441 livedata.pagination.last=\u041E\u0441\u0442\u0430\u043D\u043D\u044F \u0441\u0442\u043E\u0440\u0456\u043D\u043A\u0430 livedata.action.refresh=\u041E\u043D\u043E\u0432\u0438\u0442\u0438 livedata.action.addEntry=\u0414\u043E\u0434\u0430\u0442\u0438 \u0437\u0430\u043F\u0438\u0441 -livedata.action.reorder.hint=\u0429\u043E\u0431 \u0437\u043C\u0456\u043D\u0438\u0442\u0438 \u043F\u043E\u0440\u044F\u0434\u043E\u043A, \u043F\u0435\u0440\u0435\u0442\u044F\u0433\u043D\u0456\u0442\u044C livedata.action.resizeColumn.hint=\u0429\u043E\u0431 \u0437\u043C\u0456\u043D\u0438\u0442\u0438 \u0440\u043E\u0437\u043C\u0456\u0440, \u043F\u0435\u0440\u0435\u0442\u044F\u0433\u043D\u0456\u0442\u044C. \u041A\u043B\u0430\u0446\u043D\u0456\u0442\u044C \u0434\u0432\u0456\u0447\u0456, \u0449\u043E\u0431 \u0441\u043A\u0438\u043D\u0443\u0442\u0438. livedata.panel.filter.title=\u0424\u0456\u043B\u044C\u0442\u0440 livedata.panel.filter.noneFilterable=\u0416\u043E\u0434\u043D\u0443 \u0437 \u0432\u0456\u0434\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0445 \u0432\u043B\u0430\u0441\u0442\u0438\u0432\u043E\u0441\u0442\u0435\u0439 \u043D\u0435 \u043C\u043E\u0436\u043D\u0430 \u0432\u0456\u0434\u0444\u0456\u043B\u044C\u0442\u0440\u0443\u0432\u0430\u0442\u0438. @@ -109,3 +132,15 @@ livedata.footnotes.computedTitle=\u0414\u0435\u044F\u043A\u0456 \u0441\u0442\u04 livedata.footnotes.propertyNotViewable=\u0412\u0456\u0434\u043E\u0431\u0440\u0430\u0436\u0430\u0454\u0442\u044C\u0441\u044F, \u043A\u043E\u043B\u0438 \u0434\u043B\u044F \u043F\u0435\u0440\u0435\u0433\u043B\u044F\u0434\u0443 \u0434\u0435\u044F\u043A\u0438\u0445 \u0437\u0430\u043F\u0438\u0441\u0456\u0432 \u043F\u043E\u0442\u0440\u0456\u0431\u043D\u0456 \u0441\u043F\u0435\u0446\u0456\u0430\u043B\u044C\u043D\u0456 \u043F\u0440\u0430\u0432\u0430, \u0442\u043E\u043C\u0443 \u0437 \u043D\u0438\u0445 \u043D\u0435\u043C\u043E\u0436\u043B\u0438\u0432\u043E \u043E\u0442\u0440\u0438\u043C\u0430\u0442\u0438 \u043F\u043E\u043B\u044F. livedata.bottombar.noEntries=(\u041D\u0435\u043C\u0430\u0454 \u0437\u0430\u043F\u0438\u0441\u0456\u0432) livedata.error.updateEntriesFailed=\u041D\u0435 \u0432\u0434\u0430\u043B\u043E\u0441\u044F \u043E\u043D\u043E\u0432\u0438\u0442\u0438 \u0437\u0430\u043F\u0438\u0441\u0438 \u0437 \u043D\u0435\u0432\u0456\u0434\u043E\u043C\u043E\u0457 \u043F\u0440\u0438\u0447\u0438\u043D\u0438. + +## Used to indicate where deprecated keys start +#@deprecatedstart + +####################################### +## until 16.0.0 +####################################### +#@deprecated livedata.action.columnName.default.hint +livedata.action.reorder.hint=\u0429\u043E\u0431 \u0437\u043C\u0456\u043D\u0438\u0442\u0438 \u043F\u043E\u0440\u044F\u0434\u043E\u043A, \u043F\u0435\u0440\u0435\u0442\u044F\u0433\u043D\u0456\u0442\u044C + +## Used to indicate where deprecated keys end +#@deprecatedend diff --git a/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-webjar/src/main/vue/layouts/table/LayoutTableHeaderNames.vue b/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-webjar/src/main/vue/layouts/table/LayoutTableHeaderNames.vue index 7a6332642c4e..8bf3921fa7cf 100644 --- a/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-webjar/src/main/vue/layouts/table/LayoutTableHeaderNames.vue +++ b/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-webjar/src/main/vue/layouts/table/LayoutTableHeaderNames.vue @@ -58,45 +58,41 @@ v-show="logic.isPropertyVisible(property.id)" > -
- - +
- {{ property.name }} + + - +
- - @@ -169,8 +165,8 @@ export default { so that it matches the true property order When selection is disabled (and the select-entry-all component hidden) we don't need to readjust the offset of the indexes - as Vue handily creates a html comment where the component shoud be - So that it does not messes up with indexes + as Vue handily creates a html comment where the component should be + So that it does not mess up with indexes */ this.logic.reorderProperty(e.moved.oldIndex - 1, e.moved.newIndex - 1); }, @@ -182,13 +178,32 @@ export default { } }, - resizeColumnInit (e) { + keyboardDragNDrop(e, deltaIndex) { + let handles = e.currentTarget.closest('tr').querySelectorAll('.handle'); + let oldIndex = Array.from(handles).indexOf(e.currentTarget); + let newIndex = oldIndex + deltaIndex; + if (newIndex >= handles.length) { + this.logic.reorderProperty(oldIndex, newIndex - handles.length); + } else if (newIndex <= -1) { + this.logic.reorderProperty(oldIndex, handles.length + newIndex); + } else { + this.logic.reorderProperty(oldIndex, newIndex); + } + this.$nextTick(() => { + handles[oldIndex].focus(); + }); + }, + + mouseResizeColumnInit (e) { const th = e.currentTarget.closest("th"); e.data.leftColumn = th.querySelector(".column-name"); e.data.leftColumnBaseWidth = e.data.leftColumn.getBoundingClientRect()?.width; e.data.rightColumn = this.getNextVisibleProperty(th)?.querySelector(".column-name"); e.data.rightColumnBaseWidth = e.data.rightColumn?.getBoundingClientRect()?.width; + this.resizeColumnInit(th); + }, + resizeColumnInit (th) { // Give all column names a fixed width so that relative widths don't change when resizing (in case the current // widths are not the actual column widths). // First, collect all widths, then set them all to avoid that due to the first values being set the other values @@ -205,19 +220,37 @@ export default { } }, - resizeColumn (e) { - const offsetX = e.clientX - e.data.clickEvent.clientX; + resizeColumn(offsetX, leftColumn, rightColumn, leftColumnBaseWidth, rightColumnBaseWidth) { // Resize left column - const leftColumnWidth = e.data.leftColumnBaseWidth + offsetX; - e.data.leftColumn.style.width = `${leftColumnWidth}px`; - + let leftColumnWidth = leftColumnBaseWidth + offsetX; + leftColumn.style.width = `${leftColumnWidth}px`; // Resize right column - if (e.data.rightColumn) { - const rightColumnWidth = e.data.rightColumnBaseWidth - offsetX; - e.data.rightColumn.style.width = `${rightColumnWidth}px`; + if (rightColumn) { + let rightColumnWidth = rightColumnBaseWidth - offsetX; + rightColumn.style.width = `${rightColumnWidth}px`; } }, + mouseResizeColumn (e) { + let offsetX = e.clientX - e.data.clickEvent.clientX; + let leftColumn = e.data.leftColumn; + let rightColumn = e.data.rightColumn; + let leftColumnBaseWidth = e.data.leftColumnBaseWidth; + let rightColumnBaseWidth = e.data.rightColumnBaseWidth; + this.resizeColumn(offsetX, leftColumn, rightColumn, leftColumnBaseWidth, rightColumnBaseWidth); + }, + + keyboardResizeColumn (e, offsetX) { + const th = e.currentTarget.closest("th"); + this.resizeColumnInit(th); + + let leftColumn = th.querySelector(".column-name"); + let leftColumnBaseWidth = leftColumn.getBoundingClientRect()?.width; + let rightColumn = this.getNextVisibleProperty(th)?.querySelector(".column-name"); + let rightColumnBaseWidth = rightColumn?.getBoundingClientRect()?.width; + this.resizeColumn(offsetX, leftColumn, rightColumn, leftColumnBaseWidth, rightColumnBaseWidth); + }, + resetColumnSize (e) { // Reset all column sizes as resizing a single column sets sizes for all columns. for (const column of e.currentTarget.closest("tr").querySelectorAll(".column-name")) { @@ -236,44 +269,53 @@ export default { .layout-table th.draggable-item { display: table-cell; min-width: 4rem; - overflow: hidden; + padding: 8px 0 8px 4px; } .layout-table .column-name { - display: flex; - flex-direction: row; - justify-content: flex-start; - align-items: center; cursor: pointer; - /* Ensure that the name is never smaller than the width of the column, i.e., it always fills the available space even - when the column has been resized to a smaller width that is prevented by some table cell. */ - min-width: 100%; - position: relative; + display: flex; + justify-content: space-between; } -.layout-table .handle { - height: 100%; - margin-left: -@table-cell-padding; - padding: 0 @table-cell-padding; - color: @text-color; - background-color: @xwiki-page-content-bg; - cursor: pointer; /* IE */ - cursor: grab; - opacity: 0; - position: absolute; +.layout-table .resize-handle { + padding: 0; + cursor: col-resize; + min-width: 0; + width: 0; + border-width: 2px; + border-radius: 0; + margin-left: 2px; } -.layout-table .column-name:hover .handle { - opacity: 0.8; - transition: opacity 0.2s; + +.layout-table .column-name:focus-within .resize-handle, +.layout-table .column-name:hover .resize-handle { + border-color: @text-muted; + border-width: 3px; + margin-left: 0; +} + +.layout-table .draggable-item:not(:last-child) .resize-handle { + margin-right: -2px; } -.layout-table .handle .fa { - vertical-align: middle; + +.layout-table .draggable-item:not(:last-child) .column-name:focus-within .resize-handle, +.layout-table .draggable-item:not(:last-child) .column-name:hover .resize-handle { + margin-right: -3px; } .layout-table .property-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; + background: transparent; + border: 0; + width: 100%; + text-align: left; +} + +.draggable-item .property-name.handle { + opacity: 1; } .layout-table .sort-icon { @@ -281,10 +323,17 @@ export default { opacity: 0; padding-left: @table-cell-padding; } + +.layout-table .property-name .sort-icon { + vertical-align: baseline; +} + .layout-table .sort-icon.sorted { opacity: 1; } -.layout-table .column-name:hover .sort-icon:not(.sorted) { + +.layout-table .column-name:hover .sort-icon:not(.sorted), +.layout-table .column-name:focus-within .sort-icon:not(.sorted) { opacity: 0.5; } @@ -292,36 +341,11 @@ export default { position: relative; } -.layout-table .resize-handle { - position: absolute; - right: 0px; - top: 0px; - bottom: 0px; - transform: translateX(50%); - width: 10px; - background-color: transparent; - cursor: ew-resize; - user-select: none; - z-index: 100; - - &:hover { - background-color: @breadcrumb-bg; - } -} - /* Responsive mode */ @media screen and (max-width: @screen-xs-max) { .layout-table th.draggable-item { /* Overwrite the draggable-item display in order to show the property names (table header) as a column. */ display: block; - - .handle { - /* Always show the drag handler because hover is not available on mobile. */ - opacity: 1; - /* Display the drag handler next to the property name to avoid always hiding it. */ - position: static; - } - /* Trim long property names. */ .property-name { white-space: nowrap; From f843e98bab30cbf96144862e54def7891d225126 Mon Sep 17 00:00:00 2001 From: Thomas Mortagne Date: Tue, 16 Jan 2024 16:33:28 +0100 Subject: [PATCH 005/143] XWIKI-21801: Duplicate versions in history of documents not based on JRCS Co-authored-by: trrenty --- .../DocumentInstanceOutputFilterStream.java | 11 -- .../com/xpn/xwiki/test/MockitoOldcore.java | 149 ++++++++++-------- .../filter/documentwithattachment1content.xml | 9 +- .../filter/documentwithattachment2content.xml | 9 +- 4 files changed, 100 insertions(+), 78 deletions(-) diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/internal/filter/output/DocumentInstanceOutputFilterStream.java b/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/internal/filter/output/DocumentInstanceOutputFilterStream.java index d8e6a5e2b41c..ec2ed1c2e341 100644 --- a/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/internal/filter/output/DocumentInstanceOutputFilterStream.java +++ b/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/internal/filter/output/DocumentInstanceOutputFilterStream.java @@ -46,7 +46,6 @@ import com.xpn.xwiki.doc.XWikiAttachment; import com.xpn.xwiki.doc.XWikiDocument; import com.xpn.xwiki.doc.XWikiDocumentArchive; -import com.xpn.xwiki.store.XWikiVersioningStoreInterface; /** * @version $Id$ @@ -252,16 +251,6 @@ private void maybeSaveDocument() throws FilterException xcontext.getWiki().saveDocument(document, inputDocument.getComment(), inputDocument.isMinorEdit(), xcontext); - - if (!hasJRCSHistory) { - // Not a JRCS based history document - // Explicitly update the history because the store won't do it automatically (because - // metadata/content dirty is false) - XWikiVersioningStoreInterface versioningStore = document.getVersioningStore(xcontext); - if (versioningStore != null) { - versioningStore.updateXWikiDocArchive(document, true, xcontext); - } - } } else { // Forget the input history to let the store do its standard job document.setDocumentArchive((XWikiDocumentArchive) null); diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/test/java/com/xpn/xwiki/test/MockitoOldcore.java b/xwiki-platform-core/xwiki-platform-oldcore/src/test/java/com/xpn/xwiki/test/MockitoOldcore.java index 44ff8f2c0018..99cab4371cd5 100644 --- a/xwiki-platform-core/xwiki-platform-oldcore/src/test/java/com/xpn/xwiki/test/MockitoOldcore.java +++ b/xwiki-platform-core/xwiki-platform-oldcore/src/test/java/com/xpn/xwiki/test/MockitoOldcore.java @@ -695,35 +695,7 @@ public Void answer(InvocationOnMock invocation) throws Throwable reference = reference.setWikiReference(xcontext.getWikiReference()); } - if (document.isContentDirty() || document.isMetaDataDirty()) { - document.setDate(new Date()); - if (document.isContentDirty()) { - document.setContentUpdateDate(new Date()); - document.setContentAuthorReference(document.getAuthorReference()); - } - document.incrementVersion(); - - document.setContentDirty(false); - document.setMetaDataDirty(false); - - if (supportRevisionStore) { - // Save the document in the document archive. - getMockVersioningStore().updateXWikiDocArchive(document, true, xcontext); - } - } - document.setNew(false); - document.setStore(getMockStore()); - - // Make sure the document is not restricted. - document.setRestricted(false); - - XWikiDocument savedDocument = document.clone(); - - documents.put(document.getDocumentReferenceWithLocale(), savedDocument); - - - // Set the document as it's original document - savedDocument.setOriginalDocument(savedDocument.clone()); + saveDocument(reference, document, xcontext); return null; } @@ -881,27 +853,6 @@ public Void answer(InvocationOnMock invocation) throws Throwable document.setComment(StringUtils.defaultString(comment)); document.setMinorEdit(minorEdit); - if (document.isContentDirty() || document.isMetaDataDirty()) { - Date ndate = new Date(); - document.setDate(ndate); - if (document.isContentDirty()) { - document.setContentUpdateDate(ndate); - DocumentAuthors authors = document.getAuthors(); - authors.setContentAuthor(authors.getEffectiveMetadataAuthor()); - } - document.incrementVersion(); - - document.setContentDirty(false); - document.setMetaDataDirty(false); - - // Save the document in the document archive. - if (supportRevisionStore) { - getMockVersioningStore().updateXWikiDocArchive(document, true, xcontext); - } - } - document.setNew(false); - document.setStore(getMockStore()); - XWikiDocument previousDocument = documents.get(document.getDocumentReferenceWithLocale()); if (previousDocument != null && previousDocument != document) { @@ -920,28 +871,28 @@ public Void answer(InvocationOnMock invocation) throws Throwable document.setOriginalDocument(originalDocument); } - // Make sure the document is not restricted. - document.setRestricted(false); + saveDocument(document.getDocumentReferenceWithLocale(), document, xcontext); - XWikiDocument savedDocument = document.clone(); + XWikiDocument newOriginal = document.getOriginalDocument(); - documents.put(document.getDocumentReferenceWithLocale(), savedDocument); + try { + document.setOriginalDocument(originalDocument); - if (isNew) { if (notifyDocumentCreatedEvent) { - getObservationManager().notify(new DocumentCreatedEvent(document.getDocumentReference()), - document, getXWikiContext()); - } - } else { - if (notifyDocumentUpdatedEvent) { - getObservationManager().notify(new DocumentUpdatedEvent(document.getDocumentReference()), - document, getXWikiContext()); + if (isNew) { + getObservationManager().notify( + new DocumentCreatedEvent(document.getDocumentReference()), document, + getXWikiContext()); + } else { + getObservationManager().notify( + new DocumentUpdatedEvent(document.getDocumentReference()), document, + getXWikiContext()); + } } + } finally { + document.setOriginalDocument(newOriginal); } - // Set the document as it's original document - savedDocument.setOriginalDocument(savedDocument.clone()); - return null; } }).when(getSpyXWiki()).saveDocument(anyXWikiDocument(), any(String.class), anyBoolean(), anyXWikiContext()); @@ -1181,6 +1132,74 @@ public String answer(InvocationOnMock invocation) throws Throwable } } + private void saveDocument(DocumentReference reference, XWikiDocument document, XWikiContext xcontext) + throws XWikiException + { + boolean supportRevisionStore = this.componentManager.hasComponent(XWikiDocumentFilterUtils.class); + + if (document.isContentDirty() || document.isMetaDataDirty()) { + document.setDate(new Date()); + if (document.isContentDirty()) { + document.setContentUpdateDate(new Date()); + DocumentAuthors authors = document.getAuthors(); + authors.setContentAuthor(authors.getEffectiveMetadataAuthor()); + } + document.incrementVersion(); + + document.setContentDirty(false); + document.setMetaDataDirty(false); + + if (supportRevisionStore) { + // Save the document in the document archive. + getMockVersioningStore().updateXWikiDocArchive(document, true, xcontext); + } + } else { + if (supportRevisionStore) { + if (document.getDocumentArchive() != null) { + getMockVersioningStore().saveXWikiDocArchive(document.getDocumentArchive(), false, xcontext); + + if (!containsVersion(document, document.getRCSVersion(), xcontext)) { + getMockVersioningStore().updateXWikiDocArchive(document, false, xcontext); + } + } else { + try { + document.getDocumentArchive(xcontext); + + if (!containsVersion(document, document.getRCSVersion(), xcontext)) { + getMockVersioningStore().updateXWikiDocArchive(document, false, xcontext); + } + } catch (XWikiException e) { + // this is a non critical error + } + } + } + } + document.setNew(false); + document.setStore(getMockStore()); + + // Make sure the document is not restricted. + document.setRestricted(false); + + XWikiDocument savedDocument = document.clone(); + + documents.put(document.getDocumentReferenceWithLocale(), savedDocument); + + // Set the document as it's original document + savedDocument.setOriginalDocument(savedDocument.clone()); + } + + private boolean containsVersion(XWikiDocument doc, Version targetversion, XWikiContext context) + throws XWikiException + { + for (Version version : doc.getRevisions(context)) { + if (version.equals(targetversion)) { + return true; + } + } + + return false; + } + protected DocumentReference resolveDocument(String documentName) throws ComponentLookupException { DocumentReferenceResolver resolver = diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/test/resources/filter/documentwithattachment1content.xml b/xwiki-platform-core/xwiki-platform-oldcore/src/test/resources/filter/documentwithattachment1content.xml index 28c6d435927d..3d5891effb62 100644 --- a/xwiki-platform-core/xwiki-platform-oldcore/src/test/resources/filter/documentwithattachment1content.xml +++ b/xwiki-platform-core/xwiki-platform-oldcore/src/test/resources/filter/documentwithattachment1content.xml @@ -36,7 +36,14 @@ syntax - + + + XWiki + xwiki + + + 2.1 + hidden diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/test/resources/filter/documentwithattachment2content.xml b/xwiki-platform-core/xwiki-platform-oldcore/src/test/resources/filter/documentwithattachment2content.xml index 40393fe4b7c2..77e524ef589e 100644 --- a/xwiki-platform-core/xwiki-platform-oldcore/src/test/resources/filter/documentwithattachment2content.xml +++ b/xwiki-platform-core/xwiki-platform-oldcore/src/test/resources/filter/documentwithattachment2content.xml @@ -36,7 +36,14 @@ syntax - + + + XWiki + xwiki + + + 2.1 + hidden From c5efc1e519e710afdf3c5f40c0fcc300ad77149f Mon Sep 17 00:00:00 2001 From: Michael Hamann Date: Tue, 16 Jan 2024 16:42:59 +0100 Subject: [PATCH 006/143] XWIKI-21553: Do not override existing documents on user action (#2790) * Introduce a new listener to cancel any save that would delete the document. * Add a unit test. --- .../document/DocumentOverrideListener.java | 77 +++++++++++++++++ .../main/resources/META-INF/components.txt | 1 + .../DocumentOverrideListenerTest.java | 86 +++++++++++++++++++ 3 files changed, 164 insertions(+) create mode 100644 xwiki-platform-core/xwiki-platform-oldcore/src/main/java/org/xwiki/internal/document/DocumentOverrideListener.java create mode 100644 xwiki-platform-core/xwiki-platform-oldcore/src/test/java/org/xwiki/internal/document/DocumentOverrideListenerTest.java diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/org/xwiki/internal/document/DocumentOverrideListener.java b/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/org/xwiki/internal/document/DocumentOverrideListener.java new file mode 100644 index 000000000000..74c8ae3dfb4c --- /dev/null +++ b/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/org/xwiki/internal/document/DocumentOverrideListener.java @@ -0,0 +1,77 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.internal.document; + +import javax.inject.Named; +import javax.inject.Singleton; + +import org.xwiki.component.annotation.Component; +import org.xwiki.observation.AbstractEventListener; +import org.xwiki.observation.event.CancelableEvent; +import org.xwiki.observation.event.Event; + +import com.xpn.xwiki.doc.XWikiDocument; +import com.xpn.xwiki.internal.event.UserUpdatingDocumentEvent; + +/** + * Cancel any save that tries to save a new document if the document already exists. + * + *

+ * This can happen when the context document is set to an empty document because the user doesn't have view right, + * but the user still has, e.g., edit right. In this situation, the user would still be able to to save but it is + * hard to imagine a scenario where this would make sense. This listener therefore cancels the save in this + * situation. + *

+ * + * @version $Id$ + * @since 14.10.21 + * @since 15.5.5 + * @since 15.10.6 + */ +@Component +@Singleton +@Named(DocumentOverrideListener.NAME) +public class DocumentOverrideListener extends AbstractEventListener +{ + /** + * The unique identifier of the listener. + */ + public static final String NAME = "org.xwiki.internal.document.DocumentOverrideListener"; + + /** + * The default constructor. + */ + public DocumentOverrideListener() + { + super(NAME, new UserUpdatingDocumentEvent()); + } + + @Override + public void onEvent(Event event, Object source, Object data) + { + XWikiDocument document = (XWikiDocument) source; + XWikiDocument originalDocument = document.getOriginalDocument(); + + if (document.isNew() && originalDocument != null && !originalDocument.isNew()) { + ((CancelableEvent) event).cancel( + "The document already exists but the document to be saved is marked as new."); + } + } +} diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/META-INF/components.txt b/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/META-INF/components.txt index ba8942e0b3ae..0f4b59d7f156 100644 --- a/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/META-INF/components.txt +++ b/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/META-INF/components.txt @@ -278,3 +278,4 @@ org.xwiki.security.authservice.script.AuthServiceScriptService org.xwiki.model.validation.edit.XWikiDocumentLockEditConfirmationChecker org.xwiki.evaluation.internal.DefaultObjectEvaluator org.xwiki.evaluation.internal.VelocityObjectPropertyEvaluator +org.xwiki.internal.document.DocumentOverrideListener diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/test/java/org/xwiki/internal/document/DocumentOverrideListenerTest.java b/xwiki-platform-core/xwiki-platform-oldcore/src/test/java/org/xwiki/internal/document/DocumentOverrideListenerTest.java new file mode 100644 index 000000000000..e5f1f45e1268 --- /dev/null +++ b/xwiki-platform-core/xwiki-platform-oldcore/src/test/java/org/xwiki/internal/document/DocumentOverrideListenerTest.java @@ -0,0 +1,86 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.internal.document; + +import org.junit.jupiter.api.Test; +import org.xwiki.model.reference.DocumentReference; +import org.xwiki.observation.internal.DefaultObservationManager; +import org.xwiki.test.annotation.ComponentList; + +import com.xpn.xwiki.XWikiException; +import com.xpn.xwiki.doc.XWikiDocument; +import com.xpn.xwiki.test.MockitoOldcore; +import com.xpn.xwiki.test.junit5.mockito.InjectMockitoOldcore; +import com.xpn.xwiki.test.junit5.mockito.OldcoreTest; +import com.xpn.xwiki.test.reference.ReferenceComponentList; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.mock; + +/** + * Unit tests for {@link DocumentOverrideListener}. + * + * @version $Id$ + */ +@OldcoreTest(mockXWiki = false) +@ReferenceComponentList +@ComponentList({ DefaultObservationManager.class, DocumentOverrideListener.class }) +class DocumentOverrideListenerTest +{ + @InjectMockitoOldcore + private MockitoOldcore oldcore; + + @Test + void savingNewDocument() throws Exception + { + DocumentReference documentReference = new DocumentReference("wiki", "space", "page"); + XWikiDocument document = new XWikiDocument(documentReference); + this.oldcore.getSpyXWiki().checkSavingDocument(mock(), document, this.oldcore.getXWikiContext()); + } + + @Test + void savingExistingDocument() throws Exception + { + DocumentReference documentReference = new DocumentReference("wiki", "space", "page"); + XWikiDocument document = new XWikiDocument(documentReference); + this.oldcore.getSpyXWiki().saveDocument(document, this.oldcore.getXWikiContext()); + document = this.oldcore.getSpyXWiki().getDocument(documentReference, this.oldcore.getXWikiContext()); + assertFalse(document.isNew()); + this.oldcore.getSpyXWiki().checkSavingDocument(mock(), document, this.oldcore.getXWikiContext()); + } + + @Test + void savingOverridingExistingDocument() throws Exception + { + DocumentReference documentReference = new DocumentReference("wiki", "space", "page"); + DocumentReference userReference = new DocumentReference("wiki", "XWiki", "user"); + XWikiDocument document = new XWikiDocument(documentReference); + this.oldcore.getSpyXWiki().saveDocument(document, this.oldcore.getXWikiContext()); + XWikiDocument newDocument = new XWikiDocument(documentReference); + XWikiException exception = assertThrows(XWikiException.class, + () -> this.oldcore.getSpyXWiki() + .checkSavingDocument(userReference, newDocument, this.oldcore.getXWikiContext())); + assertEquals("Error number 9001 in 9: User [wiki:XWiki.user] has been denied the right to save the " + + "document [wiki:space.page]. Reason: [The document already exists but the document to be saved is marked " + + "as new.]", exception.getMessage()); + } +} From 01863eb6ccd361004288bc91a92261b3f23fd9c0 Mon Sep 17 00:00:00 2001 From: Michael Hamann Date: Tue, 16 Jan 2024 16:53:17 +0100 Subject: [PATCH 007/143] XWIKI-21553: Do not override existing documents on user action * Remove mock() call not available in 14.10.x * Use constants for user and document reference in the test (cherry picked from commit f140102575cbdbb5a517caf51270fa669df23667) --- .../DocumentOverrideListenerTest.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/test/java/org/xwiki/internal/document/DocumentOverrideListenerTest.java b/xwiki-platform-core/xwiki-platform-oldcore/src/test/java/org/xwiki/internal/document/DocumentOverrideListenerTest.java index e5f1f45e1268..37155d90d7d9 100644 --- a/xwiki-platform-core/xwiki-platform-oldcore/src/test/java/org/xwiki/internal/document/DocumentOverrideListenerTest.java +++ b/xwiki-platform-core/xwiki-platform-oldcore/src/test/java/org/xwiki/internal/document/DocumentOverrideListenerTest.java @@ -46,39 +46,39 @@ @ComponentList({ DefaultObservationManager.class, DocumentOverrideListener.class }) class DocumentOverrideListenerTest { + private static final DocumentReference DOCUMENT_REFERENCE = new DocumentReference("wiki", "space", "page"); + + private static final DocumentReference USER_REFERENCE = new DocumentReference("wiki", "XWiki", "user"); + @InjectMockitoOldcore private MockitoOldcore oldcore; @Test void savingNewDocument() throws Exception { - DocumentReference documentReference = new DocumentReference("wiki", "space", "page"); - XWikiDocument document = new XWikiDocument(documentReference); - this.oldcore.getSpyXWiki().checkSavingDocument(mock(), document, this.oldcore.getXWikiContext()); + XWikiDocument document = new XWikiDocument(DOCUMENT_REFERENCE); + this.oldcore.getSpyXWiki().checkSavingDocument(USER_REFERENCE, document, this.oldcore.getXWikiContext()); } @Test void savingExistingDocument() throws Exception { - DocumentReference documentReference = new DocumentReference("wiki", "space", "page"); - XWikiDocument document = new XWikiDocument(documentReference); + XWikiDocument document = new XWikiDocument(DOCUMENT_REFERENCE); this.oldcore.getSpyXWiki().saveDocument(document, this.oldcore.getXWikiContext()); - document = this.oldcore.getSpyXWiki().getDocument(documentReference, this.oldcore.getXWikiContext()); + document = this.oldcore.getSpyXWiki().getDocument(DOCUMENT_REFERENCE, this.oldcore.getXWikiContext()); assertFalse(document.isNew()); - this.oldcore.getSpyXWiki().checkSavingDocument(mock(), document, this.oldcore.getXWikiContext()); + this.oldcore.getSpyXWiki().checkSavingDocument(USER_REFERENCE, document, this.oldcore.getXWikiContext()); } @Test void savingOverridingExistingDocument() throws Exception { - DocumentReference documentReference = new DocumentReference("wiki", "space", "page"); - DocumentReference userReference = new DocumentReference("wiki", "XWiki", "user"); - XWikiDocument document = new XWikiDocument(documentReference); + XWikiDocument document = new XWikiDocument(DOCUMENT_REFERENCE); this.oldcore.getSpyXWiki().saveDocument(document, this.oldcore.getXWikiContext()); - XWikiDocument newDocument = new XWikiDocument(documentReference); + XWikiDocument newDocument = new XWikiDocument(DOCUMENT_REFERENCE); XWikiException exception = assertThrows(XWikiException.class, () -> this.oldcore.getSpyXWiki() - .checkSavingDocument(userReference, newDocument, this.oldcore.getXWikiContext())); + .checkSavingDocument(USER_REFERENCE, newDocument, this.oldcore.getXWikiContext())); assertEquals("Error number 9001 in 9: User [wiki:XWiki.user] has been denied the right to save the " + "document [wiki:space.page]. Reason: [The document already exists but the document to be saved is marked " + "as new.]", exception.getMessage()); From b759f2dcc1d5214d6ecd30954caf08da0d086b7e Mon Sep 17 00:00:00 2001 From: Thomas Mortagne Date: Wed, 17 Jan 2024 08:54:31 +0100 Subject: [PATCH 008/143] [misc] Improve comments --- .../src/main/resources/xwiki.properties.vm | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/xwiki-platform-tools/xwiki-platform-tool-configuration-resources/src/main/resources/xwiki.properties.vm b/xwiki-platform-tools/xwiki-platform-tool-configuration-resources/src/main/resources/xwiki.properties.vm index 978f84db299a..9e74537943db 100644 --- a/xwiki-platform-tools/xwiki-platform-tool-configuration-resources/src/main/resources/xwiki.properties.vm +++ b/xwiki-platform-tools/xwiki-platform-tool-configuration-resources/src/main/resources/xwiki.properties.vm @@ -76,8 +76,8 @@ #-# The directory used to store persistent data (data that should persist across server restarts). This is an #-# important directory containing important data and thus it should never be deleted (it should be backed-up along #-# with the database). -#-# For example this is where the Extension Manager stores downloaded extensions if the extension.localRepository -#-# property isn't configured. +#-# For example this is where the Extension Manager stores downloaded extensions (unless extension.localRepository +#-# property is configured to a different location). #-# #-# You can set: #-# * an absolute path (recommended) @@ -573,8 +573,7 @@ extension.repositories = $extensionRepository #-# [Since 2.5] #-# The directory where extensions are stored after being downloaded. #-# -#-# The default is extension/repository in whatever is the general persistent directory. -#-# See container.persistentDirectory. +#-# The default is /extension/repository. # extension.localRepository=extension/repository #-# [Since 3.4] From db9af9431ba7152a9b2b9c1191af99820b2da6bd Mon Sep 17 00:00:00 2001 From: Manuel Leduc Date: Wed, 17 Jan 2024 09:21:36 +0100 Subject: [PATCH 009/143] XWIKI-18733: Replace the Affected Children livetable of the Delete page with a LiveData (#1691) --- .../src/main/resources/flamingo/delete.vm | 36 ++++++++++--------- .../flamingo/test/docker/DeletePageIT.java | 16 +++++++++ .../ui/po/DeletePageConfirmationPage.java | 18 ++++++++++ 3 files changed, 53 insertions(+), 17 deletions(-) diff --git a/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-resources/src/main/resources/flamingo/delete.vm b/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-resources/src/main/resources/flamingo/delete.vm index a485c80007cf..e3386c002c6e 100644 --- a/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-resources/src/main/resources/flamingo/delete.vm +++ b/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-resources/src/main/resources/flamingo/delete.vm @@ -122,11 +122,15 @@ ## DISPLAY CONFIRMATION PAGE ####################################################### #macro(displayConfirmationPage) -
+ #getChildren() - #displayNewTargetOption() - #getChildren_legacy() - #displayConfirmMessage() + ## If xform is a parent of getChildren, the ".xform field" css is also applied on the page size limit select, making it + ## badly displayed. +
+ #displayNewTargetOption() + #getChildren_legacy() + #displayConfirmMessage() +
#end ####################################################### @@ -171,21 +175,19 @@ ## ## List the documents to be deleted using a livetable ## - #set ($collist = ['doc.title', 'doc.location', 'doc.date', 'doc.author']) - #set ($colprops = { - 'doc.title' : { 'link' : 'view' }, - 'doc.location' : { 'type': 'text', 'filterable': true, 'html': true}, - 'doc.author' : { 'link' : 'author' } - }) - ## Note: we also display translations in the table since we want to show to the user all the pages that will - ## be deleted (including translations and hidden pages). - #set ($urlParameters = "xpage=getdocuments&childrenOf=$escapetool.url($doc.space)&queryFilters=unique") - #set ($options = { - 'url' : "$doc.getURL('get', $urlParameters)", + #set ($sourceParameters = { 'translationPrefix' : 'platform.index.', - 'outputOnlyHtml' : true + 'template' : 'getdocuments.vm', + 'childrenOf': $doc.space, + 'queryFilters': 'unique', + '$doc': $doc.documentReference + }) + $services.liveData.render({ + 'id': 'deleteSpaceIndex', + 'source': 'liveTable', + 'sourceParameters': $escapetool.url($sourceParameters), + 'properties': 'doc.title,doc.location,doc.date,doc.author' }) - #livetable('deleteSpaceIndex' $collist $colprops $options) #end #displayPanel('panel-children', 'panel-default', $heading, $body) #end diff --git a/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-test/xwiki-platform-flamingo-skin-test-docker/src/test/it/org/xwiki/flamingo/test/docker/DeletePageIT.java b/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-test/xwiki-platform-flamingo-skin-test-docker/src/test/it/org/xwiki/flamingo/test/docker/DeletePageIT.java index 9875e97d6f3f..176b7276ff16 100644 --- a/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-test/xwiki-platform-flamingo-skin-test-docker/src/test/it/org/xwiki/flamingo/test/docker/DeletePageIT.java +++ b/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-test/xwiki-platform-flamingo-skin-test-docker/src/test/it/org/xwiki/flamingo/test/docker/DeletePageIT.java @@ -35,6 +35,7 @@ import org.xwiki.flamingo.skin.test.po.JobQuestionPane; import org.xwiki.flamingo.skin.test.po.RestoreStatusPage; import org.xwiki.flamingo.skin.test.po.UndeletePage; +import org.xwiki.livedata.test.po.LiveDataElement; import org.xwiki.livedata.test.po.TableLayoutElement; import org.xwiki.model.reference.DocumentReference; import org.xwiki.model.reference.SpaceReference; @@ -57,6 +58,7 @@ import org.xwiki.tree.test.po.TreeElement; import org.xwiki.tree.test.po.TreeNodeElement; +import static org.hamcrest.CoreMatchers.hasItem; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -273,6 +275,20 @@ void deleteChildren(TestUtils setup, TestReference parentReference, TestInfo inf confirmationPage = parentPage.deletePage(); assertTrue(confirmationPage.hasAffectChildrenOption()); confirmationPage.setAffectChildren(false); + confirmationPage.openAffectChildrenPanel(); + TableLayoutElement affectChildrenLiveData = new LiveDataElement("deleteSpaceIndex").getTableLayout(); + assertEquals(nbChildren, affectChildrenLiveData.countRows()); + for (int i = 1; i <= nbChildren; i++) { + SpaceReference childSpaceReference = childrenReferences[i - 1].getLastSpaceReference(); + affectChildrenLiveData.assertCellWithLink("Title", String.format("Child %d", i), + setup.getURL(childSpaceReference)); + affectChildrenLiveData.assertCellWithLink("Location", String.format("Child_%d", i), + setup.getURL(childSpaceReference)); + affectChildrenLiveData.assertRow("Date", hasItem(affectChildrenLiveData.getDatePatternMatcher())); + affectChildrenLiveData.assertCellWithLink("Last Author", "superadmin", + setup.getURL(new DocumentReference("xwiki", "XWiki", "superadmin"))); + } + DeletingPage deletingPage = confirmationPage.confirmDeletePage(); deletingPage.waitUntilFinished(); assertEquals(DELETE_SUCCESSFUL, deletingPage.getInfoMessage()); diff --git a/xwiki-platform-core/xwiki-platform-test/xwiki-platform-test-ui/src/main/java/org/xwiki/test/ui/po/DeletePageConfirmationPage.java b/xwiki-platform-core/xwiki-platform-test/xwiki-platform-test-ui/src/main/java/org/xwiki/test/ui/po/DeletePageConfirmationPage.java index 64e260932206..5d2924e12cc5 100644 --- a/xwiki-platform-core/xwiki-platform-test/xwiki-platform-test-ui/src/main/java/org/xwiki/test/ui/po/DeletePageConfirmationPage.java +++ b/xwiki-platform-core/xwiki-platform-test/xwiki-platform-test-ui/src/main/java/org/xwiki/test/ui/po/DeletePageConfirmationPage.java @@ -19,6 +19,8 @@ */ package org.xwiki.test.ui.po; +import java.util.List; + import org.openqa.selenium.By; import org.openqa.selenium.NoSuchElementException; import org.openqa.selenium.WebElement; @@ -146,4 +148,20 @@ public DeletingPage confirmDeletePage() clickYes(); return new DeletingPage(); } + + /** + * Open the Affect Children Panel. + * + * @since 16.0.0RC1 + */ + public void openAffectChildrenPanel() + { + WebElement panelCollapseButton = + getDriver().findElementWithoutWaiting(By.cssSelector(".panel-collapse-carret")); + panelCollapseButton.click(); + getDriver().waitUntilCondition(input -> { + String[] classes = panelCollapseButton.getAttribute("class").split("\\s+"); + return !List.of(classes).contains("collapsed"); + }); + } } From 9bcebfd166264b1b1b6cd1a0b116ec664d8cba33 Mon Sep 17 00:00:00 2001 From: Manuel Leduc Date: Wed, 17 Jan 2024 09:26:30 +0100 Subject: [PATCH 010/143] XWIKI-21757: Support for Live Data description (#2778) --- .../java/org/xwiki/livedata/LiveDataMeta.java | 23 ++++++ .../LiveDataRendererConfiguration.java | 4 ++ .../internal/LiveDataRendererParameters.java | 22 ++++++ .../LiveDataRendererConfigurationTest.java | 72 +++++++++++++++++++ .../macro/LiveDataMacroParameters.java | 16 ++++- .../resources/ApplicationResources.properties | 3 + .../internal/macro/LiveDataMacroTest.java | 3 +- .../tests/unit/layouts/LivedataLayout.spec.js | 55 ++++++++++++++ .../src/main/vue/layouts/LivedataLayout.vue | 20 +++++- 9 files changed, 214 insertions(+), 4 deletions(-) create mode 100644 xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-api/src/test/java/org/xwiki/livedata/internal/LiveDataRendererConfigurationTest.java create mode 100644 xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-webjar/src/main/tests/unit/layouts/LivedataLayout.spec.js diff --git a/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-api/src/main/java/org/xwiki/livedata/LiveDataMeta.java b/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-api/src/main/java/org/xwiki/livedata/LiveDataMeta.java index 1600a7417969..a91764329852 100644 --- a/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-api/src/main/java/org/xwiki/livedata/LiveDataMeta.java +++ b/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-api/src/main/java/org/xwiki/livedata/LiveDataMeta.java @@ -25,6 +25,7 @@ import org.xwiki.livedata.LiveDataPropertyDescriptor.DisplayerDescriptor; import org.xwiki.livedata.LiveDataPropertyDescriptor.FilterDescriptor; +import org.xwiki.stability.Unstable; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; @@ -63,6 +64,8 @@ public class LiveDataMeta private LiveDataSelectionConfiguration selection; + private String description; + /** * @return the default layout used to display the live data */ @@ -287,6 +290,26 @@ public void setSelection(LiveDataSelectionConfiguration selection) this.selection = selection; } + /** + * @return an optional textual description of the Live Data + * @since 16.0.0RC1 + */ + @Unstable + public String getDescription() + { + return this.description; + } + + /** + * @param description an optional textual description of the Live Data + * @since 16.0.0RC1 + */ + @Unstable + public void setDescription(String description) + { + this.description = description; + } + /** * Prevent {@code null} values where it's possible. */ diff --git a/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-api/src/main/java/org/xwiki/livedata/internal/LiveDataRendererConfiguration.java b/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-api/src/main/java/org/xwiki/livedata/internal/LiveDataRendererConfiguration.java index 86469205c5b6..3b42a0f5b89c 100644 --- a/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-api/src/main/java/org/xwiki/livedata/internal/LiveDataRendererConfiguration.java +++ b/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-api/src/main/java/org/xwiki/livedata/internal/LiveDataRendererConfiguration.java @@ -189,6 +189,10 @@ private LiveDataMeta getMeta(LiveDataRendererParameters parameters) .flatMap(ls -> ls.stream().findFirst().map(BaseDescriptor::getId)) .ifPresent(meta::setDefaultLayout); meta.setPagination(getPagination(parameters)); + String description = parameters.getDescription(); + if (StringUtils.isNoneEmpty(description)) { + meta.setDescription(description); + } return meta; } diff --git a/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-api/src/main/java/org/xwiki/livedata/internal/LiveDataRendererParameters.java b/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-api/src/main/java/org/xwiki/livedata/internal/LiveDataRendererParameters.java index 93bf17cc48f0..51784c078063 100644 --- a/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-api/src/main/java/org/xwiki/livedata/internal/LiveDataRendererParameters.java +++ b/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-api/src/main/java/org/xwiki/livedata/internal/LiveDataRendererParameters.java @@ -52,6 +52,8 @@ public class LiveDataRendererParameters private String pageSizes; + private String description; + /** * @return the Live Data instance id */ @@ -256,6 +258,24 @@ public void setPageSizes(String pageSizes) this.pageSizes = pageSizes; } + /** + * @return an optional textual description of the Live Data + * @since 16.0.0RC1 + */ + public String getDescription() + { + return this.description; + } + + /** + * @param description an optional textual description of the Live Data + * @since 16.0.0RC1 + */ + public void setDescription(String description) + { + this.description = description; + } + @Override public boolean equals(Object o) { @@ -281,6 +301,7 @@ public boolean equals(Object o) .append(this.layouts, that.layouts) .append(this.showPageSizeDropdown, that.showPageSizeDropdown) .append(this.pageSizes, that.pageSizes) + .append(this.description, that.description) .isEquals(); } @@ -299,6 +320,7 @@ public int hashCode() .append(this.layouts) .append(this.showPageSizeDropdown) .append(this.pageSizes) + .append(this.description) .toHashCode(); } } diff --git a/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-api/src/test/java/org/xwiki/livedata/internal/LiveDataRendererConfigurationTest.java b/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-api/src/test/java/org/xwiki/livedata/internal/LiveDataRendererConfigurationTest.java new file mode 100644 index 000000000000..530089d0e314 --- /dev/null +++ b/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-api/src/test/java/org/xwiki/livedata/internal/LiveDataRendererConfigurationTest.java @@ -0,0 +1,72 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.livedata.internal; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.xwiki.livedata.LiveDataConfiguration; +import org.xwiki.livedata.LiveDataConfigurationResolver; +import org.xwiki.test.junit5.mockito.ComponentTest; +import org.xwiki.test.junit5.mockito.InjectMockComponents; +import org.xwiki.test.junit5.mockito.MockComponent; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.mockito.Mockito.when; + +/** + * Test of {@link LiveDataRendererConfiguration}. + * + * @version $Id$ + * @since 16.0.0RC1 + */ +@ComponentTest +class LiveDataRendererConfigurationTest +{ + @InjectMockComponents + private LiveDataRendererConfiguration configuration; + + @MockComponent + private LiveDataConfigurationResolver stringLiveDataConfigResolver; + + @BeforeEach + void setUp() throws Exception + { + when(this.stringLiveDataConfigResolver.resolve("{}")).thenReturn(new LiveDataConfiguration()); + } + + @Test + void getLiveDataConfigurationDescriptionNotDefined() throws Exception + { + LiveDataConfiguration liveDataConfiguration = + this.configuration.getLiveDataConfiguration("{}", new LiveDataRendererParameters()); + assertNull(liveDataConfiguration.getMeta().getDescription()); + } + + @Test + void getLiveDataConfigurationDescriptionIsDefined() throws Exception + { + LiveDataRendererParameters parameters = new LiveDataRendererParameters(); + String description = "A description"; + parameters.setDescription(description); + LiveDataConfiguration liveDataConfiguration = this.configuration.getLiveDataConfiguration("{}", parameters); + assertEquals(description, liveDataConfiguration.getMeta().getDescription()); + } +} diff --git a/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-macro/src/main/java/org/xwiki/livedata/macro/LiveDataMacroParameters.java b/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-macro/src/main/java/org/xwiki/livedata/macro/LiveDataMacroParameters.java index 7d4ba518450d..73c87ea21e21 100644 --- a/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-macro/src/main/java/org/xwiki/livedata/macro/LiveDataMacroParameters.java +++ b/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-macro/src/main/java/org/xwiki/livedata/macro/LiveDataMacroParameters.java @@ -22,10 +22,11 @@ import org.xwiki.livedata.internal.LiveDataRendererParameters; import org.xwiki.livedata.internal.macro.LiveDataMacro; import org.xwiki.properties.annotation.PropertyDescription; +import org.xwiki.stability.Unstable; /** * Parameters for {@link LiveDataMacro}. - * + * * @version $Id$ * @since 12.10 */ @@ -144,4 +145,17 @@ public void setPageSizes(String pageSizes) { super.setPageSizes(pageSizes); } + + /** + * {@inheritDoc} + * + * @since 16.0.0RC1 + */ + @Override + @Unstable + @PropertyDescription("An optional textual description of the Live Data.") + public void setDescription(String description) + { + super.setDescription(description); + } } diff --git a/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-macro/src/main/resources/ApplicationResources.properties b/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-macro/src/main/resources/ApplicationResources.properties index 7e5a8f25b6e0..3eba7e68b784 100644 --- a/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-macro/src/main/resources/ApplicationResources.properties +++ b/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-macro/src/main/resources/ApplicationResources.properties @@ -84,6 +84,9 @@ rendering.macro.liveData.parameter.showPageSizeDropdown.description=Show or hide rendering.macro.liveData.parameter.pageSizes.name=Page sizes rendering.macro.liveData.parameter.pageSizes.description=The comma-separated list of page sizes to display in the page size drop-down. +rendering.macro.liveData.parameter.description.name=Description +rendering.macro.liveData.parameter.description.description=An optional textual description of the Live Data. + # # Translation keys for the live data widget. # diff --git a/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-macro/src/test/java/org/xwiki/livedata/internal/macro/LiveDataMacroTest.java b/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-macro/src/test/java/org/xwiki/livedata/internal/macro/LiveDataMacroTest.java index f4b86425cb37..5a687e41ce84 100644 --- a/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-macro/src/test/java/org/xwiki/livedata/internal/macro/LiveDataMacroTest.java +++ b/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-macro/src/test/java/org/xwiki/livedata/internal/macro/LiveDataMacroTest.java @@ -175,7 +175,7 @@ void execute() throws Exception expectedConfig.append(" 'pagination':{".trim()); expectedConfig.append(" 'pageSizes':[15,25,50],".trim()); expectedConfig.append(" 'showPageSizeDropdown':true".trim()); - expectedConfig.append(" }".trim()); + expectedConfig.append(" },'description':'A description'".trim()); expectedConfig.append(" }".trim()); expectedConfig.append("}"); @@ -194,6 +194,7 @@ void execute() throws Exception parameters.setLayouts("table, cards"); parameters.setShowPageSizeDropdown(true); parameters.setPageSizes("15, 25, 50"); + parameters.setDescription("A description"); List blocks = this.liveDataMacro.execute(parameters, null, this.context); assertBlocks(expected, blocks, this.rendererFactory); diff --git a/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-webjar/src/main/tests/unit/layouts/LivedataLayout.spec.js b/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-webjar/src/main/tests/unit/layouts/LivedataLayout.spec.js new file mode 100644 index 000000000000..4f1c9adb6db4 --- /dev/null +++ b/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-webjar/src/main/tests/unit/layouts/LivedataLayout.spec.js @@ -0,0 +1,55 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +import {shallowMount} from '@vue/test-utils'; +import LivedataLayout from "../../../layouts/LivedataLayout"; + +/** + * Initialize a shallow LivedataLayout component. + * + * @param description the optional description of the Live Data + * @returns {Wrapper} the initialized shallow wrapper + */ +function initWrapper(description) { + return shallowMount(LivedataLayout, { + provide: { + logic: { + data: { + id: 'my-layout-id', + meta: { + description + } + } + } + } + }); +} + +describe('LivedataLayout.vue', () => { + it('Without a description', () => { + const wrapper = initWrapper(); + expect(wrapper.find('.description').exists()).toBe(false); + }) + + it('With a description', () => { + const description = "A description"; + const wrapper = initWrapper(description); + expect(wrapper.find('.description').text()).toBe("A description"); + }) +}) \ No newline at end of file diff --git a/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-webjar/src/main/vue/layouts/LivedataLayout.vue b/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-webjar/src/main/vue/layouts/LivedataLayout.vue index e8ce19903959..412777db35d7 100644 --- a/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-webjar/src/main/vue/layouts/LivedataLayout.vue +++ b/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-webjar/src/main/vue/layouts/LivedataLayout.vue @@ -34,6 +34,9 @@ -->