mirror of
https://github.com/hexastack/hexabot
synced 2025-01-22 10:35:37 +00:00
feat(frontend): apply frontend updates (context)
This commit is contained in:
parent
994c8857e9
commit
7be61150ac
@ -1,18 +1,19 @@
|
||||
/*
|
||||
* Copyright © 2024 Hexastack. All rights reserved.
|
||||
* Copyright © 2025 Hexastack. All rights reserved.
|
||||
*
|
||||
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
|
||||
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
|
||||
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
|
||||
*/
|
||||
|
||||
|
||||
import { Box, FormHelperText, FormLabel } from "@mui/material";
|
||||
import { forwardRef } from "react";
|
||||
|
||||
import { useGet } from "@/hooks/crud/useGet";
|
||||
import { useHasPermission } from "@/hooks/useHasPermission";
|
||||
import { EntityType } from "@/services/types";
|
||||
import { IAttachment } from "@/types/attachment.types";
|
||||
import { IAttachment, TAttachmentContext } from "@/types/attachment.types";
|
||||
import { PermissionAction } from "@/types/permission.types";
|
||||
|
||||
import AttachmentThumbnail from "./AttachmentThumbnail";
|
||||
@ -28,6 +29,7 @@ type AttachmentThumbnailProps = {
|
||||
onChange?: (id: string | null, mimeType: string | null) => void;
|
||||
error?: boolean;
|
||||
helperText?: string;
|
||||
context: TAttachmentContext;
|
||||
};
|
||||
|
||||
const AttachmentInput = forwardRef<HTMLDivElement, AttachmentThumbnailProps>(
|
||||
@ -42,6 +44,7 @@ const AttachmentInput = forwardRef<HTMLDivElement, AttachmentThumbnailProps>(
|
||||
onChange,
|
||||
error,
|
||||
helperText,
|
||||
context,
|
||||
},
|
||||
ref,
|
||||
) => {
|
||||
@ -81,6 +84,7 @@ const AttachmentInput = forwardRef<HTMLDivElement, AttachmentThumbnailProps>(
|
||||
accept={accept}
|
||||
enableMediaLibrary={enableMediaLibrary}
|
||||
onChange={handleChange}
|
||||
context={context}
|
||||
/>
|
||||
) : null}
|
||||
{helperText ? (
|
||||
|
@ -1,11 +1,12 @@
|
||||
/*
|
||||
* Copyright © 2024 Hexastack. All rights reserved.
|
||||
* Copyright © 2025 Hexastack. All rights reserved.
|
||||
*
|
||||
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
|
||||
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
|
||||
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
|
||||
*/
|
||||
|
||||
|
||||
import CloudUploadIcon from "@mui/icons-material/CloudUpload";
|
||||
import FolderCopyIcon from "@mui/icons-material/FolderCopy";
|
||||
import { Box, Button, Divider, Grid, styled, Typography } from "@mui/material";
|
||||
@ -16,7 +17,7 @@ import { getDisplayDialogs, useDialog } from "@/hooks/useDialog";
|
||||
import { useToast } from "@/hooks/useToast";
|
||||
import { useTranslate } from "@/hooks/useTranslate";
|
||||
import { EntityType } from "@/services/types";
|
||||
import { IAttachment } from "@/types/attachment.types";
|
||||
import { IAttachment, TAttachmentContext } from "@/types/attachment.types";
|
||||
|
||||
import { AttachmentDialog } from "./AttachmentDialog";
|
||||
import AttachmentThumbnail from "./AttachmentThumbnail";
|
||||
@ -67,6 +68,7 @@ export type FileUploadProps = {
|
||||
enableMediaLibrary?: boolean;
|
||||
onChange?: (data?: IAttachment | null) => void;
|
||||
onUploadComplete?: () => void;
|
||||
context: TAttachmentContext;
|
||||
};
|
||||
|
||||
const AttachmentUploader: FC<FileUploadProps> = ({
|
||||
@ -74,6 +76,7 @@ const AttachmentUploader: FC<FileUploadProps> = ({
|
||||
enableMediaLibrary,
|
||||
onChange,
|
||||
onUploadComplete,
|
||||
context,
|
||||
}) => {
|
||||
const [attachment, setAttachment] = useState<IAttachment | undefined>(
|
||||
undefined,
|
||||
@ -97,34 +100,40 @@ const AttachmentUploader: FC<FileUploadProps> = ({
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
};
|
||||
const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
|
||||
if (event.target.files && event.target.files.length > 0) {
|
||||
const file = event.target.files.item(0);
|
||||
|
||||
const handleUpload = (file: File | null) => {
|
||||
if (file) {
|
||||
const acceptedTypes = accept.split(",");
|
||||
const isValidType = acceptedTypes.some(
|
||||
(type) =>
|
||||
file.type === type || file.name.endsWith(type.replace(".*", "")),
|
||||
const isValidType = acceptedTypes.some((mimeType) => {
|
||||
const [type, subtype] = mimeType.split("/");
|
||||
|
||||
if (!type || !subtype) return false; // Ensure valid MIME type
|
||||
|
||||
return (
|
||||
file.type === mimeType ||
|
||||
(subtype === "*" && file.type.startsWith(`${type}/`))
|
||||
);
|
||||
});
|
||||
|
||||
if (!isValidType) {
|
||||
toast.error(t("message.invalid_file_type"));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
uploadAttachment(file);
|
||||
uploadAttachment({ file, context });
|
||||
}
|
||||
};
|
||||
const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
|
||||
if (event.target.files && event.target.files.length > 0) {
|
||||
const file = event.target.files.item(0);
|
||||
|
||||
handleUpload(file);
|
||||
}
|
||||
};
|
||||
const onDrop = (event: DragEvent<HTMLElement>) => {
|
||||
if (event.dataTransfer.files && event.dataTransfer.files.length > 0) {
|
||||
const file = event.dataTransfer.files.item(0);
|
||||
|
||||
if (file) {
|
||||
uploadAttachment(file);
|
||||
}
|
||||
handleUpload(file);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1,17 +1,18 @@
|
||||
/*
|
||||
* Copyright © 2024 Hexastack. All rights reserved.
|
||||
* Copyright © 2025 Hexastack. All rights reserved.
|
||||
*
|
||||
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
|
||||
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
|
||||
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
|
||||
*/
|
||||
|
||||
|
||||
import { Box, Button, FormHelperText, FormLabel } from "@mui/material";
|
||||
import { forwardRef, useState } from "react";
|
||||
|
||||
import { useHasPermission } from "@/hooks/useHasPermission";
|
||||
import { EntityType } from "@/services/types";
|
||||
import { IAttachment } from "@/types/attachment.types";
|
||||
import { IAttachment, TAttachmentContext } from "@/types/attachment.types";
|
||||
import { PermissionAction } from "@/types/permission.types";
|
||||
|
||||
import AttachmentThumbnail from "./AttachmentThumbnail";
|
||||
@ -27,6 +28,7 @@ type MultipleAttachmentInputProps = {
|
||||
onChange?: (ids: string[]) => void;
|
||||
error?: boolean;
|
||||
helperText?: string;
|
||||
context: TAttachmentContext;
|
||||
};
|
||||
|
||||
const MultipleAttachmentInput = forwardRef<
|
||||
@ -44,6 +46,7 @@ const MultipleAttachmentInput = forwardRef<
|
||||
onChange,
|
||||
error,
|
||||
helperText,
|
||||
context,
|
||||
},
|
||||
ref,
|
||||
) => {
|
||||
@ -106,6 +109,7 @@ const MultipleAttachmentInput = forwardRef<
|
||||
accept={accept}
|
||||
enableMediaLibrary={enableMediaLibrary}
|
||||
onChange={(attachment) => handleChange(attachment)}
|
||||
context={context}
|
||||
/>
|
||||
)}
|
||||
{helperText && (
|
||||
|
@ -116,6 +116,7 @@ const ContentFieldInput: React.FC<ContentFieldInput> = ({
|
||||
value={field.value?.payload?.id}
|
||||
accept={MIME_TYPES["images"].join(",")}
|
||||
format="full"
|
||||
context="content_attachment"
|
||||
/>
|
||||
);
|
||||
default:
|
||||
|
@ -1,11 +1,12 @@
|
||||
/*
|
||||
* Copyright © 2024 Hexastack. All rights reserved.
|
||||
* Copyright © 2025 Hexastack. All rights reserved.
|
||||
*
|
||||
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
|
||||
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
|
||||
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
|
||||
*/
|
||||
|
||||
|
||||
import CloseIcon from "@mui/icons-material/Close";
|
||||
import { Button, Dialog, DialogActions, DialogContent } from "@mui/material";
|
||||
import { FC, useState } from "react";
|
||||
@ -80,6 +81,7 @@ export const ContentImportDialog: FC<ContentImportDialogProps> = ({
|
||||
}}
|
||||
label=""
|
||||
value={attachmentId}
|
||||
context="content_attachment"
|
||||
/>
|
||||
</ContentItem>
|
||||
</ContentContainer>
|
||||
|
@ -1,11 +1,12 @@
|
||||
/*
|
||||
* Copyright © 2024 Hexastack. All rights reserved.
|
||||
* Copyright © 2025 Hexastack. All rights reserved.
|
||||
*
|
||||
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
|
||||
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
|
||||
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
|
||||
*/
|
||||
|
||||
|
||||
import KeyIcon from "@mui/icons-material/Key";
|
||||
import { FormControlLabel, MenuItem, Switch } from "@mui/material";
|
||||
import { ControllerRenderProps } from "react-hook-form";
|
||||
@ -185,6 +186,7 @@ const SettingInput: React.FC<RenderSettingInputProps> = ({
|
||||
accept={MIME_TYPES["images"].join(",")}
|
||||
format="full"
|
||||
size={128}
|
||||
context="setting_attachment"
|
||||
/>
|
||||
);
|
||||
|
||||
@ -197,6 +199,7 @@ const SettingInput: React.FC<RenderSettingInputProps> = ({
|
||||
accept={MIME_TYPES["images"].join(",")}
|
||||
format="full"
|
||||
size={128}
|
||||
context="setting_attachment"
|
||||
/>
|
||||
);
|
||||
default:
|
||||
|
@ -69,6 +69,7 @@ const AttachmentMessageForm = () => {
|
||||
},
|
||||
});
|
||||
}}
|
||||
context="block_attachment"
|
||||
/>
|
||||
);
|
||||
}}
|
||||
|
@ -9,6 +9,7 @@
|
||||
import { useMutation, useQueryClient } from "react-query";
|
||||
|
||||
import { QueryType, TMutationOptions } from "@/services/types";
|
||||
import { TAttachmentContext } from "@/types/attachment.types";
|
||||
import { IBaseSchema, IDynamicProps, TType } from "@/types/base.types";
|
||||
|
||||
import { useEntityApiClient } from "../useApiClient";
|
||||
@ -23,7 +24,12 @@ export const useUpload = <
|
||||
>(
|
||||
entity: TEntity,
|
||||
options?: Omit<
|
||||
TMutationOptions<TBasic, Error, File, TBasic>,
|
||||
TMutationOptions<
|
||||
TBasic,
|
||||
Error,
|
||||
{ file: File; context: TAttachmentContext },
|
||||
TBasic
|
||||
>,
|
||||
"mutationFn" | "mutationKey"
|
||||
>,
|
||||
) => {
|
||||
@ -33,8 +39,8 @@ export const useUpload = <
|
||||
const { invalidate = true, ...otherOptions } = options || {};
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async (variables: File) => {
|
||||
const data = await api.upload(variables);
|
||||
mutationFn: async ({ file, context }) => {
|
||||
const data = await api.upload(file, context);
|
||||
const { entities, result } = normalizeAndCache(data);
|
||||
|
||||
// Invalidate all counts & collections
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
import { AxiosInstance, AxiosResponse } from "axios";
|
||||
|
||||
import { TAttachmentContext } from "@/types/attachment.types";
|
||||
import { ILoginAttributes } from "@/types/auth/login.types";
|
||||
import { IUserPermissions } from "@/types/auth/permission.types";
|
||||
import { StatsType } from "@/types/bot-stat.types";
|
||||
@ -301,7 +302,7 @@ export class EntityApiClient<TAttr, TBasic, TFull> extends ApiClient {
|
||||
return data;
|
||||
}
|
||||
|
||||
async upload(file: File) {
|
||||
async upload(file: File, context?: TAttachmentContext) {
|
||||
const { _csrf } = await this.getCsrf();
|
||||
const formData = new FormData();
|
||||
|
||||
@ -311,11 +312,17 @@ export class EntityApiClient<TAttr, TBasic, TFull> extends ApiClient {
|
||||
TBasic[],
|
||||
AxiosResponse<TBasic[]>,
|
||||
FormData
|
||||
>(`${ROUTES[this.type]}/upload?_csrf=${_csrf}`, formData, {
|
||||
>(
|
||||
`${ROUTES[this.type]}/upload?_csrf=${_csrf}${
|
||||
context ? `&context=${context}` : ""
|
||||
}`,
|
||||
formData,
|
||||
{
|
||||
headers: {
|
||||
"Content-Type": "multipart/form-data",
|
||||
},
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
return data[0];
|
||||
}
|
||||
|
@ -1,14 +1,43 @@
|
||||
/*
|
||||
* Copyright © 2024 Hexastack. All rights reserved.
|
||||
* Copyright © 2025 Hexastack. All rights reserved.
|
||||
*
|
||||
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
|
||||
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
|
||||
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
|
||||
*/
|
||||
|
||||
import { Format } from "@/services/types";
|
||||
|
||||
import { IBaseSchema, IFormat } from "./base.types";
|
||||
import { EntityType, Format } from "@/services/types";
|
||||
|
||||
import { IBaseSchema, IFormat, OmitPopulate } from "./base.types";
|
||||
import { ISubscriber } from "./subscriber.types";
|
||||
import { IUser } from "./user.types";
|
||||
|
||||
/**
|
||||
* Defines the types of owners for an attachment,
|
||||
* indicating whether the file belongs to a User or a Subscriber.
|
||||
*/
|
||||
export enum AttachmentOwnerType {
|
||||
User = "User",
|
||||
Subscriber = "Subscriber",
|
||||
}
|
||||
|
||||
export type TAttachmentOwnerType = `${AttachmentOwnerType}`;
|
||||
|
||||
/**
|
||||
* Defines the various contexts in which an attachment can exist.
|
||||
* These contexts influence how the attachment is uploaded, stored, and accessed:
|
||||
*/
|
||||
export enum AttachmentContext {
|
||||
SettingAttachment = "setting_attachment", // Attachments related to app settings, restricted to users with specific permissions.
|
||||
UserAvatar = "user_avatar", // Avatar files for users, only the current user can upload, accessible to those with appropriate permissions.
|
||||
SubscriberAvatar = "subscriber_avatar", // Avatar files for subscribers, uploaded programmatically, accessible to authorized users.
|
||||
BlockAttachment = "block_attachment", // Files sent by the bot, public or private based on the channel and user authentication.
|
||||
ContentAttachment = "content_attachment", // Files in the knowledge base, usually public but could vary based on specific needs.
|
||||
MessageAttachment = "message_attachment", // Files sent or received via messages, uploaded programmatically, accessible to users with inbox permissions.;
|
||||
}
|
||||
|
||||
export type TAttachmentContext = `${AttachmentContext}`;
|
||||
|
||||
export interface IAttachmentAttributes {
|
||||
name: string;
|
||||
@ -17,8 +46,21 @@ export interface IAttachmentAttributes {
|
||||
location: string;
|
||||
url: string;
|
||||
channel?: Record<string, any>;
|
||||
context: TAttachmentContext;
|
||||
ownerType: TAttachmentOwnerType;
|
||||
owner: string | null;
|
||||
}
|
||||
|
||||
export interface IAttachmentStub extends IBaseSchema, IAttachmentAttributes {}
|
||||
export interface IAttachmentStub
|
||||
extends IBaseSchema,
|
||||
OmitPopulate<IAttachmentAttributes, EntityType.ATTACHMENT> {}
|
||||
|
||||
export interface IAttachment extends IAttachmentStub, IFormat<Format.BASIC> {}
|
||||
export interface IAttachment extends IAttachmentStub, IFormat<Format.BASIC> {
|
||||
owner: string | null;
|
||||
}
|
||||
|
||||
export interface ISubscriberAttachmentFull
|
||||
extends IAttachmentStub,
|
||||
IFormat<Format.FULL> {
|
||||
owner: (ISubscriber | IUser)[];
|
||||
}
|
||||
|
@ -1,11 +1,12 @@
|
||||
/*
|
||||
* Copyright © 2024 Hexastack. All rights reserved.
|
||||
* Copyright © 2025 Hexastack. All rights reserved.
|
||||
*
|
||||
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
|
||||
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
|
||||
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
|
||||
*/
|
||||
|
||||
|
||||
import { GridPaginationModel, GridSortModel } from "@mui/x-data-grid";
|
||||
|
||||
import { EntityType, Format } from "@/services/types";
|
||||
@ -109,7 +110,7 @@ export const POPULATE_BY_TYPE = {
|
||||
[EntityType.MENUTREE]: [],
|
||||
[EntityType.LANGUAGE]: [],
|
||||
[EntityType.TRANSLATION]: [],
|
||||
[EntityType.ATTACHMENT]: [],
|
||||
[EntityType.ATTACHMENT]: ["owner"],
|
||||
[EntityType.CUSTOM_BLOCK]: [],
|
||||
[EntityType.CUSTOM_BLOCK_SETTINGS]: [],
|
||||
[EntityType.CHANNEL]: [],
|
||||
|
Loading…
Reference in New Issue
Block a user