From bb0fd2d53a765c5a2a4f04822cd7edf7484f3a8c Mon Sep 17 00:00:00 2001
From: Mattia Roccoberton <mattia.roccoberton@telepass.com>
Date: Mon, 10 Apr 2023 15:42:22 +0200
Subject: [PATCH 1/2] docs: README improvements

---
 README.md | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 93 insertions(+), 3 deletions(-)

diff --git a/README.md b/README.md
index 5118e93..43b4dd0 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,7 @@
 # Tiny Admin
 
+[![Gem Version](https://badge.fury.io/rb/tiny_admin.svg)](https://badge.fury.io/rb/tiny_admin) [![Linters](https://github.com/blocknotes/tiny_admin/actions/workflows/linters.yml/badge.svg)](https://github.com/blocknotes/tiny_admin/actions/workflows/linters.yml) [![Specs Rails 7.0](https://github.com/blocknotes/tiny_admin/actions/workflows/specs_rails_70.yml/badge.svg)](https://github.com/blocknotes/tiny_admin/actions/workflows/specs_rails_70.yml)
+
 A compact and composable dashboard component for Ruby.
 
 The main features are:
@@ -14,7 +16,7 @@ Please ⭐ if you like it.
 
 ## Install
 
-- Add to your Gemfile: `gem 'tiny_admin'`
+- Add to your Gemfile: `gem 'tiny_admin', '~> 0.1'`
 - Mount the app in a route (check some examples with: Hanami, Rails, Roda and standalone in [extra](extra))
 - Configure the dashboard using `TinyAdmin.configure` and/or `TinyAdmin.configure_from_file` (see [configuration](#configuration) below)
 
@@ -53,10 +55,98 @@ Components available:
 ## Configuration
 
 TinyAdmin can be configured using a YAML file and/or programmatically.
-
 See [extra](extra) folder for some usage examples.
 
-Sample:
+The following options are supported:
+
+`root` (Hash): define the root section of the admin, properties:
+  - `title` (String): root section's title;
+  - `page` (String): a view object to render;
+  - `redirect` (String): alternative to _page_ option - redirects to a specific slug;
+
+Example:
+
+```yml
+root:
+  title: MyAdmin
+  redirect: posts
+```
+
+`authentication` (Hash): define the authentication method, properties:
+  - `plugin` (String): a plugin class to use (ex. `TinyAdmin::Plugins::SimpleAuth`);
+  - `password` (String): a password hash used by _SimpleAuth_ plugin (generated with `Digest::SHA512.hexdigest("some password")`).
+
+Example:
+
+```yml
+authentication:
+  plugin: TinyAdmin::Plugins::SimpleAuth
+  password: 'f1891cea80fc05e433c943254c6bdabc159577a02a7395dfebbfbc4f7661d4af56f2d372131a45936de40160007368a56ef216a30cb202c66d3145fd24380906'
+```
+
+`sections` (Array of hashes): define the admin sections, properties:
+  - `slug` (String): section reference identifier;
+  - `name` (String): section's title;
+  - `type` (String): the type of section: `url`, `page` or `resource`;
+  - other properties depends on the section's type.
+
+For _url_ sections:
+  - `url` (String): the URL to load when clicking on the section's menu item;
+  - `options` (Hash): properties:
+    + `target` (String): link _target_ attributes (ex. `_blank`).
+
+Example:
+
+```yml
+slug: google
+name: Google.it
+type: url
+url: https://www.google.it
+options:
+  target: '_blank'
+```
+
+For _page_ sections:
+  - `page` (String): a view object to render.
+
+Example:
+
+```yml
+slug: stats
+name: Stats
+type: page
+page: Admin::Stats
+```
+
+For _resource_ sections:
+  - `model` (String): the class to use to fetch the data on an item of a collection;
+  - `repository` (String): the class to get the properties related to the model;
+  - `index` (Hash): collection's action options;
+  - `show` (Hash): detail's action options;
+  - `collection_actions` (Array of hashes): custom collection's actions;
+  - `member_actions` (Array of hashes): custom details's actions;
+  - `only` (Array of strings): list of supported actions (ex. `index`);
+  - `options` (Array of strings): resource options (ex. `hidden`).
+
+Example:
+
+```yml
+slug: posts
+name: Posts
+type: resource
+model: Post
+```
+
+`style_links` (Array of hashes): list of styles files to include, properties:
+  - `href` (String): URL for the style file;
+  - `rel` (String): type of style file.
+
+`scripts` (Array of hashes): list of scripts to include, properties:
+  - `src` (String): source URL for the script.
+
+`extra_styles` (String): inline CSS styles.
+
+### Sample
 
 ```rb
 # config/initializers/tiny_admin.rb

From 0fdf95c3e83d28898901bf6d9d61c843f3656fe6 Mon Sep 17 00:00:00 2001
From: Mattia Roccoberton <mattia.roccoberton@telepass.com>
Date: Sun, 9 Apr 2023 21:59:50 +0200
Subject: [PATCH 2/2] docs: add sample_features_app example

---
 extra/sample_features_app/admin/items.rb      | 61 +++++++++++++++++++
 .../sample_features_app/admin/missing_page.rb | 10 +++
 .../sample_features_app/admin/sample_page.rb  | 21 +++++++
 .../sample_features_app/admin/sample_page2.rb | 21 +++++++
 extra/sample_features_app/app.rb              | 25 ++++++++
 extra/sample_features_app/tiny_admin.yml      | 14 +++++
 6 files changed, 152 insertions(+)
 create mode 100644 extra/sample_features_app/admin/items.rb
 create mode 100644 extra/sample_features_app/admin/missing_page.rb
 create mode 100644 extra/sample_features_app/admin/sample_page.rb
 create mode 100644 extra/sample_features_app/admin/sample_page2.rb
 create mode 100644 extra/sample_features_app/app.rb
 create mode 100644 extra/sample_features_app/tiny_admin.yml

diff --git a/extra/sample_features_app/admin/items.rb b/extra/sample_features_app/admin/items.rb
new file mode 100644
index 0000000..d6a6640
--- /dev/null
+++ b/extra/sample_features_app/admin/items.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+module Admin
+  COLUMNS = %i[id first_col second_col third_col].freeze
+
+  Column = Struct.new(:name, :title, :type, :options)
+  Item = Struct.new(*COLUMNS)
+
+  RECORDS = [
+    Item.new(1, 'value a1', 'value a2', 'value a3'),
+    Item.new(2, 'value b1', 'value b2', 'value b3'),
+    Item.new(3, 'value c1', 'value c2', 'value c3')
+  ].freeze
+
+  class ItemsRepo < TinyAdmin::Plugins::BaseRepository
+    def fields(options: nil)
+      COLUMNS.map do |name|
+        Column.new(name, name.to_s.tr('_', ' '), :string, {})
+      end
+    end
+
+    def index_record_attrs(record, fields: nil)
+      record.to_h
+    end
+
+    def index_title
+      "Items"
+    end
+
+    def list(page: 1, limit: 10, filters: nil, sort: ['id'])
+      [
+        RECORDS,
+        RECORDS.size
+      ]
+    end
+
+    # ---
+
+    def find(reference)
+      RECORDS.find { _1.id == reference.to_i } || raise(TinyAdmin::Plugins::BaseRepository::RecordNotFound)
+    end
+
+    def show_record_attrs(record, fields: nil)
+      record.to_h
+    end
+
+    def show_title(_record)
+      "Item"
+    end
+  end
+end
+
+TinyAdmin.configure do |settings|
+  (settings.sections ||= []).push(
+    slug: 'items',
+    name: 'Items',
+    type: :resource,
+    model: Admin::Item,
+    repository: Admin::ItemsRepo
+  )
+end
diff --git a/extra/sample_features_app/admin/missing_page.rb b/extra/sample_features_app/admin/missing_page.rb
new file mode 100644
index 0000000..800b4dc
--- /dev/null
+++ b/extra/sample_features_app/admin/missing_page.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+TinyAdmin.configure do |settings|
+  (settings.sections ||= []).push(
+    slug: 'missing-page',
+    name: 'Missing Page',
+    type: :url,
+    url: '/missing-page'
+  )
+end
diff --git a/extra/sample_features_app/admin/sample_page.rb b/extra/sample_features_app/admin/sample_page.rb
new file mode 100644
index 0000000..51e9362
--- /dev/null
+++ b/extra/sample_features_app/admin/sample_page.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module Admin
+  class SamplePage < TinyAdmin::Views::DefaultLayout
+    def template
+      super do
+        h1 { 'Sample page' }
+        p { 'This is a sample page' }
+      end
+    end
+  end
+end
+
+TinyAdmin.configure do |settings|
+  (settings.sections ||= []).push(
+    slug: 'sample-page',
+    name: 'Sample Page',
+    type: :page,
+    page: Admin::SamplePage
+  )
+end
diff --git a/extra/sample_features_app/admin/sample_page2.rb b/extra/sample_features_app/admin/sample_page2.rb
new file mode 100644
index 0000000..47d57c0
--- /dev/null
+++ b/extra/sample_features_app/admin/sample_page2.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module Admin
+  class SamplePage2 < TinyAdmin::Views::DefaultLayout
+    def template
+      super do
+        h1 { 'Sample page 2' }
+        p { 'This is another sample page' }
+      end
+    end
+  end
+end
+
+TinyAdmin.configure do |settings|
+  (settings.sections ||= []).push(
+    slug: 'sample-page-2',
+    name: 'Sample Page 2',
+    type: :page,
+    page: Admin::SamplePage2
+  )
+end
diff --git a/extra/sample_features_app/app.rb b/extra/sample_features_app/app.rb
new file mode 100644
index 0000000..bed5be2
--- /dev/null
+++ b/extra/sample_features_app/app.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+# --- dependencies -------------------------------------------------------------
+begin
+  require 'bundler/inline'
+rescue LoadError => e
+  abort "#{e} - Bundler version 1.10 or later is required. Please update your Bundler"
+end
+
+gemfile(true) do
+  source 'https://rubygems.org'
+
+  gem 'rack'
+  gem 'rackup'
+  gem 'webrick'
+
+  gem 'tiny_admin', path: '../../'
+end
+
+# --- Sample features application ----------------------------------------------
+Dir[File.expand_path('admin/**/*.rb', __dir__)].each { |f| require f }
+
+TinyAdmin.configure_from_file('./tiny_admin.yml')
+
+Rackup::Server.new(app: TinyAdmin::Router, Port: 3000).start
diff --git a/extra/sample_features_app/tiny_admin.yml b/extra/sample_features_app/tiny_admin.yml
new file mode 100644
index 0000000..2f2b71f
--- /dev/null
+++ b/extra/sample_features_app/tiny_admin.yml
@@ -0,0 +1,14 @@
+---
+root_path: '/'
+root:
+  redirect: sample-page
+extra_styles: >
+  .navbar {
+    background-color: var(--bs-teal);
+  }
+  .main-content {
+    background-color: var(--bs-gray-100);
+  }
+  .main-content a {
+    text-decoration: none;
+  }
