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

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

Closed
jacobobryant opened this issue Jul 11, 2022 · 9 comments
Closed

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

jacobobryant opened this issue Jul 11, 2022 · 9 comments

Comments

@jacobobryant
Copy link
Owner

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.

  • What should be in "core" schema and what should be in theme schema? Currently I think most of the post schema should be moved out of core and into themes. Perhaps all of it can be. However Platypub needs to know how to display items in the UI. For example, post-list-item (https://github.com/jacobobryant/platypub/blob/master/src/com/platypub/feat/posts.clj#L267) needs to know the values of :post/{title,status,published-at,edited-at,tags}. Perhaps we have the theme define how items should be rendered in Platypub's navigation.
  • The core schema will at least need to define which user owns the document. Perhaps we replace the :post/user attribute with an :item/user attribute, and then push everything into the themes' schema.
  • How should Platypub/themes know if a given document has a certain type? We could add a :item/type attribute (:item/types might be better), or say "any document with attributes X, Y and Z is a valid Foo document." Or we could have themes define a predicate/malli spec which is used to filter documents. Then themes can use whatever method they want for defining document types. (That may be tricky though--eventually we want to not trust theme code.)
@tbrooke
Copy link

tbrooke commented Jul 14, 2022

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
Copy link
Owner Author

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
Copy link
Owner Author

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
Copy link

tbrooke commented Jul 19, 2022

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
Copy link
Owner Author

I read that also! Interesting article.

@jacobobryant
Copy link
Owner Author

jacobobryant commented Jul 23, 2022

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
Copy link
Owner Author

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
Copy link
Owner Author

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):

(defn get-render-opts [{:keys [biff/db user site item] :as sys}]
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):
(defn derive-opts [{:keys [site item lists posts pages] :as opts}]

@jacobobryant
Copy link
Owner Author

Closed by 146850e

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

No branches or pull requests

2 participants