Giter Site home page Giter Site logo

dadi / publish Goto Github PK

View Code? Open in Web Editor NEW
64.0 64.0 13.0 16.39 MB

Publish provides beautiful editorial interfaces for the management of content within API

Home Page: https://dadi.cloud/en/publish

JavaScript 88.88% CSS 11.06% Shell 0.02% Dockerfile 0.04%
cms cope headless publishing

publish's People

Contributors

abovedave avatar alshchur avatar danwdart avatar davidmacp avatar eduardoboucas avatar feroviktor avatar jean-luc avatar jimlambie avatar mingard avatar ohmoses avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

publish's Issues

URL filter formatting

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

Support for assets

Concept overview

  • Assets will be stored within asset collection(s) specified within config
  • Asset collections can contain one or more asset field (image/video/audio/file), nothing else.
  • AssetMeta collections are where assets are manipulated for single-use, per-parent-collection. This is typically fields such as title, alt text, caption etc. It is also where image crops will exist. One instance of an AssetMeta collection might have different available crops to others.
  • AssetMeta collections are not a collection type, but will simply be shown and hidden based on business requirements.

@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

Webpack production bundle issues

  • Adding NODE_ENV=production is not enough. a -p must also be added. This should be fixed
  • Errors in api-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 presets

Improve frontend config method

We 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.

Batch document actions

I believe we already have multi select, so all this needs is

  • action selection
  • CTA
  • Events
  • Callback confirmation

script: create component template

Create component

[sudo] publish create component

Select type

Which type of component do you want?

1) Component
2) Container
3) View
> 1

Name component

What's the name of your component?
> ButtonFoo

Output

Done! Component file and CSS file created in views/ButtonFoo

Sign in with session

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

collections/nav missing

Repeat x3

  1. Sign in
  2. Navigate to a collection
  3. Observe data
  4. Sign out

on second repeat, no collections exist on state.api.apis[0]
on third repeat, there is no nav

API-wrapper throttling

Issue

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.

TL;DR

Add throttling to API wrapper in Publish to circumvent inevitable 💥

User profile view

Create first-pass user profile view with:

Requirements

  • Store remote user data in local and remote
  • Inputs
  • Tabs
  • Handle redirect to section
  • Password reset
  • Update local on input change

Fields/tabs

Account tab

  • Full name
  • Email
  • A bio
  • Profile image

Settings

  • Language
  • Timezone
  • Date/time format

Password reset

  • Old password
  • New password
  • Repeat new password

Chore: Remove localdb

This build currently contains a local database. We must remove any of the following that relate to localdb (reasondb)

  • Modules
  • Packages
  • Documentation

Notes from previous build:

  1. API’s Currently added through the interface and stored in localdb. Could be part of config? For now, that seems like a good idea. Why would anyone else apart from engineers add and remove APIs anyway?
  2. Users Currently stored locally, but could come directly from API collection, for now, until we decide how API users can look
  3. Collections Previously we needed to cache these to deliver on each page load, but I see no reason why we don’t just have the frontend request these on load. The collection endpoint is fast to resolve and with this being a webapp there would be a single request per session. We could memcache them on the server. Thats also lightweight.
  4. Workers Interval tasks are no longer part of Publish
  5. ACL Roles are not part of the new Publish, yet. That again is something that we could handle directly in API after we scope

Collapse menu on selection

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

Add API configurations to config

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

Spec: document edit view

What I've done so far

Store

The document store contains:

  • data: An object representing the document being edited
  • validationErrors: A list of validation errors for each field (to be expanded below)

View

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)

Field handler component and dumb UI components

FieldString, like every other field handler component, receives two props:

  • schema: an object containing the field definition from the collection schema
  • value: 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.

Validation

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.

What I propose going forward

Store

The document store could have:

  • remote (renamed from data): The state of the document as it currently exists on the remote API
  • local: The state of the document as it's being edited
  • validationErrors: Same as before.

The flow

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?

Frontend config - change to endpoint

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.

FieldString: Option list

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?

Link component

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
/>

Extend docs generation to containers

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.

Config concept

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.

Sample

{
  "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"
    }
  }
}

Search support

wildcard multi-word search to be performed at document index level

Make Nav accept a generic groups prop

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.

Handle failure of auth API

Steps to reproduce

  1. Take down the API used to validate sessions.
  2. Go to /sign-in and type any email+password
  3. The app fails silently

Details

API 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.

Expected behaviour

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.

Bundle/Accumulate api-wrapper requests

Currently when using api-bridge-client, each request to the API must be POSTed 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

Toaster UI

From Slack:

I’m looking at the toaster/info banner (http://cloud.dadi.technology/kpk3). couple of questions:

  1. in your mock up, it pushes down the content of the page. is this intended?
  2. 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?
  3. 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.

Load status bar

  • Introduce thin loading bar at top of page for data loading pagination
  • Bind all api queries to status bar to better depict loading status
  • Exist as a container
  • Observe all states, and loading status

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.