Skip to content

Commit b973053

Browse files
Feature/convert videos confirm (#28)
* enable video conversion * setАllowVideoConversion new url * load user settings * Code optimization --------- Co-authored-by: Ivan Stefanov <[email protected]>
1 parent 773d714 commit b973053

File tree

11 files changed

+988
-8
lines changed

11 files changed

+988
-8
lines changed

src/api/api.ts

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
NUMBER_OF_OBJECTS_PER_PAGE,
88
USER_ROLES_OPTIONS,
99
} from '../constants/constants';
10-
import { IGetObjects, IGetUser, IUser, User } from '../types/types';
10+
import { IGetObjects, IGetUser, IGetVideoPreviewFilesSize, IUser, IUserSetting, User } from '../types/types';
1111
import axiosClient from './axios';
1212

1313
export async function getStatus(): Promise<{
@@ -317,7 +317,7 @@ export async function downloadObjectsAsZip({
317317
}): Promise<{ href: string; disposition: string }> {
318318
const res = await axiosClient.post('/object/downloadZip', {
319319
ObjectIds: objectIds,
320-
},{
320+
}, {
321321
responseType: 'blob',
322322
});
323323

@@ -401,4 +401,33 @@ export const fetchFavoritesIds = async ({
401401
params: { lastId: pageParam, PageSize: NUMBER_OF_OBJECTS_PER_PAGE },
402402
});
403403
return res.data;
404-
};
404+
};
405+
406+
export async function setАllowVideoConversion({
407+
previewConversion
408+
}: {
409+
previewConversion: boolean;
410+
}): Promise<void> {
411+
const response = await axiosClient.put('user/allowvideoconversion/' + previewConversion);
412+
413+
return response.data;
414+
}
415+
416+
export const useUserSettings = () =>
417+
useQuery({
418+
queryKey: ['userSettings'],
419+
queryFn: async (): Promise<IUserSetting> => {
420+
const res = await axiosClient.get('/users/me/settings');
421+
return res.data;
422+
},
423+
});
424+
425+
export async function GetVideoPreviewFilesSize(): Promise<IGetVideoPreviewFilesSize> {
426+
const response = await axiosClient.get('/user/getvideoconversationfilessize');
427+
return response.data;
428+
}
429+
430+
export async function DeleteVideoConversationFiles(): Promise<boolean> {
431+
const response = await axiosClient.delete('/users/deletevideoconversationfiles');
432+
return response.data;
433+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ export const ChangePassword = () => {
7979
p: 2,
8080
border: '1px solid rgb(0, 0, 0, 0.12)',
8181
borderRadius: '10px',
82-
maxWidth: '700px',
82+
maxWidth: '1100px',
8383
}}
8484
>
8585
<Accordion sx={{ boxShadow: 'none' }}>
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
import { Box, Button, LinearProgress, Stack, Typography } from '@mui/material';
2+
3+
interface ConversionActivityProps {
4+
status?: 'idle' | 'processing' | 'paused' | 'completed';
5+
userNumberOfFilesToConvert?: number;
6+
userNumberOfPreviewFiles?: number;
7+
progress?: number;
8+
onPause?: () => void;
9+
onCancel?: () => void;
10+
isLoading?: boolean;
11+
}
12+
13+
export const ConversionActivity = ({
14+
status = 'idle',
15+
userNumberOfFilesToConvert = 0,
16+
userNumberOfPreviewFiles = 0,
17+
progress = 0,
18+
onPause,
19+
onCancel,
20+
isLoading = false,
21+
}: ConversionActivityProps) => {
22+
const isPaused = status === 'paused';
23+
const isProcessing = status === 'processing';
24+
const isCompleted = status === 'completed';
25+
26+
const getStatusLabel = () => {
27+
if (isProcessing) return 'Processing';
28+
``;
29+
if (isPaused) return 'Paused';
30+
if (isCompleted) return 'Completed';
31+
return 'Idle';
32+
};
33+
34+
const getStatusColor = () => {
35+
if (isCompleted) return 'success.main';
36+
if (isPaused) return 'warning.main';
37+
return 'text.secondary';
38+
};
39+
40+
return (
41+
<Box sx={{ pt: 3, pb: 3, borderBottom: '1px solid rgb(0, 0, 0, 0.12)' }}>
42+
<Typography variant="subtitle1" fontWeight={600} sx={{ mb: 2 }}>
43+
Conversation Activity
44+
</Typography>
45+
46+
<Typography variant="body2" sx={{ mb: 0.5 }}>
47+
<Typography component="span" fontWeight={600}>
48+
Status:{' '}
49+
</Typography>
50+
<Typography component="span" color={getStatusColor()}>
51+
{getStatusLabel()}
52+
</Typography>
53+
</Typography>
54+
{isProcessing && (
55+
<Typography variant="body2" color="text.secondary" sx={{ mb: 2 }}>
56+
{userNumberOfPreviewFiles} out of {userNumberOfFilesToConvert} video
57+
{userNumberOfFilesToConvert !== 1 ? 's are ' : 'is '} in queue
58+
</Typography>
59+
)}
60+
61+
{isCompleted && (
62+
<Typography variant="body2" color="text.secondary" sx={{ mb: 2 }}>
63+
Processed {userNumberOfPreviewFiles} video file
64+
{userNumberOfPreviewFiles !== 1 ? 's ' : ' '}
65+
</Typography>
66+
)}
67+
68+
{(isCompleted || isProcessing) && (
69+
<Box sx={{ mb: 2 }}>
70+
<Box
71+
sx={{
72+
display: 'flex',
73+
alignItems: 'center',
74+
justifyContent: 'space-between',
75+
mb: 1,
76+
}}
77+
>
78+
<LinearProgress
79+
variant="determinate"
80+
value={progress}
81+
sx={{
82+
flex: 1,
83+
height: 8,
84+
borderRadius: 4,
85+
backgroundColor: 'rgba(0, 0, 0, 0.12)',
86+
'& .MuiLinearProgress-bar': {
87+
borderRadius: 4,
88+
backgroundColor: 'primary.main',
89+
},
90+
}}
91+
/>
92+
<Typography
93+
variant="body2"
94+
fontWeight={600}
95+
sx={{ ml: 2, minWidth: '45px' }}
96+
>
97+
{progress}%
98+
</Typography>
99+
</Box>
100+
</Box>
101+
)}
102+
<Stack direction="row" spacing={2}>
103+
{false && (<Button
104+
variant="outlined"
105+
onClick={onPause}
106+
disabled={!isProcessing || isLoading}
107+
>
108+
{isPaused ? 'Resume' : 'Pause'}
109+
</Button>
110+
)}
111+
{isProcessing && (<Button
112+
variant="outlined"
113+
color="error"
114+
onClick={onCancel}
115+
//disabled={(!isProcessing && !isPaused) || isLoading}
116+
>
117+
Cancel
118+
</Button>
119+
)}
120+
</Stack>
121+
</Box>
122+
);
123+
};
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import React, { useState } from 'react';
1818
import toast from 'react-hot-toast';
1919
import { useNavigate } from 'react-router-dom';
2020

21-
import { deleteAccount } from '../api/api';
21+
import { deleteAccount } from '../../api/api';
2222

2323
export const DeleteAccount = () => {
2424
const [password, setPassword] = useState('');
@@ -49,7 +49,7 @@ export const DeleteAccount = () => {
4949
p: 2,
5050
border: '1px solid rgb(0, 0, 0, 0.12)',
5151
borderRadius: '10px',
52-
maxWidth: '700px',
52+
maxWidth: '1100px',
5353
mt: 4,
5454
}}
5555
>

src/components/Users/Storage.tsx

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import { Box, Button, LinearProgress, Stack, Typography } from '@mui/material';
2+
3+
interface StorageProps {
4+
userSize?: number;
5+
userUsedQuota: number;
6+
quotaTotal?: number;
7+
userSizeOfFilesToConvert?: number;
8+
onClearTemporaryFiles?: () => void;
9+
toDeletePreviewFiles?: boolean;
10+
}
11+
12+
const formatBytes = (bytes: number): string => {
13+
if (isNaN(bytes)) return '--';
14+
15+
const units = ['B', 'KB', 'MB', 'GB'];
16+
let size = Math.abs(bytes);
17+
let unitIndex = 0;
18+
19+
while (size >= 1024 && unitIndex < units.length - 1) {
20+
size /= 1024;
21+
unitIndex++;
22+
}
23+
24+
return `${size.toFixed(2)} ${units[unitIndex]}`;
25+
};
26+
27+
export const Storage = ({
28+
userSize = 0,
29+
userUsedQuota,
30+
quotaTotal = 1,
31+
userSizeOfFilesToConvert = 0,
32+
onClearTemporaryFiles,
33+
toDeletePreviewFiles = false
34+
}: StorageProps) => {
35+
const progress = quotaTotal > 0
36+
? parseInt(
37+
(userSize / quotaTotal) * 100 + '',
38+
10
39+
)
40+
: 0
41+
42+
return (
43+
<Box sx={{ pt: 3 }}>
44+
<Typography variant="subtitle1" fontWeight={600} sx={{ mb: 2 }}>
45+
Storage
46+
</Typography>
47+
48+
<Typography variant="body2" sx={{ mb: 1.5 }}>
49+
<Typography component="span" fontWeight={600}>
50+
Converted video usage:{' '}
51+
</Typography>
52+
<Typography component="span">
53+
{formatBytes(userSize)} of {formatBytes(quotaTotal)}
54+
</Typography>
55+
</Typography>
56+
57+
<Box sx={{ mb: 2 }}>
58+
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', mb: 1 }}>
59+
<LinearProgress
60+
variant="determinate"
61+
value={progress}
62+
sx={{
63+
flex: 1,
64+
height: 8,
65+
borderRadius: 4,
66+
backgroundColor: 'rgba(0, 0, 0, 0.12)',
67+
'& .MuiLinearProgress-bar': {
68+
borderRadius: 4,
69+
backgroundColor: 'primary.main'
70+
}
71+
}}
72+
/>
73+
<Typography variant="body2" fontWeight={600} sx={{ ml: 2, minWidth: '45px' }}>
74+
{progress}%
75+
</Typography>
76+
</Box>
77+
</Box>
78+
79+
<Stack spacing={1} sx={{ mb: 2 }}>
80+
<Box>
81+
<Typography variant="body2" color="text.secondary" display="inline">
82+
Original Videos:{' '}
83+
</Typography>
84+
<Typography variant="body2" display="inline" fontWeight={600}>
85+
{formatBytes(userSizeOfFilesToConvert)}
86+
</Typography>
87+
</Box>
88+
<Box>
89+
<Typography variant="body2" color="text.secondary" display="inline">
90+
Converted Videos:{' '}
91+
</Typography>
92+
<Typography variant="body2" display="inline" fontWeight={600}>
93+
{formatBytes(userSize)}
94+
</Typography>
95+
</Box>
96+
</Stack>
97+
98+
{false && toDeletePreviewFiles && (
99+
<Button
100+
variant="outlined"
101+
onClick={onClearTemporaryFiles}
102+
startIcon={
103+
<Typography component="span" sx={{ mr: 0.5 }}>
104+
🗑️
105+
</Typography>
106+
}
107+
>
108+
Clear temporary preview files
109+
</Button>
110+
)}
111+
112+
{userUsedQuota > quotaTotal && (
113+
<Typography variant="body2" color="error.main">
114+
Warning: You have exceeded your storage quota.
115+
</Typography>
116+
)}
117+
</Box>
118+
);
119+
};

0 commit comments

Comments
 (0)