Giter Site home page Giter Site logo

mavo's Introduction

Mavo is an HTML-based language for building small scale data-driven websites without programming knowledge (no JS, no backends needed!), just by writing HTML. For JavaScript developers (who like HTML), Mavo can also be used as a declarative, reactive front-end framework to make UI development easier.

Useful links:

  • mavo.io for info on what Mavo is, demos, usage etc
  • plugins.mavo.io to extend what Mavo can do with plugins
  • play.mavo.io to experiment with Mavo, make bug testcases etc
  • CONTRIBUTING.md for info on asking questions, filing bug reports, and contributing to Mavo’s development

mavo's People

Contributors

a-alhm avatar andreasplesch avatar ashsearle avatar barishnamazov avatar betaveros avatar corwin-of-amber avatar dependabot[bot] avatar dmitrysharabin avatar dsan10s avatar efeichen avatar etunaaikido avatar francesca-cicileo avatar hopeful2 avatar jwass91 avatar kjartanm avatar leaverou avatar mattmccutchen avatar mohammadkhalafi avatar norbitrial avatar notpushkin avatar parulsingh23 avatar rafidoth avatar raytran avatar rubenverborgh avatar valterkraemer avatar visualdatasolutions 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  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  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

mavo's Issues

Add button is visible in read mode

<ul data-store="...">
    <li property="foo" data-multiple>...
</ul>

Special casing uls means add button is added after <ul> instead of after <li> therefore outside the [data-store]

Option to duplicate items

In addition to add, it may be efficient to duplicate/modify an existing item.
This would also be a way to address the "which template to use for multiple types" problem we discussed, though not a complete solution.

Support rich HTML as values

Multiline strings often need simple formatting, such as links, bold etc.
This is currently not possible, as everything is done through textContent.

Undo functionality

Edit to make this current:

Currently, the only data edit that can be undone is deletion. That is special-cased, implemented via a rather clumsy mechanism that involves a lot of special casing in expressions etc, it’s buggy, increases the amount of stuff that needs to be styled, both by Mavo and by the author, and complicates the eventual data mutation API.
Instead, soft deletion should be abolished, and all data mutations should be added to an undo stack that can be undone and redone via shortcuts and potentially Mavo bar buttons.
This will also make it much easier to implement diff-based (incremental) saving by storage backends, if there is a record of what actions have happened since the last save.

Original text (which doesn’t make any sense now):

If #6 is implemented, then edit, save, cancel will become global (no need to edit items separately if the editing is just-in-time).
However, that makes it imperative to have a different mechanism for error recovery than a cancel button: Undo. If I can edit all my talks at once, I don't want to have to cancel ALL my edits because I made a mistake.

Editing widget for durations

If a <time>'s datetime attribute is a duration, an appropriate editing widget needs to be used. Currently, it will incorrectly be a date input.

Implement references to other objects that have an id property

As discussed with @karger today.

Idea: Strings that happen to be the same as some id property in the data structure can be dereferenced to the object that contains this property. In case of duplicate values, first (or last?) one wins.

Implementation thoughts:

  • We don’t want to introduce a performance hit if the strings are not dereferenced. That means accessors are out of the question. ES6 Proxies seem like the best way to do it.
  • array of all properties named id so we don’t have to traverse the entire tree.

Wrapped text overflows when edited

Since <input> can't wrap, it can cause really weird results when it's used to edit wrapped elements:

image

Potential solutions:

  1. max-width on <input> equal to the available width on the first line. Probably the easiest one, but it breaks wysiwyg-ness a bit when you have two lines of text and they suddenly become a scrolled one on edit. OTOH, it's done a lot, so people are used to it.
  2. Use multiple <inputs>, simulate the wrapping logic and add/remove inputs as needed. Probably a huge mess.
  3. <textarea> everywhere, instead of <input>, as <textarea> does wrap. Probably hard to make it emulate a wrapped inline element, as it's a block.
  4. Use contentEditable. Always a mess.

Handle duplicate properties gracefully

Currently, the latter overwrites the former.
Instead, both should coexist and saved as an array. Then, in the future, the user can turn them into a collection with zero data loss.

It's basically the exact inverse of treating a singular scope as an array when rendering, if its property is a collection in the template.

Drag and drop on collection items

This is about the saved order of items, which is separate from any future end user sorting.
Many types of collections need this and are not necessarily ordered by any particular property, e.g. todo lists, palettes (lists of colors) etc.

To consider: Where to drag from? Should the entire item be draggable (might interfere with other bits of the UI given the huge variance of different wysies) or should there be a resize handle? If the latter, where to place said resize handle? (again, the variance of wysies makes any UI addition hard)

Decouple storage from filetype

Currently the active Storage subclass for each wysie instance handles both (de)serialization and storage. These should be separate, so we could support multiple filetypes regardless of storage. E.g. so that a collection without child collections/scopes could be saved as a CSV, to take advantage of append-only permissions, such as the ones SOLID supports (append only is useless for JSON files).

Just in time property editing

Do not create editors for all properties when the outer scope is edited. Make everything editable, but actually create the editor when the user interacts with the property (1).
This way, editing of an entire collection will become much faster, as both DOM interaction and number of elements will be minimized.

(1) Property interaction =

  1. Clicking on it
  2. Focusing and pressing spacebar, enter or just start typing
  3. Anything else?

Basic importer

As much as we're not focusing on legacy, this will be a killer feature for adoption.

As it currently stands, if somebody has a collection in HTML, they must still make a template and either convert their data to JSON manually, or enter them via the UI. This is a huge hassle, which for most cases could be avoided pretty easily.

If the storage file is empty, wysie would kickstart the import. Once the data is imported & saved, the user would get a message to clean up their HTML to avoid duplicate data being shown.

This is also a nice self-contained project for a UROP, though I'm not optimistic that it would be of interest.

Add/clone/move buttons across collections and wysies

Collections already allow for custom wysie buttons, i.e. buttons near the collection with a class of wysie-add or add. They should also have an attribute to specify where they will add an item, if that's not the collection closest to them. Being able to move items around with the press of a button will be immensely useful for a number of use cases, e.g. shopping carts, categorization tasks and many others.

Global UI on a bar at the top of the viewport

Depends on: #6

Once #6 is implemented, then edit, save, cancel will all become global, i.e. each will have one button per wysie instance.
As it currently stands, it's very difficult to add any UI to the user's template because of the huge variance between different wysies. The less we change their template, the better.
All global controls need to move to a bar at the top, which will be visible only when its corresponding wysie instance is visible.

List of global controls (assuming #6 is implemented):

  • Login/logout/current user info
  • Progress indicator
  • Edit, save, cancel buttons
  • Undo/redo, if #10 is implemented.

Being separate will make styling much easier too, and can actually be a usability improvement in cases of large wysies that span longer than the viewport height, in which case one has to scroll up and down a lot to reach global controls or to see the progress indicator. It is also on par with what many CMSes do, e.g. Wordpress:

image

Challenges: What to do when there are more than 1 wysies visible on the screen?

Preserve order of properties in scopes?

Currently if the order of properties in the template is different than the order in the JSON, the order in the JSON will change. Also, if there are any unhandled properties, they will be added at the end when saving.

Not sure if this should be considered a bug, since JSON objects are supposed to be unordered. However, it would mess up any diffing.

Improve usability of wysifying pages

Currently, if a user adds wysie properties to an item that is going to be a collection, the item is removed from the DOM and used as a template. If it contains any data, it is used as default values and if its data actually need to be stored, it needs to be reentered.
This is disruptive and confusing.
The common flow is, I add an item with my data, I style it, then I wysify it. The item should still be there, just editable. I can always delete it if I don’t want it. Also, its data could become examples in the sense of using them in placeholders, but they should not become default values. Using them as default values forces people to meticulously clean up their template in order to make a usable application, which could be done automatically. If I want to specify default values, there should be a separate attribute for that. E.g. in the list of talks, if the first talk is in Singapore, I don't want to have to have to replace Singapore every time I add a new talk. Instead, it could be used in the placeholder, which instead of (city) could become City, ex: Singapore.

Implementation-wise:

  • If the JSON is empty and the template has data, extract the data, save it and use it in placeholders.
  • data-default attribute for default values. If used with no value, the content becomes the default value.
  • If there's only one item in the JSON, check if the template contains data that the item doesn't have and if it does check if other properties match the template data. If so, import these properties too. This is important because people will most likely want to gradually make this editable and check what wysie does, so if the only import happens when the JSON is empty, this use case will not work.
  • If we do all this how do they create initially empty collections? They can delete the initial item. Or they can put the template in a <template> tag. Maybe an attribute too?

Conflict resolution when content with expressions is externally modified

Use cases:

  • A class is added after the expression was picked up.
  • The expression is part of a default value that could be overwritten
  • A third-party script modified the content in some other way

Possible solution: Use mutation observers to track changes to content with expressions. Since we have the old value, the new value and the expression value(s), we can figure out how to change the stored expression to include the change.

Support <template>

Useful for collection items without a container, e.g.:

<dl>
  <template data-multiple property=person>
    <dt>name</dt>
    <dd property=name></dd>
  </template>
</dl>

Storage API should take advantage of backends with more granular permissions

Currently, it makes the following assumptions:

  • Data is publicly readable
  • Data is either publicly editable or editable after authentication
  • When loading data from one's own server (i.e. not using one of the supported backends), data is not editable.

All these assumptions are false.

Possible structure:

There should be a permissions object (Wysie.Storage#can?) whose properties would be:

  • login
  • read
  • edit
  • add
  • delete

and whose values would be either true or false. It would be possible to subscribe to permission changes and act accordingly every time there is a transition.

Scopes should also be able to be primitives

Structures like this should be allowed:

<a property="url" data-multiple>
    <span property="name"></span>
</a>

and produce JSON like:

url: [
    { "url": "http://...", "name": "..." },
    { "url": "http://...", "name": "..." },
    ...
]

Dynamic editors

If the nested editor contains a property (or is a property), it should not be removed from the DOM. Instead, it should just be hidden until edit mode.

This will enable variable options per select:


"foo": [
    {
        "bar": "optionK",
        "barOption": ["option1", "option2", …, "optionN"]
    }
    
]
<article property=foo data-multiple>
    <span property="bar">
        <select>
            <option property=barOption></option>
        </select>
    </span>
</article>

Preserve data that is not in the template

Currently properties that are not in a template are preserved, but:

  1. If wysie is only rendering a subtree, the rest of the tree is not preserved
  2. Cannot load only part of a collection, and even if we could, the remaining items would not be preserved. This is needed to do any kind of pagination which will enable wysie to work with much bigger types of apps (e.g. a wysie blog!).

Automatic adding of new items

A common UI pattern is having an item automatically added to a collection instead of having to press an "Add item" button. E.g. most to-do lists do this.

Wysie should do this for top-level collections. For nested collections, it would probably modify the layout way too much.

Caveat: Item needs to have some flag set so that it's not saved if the user has not interacted with it, since this is not the same as clicking "add item".

Decouple edit and save buttons

Currently, pressing Save returns the user to read mode. However, since editing is now global, it makes sense that the user would want to save often, without necessarily concluding their editing. Therefore, Edit should become a toggle between edit and read mode, and save should do nothing more than save.

Then we can also move the saving progress indicator to the save button, and maybe in the future have autosave.

The only wart is, now what does cancel do?
The easiest to implement option would be that it just discards any unsaved changes. If they enabled autosave, well, tough luck. This is probably what we'll do initially. And rename it to "Revert", obvs.

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.