Index: components/EntityMediaList/EntityMediaList.columns.tsx
===================================================================
diff -u -r553d861f45033d5546b32923f4ab7c685a382d36 -r68008a953e5a9f01bfa7dd92a456260017b2d158
--- components/EntityMediaList/EntityMediaList.columns.tsx (.../EntityMediaList.columns.tsx) (revision 553d861f45033d5546b32923f4ab7c685a382d36)
+++ components/EntityMediaList/EntityMediaList.columns.tsx (.../EntityMediaList.columns.tsx) (revision 68008a953e5a9f01bfa7dd92a456260017b2d158)
@@ -1,133 +1,140 @@
-import { ExportOutlined, InfoCircleFilled } from '@ant-design/icons';
-import { DatePicker, message, Spin, Tag, Tooltip } from 'antd';
-import { IEntityMedia, IMediaClassificationFields, IMediaDetails, IMediaFile, IMediaType } from 'lemans-api/models/Media/media.types';
-import { IMediaClassification } from 'lemans-api/models/Media/mediaClassification.types';
-import { InlineEdit } from 'lemans-common';
-import { IOptionProps } from 'lemans-common/components/InlineEdit/Select/Select.types';
-import { useLoader } from 'lemans-common/libs/useToggle';
-import { Link, service } from 'lemans-dashboard-common';
-import moment from 'moment';
-import CopyToClipboard from 'react-copy-to-clipboard';
-import { MediaPreview } from '../MediaPreview';
-import { useEffect, useState } from 'react';
-
-export const MediaImageColumn = (_: any, media: IMediaFile & IMediaType) =>
- ;
-
-export const MediaEntityTagsColumn = (entityId:string, primaryMediaId:number) => (_:any, media: IEntityMedia) => {
- const filteredNumbers = (media.webPartNumber || "").split(",").filter(number => entityId !== `${number}`);
-
- return <>
- {filteredNumbers.length > 0 &&
- Web Part Numbers
- {filteredNumbers.map(number => {number})}
- >}
- >
-
- }
- {primaryMediaId === media.mediaId && Primary}
- {media.isHidden && Hidden}
- >;
-}
-
-export const MediaFileTypeColumn = (_: any, media: IMediaFile) => <>{media.mediaTypeDescription}>;
-
-export const MediaFileNameColumn = (_: any, media: IMediaFile) => {
- const partNumber = media.fullFileName.split(/[\.\_]/)[0];
-
- const onCopy = () => {
- message.success(`${partNumber} copied to your clipboard`);
- }
-
- return <>
-
- {media.fullFileName}
-
-
-
-
-
- >;
-}
-
-type MediaInfo = IMediaClassificationFields & IMediaDetails & IMediaType;
-const ClassificationSelect = ({mediaId, mediaClassificationId, mediaTypeId}: MediaInfo) => {
- const [classificationId, setClassificationId] = useState(mediaClassificationId);
-
- const [options, setOptions] = useState([]);
- useEffect(() => {
- service.media.classification.get("ds").then((classifications: IMediaClassification[]) => {
- setOptions(classifications
- .filter(c => c.mediaTypeId === mediaTypeId)
- .map(c => ({
- text: c.classificationName || "",
- value: c.mediaClassificationId || ""
- }))
- );
- });
- }, []);
-
- const saveChanges = (newMediaClassificationId: number) =>
- service.media.update("ds", mediaId, { mediaClassificationId: newMediaClassificationId })
- .then(() => {
- setClassificationId(newMediaClassificationId);
- });
-
- return ;
-}
-
-export const MediaClassificationColumn = (_: any, media: MediaInfo) =>
- ;
-
-const DescriptionEdit = (media:IMediaDetails) => {
- const [descr, setDescr] = useState(media.description);
- const saveChanges = (description: string) => service.media.update('ds', media.mediaId, { description })
- .then(() => {
- setDescr(description);
- });
-
- return ;
-}
-
-export const MediaDescriptionColumn = (_: any, media: IMediaDetails) =>
- ;
-
-const DateEdit = ({media, field}:{media:IMediaDetails, field:keyof IMediaDetails}) => {
- const [date, setDate] = useState(media[field]);
- const loading = useLoader();
-
- const onChange = (newDate: moment.Moment | null) => {
- loading.start();
- const n = newDate ? newDate.toISOString() : null;
- return service.media.update("ds", media.mediaId, { [field]: n })
- .then(() => {
- setDate(n);
- })
- .finally(loading.done);
- }
-
- return
-
- ;
-}
-
-const dateColumn = (field:keyof IMediaDetails) => (_: any, media: IMediaDetails) =>
- ;
-
-export const MediaEffectiveDateColumn = dateColumn("effectiveDate");
-export const MediaRemoveDateColumn = dateColumn("removeDate");
+import { ExportOutlined, InfoCircleFilled } from '@ant-design/icons';
+import { DatePicker, message, Spin, Tag, Tooltip } from 'antd';
+import { IEntityMedia, IMediaClassificationFields, IMediaDetails, IMediaFile, IMediaType } from 'lemans-api/models/Media/media.types';
+import { IMediaClassification } from 'lemans-api/models/Media/mediaClassification.types';
+import { InlineEdit } from 'lemans-common';
+import { IOptionProps } from 'lemans-common/components/InlineEdit/Select/Select.types';
+import { useLoader } from 'lemans-common/libs/useToggle';
+import { Link, service } from 'lemans-dashboard-common';
+import moment from 'moment';
+import CopyToClipboard from 'react-copy-to-clipboard';
+import { MediaPreview } from '../MediaPreview';
+import { useEffect, useState } from 'react';
+
+export const MediaImageColumn = (_: any, media: IMediaFile & IMediaType) =>
+ ;
+
+export const MediaEntityTagsColumn = (entityId:string, primaryMediaId:number) => (_:any, media: IEntityMedia) => {
+ const filteredNumbers = (media.webPartNumber || "").split(",").filter(number => entityId !== `${number}`);
+
+ return <>
+ {filteredNumbers.length > 0 &&
+ Web Part Numbers
+ {filteredNumbers.map(number => {number})}
+ >}
+ >
+
+ }
+ {primaryMediaId === media.mediaId && Primary}
+ {media.isHidden && Hidden}
+ >;
+}
+
+export const MediaFileTypeColumn = (_: any, media: IMediaFile) => <>{media.mediaTypeDescription}>;
+
+export const MediaFileNameColumn = (_: any, media: IMediaFile) => {
+ const partNumber = media.fullFileName.split(/[\.\_]/)[0];
+
+ const onCopy = () => {
+ message.success(`${partNumber} copied to your clipboard`);
+ }
+
+ return <>
+
+ {media.fullFileName}
+
+
+
+
+
+ >;
+}
+
+type MediaInfo = IMediaClassificationFields & IMediaDetails & IMediaType;
+const ClassificationSelect = ({mediaId, mediaClassificationId, mediaTypeId}: MediaInfo) => {
+ const [classificationId, setClassificationId] = useState(mediaClassificationId);
+
+ const [options, setOptions] = useState([]);
+ useEffect(() => {
+ service.media.classification.get("ds").then((classifications: IMediaClassification[]) => {
+ setOptions(classifications
+ .filter(c => c.mediaTypeId === mediaTypeId)
+ .map(c => ({
+ text: c.classificationName || "",
+ value: c.mediaClassificationId || ""
+ }))
+ );
+ });
+ }, []);
+
+ const saveChanges = (newMediaClassificationId: number) =>
+ service.media.update("ds", mediaId, { mediaClassificationId: newMediaClassificationId })
+ .then(() => {
+ setClassificationId(newMediaClassificationId);
+ });
+
+ return ;
+}
+
+export const MediaClassificationColumn = (_: any, media: MediaInfo) =>
+ ;
+
+const DescriptionEdit = (media:IMediaDetails) => {
+ const [descr, setDescr] = useState(media.description);
+ const saveChanges = (description: string) => service.media.update('ds', media.mediaId, { description })
+ .then(() => {
+ setDescr(description);
+ });
+
+ return ;
+}
+
+export const MediaDescriptionColumn = (_: any, media: IMediaDetails) =>
+ ;
+
+const DateEdit = ({media, field}:{media:IMediaDetails, field:keyof IMediaDetails}) => {
+ const [date, setDate] = useState(media[field]);
+ const loading = useLoader();
+
+ const onChange = (newDate: moment.Moment | null) => {
+ loading.start();
+ const n = newDate ? newDate.toISOString() : null;
+ return service.media.update("ds", media.mediaId, { [field]: n })
+ .then(() => {
+ setDate(n);
+ })
+ .finally(loading.done);
+ }
+
+ return
+
+ ;
+}
+
+const dateColumn = (field:keyof IMediaDetails) => (_: any, media: IMediaDetails) =>
+ ;
+
+export const MediaEffectiveDateColumn = dateColumn("effectiveDate");
+export const MediaRemoveDateColumn = dateColumn("removeDate");
+
+// Added Date column - displays the creation date from audit fields
+export const MediaAddedDateColumn = (_: any, media: IEntityMedia) => {
+ return media.dateCreated ?
+ {moment(media.dateCreated).format('MM/DD/YYYY')} :
+ -;
+};
Index: components/EntityMediaList/EntityMediaList.component.tsx
===================================================================
diff -u -re1e0304a8b1124189c33e7413c3cbecc2667b504 -r68008a953e5a9f01bfa7dd92a456260017b2d158
--- components/EntityMediaList/EntityMediaList.component.tsx (.../EntityMediaList.component.tsx) (revision e1e0304a8b1124189c33e7413c3cbecc2667b504)
+++ components/EntityMediaList/EntityMediaList.component.tsx (.../EntityMediaList.component.tsx) (revision 68008a953e5a9f01bfa7dd92a456260017b2d158)
@@ -1,110 +1,111 @@
-import { OrderedListOutlined } from "@ant-design/icons/lib";
-import { Col, Row, Spin, Table, Tabs } from 'antd';
-import { IEntityMedia } from 'lemans-api/models/Media/media.types';
-import { SortableTable, useRowSelection } from 'lemans-common';
-import { GenericActionBar } from 'lemans-common/components/GenericActionBar';
-import { IGenericActionBarOption } from "lemans-common/components/GenericActionBar/GenericActionBar.types";
-import { useLoader, useTrigger } from 'lemans-common/libs/useToggle';
-import { api, service } from 'lemans-dashboard-common';
-import React, { Key } from 'react';
-import { brandMediaOptions, partMediaOptions, productMediaOptions } from "../MediaSearch/MediaSearch.helpers";
-import { MediaClassificationColumn, MediaDescriptionColumn, MediaEffectiveDateColumn, MediaEntityTagsColumn, MediaFileNameColumn, MediaFileTypeColumn, MediaImageColumn, MediaRemoveDateColumn } from "./EntityMediaList.columns";
-import './EntityMediaList.styles.less';
-import { EntityMediaListProps } from './EntityMediaList.types';
-
-export const EntityMediaListComponent = (props:EntityMediaListProps) => {
- const [media, setMedia] = React.useState([]);
- const loading = useLoader();
- const [selectedMedia, setSelectedMedia, rowSelection] = useRowSelection();
-
- const [primaryMediaId, setPrimaryMediaId] = React.useState(1234);
-
- const [refreshTrigger, refresh] = useTrigger();
-
- React.useEffect(() => {
- loading.start();
-
- const loadEntity:any =
- props.entity === "part" ? service.part.get :
- props.entity === "product" ? service.product.get :
- service.brand.get;
- loadEntity(props.entityId as never).then((e:any) => setPrimaryMediaId(e.primaryMediaId));
-
- setSelectedMedia([]);
-
- service.media.entity.search(props.entity, props.entityId, {...props.filters, sorting: "sequence ASC", pageSize: 1000})
- .then(setMedia)
- .catch(api.handleError)
- .finally(loading.done);
- }, [props.entity, props.entityId, props.filters, refreshTrigger]);
-
- const options:IGenericActionBarOption[] = {
- part: partMediaOptions,
- product: productMediaOptions,
- brand: brandMediaOptions,
- }[props.entity] as IGenericActionBarOption[];
-
- const onActionComplete = () => {
- refresh();
- setSelectedMedia([]);
- };
-
- const sortEntities = (src: IEntityMedia, dst: IEntityMedia, position: "BEFORE" | "AFTER") => {
- loading.start();
-
- // Update local state before calling backend
- const newMedia = [...media];
- const oldIndex = newMedia.findIndex(item => item.mediaId === src.mediaId);
- const newIndex = newMedia.findIndex(item => item.mediaId === dst.mediaId);
-
- if (oldIndex === -1 || newIndex === -1) return;
-
- // Move the item locally
- const [movedItem] = newMedia.splice(oldIndex, 1);
- newMedia.splice(position === "BEFORE" ? newIndex : newIndex + 1, 0, movedItem);
-
- setMedia(newMedia);
-
- // Call backend to persist sorting
- service.media.entity.move(props.entity, props.entityId, src.mediaId, dst.mediaId, position)
- .catch(api.handleError) // Handle API failure gracefully
- .finally(loading.done);
- };
-
- const showTotal = (total: number, range: [number, number]) => `${range[0]} - ${range[1]} of ${total}`;
-
- return
-
-
-
- }
- >
- List} key="list">
-
-
-
-
-
-
-
-
-
-
-
-
- ;
-}
+import { OrderedListOutlined } from "@ant-design/icons/lib";
+import { Col, Row, Spin, Table, Tabs } from 'antd';
+import { IEntityMedia } from 'lemans-api/models/Media/media.types';
+import { SortableTable, useRowSelection } from 'lemans-common';
+import { GenericActionBar } from 'lemans-common/components/GenericActionBar';
+import { IGenericActionBarOption } from "lemans-common/components/GenericActionBar/GenericActionBar.types";
+import { useLoader, useTrigger } from 'lemans-common/libs/useToggle';
+import { api, service } from 'lemans-dashboard-common';
+import React, { Key } from 'react';
+import { brandMediaOptions, partMediaOptions, productMediaOptions } from "../MediaSearch/MediaSearch.helpers";
+import { MediaClassificationColumn, MediaDescriptionColumn, MediaEffectiveDateColumn, MediaEntityTagsColumn, MediaFileNameColumn, MediaFileTypeColumn, MediaImageColumn, MediaRemoveDateColumn, MediaAddedDateColumn } from "./EntityMediaList.columns";
+import './EntityMediaList.styles.less';
+import { EntityMediaListProps } from './EntityMediaList.types';
+
+export const EntityMediaListComponent = (props:EntityMediaListProps) => {
+ const [media, setMedia] = React.useState([]);
+ const loading = useLoader();
+ const [selectedMedia, setSelectedMedia, rowSelection] = useRowSelection();
+
+ const [primaryMediaId, setPrimaryMediaId] = React.useState(1234);
+
+ const [refreshTrigger, refresh] = useTrigger();
+
+ React.useEffect(() => {
+ loading.start();
+
+ const loadEntity:any =
+ props.entity === "part" ? service.part.get :
+ props.entity === "product" ? service.product.get :
+ service.brand.get;
+ loadEntity(props.entityId as never).then((e:any) => setPrimaryMediaId(e.primaryMediaId));
+
+ setSelectedMedia([]);
+
+ service.media.entity.search(props.entity, props.entityId, {...props.filters, sorting: "sequence ASC", pageSize: 1000})
+ .then(setMedia)
+ .catch(api.handleError)
+ .finally(loading.done);
+ }, [props.entity, props.entityId, props.filters, refreshTrigger]);
+
+ const options:IGenericActionBarOption[] = {
+ part: partMediaOptions,
+ product: productMediaOptions,
+ brand: brandMediaOptions,
+ }[props.entity] as IGenericActionBarOption[];
+
+ const onActionComplete = () => {
+ refresh();
+ setSelectedMedia([]);
+ };
+
+ const sortEntities = (src: IEntityMedia, dst: IEntityMedia, position: "BEFORE" | "AFTER") => {
+ loading.start();
+
+ // Update local state before calling backend
+ const newMedia = [...media];
+ const oldIndex = newMedia.findIndex(item => item.mediaId === src.mediaId);
+ const newIndex = newMedia.findIndex(item => item.mediaId === dst.mediaId);
+
+ if (oldIndex === -1 || newIndex === -1) return;
+
+ // Move the item locally
+ const [movedItem] = newMedia.splice(oldIndex, 1);
+ newMedia.splice(position === "BEFORE" ? newIndex : newIndex + 1, 0, movedItem);
+
+ setMedia(newMedia);
+
+ // Call backend to persist sorting
+ service.media.entity.move(props.entity, props.entityId, src.mediaId, dst.mediaId, position)
+ .catch(api.handleError) // Handle API failure gracefully
+ .finally(loading.done);
+ };
+
+ const showTotal = (total: number, range: [number, number]) => `${range[0]} - ${range[1]} of ${total}`;
+
+ return
+
+
+
+ }
+ >
+ List} key="list">
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ;
+}