feat: add RTL attr

This commit is contained in:
Mohamed Marrouchi 2024-09-24 07:59:59 +01:00
parent bc17c3d284
commit 16e7431d83
13 changed files with 72 additions and 26 deletions

View File

@ -33,7 +33,7 @@ export const baseLanguage = {
...modelInstance, ...modelInstance,
title: 'English', title: 'English',
code: 'en', code: 'en',
default: true, isDefault: true,
}; };
export const entitiesMock: NlpEntityFull[] = [ export const entitiesMock: NlpEntityFull[] = [

View File

@ -139,7 +139,7 @@ describe('LanguageController', () => {
it('should mark a language as default', async () => { it('should mark a language as default', async () => {
jest.spyOn(languageService, 'updateOne'); jest.spyOn(languageService, 'updateOne');
const translationUpdateDto = { default: true }; const translationUpdateDto = { isDefault: true };
const frLang = await languageService.findOne({ code: 'fr' }); const frLang = await languageService.findOne({ code: 'fr' });
const result = await languageController.updateOne( const result = await languageController.updateOne(
frLang.id, frLang.id,
@ -156,7 +156,7 @@ describe('LanguageController', () => {
}); });
const enLang = await languageService.findOne({ code: 'en' }); const enLang = await languageService.findOne({ code: 'en' });
expect(enLang.default).toBe(false); expect(enLang.isDefault).toBe(false);
}); });
it('should throw a NotFoundException when attempting to update a translation by id', async () => { it('should throw a NotFoundException when attempting to update a translation by id', async () => {
@ -169,7 +169,7 @@ describe('LanguageController', () => {
describe('deleteOne', () => { describe('deleteOne', () => {
it('should throw when attempting to delete the default language', async () => { it('should throw when attempting to delete the default language', async () => {
const defaultLang = await languageService.findOne({ default: true }); const defaultLang = await languageService.findOne({ isDefault: true });
await expect( await expect(
languageController.deleteOne(defaultLang.id), languageController.deleteOne(defaultLang.id),

View File

@ -115,10 +115,10 @@ export class LanguageController extends BaseController<Language> {
@Param('id') id: string, @Param('id') id: string,
@Body() languageUpdate: LanguageUpdateDto, @Body() languageUpdate: LanguageUpdateDto,
): Promise<Language> { ): Promise<Language> {
if ('default' in languageUpdate) { if ('isDefault' in languageUpdate) {
if (languageUpdate.default) { if (languageUpdate.isDefault) {
// A new default language is define, make sure that only one is marked as default // A new default language is define, make sure that only one is marked as default
await this.languageService.updateMany({}, { default: false }); await this.languageService.updateMany({}, { isDefault: false });
} else { } else {
throw new BadRequestException('Should not be able to disable default'); throw new BadRequestException('Should not be able to disable default');
} }
@ -142,7 +142,7 @@ export class LanguageController extends BaseController<Language> {
@HttpCode(204) @HttpCode(204)
async deleteOne(@Param('id') id: string): Promise<DeleteResult> { async deleteOne(@Param('id') id: string): Promise<DeleteResult> {
const result = await this.languageService.deleteOne({ const result = await this.languageService.deleteOne({
default: false, // Prevent deleting the default language isDefault: false, // Prevent deleting the default language
_id: id, _id: id,
}); });
if (result.deletedCount === 0) { if (result.deletedCount === 0) {

View File

@ -25,7 +25,12 @@ export class LanguageCreateDto {
@ApiProperty({ description: 'Is Default Language ?', type: Boolean }) @ApiProperty({ description: 'Is Default Language ?', type: Boolean })
@IsNotEmpty() @IsNotEmpty()
@IsBoolean() @IsBoolean()
default: boolean; isDefault: boolean;
@ApiProperty({ description: 'Whether Language is RTL', type: Boolean })
@IsNotEmpty()
@IsBoolean()
isRTL?: boolean;
} }
export class LanguageUpdateDto extends PartialType(LanguageCreateDto) {} export class LanguageUpdateDto extends PartialType(LanguageCreateDto) {}

View File

@ -31,7 +31,13 @@ export class Language extends BaseSchema {
@Prop({ @Prop({
type: Boolean, type: Boolean,
}) })
default: boolean; isDefault: boolean;
@Prop({
type: Boolean,
default: false,
})
isRTL?: boolean;
} }
export const LanguageModel: ModelDefinition = { export const LanguageModel: ModelDefinition = {

View File

@ -13,11 +13,11 @@ export const languageModels: LanguageCreateDto[] = [
{ {
title: 'English', title: 'English',
code: 'en', code: 'en',
default: true, isDefault: true,
}, },
{ {
title: 'Français', title: 'Français',
code: 'fr', code: 'fr',
default: false, isDefault: false,
}, },
]; ];

View File

@ -54,7 +54,7 @@ export class LanguageService extends BaseService<Language> {
*/ */
@Cacheable(DEFAULT_LANGUAGE_CACHE_KEY) @Cacheable(DEFAULT_LANGUAGE_CACHE_KEY)
async getDefaultLanguage() { async getDefaultLanguage() {
return await this.findOne({ default: true }); return await this.findOne({ isDefault: true });
} }
/** /**

View File

@ -16,12 +16,14 @@ export const languageFixtures: LanguageUpdateDto[] = [
{ {
title: 'English', title: 'English',
code: 'en', code: 'en',
default: true, isDefault: true,
isRTL: false,
}, },
{ {
title: 'Français', title: 'Français',
code: 'fr', code: 'fr',
default: false, isDefault: false,
isRTL: false,
}, },
]; ];

View File

@ -7,9 +7,15 @@
* 3. SaaS Restriction: This software, or any derivative of it, may not be used to offer a competing product or service (SaaS) without prior written consent from Hexastack. Offering the software as a service or using it in a commercial cloud environment without express permission is strictly prohibited. * 3. SaaS Restriction: This software, or any derivative of it, may not be used to offer a competing product or service (SaaS) without prior written consent from Hexastack. Offering the software as a service or using it in a commercial cloud environment without express permission is strictly prohibited.
*/ */
import { Dialog, DialogActions, DialogContent } from "@mui/material"; import {
Dialog,
DialogActions,
DialogContent,
FormControlLabel,
Switch,
} from "@mui/material";
import { FC, useEffect } from "react"; import { FC, useEffect } from "react";
import { useForm } from "react-hook-form"; import { Controller, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import DialogButtons from "@/app-components/buttons/DialogButtons"; import DialogButtons from "@/app-components/buttons/DialogButtons";
@ -56,10 +62,12 @@ export const LanguageDialog: FC<LanguageDialogProps> = ({
register, register,
formState: { errors }, formState: { errors },
handleSubmit, handleSubmit,
control,
} = useForm<ILanguageAttributes>({ } = useForm<ILanguageAttributes>({
defaultValues: { defaultValues: {
title: data?.title || "", title: data?.title || "",
code: data?.code || "", code: data?.code || "",
isRTL: data?.isRTL || false,
}, },
}); });
const validationRules = { const validationRules = {
@ -87,6 +95,7 @@ export const LanguageDialog: FC<LanguageDialogProps> = ({
reset({ reset({
title: data.title, title: data.title,
code: data.code, code: data.code,
isRTL: data.isRTL,
}); });
} else { } else {
reset(); reset();
@ -119,6 +128,18 @@ export const LanguageDialog: FC<LanguageDialogProps> = ({
multiline={true} multiline={true}
/> />
</ContentItem> </ContentItem>
<ContentItem>
<Controller
name="isRTL"
control={control}
render={({ field }) => (
<FormControlLabel
control={<Switch {...field} checked={field.value} />}
label={t("label.is_rtl")}
/>
)}
/>
</ContentItem>
</ContentContainer> </ContentContainer>
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>

View File

@ -71,11 +71,11 @@ export const Languages = () => {
}, },
}); });
const toggleDefault = (row: ILanguage) => { const toggleDefault = (row: ILanguage) => {
if (!row.default) { if (!row.isDefault) {
updateLanguage({ updateLanguage({
id: row.id, id: row.id,
params: { params: {
default: true, isDefault: true,
}, },
}); });
} }
@ -87,7 +87,7 @@ export const Languages = () => {
label: ActionColumnLabel.Toggle, label: ActionColumnLabel.Toggle,
action: (row) => toggleDefault(row), action: (row) => toggleDefault(row),
requires: [PermissionAction.UPDATE], requires: [PermissionAction.UPDATE],
getState: (row) => row.default, getState: (row) => row.isDefault,
helperText: t("button.mark_as_default"), helperText: t("button.mark_as_default"),
}, },
{ {
@ -99,7 +99,7 @@ export const Languages = () => {
label: ActionColumnLabel.Delete, label: ActionColumnLabel.Delete,
action: (row) => deleteDialogCtl.openDialog(row.id), action: (row) => deleteDialogCtl.openDialog(row.id),
requires: [PermissionAction.DELETE], requires: [PermissionAction.DELETE],
isDisabled: (row) => row.default, isDisabled: (row) => row.isDefault,
}, },
], ],
t("label.operations"), t("label.operations"),
@ -124,8 +124,17 @@ export const Languages = () => {
}, },
{ {
flex: 1, flex: 1,
field: "default", field: "isDefault",
headerName: t("label.default"), headerName: t("label.is_default"),
disableColumnMenu: true,
renderHeader,
headerAlign: "left",
valueGetter: (value) => (value ? t("label.yes") : t("label.no")),
},
{
flex: 1,
field: "isRTL",
headerName: t("label.is_rtl"),
disableColumnMenu: true, disableColumnMenu: true,
renderHeader, renderHeader,
headerAlign: "left", headerAlign: "left",

View File

@ -549,7 +549,8 @@
"other": "Other", "other": "Other",
"no_data": "No data", "no_data": "No data",
"code": "Code", "code": "Code",
"default": "Default" "is_default": "Default",
"is_rtl": "RTL"
}, },
"placeholder": { "placeholder": {
"your_username": "Your username", "your_username": "Your username",

View File

@ -549,7 +549,8 @@
"other": "Autre", "other": "Autre",
"no_data": "Pas de données", "no_data": "Pas de données",
"code": "Code", "code": "Code",
"default": "Par Défaut" "is_default": "Par Défaut",
"is_rtl": "RTL"
}, },
"placeholder": { "placeholder": {
"your_username": "Votre nom d'utilisateur", "your_username": "Votre nom d'utilisateur",

View File

@ -16,7 +16,8 @@ export type ILanguages = Record<string, string>;
export interface ILanguageAttributes { export interface ILanguageAttributes {
title: string; title: string;
code: string; code: string;
default: boolean; isDefault: boolean;
isRTL: boolean;
} }
export interface ILanguageStub export interface ILanguageStub