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 () => {