diff --git a/.eslintrc b/.eslintrc index fa5a87d17..6f009085b 100644 --- a/.eslintrc +++ b/.eslintrc @@ -29,12 +29,6 @@ }, "rules": { "import/order": "off", - "react/function-component-definition": [ - 2, - { - "namedComponents": "arrow-function", - }, - ], "react/jsx-uses-react": "off", "react/react-in-jsx-scope": "off", // remove when possible @@ -109,6 +103,7 @@ }, ], "import/prefer-default-export": "off", + "react/function-component-definition": "off", }, "overrides": [ { diff --git a/cypress/e2e/item/publish/languages.cy.ts b/cypress/e2e/item/publish/languages.cy.ts index bf20dd866..07d2e574d 100644 --- a/cypress/e2e/item/publish/languages.cy.ts +++ b/cypress/e2e/item/publish/languages.cy.ts @@ -1,131 +1,57 @@ -import { Category, CategoryType } from '@graasp/sdk'; +import { PackedFolderItemFactory } from '@graasp/sdk'; import { buildItemPath } from '../../../../src/config/paths'; import { - LANGUAGES_ADD_BUTTON_HEADER, + LANGUAGE_SELECTOR_ID, LIBRARY_SETTINGS_LANGUAGES_ID, - MUI_CHIP_REMOVE_BTN, - buildCategoryDropdownParentSelector, - buildCategorySelectionId, - buildCategorySelectionOptionId, buildDataCyWrapper, - buildDataTestIdWrapper, + buildPublishAttrContainer, buildPublishButtonId, - buildPublishChip, - buildPublishChipContainer, } from '../../../../src/config/selectors'; -import { - ITEM_WITH_LANGUAGE, - SAMPLE_CATEGORIES, -} from '../../../fixtures/categories'; import { PUBLISHED_ITEM } from '../../../fixtures/items'; import { MEMBERS, SIGNED_OUT_MEMBER } from '../../../fixtures/members'; -const LANGUAGES_DATA_CY = buildDataCyWrapper( - buildPublishChipContainer(LIBRARY_SETTINGS_LANGUAGES_ID), -); +const LANGUAGE_CHIP_SELECTOR = `${buildDataCyWrapper( + buildPublishAttrContainer(LIBRARY_SETTINGS_LANGUAGES_ID), +)} [role="button"]`; const openPublishItemTab = (id: string) => cy.get(`#${buildPublishButtonId(id)}`).click(); -const toggleOption = ( - id: string, - categoryType: CategoryType | `${CategoryType}`, -) => { - cy.get(`#${buildCategorySelectionId(categoryType)}`).click(); - cy.get(`#${buildCategorySelectionOptionId(categoryType, id)}`).click(); +const toggleOption = (lang: string) => { + cy.get(`#${LANGUAGE_SELECTOR_ID}`).click(); + cy.get(`[role="option"][data-value="${lang}"]`).click(); }; -const openLanguagesModal = () => { - cy.get(buildDataCyWrapper(LANGUAGES_ADD_BUTTON_HEADER)).click(); +const openLanguageModal = () => { + cy.get(LANGUAGE_CHIP_SELECTOR).click(); }; -describe('Item without language', () => { - it('Display item without language', () => { - const item = { ...ITEM_WITH_LANGUAGE, categories: [] as Category[] }; - cy.setUpApi({ items: [item] }); - cy.visit(buildItemPath(item.id)); - openPublishItemTab(item.id); - - // check for not displaying if no categories - cy.get(LANGUAGES_DATA_CY).should('not.exist'); - }); -}); - describe('Item with language', () => { - const item = ITEM_WITH_LANGUAGE; + const item = PackedFolderItemFactory({ lang: 'fr' }); beforeEach(() => { - cy.setUpApi({ items: [ITEM_WITH_LANGUAGE] }); + cy.setUpApi({ items: [item] }); cy.visit(buildItemPath(item.id)); openPublishItemTab(item.id); }); it('Display item language', () => { // check for displaying value - const { - categories: [{ category }], - } = item; - const { name } = SAMPLE_CATEGORIES.find(({ id }) => id === category.id); - cy.get(LANGUAGES_DATA_CY).contains(name); - }); - - describe('Delete a language', () => { - let id: string; - let category: Category; - let categoryType: Category['type']; - beforeEach(() => { - const { - categories: [itemCategory], - } = item; - ({ category, id } = itemCategory); - categoryType = SAMPLE_CATEGORIES.find( - ({ id: cId }) => cId === category.id, - )?.type; - }); - - afterEach(() => { - cy.wait('@deleteItemCategory').then((data) => { - const { - request: { url }, - } = data; - expect(url.split('/')).contains(id); - }); - }); - - it('Using Dropdown in modal', () => { - openLanguagesModal(); - toggleOption(category.id, categoryType); - }); - - it('Using cross on language tag in modal', () => { - openLanguagesModal(); - - cy.get( - buildDataCyWrapper(buildCategoryDropdownParentSelector(categoryType)), - ) - .find(`[data-tag-index=0] > svg`) - .click(); - }); - - it('Using cross on language container', () => { - cy.get(buildDataCyWrapper(buildPublishChip(category.name))) - .find(buildDataTestIdWrapper(MUI_CHIP_REMOVE_BTN)) - .click(); - }); + cy.get(LANGUAGE_CHIP_SELECTOR).contains('Français'); }); - it('Add a language', () => { - openLanguagesModal(); - const { type, id } = SAMPLE_CATEGORIES[3]; - toggleOption(id, type); + it('Change language', () => { + openLanguageModal(); + toggleOption('es'); - cy.wait('@postItemCategory').then((data) => { + cy.wait('@editItem').then((data) => { const { - request: { url }, + request: { url, body }, } = data; expect(url.split('/')).contains(item.id); + expect(body.lang).to.eq('es'); }); }); }); diff --git a/cypress/fixtures/categories.ts b/cypress/fixtures/categories.ts index b3ad1c972..f641c710d 100644 --- a/cypress/fixtures/categories.ts +++ b/cypress/fixtures/categories.ts @@ -66,16 +66,6 @@ export const ITEM_WITH_CATEGORIES: ItemForTest = { categories: SAMPLE_ITEM_CATEGORIES, }; -export const ITEM_WITH_LANGUAGE: ItemForTest = { - ...PUBLISHED_ITEM, - settings: { - tags: CUSTOMIZED_TAGS, - displayCoEditors: true, - }, - // for tests - categories: SAMPLE_ITEM_LANGUAGE, -}; - export const ITEM_WITH_CATEGORIES_CONTEXT = { items: [ITEM_WITH_CATEGORIES], itemValidationGroups: [ diff --git a/src/components/item/publish/ItemPublishTab.tsx b/src/components/item/publish/ItemPublishTab.tsx index 1ce9ab410..fb2b4a089 100644 --- a/src/components/item/publish/ItemPublishTab.tsx +++ b/src/components/item/publish/ItemPublishTab.tsx @@ -14,7 +14,7 @@ import { import CategoriesContainer from '@/components/item/publish/CategoriesContainer'; import CoEditorsContainer from '@/components/item/publish/CoEditorsContainer'; import EditItemDescription from '@/components/item/publish/EditItemDescription'; -import LanguagesContainer from '@/components/item/publish/LanguagesContainer'; +import { LanguageContainer } from '@/components/item/publish/LanguageContainer'; import LicenseContainer from '@/components/item/publish/LicenseContainer'; import PublicationStatusComponent from '@/components/item/publish/PublicationStatusComponent'; import PublicationThumbnail from '@/components/item/publish/PublicationThumbnail'; @@ -84,7 +84,7 @@ const ItemPublishTab = (): JSX.Element => { - + diff --git a/src/components/item/publish/LanguageContainer.tsx b/src/components/item/publish/LanguageContainer.tsx new file mode 100644 index 000000000..fd292af41 --- /dev/null +++ b/src/components/item/publish/LanguageContainer.tsx @@ -0,0 +1,66 @@ +import { Button, Chip, Stack, Typography } from '@mui/material'; + +import { PackedItem } from '@graasp/sdk'; +import { DEFAULT_LANG, langs } from '@graasp/translations'; + +import useModalStatus from '@/components/hooks/useModalStatus'; +import { useBuilderTranslation } from '@/config/i18n'; +import { LIBRARY_SETTINGS_LANGUAGES_ID } from '@/config/selectors'; +import { BUILDER } from '@/langs/constants'; + +import LanguageSelect from '../settings/LanguageSelect'; +import PublicationAttributeContainer from './PublicationAttributeContainer'; +import PublicationModal from './PublicationModal'; + +type Props = { + item: PackedItem; +}; + +export function LanguageContainer({ item }: Props): JSX.Element { + const { t } = useBuilderTranslation(); + const { isOpen, openModal, closeModal } = useModalStatus(); + + const title = t(BUILDER.ITEM_LANGUAGE_CONTAINER_TITLE); + + const computeKey = (id: string) => `license-${id}`; + + const modalActions = [ + , + ]; + + let currentLang = langs[DEFAULT_LANG]; + if (item.lang in langs) { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + currentLang = langs[item.lang]; + } + + return ( + <> + + {title} + + {t(BUILDER.ITEM_LANGUAGE_DESCRIPTION)} + + + {t(BUILDER.ITEM_LANGUAGE_DESCRIPTION_LIMITATION)} + + + + } + isOpen={isOpen} + handleOnClose={closeModal} + dialogActions={modalActions} + /> + } + /> + + ); +} diff --git a/src/components/item/publish/LanguagesContainer.tsx b/src/components/item/publish/LanguagesContainer.tsx deleted file mode 100644 index 29b92770d..000000000 --- a/src/components/item/publish/LanguagesContainer.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import { Category, CategoryType } from '@graasp/sdk'; - -import { useBuilderTranslation } from '@/config/i18n'; -import { LIBRARY_SETTINGS_LANGUAGES_ID } from '@/config/selectors'; -import { BUILDER } from '@/langs/constants'; - -import ItemCategoryContainer from './ItemCategoryContainer'; - -type Props = { - itemId: string; -}; - -const CHIP_COLOR = '#9a49de'; -const SYNC_STATUS_KEY = 'PublishLanguage'; - -export const LanguagesContainer = ({ itemId }: Props): JSX.Element | null => { - const keepLanguageOnly = ({ type }: Category) => - type === CategoryType.Language; - - const { t } = useBuilderTranslation(); - - const title = t(BUILDER.ITEM_LANGUAGES_CONTAINER_TITLE); - const description = t(BUILDER.ITEM_LANGUAGES_CONTAINER_MISSING_WARNING); - const emptyMessage = t(BUILDER.ITEM_LANGUAGES_CONTAINER_EMPTY_BUTTON); - - return ( - - ); -}; -export default LanguagesContainer; diff --git a/src/components/item/publish/PublicationAttributeContainer.tsx b/src/components/item/publish/PublicationAttributeContainer.tsx index e24a2c0f1..c4de955b0 100644 --- a/src/components/item/publish/PublicationAttributeContainer.tsx +++ b/src/components/item/publish/PublicationAttributeContainer.tsx @@ -36,12 +36,12 @@ type Props = { dataTestId: string; title: string; titleIcon?: JSX.Element; - titleActionBtn: JSX.Element; + titleActionBtn?: JSX.Element; content?: JSX.Element | JSX.Element[]; isLoading?: boolean; - emptyDataMessage: string; - attributeDescription: string; - onEmptyClick: () => void; + emptyDataMessage?: string; + attributeDescription?: string; + onEmptyClick?: () => void; }; export const PublicationAttributeContainer = ({ @@ -83,7 +83,7 @@ export const PublicationAttributeContainer = ({ const handleOnContainerClick = () => { if (hasNoData) { - onEmptyClick(); + onEmptyClick?.(); } }; diff --git a/src/langs/ar.json b/src/langs/ar.json index f34153c82..d9329495f 100644 --- a/src/langs/ar.json +++ b/src/langs/ar.json @@ -97,9 +97,6 @@ "ITEM_CATEGORIES_CONTAINER_TITLE": "الفئة", "ITEM_CATEGORIES_CONTAINER_MISSING_WARNING": "أضف فئة واحدة على الأقل لتحديد الموضوع العالمي للمحتوى الخاص بك بشكل أفضل", "ITEM_CATEGORIES_CONTAINER_EMPTY_BUTTON": "أضف فئة", - "ITEM_LANGUAGES_CONTAINER_TITLE": "اللغات", - "ITEM_LANGUAGES_CONTAINER_MISSING_WARNING": "أضف لغة واحدة على الأقل تمت بها كتابة منشورك", - "ITEM_LANGUAGES_CONTAINER_EMPTY_BUTTON": "أضف لغة", "ITEM_LICENSE_CONTAINER_TITLE": "رخصة", "ITEM_LICENSE_CONTAINER_MISSING_WARNING": "حدد الترخيص لشرح كيفية استخدام المستخدمين الآخرين لمنشورك", "ITEM_LICENSE_CONTAINER_EMPTY_BUTTON": "أضف ترخيصًا", diff --git a/src/langs/constants.ts b/src/langs/constants.ts index 54f75d3e6..20b01a1aa 100644 --- a/src/langs/constants.ts +++ b/src/langs/constants.ts @@ -222,11 +222,9 @@ export const BUILDER = { 'ITEM_CATEGORIES_CONTAINER_MISSING_WARNING', ITEM_CATEGORIES_CONTAINER_EMPTY_BUTTON: 'ITEM_CATEGORIES_CONTAINER_EMPTY_BUTTON', - ITEM_LANGUAGES_CONTAINER_TITLE: 'ITEM_LANGUAGES_CONTAINER_TITLE', - ITEM_LANGUAGES_CONTAINER_MISSING_WARNING: - 'ITEM_LANGUAGES_CONTAINER_MISSING_WARNING', - ITEM_LANGUAGES_CONTAINER_EMPTY_BUTTON: - 'ITEM_LANGUAGES_CONTAINER_EMPTY_BUTTON', + ITEM_LANGUAGE_CONTAINER_TITLE: 'ITEM_LANGUAGE_CONTAINER_TITLE', + ITEM_LANGUAGE_DESCRIPTION: 'ITEM_LANGUAGE_DESCRIPTION', + ITEM_LANGUAGE_DESCRIPTION_LIMITATION: 'ITEM_LANGUAGE_DESCRIPTION_LIMITATION', ITEM_LICENSE_CONTAINER_TITLE: 'ITEM_LICENSE_CONTAINER_TITLE', ITEM_LICENSE_CONTAINER_MISSING_WARNING: 'ITEM_LICENSE_CONTAINER_MISSING_WARNING', diff --git a/src/langs/de.json b/src/langs/de.json index 63acb2bd0..ee457d203 100644 --- a/src/langs/de.json +++ b/src/langs/de.json @@ -97,9 +97,7 @@ "ITEM_CATEGORIES_CONTAINER_TITLE": "Kategorie", "ITEM_CATEGORIES_CONTAINER_MISSING_WARNING": "Fügen Sie mindestens eine Kategorie hinzu, um das globale Thema Ihres Inhalts besser zu definieren", "ITEM_CATEGORIES_CONTAINER_EMPTY_BUTTON": "Kategorie hinzufügen", - "ITEM_LANGUAGES_CONTAINER_TITLE": "Sprachen", - "ITEM_LANGUAGES_CONTAINER_MISSING_WARNING": "Fügen Sie mindestens eine Sprache hinzu", - "ITEM_LANGUAGES_CONTAINER_EMPTY_BUTTON": "Sprache hinzufügen", + "ITEM_LANGUAGE_CONTAINER_TITLE": "Sprache", "ITEM_LICENSE_CONTAINER_TITLE": "Lizenz", "ITEM_LICENSE_CONTAINER_MISSING_WARNING": "Definieren Sie die Lizenz, um zu erklären, wie andere Benutzer Ihre Publikation verwenden können", "ITEM_LICENSE_CONTAINER_EMPTY_BUTTON": "Lizenz hinzufügen", diff --git a/src/langs/en.json b/src/langs/en.json index c738e7750..328567d95 100644 --- a/src/langs/en.json +++ b/src/langs/en.json @@ -100,9 +100,9 @@ "ITEM_CATEGORIES_CONTAINER_TITLE": "Category", "ITEM_CATEGORIES_CONTAINER_MISSING_WARNING": "Add at least one category to better define the global theme of your content", "ITEM_CATEGORIES_CONTAINER_EMPTY_BUTTON": "Add a category", - "ITEM_LANGUAGES_CONTAINER_TITLE": "Languages", - "ITEM_LANGUAGES_CONTAINER_MISSING_WARNING": "Add at least one language in which your publication is written", - "ITEM_LANGUAGES_CONTAINER_EMPTY_BUTTON": "Add a language", + "ITEM_LANGUAGE_CONTAINER_TITLE": "Language", + "ITEM_LANGUAGE_DESCRIPTION": "Choose the language which your item is written in.", + "ITEM_LANGUAGE_DESCRIPTION_LIMITATION": "Graasp proposes a fixed set of languages. If your language is not in the set, you can contact us to discuss about possible support.", "ITEM_LICENSE_CONTAINER_TITLE": "License", "ITEM_LICENSE_CONTAINER_MISSING_WARNING": "Define the license to explain how other users can use your publication", "ITEM_LICENSE_CONTAINER_EMPTY_BUTTON": "Add a license", diff --git a/src/langs/es.json b/src/langs/es.json index c8e926269..4139b0c7c 100644 --- a/src/langs/es.json +++ b/src/langs/es.json @@ -97,9 +97,6 @@ "ITEM_CATEGORIES_CONTAINER_TITLE": "Categoría", "ITEM_CATEGORIES_CONTAINER_MISSING_WARNING": "Añade al menos una categoría para definir mejor el tema global de tu contenido", "ITEM_CATEGORIES_CONTAINER_EMPTY_BUTTON": "Añadir una categoría", - "ITEM_LANGUAGES_CONTAINER_TITLE": "Idiomas", - "ITEM_LANGUAGES_CONTAINER_MISSING_WARNING": "Añade al menos un idioma en el que esté escrita tu publicación.", - "ITEM_LANGUAGES_CONTAINER_EMPTY_BUTTON": "Añadir un idioma", "ITEM_LICENSE_CONTAINER_TITLE": "Licencia", "ITEM_LICENSE_CONTAINER_MISSING_WARNING": "Defina la licencia para explicar cómo otros usuarios pueden usar su publicación.", "ITEM_LICENSE_CONTAINER_EMPTY_BUTTON": "Agregar una licencia", diff --git a/src/langs/fr.json b/src/langs/fr.json index 44ed42dbb..6fe02f5a5 100644 --- a/src/langs/fr.json +++ b/src/langs/fr.json @@ -100,9 +100,9 @@ "ITEM_CATEGORIES_CONTAINER_TITLE": "Catégories", "ITEM_CATEGORIES_CONTAINER_MISSING_WARNING": "Ajoutez au moins une catégorie pour mieux définir la thématique globale de votre contenu", "ITEM_CATEGORIES_CONTAINER_EMPTY_BUTTON": "Ajouter une catégorie", - "ITEM_LANGUAGES_CONTAINER_TITLE": "Langues", - "ITEM_LANGUAGES_CONTAINER_MISSING_WARNING": "Ajoutez au moins une langue dans laquelle votre publication est rédigée", - "ITEM_LANGUAGES_CONTAINER_EMPTY_BUTTON": "Ajouter une langue", + "ITEM_LANGUAGE_CONTAINER_TITLE": "Langue", + "ITEM_LANGUAGE_DESCRIPTION": "Choisissez la langue dans laquelle l'élément est écrit.", + "ITEM_LANGUAGE_DESCRIPTION_LIMITATION": "Graasp propose un set défini de langues. Si votre langue ne fait pas partie de la liste, vous pouvez nous contacter pour discuter d'un éventuel support.", "ITEM_LICENSE_CONTAINER_TITLE": "Licence", "ITEM_LICENSE_CONTAINER_MISSING_WARNING": "Définir la licence pour expliquer comment les autres utilisateurs peuvent utiliser votre publication", "ITEM_LICENSE_CONTAINER_EMPTY_BUTTON": "Ajouter une licence", diff --git a/src/langs/it.json b/src/langs/it.json index 640a3f6b9..fcba40f29 100644 --- a/src/langs/it.json +++ b/src/langs/it.json @@ -97,9 +97,6 @@ "ITEM_CATEGORIES_CONTAINER_TITLE": "Categoria", "ITEM_CATEGORIES_CONTAINER_MISSING_WARNING": "Aggiungi almeno una categoria per definire meglio il tema globale dei tuoi contenuti", "ITEM_CATEGORIES_CONTAINER_EMPTY_BUTTON": "Aggiungi una categoria", - "ITEM_LANGUAGES_CONTAINER_TITLE": "Le lingue", - "ITEM_LANGUAGES_CONTAINER_MISSING_WARNING": "Aggiungi almeno una lingua in cui è scritta la tua pubblicazione", - "ITEM_LANGUAGES_CONTAINER_EMPTY_BUTTON": "Aggiungi una lingua", "ITEM_LICENSE_CONTAINER_TITLE": "Licenza", "ITEM_LICENSE_CONTAINER_MISSING_WARNING": "Definisci la licenza per spiegare come altri utenti possono utilizzare la tua pubblicazione", "ITEM_LICENSE_CONTAINER_EMPTY_BUTTON": "Aggiungi una licenza",