mirror of
https://github.com/stonith404/pingvin-share.git
synced 2025-01-22 01:22:32 -05:00
feat(MyShares): show information about own share security options (#720)
* Provide security information about owned shares * Add visitor count display for shares with max views * Add password protection indicator to shares table * Remove validation from MyShareSecurityDTO * center lock icon and add spacing * refactor: run formatter --------- Co-authored-by: Elias Schneider <login@eliasschneider.com>
This commit is contained in:
parent
4d3aa398a2
commit
b58dcdba0b
7 changed files with 60 additions and 9 deletions
|
@ -2,6 +2,7 @@ import { Expose, plainToClass, Type } from "class-transformer";
|
|||
import { ShareDTO } from "./share.dto";
|
||||
import { FileDTO } from "../../file/dto/file.dto";
|
||||
import { OmitType } from "@nestjs/swagger";
|
||||
import { MyShareSecurityDTO } from "./myShareSecurity.dto";
|
||||
|
||||
export class MyShareDTO extends OmitType(ShareDTO, [
|
||||
"files",
|
||||
|
@ -21,6 +22,9 @@ export class MyShareDTO extends OmitType(ShareDTO, [
|
|||
@Type(() => OmitType(FileDTO, ["share", "from"] as const))
|
||||
files: Omit<FileDTO, "share" | "from">[];
|
||||
|
||||
@Expose()
|
||||
security?: MyShareSecurityDTO;
|
||||
|
||||
from(partial: Partial<MyShareDTO>) {
|
||||
return plainToClass(MyShareDTO, partial, { excludeExtraneousValues: true });
|
||||
}
|
||||
|
|
9
backend/src/share/dto/myShareSecurity.dto.ts
Normal file
9
backend/src/share/dto/myShareSecurity.dto.ts
Normal file
|
@ -0,0 +1,9 @@
|
|||
import { Expose } from "class-transformer";
|
||||
|
||||
export class MyShareSecurityDTO {
|
||||
@Expose()
|
||||
passwordProtected: boolean;
|
||||
|
||||
@Expose()
|
||||
maxViews: number;
|
||||
}
|
|
@ -233,7 +233,7 @@ export class ShareService {
|
|||
orderBy: {
|
||||
expiration: "desc",
|
||||
},
|
||||
include: { recipients: true, files: true },
|
||||
include: { recipients: true, files: true, security: true },
|
||||
});
|
||||
|
||||
return shares.map((share) => {
|
||||
|
@ -241,6 +241,10 @@ export class ShareService {
|
|||
...share,
|
||||
size: share.files.reduce((acc, file) => acc + parseInt(file.size), 0),
|
||||
recipients: share.recipients.map((recipients) => recipients.email),
|
||||
security: {
|
||||
maxViews: share.security?.maxViews,
|
||||
passwordProtected: !!share.security?.password,
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
|
@ -124,6 +124,8 @@ export default {
|
|||
"account.shares.table.expiresAt": "Läuft ab am",
|
||||
"account.shares.table.createdAt": "Angelegt am",
|
||||
"account.shares.table.size": "Größe",
|
||||
"account.shares.table.password-protected": "Passwortgeschützt",
|
||||
"account.shares.table.visitor-count": "{count} von {max}",
|
||||
"account.shares.table.expiry-never": "nie",
|
||||
"account.shares.modal.share-informations": "Teile deine Information",
|
||||
"account.shares.modal.share-link": "Freigabe teilen",
|
||||
|
|
|
@ -158,6 +158,8 @@ export default {
|
|||
"account.shares.table.expiresAt": "Expires on",
|
||||
"account.shares.table.createdAt": "Created on",
|
||||
"account.shares.table.size": "Size",
|
||||
"account.shares.table.password-protected": "Password protected",
|
||||
"account.shares.table.visitor-count": "{count} of {max}",
|
||||
"account.shares.table.expiry-never": "Never",
|
||||
|
||||
"account.shares.modal.share-informations": "Share informations",
|
||||
|
|
|
@ -15,7 +15,7 @@ import { useModals } from "@mantine/modals";
|
|||
import moment from "moment";
|
||||
import Link from "next/link";
|
||||
import { useEffect, useState } from "react";
|
||||
import { TbEdit, TbInfoCircle, TbLink, TbTrash } from "react-icons/tb";
|
||||
import { TbEdit, TbInfoCircle, TbLink, TbLock, TbTrash } from "react-icons/tb";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
import Meta from "../../components/Meta";
|
||||
import showShareInformationsModal from "../../components/account/showShareInformationsModal";
|
||||
|
@ -85,13 +85,37 @@ const MyShares = () => {
|
|||
<tbody>
|
||||
{shares.map((share) => (
|
||||
<tr key={share.id}>
|
||||
<td>{share.id}</td>
|
||||
<td>{share.name}</td>
|
||||
<td>{share.views}</td>
|
||||
<td>
|
||||
{moment(share.expiration).unix() === 0
|
||||
? <FormattedMessage id="account.shares.table.expiry-never" />
|
||||
: moment(share.expiration).format("LLL")}
|
||||
<Group spacing="xs">
|
||||
{share.id}{" "}
|
||||
{share.security.passwordProtected && (
|
||||
<TbLock
|
||||
color="orange"
|
||||
title={t("account.shares.table.password-protected")}
|
||||
/>
|
||||
)}
|
||||
</Group>
|
||||
</td>
|
||||
<td>{share.name}</td>
|
||||
<td>
|
||||
{share.security.maxViews ? (
|
||||
<FormattedMessage
|
||||
id="account.shares.table.visitor-count"
|
||||
values={{
|
||||
count: share.views,
|
||||
max: share.security.maxViews,
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
share.views
|
||||
)}
|
||||
</td>
|
||||
<td>
|
||||
{moment(share.expiration).unix() === 0 ? (
|
||||
<FormattedMessage id="account.shares.table.expiry-never" />
|
||||
) : (
|
||||
moment(share.expiration).format("LLL")
|
||||
)}
|
||||
</td>
|
||||
<td>
|
||||
<Group position="right">
|
||||
|
|
|
@ -34,9 +34,10 @@ export type ShareMetaData = {
|
|||
isZipReady: boolean;
|
||||
};
|
||||
|
||||
export type MyShare = Share & {
|
||||
export type MyShare = Omit<Share, "hasPassword"> & {
|
||||
views: number;
|
||||
createdAt: Date;
|
||||
security: MyShareSecurity;
|
||||
};
|
||||
|
||||
export type MyReverseShare = {
|
||||
|
@ -52,3 +53,8 @@ export type ShareSecurity = {
|
|||
maxViews?: number;
|
||||
password?: string;
|
||||
};
|
||||
|
||||
export type MyShareSecurity = {
|
||||
passwordProtected: boolean;
|
||||
maxViews: number;
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue