jacobobryant / platypub

A publishing platform built with Biff
MIT License
65 stars 13 forks source link

Support multiple "item" types, not just posts #43

Closed jacobobryant closed 2 years ago

jacobobryant commented 2 years ago

Platypub's schema has a :post document baked in. Right now we use that for two different types of documents: posts and pages. Some themes would benefit from additional types of documents, like events. We need to figure out how to handle this without bloating the core schema.

See #41. We could have the custom schema define not only individual attributes, but document types as well. This may require some hammock time.

tbrooke commented 2 years ago

I like item/types - with a core platypub schema -- then, tell me if I am getting too complicated, a new platypub menu selection for type - maybe have some defaults but for example a user could create an event type and the attributes could be tags, place holders for css directives etc. -- so the item schema would handle content and the type schema would handle location, formatting and display- the themes could reference the type to place or format the item

jacobobryant commented 2 years ago

menu selection for type - maybe have some defaults but for example a user could create an event type

I think we'll want the themes to define the types, since the themes know what kind of data they need. If users create the types, then every theme has to start out by saying "this theme needs documents of type X, Y and Z, so make some new types for those and include these attributes..." (i.e. either way the theme has to create the type, but this way it's forced to go through the user). A while ago I tried to make an application that stored all the user's data in their own Airtable account and that was the main problem I ran into.

(Let me know if I'm misunderstanding your suggestion.)

As for :item/types -- the thing I'm trying to figure out is, how will it work out for extensibility/interoperability? e.g. say you've been using theme A which works with event documents. However you need to add/change some behavior, so you write theme B which also works with events. For theme B, you want to extend theme A's schema for events such that any events you create while using theme A will still be recognized by theme B, and vice-versa.

Maybe that would be possible with :item/types; I just haven't thought about it enough yet to have all the details hashed out. That's why letting themes define a general predicate function appeals to me: no need to figure out the details; just let the themes figure it out over time ;). checking for a specific value of :item/types would be a special case of a predicate function anyway.

It might not actually be that hard to let themes define a malli spec, but sanitize the spec to make sure it doesn't have any arbitrary code (e.g. don't allow fn schemas).

However I do also want to avoid overthinking things.* Either way I think we need a proof-of-concept of some sort so we can talk about the concrete implementation details more easily.

*If this was a commercial product I'd probably just hard code a few schemas into Platypub and get on with it, but since it's not I feel ok taking some extra time to play around and make something very extensible :).

jacobobryant commented 2 years ago

If you really want to go down the rabbit hole on this, https://www.inkandswitch.com/cambria/ is a good (and long) read.

I also get the feeling that this problem is essentially the same as the expression problem perhaps? Basically I'm thinking that if I just brush up on Clojure's polymorphism/data type handling stuff maybe the correct implementation for platypub will become obvious. Just need to spend a bit of time on it.

tbrooke commented 2 years ago

Another somewhat related deep dive into something I have never completely understood but it seems to me that with a true RESTful API an event for example would know how to display itself: How did Rest become the opposite of Rest

jacobobryant commented 2 years ago

I read that also! Interesting article.

jacobobryant commented 2 years ago

Didn't quite finish a proof of concept on this today, but am planning to have something ready to discuss either tomorrow or friday next week.

as a sneak peak I'm thinking that themes can have a config.edn file which will subsume the custom-schema.edn file, while providing some extra stuff. Here's the start of what that might look like for the default theme:

{:site-fields
 [{:label "Primary color"
   :default "#343a40"
   :key :com.platypub/primary-color}
  {:label "Accent color"
   :default "#009b50"
   :key :com.platypub/accent-color}
  {:label "Tertiary color"
   :default "#e5e7eb"
   :key :com.platypub/tertiary-color}
  {:label "Logo image URL"
   :description "Suggested dimensions: 320x60 px"
   :key :com.platypub/logo-image}
  {:label "Logo destination URL"
   :description "Where should people go when they click on the logo?"
   :default "/"
   :key :com.platypub/logo-url}
  {:label "Author name"
   :key :com.platypub/author-name}
  {:label "Author URL"
   :key :com.platypub/author-url}
  {:label "Author image URL"
   :key :com.platypub/author-image}
  {:label "Discourse forum URL"
   :description "Optional. If you set up a Discourse forum, you can use it to embed comments on your blog posts."
   :key :com.platypub/discourse-url}
  {:label "Embed HTML"
   :description "This snippet will be injected into the head of every page. Useful for analytics."
   :key :com.platypub/embed-html}
  {:label "Navigation links"
   :default "/ Home\n/archive/ Archive\n/about/ About"
   :key :com.platypub/nav-links
   :type :textarea}]

 :items
 [{:key :com.platypub/post
   :label "Post"

   ;; query-keys will be translated to the following when getting the documents to display on the posts page:
   ;  '{:find [[item :com.platypub.post/title]
   ;           [item :com.platypub/types :com.platypub/post]]}
   :query-keys [:com.platypub.post/title
                [:com.platypub/types :com.platypub/post]]

   :fields
   [{:key :com.platypub.post/title
     :label "Title"}
    {:key :com.platypub.post/published-at
     :label "Published at"
     :type :instant}]

   :sendable true

   :render/label :com.platypub.post/title
   }]}

That's very incomplete, but with just a few more keys I think we can move all the post-specific information into this file and have Platypub deal only with generic items. Once I have this example file finished, the next step would be to try to rewrite the platypub core code so it never uses any :post/ keys explicitly. And see if any problems come up.

*in particular, need to add at least one more :render/* key to define e.g. how the small line of text underneath each post title in on the posts page should be rendered. Also would like to add some kind of :table-settings key or something, that defines grouping and sorting as data. can be used to group posts by draft vs. published and sort by edited/published date.

jacobobryant commented 2 years ago

I've been working on this the past few days, and hopefully will have it finished tomorrow. If not, then friday. Nav bar will look like this:

image

Now instead of "posts" there will be "items", and themes will define what those items are via this config.edn file. The default theme defines "posts" and "pages" as seen in the screenshot.

jacobobryant commented 2 years ago

This is now complete. It's on an items branch (https://github.com/jacobobryant/platypub/tree/items). I will probably merge it to master tomorrow/monday. This is a pretty big set of changes. It also requires running a DB migration:

  1. check out the items branch
  2. run ./task dev
  3. go to repl.clj and call the migrate-items! function

After that you can go to localhost:8080 and you should see the new UI as seen in the screenshot above.

Custom themes will need to be updated. See get-render-opts (the return value is what gets passed to the theme): https://github.com/jacobobryant/platypub/blob/fe2dc098fbd197cc70d9b29e0b158bfe85cfcf49/src/com/platypub/util.clj#L200 and derive-opts (this is what the default theme does to the result of get-render-opts before passing it on to the rest of the theme code): https://github.com/jacobobryant/platypub/blob/fe2dc098fbd197cc70d9b29e0b158bfe85cfcf49/themes/default/common.bb#L189

jacobobryant commented 2 years ago

Closed by https://github.com/jacobobryant/platypub/commit/146850e30ffe59ab32b7ec5f2a53b447fcb11e86