ghép API sendManifest
This commit is contained in:
parent
4accb1dfc5
commit
bd21d18c21
|
|
@ -74,6 +74,9 @@ export const API_ENDPOINTS = {
|
||||||
DELETE_REQUIRED_FILE: `${BASE_URL}/AppVersion/requirefile/delete`,
|
DELETE_REQUIRED_FILE: `${BASE_URL}/AppVersion/requirefile/delete`,
|
||||||
DELETE_FILES: `${BASE_URL}/AppVersion/delete`,
|
DELETE_FILES: `${BASE_URL}/AppVersion/delete`,
|
||||||
},
|
},
|
||||||
|
MANIFEST: {
|
||||||
|
SEND_ALL: `${BASE_URL}/Manifest/sendall`,
|
||||||
|
},
|
||||||
DEVICE_COMM: {
|
DEVICE_COMM: {
|
||||||
DOWNLOAD_FILES: (roomName: string) => `${BASE_URL}/DeviceComm/downloadfile/${roomName}`,
|
DOWNLOAD_FILES: (roomName: string) => `${BASE_URL}/DeviceComm/downloadfile/${roomName}`,
|
||||||
INSTALL_MSI: (roomName: string) => `${BASE_URL}/DeviceComm/installmsi/${roomName}`,
|
INSTALL_MSI: (roomName: string) => `${BASE_URL}/DeviceComm/installmsi/${roomName}`,
|
||||||
|
|
|
||||||
|
|
@ -186,11 +186,10 @@ export function useDeleteFile() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hook để gửi manifest [MOCK]
|
* Hook để gửi manifest
|
||||||
*/
|
*/
|
||||||
export function useSendManifest() {
|
export function useSendManifest() {
|
||||||
return useMutation({
|
return useMutation({
|
||||||
mutationFn: (data: { targets: string[]; MsiFileIds: number[] }) =>
|
mutationFn: () => appVersionService.sendManifest(),
|
||||||
appVersionService.sendManifest(data),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -191,23 +191,16 @@ function AppsComponent() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSendManifest = async (roomNames: string[]) => {
|
const handleSendManifest = async (targets: string[]) => {
|
||||||
if (!table) {
|
// targets ignored for now — API sendall broadcasts to all devices via MQTT
|
||||||
toast.error("Không thể lấy thông tin bảng!");
|
// TODO: use targets when per-room/per-device manifest API is available
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const selectedRows = table.getSelectedRowModel().rows;
|
|
||||||
if (selectedRows.length === 0) {
|
|
||||||
toast.error("Vui lòng chọn ít nhất một file để gửi manifest!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const MsiFileIds = selectedRows.map((row: any) => row.original.id);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await sendManifestMutation.mutateAsync({ targets: roomNames, MsiFileIds });
|
await sendManifestMutation.mutateAsync();
|
||||||
toast.success("Đã gửi manifest cho các phòng đã chọn!");
|
toast.success(
|
||||||
|
targets.length > 0
|
||||||
|
? `Đã gửi manifest cho ${targets.length} mục!`
|
||||||
|
: "Đã gửi manifest đến tất cả thiết bị!"
|
||||||
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
toast.error("Gửi manifest thất bại!");
|
toast.error("Gửi manifest thất bại!");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -131,14 +131,9 @@ export async function deleteFile(data: { MsiFileIds: number[] }): Promise<{ mess
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [MOCK] Gửi manifest đến các phòng/thiết bị
|
* Gửi manifest (build + publish MQTT tới tất cả required files)
|
||||||
* @param data - { targets: string[]; MsiFileIds: number[] }
|
|
||||||
*/
|
*/
|
||||||
export async function sendManifest(data: {
|
export async function sendManifest(): Promise<{ status: string; message: string }> {
|
||||||
targets: string[];
|
const response = await axios.post(API_ENDPOINTS.MANIFEST.SEND_ALL);
|
||||||
MsiFileIds: number[];
|
return response.data;
|
||||||
}): Promise<{ message: string }> {
|
|
||||||
// TODO: replace with real endpoint
|
|
||||||
await new Promise((resolve) => setTimeout(resolve, 800));
|
|
||||||
return { message: `[MOCK] Manifest sent to ${data.targets.join(", ")}` };
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ export function AppManagerTemplate<TData>({
|
||||||
pageSizeOptions = [5, 10, 15, 20],
|
pageSizeOptions = [5, 10, 15, 20],
|
||||||
}: AppManagerTemplateProps<TData>) {
|
}: AppManagerTemplateProps<TData>) {
|
||||||
const [dialogOpen, setDialogOpen] = useState(false);
|
const [dialogOpen, setDialogOpen] = useState(false);
|
||||||
const [dialogType, setDialogType] = useState<"room" | "device" | "download-room" | "download-device" | "manifest-room" | null>(null);
|
const [dialogType, setDialogType] = useState<"room" | "device" | "download-room" | "download-device" | "manifest-room" | "manifest-device" | null>(null);
|
||||||
|
|
||||||
const sortedData = useMemo(() => {
|
const sortedData = useMemo(() => {
|
||||||
const firstItem = data?.[0] as { fileName?: string } | undefined;
|
const firstItem = data?.[0] as { fileName?: string } | undefined;
|
||||||
|
|
@ -128,6 +128,7 @@ export function AppManagerTemplate<TData>({
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const openManifestRoomDialog = () => {
|
const openManifestRoomDialog = () => {
|
||||||
if (rooms.length > 0 && onSendManifest) {
|
if (rooms.length > 0 && onSendManifest) {
|
||||||
setDialogType("manifest-room");
|
setDialogType("manifest-room");
|
||||||
|
|
@ -135,6 +136,18 @@ export function AppManagerTemplate<TData>({
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const openManifestDeviceDialog = () => {
|
||||||
|
if (onSendManifest) {
|
||||||
|
setDialogType("manifest-device");
|
||||||
|
setDialogOpen(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleManifestAll = async () => {
|
||||||
|
if (!onSendManifest) return;
|
||||||
|
await onSendManifest([]);
|
||||||
|
};
|
||||||
|
|
||||||
const handleUpdateAll = async () => {
|
const handleUpdateAll = async () => {
|
||||||
if (!onUpdate) return;
|
if (!onUpdate) return;
|
||||||
try {
|
try {
|
||||||
|
|
@ -229,14 +242,16 @@ export function AppManagerTemplate<TData>({
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
{onSendManifest && (
|
{onSendManifest && (
|
||||||
<Button
|
<RequestUpdateMenu
|
||||||
onClick={openManifestRoomDialog}
|
onUpdateAll={handleManifestAll}
|
||||||
disabled={sendManifestLoading}
|
onUpdateRoom={openManifestRoomDialog}
|
||||||
variant="outline"
|
onUpdateDevice={openManifestDeviceDialog}
|
||||||
className="gap-2"
|
loading={sendManifestLoading}
|
||||||
>
|
label="Gửi Manifest"
|
||||||
{sendManifestLoading ? "Đang gửi..." : "Gửi Manifest"}
|
allLabel="Gửi tất cả"
|
||||||
</Button>
|
roomLabel="Gửi theo phòng"
|
||||||
|
deviceLabel="Gửi theo thiết bị"
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{onDeleteFromServer && onDeleteFromRequired && (
|
{onDeleteFromServer && onDeleteFromRequired && (
|
||||||
|
|
@ -336,33 +351,8 @@ export function AppManagerTemplate<TData>({
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Dialog gửi manifest - chọn phòng */}
|
|
||||||
{dialogType === "manifest-room" && (
|
|
||||||
<SelectDialog
|
|
||||||
open={dialogOpen}
|
|
||||||
onClose={() => {
|
|
||||||
setDialogOpen(false);
|
|
||||||
setDialogType(null);
|
|
||||||
}}
|
|
||||||
title="Chọn phòng"
|
|
||||||
description="Chọn các phòng để gửi manifest"
|
|
||||||
icon={<Building2 className="w-6 h-6 text-primary" />}
|
|
||||||
items={mapRoomsToSelectItems(rooms)}
|
|
||||||
onConfirm={async (selectedItems) => {
|
|
||||||
if (!onSendManifest) return;
|
|
||||||
try {
|
|
||||||
await onSendManifest(selectedItems);
|
|
||||||
} catch (e) {
|
|
||||||
console.error("Send manifest error:", e);
|
|
||||||
} finally {
|
|
||||||
setDialogOpen(false);
|
|
||||||
setDialogType(null);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Dialog tải file - tìm thiết bị */}
|
{/* Dialog tải file - tìm thiết bị */}
|
||||||
{dialogType === "download-device" && (
|
{dialogType === "download-device" && (
|
||||||
<DeviceSearchDialog
|
<DeviceSearchDialog
|
||||||
open={dialogOpen && dialogType === "download-device"}
|
open={dialogOpen && dialogType === "download-device"}
|
||||||
|
|
@ -391,6 +381,60 @@ export function AppManagerTemplate<TData>({
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* Dialog gửi manifest - chọn phòng */}
|
||||||
|
{dialogType === "manifest-room" && (
|
||||||
|
<SelectDialog
|
||||||
|
open={dialogOpen}
|
||||||
|
onClose={() => {
|
||||||
|
setDialogOpen(false);
|
||||||
|
setDialogType(null);
|
||||||
|
}}
|
||||||
|
title="Chọn phòng"
|
||||||
|
description="Chọn các phòng để gửi manifest"
|
||||||
|
icon={<Building2 className="w-6 h-6 text-primary" />}
|
||||||
|
items={mapRoomsToSelectItems(rooms)}
|
||||||
|
onConfirm={async (selectedItems) => {
|
||||||
|
if (!onSendManifest) return;
|
||||||
|
try {
|
||||||
|
await onSendManifest(selectedItems);
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Send manifest error:", e);
|
||||||
|
} finally {
|
||||||
|
setDialogOpen(false);
|
||||||
|
setDialogType(null);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Dialog gửi manifest - chọn thiết bị */}
|
||||||
|
{dialogType === "manifest-device" && (
|
||||||
|
<DeviceSearchDialog
|
||||||
|
open={dialogOpen && dialogType === "manifest-device"}
|
||||||
|
onClose={() => {
|
||||||
|
setDialogOpen(false);
|
||||||
|
setDialogType(null);
|
||||||
|
}}
|
||||||
|
rooms={rooms}
|
||||||
|
fetchDevices={getDeviceFromRoom}
|
||||||
|
onSelect={async (deviceIds) => {
|
||||||
|
if (!onSendManifest) {
|
||||||
|
setDialogOpen(false);
|
||||||
|
setDialogType(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await onSendManifest(deviceIds);
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Send manifest error:", e);
|
||||||
|
} finally {
|
||||||
|
setDialogOpen(false);
|
||||||
|
setDialogType(null);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user