Skip to content
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 15 additions & 11 deletions shesha-reactjs/src/components/storedFilesRendererBase/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import { ButtonGroupItemProps } from '@/providers/buttonGroupConfigurator/models
import { ButtonGroup } from '@/designer-components/button/buttonGroup/buttonGroup';
import { FormIdentifier } from '@/providers/form/models';
import { DataContextProvider } from '@/providers/dataContextProvider';
import { FileVersionsButton, ExtraContent, createPlaceholderFile, getListTypeAndLayout, fetchStoredFile } from './utils';
import { FileVersionsButton, ExtraContent, createPlaceholderFile, getListTypeAndLayout, fetchStoredFile, FileNameDisplay } from './utils';
import classNames from 'classnames';
import { isFileTypeAllowed } from '@/utils/fileValidation';
import ShaIcon, { IconType } from '@/components/shaIcon';
Expand Down Expand Up @@ -443,12 +443,13 @@ export const StoredFilesRendererBase: FC<IStoredFilesRendererBaseProps> = ({
return (
<div className={classNames(isDownloaded && styleDownloadedFiles ? styles.downloadedFile : '', styles.fileNameWrapper)} onClick={handleItemClick}>
<div className={styles.fileName}>
<Popover content={actions} trigger="hover" placement="top" classNames={{ root: styles.actionsPopover }}>
<Space direction="horizontal" size="small">
<span>{iconRender(file)}</span>
<span>{file.name}</span>
</Space>
</Popover>
{iconRender(file)}
<FileNameDisplay
file={file}
className={styles.fileName}
popoverContent={actions}
popoverClassName={styles.actionsPopover}
/>
</div>
{isDownloaded && styleDownloadedFiles && (
<div className={styles.downloadedIcon}>
Expand Down Expand Up @@ -481,9 +482,14 @@ export const StoredFilesRendererBase: FC<IStoredFilesRendererBaseProps> = ({
return (
<div>
{renderContent()}
{listType === 'thumbnail' && (
{listType === 'thumbnail' && !isDragger && (
<div className={isDownloaded ? styles.downloadedFile : ''}>
<div className={styles.fileName}>{file.name}</div>
<FileNameDisplay
file={file}
className={styles.fileName}
popoverContent={actions}
popoverClassName={styles.actionsPopover}
/>
</div>
)}
{hasExtraContent && extraFormId && (
Expand Down Expand Up @@ -560,7 +566,6 @@ export const StoredFilesRendererBase: FC<IStoredFilesRendererBaseProps> = ({
icon={<UploadOutlined />}
disabled={disabled}
{...uploadBtnProps}
onClick={isDragger ? undefined : () => hiddenUploadInputRef.current.click()}
className={classNames(styles.uploadButton, uploadBtnProps?.className)}
>
{isDragger ? "Click or drag file to upload" : listType === 'text' && '(press to upload)'}
Expand Down Expand Up @@ -604,7 +609,6 @@ export const StoredFilesRendererBase: FC<IStoredFilesRendererBaseProps> = ({
/>
)}
</div>

</>
)
)
Expand Down
126 changes: 80 additions & 46 deletions shesha-reactjs/src/components/storedFilesRendererBase/styles/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export const useStyles = createStyles(({ token, css, cx, prefixCls }, { style =
minWidth: containerMinWidth, marginTop, marginLeft, marginRight, marginBottom, paddingTop,
paddingLeft, paddingRight, paddingBottom, ...restContainerStyles } = containerStyles;

const { gap, layout, isDragger, hasFiles } = model;
const { gap, layout, hasFiles } = model;

const storedFilesRendererBtnContainer = "stored-files-renderer-btn-container";
const storedFilesRendererNoFiles = "stored-files-renderer-no-files";
Expand All @@ -40,31 +40,28 @@ export const useStyles = createStyles(({ token, css, cx, prefixCls }, { style =
const colorBgTextHover = '#f0f0f0';

const fileName = cx("item-file-name", css`
display: ${model.hideFileName ? 'none' : 'flex'};
color: ${color ?? token.colorPrimary} !important;
font-size: ${fontSize ?? '14px'} !important;
font-weight: ${fontWeight ?? '400'} !important;
font-family: ${fontFamily ?? 'Segoe UI'} !important;
text-align: ${textAlign ?? 'left'} !important;
justify-content: ${textAlign === 'center' ? 'center' : textAlign === 'right' ? 'flex-end' : 'flex-start'} !important;
margin: 2px 0px;
position: relative;
display: flex;
gap: 8px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
flex: 1;
cursor: pointer;
&:hover {
background-color: ${colorBgTextHover} !important;
opacity: 1 !important;
overflow: visible;
width: max-content;
min-width: 100%;
border-radius: 4px;
padding: 0 8px;
z-index: 999 !important;
white-space: nowrap;
min-width: 0;
.ant-typography {
display: ${model.hideFileName ? 'none' : 'block'};
color: ${color ?? token.colorPrimary} !important;
font-size: ${fontSize ?? '14px'} !important;
font-weight: ${fontWeight ?? '400'} !important;
font-family: ${fontFamily ?? 'Segoe UI'} !important;
text-align: ${textAlign ?? 'left'} !important;
justify-content: ${textAlign === 'center' ? 'center' : textAlign === 'right' ? 'flex-end' : 'flex-start'} !important;
margin: 2px 0px;
position: relative;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
cursor: pointer;
max-width: 100%;
min-width: 0;
}
`);

Expand Down Expand Up @@ -100,12 +97,21 @@ export const useStyles = createStyles(({ token, css, cx, prefixCls }, { style =
}

.item-file-name {
color: ${downloadedFileStyles?.color ?? color} !important;
font-size: ${downloadedFileStyles?.fontSize ?? fontSize} !important;
font-weight: ${downloadedFileStyles?.fontWeight ?? fontWeight} !important;
font-family: ${downloadedFileStyles?.fontFamily ?? fontFamily} !important;
text-align: ${downloadedFileStyles?.textAlign ?? textAlign} !important;
${downloadedFileStyles?.textAlign === 'center' ? 'justify-content: center' : downloadedFileStyles?.textAlign === 'right' ? 'justify-content: flex-end' : 'justify-content: flex-start'} !important;
.ant-typography {
display: ${model.hideFileName ? 'none' : 'flex'};
color: ${downloadedFileStyles?.color ?? color} !important;
font-size: ${downloadedFileStyles?.fontSize ?? fontSize} !important;
font-weight: ${downloadedFileStyles?.fontWeight ?? fontWeight} !important;
font-family: ${downloadedFileStyles?.fontFamily ?? fontFamily} !important;
text-align: ${downloadedFileStyles?.textAlign ?? textAlign} !important;
${downloadedFileStyles?.textAlign === 'center' ? 'justify-content: center' : downloadedFileStyles?.textAlign === 'right' ? 'justify-content: flex-end' : 'justify-content: flex-start'} !important;
margin: 2px 0px;
position: relative;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
cursor: pointer;
}
}

.ant-upload-list-item-action {
Expand Down Expand Up @@ -189,10 +195,6 @@ export const useStyles = createStyles(({ token, css, cx, prefixCls }, { style =
color: ${token.colorPrimary} !important;
};
}

.ant-upload-drag {
${hasFiles ? 'border: unset' : ''}
}

.ant-upload-list-item {
display: flex;
Expand Down Expand Up @@ -245,26 +247,42 @@ export const useStyles = createStyles(({ token, css, cx, prefixCls }, { style =
}

.ant-upload-list-text {
> .downloaded-icon {
position: relative;
top: unset;
right: unset;
}
overflow: hidden;
${!hasFiles ? 'display: none;' : ''}
>.ant-upload-list-item-container {
> div {
>.file-name-wrapper {
>.item-file-name {
width: 100%;
gap: 8px;
}
}
> .downloaded-icon {
position: relative;
top: unset;
right: unset;
}
}
}
}

.${prefixCls}-upload:not(.ant-upload-drag) {
.${prefixCls}-upload-select {
${rest}
border: unset;
${(layout && !isDragger) && `width: ${thumbnailWidth} !important;`};
${(layout && !isDragger) && `height: ${thumbnailHeight} !important;`};

width: ${layout ? thumbnailWidth : '100%'} !important;
height: ${layout ? thumbnailHeight : '100%'} !important;
align-items: center;

.ant-upload {
width: ${layout ? thumbnailWidth : '100%'} !important;
height: ${layout ? thumbnailHeight : '100%'} !important;
}

&.${prefixCls}-upload-btn {
padding: unset;

.${prefixCls}-upload-drag-icon {
margin: unset;
margin: unset !important;
}

.${storedFilesRendererNoFiles} {
Expand All @@ -273,14 +291,30 @@ export const useStyles = createStyles(({ token, css, cx, prefixCls }, { style =

.ant-upload-select {
align-content: center;
width: ${thumbnailWidth} !important;
}
}
}

.${prefixCls}-upload-drag {
${hasFiles ? 'border: unset !important;' : ''}
.${prefixCls}-upload-btn {
padding: unset !important;
width: 100% !important;

.ant-upload-drag-icon {
margin: 0 !important;
}
}

.item-file-name {
width: max-content !important;
.ant-typography {
width: max-content !important;
}
}
}

.ant-btn {
color: ${token.colorPrimary} !important;
padding: 0;
* {
font-size: ${fontSize ?? '14px'} !important;
font-weight: ${fontWeight ?? '400'} !important;
Expand All @@ -291,7 +325,7 @@ export const useStyles = createStyles(({ token, css, cx, prefixCls }, { style =
display: flex;
margin-top: 4px;
justify-content: flex-end;
width: ${containerWidth};
width: 100%;
max-width: ${containerMaxWidth};
min-width: ${containerMinWidth};
}
Expand Down
47 changes: 46 additions & 1 deletion shesha-reactjs/src/components/storedFilesRendererBase/utils.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { FC } from 'react';
import { Button, Popover, Skeleton } from 'antd';
import { Button, Popover, Skeleton, Typography, UploadFile } from 'antd';
import { HistoryOutlined } from '@ant-design/icons';
import filesize from 'filesize';
import { ConfigurableForm, DateDisplay } from '@/components';
Expand Down Expand Up @@ -169,3 +169,48 @@ export const ExtraContent: FC<IExtraContentProps> = ({ file, formId }) => {

return <ConfigurableForm formId={formId} mode="readonly" initialValues={file} />;
};


const { Text } = Typography;

// Helper function to format file size
const formatFileSize = (bytes?: number): string => {
if (bytes === undefined) return '';
if (bytes < 1024) return `${bytes} B`;
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(2)} KB`;
if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)} GB`;
};

// Helper component to render file name with ellipsis and title
export const FileNameDisplay: FC<{
file: UploadFile;
className?: string;
popoverContent?: React.ReactNode;
popoverClassName?: string;
}> = ({ file, className, popoverContent, popoverClassName }) => {
const sizeStr = formatFileSize(file.size);
const title = sizeStr ? `${file.name} (${sizeStr})` : file.name;

const textElement = (
<Text
ellipsis
title={title}
style={{ display: 'block' }}
>
{file.name}
</Text>
);

return (
<div className={className} style={{ overflow: 'hidden', flex: 1 }}>
{popoverContent ? (
<Popover content={popoverContent} trigger="hover" placement="top" classNames={{ root: popoverClassName }}>
{textElement}
</Popover>
) : (
textElement
)}
</div>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export const useStyles = createStyles(({ css, cx }) => {

`);
const codeEditorContainer = cx("sha-code-editor-container", css`
height: 100%;
display: flex;
flex-direction: column;
`);
Expand Down