mirror of
https://github.com/Qortal/Qortal-Hub.git
synced 2025-07-23 04:36:52 +00:00
Add translations
This commit is contained in:
@@ -446,7 +446,7 @@ export const AppsDevModeHome = ({
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: '5px',
|
||||
}}
|
||||
}} // TODO translate
|
||||
>
|
||||
<Label>Domain</Label>
|
||||
<Input
|
||||
|
@@ -152,7 +152,6 @@ export const AppsPrivate = ({ myName }) => {
|
||||
const object64 = await objectToBase64(objectToSave);
|
||||
const decryptedData = await window.sendMessage(
|
||||
'ENCRYPT_QORTAL_GROUP_DATA',
|
||||
|
||||
{
|
||||
base64: object64,
|
||||
groupId: selectedGroup,
|
||||
@@ -313,7 +312,7 @@ 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>
|
||||
|
@@ -371,7 +371,6 @@ export const AddGroup = ({ address, open, setOpen }) => {
|
||||
}}
|
||||
>
|
||||
<Label>
|
||||
{' '}
|
||||
{t('group:group.type', {
|
||||
postProcess: 'capitalize',
|
||||
})}
|
||||
@@ -428,6 +427,7 @@ export const AddGroup = ({ address, open, setOpen }) => {
|
||||
postProcess: 'capitalize',
|
||||
})}
|
||||
</Label>
|
||||
|
||||
<Select
|
||||
labelId="demo-simple-select-label"
|
||||
id="demo-simple-select"
|
||||
|
@@ -15,6 +15,7 @@ export const InviteMember = ({ groupId, setInfoSnack, setOpenSnack, show }) => {
|
||||
const inviteMember = async () => {
|
||||
try {
|
||||
const fee = await getFee('GROUP_INVITE');
|
||||
|
||||
await show({
|
||||
message: t('group:question.perform_transaction', {
|
||||
action: 'GROUP_INVITE',
|
||||
@@ -22,7 +23,9 @@ export const InviteMember = ({ groupId, setInfoSnack, setOpenSnack, show }) => {
|
||||
}),
|
||||
publishFee: fee.fee + ' QORT',
|
||||
});
|
||||
|
||||
setIsLoadingInvite(true);
|
||||
|
||||
if (!expiryTime || !value) return;
|
||||
new Promise((res, rej) => {
|
||||
window
|
||||
@@ -42,7 +45,6 @@ export const InviteMember = ({ groupId, setInfoSnack, setOpenSnack, show }) => {
|
||||
});
|
||||
setOpenSnack(true);
|
||||
res(response);
|
||||
|
||||
setValue('');
|
||||
return;
|
||||
}
|
||||
@@ -56,7 +58,11 @@ export const InviteMember = ({ groupId, setInfoSnack, setOpenSnack, show }) => {
|
||||
.catch((error) => {
|
||||
setInfoSnack({
|
||||
type: 'error',
|
||||
message: error?.message || 'An error occurred',
|
||||
message:
|
||||
error?.message ||
|
||||
t('core:message.error.generic', {
|
||||
postProcess: 'capitalize',
|
||||
}),
|
||||
});
|
||||
setOpenSnack(true);
|
||||
rej(error);
|
||||
@@ -81,16 +87,21 @@ export const InviteMember = ({ groupId, setInfoSnack, setOpenSnack, show }) => {
|
||||
}}
|
||||
>
|
||||
{t('group:action.invite_member', { postProcess: 'capitalize' })}
|
||||
|
||||
<Spacer height="20px" />
|
||||
|
||||
<Input
|
||||
value={value}
|
||||
placeholder="Name or address"
|
||||
onChange={(e) => setValue(e.target.value)}
|
||||
/>
|
||||
|
||||
<Spacer height="20px" />
|
||||
|
||||
<Label>
|
||||
{t('group:invitation_expiry', { postProcess: 'capitalize' })}
|
||||
</Label>
|
||||
|
||||
<Select
|
||||
labelId="demo-simple-select-label"
|
||||
id="demo-simple-select"
|
||||
@@ -109,7 +120,9 @@ export const InviteMember = ({ groupId, setInfoSnack, setOpenSnack, show }) => {
|
||||
<MenuItem value={1296000}>{t('core:time.day', { count: 15 })}</MenuItem>
|
||||
<MenuItem value={2592000}>{t('core:time.day', { count: 30 })}</MenuItem>
|
||||
</Select>
|
||||
|
||||
<Spacer height="20px" />
|
||||
|
||||
<LoadingButton
|
||||
variant="contained"
|
||||
loadingPosition="start"
|
||||
|
@@ -34,7 +34,6 @@ import {
|
||||
import { Spacer } from '../../common/Spacer';
|
||||
import { CustomLoader } from '../../common/CustomLoader';
|
||||
import { RequestQueueWithPromise } from '../../utils/queue/queue';
|
||||
|
||||
import {
|
||||
myGroupsWhereIAmAdminAtom,
|
||||
promotionTimeIntervalAtom,
|
||||
@@ -89,9 +88,7 @@ export const ListOfGroupPromotions = () => {
|
||||
const [promotionTimeInterval, setPromotionTimeInterval] = useAtom(
|
||||
promotionTimeIntervalAtom
|
||||
);
|
||||
|
||||
const [isExpanded, setIsExpanded] = React.useState(false);
|
||||
|
||||
const [openSnack, setOpenSnack] = useState(false);
|
||||
const [infoSnack, setInfoSnack] = useState(null);
|
||||
const [fee, setFee] = useState(null);
|
||||
@@ -99,7 +96,6 @@ export const ListOfGroupPromotions = () => {
|
||||
const [isLoadingPublish, setIsLoadingPublish] = useState(false);
|
||||
const { show } = useContext(MyContext);
|
||||
const setTxList = useSetAtom(txListAtom);
|
||||
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['core', 'group']);
|
||||
const listRef = useRef(null);
|
||||
@@ -250,8 +246,9 @@ export const ListOfGroupPromotions = () => {
|
||||
});
|
||||
setInfoSnack({
|
||||
type: 'success',
|
||||
message:
|
||||
'Successfully published promotion. It may take a couple of minutes for the promotion to appear',
|
||||
message: t('group:message.success.group_promotion', {
|
||||
postProcess: 'capitalize',
|
||||
}),
|
||||
});
|
||||
setOpenSnack(true);
|
||||
setText('');
|
||||
@@ -261,7 +258,10 @@ export const ListOfGroupPromotions = () => {
|
||||
setInfoSnack({
|
||||
type: 'error',
|
||||
message:
|
||||
error?.message || 'Error publishing the promotion. Please try again',
|
||||
error?.message ||
|
||||
t('group:message.error.group_promotion', {
|
||||
postProcess: 'capitalize',
|
||||
}),
|
||||
});
|
||||
setOpenSnack(true);
|
||||
} finally {
|
||||
@@ -290,8 +290,9 @@ export const ListOfGroupPromotions = () => {
|
||||
if (!response?.error) {
|
||||
setInfoSnack({
|
||||
type: 'success',
|
||||
message:
|
||||
'Successfully requested to join group. It may take a couple of minutes for the changes to propagate',
|
||||
message: t('group:message.success.group_join', {
|
||||
postProcess: 'capitalize',
|
||||
}),
|
||||
});
|
||||
|
||||
if (isOpen) {
|
||||
@@ -299,8 +300,14 @@ export const ListOfGroupPromotions = () => {
|
||||
{
|
||||
...response,
|
||||
type: 'joined-group',
|
||||
label: `Joined Group ${group?.groupName}: awaiting confirmation`,
|
||||
labelDone: `Joined Group ${group?.groupName}: success!`,
|
||||
label: t('group:message.success.group_join_label', {
|
||||
group_name: group?.groupName,
|
||||
postProcess: 'capitalize',
|
||||
}),
|
||||
labelDone: t('group:message.success.group_join_label', {
|
||||
group_name: group?.groupName,
|
||||
postProcess: 'capitalize',
|
||||
}),
|
||||
done: false,
|
||||
groupId,
|
||||
},
|
||||
@@ -311,15 +318,20 @@ export const ListOfGroupPromotions = () => {
|
||||
{
|
||||
...response,
|
||||
type: 'joined-group-request',
|
||||
label: `Requested to join Group ${group?.groupName}: awaiting confirmation`,
|
||||
labelDone: `Requested to join Group ${group?.groupName}: success!`,
|
||||
label: t('group:message.success.group_join_request', {
|
||||
group_name: group?.groupName,
|
||||
postProcess: 'capitalize',
|
||||
}),
|
||||
labelDone: t('group:message.success.group_join_outcome', {
|
||||
group_name: group?.groupName,
|
||||
postProcess: 'capitalize',
|
||||
}),
|
||||
done: false,
|
||||
groupId,
|
||||
},
|
||||
...prev,
|
||||
]);
|
||||
}
|
||||
|
||||
setOpenSnack(true);
|
||||
handlePopoverClose();
|
||||
res(response);
|
||||
@@ -336,7 +348,9 @@ export const ListOfGroupPromotions = () => {
|
||||
.catch((error) => {
|
||||
setInfoSnack({
|
||||
type: 'error',
|
||||
message: error.message || 'An error occurred',
|
||||
message:
|
||||
error.message ||
|
||||
t('core:message.error.generic', { postProcess: 'capitalize' }),
|
||||
});
|
||||
setOpenSnack(true);
|
||||
rej(error);
|
||||
@@ -385,7 +399,7 @@ export const ListOfGroupPromotions = () => {
|
||||
fontSize: '1rem',
|
||||
}}
|
||||
>
|
||||
Group promotions{' '}
|
||||
{t('group:group.promotions', { postProcess: 'capitalize' })}{' '}
|
||||
{promotions.length > 0 && ` (${promotions.length})`}
|
||||
</Typography>
|
||||
|
||||
@@ -444,7 +458,7 @@ export const ListOfGroupPromotions = () => {
|
||||
fontSize: '12px',
|
||||
}}
|
||||
>
|
||||
Add Promotion
|
||||
{t('group.action.add_promotion', { postProcess: 'capitalize' })}
|
||||
</Button>
|
||||
</Box>
|
||||
|
||||
@@ -490,7 +504,9 @@ export const ListOfGroupPromotions = () => {
|
||||
color: 'rgba(255, 255, 255, 0.2)',
|
||||
}}
|
||||
>
|
||||
Nothing to display
|
||||
{t('group.message.generic.no_display', {
|
||||
postProcess: 'capitalize',
|
||||
})}
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
@@ -537,23 +553,25 @@ export const ListOfGroupPromotions = () => {
|
||||
ref={rowVirtualizer.measureElement} //measure dynamic row height
|
||||
key={promotion?.identifier}
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: '50%', // Move to the center horizontally
|
||||
transform: `translateY(${virtualRow.start}px) translateX(-50%)`, // Adjust for centering
|
||||
width: '100%', // Control width (90% of the parent)
|
||||
padding: '10px 0',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
overscrollBehavior: 'none',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: '5px',
|
||||
left: '50%', // Move to the center horizontally
|
||||
overscrollBehavior: 'none',
|
||||
padding: '10px 0',
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
transform: `translateY(${virtualRow.start}px) translateX(-50%)`, // Adjust for centering
|
||||
width: '100%', // Control width (90% of the parent)
|
||||
}}
|
||||
>
|
||||
<ErrorBoundary
|
||||
fallback={
|
||||
<Typography>
|
||||
Error loading content: Invalid Data
|
||||
{t('group.message.generic.invalid_data', {
|
||||
postProcess: 'capitalize',
|
||||
})}
|
||||
</Typography>
|
||||
}
|
||||
>
|
||||
@@ -568,7 +586,7 @@ export const ListOfGroupPromotions = () => {
|
||||
<Popover
|
||||
open={openPopoverIndex === promotion?.groupId}
|
||||
anchorEl={popoverAnchor}
|
||||
onClose={(event, reason) => {
|
||||
onClose={(reason) => {
|
||||
if (reason === 'backdropClick') {
|
||||
// Prevent closing on backdrop click
|
||||
return;
|
||||
@@ -603,7 +621,10 @@ export const ListOfGroupPromotions = () => {
|
||||
fontWeight: 600,
|
||||
}}
|
||||
>
|
||||
Group name: {` ${promotion?.groupName}`}
|
||||
{t('group:group.name', {
|
||||
postProcess: 'capitalize',
|
||||
})}
|
||||
: {` ${promotion?.groupName}`}
|
||||
</Typography>
|
||||
|
||||
<Typography
|
||||
@@ -612,8 +633,10 @@ export const ListOfGroupPromotions = () => {
|
||||
fontWeight: 600,
|
||||
}}
|
||||
>
|
||||
Number of members:{' '}
|
||||
{` ${promotion?.memberCount}`}
|
||||
{t('group:group.member_number', {
|
||||
postProcess: 'capitalize',
|
||||
})}
|
||||
: {` ${promotion?.memberCount}`}
|
||||
</Typography>
|
||||
|
||||
{promotion?.description && (
|
||||
@@ -634,9 +657,9 @@ export const ListOfGroupPromotions = () => {
|
||||
fontWeight: 600,
|
||||
}}
|
||||
>
|
||||
*This is a closed/private group, so you
|
||||
will need to wait until an admin accepts
|
||||
your request
|
||||
{t('group:message.generic.closed_group', {
|
||||
postProcess: 'capitalize',
|
||||
})}
|
||||
</Typography>
|
||||
)}
|
||||
|
||||
@@ -657,7 +680,9 @@ export const ListOfGroupPromotions = () => {
|
||||
variant="contained"
|
||||
onClick={handlePopoverClose}
|
||||
>
|
||||
Close
|
||||
{t('core:action.close', {
|
||||
postProcess: 'capitalize',
|
||||
})}
|
||||
</LoadingButton>
|
||||
|
||||
<LoadingButton
|
||||
@@ -671,7 +696,9 @@ export const ListOfGroupPromotions = () => {
|
||||
)
|
||||
}
|
||||
>
|
||||
Join
|
||||
{t('core:action.join', {
|
||||
postProcess: 'capitalize',
|
||||
})}
|
||||
</LoadingButton>
|
||||
</Box>
|
||||
</Box>
|
||||
@@ -755,8 +782,12 @@ export const ListOfGroupPromotions = () => {
|
||||
}}
|
||||
>
|
||||
{promotion?.isOpen
|
||||
? 'Public group'
|
||||
: 'Private group'}
|
||||
? t('group:group.public', {
|
||||
postProcess: 'capitalize',
|
||||
})
|
||||
: t('group:group.private', {
|
||||
postProcess: 'capitalize',
|
||||
})}
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
@@ -790,7 +821,10 @@ export const ListOfGroupPromotions = () => {
|
||||
color: theme.palette.text.primary,
|
||||
}}
|
||||
>
|
||||
Join Group: {` ${promotion?.groupName}`}
|
||||
{t('group:action.join_group', {
|
||||
postProcess: 'capitalize',
|
||||
})}
|
||||
: {` ${promotion?.groupName}`}
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
@@ -810,90 +844,114 @@ export const ListOfGroupPromotions = () => {
|
||||
|
||||
<Spacer height="20px" />
|
||||
|
||||
{isShowModal && (
|
||||
<Dialog
|
||||
open={isShowModal}
|
||||
aria-labelledby="alert-dialog-title"
|
||||
aria-describedby="alert-dialog-description"
|
||||
>
|
||||
<DialogTitle id="alert-dialog-title">
|
||||
{'Promote your group to non-members'}
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<DialogContentText id="alert-dialog-description">
|
||||
Only the latest promotion from the week will be shown for your
|
||||
group.
|
||||
</DialogContentText>
|
||||
<DialogContentText id="alert-dialog-description2">
|
||||
Max 200 characters. Publish Fee: {fee && fee} {' QORT'}
|
||||
</DialogContentText>
|
||||
<Spacer height="20px" />
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: '5px',
|
||||
}}
|
||||
<Dialog
|
||||
open={isShowModal}
|
||||
aria-labelledby="alert-dialog-title"
|
||||
aria-describedby="alert-dialog-description"
|
||||
>
|
||||
<DialogTitle id="alert-dialog-title">
|
||||
{t('group:action.promote_group', { postProcess: 'capitalize' })}
|
||||
</DialogTitle>
|
||||
|
||||
<DialogContent>
|
||||
<DialogContentText id="alert-dialog-description">
|
||||
{t('group:message.generic.latest_promotion', {
|
||||
postProcess: 'capitalize',
|
||||
})}
|
||||
</DialogContentText>
|
||||
|
||||
<DialogContentText id="alert-dialog-description2">
|
||||
{t('group:message.generic.max_chars', {
|
||||
postProcess: 'capitalize',
|
||||
})}
|
||||
: {fee && fee} {' QORT'}
|
||||
</DialogContentText>
|
||||
|
||||
<Spacer height="20px" />
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: '5px',
|
||||
}}
|
||||
>
|
||||
<Label>
|
||||
{t('group:action.select_group', {
|
||||
postProcess: 'capitalize',
|
||||
})}
|
||||
</Label>
|
||||
|
||||
<Label>
|
||||
{t('group:message.generic.admin_only', {
|
||||
postProcess: 'capitalize',
|
||||
})}
|
||||
</Label>
|
||||
|
||||
<Select
|
||||
labelId="demo-simple-select-label"
|
||||
id="demo-simple-select"
|
||||
value={selectedGroup}
|
||||
label="Groups where you are an admin"
|
||||
onChange={(e) => setSelectedGroup(e.target.value)}
|
||||
variant="outlined"
|
||||
>
|
||||
<Label>Select a group</Label>
|
||||
<Label>Only groups where you are an admin will be shown</Label>
|
||||
<Select
|
||||
labelId="demo-simple-select-label"
|
||||
id="demo-simple-select"
|
||||
value={selectedGroup}
|
||||
label="Groups where you are an admin"
|
||||
onChange={(e) => setSelectedGroup(e.target.value)}
|
||||
variant="outlined"
|
||||
>
|
||||
{myGroupsWhereIAmAdmin?.map((group) => {
|
||||
return (
|
||||
<MenuItem key={group?.groupId} value={group?.groupId}>
|
||||
{group?.groupName}
|
||||
</MenuItem>
|
||||
);
|
||||
})}
|
||||
</Select>
|
||||
</Box>
|
||||
<Spacer height="20px" />
|
||||
<TextField
|
||||
label="Promotion text"
|
||||
variant="filled"
|
||||
fullWidth
|
||||
value={text}
|
||||
onChange={(e) => setText(e.target.value)}
|
||||
inputProps={{
|
||||
maxLength: 200,
|
||||
}}
|
||||
multiline={true}
|
||||
sx={{
|
||||
'& .MuiFormLabel-root': {
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
'& .MuiFormLabel-root.Mui-focused': {
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button
|
||||
disabled={isLoadingPublish}
|
||||
variant="contained"
|
||||
onClick={() => setIsShowModal(false)}
|
||||
>
|
||||
Close
|
||||
</Button>
|
||||
<Button
|
||||
disabled={!text.trim() || !selectedGroup || isLoadingPublish}
|
||||
variant="contained"
|
||||
onClick={publishPromo}
|
||||
autoFocus
|
||||
>
|
||||
Publish
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
)}
|
||||
{myGroupsWhereIAmAdmin?.map((group) => {
|
||||
return (
|
||||
<MenuItem key={group?.groupId} value={group?.groupId}>
|
||||
{group?.groupName}
|
||||
</MenuItem>
|
||||
);
|
||||
})}
|
||||
</Select>
|
||||
</Box>
|
||||
|
||||
<Spacer height="20px" />
|
||||
|
||||
<TextField
|
||||
label="Promotion text"
|
||||
variant="filled"
|
||||
fullWidth
|
||||
value={text}
|
||||
onChange={(e) => setText(e.target.value)}
|
||||
inputProps={{
|
||||
maxLength: 200,
|
||||
}}
|
||||
multiline={true}
|
||||
sx={{
|
||||
'& .MuiFormLabel-root': {
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
'& .MuiFormLabel-root.Mui-focused': {
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</DialogContent>
|
||||
|
||||
<DialogActions>
|
||||
<Button
|
||||
disabled={isLoadingPublish}
|
||||
variant="contained"
|
||||
onClick={() => setIsShowModal(false)}
|
||||
>
|
||||
{t('core:action.close', {
|
||||
postProcess: 'capitalize',
|
||||
})}
|
||||
</Button>
|
||||
<Button
|
||||
disabled={!text.trim() || !selectedGroup || isLoadingPublish}
|
||||
variant="contained"
|
||||
onClick={publishPromo}
|
||||
autoFocus
|
||||
>
|
||||
{t('core:action.publish', {
|
||||
postProcess: 'capitalize',
|
||||
})}
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
|
||||
<CustomizedSnackbars
|
||||
open={openSnack}
|
||||
setOpen={setOpenSnack}
|
||||
|
@@ -1,21 +1,17 @@
|
||||
import * as React from 'react';
|
||||
import Button from '@mui/material/Button';
|
||||
import Snackbar, { SnackbarCloseReason } from '@mui/material/Snackbar';
|
||||
import Snackbar from '@mui/material/Snackbar';
|
||||
import Alert from '@mui/material/Alert';
|
||||
|
||||
export const LoadingSnackbar = ({open, info}) => {
|
||||
|
||||
export const LoadingSnackbar = ({ open, info }) => {
|
||||
return (
|
||||
<div>
|
||||
<Snackbar anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }} open={open}>
|
||||
<Alert
|
||||
severity="info"
|
||||
variant="filled"
|
||||
sx={{ width: '100%' }}
|
||||
>
|
||||
<Snackbar
|
||||
anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }}
|
||||
open={open}
|
||||
>
|
||||
<Alert severity="info" variant="filled" sx={{ width: '100%' }}>
|
||||
{info?.message}
|
||||
</Alert>
|
||||
</Snackbar>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
@@ -1,4 +1,3 @@
|
||||
import * as React from 'react';
|
||||
import Snackbar, { SnackbarCloseReason } from '@mui/material/Snackbar';
|
||||
import Alert from '@mui/material/Alert';
|
||||
|
||||
|
@@ -198,9 +198,11 @@ export const TaskManager = ({ getUserInfo }) => {
|
||||
/>
|
||||
)}
|
||||
</ListItemIcon>
|
||||
|
||||
<ListItemText primary="Ongoing Transactions" />
|
||||
{open ? <ExpandLess /> : <ExpandMore />}
|
||||
</ListItemButton>
|
||||
|
||||
<Collapse in={open} timeout="auto" unmountOnExit>
|
||||
<List component="div" disablePadding>
|
||||
{txList.map((item) => (
|
||||
|
Reference in New Issue
Block a user