From 2122f74cc30c2cb9f4c31fce5c5af5027fa81de3 Mon Sep 17 00:00:00 2001 From: rizky Date: Fri, 9 Aug 2024 19:54:39 -0700 Subject: [PATCH] fix lib --- comps/form/field/Field.tsx | 4 +- comps/form/field/type/TypeInput.tsx | 2 +- comps/form/field/type/TypeUpload.tsx | 277 +------------------- comps/form/field/type/TypeUploadMulti.tsx | 0 comps/form/field/type/TypeUploadSingle.tsx | 281 +++++++++++++++++++++ comps/form/typings.ts | 10 +- comps/form/utils/use-field.tsx | 14 +- exports.tsx | 1 + 8 files changed, 302 insertions(+), 287 deletions(-) create mode 100755 comps/form/field/type/TypeUploadMulti.tsx create mode 100755 comps/form/field/type/TypeUploadSingle.tsx diff --git a/comps/form/field/Field.tsx b/comps/form/field/Field.tsx index c62b19f..2b2c97a 100755 --- a/comps/form/field/Field.tsx +++ b/comps/form/field/Field.tsx @@ -1,11 +1,11 @@ import { useLocal } from "@/utils/use-local"; +import { call_prasi_events } from "lib/exports"; import { FC, useEffect } from "react"; import { FieldProp } from "../typings"; import { useField } from "../utils/use-field"; +import { validate } from "../utils/validate"; import { FieldInput } from "./FieldInput"; import { Label } from "./Label"; -import { validate } from "../utils/validate"; -import { call_prasi_events } from "lib/exports"; export const Field: FC = (arg) => { const showlabel = arg.show_label || "y"; diff --git a/comps/form/field/type/TypeInput.tsx b/comps/form/field/type/TypeInput.tsx index 7e65a24..f84eb33 100755 --- a/comps/form/field/type/TypeInput.tsx +++ b/comps/form/field/type/TypeInput.tsx @@ -63,7 +63,7 @@ export const FieldTypeInput: FC<{ // let value: any = "2024-05-14T05:58:01.376Z" // case untuk date time field.input = input; - field.prop = prop; + if (!field.prop) field.prop = prop; if (["date", "datetime", "datetime-local", "time"].includes(type_field)) { if (typeof value === "string" || value instanceof Date) { let date = parse(value); diff --git a/comps/form/field/type/TypeUpload.tsx b/comps/form/field/type/TypeUpload.tsx index e6cbab8..2900b35 100755 --- a/comps/form/field/type/TypeUpload.tsx +++ b/comps/form/field/type/TypeUpload.tsx @@ -1,20 +1,11 @@ import { useLocal } from "@/utils/use-local"; import get from "lodash.get"; +import { Loader2, Paperclip, Trash2, Upload } from "lucide-react"; import { FC } from "react"; -import { FMLocal, FieldLocal, FieldProp } from "../../typings"; -import { PropTypeInput } from "./TypeInput"; import * as XLSX from "xlsx"; -import { - ArrowDownToLine, - ExternalLink, - Loader2, - Paperclip, - SquareArrowOutUpRight, - Trash2, - Upload, -} from "lucide-react"; -import { Spinner } from "lib/comps/ui/field-loading"; +import { FMLocal, FieldLocal, FieldProp } from "../../typings"; import { FilePreview } from "./FilePreview"; +import { PropTypeInput } from "./TypeInput"; const w = window as unknown as { serverurl: string; }; @@ -27,264 +18,6 @@ export const FieldUpload: FC<{ arg: FieldProp; on_change: (e: any) => void | Promise; }> = ({ field, fm, prop, on_change, arg }) => { - const styling = arg.upload_style ? arg.upload_style : "full"; - let type_field = prop.sub_type; - let value: any = fm.data[field.name]; - // let type_upload = - const input = useLocal({ - value: 0 as any, - display: false as any, - ref: null as any, - drop: false as boolean, - fase: value ? "preview" : ("start" as "start" | "upload" | "preview"), - style: "inline" as "inline" | "full", - }); - - const on_upload = async (event: any) => { - let file = null; - try { - file = event.target.files[0]; - } catch (ex) {} - if (type_field === "import") { - const reader = new FileReader(); - - reader.onload = (e: any) => { - const binaryStr = e.target.result; - const workbook = XLSX.read(binaryStr, { type: "binary" }); - - const worksheet = workbook.Sheets[workbook.SheetNames[0]]; - const jsonData = XLSX.utils.sheet_to_json(worksheet); - if (typeof on_change === "function") { - const res = on_change({ - value: jsonData, - file: file, - binnary: e.target.result, - }); - } - }; - reader.readAsBinaryString(file); - } else { - const formData = new FormData(); - formData.append("file", file); - - let url = siteurl("/_upload"); - if ( - location.hostname === "prasi.avolut.com" || - location.host === "localhost:4550" - ) { - const newurl = new URL(location.href); - newurl.pathname = `/_proxy/${url}`; - url = newurl.toString(); - } - input.fase = "upload"; - input.render(); - try { - const response = await fetch(url, { - method: "POST", - body: formData, - }); - - if (response.ok) { - const contentType: any = response.headers.get("content-type"); - let result; - if (contentType.includes("application/json")) { - result = await response.json(); - } else if (contentType.includes("text/plain")) { - result = await response.text(); - } else { - result = await response.blob(); - } - if (Array.isArray(result)) { - fm.data[field.name] = `_file${get(result, "[0]")}`; - fm.render(); - setTimeout(() => { - input.fase = "preview"; - input.render(); - }, 1000); - } else { - input.fase = "start"; - input.render(); - alert("Error upload"); - } - } else { - } - } catch (ex) { - input.fase = "start"; - input.render(); - alert("Error upload"); - } - } - if (input.ref) { - input.ref.value = null; - } - }; - - if (isEditor) input.fase = "start"; - - return ( -
- {input.fase === "start" ? ( - <> -
- {!isEditor && ( - (input.ref = ref)} - type="file" - multiple={false} - onChange={on_upload} - className={cx( - "c-absolute c-w-full c-h-full c-cursor-pointer c-top-0 c-left-0 c-opacity-0" - )} - /> - )} - {styling !== "full" ? ( - <> -
{ - if (input.ref) { - console.log(input.ref); - input.ref.click(); - } - }} - className="c-items-center c-flex c-text-base c-px-3 c-outline-none c-rounded c-cursor-pointer " - > -
- -
-
- Upload File -
-
- - ) : ( - <> -
{ - e.preventDefault(); - input.drop = false; - input.render(); - }} - onDragOver={(e: any) => { - // Prevent default behavior (Prevent file from being opened) - e.preventDefault(); - input.drop = true; - input.render(); - }} - className={cx( - input.drop ? "c-bg-gray-100" : "", - "hover:c-bg-gray-100 c-flex-grow c-m-1 c-relative c-flex-grow c-p-4 c-items-center c-flex c-flex-row c-text-gray-400 c-border c-border-gray-200 c-border-dashed c-rounded c-cursor-pointer" - )} - > -
- - - - - - -
- - Drop Your File or{" "} - - Browse - - -
-
-
- - )} -
- - ) : input.fase === "upload" ? ( -
-
- -
-
Uploading
-
- ) : input.fase === "preview" ? ( -
- -
- { - e.preventDefault(); - e.stopPropagation(); - if (confirm("Clear this file ?")) { - input.fase = "start"; - fm.data[field.name] = null; - fm.render(); - } - }} - /> -
-
- ) : ( - <> - )} -
- ); -}; - -const IconFile: FC<{ type: string }> = ({ type }) => { - if (["xlsx"].includes(type)) { - return ( -
- - - -
- ); - } else { - return ( -
- -
- ); - } - return ( -
- - - -
- ); + console.log(field.prop.upload); + return <>; }; diff --git a/comps/form/field/type/TypeUploadMulti.tsx b/comps/form/field/type/TypeUploadMulti.tsx new file mode 100755 index 0000000..e69de29 diff --git a/comps/form/field/type/TypeUploadSingle.tsx b/comps/form/field/type/TypeUploadSingle.tsx new file mode 100755 index 0000000..a3012eb --- /dev/null +++ b/comps/form/field/type/TypeUploadSingle.tsx @@ -0,0 +1,281 @@ +import { useLocal } from "@/utils/use-local"; +import get from "lodash.get"; +import { Loader2, Paperclip, Trash2, Upload } from "lucide-react"; +import { FC } from "react"; +import * as XLSX from "xlsx"; +import { FMLocal, FieldLocal, FieldProp } from "../../typings"; +import { FilePreview } from "./FilePreview"; +import { PropTypeInput } from "./TypeInput"; +const w = window as unknown as { + serverurl: string; +}; + +export const FieldUploadSingle: FC<{ + field: FieldLocal; + fm: FMLocal; + prop: PropTypeInput; + styling?: string; + arg: FieldProp; + on_change: (e: any) => void | Promise; +}> = ({ field, fm, prop, on_change, arg }) => { + const styling = arg.upload_style ? arg.upload_style : "full"; + let type_field = prop.sub_type; + let value: any = fm.data[field.name]; + // let type_upload = + const input = useLocal({ + value: 0 as any, + display: false as any, + ref: null as any, + drop: false as boolean, + fase: value ? "preview" : ("start" as "start" | "upload" | "preview"), + style: "inline" as "inline" | "full", + }); + + const on_upload = async (event: any) => { + let file = null; + try { + file = event.target.files[0]; + } catch (ex) {} + if (type_field === "import") { + const reader = new FileReader(); + + reader.onload = (e: any) => { + const binaryStr = e.target.result; + const workbook = XLSX.read(binaryStr, { type: "binary" }); + + const worksheet = workbook.Sheets[workbook.SheetNames[0]]; + const jsonData = XLSX.utils.sheet_to_json(worksheet); + if (typeof on_change === "function") { + const res = on_change({ + value: jsonData, + file: file, + binnary: e.target.result, + }); + } + }; + reader.readAsBinaryString(file); + } else { + const formData = new FormData(); + formData.append("file", file); + + let url = siteurl("/_upload"); + if ( + location.hostname === "prasi.avolut.com" || + location.host === "localhost:4550" + ) { + const newurl = new URL(location.href); + newurl.pathname = `/_proxy/${url}`; + url = newurl.toString(); + } + input.fase = "upload"; + input.render(); + try { + const response = await fetch(url, { + method: "POST", + body: formData, + }); + + if (response.ok) { + const contentType: any = response.headers.get("content-type"); + let result; + if (contentType.includes("application/json")) { + result = await response.json(); + } else if (contentType.includes("text/plain")) { + result = await response.text(); + } else { + result = await response.blob(); + } + if (Array.isArray(result)) { + fm.data[field.name] = `_file${get(result, "[0]")}`; + fm.render(); + setTimeout(() => { + input.fase = "preview"; + input.render(); + }, 1000); + } else { + input.fase = "start"; + input.render(); + alert("Error upload"); + } + } else { + } + } catch (ex) { + input.fase = "start"; + input.render(); + alert("Error upload"); + } + } + if (input.ref) { + input.ref.value = null; + } + }; + + if (isEditor) input.fase = "start"; + + return ( +
+ {input.fase === "start" ? ( + <> +
+ {!isEditor && ( + (input.ref = ref)} + type="file" + multiple={false} + onChange={on_upload} + className={cx( + "c-absolute c-w-full c-h-full c-cursor-pointer c-top-0 c-left-0 c-opacity-0" + )} + /> + )} + {styling !== "full" ? ( + <> +
{ + if (input.ref) { + console.log(input.ref); + input.ref.click(); + } + }} + className="c-items-center c-flex c-text-base c-px-1 c-outline-none c-rounded c-cursor-pointer " + > +
+ +
+
+ Upload File +
+
+ + ) : ( + <> +
{ + e.preventDefault(); + input.drop = false; + input.render(); + }} + onDragOver={(e: any) => { + // Prevent default behavior (Prevent file from being opened) + e.preventDefault(); + input.drop = true; + input.render(); + }} + className={cx( + input.drop ? "c-bg-gray-100" : "", + "hover:c-bg-gray-100 c-flex-grow c-m-1 c-relative c-flex-grow c-p-4 c-items-center c-flex c-flex-row c-text-gray-400 c-border c-border-gray-200 c-border-dashed c-rounded c-cursor-pointer" + )} + > +
+ + + + + + +
+ + Drop Your File or{" "} + + Browse + + +
+
+
+ + )} +
+ + ) : input.fase === "upload" ? ( +
+
+ +
+
Uploading
+
+ ) : input.fase === "preview" ? ( +
+ +
+ { + e.preventDefault(); + e.stopPropagation(); + if (confirm("Clear this file ?")) { + input.fase = "start"; + fm.data[field.name] = null; + fm.render(); + } + }} + /> +
+
+ ) : ( + <> + )} +
+ ); +}; + +const IconFile: FC<{ type: string }> = ({ type }) => { + if (["xlsx"].includes(type)) { + return ( +
+ + + +
+ ); + } else { + return ( +
+ +
+ ); + } + return ( +
+ + + +
+ ); +}; diff --git a/comps/form/typings.ts b/comps/form/typings.ts index 2b985e4..1a1d81d 100755 --- a/comps/form/typings.ts +++ b/comps/form/typings.ts @@ -48,6 +48,7 @@ export type FieldProp = { label: string; desc?: string; props?: any; + upload?: { mode: "single-file" | "multi-file" }; link: { text: | string @@ -107,10 +108,7 @@ export type FieldProp = { current: any; options: { value: string; label: string; item?: any }[]; }) => boolean; - on_init: (arg: { - field: any, - name: string - }) => void; + on_init: (arg: { field: any; name: string }) => void; pk: string; sub_type: string; placeholder: string; @@ -189,11 +187,11 @@ export type FieldInternal = { name: string; fm: FMLocal; }) => void | Promise; - prop?: any; + prop?: FieldProp; max_date?: FieldProp["max_date"]; min_date?: FieldProp["min_date"]; error?: any; - table_fields?: any[] + table_fields?: any[]; }; export type FieldLocal = FieldInternal & { render: () => void; diff --git a/comps/form/utils/use-field.tsx b/comps/form/utils/use-field.tsx index ef01a3c..aefb759 100755 --- a/comps/form/utils/use-field.tsx +++ b/comps/form/utils/use-field.tsx @@ -16,9 +16,9 @@ export const useField = ( input: {}, ref: null as any, } as any); - const ref = useRef(null as any) + const ref = useRef(null as any); field.ref = ref; - + const name = typeof arg.name === "string" ? arg.name : arg.name(); const label = typeof arg.label === "string" ? arg.label : arg.label(); const required = @@ -34,11 +34,12 @@ export const useField = ( custom: arg.custom, required: required === "y", required_msg: arg.required_msg, - disabled: typeof arg.disabled === "function" ? arg.disabled : arg.disabled === "y", + disabled: + typeof arg.disabled === "function" ? arg.disabled : arg.disabled === "y", on_change: arg.on_change, max_date: arg.max_date, min_date: arg.min_date, - table_fields: [] + table_fields: [], }; if (field.status === "init" || isEditor) { @@ -52,13 +53,14 @@ export const useField = ( useEffect(() => { if (field.status === "init" || !fm.fields[name]) { field.status = "ready"; - if(!fm.fields){ - fm.fields = {} + if (!fm.fields) { + fm.fields = {}; } fm.fields[name] = field; field.render(); } }, []); + field.prop = arg; return field; }; diff --git a/exports.tsx b/exports.tsx index 1a5cb42..1fe162b 100755 --- a/exports.tsx +++ b/exports.tsx @@ -54,6 +54,7 @@ const form = lazifyMany({ Form: async () => (await import("@/comps/form/Form")).Form, Field: async () => (await import("@/comps/form/field/Field")).Field, }); + export const Form = form.Form; export const Field = form.Field;