-
Notifications
You must be signed in to change notification settings - Fork 1
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
PoC - FDS folder support #4771
base: master
Are you sure you want to change the base?
PoC - FDS folder support #4771
Conversation
: apiURL; | ||
|
||
const newApiURL = new URL(fullUrl); | ||
newApiURL.searchParams.set('entryClassNames', item.entryClassName); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updating only the entryClassName
but can be anything, in the same way we are doing in loadData helper
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep, this function could even be a callback delegated to the FDS caller. FDS should not assume much about how data is structured.
For a PoC this is more than fine though.
In terms of the type of change for apiURL
, it's very likely we'll need to modify the filter
odata expression. This is an spetialization of the more general function that does an arbitrary modification on the URL, which allows us to make some assumptions:
- Data about folders is consistently encoded in item field(s). Ideally, but not strictly needed:
- in one single field,
- always the same field. This simplifies computation of the relevant
odata
expression
- Backend is able to consistently filter out data by such field(s), meaning
- when such field is used to filter, backend will return elements that are immediate children of the provided "folder"
- The above happens regardless the type of elements involved, and is compatible with the rest of parameters in the REST request (such as pagination, sort or other odata expressions connected with
and
operator)
- Endpoint to read data won't change during component usage because only
odata
is allowed to change when browsing folders. This is in line with how filters and other parameterization work now. - Relevant
odata
expression can be provided on FDS invocation as part ofadditionalAPIURLParameters
. This is a known requirement - We can consider other ways to "delegate" this function to the caller, yet control the way
apiURL
is mutated. For instance- Caller might just return an
odata
string that FDS appends viaand
operator - Caller could give the parameter that has to be added to the expression, very much like a filter, then FDS would handle the rest
- Caller might just return an
I provide above items just for thought and discussion. We don't need to shape final solution yet, but instead we can prepare FDS to support this feature under such assumptions, fine tuning what we finally surface into component API later on.
@@ -85,6 +86,12 @@ export const INTERNAL_CELL_RENDERERS: Array<IInternalRenderer> = [ | |||
name: 'link', | |||
type: 'internal', | |||
}, | |||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Define renderer as internal for convenience. It could be a customCellRenderer in the CMS project
options: any; | ||
value: string; | ||
}) => { | ||
const isFolder = itemData?.entryClassName.includes('Folder'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤷
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is another key aspect of the proposal. I see 3 points of discussion here
First, the isFolder
implementation. Similarly to the apiURL
mutation function, knowlege to distinguish between a container and a "leaf" item can be delegated to the caller. Of course, for PoC purposes we can provide a default implementation of this function. I don't see a clear way to implement a sensible default, perhaps what you propose is a great best effort way. Still I see the need to open component API to allow alternate implementations to be provided from the outside.
Second, make all this opt in. We need to preserve existing behavior, therefore, enabling container browsing is something that has to be explicitly configured. We need to determine the right way to do this from the perspective of the FDS react component, then translate that to custom//system data sets. We can deal with this later on.
Last, and more important, whether we need a dedicated renderer or not. Using a renderer means allowing folder navigation only in tables, which is fine for now but can be perceived as a bug shortly after we release this.
Opposed to FDS providing isFolder
and openFolder
functions (let's not consider how configurable can they be) is a clear need, I don't see NavigationLinkRenderer
as a must here. Instead, such functions are just helpers for the view to do its job, being a view's responsibility to handle navigation appropriately. This is clearly seen in case we want to provide a custom view renderer.
This does not remove the obligation of FDS to provide folder support for its ootb views, but allows to do it in specific ways.
- For the case of tables, we can still have this renderer (
isFolder
shall be hoisted to the top level though). But we might instead enhanceActionLinkRenderer
to implement the navigation, and/or wrap the rest of ootb renderers with anonclick
function to trigger it. Specific behavior will depend on product management, but also, we need to consider the fact that CMS may want to add their own custom cell renderer - Cards can provide an href/onclick handler that would implement navigation
- Similar for List view, by adding some click handler on the title
onClick={(event) => { | ||
event.preventDefault(); | ||
|
||
openFolder({item: itemData}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can use the same renderer to navigate to a content (document, media, ...) using navigate
utility once they provide an URI for it.
return ( | ||
<div | ||
className="col-md-3" | ||
key={ | ||
key={index} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not related. Just removing ugly console warnings.
@@ -566,7 +567,10 @@ const FrontendDataSet = ({ | |||
} | |||
setDataLoading(false); | |||
} | |||
Liferay.on(EVENTS.OPEN_FOLDER, openFolder); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Open an ear just in case we need to listen for external change requests (breadcrumb)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How event emitter knows which item
shall be provided to openFolder()
function?
Also, we shall emit this event from openFolder()
function so that external parties can know (e.g. update the breadcrumb). A consequence of this is that we must ignore events emitted by ourselves, or emit a different one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, I would expect a dumb Breadcrumb component that only displays stuff and provides a callback.
({ active, href, label, onClick, ...otherProps }: IItem)
Whoever configures the breadcrumb (CMS Team) should know which ...otherProps
will need when they click on an item so they can update breadcrumbs back and fire the event to FDS with the correct data (folderId
x.e.)
@@ -667,6 +668,7 @@ function CellRenderer({ | |||
itemId={itemId} | |||
loadData={loadData} | |||
onItemsChange={onItemsChange} | |||
openFolder={openFolder} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couple of nits here:
- This function shall be available throughout all visualization modes, probably we can expose it in the context
- Naming might be a bit more general, folders is just a particular form of containers. I'm thinking about browsing organizations and users, portal instances and sites, or any other containment relationship we might want to support
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
openFolder
is already available through context, just wanted to keep renderer lean 😃
About naming, we could change to a more generic openContainer
or simply browse
.
options: any; | ||
value: string; | ||
}) => { | ||
const isFolder = itemData?.entryClassName.includes('Folder'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is another key aspect of the proposal. I see 3 points of discussion here
First, the isFolder
implementation. Similarly to the apiURL
mutation function, knowlege to distinguish between a container and a "leaf" item can be delegated to the caller. Of course, for PoC purposes we can provide a default implementation of this function. I don't see a clear way to implement a sensible default, perhaps what you propose is a great best effort way. Still I see the need to open component API to allow alternate implementations to be provided from the outside.
Second, make all this opt in. We need to preserve existing behavior, therefore, enabling container browsing is something that has to be explicitly configured. We need to determine the right way to do this from the perspective of the FDS react component, then translate that to custom//system data sets. We can deal with this later on.
Last, and more important, whether we need a dedicated renderer or not. Using a renderer means allowing folder navigation only in tables, which is fine for now but can be perceived as a bug shortly after we release this.
Opposed to FDS providing isFolder
and openFolder
functions (let's not consider how configurable can they be) is a clear need, I don't see NavigationLinkRenderer
as a must here. Instead, such functions are just helpers for the view to do its job, being a view's responsibility to handle navigation appropriately. This is clearly seen in case we want to provide a custom view renderer.
This does not remove the obligation of FDS to provide folder support for its ootb views, but allows to do it in specific ways.
- For the case of tables, we can still have this renderer (
isFolder
shall be hoisted to the top level though). But we might instead enhanceActionLinkRenderer
to implement the navigation, and/or wrap the rest of ootb renderers with anonclick
function to trigger it. Specific behavior will depend on product management, but also, we need to consider the fact that CMS may want to add their own custom cell renderer - Cards can provide an href/onclick handler that would implement navigation
- Similar for List view, by adding some click handler on the title
<span className="c-pr-2"> | ||
<ClayIcon symbol="folder" /> | ||
</span> | ||
)} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This bit signals an interesting requirement: we need to alter the way things are rendered when they are folders.
For table views we have more chances thanks to the renderers. For cards/lists, I don't have anything specific in mind.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cards & List have the symbol
property mapped to the schema.
ClayCardWithHorizontal icon defaults to "folder", but there is no design combining cards with folders and documents.
6d66046
to
2a3ffad
Compare
@dsanz @markocikos Added a last bonus commit with a first attempt to move |
Scope
In this PoC we want to test how to implement a way to navigate within folders inside a FDS, showing its contents. To achieve this, we may want to update the
apiURL
prop that it is used to retrieve the data for a given FDS.Also, we need to identify which content is a folder
Concerns
entryClassName
of an item to check if it contains*Folder
. While this is valid for some Liferay content (Web Content :com.liferay.journal.model.JournalFolder
, KnowledgeBase:com.liferay.knowledge.base.model.KBFolder
) it does not work with Objects out of the box.apiURL
and retrieve new data, but we cannot ensure that the actual table schema matches the upcoming data.UI
folder.mp4