preaction / Statocles

Static website CMS
http://preaction.me/statocles
Other
84 stars 33 forks source link

Statocles app gets generic #586

Open wbazant opened 4 years ago

coveralls commented 4 years ago

Coverage Status

Coverage remained the same at 86.182% when pulling 35e42718cebeb5f0898e5c0f74502707467c9482 on wbazant:v2_tags_in_default_templates into 24f6c2552c159a79f4a0443e91eb9f11c703b68a on preaction:v2.

wbazant commented 4 years ago

@preaction we were talking about this problem where a piece of content doesn't know which app it was linked from.

I think the solution is to decide that an "app" is a list of posts built on a Yancy query, and tied to a route. It becomes quite configurable - choices like draft => 1/0 vs. status => "published"/"draft" are easy-to-change, sane defaults. One can configure a route for posts only by a certain author, with a certain flag, etc.

This PR breaks something with the themes: I can choose default or bootstrap, but t/theme.t fails, and

@@ -155,8 +171,8 @@ sub startup {
     $app->plugin( Export => );
     push @{$app->export->pages}, '/sitemap.xml', '/robots.txt';
     $app->plugin( AutoReload => );
-
-    if ( my $theme = $app->config->{theme} ) {
+    do {
+        my $theme = $app->config->{theme} //= '+Statocles/theme/default';

seems necessary to fix the other tests. I can spend more time on finding out what it is, if you approve of the general direction.

It's potentially questionable because it blocks a certain route for development. Statocles::App can make default categories from tags, and it can probably also handle a few other optional extras. However, it can't also be something completely different, like a Pod renderer.

If a "blog" is just a Statocles::App with a suggested setup, the current Yancy schema for posts - saying that each $item shall have an author, title, and tags, could also be downgraded to merely a sensible suggestion. Then someone who wants different $item metadata could achieve it with their own configuration and template/layout, and after configuring Yancy accordingly they would also have a cool CMS for it.

preaction commented 4 years ago

There are two application ideas that don't quite fit the model of a simple list.

Maybe the idea of having applications manage multiple different lists of data is the problem here: If an app only had one filter and only displayed one list of content, then each app would be a "category" of the site. We could change tags to be just one way to get a document into a category (so, tags aren't links anymore, just labels), and there could be another area on the page for Categories: that would be links (to the landing page of each app the document could appear in). I'm writing a v0 -> v2 upgrade script, and that could be used to generate an appropriate configuration for a v0 blog (though, it wouldn't automatically add new apps when a new tag is created...)

I would definitely be okay if Statocles::App was the generic content list app (so, Statocles::App::List is renamed to Statocles::App). A lot can be done with a simple list and a template, and it would provide some uniformity to the apps: Every app should define a filter to control what content it sees, a template to use to render, etc... So every app should subclass the main Statocles::App.

I'll have to think about this, and maybe try out a couple options to see the pros/cons. If the configuration file gets too complicated, it'll be more difficult to manage / understand. But also maybe we don't need to optimize for sites with 40 different overlapping topics of content (https://mojolicious.io/blog/ has >50 tags by my count).

(aside: "topic" is a shorter word than "category", and might better define what it's doing: collecting articles with similar subject matter)

wbazant commented 4 years ago

@preaction Search and calendar are very nice use cases: they can be generically added to anyone's blog. I think we can arrive at a design that handles them by leaning on the "categories/topics" that an app has.

Each app has a filter: that's a bit like SQL's "where" clause. With more generic topics we would aim at something like a "group by" clause. When an app has topics, it should do the following when it is being registered:

Here are some examples. The current categories correspond to something like below, where the bucket is made from a 'value', and '?' is replaced with it in the bound route for a bucket, like in a stored procedure or something:

{
  value => 'tags',
  filter => { tags => {-has => '?' }},
}

A similar one, for retrieving all posts from the same author:

{
  value => 'author',
  filter => { author => '?'},
}

A calendar is

{
  value => 'date',
  filter => { date => '?' },
}

a template would be using {text, href} assuming that the text field is a date, and be tasked with making a cool widget.

The search index corresponds to a "topic" that puts everything in one bucket:

{
  value => '',
  filter => {},
}

To make the search functional, the template would call a helper and go through the items, tokenising on the item$markdown and making a link from an item$path.

A topic frequently corresponds to a widget in the sidebar: "Categories" and a list of tags, "Posted by" with all the authors, "Search" that searches, "Calendar" that lets you click on days and get posts from that day. However, I expect the functionality will show up throughout the layout: clicking on an author name and seeing their posts, or clicking a label #gardening to see all gardening posts.

I don't know how I would translate "stored procedures" (SQL::Abstract queries with a "?" appearing) to actual code, and keeping items together with text and href is very flexible but seems like too much, and so far it only seems needed for the search use case.

wbazant commented 4 years ago

This branch has a "posted on" and "tags" added to individual blog pages which is probably a patch more than a feature - added through "item-caption" etc. I should have probably done it separately, just now I've tried to make a post on my blog from a master branch, these were gone from posts, and I wondered why.