Publicly shared Gallery View
Feature description
You can already share the GridView
publicly but now we also want to be able to share the GalleryView
publicly.
The public sharing of the GalleryView
should respect the same constrains as the GridView
:
- Filters should be applied to the view
- Sorts should be applied to the view
- Hidden fields should stay hidden
- All changes to the public view should be local to the person viewing
One of the bigger challenges of this task will be to understand what we can re-use from the GridView
implementation and make it accessible for both use cases.
Technical plan (work in progress)
Additional functionality
- Implement
get_visible_field_options_in_order
andget_hidden_field_options
forGalleryViewType
- This is required for public views (it will throw if not implemented)
- This is used by the realtime updates for example to apply additional filters to the
queryset
- Enable
can_share
on the view type in both front and backend- This essentially tells Baserow that this view can be publicly shared
- It also automatically adds the
Share View
button to theGalleryView
- Set
getPublicRoute
onGalleryViewType
in the frontend- This property defines which component to route to when the public view is called
Refactoring
Primary field separation
At the moment we separate the primary
field from the more general fields
in the Table
component and all its sub-components.
The concept of the primary
field having a special status only applies for the GridView
and should therefore also only be implemented in the GridView
and not across all Table
instances.
In order to full understand if we can eliminate primary
from Table
I create a drawing which illustrates how primary
is passed around from Table
and which of these components and functions actually need primary
to work properly.
Legend
-
Green: Does not need
primary
-
Yellow: Uses
primary
for convenience -
Red: Uses
primary
for functionality - Light Blue: Starting point
- Dark Blue: Referenced but not existing functions
Looking at the drawing we can establish a few thing:
- Creating and editing new rows in the kanban and gallery view depends on
primary
- The header value is determined by the
primary
field value, which makes sense to me - We would need to get rid of that feature or implement a fallback if
primary
doesn't exist - A possible solution would be to just always chose the first field, but then the header loses its meaning imo
- The header value is determined by the
- The
Table
does depend onprimary
for setting sensible default values- This could be changed by again just using the first field as a default value
- I wouldn't be super happy with that change since I like using a "special" value as the default and not just a random one
- The
Table
is also part of the public view so if we want to keep this feature we can't allow exclusion of theprimary
field
- This could be changed by again just using the first field as a default value
-
gallery/updatedExistingRow
doesn't seem to exist somehow, unrelated to what we are trying to do, just an interesting find -
getRowSortFunction
could be annoying- We could check if it can handle
null
asprimary
properly already - If it doesn't we can rewrite the function to handle it
- The code suggests it might be able to handle it
- We could check if it can handle
-
FieldLookupSubForm
needsprimary
- Since row colouring is not part of the public view this is not a concern to us for this ticket but it is a general concern
Solutions
Based on the above I see a few solutions to make this work for the Public Gallery View
1. Don't allow removing primary
field on gallery view
While the Gallery View itself might not depend on primary
, Table
does. This is not an issue when dealing with the view in non-public mode since primary
might be hidden but is still accessible, while in public mode if the field is hidden, it is not accessible and therefore breaks Table
functionality.
This is the easiest solution but it would mean that we would restrict the user that they can't hide primary fields.
A slightly more complicated version would be, where we allow users to hide primary fields while they are in non-public mode but we don't allow them to hide it in public mode. This would require some UX and might be upsetting for the user but it is an option, just wanted to mention it.
2. Remove primary
everywhere we can
We could just go ahead and remove primary from every node in the chart that is green and there are alternatives for the nodes that are yellow.
This would require a major refactor and is the most expansive solution.
There are some minor risks in case we have missed some dependency that was crucial along the way.
This solution would also remove the best practise of having a meaningful default value for our Table
menus which I am not too happy about.
In the case that we would ever create a dependency in the future to primary
in any of these views the refactor will have done more damage than helped.
3. Remove primary
where possible and still do (1.)
We could go with solution (1.) but still proceed to purge primary from every green node.
This would have the drawbacks of solution (1.) but might lead us to some cleaner code.
Conclusion
Personally I think this is a question of if we are willing to restrict the user to not be able to hide primary
on Gallery Views. If we are willing, then I think (1.) or (3.) are the best solutions. If we are not willing to make that restriction then we will have to go with (2.).
Reuse existing public Grid View code
PublicViewInfoEndpoint (Breaking Change)
The PublicGridViewInfoView
and PublicGalleryViewInfoView
are identical at the moment.
We should create a new endpoint in /views/views.py
that is generic for all views
.
We already have moved several generic endpoints in regards to public views to that file, such as PublicViewAuthView
and PublicViewLinkRowFieldLookupView
PublicGalleryViewRowsView (Breaking Change)
Both of the endpoints are almost the same. The only difference being that they use different paginators. The PublicGalleryViewRowsView
uses GalleryLimitOffsetPagination
and PublicGridViewRowsView
uses LimitOffsetPagination
or PageNumberPagination
.
We should create a new Base Class which the Views can extend from.
That base class should implement the shared functionality and leave the paginator configurable via a class porperty that can be set by the sub classes implementing the base class.
Store
At the moment, both the Grid
store and the Gallery
store deal with their own public
state.
We should create a new mixin Public
which deals with the public state. This mixin can then be injected into both the Gallery
and Grid
store.
Specifically I am talking about this action
and all mutations
/state
related to it:
setPublic({ commit }, { isPublic, publicAuthToken }) {
commit('setIsPublic', isPublic)
commit('setPublicAuthToken', publicAuthToken)
},
Public View
At the moment we have 2 separate public views, one for the gallery view and another for the grid view.
Both of these views run essentially the same code with very minor differences.
These differences are:
-
GridService
andGalleryService
are used to executefetchPublicViewInfo
- We can pass a prop
service
which can be used to fetch the required data
- We can pass a prop
-
/gallery/
and/grid/
are used to refer to the store which executessetPublic
- This issue will be resolved once
setPublic
has become part of theView
store
- This issue will be resolved once
After these differences are resolved we can just have one generic component which renders the Table
.
Considerations
We might want to also consider future views that become public when making this change. I think the change will be future proof since we are making everything generic up to the View
level in terms of setting something as public and something similar has already happened with Table
, so, I am not concerend.