feat(app): minor improvements
Build and Push Docker image / build-and-push (push) Successful in 5m0s Details

added sender and sendTime to announcements
added sendTime as duration to message
improved duration function (no more 59Min instead of 1Std)
This commit is contained in:
Valentin Kolb 2024-06-12 00:54:36 +02:00
parent ed2056fded
commit 841be395f9
8 changed files with 73 additions and 60 deletions

View File

@ -57,11 +57,15 @@ function getLocalizedNowWord(locale: string) {
return translations[locale as keyof typeof translations] || 'now';
}
export const humanDeltaFromNow = (start: string | Date | Dayjs, end: string | Date | Dayjs): {
export const humanDeltaFromNow = (start: string | Date | Dayjs, end?: string | Date | Dayjs): {
message: string,
delta: "PAST" | "FUTURE" | "NOW"
} => {
if (!end) {
end = start
}
// check if end is in the past
if (dayjs(end).isBefore(dayjs())) {
return {
@ -112,29 +116,27 @@ export const pprintDateRange = (d1: string | Date | Dayjs, d2: string | Date | D
* @param date2
*/
export function formatDuration(date1: string | Date | Dayjs, date2: string | Date | Dayjs) {
const start = dayjs(date1)
const end = dayjs(date2)
const diff = end.diff(start)
const duration = dayjs.duration(diff)
const weeks = Math.floor(duration.asDays() / 7);
const days = duration.days() % 7;
const hours = duration.hours();
const minutes = duration.minutes();
const parts = [];
// ignore seconds and milliseconds
date1 = dayjs(date1).startOf('minute');
date2 = dayjs(date2).startOf('minute');
if (weeks > 0) {
parts.push(`${weeks} Wo`);
}
if (days > 0 || weeks > 0) {
parts.push(`${days} Tag${days > 1 ? 'e' : ''}`);
}
if (hours > 0) {
parts.push(`${hours} Std`);
}
if (minutes > 0) {
parts.push(`${minutes} Min`);
}
// get the difference in milliseconds
const diff = dayjs(date2).diff(dayjs(date1));
const durationObj = dayjs.duration(diff);
return parts.join(', ');
// get the duration in weeks, days, hours and minutes
const weeks = Math.floor(durationObj.asWeeks());
const days = durationObj.days();
const hours = durationObj.hours();
const minutes = durationObj.minutes();
// create a string array with the duration parts
const result: string[] = [];
if (weeks > 0) result.push(`${weeks} Wo`);
if (days > 0) result.push(`${days} Tag${days > 1 ? 'e' : ''}`);
if (hours > 0) result.push(`${hours} Std`);
if (minutes > 0) result.push(`${minutes} Min`);
return result.join(', ');
}

View File

@ -3,17 +3,14 @@
position: relative;
flex-direction: column;
box-shadow: var(--shadow);
background-color: var(--mantine-color-body);
padding: var(--padding);
border: var(--border);
border-color: var(--mantine-primary-color-5);
border-radius: var(--mantine-radius-lg);
border-radius: var(--border-radius);
margin: var(--gap);
max-width: 100%;
word-break: break-all;
@ -24,4 +21,11 @@
font-size: var(--mantine-font-size-lg);
font-weight: bold;
color: var(--mantine-primary-color-5);
margin: 0;
}
.subjectStack {
display: flex;
flex-direction: column;
justify-content: center;
}

View File

@ -1,26 +1,37 @@
import InnerHtml from "@/components/InnerHtml";
import classes from './Announcement.module.css'
import {Group, ThemeIcon} from "@mantine/core";
import {Group, Text, ThemeIcon, Tooltip} from "@mantine/core";
import {IconSpeakerphone} from "@tabler/icons-react";
import {MessagesModel} from "@/models/MessageTypes.ts";
import {getUserName} from "@/components/users/modals/util.tsx";
import {humanDeltaFromNow, pprintDate} from "@/lib/datetime.ts";
export default function Announcement({subject, content}: {
subject: string | null,
content: string,
export default function Announcement({announcement}: {
announcement: MessagesModel
}) {
const senderName = getUserName(announcement.expand.sender)
return <div className={classes.announcement}>
<Group justify={"space-between"} wrap={"nowrap"} align={"top"} mb={"md"}>
{subject && <div className={classes.subject}>
{subject}
<div className={classes.subjectStack}>
{announcement.subject && <div className={`${classes.subject} wrapWords`}>
{announcement.subject}
</div>}
<Text size={"xs"} c={"dimmed"} className={"wrapWords"}>
{senderName} {pprintDate(announcement.created)} {humanDeltaFromNow(announcement.created).message}
</Text>
</div>
<Tooltip label={`Ankündigung von ${getUserName(announcement.expand.sender)}`} withArrow>
<ThemeIcon
className={classes.icon}
variant={"transparent"} size={"sm"}
>
<IconSpeakerphone/>
</ThemeIcon>
</Tooltip>
</Group>
<InnerHtml html={content}/>
<InnerHtml html={announcement.content}/>
</div>
}

View File

@ -2,5 +2,6 @@
flex-grow: 1;
overflow-y: auto;
display: flex;
flex-direction: column-reverse;
flex-direction: column;
gap: var(--gap);
}

View File

@ -2,7 +2,7 @@ import {useInfiniteQuery} from "@tanstack/react-query";
import {PocketBaseErrorAlert, usePB} from "@/lib/pocketbase.tsx";
import {Button, Center, Loader, Text} from "@mantine/core";
import classes from './Announcements.module.css'
import {IconMessageCircleUp} from "@tabler/icons-react";
import {IconMessageCircleDown} from "@tabler/icons-react";
import Announcement from "@/pages/chat/components/Announcement.tsx";
export default function Announcements() {
@ -11,9 +11,10 @@ export default function Announcements() {
const query = useInfiniteQuery({
queryKey: ["announcements"],
queryFn: async ({pageParam}) => (
await pb.collection("messages").getList(pageParam, 100, {
await pb.collection("messages").getList(pageParam, 50, {
filter: `isAnnouncement=true&&sender!='${user?.id}'`,
sort: "-created"
sort: "-created",
expand: "sender"
})
),
getNextPageParam: (lastPage) =>
@ -39,8 +40,7 @@ export default function Announcements() {
{announcements.map((announcement) => (
<Announcement
key={announcement.id}
subject={announcement.subject}
content={announcement.content}
announcement={announcement}
/>
))}
@ -50,21 +50,18 @@ export default function Announcements() {
variant={"transparent"} color={"blue"}
radius={"xl"}
onClick={() => query.fetchNextPage()}
leftSection={<IconMessageCircleUp/>}
leftSection={<IconMessageCircleDown/>}
loading={query.isFetchingNextPage}
>
Mehr laden
</Button>
</Center>
) : <div className={classes.text}>
) : announcements.length === 0 ? <div className={classes.text}>
<Text ta={"center"} size={"xs"} c={"dimmed"}>
{
announcements.length > 0 ?
"Keine weiteren Ankündigungen"
: "Noch keine Ankündigungen"
}
"Noch keine Ankündigungen"
</Text>
</div>}
</div> : null
}
</div>
</div>
}

View File

@ -17,8 +17,6 @@
position: relative;
flex-direction: column;
box-shadow: var(--shadow);
background-color: var(--mantine-color-body);
padding: var(--padding);

View File

@ -8,7 +8,7 @@ import {useInfiniteQuery, useMutation} from "@tanstack/react-query";
import {PocketBaseErrorAlert, usePB} from "@/lib/pocketbase.tsx";
import InnerHtml from "@/components/InnerHtml";
import {getUserName} from "@/components/users/modals/util.tsx";
import {pprintDateTime} from "@/lib/datetime.ts";
import {humanDeltaFromNow, pprintDateTime} from "@/lib/datetime.ts";
import {EventListModel} from "@/models/EventTypes.ts";
export default function Messages({eventList}: {
@ -87,7 +87,7 @@ export default function Messages({eventList}: {
<InnerHtml html={message.content}/>
<div className={classes.messageSender}>
{pprintDateTime(message.created)}
{humanDeltaFromNow(message.created).message} {pprintDateTime(message.created)}
</div>
</div>
))}

View File

@ -1,5 +1,5 @@
.announcementsContainer {
max-height: 60vh;
max-height: 40vh;
display: flex;
& > * {
max-height: 100%;