Open lkostrowski opened 1 year ago
Entire process make sense to me. Very nice idea with discriminating union (type guard by type field) 👍 .
ResourceMeta - so do we want to keep just the ids of resources? If so can we name it accordingly eg. variantId
instead of variants
- small thing but self-explanatory
Options - I think we can combine options and resource type together and based on the resource type prepare specific options. Here we can also benefit from type guards.
type CustomerResource = {
type: "customer",
options: SomeCustomerRelatedOptions
}
type ProductResource = {
type: "product",
options: SomeProductRelatedOptions
}
type Resource =
| CustomerResource
| ProductResource
actions.sendResources({
resource: Resource,
id: string
})
Pre-filtering - I think some of them shouldn't be even overridable, or perhaps dashbaord can check permissions and allow it or not (depending on the resource type and its scope)
I also like the idea of Resource Picker - I'm curious if MacawUI components can help reduce the boilerplate needed to serve all use cases e.g loading, error states, etc., or if it should be AppBridge who is responsible for providing such components?
@krzysztofzuraw AppBridge is a communication bus only and the scope of the RFC is the contract only.
In terms of the UI there are a few assumptions
The subject of further discussion is what "business" components to developer and in what package
Additional request based on my apps: Attribute picker. It's used by search and product feed to choose which Saleor Attributes should be submitted to the external APIs.
Context
Browsing resources in Dashboard is critical for great UX/DX. Users can have very rich data and a huge volume of various products, orders, customers, etc.
To make this experience great, Dashboard grows with advanced data grids with rich filtering, sorting, and configuration.
However, Apps don't share a Dashboard codebase. Each app, despite access to the same Saleor resources and Macaw UI, will have to implement resource lists on its own. Considering scope of app app its not possible to provider such a good UX as the Dashboard.
To avoid solutions based on shared code or code duplication, app can establish an interface with Dashboard and ask Dashboard to provide required UI. This is the scope of this RFC
UI context
Simple drafts:
App that provides control to open a Resource Picker (in this case - customers)
Dashboard opens dedicated resource picker outside of the iframe
Proposed solution
The unit responsible of structured postMessage communication between the Dashboard frontend and the App frontend is AppBridge
AppBridge provides a
dispatch()
method, and there are strictly typed factories for every event type.This solution extends the existing interface and adds more actions and responses.
API
postMessage doesn't provide a "response" concept. If the dashboard successfully handles the message, it sends another
postMessage
with the same ID (that is provided by the app or random), so the App can handle failures.This requires bi-directional communication.
Request interface
The request will be initialized from the app.
Under the hood,
requestResources
is translated to includetype: "resources-request"
id
can be set to exclusively match requests with a responseResourceType
The
ResourceType
is the literal representing every supported resource, for example:export type ResourceType = "customers" | "orders" | "products" | "categories" | "collections" | "giftcards" | "vouchers"
etc.Each resource can be implemented iteratively.
Options
Options can contain an additional payload that the dashboard can use to pre-configure the resource picker. The simple and accurate use case is to provide initial filters, sort, and search fields that the app assumes should be picked.
Question/to discuss: should the app be able to "lock" the filter, or should the user be able to remove the pre-selected filter and pick any resource?
Use case: app wants to work on fulfilled orders only. It will set the initial filter to
status: fulfilled
. Users can override it, but the app will filter them anyway.API for Options TBD, based on Dashboard team input on how data grid is configurable.
Request handling
The dashboard will implement a resource picker on some kind of full-screen (or almost full-screen) overlay/modal. The app can't be unmounted.
Security
The dashboard must validate (on the frontend) if the user has permission to display the resource. The dashboard should return an error response (success: false + message)
Response interface
Dashboard will respond with a
postMessage
and event will be constructed via factory from the app-sdkresourceType
is the original resource that was requestedid
is the ID that was created in the Appresources
contains a result - items picked by the user represented by ResourceMetaResourceMeta
It's hard to implement the simple interface to provide all required fields that the app needs. It's where graphQL is powerful, but implementing this in a simple postMessage interface will be hard, especially considering limited access due to permissions
Hence, in the first scope, I suggest only providing very basic data. If an app requires it, it has to fetch it from the API. In the future we can extend it with some dynamic schema building so App can request what it needs
Very simple and initial
ResourceMeta
can be represented like this:type
field is helpful, because it allows App codebase to implement type guards, without accessing parent object:For example, further implementations can look more advanced:
Thanks to the
type
App can easily write such logic: