Translate app

This commit is contained in:
Nicola Benaglia
2025-05-16 09:08:45 +02:00
parent 45e5e9b660
commit daa8a9145b
12 changed files with 352 additions and 109 deletions

View File

@@ -54,13 +54,23 @@ export const AppsDesktop = ({
const myApp = useMemo(() => {
return availableQapps.find(
(app) => app.name === myName && app.service === 'APP'
(app) =>
app.name === myName &&
app.service ===
t('core:app', {
postProcess: 'capitalizeAll',
})
);
}, [myName, availableQapps]);
const myWebsite = useMemo(() => {
return availableQapps.find(
(app) => app.name === myName && app.service === 'WEBSITE'
(app) =>
app.name === myName &&
app.service ===
t('core:website', {
postProcess: 'capitalizeAll',
})
);
}, [myName, availableQapps]);
@@ -247,7 +257,6 @@ export const AppsDesktop = ({
setTabs((prev) => [...prev, newTab]);
setSelectedTab(newTab);
setMode('viewer');
setIsNewTabWindow(false);
};
@@ -258,6 +267,7 @@ export const AppsDesktop = ({
unsubscribeFromEvent('addTab', addTabFunc);
};
}, [tabs]);
const setSelectedTabFunc = (e) => {
const data = e.detail?.data;
if (e.detail?.isDevMode) return;
@@ -327,9 +337,9 @@ export const AppsDesktop = ({
return (
<AppsParent
sx={{
position: !show && 'fixed',
left: !show && '-200vw',
flexDirection: 'row',
left: !show && '-200vw',
position: !show && 'fixed',
}}
>
<Box
@@ -450,6 +460,7 @@ export const AppsDesktop = ({
}}
>
<Spacer height="30px" />
<AppsHomeDesktop
myName={myName}
availableQapps={availableQapps}
@@ -476,15 +487,18 @@ export const AppsDesktop = ({
{mode === 'appInfo-from-category' && !selectedTab && (
<AppInfo app={selectedAppInfo} myName={myName} />
)}
<AppsCategoryDesktop
availableQapps={availableQapps}
isShow={mode === 'category' && !selectedTab}
category={selectedCategory}
myName={myName}
/>
{mode === 'publish' && !selectedTab && (
<AppPublish names={myName ? [myName] : []} categories={categories} />
)}
{tabs.map((tab) => {
if (!iframeRefs.current[tab.tabId]) {
iframeRefs.current[tab.tabId] = React.createRef();

View File

@@ -1,7 +1,6 @@
import React, { useEffect, useRef, useState } from 'react';
import { AppsDevModeHome } from './AppsDevModeHome';
import { Spacer } from '../../common/Spacer';
import {
executeEvent,
subscribeToEvent,
@@ -10,7 +9,6 @@ import {
import { AppsParent } from './Apps-styles';
import AppViewerContainer from './AppViewerContainer';
import ShortUniqueId from 'short-unique-id';
import { Box, ButtonBase, useTheme } from '@mui/material';
import { HomeIcon } from '../../assets/Icons/HomeIcon';
import { Save } from '../Save/Save';
@@ -137,7 +135,6 @@ export const AppsDevMode = ({
setTabs(copyTabs);
setSelectedTab(newTab);
setMode('viewer');
setIsNewTabWindow(false);
};
@@ -260,6 +257,7 @@ export const AppsDevMode = ({
}
/>
</ButtonBase>
<ButtonBase
onClick={() => {
setDesktopViewMode('apps');
@@ -282,6 +280,7 @@ export const AppsDevMode = ({
/>
</IconWrapper>
</ButtonBase>
<ButtonBase
onClick={() => {
setDesktopViewMode('chat');
@@ -351,6 +350,7 @@ export const AppsDevMode = ({
}}
>
<Spacer height="30px" />
<AppsDevModeHome
myName={myName}
availableQapps={availableQapps}

View File

@@ -1,14 +1,12 @@
import React, { useContext, useMemo, useState } from 'react';
import { useContext, useState } from 'react';
import {
AppCircle,
AppCircleContainer,
AppCircleLabel,
AppLibrarySubTitle,
AppsContainer,
AppsParent,
} from './Apps-styles';
import { Buffer } from 'buffer';
import {
Avatar,
Box,
@@ -17,13 +15,11 @@ import {
Dialog,
DialogActions,
DialogContent,
DialogContentText,
DialogTitle,
Input,
} from '@mui/material';
import { Add } from '@mui/icons-material';
import { MyContext, getBaseApiReact } from '../../App';
import LogoSelected from '../../assets/svgs/LogoSelected.svg';
import { executeEvent } from '../../utils/events';
import { Spacer } from '../../common/Spacer';
import { useModal } from '../../common/useModal';
@@ -31,6 +27,8 @@ import { createEndpoint, isUsingLocal } from '../../background';
import { Label } from '../Group/AddGroup';
import ShortUniqueId from 'short-unique-id';
import swaggerSVG from '../../assets/svgs/swagger.svg';
import { useTranslation } from 'react-i18next';
const uid = new ShortUniqueId({ length: 8 });
export const AppsDevModeHome = ({
@@ -43,7 +41,7 @@ export const AppsDevModeHome = ({
const [domain, setDomain] = useState('127.0.0.1');
const [port, setPort] = useState('');
const [selectedPreviewFile, setSelectedPreviewFile] = useState(null);
const { t } = useTranslation(['core', 'group']);
const { isShow, onCancel, onOk, show, message } = useModal();
const {
openSnackGlobal,
@@ -61,6 +59,7 @@ export const AppsDevModeHome = ({
console.log('No file selected.');
}
};
const handleSelectDirectry = async (existingDirectoryPath) => {
const { buffer, directoryPath } =
await window.electron.selectAndZipDirectory(existingDirectoryPath);
@@ -79,8 +78,7 @@ export const AppsDevModeHome = ({
setInfoSnackCustom({
type: 'error',
message:
'Please use your local node for dev mode! Logout and use Local node.',
message: '',
});
return;
}
@@ -115,20 +113,21 @@ export const AppsDevModeHome = ({
const usingLocal = await isUsingLocal();
if (!usingLocal) {
setOpenSnackGlobal(true);
setInfoSnackCustom({
type: 'error',
message:
'Please use your local node for dev mode! Logout and use Local node.',
message: t('core:message.generic.devmode_local_node', {
postProcess: 'capitalizeFirst',
}),
});
return;
}
if (!myName) {
setOpenSnackGlobal(true);
setInfoSnackCustom({
type: 'error',
message: 'You need a name to use preview',
message: t('core:message.generic.name_preview', {
postProcess: 'capitalizeFirst',
}),
});
return;
}
@@ -137,15 +136,16 @@ export const AppsDevModeHome = ({
if (!buffer) {
setOpenSnackGlobal(true);
setInfoSnackCustom({
type: 'error',
message: 'Please select a file',
message: t('core:message.generic.select_file', {
postProcess: 'capitalizeFirst',
}),
});
return;
}
const postBody = Buffer.from(buffer).toString('base64');
const postBody = Buffer.from(buffer).toString('base64');
const endpoint = await createEndpoint(
`/arbitrary/APP/${myName}/zip?preview=true`
);
@@ -156,6 +156,7 @@ export const AppsDevModeHome = ({
},
body: postBody,
});
if (!response?.ok) throw new Error('Invalid zip');
const previewPath = await response.text();
if (tabId) {
@@ -192,20 +193,21 @@ export const AppsDevModeHome = ({
const usingLocal = await isUsingLocal();
if (!usingLocal) {
setOpenSnackGlobal(true);
setInfoSnackCustom({
type: 'error',
message:
'Please use your local node for dev mode! Logout and use Local node.',
message: t('core:message.generic.devmode_local_node', {
postProcess: 'capitalizeFirst',
}),
});
return;
}
if (!myName) {
setOpenSnackGlobal(true);
setInfoSnackCustom({
type: 'error',
message: 'You need a name to use preview',
message: t('core:message.generic.name_preview', {
postProcess: 'capitalizeFirst',
}),
});
return;
}
@@ -214,15 +216,16 @@ export const AppsDevModeHome = ({
if (!buffer) {
setOpenSnackGlobal(true);
setInfoSnackCustom({
type: 'error',
message: 'Please select a file',
message: t('core:message.generic.select_file', {
postProcess: 'capitalizeFirst',
}),
});
return;
}
const postBody = Buffer.from(buffer).toString('base64');
const postBody = Buffer.from(buffer).toString('base64');
const endpoint = await createEndpoint(
`/arbitrary/APP/${myName}/zip?preview=true`
);
@@ -233,8 +236,15 @@ export const AppsDevModeHome = ({
},
body: postBody,
});
if (!response?.ok) throw new Error('Invalid zip');
if (!response?.ok)
throw new Error(
t('core:message.error.invalid_zip', {
postProcess: 'capitalizeFirst',
})
);
const previewPath = await response.text();
if (tabId) {
executeEvent('appsDevModeUpdateTab', {
data: {
@@ -276,7 +286,7 @@ export const AppsDevModeHome = ({
fontSize: '30px',
}}
>
Dev Mode Apps
{t('core:devmode_apps', { postProcess: 'capitalizeFirst' })}
</AppLibrarySubTitle>
</AppsContainer>
@@ -301,7 +311,9 @@ export const AppsDevModeHome = ({
<AppCircle>
<Add>+</Add>
</AppCircle>
<AppCircleLabel>Server</AppCircleLabel>
<AppCircleLabel>
{t('core:server', { postProcess: 'capitalizeFirst' })}
</AppCircleLabel>
</AppCircleContainer>
</ButtonBase>
@@ -319,7 +331,9 @@ export const AppsDevModeHome = ({
<Add>+</Add>
</AppCircle>
<AppCircleLabel>Zip</AppCircleLabel>
<AppCircleLabel>
{t('core:zip', { postProcess: 'capitalizeFirst' })}
</AppCircleLabel>
</AppCircleContainer>
</ButtonBase>
@@ -336,7 +350,9 @@ export const AppsDevModeHome = ({
<AppCircle>
<Add>+</Add>
</AppCircle>
<AppCircleLabel>Directory</AppCircleLabel>
<AppCircleLabel>
{t('core:directory', { postProcess: 'capitalizeFirst' })}
</AppCircleLabel>
</AppCircleContainer>
</ButtonBase>
@@ -365,7 +381,9 @@ export const AppsDevModeHome = ({
objectFit: 'fill',
},
}}
alt="Q-Sandbox"
alt={t('core:q_apps.q_sandbox', {
postProcess: 'capitalizeFirst',
})}
src={`${getBaseApiReact()}/arbitrary/THUMBNAIL/Q-Sandbox/qortal_avatar?async=true`}
>
<img
@@ -378,7 +396,11 @@ export const AppsDevModeHome = ({
</Avatar>
</AppCircle>
<AppCircleLabel>Q-Sandbox</AppCircleLabel>
<AppCircleLabel>
{t('core:q_apps.q_sandbox', {
postProcess: 'capitalizeFirst',
})}
</AppCircleLabel>
</AppCircleContainer>
</ButtonBase>
@@ -407,7 +429,9 @@ export const AppsDevModeHome = ({
objectFit: 'fill',
},
}}
alt="API"
alt={t('core:api', {
postProcess: 'capitalizeAll',
})}
src={swaggerSVG}
>
<img
@@ -420,7 +444,11 @@ export const AppsDevModeHome = ({
</Avatar>
</AppCircle>
<AppCircleLabel>API</AppCircleLabel>
<AppCircleLabel>
{t('core:api', {
postProcess: 'capitalizeAll',
})}
</AppCircleLabel>
</AppCircleContainer>
</ButtonBase>
</AppsContainer>
@@ -437,7 +465,9 @@ export const AppsDevModeHome = ({
}}
>
<DialogTitle id="alert-dialog-title">
{'Add custom framework'}
{t('core:action.add_custom_framework', {
postProcess: 'capitalizeFirst',
})}
</DialogTitle>
<DialogContent>
@@ -446,15 +476,22 @@ export const AppsDevModeHome = ({
display: 'flex',
flexDirection: 'column',
gap: '5px',
}} // TODO translate
}}
>
<Label>Domain</Label>
<Label>
{t('core:domain', {
postProcess: 'capitalizeFirst',
})}
</Label>
<Input
placeholder="Domain"
placeholder={t('core:domain', {
postProcess: 'capitalizeFirst',
})}
value={domain}
onChange={(e) => setDomain(e.target.value)}
/>
</Box>
<Box
sx={{
display: 'flex',
@@ -463,9 +500,15 @@ export const AppsDevModeHome = ({
marginTop: '15px',
}}
>
<Label>Port</Label>
<Label>
{t('core:port', {
postProcess: 'capitalizeFirst',
})}
</Label>
<Input
placeholder="Port"
placeholder={t('core:port', {
postProcess: 'capitalizeFirst',
})}
value={port}
onChange={(e) => setPort(e.target.value)}
/>
@@ -474,15 +517,20 @@ export const AppsDevModeHome = ({
<DialogActions>
<Button variant="contained" onClick={onCancel}>
Close
{t('core:action.close', {
postProcess: 'capitalizeFirst',
})}
</Button>
<Button
disabled={!domain || !port}
variant="contained"
onClick={() => onOk({ portVal: port, domainVal: domain })}
autoFocus
>
Add
{t('core:action.add', {
postProcess: 'capitalizeFirst',
})}
</Button>
</DialogActions>
</Dialog>

View File

@@ -23,7 +23,6 @@ export const AppsDevModeNavBar = () => {
const [navigationController, setNavigationController] = useAtom(
navigationControllerAtom
);
const theme = useTheme();
const [isNewTabWindow, setIsNewTabWindow] = useState(false);
const tabsRef = useRef(null);

View File

@@ -16,6 +16,7 @@ import ArrowOutwardIcon from '@mui/icons-material/ArrowOutward';
import { AppsPrivate } from './AppsPrivate';
import ThemeSelector from '../Theme/ThemeSelector';
import LanguageSelector from '../Language/LanguageSelector';
import { useTranslation } from 'react-i18next';
export const AppsHomeDesktop = ({
setMode,
@@ -26,6 +27,7 @@ export const AppsHomeDesktop = ({
}) => {
const [qortalUrl, setQortalUrl] = useState('');
const theme = useTheme();
const { t } = useTranslation(['core', 'group']);
const openQortalUrl = () => {
try {
@@ -41,6 +43,7 @@ export const AppsHomeDesktop = ({
console.log(error);
}
};
return (
<>
<AppsContainer
@@ -51,9 +54,9 @@ export const AppsHomeDesktop = ({
<AppLibrarySubTitle
sx={{
fontSize: '30px',
}} // TODO translate
}}
>
Apps Dashboard
{t('core:apps_dashboard', { postProcess: 'capitalizeFirst' })}
</AppLibrarySubTitle>
</AppsContainer>
@@ -66,14 +69,14 @@ export const AppsHomeDesktop = ({
>
<Box
sx={{
display: 'flex',
gap: '20px',
alignItems: 'center',
backgroundColor: theme.palette.background.paper,
padding: '7px',
borderRadius: '20px',
width: '100%',
display: 'flex',
gap: '20px',
maxWidth: '500px',
padding: '7px',
width: '100%',
}}
>
<Input
@@ -143,7 +146,9 @@ export const AppsHomeDesktop = ({
<AddIcon />
</AppCircle>
<AppCircleLabel>Library</AppCircleLabel>
<AppCircleLabel>
{t('core:library', { postProcess: 'capitalizeFirst' })}
</AppCircleLabel>
</AppCircleContainer>
</ButtonBase>

View File

@@ -41,6 +41,7 @@ import { Virtuoso } from 'react-virtuoso';
import { executeEvent } from '../../utils/events';
import { ComposeP, ShowMessageReturnButton } from '../Group/Forum/Mail-styles';
import { ReturnIcon } from '../../assets/Icons/ReturnIcon.tsx';
import { useTranslation } from 'react-i18next';
const officialAppList = [
'q-tube',
@@ -104,6 +105,7 @@ export const AppsLibraryDesktop = ({
const [searchValue, setSearchValue] = useState('');
const virtuosoRef = useRef(null);
const theme = useTheme();
const { t } = useTranslation(['core', 'group']);
const officialApps = useMemo(() => {
return availableQapps.filter(
@@ -210,9 +212,13 @@ export const AppsLibraryDesktop = ({
ml: 1,
paddingLeft: '12px',
}}
placeholder="Search for apps"
placeholder={t('core:action.search_apps', {
postProcess: 'capitalizeFirst',
})}
inputProps={{
'aria-label': 'Search for apps',
'aria-label': t('core:action.search_apps', {
postProcess: 'capitalizeFirst',
}),
fontSize: '16px',
fontWeight: 400,
}}
@@ -273,10 +279,14 @@ export const AppsLibraryDesktop = ({
}}
onClick={() => {
executeEvent('navigateBack', {});
}} // TODO translate
}}
>
<ReturnIcon />
<ComposeP>Return to Apps Dashboard</ComposeP>
<ComposeP>
{t('core:action.return_apps_dashboard', {
postProcess: 'capitalizeFirst',
})}
</ComposeP>
</ShowMessageReturnButton>
<Spacer height="20px" />
@@ -302,7 +312,11 @@ export const AppsLibraryDesktop = ({
</AppsWidthLimiter>
) : searchedList?.length === 0 && debouncedValue ? (
<AppsWidthLimiter>
<Typography>No results</Typography>
<Typography>
{t('core:message.generic.no_results', {
postProcess: 'capitalizeFirst',
})}
</Typography>
</AppsWidthLimiter>
) : (
<>
@@ -311,7 +325,7 @@ export const AppsLibraryDesktop = ({
fontSize: '30px',
}}
>
Official Apps
{t('core:apps_official', { postProcess: 'capitalizeFirst' })}
</AppLibrarySubTitle>
<Spacer height="45px" />
@@ -396,7 +410,13 @@ export const AppsLibraryDesktop = ({
textAlign: 'start',
}}
>
{hasPublishApp ? 'Update your app' : 'Publish your app'}
{hasPublishApp
? t('core:action.update_app', {
postProcess: 'capitalizeFirst',
})
: t('core:action.publish_app', {
postProcess: 'capitalizeFirst',
})}
</AppLibrarySubTitle>
<Spacer height="18px" />
@@ -422,7 +442,13 @@ export const AppsLibraryDesktop = ({
}}
>
<PublishQAppCTAButton>
{hasPublishApp ? 'Update' : 'Publish'}
{hasPublishApp
? t('core:action.update', {
postProcess: 'capitalizeFirst',
})
: t('core:action.publish', {
postProcess: 'capitalizeFirst',
})}
</PublishQAppCTAButton>
<Spacer width="20px" />
@@ -441,7 +467,9 @@ export const AppsLibraryDesktop = ({
fontSize: '30px',
}}
>
Categories
{t('core:category_other', {
postProcess: 'capitalizeFirst',
})}
</AppLibrarySubTitle>
<Spacer height="18px" />
@@ -480,7 +508,7 @@ export const AppsLibraryDesktop = ({
},
}}
>
All
{t('core:all', { postProcess: 'capitalizeFirst' })}
</Box>
</ButtonBase>

View File

@@ -32,6 +32,7 @@ import {
sortablePinnedAppsAtom,
} from '../../atoms/global';
import { useAtom, useSetAtom } from 'jotai';
import { useTranslation } from 'react-i18next';
export function saveToLocalStorage(key, subKey, newValue) {
try {
@@ -75,7 +76,7 @@ export const AppsNavBarDesktop = ({ disableBack }) => {
);
const theme = useTheme();
const { t } = useTranslation(['core', 'group']);
const [isNewTabWindow, setIsNewTabWindow] = useState(false);
const tabsRef = useRef(null);
const [anchorEl, setAnchorEl] = useState(null);
@@ -238,6 +239,7 @@ export const AppsNavBarDesktop = ({ disableBack }) => {
}}
/>
</ButtonBase>
<ButtonBase
onClick={(e) => {
if (!selectedTab) return;
@@ -274,9 +276,9 @@ export const AppsNavBarDesktop = ({ disableBack }) => {
paper: {
sx: {
backgroundColor: theme.palette.background.default,
borderRadius: '5px',
color: theme.palette.text.primary,
width: '148px',
borderRadius: '5px',
},
},
}}
@@ -375,9 +377,18 @@ export const AppsNavBarDesktop = ({ disableBack }) => {
: theme.palette.text.primary,
},
}}
primary={`${isSelectedAppPinned ? 'Unpin app' : 'Pin app'}`}
primary={`${
isSelectedAppPinned
? t('core:action.unpin_app', {
postProcess: 'capitalizeFirst',
})
: t('core:action.pin_app', {
postProcess: 'capitalizeFirst',
})
}}`}
/>
</MenuItem>
<MenuItem
onClick={() => {
if (selectedTab?.refreshFunc) {
@@ -404,6 +415,7 @@ export const AppsNavBarDesktop = ({ disableBack }) => {
}}
/>
</ListItemIcon>
<ListItemText
sx={{
'& .MuiTypography-root': {
@@ -447,7 +459,9 @@ export const AppsNavBarDesktop = ({ disableBack }) => {
color: theme.palette.text.primary,
},
}}
primary="Copy link"
primary={t('core:action.copy_link', {
postProcess: 'capitalizeFirst',
})}
/>
</MenuItem>
)}

View File

@@ -36,6 +36,7 @@ import { fileToBase64 } from '../../utils/fileReading';
import { objectToBase64 } from '../../qdn/encryption/group-encryption';
import { getFee } from '../../background';
import { useAtom } from 'jotai';
import { useTranslation } from 'react-i18next';
const maxFileSize = 50 * 1024 * 1024; // 50MB
@@ -62,6 +63,7 @@ export const AppsPrivate = ({ myName }) => {
const [memberGroups] = useAtom(memberGroupsAtom);
const theme = useTheme();
const { t } = useTranslation(['core', 'group']);
const myGroupsPrivate = useMemo(() => {
return memberGroups?.filter(
@@ -98,9 +100,11 @@ export const AppsPrivate = ({ myName }) => {
errors.forEach((error) => {
if (error.code === 'file-too-large') {
console.error(
`File ${file.name} is too large. Max size allowed is ${
maxFileSize / (1024 * 1024)
} MB.`
t('core:message.error.file_too_large', {
filename: file.name,
size: maxFileSize / (1024 * 1024),
postProcess: 'capitalizeFirst',
})
);
}
});
@@ -111,7 +115,6 @@ export const AppsPrivate = ({ myName }) => {
const addPrivateApp = async () => {
try {
if (privateAppValues?.groupId === 0) return;
await openApp(privateAppValues, true);
} catch (error) {
console.error(error);
@@ -139,9 +142,28 @@ export const AppsPrivate = ({ myName }) => {
const publishPrivateApp = async () => {
try {
if (selectedGroup === 0) return;
if (!logo) throw new Error('Please select an image for a logo');
if (!myName) throw new Error('You need a Qortal name to publish');
if (!newPrivateAppValues?.name) throw new Error('Your app needs a name');
if (!logo)
throw new Error(
t('core:message.generic.select_image', {
postProcess: 'capitalizeFirst',
})
);
if (!myName)
throw new Error(
t('core:message.generic.name_publish', {
postProcess: 'capitalizeFirst',
})
);
if (!newPrivateAppValues?.name)
throw new Error(
t('core:message.error.app_need_name', {
postProcess: 'capitalizeFirst',
})
);
const base64Logo = await fileToBase64(logo);
const base64App = await fileToBase64(file);
const objectToSave = {
@@ -160,16 +182,22 @@ export const AppsPrivate = ({ myName }) => {
if (decryptedData?.error) {
throw new Error(
decryptedData?.error || 'Unable to encrypt app. App not published'
decryptedData?.error ||
t('core:message.error.unable_encrypt_app', {
postProcess: 'capitalizeFirst',
})
);
}
const fee = await getFee('ARBITRARY');
await show({
message: 'Would you like to publish this app?',
message: t('core:save_options.publish_app', {
postProcess: 'capitalizeFirst',
}),
publishFee: fee.fee + ' QORT',
});
await new Promise((res, rej) => {
window
.sendMessage('publishOnQDN', {
@@ -185,7 +213,12 @@ export const AppsPrivate = ({ myName }) => {
rej(response.error);
})
.catch((error) => {
rej(error.message || 'An error occurred');
rej(
error.message ||
t('core:message.error.generic', {
postProcess: 'capitalizeFirst',
})
);
});
});
@@ -203,7 +236,11 @@ export const AppsPrivate = ({ myName }) => {
setOpenSnackGlobal(true);
setInfoSnackCustom({
type: 'error',
message: error?.message || 'Unable to publish app',
message:
error?.message ||
t('core:message.error.unable_publish_app', {
postProcess: 'capitalizeFirst',
}),
});
}
};
@@ -241,6 +278,7 @@ export const AppsPrivate = ({ myName }) => {
<AppCircleLabel>Private</AppCircleLabel>
</AppCircleContainer>
</ButtonBase>
{isOpenPrivateModal && (
<Dialog
open={isOpenPrivateModal}
@@ -312,10 +350,19 @@ export const AppsPrivate = ({ myName }) => {
display: 'flex',
flexDirection: 'column',
gap: '5px',
}} // TODO translate
}}
>
<Label>Select a group</Label>
<Label>Only private groups will be shown</Label>
<Label>
{t('group:action.select_group', {
postProcess: 'capitalizeFirst',
})}
</Label>
<Label>
{t('group:message.generic.only_private_groups', {
postProcess: 'capitalizeFirst',
})}
</Label>
<Select
labelId="demo-simple-select-label"
id="demo-simple-select"
@@ -330,7 +377,11 @@ export const AppsPrivate = ({ myName }) => {
});
}}
>
<MenuItem value={0}>No group selected</MenuItem>
<MenuItem value={0}>
{t('group:message.generic.no_selection', {
postProcess: 'capitalizeFirst',
})}
</MenuItem>
{myGroupsPrivate
?.filter((item) => !item?.isOpen)
@@ -343,7 +394,9 @@ export const AppsPrivate = ({ myName }) => {
})}
</Select>
</Box>
<Spacer height="10px" />
<Box
sx={{
display: 'flex',
@@ -352,7 +405,9 @@ export const AppsPrivate = ({ myName }) => {
marginTop: '15px',
}}
>
<Label>name</Label>
<Label>
{t('core:name', { postProcess: 'capitalizeFirst' })}
</Label>
<Input
placeholder="name"
value={privateAppValues?.name}
@@ -366,6 +421,7 @@ export const AppsPrivate = ({ myName }) => {
}
/>
</Box>
<Box
sx={{
display: 'flex',
@@ -374,9 +430,14 @@ export const AppsPrivate = ({ myName }) => {
marginTop: '15px',
}}
>
<Label>identifier</Label>
<Label>
{t('core:identifier', { postProcess: 'capitalizeFirst' })}
</Label>
<Input
placeholder="identifier"
placeholder={t('core:identifier', {
postProcess: 'capitalizeFirst',
})}
value={privateAppValues?.identifier}
onChange={(e) =>
setPrivateAppValues((prev) => {
@@ -397,7 +458,7 @@ export const AppsPrivate = ({ myName }) => {
setIsOpenPrivateModal(false);
}}
>
Close
{t('core:action.close', { postProcess: 'capitalizeFirst' })}
</Button>
<Button
disabled={
@@ -410,7 +471,7 @@ export const AppsPrivate = ({ myName }) => {
onClick={() => addPrivateApp()}
autoFocus
>
Access
{t('core:action.access', { postProcess: 'capitalizeFirst' })}
</Button>
</DialogActions>
</>
@@ -424,7 +485,9 @@ export const AppsPrivate = ({ myName }) => {
fontSize: '14px',
}}
>
Select .zip file containing static content:{' '}
{t('core:message.generic.select_zip', {
postProcess: 'capitalizeFirst',
})}
</PublishQAppInfo>
<Spacer height="10px" />
@@ -435,10 +498,11 @@ export const AppsPrivate = ({ myName }) => {
fontSize: '14px',
}}
>{`
50mb MB maximum`}</PublishQAppInfo>
50mb MB max`}</PublishQAppInfo>
{file && (
<>
<Spacer height="5px" />
<PublishQAppInfo>{`Selected: (${file?.name})`}</PublishQAppInfo>
</>
)}
@@ -454,7 +518,13 @@ export const AppsPrivate = ({ myName }) => {
>
{' '}
<input {...getInputProps()} />
{file ? 'Change' : 'Choose'} File
{file
? t('core:action.change_file', {
postProcess: 'capitalizeFirst',
})
: t('core:action.choose_file', {
postProcess: 'capitalizeFirst',
})}
</PublishQAppChoseFile>
<Spacer height="20px" />
@@ -466,10 +536,18 @@ export const AppsPrivate = ({ myName }) => {
gap: '5px',
}}
>
<Label>Select a group</Label>
<Label>
Only groups where you are an admin will be shown
{t('group:action.select_group', {
postProcess: 'capitalizeFirst',
})}
</Label>
<Label>
{t('group:amessage.generic.admin_only', {
postProcess: 'capitalizeFirst',
})}
</Label>
<Select
labelId="demo-simple-select-label"
id="demo-simple-select"
@@ -477,7 +555,11 @@ export const AppsPrivate = ({ myName }) => {
label="Groups where you are an admin"
onChange={(e) => setSelectedGroup(e.target.value)}
>
<MenuItem value={0}>No group selected</MenuItem>
<MenuItem value={0}>
{t('group:message.generic.no_selection', {
postProcess: 'capitalizeFirst',
})}
</MenuItem>
{myGroupsWhereIAmAdmin
?.filter((item) => !item?.isOpen)
.map((group) => {
@@ -500,9 +582,13 @@ export const AppsPrivate = ({ myName }) => {
marginTop: '15px',
}}
>
<Label>identifier</Label>
<Label>
{t('core:identifier', { postProcess: 'capitalizeFirst' })}
</Label>
<Input
placeholder="identifier"
placeholder={t('core:identifier', {
postProcess: 'capitalizeFirst',
})}
value={newPrivateAppValues?.identifier}
onChange={(e) =>
setNewPrivateAppValues((prev) => {
@@ -525,9 +611,14 @@ export const AppsPrivate = ({ myName }) => {
marginTop: '15px',
}}
>
<Label>App name</Label>
<Label>
{t('core:app_name', { postProcess: 'capitalizeFirst' })}
</Label>
<Input
placeholder="App name"
placeholder={t('core:app_name', {
postProcess: 'capitalizeFirst',
})}
value={newPrivateAppValues?.name}
onChange={(e) =>
setNewPrivateAppValues((prev) => {
@@ -543,10 +634,15 @@ export const AppsPrivate = ({ myName }) => {
<Spacer height="10px" />
<ImageUploader onPick={(file) => setLogo(file)}>
<Button variant="contained">Choose logo</Button>
<Button variant="contained">
{t('core:action.choose_logo', {
postProcess: 'capitalizeFirst',
})}
</Button>
</ImageUploader>
{logo?.name}
<Spacer height="25px" />
</DialogContent>
@@ -558,7 +654,7 @@ export const AppsPrivate = ({ myName }) => {
clearFields();
}}
>
Close
{t('core:action.close', { postProcess: 'capitalizeFirst' })}
</Button>
<Button
@@ -572,7 +668,7 @@ export const AppsPrivate = ({ myName }) => {
onClick={() => publishPrivateApp()}
autoFocus
>
Publish
{t('core:action.publish', { postProcess: 'capitalizeFirst' })}
</Button>
</DialogActions>
</>