Skip to content

Commit

Permalink
Merge pull request #48 from HakierGrzonzo/26-pasek-postępu-przy-wysył…
Browse files Browse the repository at this point in the history
…aniu-plików

26 pasek postępu przy wysyłaniu plików
  • Loading branch information
Havystar authored Apr 25, 2022
2 parents 0ab4fff + d0d52de commit 563fa64
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 58 deletions.
5 changes: 3 additions & 2 deletions backend/backend/measurements.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from fastapi_users.fastapi_users import FastAPIUsers
from sqlalchemy.sql import select, delete
from sqlalchemy.ext.asyncio.session import AsyncSession
from sqlalchemy.sql.expression import desc
from starlette.responses import Response
from fastapi_redis_cache import cache
from .tasks import on_new_location
Expand Down Expand Up @@ -71,7 +72,7 @@ def _check_tags(
async def get_all_measurements(
self, session: AsyncSession
) -> list[Measurement]:
result = await session.execute(select(Measurements))
result = await session.execute(select(Measurements).order_by(Measurements.title))
return [
self._table_to_model(x) for x in result.unique().scalars().all()
]
Expand Down Expand Up @@ -141,7 +142,7 @@ async def get_my_measurements(
result = await session.execute(
select(Measurements).filter(
Measurements.author_id == current_user.id
)
).order_by(desc(Measurements.location_time))
)
return [
self._table_to_model(x) for x in result.unique().scalars().all()
Expand Down
17 changes: 17 additions & 0 deletions frontend/editor/src/components/measurementRow.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Typography } from "@mui/material";

interface RowProps {
name: string;
children: any;
}

export function MeasuermentRow(props: RowProps) {
const {name, children} = props;
return <>
<div className='measurement-row'>
<Typography variant="h6">{name}:</Typography>
<div className='w-24' />
<Typography variant="body1">{children}</Typography>
</div>
</>
}
154 changes: 98 additions & 56 deletions frontend/editor/src/pages/Pc.tsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,64 @@
import { useState, useEffect } from "react";
import { Button, CircularProgress, Typography } from "@mui/material";
import { useState, useEffect, useReducer } from "react";
import { Button, Chip, CircularProgress, LinearProgress, Typography } from "@mui/material";
import { useSnackbar } from "notistack";
import { DataService, FilesService, Measurement, Location } from "../api";
import { DataService, FilesService, Measurement, Location, FileReference } from "../api";
import { checkFiContainAllFiles } from "../utils/fileUtils";
import { MeasuermentRow } from "../components/measurementRow";
import _ from 'lodash';

type CountAction =
| { type: 'add', newFiles: number}
| { type: 'fileuploaded'};

interface CountState {
max: number;
now: number;
}

function countReducer(state: CountState, action: CountAction): CountState {
switch (action.type) {
case 'add':
return {now: state.now + action.newFiles, max: action.newFiles};
case 'fileuploaded':
return {now: state.now - 1, max: state.max}
default:
throw new Error()
}
}

export default function MobileEdit() {
const { enqueueSnackbar } = useSnackbar();
const [measurements, setMeasurements] = useState<Measurement[]>();
const [uploadingFilesCount, dispatch] = useReducer(countReducer, {now: 0, max: 0});

function showLocalization(localization: Location) {
window.open(`https://www.google.com/maps/place/${localization.latitude} ${localization.longitude}`, "_blank");
}

function send(id: number) {
async function send(id: number) {
const input = document.getElementById(`${id}`) as HTMLInputElement;
if(!input || !input.files) {
return;
}

dispatch({type: 'add', newFiles: input.files.length})
for (const file of input.files) {
let body = {
uploaded_file: file
}
FilesService.uploadNewFileApiFilesPost(id, body).then(() => {
try {
await FilesService.uploadNewFileApiFilesPost(id, body)
enqueueSnackbar("The file was added", {
variant: "success",
});
}).catch(() => {
}
catch {
enqueueSnackbar(`Ops! We have some error with file upload check your internet connection or login again`, {
variant: "error",
});
});
}
dispatch({type: 'fileuploaded'})
}
await fetchData()
}

async function fetchData() {
Expand All @@ -44,6 +70,24 @@ export default function MobileEdit() {
setMeasurements(measures);
}

async function deleteFile(file: FileReference, e: Event) {
e.preventDefault()
if (confirm(`Do you really want to delete "${file.original_name}"?`)) {
try {
await FilesService.deleteFileApiFilesDeleteIdGet(file.file_id)
enqueueSnackbar(`Deleted ${file.original_name}`, {
variant: "success",
});
}
catch {
enqueueSnackbar(`Ops! Grzez failed to delete ${file.original_name}`, {
variant: "error",
});
}
await fetchData()
}
}

useEffect(() => {
fetchData();
}, []);
Expand All @@ -61,54 +105,52 @@ export default function MobileEdit() {
return (
<div key={measurement.measurement_id}
className={checkFiContainAllFiles(measurement.files) ? "measurement bg-stone-800" : "measurement bg-stone-700" }>
<div className='measurement-row'>
<Typography variant="h6">title:</Typography>
<div className='w-24' />
<Typography variant="h6">{measurement.title}</Typography>
</div>
<div className='measurement-row'>
<Typography variant="h6">description:</Typography>
<div className='w-24' />
<Typography variant="body1">{measurement.description}</Typography>
</div>
<div className='measurement-row'>
<Typography variant="h6">notes:</Typography>
<div className='w-24' />
<Typography variant="body1">{measurement.notes}</Typography>
</div>
<div className='measurement-row'>
<Typography variant="h6">tags:</Typography>
<div className='w-24' />
<Typography variant="body1">{measurement.tags.join(", ")}</Typography>
</div>
<div className='measurement-row'>
<Typography variant="h6">laeq:</Typography>
<div className='w-24' />
<Typography variant="body1">{measurement.laeq}</Typography>
</div>
<div className='measurement-row'>
<Typography variant="h6">data:</Typography>
<div className='w-24' />
<Typography variant="body1">{measurement.location.time}</Typography>
</div>
<div onClick={() => showLocalization(measurement.location)} className='measurement-row cursor-pointer'>
<Typography variant="h6">localization:</Typography>
<div className='w-24' />
<Typography variant="body1">
{measurement.location.latitude} {measurement.location.longitude}</Typography>
</div>
<div className='measurement-row'>
<Typography variant="h6">files:</Typography>
<div className='w-24' />
<Typography variant="body1">{measurement.files.map((file, index, arr) => (
<span key={file.file_id}>
<a title={file?.optimized_mime} href={file.link}>{file.mime}</a>{index < arr.length - 1 ? ", " : ""}
</span>
))}</Typography>
</div>
<div className='measurement-row'>
<input type="file" name="multipleFiles" multiple id={String(measurement.measurement_id)} />
</div>
<Typography variant="h6">
{measurement.title}
</Typography>
<MeasuermentRow name="description">
{measurement.description}
</MeasuermentRow>
<MeasuermentRow name="notes">
{measurement.notes}
</MeasuermentRow>
<MeasuermentRow name="tags">
{measurement.tags.map(
(tag, index) => <Chip key={tag + index} label={tag}/>)}
</MeasuermentRow>
<MeasuermentRow name="laeq">
{measurement.laeq}
</MeasuermentRow>
<MeasuermentRow name="time">
{new Date(Date.parse(measurement.location.time)).toLocaleString()}
</MeasuermentRow>
<MeasuermentRow name="location">
<Chip
label={`${measurement.location.latitude} ${measurement.location.longitude}`}
onClick={() => showLocalization(measurement.location)}/>
</MeasuermentRow>
<MeasuermentRow name="files">
{measurement.files.map((file) => <Chip
key={file.file_id}
label={file.original_name}
color={file.optimized_mime ? "success" : "primary"}
component="a"
title={file.mime}
href={file.link}
onDelete={(e) => deleteFile(file, e)}
clickable
/>
)}
</MeasuermentRow>
{uploadingFilesCount.now > 0 ?
<>
<LinearProgress variant="determinate" value={100 - uploadingFilesCount.now / uploadingFilesCount.max * 100}/>
</>
: <>
<div className='measurement-row'>
<input type="file" name="multipleFiles" multiple id={String(measurement.measurement_id)} />
</div>
</>}
<div className='measurement-row-last'>
<Button type="submit" variant="contained" onClick={() => send(measurement.measurement_id)} >send</Button>
<Button type="submit" variant="contained"
Expand Down

0 comments on commit 563fa64

Please sign in to comment.