1+ /* eslint-disable require-jsdoc */
12import {
23 Avatar ,
4+ createStyles ,
35 Icon ,
46 IconButton ,
57 ListItem ,
68 ListItemAvatar ,
79 ListItemIcon ,
810 ListItemSecondaryAction ,
911 ListItemText ,
12+ makeStyles ,
1013} from '@material-ui/core'
1114import { InsertDriveFile } from '@material-ui/icons'
1215import { Repository } from '@sensenet/client-core'
@@ -15,6 +18,42 @@ import { GenericContent, Image, User } from '@sensenet/default-content-types'
1518import React from 'react'
1619import { renderIconDefault } from '../icon'
1720
21+ export type PathConfig = {
22+ appPath : string
23+ snPath ?: string
24+ }
25+
26+ export type Paths = Record < string , PathConfig >
27+
28+ function getAppPathAndContent ( PATHS : Paths , targetPath : string ) {
29+ const matches = Object . entries ( PATHS )
30+ . filter ( ( [ , config ] ) => config . snPath && targetPath . startsWith ( config . snPath ) )
31+ . sort ( ( a , b ) => b [ 1 ] . snPath ! . length - a [ 1 ] . snPath ! . length )
32+
33+ if ( ! matches [ 0 ] ) return undefined
34+
35+ const [ , config ] = matches [ 0 ]
36+ const contentePath = targetPath . substring ( config . snPath ! . length )
37+
38+ return {
39+ appPath : config . appPath ,
40+ contentePath,
41+ }
42+ }
43+
44+ function buildCustomPath ( path : string , action : string | undefined , contentePath : string ) {
45+ const customPath = path
46+ . replace ( ':browseType' , 'explorer' )
47+ . replace ( '/:path' , '' ) // Remove the path parameter
48+ . replace ( ':action?' , action || 'default' )
49+
50+ const url = new URL ( window . location . origin )
51+ url . pathname = customPath
52+ url . searchParams . set ( 'content' , contentePath )
53+
54+ return url . toString ( )
55+ }
56+
1857interface DefaultItemTemplateProps {
1958 content : GenericContent
2059 remove ?: ( id : number ) => void
@@ -24,13 +63,29 @@ interface DefaultItemTemplateProps {
2463 repository ?: Repository
2564 multiple : boolean
2665 renderIcon ?: ( name : string ) => JSX . Element
66+ paths : Paths
2767}
2868
69+ const useStyles = makeStyles ( ( ) =>
70+ createStyles ( {
71+ referenceItemText : {
72+ textAlign : 'left' ,
73+ paddingRight : 15 ,
74+ cursor : 'pointer' ,
75+ '&[data-clickable="true"]:hover' : {
76+ textDecoration : 'underline' ,
77+ } ,
78+ } ,
79+ } ) ,
80+ )
81+
2982/**
3083 * Represents a default renderer for reference grid row
3184 */
3285export const DefaultItemTemplate : React . FC < DefaultItemTemplateProps > = ( props ) => {
33- const { content, repository } = props
86+ const { content, repository, paths } = props
87+
88+ const classes = useStyles ( )
3489
3590 const renderIcon = ( item : GenericContent | User | Image ) => {
3691 if ( repository ?. schemas . isContentFromType < User > ( item , 'User' ) ) {
@@ -107,7 +162,26 @@ export const DefaultItemTemplate: React.FC<DefaultItemTemplateProps> = (props) =
107162 return (
108163 < ListItem style = { props . actionName === 'browse' ? { padding : 0 } : undefined } key = { content . Id } button = { false } >
109164 { content . Type ? renderIcon ( content ) : null }
110- < ListItemText primary = { content . DisplayName } style = { { textAlign : 'left' , paddingRight : 15 } } />
165+ < ListItemText
166+ onClick = { ( ) => {
167+ if ( content . Id === - 1 || ! paths ) {
168+ return
169+ }
170+ const referencedItemPaths = getAppPathAndContent ( paths , content . Path )
171+
172+ if ( ! referencedItemPaths ) {
173+ return
174+ }
175+
176+ const { appPath, contentePath } = referencedItemPaths
177+
178+ const fullUrl = buildCustomPath ( appPath , props . actionName , contentePath )
179+ window . location . href = fullUrl
180+ } }
181+ primary = { content . DisplayName }
182+ className = { classes . referenceItemText }
183+ data-clickable = { content . Id !== - 1 }
184+ />
111185 { props . actionName && props . actionName !== 'browse' && ! props . readOnly ? (
112186 < ListItemSecondaryAction >
113187 { content . Id > 0 ? (
0 commit comments