diff --git a/client/src/components/column.tsx b/client/src/components/column.tsx index 9aaaf4c..e9252a6 100644 --- a/client/src/components/column.tsx +++ b/client/src/components/column.tsx @@ -11,6 +11,7 @@ import { DateField, TextField } from "@refinedev/antd"; import Icon from "@ant-design/icons"; import { ReactComponent as SpoolIcon } from "../icon_spool.svg"; import { useTranslate } from "@refinedev/core"; +import { enrichText } from "../utils/parsing"; dayjs.extend(utc); @@ -62,10 +63,18 @@ function Column(props: BaseColumnProps & FilteredColumnProps & CustomC } export function SortedColumn(props: BaseColumnProps) { - // return ; return Column(props); } +export function RichColumn(props: BaseColumnProps) { + return Column({ + ...props, + render: (value: string | undefined) => { + return enrichText(value); + }, + }); +} + export function FilteredColumn(props: BaseColumnProps) { const typedFilters = typeFilters(props.tableState.filters); diff --git a/client/src/pages/filaments/list.tsx b/client/src/pages/filaments/list.tsx index 6bf9176..65d739c 100644 --- a/client/src/pages/filaments/list.tsx +++ b/client/src/pages/filaments/list.tsx @@ -9,7 +9,14 @@ import { genericSorter, typeSorters } from "../../utils/sorting"; import { genericFilterer, typeFilters } from "../../utils/filtering"; import { EditOutlined, FilterOutlined } from "@ant-design/icons"; import { TableState, useInitialTableState, useStoreInitialState } from "../../utils/saveload"; -import { DateColumn, FilteredColumn, NumberColumn, SortedColumn, SpoolIconColumn } from "../../components/column"; +import { + DateColumn, + FilteredColumn, + NumberColumn, + RichColumn, + SortedColumn, + SpoolIconColumn, +} from "../../components/column"; dayjs.extend(utc); @@ -246,7 +253,7 @@ export const FilamentList: React.FC = () => { dataSource, tableState, })} - {SortedColumn({ + {RichColumn({ id: "comment", i18ncat: "filament", dataSource, diff --git a/client/src/pages/filaments/show.tsx b/client/src/pages/filaments/show.tsx index 43c8256..0df6d42 100644 --- a/client/src/pages/filaments/show.tsx +++ b/client/src/pages/filaments/show.tsx @@ -6,6 +6,7 @@ import { NumberFieldUnit } from "../../components/numberField"; import dayjs from "dayjs"; import utc from "dayjs/plugin/utc"; import { IFilament } from "./model"; +import { enrichText } from "../../utils/parsing"; dayjs.extend(utc); @@ -90,7 +91,7 @@ export const FilamentShow: React.FC = () => { {t("filament.fields.article_number")} {t("filament.fields.comment")} - + ); }; diff --git a/client/src/pages/spools/list.tsx b/client/src/pages/spools/list.tsx index 203c514..e7bae19 100644 --- a/client/src/pages/spools/list.tsx +++ b/client/src/pages/spools/list.tsx @@ -9,7 +9,14 @@ import { genericFilterer, typeFilters } from "../../utils/filtering"; import { ISpool } from "./model"; import { TableState, useInitialTableState, useSavedState, useStoreInitialState } from "../../utils/saveload"; import { EditOutlined, FilterOutlined, InboxOutlined, ToTopOutlined } from "@ant-design/icons"; -import { DateColumn, FilteredColumn, NumberColumn, SortedColumn, SpoolIconColumn } from "../../components/column"; +import { + DateColumn, + FilteredColumn, + NumberColumn, + RichColumn, + SortedColumn, + SpoolIconColumn, +} from "../../components/column"; import { setSpoolArchived } from "./functions"; import SelectAndPrint from "../../components/selectAndPrintDialog"; @@ -305,7 +312,7 @@ export const SpoolList: React.FC = () => { dataSource, tableState, })} - {SortedColumn({ + {RichColumn({ id: "comment", i18ncat: "spool", dataSource, diff --git a/client/src/pages/spools/show.tsx b/client/src/pages/spools/show.tsx index 66152a1..fad30f1 100644 --- a/client/src/pages/spools/show.tsx +++ b/client/src/pages/spools/show.tsx @@ -6,6 +6,7 @@ import { NumberFieldUnit } from "../../components/numberField"; import dayjs from "dayjs"; import utc from "dayjs/plugin/utc"; import { ISpool } from "./model"; +import { enrichText } from "../../utils/parsing"; dayjs.extend(utc); @@ -90,7 +91,7 @@ export const SpoolShow: React.FC = () => { {t("spool.fields.lot_nr")} {t("spool.fields.comment")} - + {t("spool.fields.archived")} diff --git a/client/src/pages/vendors/list.tsx b/client/src/pages/vendors/list.tsx index aa812f9..345e5d5 100644 --- a/client/src/pages/vendors/list.tsx +++ b/client/src/pages/vendors/list.tsx @@ -9,7 +9,7 @@ import { genericFilterer, typeFilters } from "../../utils/filtering"; import { IVendor } from "./model"; import { TableState, useInitialTableState, useStoreInitialState } from "../../utils/saveload"; import { EditOutlined, FilterOutlined } from "@ant-design/icons"; -import { DateColumn, SortedColumn } from "../../components/column"; +import { DateColumn, RichColumn, SortedColumn } from "../../components/column"; dayjs.extend(utc); @@ -141,7 +141,7 @@ export const VendorList: React.FC = () => { dataSource, tableState, })} - {SortedColumn({ + {RichColumn({ id: "comment", i18ncat: "vendor", dataSource, diff --git a/client/src/pages/vendors/show.tsx b/client/src/pages/vendors/show.tsx index 0bea96c..91fe291 100644 --- a/client/src/pages/vendors/show.tsx +++ b/client/src/pages/vendors/show.tsx @@ -5,6 +5,7 @@ import { Typography } from "antd"; import dayjs from "dayjs"; import utc from "dayjs/plugin/utc"; import { IVendor } from "./model"; +import { enrichText } from "../../utils/parsing"; dayjs.extend(utc); @@ -31,7 +32,7 @@ export const VendorShow: React.FC = () => { {t("vendor.fields.name")} {t("vendor.fields.comment")} - + ); }; diff --git a/client/src/utils/parsing.ts b/client/src/utils/parsing.ts deleted file mode 100644 index 965c817..0000000 --- a/client/src/utils/parsing.ts +++ /dev/null @@ -1,20 +0,0 @@ - -// Number formatter that nicely formats numbers with correct decimal separator -export function numberFormatter(value: number | undefined) { - return value ? Number(value).toLocaleString() : ""; -} - -// Number parser that supports both comma and dot as decimal separator -export function numberParser(value: string | undefined) { - // Convert comma to dot - const decimalSeparator = (1.1).toLocaleString().charAt(1); - if (decimalSeparator === ",") { - value = value?.replace(",", "."); - } - - // Remove all non-digit characters - value = value?.replace(/[^\d.-]/g, ""); - - // Parse as float - return parseFloat(value || "0"); -} diff --git a/client/src/utils/parsing.tsx b/client/src/utils/parsing.tsx new file mode 100644 index 0000000..7e59ca3 --- /dev/null +++ b/client/src/utils/parsing.tsx @@ -0,0 +1,45 @@ +import React from "react"; + +// Number formatter that nicely formats numbers with correct decimal separator +export function numberFormatter(value: number | undefined) { + return value ? Number(value).toLocaleString() : ""; +} + +// Number parser that supports both comma and dot as decimal separator +export function numberParser(value: string | undefined) { + // Convert comma to dot + const decimalSeparator = (1.1).toLocaleString().charAt(1); + if (decimalSeparator === ",") { + value = value?.replace(",", "."); + } + + // Remove all non-digit characters + value = value?.replace(/[^\d.-]/g, ""); + + // Parse as float + return parseFloat(value || "0"); +} + +export function enrichText(text: string | undefined) { + // Regular expression to match URLs + const urlRegex = + /(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]+\.[^\s]{2,}|www\.[a-zA-Z0-9]+\.[^\s]{2,})/gi; + + // Split the input text by URLs + const parts = (text ?? "").split(urlRegex); + + // Convert URLs to tags + const elements = parts.map((part, index) => { + if (part.match(urlRegex)) { + return ( + + {part} + + ); + } else { + return {part}; + } + }); + + return <>{elements}; +}