diff --git a/src/components/BaseSettings/BaseSettingsComponent.tsx b/src/components/BaseSettings/BaseSettingsComponent.tsx index 92c7df0a3b..92f0c95dca 100644 --- a/src/components/BaseSettings/BaseSettingsComponent.tsx +++ b/src/components/BaseSettings/BaseSettingsComponent.tsx @@ -29,7 +29,7 @@ export default function BaseSettingsComponent( toggleVisibility()} > diff --git a/src/components/ProjectSettings/ProjectLanguages.tsx b/src/components/ProjectSettings/ProjectLanguages.tsx index ccd998e31f..bf822e80a8 100644 --- a/src/components/ProjectSettings/ProjectLanguages.tsx +++ b/src/components/ProjectSettings/ProjectLanguages.tsx @@ -27,6 +27,12 @@ import theme from "types/theme"; import { newWritingSystem, semDomWritingSystems } from "types/writingSystem"; import { getAnalysisLangsFromWords } from "utilities/wordUtilities"; +const addAnalysisLangButtonId = "analysis-language-new"; +const addAnalysisLangCleanButtonId = "analysis-language-new-clear"; +const addAnalysisLangConfirmButtonId = "analysis-language-new-confirm"; +const getProjAnalysisLangsButtonId = "analysis-language-get"; +const semDomLangSelectId = "semantic-domains-language"; + export default function ProjectLanguages( props: ProjectSettingPropsWithUpdate ): ReactElement { @@ -89,7 +95,7 @@ export default function ProjectLanguages( }; const writingSystemButtons = (index: number): ReactElement => { - return index === 0 ? ( + return index === 0 || props.readOnly ? ( // The top writing system is default and needs no buttons. ) : ( @@ -139,16 +145,104 @@ export default function ProjectLanguages( setNewLang(newWritingSystem()); }; + const addAnalysisLangButtons = (): ReactElement => ( + <> + } + textId="projectSettings.language.addAnalysisLanguage" + onClick={() => setAdd(true)} + buttonId={addAnalysisLangButtonId} + /> + } + textId="projectSettings.language.getGlossLanguages" + onClick={() => getActiveAnalysisLangs()} + buttonId={getProjAnalysisLangsButtonId} + /> + {langsInProj} + + ); + + const addAnalysisLangPicker = (): ReactElement => ( + + + + setNewLang((prev: WritingSystem) => ({ ...prev, bcp47 })) + } + name={newLang.bcp47} + setName={(name: string) => + setNewLang((prev: WritingSystem) => ({ ...prev, name })) + } + font={newLang.font} + setFont={(font: string) => + setNewLang((prev: WritingSystem) => ({ ...prev, font })) + } + t={languagePickerStrings_en} + /> + {" "} + + addAnalysisWritingSystem()} + id={addAnalysisLangConfirmButtonId} + size="large" + > + + + {" "} + + resetState()} + id={addAnalysisLangCleanButtonId} + size="large" + > + + + + + ); + + const semDomLangSelect = (): ReactElement => ( + + ); + return ( <> - + {/* Vernacular language */} + {t("projectSettings.language.vernacular")} - {": "} - + + {/* Analysis languages */} + {t("projectSettings.language.analysis")} - {": "} {props.project.analysisWritingSystems.map((writingSystem, index) => ( ))} - {add ? ( - - - - setNewLang((prev: WritingSystem) => ({ ...prev, bcp47 })) - } - name={newLang.bcp47} - setName={(name: string) => - setNewLang((prev: WritingSystem) => ({ ...prev, name })) - } - font={newLang.font} - setFont={(font: string) => - setNewLang((prev: WritingSystem) => ({ ...prev, font })) - } - t={languagePickerStrings_en} - /> - {" "} - - addAnalysisWritingSystem()} - id="analysis-language-new-confirm" - size="large" - > - - - {" "} - - resetState()} - id="analysis-language-new-clear" - size="large" - > - - - - - ) : ( - <> - } - textId="projectSettings.language.addAnalysisLanguage" - onClick={() => setAdd(true)} - buttonId={"analysis-language-new"} - /> - } - textId="projectSettings.language.getGlossLanguages" - onClick={() => getActiveAnalysisLangs()} - buttonId={"analysis-language-get"} - /> - {langsInProj} - - )} - + {!props.readOnly && + (add ? addAnalysisLangPicker() : addAnalysisLangButtons())} + + {/* Semantic domains language */} + {t("projectSettings.language.semanticDomains")} - {": "} - + {props.readOnly ? ( + props.project.semDomWritingSystem.bcp47 ? ( + + ) : ( + + {t("projectSettings.language.semanticDomainsDefault")} + + ) + ) : ( + semDomLangSelect() + )} ); } @@ -265,25 +292,21 @@ function ImmutableWritingSystem( {`${props.index + 1}. `} )} - {!!props.ws.name && ( - - + + {!!props.ws.name && ( + {`${t("projectSettings.language.name")}: ${props.ws.name}, `} - - )} - - + )} + {`${t("projectSettings.language.bcp47")}: ${props.ws.bcp47}`} - - {!!props.ws.font && ( - - + {!!props.ws.font && ( + {`, ${t("projectSettings.language.font")}: ${props.ws.font}`} - - )} + )} + {props.buttons} ); diff --git a/src/components/ProjectSettings/ProjectSettingsTypes.ts b/src/components/ProjectSettings/ProjectSettingsTypes.ts index 81033420c0..40d9273791 100644 --- a/src/components/ProjectSettings/ProjectSettingsTypes.ts +++ b/src/components/ProjectSettings/ProjectSettingsTypes.ts @@ -7,5 +7,6 @@ export interface ProjectSettingPropsWithSet { export interface ProjectSettingPropsWithUpdate { project: Project; + readOnly?: boolean; updateProject: (project: Project) => Promise; } diff --git a/src/components/ProjectSettings/index.tsx b/src/components/ProjectSettings/index.tsx index b3291e83c3..9390e46f3c 100644 --- a/src/components/ProjectSettings/index.tsx +++ b/src/components/ProjectSettings/index.tsx @@ -96,16 +96,20 @@ export default function ProjectSettingsComponent() { /> )} - {/*Project Vernacular and Analysis Languages*/} - {permissions.includes(Permission.DeleteEditSettingsAndUsers) && ( - } - title={t("projectSettings.language.languages")} - body={ - - } - /> - )} + {/*Project languages*/} + } + title={t("projectSettings.language.languages")} + body={ + + } + /> {/* Import Lift file */} {permissions.includes(Permission.Import) && ( diff --git a/src/components/ProjectSettings/tests/ProjectLangauges.test.tsx b/src/components/ProjectSettings/tests/ProjectLangauges.test.tsx index 6b67727a3b..31b15bc675 100644 --- a/src/components/ProjectSettings/tests/ProjectLangauges.test.tsx +++ b/src/components/ProjectSettings/tests/ProjectLangauges.test.tsx @@ -1,3 +1,4 @@ +import { Button, Select } from "@mui/material"; import { LanguagePicker } from "mui-language-picker"; import renderer from "react-test-renderer"; @@ -22,11 +23,18 @@ function mockProject(systems?: WritingSystem[]) { return { ...newProject(), analysisWritingSystems: systems ?? [] }; } -const renderProjLangs = async (project: Project): Promise => { +const renderProjLangs = async ( + project: Project, + readOnly = false +): Promise => { mockUpdateProject.mockResolvedValue(undefined); await renderer.act(async () => { projectMaster = renderer.create( - + ); }); }; @@ -43,8 +51,10 @@ const renderAndClickAdd = async (): Promise => { }; describe("ProjectLanguages", () => { - it("renders", async () => { - await renderProjLangs(mockProject([...mockAnalysisWritingSystems])); + it("renders readOnly", async () => { + await renderProjLangs(mockProject([...mockAnalysisWritingSystems]), true); + expect(projectMaster.root.findAllByType(Button)).toHaveLength(0); + expect(projectMaster.root.findAllByType(Select)).toHaveLength(0); }); it("can add language to project", async () => { diff --git a/src/components/ProjectSettings/tests/index.test.tsx b/src/components/ProjectSettings/tests/index.test.tsx index cf1d4096cd..be5187ef0a 100644 --- a/src/components/ProjectSettings/tests/index.test.tsx +++ b/src/components/ProjectSettings/tests/index.test.tsx @@ -19,6 +19,7 @@ import "tests/reactI18nextMock"; import { Permission } from "api/models"; import BaseSettingsComponent from "components/BaseSettings/BaseSettingsComponent"; import ProjectSettings from "components/ProjectSettings"; +import ProjectLanguages from "components/ProjectSettings/ProjectLanguages"; import { randomProject } from "types/project"; jest.mock("react-router-dom", () => ({ @@ -94,14 +95,16 @@ beforeEach(() => { resetMocks(); }); -const withNoPerm = [List]; // icon for ProjectSwitch +const withNoPerm = [ + List, // icon for ProjectSwitch + Language, // icon for ProjectLanguages (but readOnly w/o DeleteEditPerm) +]; const withArchivePerm = [Archive]; // icon for archive component const withDeleteEditPerm = [ Edit, // icon for ProjectName - Language, // icon for ProjectLanguages, People, // icon for ActiveProjectUsers PersonAdd, // icon for AddProjectUsers - Sms, // icon for ProjectAutocomplete, + Sms, // icon for ProjectAutocomplete ]; const withExportPerm = [GetApp]; // icon for ExportButton const withImportPerm = [CloudUpload]; // icon for ProjectImport @@ -116,6 +119,10 @@ describe("ProjectSettings", () => { expect( projSettingsInstance.findAllByType(BaseSettingsComponent) ).toHaveLength(withNoPerm.length); + + expect( + projSettingsInstance.findByType(ProjectLanguages).props.readOnly + ).toBeTruthy(); }); test("with Permission.Archive", async () => { @@ -140,6 +147,10 @@ describe("ProjectSettings", () => { expect( projSettingsInstance.findAllByType(BaseSettingsComponent) ).toHaveLength(withNoPerm.length + withDeleteEditPerm.length); + + expect( + projSettingsInstance.findByType(ProjectLanguages).props.readOnly + ).toBeFalsy(); }); test("with Permission.Export", async () => {