dadi / publish Goto Github PK
View Code? Open in Web Editor NEWPublish provides beautiful editorial interfaces for the management of content within API
Home Page: https://dadi.cloud/en/publish
Publish provides beautiful editorial interfaces for the management of content within API
Home Page: https://dadi.cloud/en/publish
Currently we're using the same structure as an API filter. As per discussion with @josephdenne we will change this in post-mvp to:
/{field}/{analyser}/{value}
(repeatable)
e.g.
/first_name/is/foo/last_name/is/bar
@abovebored @eduardoboucas There is no requirement for the media view, outside of document edit. That means no unassigned batch uploads.
This view remains
http://cloud.dadi.technology/XtcB
When there is a missing or incomplete Publish block on a field or in collection settings, fallbacks must populate default menus and field display
New ES6 syntax for default props
static defaultProps = {
type: 'button'
}
Currently login values are static. I was unable to get a form to submit properly. See here.
As per discussions with @eduardoboucas, underscore can be removed from frontend templates
NODE_ENV=production
is not enough. a -p
must also be added. This should be fixedapi-wrapper-core
when compiling production. This can be fixed by removing all ES2015-only syntax such as let
and arrow functions. Perhaps it relates to api-wrapper-core
being included in api-wrapper
and webpack having issues applying ES2015 babel presetsWe need to be able to specifically choose which fields of nested objects care passed through to frontend.
An example with be apis
, where we need to strip the credentials from each returned object in the array.
I believe we already have multi select, so all this needs is
[sudo] publish create component
Which type of component do you want?
1) Component
2) Container
3) View
> 1
What's the name of your component?
> ButtonFoo
Done! Component file and CSS file created in views/ButtonFoo
Moving from the original localdb method, we need a sign in routine that checks API for the user. There is a hook in place already that should handle checking the result of a user/pass post body
Repeat x3
on second repeat, no collections exist on state.api.apis[0]
on third repeat, there is no nav
When errors exist in close proximity to API fetch
requests, we have occasionally seen uncaught looping where a multitude of concurrent requests are being made to API. In development this can crash a tab, but in production it's likely to hamper API performance and potentially exceed allocated memory on Publish instance. We need to capture this with some level of throttling in Publish api-wrapper.
Add throttling to API wrapper in Publish to circumvent inevitable
Filters and other search params are stripped when paginating
Create first-pass user profile view with:
Account tab
Settings
Password reset
This build currently contains a local database. We must remove any of the following that relate to localdb (reasondb)
Notes from previous build:
Can we get menu to close when you make a selection?
Mobile menu should collapse on selection and be closable
Maybe change burger to cross
Error notification when incorrect sign-in credentials submitted has disappeared
To avoid reliance on a local database, all API configurations will be held in config. We will start with a single API as there is no requirement currently for multiple. This can be reviewed and changed post-MVP
The document store contains:
data
: An object representing the document being editedvalidationErrors
: A list of validation errors for each field (to be expanded below)DocumentEdit
(view) reads data from state, groups fields by section and UI position. In the future, it could make sense to move some of this logic away from the view and into a container (I suspect this will make sense once we work on the media collection). The view also decides which component will render the field based on its type (for example, a field of type String
will be handed over to the FieldString
component)
FieldString
, like every other field handler component, receives two props:
schema
: an object containing the field definition from the collection schemavalue
: the current value of the field in the document being edited (if any)It then decides which (dumb) components it needs to render its contents. For example, FieldString
currently uses Label
and TextInput
, but a FieldObject
might use another set of components. Note that these dumb components have no idea what a document, collection or validation routine are. These concepts are controlled by the field components.
Field components also handle validation. They read the rules from the schema
prop they receive and can do actions on different events of their child components. For example, FieldString
listens on onKeyUp
to validate on every keystroke. Other components might want to listen to different events.
Field components receive two callbacks as props:
onError
: This will be called whenever the validation has failed for the field. It's used by the parent (view) to fire an action to the store registering the validation error, which will update the UI accordingly.
onErrorClear
: This will be called whenever a validation error has been cleared. Similarly, an action will be fired to the store clearing the errors for the field, updating the UI accordingly.
The document store could have:
remote
(renamed from data
): The state of the document as it currently exists on the remote APIlocal
: The state of the document as it's being editedvalidationErrors
: Same as before.In addition to onError
and onErrorClear
, field components also receive a onUpdate
callback. This callback will be used by the parent (view) to fire actions that will update document.local
with the new value. Each field component can then decide when to fire this callback — for example, for FieldString
it might make sense to only fire an update call on onChange
and not on onKeyUp
, but an image field might use a completely different event.
When we move to collaborative editing, the view can listen for socket events and fire update actions from other users too. The fact that the local document is always updated by actions makes it really flexible.
At any point in time, we can do a diff between local
and remote
to show what we're about to edit. When it's time to submit (which will only be possible if there's nothing in validationErrors
, we push local
to API bridge.
Thoughts?
Currently the frontend config is created during the build process.
As the app will exists as an NPM module, and the config will exist outside of core and the core build process, we must move the frontend config data into an RESTful response from an auth based endpoint, to be called on clientside app load.
Results could be cached.
A transitioning feature from v1 publish is the ability to specify options for a String, encapsulated in two parts of the field block:
{
"foo": {
"type": "String",
"validation": {
"pattern": "[bar|baz]"
},
"publish": {
"options": [
{"label": "Bar", "value": "bar"},
{"label": "Baz", "value": "baz"}
]
}
}
}
@eduardoboucas outstanding question as discussed on Slack: Do we call this options? If not, what?
Using the router lib, the Link
component will take the same parameters to generate an anchor.
<!-- Current path -->
<Link
params={bar: 'baz'}
/>
<!-- new path -->
<Link
path='/foo'
params={bar: 'baz'}
/>
<!-- new path with existing params -->
<Link
path='/foo'
params={bar: 'baz'}
update
/>
Transitioning between article edit view and document list causes entire app to refresh
Optional way of adding a description to a field for less experienced users.
Open for discussion prior to raising a ticket in @dadi/api
Currently, we're only generating automated documentation for files within frontend/components
. Along with our effort of moving logic into containers (#91), I've been adding documentation to containers. We'll need to extend the build-docs command to also look at frontend/containers
and output Markdown files to docs/containers
.
Nice to have: maybe the markdown generator could differentiate between components and containers, making it clear whether something has access to the global store or not. We're looking to build our own Markdown generator anyway, so perhaps this is something we can add.
Introduce the ability to add and remove multiple filters
Filters are appended to the url but are not taking affect
In addition to existing red highlight.
As per discussion with @josephdenne, a proposal for a concept that breaks down the required configuration blocks into apis and collections in order to limit the amount of api data stored in publish.
The apis
, structure
and auth
blocks relate to an api, database and collection that holds further information.
apis
would list all connected api
credentials, including host, port, database etc.
auth
is a single collection containing the users for publish (and other apps in future)
structure
would contain menu structure, such as sort ordering.
For now, we'll stick with the single config for MVP, or at least until just before release. This needs some serious scrutiny which we'll only find when we've exposed other MVP-related issues.
{
"app": {
"name": "DADI Publish",
"publisher": "Publisher Name",
"baseUrl": "http://am.dev.dadi.technology"
},
"server": {
"host": "0.0.0.0",
"port": 3000,
"authenticate": true
},
"apis": {
"name": "Publish Test API",
"host": "http://am.dev.dadi.technology",
"port": 3003,
"collection": "apis",
"database": "control",
"version": "1.0",
"credentials": {
"clientId": "testClient",
"secret": "superSecret"
}
},
"structure": {
"name": "Publish Test API",
"host": "http://am.dev.dadi.technology",
"port": 3003,
"collection": "structure",
"database": "control",
"version": "1.0",
"credentials": {
"clientId": "testClient",
"secret": "superSecret"
}
},
"auth": {
"host": "http://am.dev.dadi.technology",
"port": 3003,
"collection": "users",
"database": "control",
"version": "1.0",
"credentials": {
"clientId": "testClient",
"secret": "superSecret"
}
}
}
wildcard multi-word search to be performed at document index level
Currently, <Nav>
accepts a groups
prop, which is created by <CollectionNav>
. The idea being that <CollectionNav>
fetches data about collections and groups, builds an array of items and passes that to <Nav>
, which stays dumb and simply renders the items.
However, <Nav>
is expecting a very specific type of object (the object representing a collection). And it's now also doing things like slugifying the collection name (you added this, right @mingard?). Ideally, all the logic that is specific to collections should happen in <CollectionNav>
, which would create a fairly generic object to pass to <Nav>
. Something like:
[
{
id: "item1",
label: "Item number 1",
href: "/item1"
subItems: []
},
{
id: "item2"
label: "Item number 2",
href: "/item2",
subItems: [
{
id: "subitem1",
label: "Sub-item number 1",
href: "/item2/subitem1"
}
]
}
]
This would keep <Nav>
truly generic and it would allow it to be reused in a different context, perhaps one that doesn't involve collections at all.
/sign-in
and type any email+passwordAPI wrapper is returning an error object which can be seen by adding a catch()
here. But the app doesn't seem to pick up this error, perhaps because of the way that controller is being called as a middleware here.
The failure should bubble all the way up to the view, so that I'm able to add a catch()
here and deal with the error by displaying a message.
I have some ideas to handle this last bit, which will involve adding some constants to represent error states and display messages accordingly, but if you could help me get to the point where I can capture the failure on the view that'd be great.
Currently when using api-bridge-client, each request to the API must be POST
ed individually. The wrapper takes to post body (JSON representation of an API request) and runs this through api-wrapper
In some scenarios, such as fetching the config for each collection, we may benefit from running these in batch, as for a single API there could be 10's of collections.
A method of pushing multiple queries into a queue would be useful here. This could perhaps live outside of api-bridge-client in a api-bridge-queue
library, meaning the only change required would be in the route, where a simple check on the presence of the key queries
would build queries to run Promise.all
before return.
Anyway, something like that could be useful @eduardoboucas
From Slack:
I’m looking at the toaster/info banner (http://cloud.dadi.technology/kpk3). couple of questions:
- in your mock up, it pushes down the content of the page. is this intended?
- it’s positioned with the header, which is not fixed positioned. this means that if I have scrolled down the page and hit save, I won’t be able to see the toaster unless I scroll all the way up again. what are your thoughts?
- does it automatically close itself after a period of time, or do you have to close it? the label saying “10 minutes ago” makes me thing the latter, but I don’t see any controls.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.