diff --git a/comps/form/field/type/FilePreview.tsx b/comps/form/field/type/FilePreview.tsx new file mode 100755 index 0000000..952f180 --- /dev/null +++ b/comps/form/field/type/FilePreview.tsx @@ -0,0 +1,102 @@ +import { ExternalLink } from "lucide-react"; + +export const FilePreview = ({ url }: { url: string }) => { + const file = getFileName(url); + const color = darkenColor(generateRandomColor(file.extension)); + let content = ( +
+ {file.extension} +
+ ); + if (url.startsWith("_file/")) { + if ([".png", ".jpeg", ".jpg", ".webp"].find((e) => url.endsWith(e))) { + content = ( + + ); + } + } + return ( + <> + {file.extension && ( +
{ + let _url = siteurl(url || ""); + window.open(_url, "_blank"); + }} + > + {content} +
+ +
+
+ )} + + ); +}; +function darkenColor(color: string, factor: number = 0.5): string { + const rgb = hexToRgb(color); + const r = Math.floor(rgb.r * factor); + const g = Math.floor(rgb.g * factor); + const b = Math.floor(rgb.b * factor); + return rgbToHex(r, g, b); +} + +function hexToRgb(hex: string): { r: number; g: number; b: number } { + const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); + return result + ? { + r: parseInt(result[1], 16), + g: parseInt(result[2], 16), + b: parseInt(result[3], 16), + } + : { r: 0, g: 0, b: 0 }; +} + +function rgbToHex(r: number, g: number, b: number): string { + return `#${r.toString(16).padStart(2, "0")}${g + .toString(16) + .padStart(2, "0")}${b.toString(16).padStart(2, "0")}`; +} +function generateRandomColor(str: string): string { + let hash = 0; + if (str.length === 0) return hash.toString(); // Return a string representation of the hash + for (let i = 0; i < str.length; i++) { + hash = str.charCodeAt(i) + ((hash << 5) - hash); + hash = hash & hash; + } + let color = "#"; + for (let i = 0; i < 3; i++) { + const value = (hash >> (i * 8)) & 255; + color += ("00" + value.toString(16)).substr(-2); + } + return color; +} +const getFileName = (url: string) => { + const fileName = url.substring(url.lastIndexOf("/") + 1); + const dotIndex = fileName.lastIndexOf("."); + const fullname = fileName; + if (dotIndex === -1) { + return { name: fileName, extension: "", fullname }; + } + const name = fileName.substring(0, dotIndex); + const extension = fileName.substring(dotIndex + 1); + return { name, extension, fullname }; +}; diff --git a/comps/form/field/type/TypeInput.tsx b/comps/form/field/type/TypeInput.tsx index f3fe4d0..7e65a24 100755 --- a/comps/form/field/type/TypeInput.tsx +++ b/comps/form/field/type/TypeInput.tsx @@ -3,12 +3,11 @@ import { useLocal } from "@/utils/use-local"; import parser from "any-date-parser"; import Datepicker from "lib/comps/custom/Datepicker"; import { EyeIcon, EyeOff } from "lucide-react"; -import { FC, FocusEvent, KeyboardEvent, MouseEvent } from "react"; +import { FC, FocusEvent } from "react"; import { FMLocal, FieldLocal, FieldProp } from "../../typings"; import { FieldMoney } from "./TypeMoney"; import { FieldRichText } from "./TypeRichText"; import { FieldUpload } from "./TypeUpload"; -import { FieldToggle } from "./TypeToggle"; export type PropTypeInput = { type: "input"; @@ -25,7 +24,6 @@ export type PropTypeInput = { | "toggle" | "rich-text" | "upload" - | "file" | "search" | "password" | "import" diff --git a/comps/form/field/type/TypeUpload.tsx b/comps/form/field/type/TypeUpload.tsx index 3fc71ff..e6cbab8 100755 --- a/comps/form/field/type/TypeUpload.tsx +++ b/comps/form/field/type/TypeUpload.tsx @@ -14,6 +14,7 @@ import { Upload, } from "lucide-react"; import { Spinner } from "lib/comps/ui/field-loading"; +import { FilePreview } from "./FilePreview"; const w = window as unknown as { serverurl: string; }; @@ -38,9 +39,7 @@ export const FieldUpload: FC<{ fase: value ? "preview" : ("start" as "start" | "upload" | "preview"), style: "inline" as "inline" | "full", }); - let display: any = null; - const disabled = - typeof field.disabled === "function" ? field.disabled() : field.disabled; + const on_upload = async (event: any) => { let file = null; try { @@ -226,23 +225,15 @@ export const FieldUpload: FC<{ ) : input.fase === "preview" ? (
-
{ - let url = siteurl(value); - window.open(url, "_blank"); - }} - > - -
- -
-
+
{ + onClick={(e) => { + e.preventDefault(); + e.stopPropagation(); if (confirm("Clear this file ?")) { + input.fase = "start"; fm.data[field.name] = null; fm.render(); } @@ -255,126 +246,6 @@ export const FieldUpload: FC<{ )}
); - return ( -
-
- -
-
- {getFileName("https://www.example.com/path/to/your/file.txt").fullname} -
-
-
- { - let url = siteurl(value); - window.open(url, "_blank"); - }} - /> - { - fm.data[field.name] = null; - fm.render(); - }} - /> -
-
-
- ); -}; - -const Filename = ({ url }: { url: string }) => { - const file = getFileName(url); - - const color = darkenColor(generateRandomColor(file.extension)); - return ( - <> - {file.extension && ( -
- {file.extension} -
- )} -
- View File in New Tab -
- - ); -}; -function darkenColor(color: string, factor: number = 0.5): string { - const rgb = hexToRgb(color); - const r = Math.floor(rgb.r * factor); - const g = Math.floor(rgb.g * factor); - const b = Math.floor(rgb.b * factor); - return rgbToHex(r, g, b); -} - -function hexToRgb(hex: string): { r: number; g: number; b: number } { - const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); - return result - ? { - r: parseInt(result[1], 16), - g: parseInt(result[2], 16), - b: parseInt(result[3], 16), - } - : { r: 0, g: 0, b: 0 }; -} - -function rgbToHex(r: number, g: number, b: number): string { - return `#${r.toString(16).padStart(2, "0")}${g - .toString(16) - .padStart(2, "0")}${b.toString(16).padStart(2, "0")}`; -} -function generateRandomColor(str: string): string { - let hash = 0; - if (str.length === 0) return hash.toString(); // Return a string representation of the hash - for (let i = 0; i < str.length; i++) { - hash = str.charCodeAt(i) + ((hash << 5) - hash); - hash = hash & hash; - } - let color = "#"; - for (let i = 0; i < 3; i++) { - const value = (hash >> (i * 8)) & 255; - color += ("00" + value.toString(16)).substr(-2); - } - return color; -} -const getFileName = (url: string) => { - const fileName = url.substring(url.lastIndexOf("/") + 1); - const dotIndex = fileName.lastIndexOf("."); - const fullname = fileName; - if (dotIndex === -1) { - return { name: fileName, extension: "", fullname }; - } - const name = fileName.substring(0, dotIndex); - const extension = fileName.substring(dotIndex + 1); - return { name, extension, fullname }; }; const IconFile: FC<{ type: string }> = ({ type }) => { diff --git a/comps/form/gen/fields.ts b/comps/form/gen/fields.ts index c6f5374..50c72aa 100755 --- a/comps/form/gen/fields.ts +++ b/comps/form/gen/fields.ts @@ -60,7 +60,7 @@ export const newField = async ( field.name.includes(e) ) ) { - sub_type = "file"; + sub_type = "upload"; } return createItem({ diff --git a/utils/format-value.tsx b/utils/format-value.tsx index cda2a67..6199821 100755 --- a/utils/format-value.tsx +++ b/utils/format-value.tsx @@ -1,9 +1,10 @@ import { GFCol } from "@/gen/utils"; +import dayjs from "dayjs"; +import { formatDate } from "lib/comps/custom/Datepicker/helpers"; +import { FilePreview } from "lib/comps/form/field/type/FilePreview"; +import { formatMoney } from "lib/comps/form/field/type/TypeMoney"; import { FC } from "react"; import { isEmptyString } from "./is-empty-string"; -import { formatDate } from "lib/comps/custom/Datepicker/helpers"; -import dayjs from "dayjs"; -import { formatMoney } from "lib/comps/form/field/type/TypeMoney"; export const fields_map = new Map(); @@ -121,25 +122,13 @@ export const FormatValue: FC<{ } } - // let prefix = <>; - // if (typeof tree_depth === "number" && tree_depth > 0) { - // prefix = ( - //
- //
- //
- // ); - // } + if ( + ["attachment", "file", "img", "image"].find((e) => + name.toLowerCase().includes(e) + ) + ) { + return ; + } return (