Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Display the image in case of Reference fields on admin UI #1525

Merged
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import {
} from '@material-ui/core'
import { InsertDriveFile } from '@material-ui/icons'
import { Repository } from '@sensenet/client-core'
import { GenericContent, User } from '@sensenet/default-content-types'
import { PathHelper } from '@sensenet/client-utils'
import { GenericContent, Image, User } from '@sensenet/default-content-types'
import React from 'react'
import { renderIconDefault } from '../icon'

Expand All @@ -30,30 +31,82 @@ interface DefaultItemTemplateProps {
*/
export const DefaultItemTemplate: React.FC<DefaultItemTemplateProps> = (props) => {
const { content, repository } = props
return (
<ListItem key={content.Id} button={false}>
{content.Type ? (
repository?.schemas.isContentFromType<User>(content, 'User') ? (

const renderIcon = (item: GenericContent | User | Image) => {
if (repository?.schemas.isContentFromType<User>(item, 'User')) {
const avatarUrl = item.Avatar?.Url
if (avatarUrl) {
return (
<ListItemAvatar>
{
<Avatar
alt={content.FullName}
alt={item.FullName}
src={
content.Avatar?.Url && repository?.configuration.repositoryUrl
? `${repository.configuration.repositoryUrl}${content.Avatar.Url}`
avatarUrl && repository?.configuration.repositoryUrl
? `${repository.configuration.repositoryUrl}${avatarUrl}`
: ''
}
/>
}
</ListItemAvatar>
) : (
<ListItemIcon style={{ marginRight: 0 }}>
<Icon>
<InsertDriveFile />
</Icon>
</ListItemIcon>
)
) : null}
}

return (
<ListItemAvatar>
<Avatar alt={item.DisplayName}>
{item.DisplayName?.split(' ')
.map((namePart) => namePart[0])
.join('.')}
</Avatar>
</ListItemAvatar>
)
}

if (repository?.schemas.isContentFromType<Image>(item, 'Image') && (!item.PageCount || item.PageCount <= 0)) {
return (
<ListItemIcon>
<img
data-test="reference-selection-image"
alt={item.DisplayName}
src={`${repository?.configuration.repositoryUrl}${item.Path}`}
style={{ width: '3em', height: '3em', objectFit: 'scale-down' }}
/>
</ListItemIcon>
)
}

if (repository?.schemas.isContentFromType<Image>(item, 'Image') && item.PageCount && item.PageCount > 0) {
return (
<ListItemIcon>
<img
data-test="reference-selection-image"
alt={item.DisplayName}
src={PathHelper.joinPaths(
repository?.configuration.repositoryUrl,
item.Path,
'/Previews',
item.Version as string,
'thumbnail1.png',
)}
style={{ width: '3em', height: '3em', objectFit: 'scale-down' }}
/>
</ListItemIcon>
)
}

return (
<ListItemIcon style={{ marginRight: 0 }}>
<Icon>
<InsertDriveFile />
</Icon>
</ListItemIcon>
)
}

return (
<ListItem key={content.Id} button={false}>
{content.Type ? renderIcon(content) : null}
<ListItemText
primary={content.DisplayName}
style={content.Id < 0 ? { textAlign: 'right', paddingRight: 16 } : { textAlign: 'left' }}
Expand Down
4 changes: 4 additions & 0 deletions packages/sn-controls-react/test/__mocks__/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,7 @@ export const testArticle = {
export const testFolder = {
Type: 'Folder',
} as GenericContent

export const testImage = {
Type: 'Image',
} as GenericContent
136 changes: 134 additions & 2 deletions packages/sn-controls-react/test/reference-grid.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { ReferencePicker } from '../src/fieldcontrols/reference-grid/reference-p

const defaultSettings = {
Type: 'ReferenceFieldSetting',
AllowedTypes: ['User', 'Group'],
AllowedTypes: ['User', 'Group', 'Image'],
SelectionRoots: ['/Root/IMS', '/Root'],
Name: 'Members',
FieldClassName: 'SenseNet.ContentRepository.Fields.ReferenceField',
Expand All @@ -43,6 +43,27 @@ const userContent = {
},
}

const imageContent = {
Name: 'Test Image',
Path: '/Root/Content/Images/Picture.jpg',
DisplayName: 'Test Image',
Id: 4830,
Type: 'Image',
Enabled: true,
PageCount: 0,
}

const GenericContent = {
Name: 'Test Generic',
Path: '/Root/Content/SampleWorkspace/Memos/TestMemo',
DisplayName: 'Test Memo',
Id: 4830,
Type: 'GenericContent',
}

type ImageContentType = typeof imageContent
type PreviewImageContentType = ImageContentType & { Version: string }

const repository: any = {
load: jest.fn((props) => {
return { d: userContent }
Expand Down Expand Up @@ -95,7 +116,7 @@ describe('Reference grid field control', () => {
})

expect((wrapper!.update().find(Picker).prop('itemsODataOptions') as ODataParams<Folder>).filter).toBe(
"isOf('Folder') or isOf('User') or isOf('Group')",
"isOf('Folder') or isOf('User') or isOf('Group') or isOf('Image')",
)
})

Expand All @@ -113,6 +134,117 @@ describe('Reference grid field control', () => {
"isOf('GenericContent')",
)
})

it('DefaultItemTemplate should render file icon on GenericContent', async () => {
const repo = {
loadCollection: jest.fn(() => {
return { d: { results: [GenericContent] } }
}),
schemas: {
isContentFromType: jest.fn(() => false),
},
load: jest.fn((props) => {
return { d: GenericContent }
}),
} as any

let wrapper: any

await act(async () => {
wrapper = mount(
<ReferenceGrid actionName="browse" settings={defaultSettings} content={GenericContent} repository={repo} />,
)
})

/*find by data-test attribe an icon */
expect(wrapper.update().find('[data-test="file-icon"]')).toBeDefined()
})

it('should render the monogram of Displayname when no Avatar.Url is provided in DefaultItemTemplate', async () => {
const avatarLessUserContent = { ...userContent, Avatar: { Url: '' } }

const repo = {
loadCollection: jest.fn(() => {
return { d: { results: [avatarLessUserContent] } }
}),
schemas: repository.schemas,
load: jest.fn((props) => {
return { d: avatarLessUserContent }
}),
} as any

let wrapper: any

await act(async () => {
wrapper = mount(
<ReferenceGrid
actionName="browse"
settings={defaultSettings}
content={avatarLessUserContent}
repository={repo}
/>,
)
})

expect(wrapper.update().find(Avatar).text()).toBe('A.M')
})

it('should render img tag if type is image and there is no preview generated', async () => {
const repo = {
loadCollection: jest.fn(() => {
return { d: { results: [{ ...imageContent }] } }
}),
schemas: {
isContentFromType: jest.fn((a, b) => b === 'Image'),
},
configuration: repository.configuration,
load: jest.fn((props) => {
return { d: imageContent }
}),
} as any
let wrapper: any
await act(async () => {
wrapper = mount(
<ReferenceGrid actionName="browse" settings={defaultSettings} content={imageContent} repository={repo} />,
)
})

expect(wrapper.update().find('img').prop('src')).toContain(imageContent.Path)
expect(wrapper.update().find('img').prop('alt')).toBe(imageContent.DisplayName)
})

it('should render img tag if type is image when preview has been generated', async () => {
const previewImageContent: PreviewImageContentType = { ...imageContent, Version: '1.0', PageCount: 1 }

const repo = {
loadCollection: jest.fn(() => {
return { d: { results: [{ ...previewImageContent }] } }
}),
schemas: {
isContentFromType: jest.fn((a, b) => b === 'Image'),
},
configuration: repository.configuration,
load: jest.fn((props) => {
return { d: previewImageContent }
}),
} as any

let wrapper: any

await act(async () => {
wrapper = mount(
<ReferenceGrid
actionName="browse"
settings={defaultSettings}
content={previewImageContent}
repository={repo}
/>,
)
})

expect(wrapper.update().find('img').prop('src')).toContain('thumbnail1.png')
expect(wrapper.update().find('img').prop('alt')).toBe(previewImageContent.DisplayName)
})
})
describe('in edit/new view', () => {
it('should throw error when no repository is passed', () => {
Expand Down