Store resource
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
ActiveAdmin.register Store do
|
||||
permit_params :name, :catalog_url, :store_repository_url
|
||||
|
||||
menu priority: 5, label: "🛒 Stores"
|
||||
|
||||
index do
|
||||
selectable_column
|
||||
id_column
|
||||
column :name
|
||||
column :catalog_url do |store|
|
||||
link_to store.catalog_url, store.catalog_url, target: "_blank", rel: "noopener"
|
||||
end
|
||||
column :store_repository_url do |store|
|
||||
link_to store.store_repository_url, store.store_repository_url, target: "_blank", rel: "noopener"
|
||||
end
|
||||
column :updated_at
|
||||
actions
|
||||
end
|
||||
|
||||
filter :name
|
||||
filter :catalog_url
|
||||
filter :store_repository_url
|
||||
|
||||
show do
|
||||
attributes_table do
|
||||
row :id
|
||||
row :name
|
||||
row :catalog_url do |store|
|
||||
link_to store.catalog_url, store.catalog_url, target: "_blank", rel: "noopener"
|
||||
end
|
||||
row :store_repository_url do |store|
|
||||
link_to store.store_repository_url, store.store_repository_url, target: "_blank", rel: "noopener"
|
||||
end
|
||||
row :created_at
|
||||
row :updated_at
|
||||
end
|
||||
para do
|
||||
"Listed by GET /api/stores, which the desktop client reads on first run: it " \
|
||||
"takes the config from the store repository and points it at the catalog above."
|
||||
end
|
||||
end
|
||||
|
||||
form do |f|
|
||||
f.inputs do
|
||||
f.input :name, hint: "What the client shows in its store picker"
|
||||
f.input :catalog_url, hint: "Base URL of the WarpEngine catalog, e.g. https://teletypegames.org"
|
||||
f.input :store_repository_url,
|
||||
hint: "Repository holding the store's config.json, e.g. " \
|
||||
"https://git.teletypegames.org/stores/ttg-desktop-store"
|
||||
end
|
||||
f.actions
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,20 @@
|
||||
class Api::StoresController < ApiController
|
||||
resource_description do
|
||||
short "Stores"
|
||||
end
|
||||
|
||||
api :GET, "/api/stores", "List the stores a client can install from"
|
||||
desc <<~DESC
|
||||
The registry the graphical desktop client reads on first run: which catalogs
|
||||
exist, and where each one's store configuration lives. Public on purpose —
|
||||
a client has nobody to log in as.
|
||||
DESC
|
||||
returns code: 200, desc: "Array of stores" do
|
||||
property :name, String, desc: "Display name of the store"
|
||||
property :catalogUrl, String, desc: "Base URL of the WarpEngine catalog it serves"
|
||||
property :storeRepositoryUrl, String, desc: "Repository holding the store's config.json"
|
||||
end
|
||||
def index
|
||||
render json: StoreService.new.index
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,21 @@
|
||||
# A store a client can install from: a WarpEngine catalog, and the repository
|
||||
# holding the store's own configuration.
|
||||
#
|
||||
# This is deliberately not part of WarpEngine. The engine serves one catalog and
|
||||
# has no business knowing which stores exist for it; the registry is a property of
|
||||
# this site, which is what the graphical client asks.
|
||||
class Store < ApplicationRecord
|
||||
URL = %r{\Ahttps?://\S+\z}
|
||||
|
||||
validates :name, presence: true
|
||||
validates :catalog_url, presence: true, format: { with: URL, message: "must be an http(s) URL" }
|
||||
validates :store_repository_url, presence: true, format: { with: URL, message: "must be an http(s) URL" }
|
||||
|
||||
default_scope { where(deleted_at: nil) }
|
||||
|
||||
scope :ordered, -> { order(:name) }
|
||||
|
||||
def self.ransackable_attributes(auth_object = nil)
|
||||
%w[id name catalog_url store_repository_url created_at updated_at]
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,9 @@
|
||||
class StoreSerializer < Blueprinter::Base
|
||||
include WarpEngine::TimestampFields
|
||||
|
||||
field :name
|
||||
# camelCase, as the catalog's own payloads use — one convention for a client
|
||||
# that reads both.
|
||||
field(:catalogUrl) { |store| store.catalog_url }
|
||||
field(:storeRepositoryUrl) { |store| store.store_repository_url }
|
||||
end
|
||||
@@ -0,0 +1,5 @@
|
||||
class StoreService
|
||||
def index
|
||||
StoreSerializer.render_as_hash(Store.ordered)
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user