Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Query for Supported Properties #8

Open
dshanske opened this issue Dec 5, 2018 · 21 comments
Open

Query for Supported Properties #8

dshanske opened this issue Dec 5, 2018 · 21 comments

Comments

@dshanske
Copy link
Member

@dshanske dshanske commented Dec 5, 2018

Separated from #1.

Suggest that the config query return a properties element that notes which experimental properties the endpoint supports so the client can choose to hide unsupported ones

@EdwardHinkle
Copy link

@EdwardHinkle EdwardHinkle commented Apr 15, 2019

I think this is definitely needed, not just for experimental properties but also for official ones. Because if Micropub were to become an Evergreen Spec like @aaronpk was thinking through a bit in chat the other day, we would need a way to define what parts people support since you might have older, unsupported endpoints at some point.

@gRegorLove
Copy link
Member

@gRegorLove gRegorLove commented Apr 16, 2019

I'm interested in this in conjunction with #11. I'm adding visibility options to indiebookclub. I think it's important that IBC can tell if the mp server supports "private" or "unlisted" before presenting those options in the UI.

@grantcodes
Copy link

@grantcodes grantcodes commented Apr 16, 2019

So I think there are at least 2 ways we would need to show full support for a property:

  1. The basic property is supported and accepts any value, e.g. things like summary and category can accept pretty much anything, but would be nice to know if they are supported
  2. A property that accepts a value from a set list of values, eg the visibility example that supports "private", "unlisted", "public" etc..

But because microformats is pretty fluid it becomes quite complicated when there are some fields that should accept multiple values (mp-syndicate-to), and some that should only accept single values (visibility), and some that could be from a list but allow new values (category).

There is already the prior art of the category query #5 and syndicate-to that are both fairly different already.

In an ideal world there would be a way to define support for any existing property that would also work with any future or custom property too, this could potentially allow micropub clients to be future proof and display a ui for any property.

@EdwardHinkle
Copy link

@EdwardHinkle EdwardHinkle commented Apr 16, 2019

Hmmm interesting @grantcodes that’s definitely something to think through

@EdwardHinkle
Copy link

@EdwardHinkle EdwardHinkle commented Apr 16, 2019

So initially brainstorming this: you definitely don't want to simplify the syndicate-to object because that is needed. I also don't know that you would want to complicate the category array by making the strings be objects, because then you're just adding complexity turning all the category strings into an object like { uid: categoryName }

So instead, I'm wondering if there are two known value types of properties: objects and strings. A string is a simple base-line and if you need to control anything else about it other than having it be a simple string it becomes a standard object.

I think, as you said, you also need to define some behaviors around a property, so I'm roughly suggesting something like this:

properties: {
  "visibility": {
   "new-values": false,
    "max-values": 1,
    "value-type": "string",
    "default": "private", 
    "options": [
      "public",
      "private",
      "unlisted"
    ]
  },
  "category": {
    "new-values": true,
    "max-values": 0, // 0 = unlimited
    "value-type": "string",
    "default": null, // Or this could be undefined
    "options": [
      // this is an array of strings of previous categories
    ]
  },
  "syndicate-to": {
    "new-values": false,
    "max-values": 0,
    "value-type": "object",
    "default": null,
    "options": [
      {
        "uid": "uid of object",
        "name": "display name of object"
      },
      {
        "uid": "twitter-service",
        "name": "Twitter Username"
      },
     {
        "uid": "github-service",
        "name": "GitHub Username"
      },
    ]
  }
}

There are some immediate potential issues with this direction that need to be taken into consideration, but it's something we can iterate on. For certain things like categories, there can be a LOT of values, thus it may be better to instead of returning an array of values, to provide some indicator that the user has to send a different query for the given options, maybe it's by leaving out the options attribute of the property object.

In which case:

  • no options attribute means you have to query the values in a separate query request
  • an empty options array means no values present
  • an options array with content means you have all existing content

NOTE: This would alter behavior of syndicate-to values, so modern Micropub clients would first have to check if the properties object exists, if so they would use that, and if not, they would need to look in the standard location for syndicate-to values.

EDIT: Based on the conversation by @grantcodes in #11 (comment), I have added a default attribute to the brainstorm above so that a client knows what value it should default to. If a property shouldn't have a default value we can either set default to null OR just not include that attribute, I'm fine either way

@EdwardHinkle
Copy link

@EdwardHinkle EdwardHinkle commented Apr 16, 2019

This GitHub issue is going to be refocused on the original two issues:

  1. Hiding properties in a client that aren't supported by a server
  2. Providing pre-defined options and defaults for those supported properties

The other conversations in this issue around supporting new properties, etc are moving to this new issue: #21 which is about helping clients to add support for properties that they don't know about or don't support already

@EdwardHinkle
Copy link

@EdwardHinkle EdwardHinkle commented Jun 18, 2019

Has anyone done any server work to implement this at a basic level? @dshanske @gRegorLove @grantcodes

I'm planning on adding some basic support to my server that essentially provides something like:

properties: [
  {
    "name": "visibility"
    "default": "private", 
    "options": [
      "public",
      "private",
      "unlisted",
      "protected"
    ]
  },
  {
    "name": "category"
  },
  {
    "name": "syndicate-to"
  }
}

This is a simple array with objects that MUST contain a name, and the name MUST match the property name that will be included in the Micropub request. Also, you'll notice the server MAY return a default value and/or a list of options. Since category and syndicate-to's options list can be long, on my server I'm opting out of returning those and instead it has to be fetched separately using their query endpoints. I'll report back after I've implemented this both on my server and in Chronicler and let you all know how it turned out for me.

@dshanske
Copy link
Member Author

@dshanske dshanske commented Jun 18, 2019

I am willing to. I only do the properties, not their values yet.

@EdwardHinkle
Copy link

@EdwardHinkle EdwardHinkle commented Jun 18, 2019

You do currently include the available properties? What does your current return look like for this Endpoint?

@dshanske
Copy link
Member Author

@dshanske dshanske commented Jun 18, 2019

Properties as a single level array. But no one is consuming it

@aaronpk
Copy link
Member

@aaronpk aaronpk commented Sep 29, 2019

I implemented initial support in Quill for this. Quill now looks for the following object in the q=config response:

  "visibility": ["public","unlisted","private"]

The reasoning for this is I want clients to be aware of the meaning of these values, and I want servers to be able to support only a subset of these values. I also don't want servers to be able to define arbitrary visibilities here, because visibility is not the same as access control (see audience for access control).

Quill hides the syndication options if you choose "private", so it needs to know what these strings mean. I also want clients to be able to localize these strings, so that's why the server doesn't return a label for them either.

@grantcodes
Copy link

@grantcodes grantcodes commented Sep 30, 2019

Another question with this: Should a client decide to hide UI for properties it cannot detect support for? I think previously there was a general reasoning for no because servers should support accepting property, but that feels dangerous with privacy related things like visibility.

But extrapolating on that it would be nice to be able to tell if other properties are / are not supported (micro.blog being a good example). For that I think the properties array mentioned previously works well. If a server does not return a properties option you can default to showing all non dangerous UI options, but if there is a properties you can hide certain things.

I think I will try to implement something along those lines in together and my other micropub clients.

@aaronpk
Copy link
Member

@aaronpk aaronpk commented Oct 2, 2019

I think this is getting confused with #1.

Manton and I hashed this out a bit in Austin and shipped it on Micro.blog and Quill. Quill will only show interfaces for supported post types if the micropub endpoint says it supports only certain post types. If the micropub endpoint doesn't specify, then Quill shows everything.

@EdwardHinkle
Copy link

@EdwardHinkle EdwardHinkle commented Oct 2, 2019

Hey, I haven’t been around much because I’ve been busy, but this popped up in my GitHub notifications. I don’t think it’s confused with #1, it’s a sibling to #1. The very first post in this issue by GWG says “which experimental properties the endpoint supports so the client can choose to HIDE unsupported ones”

#1 is strictly about properties that can be defined as post type. It doesn’t solve the very real issue of drafts status, visibility, etc.

@grantcodes
Copy link

@grantcodes grantcodes commented Oct 2, 2019

Yep I agree with @EdwardHinkle

There is definite overlap, but there are clear differences between post types and other properties.

In particular the properties that are more related to how posts are handled on the backend, rather than their content. visibility & post-status definitely being the biggest ones for now as @EdwardHinkle mentioned. If a user trys to save a post as a draft but their site doesn't support drafts that is potentially dangerous.

The solution that @aaronpk is using for visibility is fine, but doesn't seem very extendable to me, as more similar things get added the top level of the micropub config could get very noisy.

Then there are lots of other things that may not be supported but are not necessarily dangerous - eg. mp-slug, category etc etc. So it would still be nice to be able so remove redundant UI components in micropub clients.

@manton
Copy link

@manton manton commented Jul 15, 2020

I just wanted to highlight a proposal from #1 that I think is an elegant solution to this, building off of the post-types field. A simplified version that just includes the supported properties for a given post type would look like something like this:

GET /q=config
{
  "post-types": [
    {
      "type": "note",
      "name": "Note",
      "properties": [ "content", "category", "photo", "published", "post-status" ]
    }
  ]
}

@jamietanna
Copy link

@jamietanna jamietanna commented Oct 18, 2020

I've settled on the following contract when calling q=properties:

{
    "properties": [
        {
            "name": "name",
            "hints": [],
            "display-name": "Title"
        },
        {
            "name": "nickname",
            "hints": [],
            "display-name": "Nickname"
        },
        {
            "name": "photo",
            "hints": [
                "url"
            ],
            "display-name": "Photo"
        },
        {
            "name": "published",
            "hints": [
                "date"
            ],
            "display-name": "Date Published"
        },
        {
            "name": "category",
            "hints": [
                "multivalue"
            ],
            "display-name": "Category / tag"
        },
        {
            "name": "rsvp",
            "hints": [],
            "options": [
                "yes",
                "no",
                "maybe",
                "interested"
            ],
            "default": "yes",
            "display-name": "RSVP"
        },
        {
            "name": "content",
            "hints": [
                "multiline"
            ],
            "display-name": "content"
        },
        {
            "name": "syndication",
            "hints": [
                "multivalue",
                "url"
            ],
            "display-name": "Syndication URL"
        },
        {
            "name": "summary",
            "hints": [],
            "display-name": "Summary"
        },
        {
            "name": "end",
            "hints": [
                "date"
            ],
            "display-name": "End Date"
        },
        {
            "name": "start",
            "hints": [
                "date"
            ],
            "display-name": "Start Date"
        },
        {
            "name": "num",
            "hints": [],
            "display-name": "Number"
        },
        {
            "name": "unit",
            "hints": [],
            "display-name": "Unit"
        },
        {
            "name": "url",
            "hints": [
                "url"
            ],
            "display-name": "Url"
        },
        {
            "name": "rel=twitter",
            "hints": [],
            "display-name": "Twitter username"
        },
        {
            "name": "repost-of",
            "hints": [
                "url"
            ],
            "display-name": "URL to be Reposted"
        },
        {
            "name": "like-of",
            "hints": [
                "url"
            ],
            "display-name": "URL to Like"
        },
        {
            "name": "in-reply-to",
            "hints": [
                "url"
            ],
            "display-name": "URL to Reply To"
        },
        {
            "name": "bookmark-of",
            "hints": [
                "url"
            ],
            "display-name": "URL to Bookmark"
        },
        {
            "name": "read-status",
            "hints": [],
            "options": [
                "to-read",
                "reading",
                "finished"
            ],
            "default": "finished",
            "display-name": "Reading Status"
        },
        {
            "name": "read-of",
            "hints": [
                "url"
            ],
            "display-name": "URL to Mark Reading Status Of"
        }
    ]
}

The hints allow for making it clear to a consumer how to style the input, i.e. should it be multi-line input, should we have some way of specifying multiple items, etc.

I've also followed the idea of options and default, as well as being able to provide a friendly display-name to the client.

This works really nicely in conjunction with #33.

@prof-milki
Copy link

@prof-milki prof-milki commented Apr 8, 2021

I'm not exactly sure why there should be a separate ?q=properties. Any such property declarations belong merged with ?q=query and its post-types list. (Shaving off a few bytes on the first one is a bad tradeoff for requiring more API requests.)

Also I would advocate for more blatant HTML parity when it comes to naming things:

 {
    "media-endpoint": "…",
    "syndicate-to": [],
    "post-types": [
        {
            "type": "note",
            "name": "Blog/Technote",
            "-map": "technote",
            "properties": [
                {
                    "name:" "content",
                    "label": "Content",
                    "type": "textarea markdown",
                    "value": "## Note\n...",
                    "required": true,
                    "-map": "stdin"
                },
                {
                    "name": "summary",
                    "label": "Timeline note",
                    "type": "text plain",
                    "placeholder": "commit description...",
                    "-map": "title"
                },
                {
                    "name": "background-color",
                    "type": "color",
                    "required": false,
                    "-map": "bgcolor"
                },
                {
                    "name:" "photo",
                    "type": "file",
                    "accepts": "image/*",
                    "is-media": true,
                    "required": false
                }
            ],
            "required-properties": ["content"],
            "accepts-media": true
        },
        {
            "type": "entry",
            "name": "Wiki page",
            "-map": "wiki",
            "accepts-media": true,
            "properties": [
                { "name": "content",},
                { "name": "title",},
                { "name": "file",}
            ],
            "required-properties": ["content", "title"]
        }
    ]
}
Rationale
  • It's unlikely a compound properties list would do you any good. Your micropub endpoint either has but one h-type supported; so it doesn't add much duplication when properties are noted right there. And if different post-types were supported, the overlap would be mostly just the content field. But even that is possible to divert between post-types (e.g. "h-entry" being a blog post, but "h-chat" required a single-line content field).

  • Changed properties: to be a list of dicts (rather than having each key be the name:), as that's more in line with the existing config structures. Now this opens up the possibility of duplicate entries. (But optimizing for edge cases is rarely a good idea.)

  • Another diversion from the post-types structure would be label: or title: instead of name: for the properties list.

  • Instead of a hint: list (as proposed by @jamietanna above), it might be more consistent to use type: (like in <input type=…>). Which implies a lot of known vocabulary:

    type what it renders as
    text standard <input> field
    textarea a multiline <textarea> content field
    select a <select> box, taking values from a select: [] list
    url standard input field, but with url validation
    email standard input field, but with email validation
    datetime calendar input
    file an upload element
    hidden secret input field
    checkbox boolean property (for e.g. visibility?)
    h-card nested structure
  • Speaking of select, that might be controversial. Noone can ever settle between select/choices/options. But again for strong parity, I would also prefer "select": [] to enlist the allowed values.

          {
              "name": "tkt-type",
              "type": "select",
              "select": ["Code_Defect", "Documentation", "Feature_Request"]
          }
  • And once you go with the input field scheme, you also get obvious attributes like placeholder: and value: (rather than default:) here.

    attr pretty much what it means in HTML
    name: property field name
    required: isn't optional (bool-ish attr)
    value: the preset/default value
    placeholder: example value
    select: a <select> box, taking values from a select: [] list
    label: or title: ?
    multiple: for select property (bool-ish attr)
    accepts: mime list for file upload properties
    -map: internal attribute (mp client should ignore those)
  • Arguably this might be a bit too programmatic - it's essentially a JSON serialization of form fields. But then again, certainly helps auto-discovery, or merging standard and unknown properties/post-types, or even super dumb clients (craft a <form> pointed directly at the MP endpoint).

reg extensions: [ "post-types-properties-dict-input" ]

@manton
Copy link

@manton manton commented Apr 16, 2021

This is getting quite complicated. I think this is out of scope for Micropub. Very few people need to build a general-purpose editor that can dynamically adapt to this level.

My suggestion above (July 15th) would solve the original request in an easy, backwards-compatible way, though.

@dshanske
Copy link
Member Author

@dshanske dshanske commented Dec 5, 2021

There are per-post-type properties, and global properties. I had only intended to address global properties. Proposing that: visibility, post-status, and mp-slug all apply equally to all post types, so should be specified as such. I think the proposals about per-post type items are worth discussion,

Quill and Indiebookclub as clients now implement visibility as a return in q=config.

@gRegorLove
Copy link
Member

@gRegorLove gRegorLove commented Dec 6, 2021

indiebookclub now checks for the same config options Aaron described above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
8 participants