diff --git a/Resources/translations/universal_discovery_widget.en.xliff b/Resources/translations/universal_discovery_widget.en.xliff index 666d35be..92f22be1 100644 --- a/Resources/translations/universal_discovery_widget.en.xliff +++ b/Resources/translations/universal_discovery_widget.en.xliff @@ -21,6 +21,16 @@ Browse key: browse.label + + Add + Add + key: browser.add + + + Selected + Selected + key: browser.selected + Cancel Cancel @@ -116,11 +126,21 @@ Subtree key: filters.subtree + + Bookmark + Bookmark + key: meta_preview.bookmark + Creation Date Creation Date key: meta_preview.creation_date + + Edit + Edit + key: meta_preview.edit + Edit translation Edit translation @@ -131,6 +151,11 @@ Last Modified key: meta_preview.last_modified + + Preview + Preview + key: meta_preview.preview + Translations Translations @@ -181,6 +206,31 @@ Some helpful search tips key: search.tips + + Clear all + Clear all + key: selected_locations.clear_all + + + Clear selection + Clear selection + key: selected_locations.clear_selection + + + Collapse sidebar + Collapse sidebar + key: selected_locations.collapse.sidebar + + + Confirm selection + Confirm selection + key: selected_locations.confirm_selection + + + Expand sidebar + Expand sidebar + key: selected_locations.expand.sidebar + selected selected @@ -191,11 +241,31 @@ Date key: sorting.date.label + + Sort by Date + Sort by Date + key: sorting.date.tooltip + + + Grid view + Grid view + key: sorting.grid.view + Name Name key: sorting.name.label + + Sort by Name + Sort by Name + key: sorting.name.tooltip + + + Panels view + Panels view + key: sorting.panels.view + diff --git a/src/modules/universal-discovery/components/content-create-button/content.create.button.js b/src/modules/universal-discovery/components/content-create-button/content.create.button.js index 759f8daa..a2dddf3e 100644 --- a/src/modules/universal-discovery/components/content-create-button/content.create.button.js +++ b/src/modules/universal-discovery/components/content-create-button/content.create.button.js @@ -19,7 +19,9 @@ const ContentCreateButton = ({ isDisabled }) => { const [selectedLocations, dispatchSelectedLocationsAction] = useContext(SelectedLocationsContext); const [multiple, multipleItemsLimit] = useContext(MultipleConfigContext); const { hidden, allowedLocations } = useContext(ContentOnTheFlyConfigContext); + const createLabel = Translator.trans(/*@Desc("Create")*/ 'create_content.create', {}, 'universal_discovery_widget'); const toggleContentCreateVisibility = () => { + window.eZ.helpers.tooltips.hideAll(); setCreateContentVisible((prevState) => !prevState); }; let selectedLocation = loadedLocationsMap.find((loadedLocation) => loadedLocation.parentLocationId === markedLocationId); @@ -46,7 +48,9 @@ const ContentCreateButton = ({ isDisabled }) => { diff --git a/src/modules/universal-discovery/components/content-create-widget/content.create.widget.js b/src/modules/universal-discovery/components/content-create-widget/content.create.widget.js index 400418a4..c657f163 100644 --- a/src/modules/universal-discovery/components/content-create-widget/content.create.widget.js +++ b/src/modules/universal-discovery/components/content-create-widget/content.create.widget.js @@ -1,4 +1,4 @@ -import React, { useContext, useState } from 'react'; +import React, { useContext, useState, useEffect, useRef } from 'react'; import Icon from '../../../common/icon/icon'; @@ -17,6 +17,7 @@ const languages = Object.values(window.eZ.adminUiConfig.languages.mappings); const contentTypes = Object.entries(window.eZ.adminUiConfig.contentTypes); const ContentCreateWidget = () => { + const refContentTree = useRef(null); const [markedLocationId, setMarkedLocationId] = useContext(MarkedLocationIdContext); const [loadedLocationsMap, dispatchLoadedLocationsAction] = useContext(LoadedLocationsMapContext); const { allowedLanguages, preselectedLanguage, preselectedContentType } = useContext(ContentOnTheFlyConfigContext); @@ -69,16 +70,26 @@ const ContentCreateWidget = () => { 'universal_discovery_widget' ); const createLabel = Translator.trans(/*@Desc("Create")*/ 'create_content.create', {}, 'universal_discovery_widget'); + const closeLabel = Translator.trans(/*@Desc("Close")*/ 'popup.close.label', {}, 'universal_discovery_widget'); const widgetClassName = createCssClassNames({ 'c-content-create': true, 'c-content-create--hidden': !createContentVisible, }); + useEffect(() => { + window.eZ.helpers.tooltips.parse(refContentTree.current); + }, []); + return ( -
+
{createContentLabel}
-
diff --git a/src/modules/universal-discovery/components/content-edit-button/content.edit.button.js b/src/modules/universal-discovery/components/content-edit-button/content.edit.button.js index 7ae4bf7d..b5473260 100644 --- a/src/modules/universal-discovery/components/content-edit-button/content.edit.button.js +++ b/src/modules/universal-discovery/components/content-edit-button/content.edit.button.js @@ -21,6 +21,7 @@ const ContentEditButton = ({ version, location, isDisabled }) => { const [isTranslationSelectorVisible, setIsTranslationSelectorVisible] = useState(false); const contentTypeInfo = contentTypesMap[location.ContentInfo.Content.ContentType._href]; const isUserContentType = window.eZ.adminUiConfig.userContentTypes.includes(contentTypeInfo.identifier); + const editLabel = Translator.trans(/*@Desc("Edit")*/ 'meta_preview.edit', {}, 'universal_discovery_widget'); useEffect(() => { setIsTranslationSelectorVisible(false); @@ -107,7 +108,9 @@ const ContentEditButton = ({ version, location, isDisabled }) => { {renderTranslationSelector()} diff --git a/src/modules/universal-discovery/components/content-table/content.table.js b/src/modules/universal-discovery/components/content-table/content.table.js index cd2190b7..8f80ff4f 100644 --- a/src/modules/universal-discovery/components/content-table/content.table.js +++ b/src/modules/universal-discovery/components/content-table/content.table.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useEffect, useRef } from 'react'; import PropTypes from 'prop-types'; import ContentTableItem from './content.table.item'; @@ -6,12 +6,17 @@ import ContentTableItem from './content.table.item'; import Pagination from '../../../common/pagination/pagination'; const ContentTable = ({ count, itemsPerPage, items, activePageIndex, title, onPageChange }) => { + const refContentTable = useRef(null); const nameLabel = Translator.trans(/*@Desc("Name")*/ 'content_table.name', {}, 'universal_discovery_widget'); const modifiedLabel = Translator.trans(/*@Desc("Modified")*/ 'content_table.modified', {}, 'universal_discovery_widget'); const contentTypeLabel = Translator.trans(/*@Desc("Content Type")*/ 'content_table.content_type', {}, 'universal_discovery_widget'); + useEffect(() => { + window.eZ.helpers.tooltips.parse(refContentTable.current); + }, []); + return ( -
+
{title}
diff --git a/src/modules/universal-discovery/components/finder/finder.leaf.js b/src/modules/universal-discovery/components/finder/finder.leaf.js index 33c0b7c4..1448ec86 100644 --- a/src/modules/universal-discovery/components/finder/finder.leaf.js +++ b/src/modules/universal-discovery/components/finder/finder.leaf.js @@ -1,4 +1,4 @@ -import React, { useContext } from 'react'; +import React, { useContext, useEffect } from 'react'; import PropTypes from 'prop-types'; import ToggleSelectionButton from '../toggle-selection-button/toggle.selection.button'; @@ -58,6 +58,10 @@ const FinderLeaf = ({ location }) => { 'c-finder-leaf--not-selectable': isNotSelectable, }); + useEffect(() => { + window.eZ.helpers.tooltips.parse(window.document.querySelector('.c-udw-tab')); + }, []); + return (
@@ -67,7 +71,9 @@ const FinderLeaf = ({ location }) => { customPath={contentTypesMap[location.ContentInfo.Content.ContentType._href].thumbnail} /> - {location.ContentInfo.Content.TranslatedName} + + {location.ContentInfo.Content.TranslatedName} + {renderToggleSelectionButton()}
diff --git a/src/modules/universal-discovery/components/menu-button/menu.button.js b/src/modules/universal-discovery/components/menu-button/menu.button.js index db643453..04b2b4b5 100644 --- a/src/modules/universal-discovery/components/menu-button/menu.button.js +++ b/src/modules/universal-discovery/components/menu-button/menu.button.js @@ -3,14 +3,14 @@ import PropTypes from 'prop-types'; import { createCssClassNames } from '../../../common/helpers/css.class.names'; -const MenuButton = ({ extraClasses, onClick, isDisabled, children }) => { +const MenuButton = ({ extraClasses, onClick, isDisabled, title, children }) => { const className = createCssClassNames({ 'c-menu-button': true, [extraClasses]: !!extraClasses, }); return ( - ); @@ -20,6 +20,7 @@ MenuButton.propTypes = { extraClasses: PropTypes.string, onClick: PropTypes.func.isRequired, isDisabled: PropTypes.bool, + title: PropTypes.string, children: PropTypes.any, }; @@ -27,6 +28,7 @@ MenuButton.defaultProps = { children: [], extraClasses: '', isDisabled: false, + title: '', }; export default MenuButton; diff --git a/src/modules/universal-discovery/components/selected-locations/selected.locations.item.js b/src/modules/universal-discovery/components/selected-locations/selected.locations.item.js index 0f8449d5..479e43e5 100644 --- a/src/modules/universal-discovery/components/selected-locations/selected.locations.item.js +++ b/src/modules/universal-discovery/components/selected-locations/selected.locations.item.js @@ -1,4 +1,4 @@ -import React, { useContext, useMemo } from 'react'; +import React, { useContext, useEffect, useMemo, useRef } from 'react'; import PropTypes from 'prop-types'; import Icon from '../../../common/icon/icon'; @@ -7,9 +7,16 @@ import Thumbnail from '../../../common/thumbnail/thumbnail'; import { SelectedLocationsContext, ContentTypesMapContext } from '../../universal.discovery.module'; const SelectedLocationsItem = ({ location, permissions }) => { + const refSelectedLocationsItem = useRef(null); const [selectedLocations, dispatchSelectedLocationsAction] = useContext(SelectedLocationsContext); const contentTypesMap = useContext(ContentTypesMapContext); + const clearLabel = Translator.trans( + /*@Desc("Clear selection")*/ 'selected_locations.clear_selection', + {}, + 'universal_discovery_widget' + ); const removeFromSelection = () => { + window.eZ.helpers.tooltips.hideAll(refSelectedLocationsItem.current); dispatchSelectedLocationsAction({ type: 'REMOVE_SELECTED_LOCATION', id: location.id }); }; const sortedActions = useMemo(() => { @@ -23,8 +30,12 @@ const SelectedLocationsItem = ({ location, permissions }) => { const version = location.ContentInfo.Content.CurrentVersion.Version; const thumbnailData = version ? version.Thumbnail : {}; + useEffect(() => { + window.eZ.helpers.tooltips.parse(refSelectedLocationsItem.current); + }, []); + return ( -
+
@@ -40,7 +51,12 @@ const SelectedLocationsItem = ({ location, permissions }) => { return ; })} -
diff --git a/src/modules/universal-discovery/components/selected-locations/selected.locations.js b/src/modules/universal-discovery/components/selected-locations/selected.locations.js index 285ea2cd..54bde702 100644 --- a/src/modules/universal-discovery/components/selected-locations/selected.locations.js +++ b/src/modules/universal-discovery/components/selected-locations/selected.locations.js @@ -1,4 +1,4 @@ -import React, { useContext, useState, Fragment } from 'react'; +import React, { useContext, useState, useEffect, useRef, Fragment } from 'react'; import Icon from '../../../common/icon/icon'; import SelectedLocationsItem from './selected.locations.item'; @@ -7,6 +7,8 @@ import { createCssClassNames } from '../../../common/helpers/css.class.names'; import { SelectedLocationsContext, ConfirmContext, AllowConfirmationContext } from '../../universal.discovery.module'; const SelectedLocations = () => { + const refSelectedLocations = useRef(null); + const refTogglerButton = useRef(null); const [selectedLocations, dispatchSelectedLocationsAction] = useContext(SelectedLocationsContext); const allowConfirmation = useContext(AllowConfirmationContext); const onConfirm = useContext(ConfirmContext); @@ -15,7 +17,15 @@ const SelectedLocations = () => { 'c-selected-locations': true, 'c-selected-locations--expanded': isExpanded, }); + const expandLabel = Translator.trans(/*@Desc("Expand sidebar")*/ 'selected_locations.expand.sidebar', {}, 'universal_discovery_widget'); + const collapseLabel = Translator.trans( + /*@Desc("Collapse sidebar")*/ 'selected_locations.collapse.sidebar', + {}, + 'universal_discovery_widget' + ); + const togglerLabel = isExpanded ? collapseLabel : expandLabel; const clearSelection = () => { + window.eZ.helpers.tooltips.hideAll(refSelectedLocations.current); dispatchSelectedLocationsAction({ type: 'CLEAR_SELECTED_LOCATIONS' }); }; const toggleExpanded = () => { @@ -35,18 +45,41 @@ const SelectedLocations = () => { const iconName = isExpanded ? 'caret-next' : 'caret-back'; return ( - ); }; const renderActionButtons = () => { + const confirmSelectionLabel = Translator.trans( + /*@Desc("Confirm selection")*/ 'selected_locations.confirm_selection', + {}, + 'universal_discovery_widget' + ); + const clearAllLabel = Translator.trans(/*@Desc("Clear all")*/ 'selected_locations.clear_all', {}, 'universal_discovery_widget'); + return ( - - @@ -70,12 +103,21 @@ const SelectedLocations = () => { ); }; + useEffect(() => { + window.eZ.helpers.tooltips.parse(refSelectedLocations.current); + window.eZ.helpers.tooltips.hideAll(); + + if (refTogglerButton.current) { + refTogglerButton.current.dataset.originalTitle = togglerLabel; + } + }, [isExpanded]); + if (!allowConfirmation) { return null; } return ( -
+
{renderToggleButton()} diff --git a/src/modules/universal-discovery/components/sort-switcher/sort.switcher.js b/src/modules/universal-discovery/components/sort-switcher/sort.switcher.js index b50c5b6f..dbf6eb6b 100644 --- a/src/modules/universal-discovery/components/sort-switcher/sort.switcher.js +++ b/src/modules/universal-discovery/components/sort-switcher/sort.switcher.js @@ -34,7 +34,12 @@ const SortSwitcher = ({ isDisabled }) => { }; return ( - + {option.label} ); diff --git a/src/modules/universal-discovery/components/toggle-selection-button/toggle.selection.button.js b/src/modules/universal-discovery/components/toggle-selection-button/toggle.selection.button.js index d29775b2..bd350c60 100644 --- a/src/modules/universal-discovery/components/toggle-selection-button/toggle.selection.button.js +++ b/src/modules/universal-discovery/components/toggle-selection-button/toggle.selection.button.js @@ -1,15 +1,19 @@ -import React, { useContext } from 'react'; +import React, { useContext, useEffect, useRef, useState } from 'react'; import PropTypes from 'prop-types'; import Icon from '../../../common/icon/icon'; import { createCssClassNames } from '../../../common/helpers/css.class.names'; -import { SelectedLocationsContext, MultipleConfigContext } from '../../universal.discovery.module'; +import { SelectedLocationsContext, MultipleConfigContext, ContainersOnlyContext } from '../../universal.discovery.module'; const ToggleSelectionButton = ({ location }) => { + const refToggleSelectionButton = useRef(null); const [selectedLocations, dispatchSelectedLocationsAction] = useContext(SelectedLocationsContext); const [multiple, multipleItemsLimit] = useContext(MultipleConfigContext); const isSelected = selectedLocations.some((selectedItem) => selectedItem.location.id === location.id); + const addLabel = Translator.trans(/*@Desc("Add")*/ 'browser.add', {}, 'universal_discovery_widget'); + const selectedLabel = Translator.trans(/*@Desc("Selected")*/ 'browser.selected', {}, 'universal_discovery_widget'); + const toggleSelectionLabel = isSelected ? selectedLabel : addLabel; const iconName = isSelected ? 'checkmark' : 'create'; const className = createCssClassNames({ 'c-toggle-selection-button': true, @@ -21,12 +25,29 @@ const ToggleSelectionButton = ({ location }) => { dispatchSelectedLocationsAction(action); }; + useEffect(() => { + window.eZ.helpers.tooltips.hideAll(window.document.querySelector('.c-udw-tab')); + + // Title on toggler selection button is dynamic, for this we have to change 'data-original-title'. + // Remove title is neccessary to prevent situation when we have bootsrap and native title. + if (refToggleSelectionButton.current.getAttribute('data-original-title')) { + refToggleSelectionButton.current.removeAttribute('title'); + } + + refToggleSelectionButton.current.setAttribute('data-original-title', toggleSelectionLabel); + }, [isSelected]); + if (multiple && !isSelected && selectedLocations.length >= multipleItemsLimit && multipleItemsLimit !== 0) { return null; } return ( - ); diff --git a/src/modules/universal-discovery/components/view-switcher/view.switcher.js b/src/modules/universal-discovery/components/view-switcher/view.switcher.js index d971dd06..ae9d2296 100644 --- a/src/modules/universal-discovery/components/view-switcher/view.switcher.js +++ b/src/modules/universal-discovery/components/view-switcher/view.switcher.js @@ -20,10 +20,16 @@ const ViewSwitcher = ({ isDisabled }) => { const extraClasses = view.id === currentView ? 'c-menu-button--selected' : ''; const onClick = () => { setCurrentView(view.id); + window.eZ.helpers.tooltips.hideAll(); }; return ( - + ); diff --git a/src/modules/universal-discovery/content.meta.preview.module.js b/src/modules/universal-discovery/content.meta.preview.module.js index d6a1a85e..d0a2d508 100644 --- a/src/modules/universal-discovery/content.meta.preview.module.js +++ b/src/modules/universal-discovery/content.meta.preview.module.js @@ -1,4 +1,4 @@ -import React, { useContext, useMemo } from 'react'; +import React, { useContext, useEffect, useMemo, useState, useRef } from 'react'; import Icon from '../common/icon/icon'; import Thumbnail from '../common/thumbnail/thumbnail'; @@ -15,6 +15,7 @@ import { } from './universal.discovery.module'; const ContentMetaPreview = () => { + const refContentMetaPreview = useRef(null); const [markedLocationId, setMarkedLocationId] = useContext(MarkedLocationIdContext); const [loadedLocationsMap, dispatchLoadedLocationsAction] = useContext(LoadedLocationsMapContext); const contentTypesMap = useContext(ContentTypesMapContext); @@ -29,6 +30,13 @@ const ContentMetaPreview = () => { ); }, [markedLocationId, loadedLocationsMap]); + const bookmarkLabel = Translator.trans(/*@Desc("Bookmark")*/ 'meta_preview.bookmark', {}, 'universal_discovery_widget'); + const previewLabel = Translator.trans(/*@Desc("Preview")*/ 'meta_preview.preview', {}, 'universal_discovery_widget'); + + useEffect(() => { + window.eZ.helpers.tooltips.parse(refContentMetaPreview.current); + }); + if (!locationData || !locationData.location || !locationData.version || markedLocationId === 1) { return null; } @@ -51,7 +59,11 @@ const ContentMetaPreview = () => { }; const renderActions = () => { const previewButton = allowRedirects ? ( - ) : null; @@ -69,13 +81,18 @@ const ContentMetaPreview = () => { const translationsLabel = Translator.trans(/*@Desc("Translations")*/ 'meta_preview.translations', {}, 'universal_discovery_widget'); return ( -
+
{location.ContentInfo.Content.TranslatedName} -
diff --git a/src/modules/universal-discovery/universal.discovery.module.js b/src/modules/universal-discovery/universal.discovery.module.js index 31eeb459..8a079a05 100644 --- a/src/modules/universal-discovery/universal.discovery.module.js +++ b/src/modules/universal-discovery/universal.discovery.module.js @@ -18,14 +18,27 @@ const CLASS_SCROLL_DISABLED = 'ez-scroll-disabled'; export const SORTING_OPTIONS = [ { label: Translator.trans(/*@Desc("Date")*/ 'sorting.date.label', {}, 'universal_discovery_widget'), + tooltipLabel: Translator.trans(/*@Desc("Sort by Date")*/ 'sorting.date.tooltip', {}, 'universal_discovery_widget'), sortClause: 'DatePublished', }, { label: Translator.trans(/*@Desc("Name")*/ 'sorting.name.label', {}, 'universal_discovery_widget'), + tooltipLabel: Translator.trans(/*@Desc("Sort by Name")*/ 'sorting.name.tooltip', {}, 'universal_discovery_widget'), sortClause: 'ContentName', }, ]; -export const VIEWS = [{ id: 'grid', icon: 'view-grid' }, { id: 'finder', icon: 'panels' }]; +export const VIEWS = [ + { + id: 'grid', + icon: 'view-grid', + tooltipLabel: Translator.trans(/*@Desc("Grid view")*/ 'sorting.grid.view', {}, 'universal_discovery_widget'), + }, + { + id: 'finder', + icon: 'panels', + tooltipLabel: Translator.trans(/*@Desc("Panels view")*/ 'sorting.panels.view', {}, 'universal_discovery_widget'), + }, +]; const restInfo = { token: document.querySelector('meta[name="CSRF-Token"]').content, @@ -131,6 +144,7 @@ const UniversalDiscoveryModule = (props) => { loadContentTypes(restInfo, handleLoadContentTypes); window.document.body.dispatchEvent(new CustomEvent('ez-udw-opened')); + window.eZ.helpers.tooltips.parse(window.document.querySelector('.c-udw-tab')); return () => { window.document.body.dispatchEvent(new CustomEvent('ez-udw-closed'));