commit: 9239e4ce4d4e958e62552d4a01183d0295c020f5
parent: 06f26e09b4bff120181eaaeb70a833482368ea63
Author: Eugen Rochko <eugen@zeonfederated.com>
Date: Thu, 14 Sep 2017 00:04:30 +0200
Uploads for admin site settings (#4913)
* Improve OpenGraph tags for about pages
* Add thumbnail admin setting
* Fix error
* Fix up
Diffstat:
16 files changed, 123 insertions(+), 28 deletions(-)
diff --git a/app/controllers/admin/settings_controller.rb b/app/controllers/admin/settings_controller.rb
@@ -14,6 +14,7 @@ module Admin
open_deletion
timeline_preview
bootstrap_timeline_accounts
+ thumbnail
).freeze
BOOLEAN_SETTINGS = %w(
@@ -22,14 +23,23 @@ module Admin
timeline_preview
).freeze
+ UPLOAD_SETTINGS = %w(
+ thumbnail
+ ).freeze
+
def edit
@admin_settings = Form::AdminSettings.new
end
def update
settings_params.each do |key, value|
- setting = Setting.where(var: key).first_or_initialize(var: key)
- setting.update(value: value_for_update(key, value))
+ if UPLOAD_SETTINGS.include?(key)
+ upload = SiteUpload.where(var: key).first_or_initialize(var: key)
+ upload.update(file: value)
+ else
+ setting = Setting.where(var: key).first_or_initialize(var: key)
+ setting.update(value: value_for_update(key, value))
+ end
end
flash[:notice] = I18n.t('generic.changes_saved_msg')
diff --git a/app/javascript/images/mastodon_small.jpg b/app/javascript/images/mastodon_small.jpg
Binary files differ.
diff --git a/app/javascript/images/preview.jpg b/app/javascript/images/preview.jpg
Binary files differ.
diff --git a/app/models/site_upload.rb b/app/models/site_upload.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+# == Schema Information
+#
+# Table name: site_uploads
+#
+# id :integer not null, primary key
+# var :string default(""), not null
+# file_file_name :string
+# file_content_type :string
+# file_file_size :integer
+# file_updated_at :datetime
+# meta :json
+# created_at :datetime not null
+# updated_at :datetime not null
+#
+
+class SiteUpload < ApplicationRecord
+ has_attached_file :file
+
+ validates_attachment_content_type :file, content_type: /\Aimage\/.*\z/
+ validates :var, presence: true, uniqueness: true
+
+ before_save :set_meta
+ after_commit :clear_cache
+
+ def cache_key
+ "site_uploads/#{var}"
+ end
+
+ private
+
+ def set_meta
+ tempfile = file.queued_for_write[:original]
+
+ return if tempfile.nil?
+
+ geometry = Paperclip::Geometry.from_file(tempfile)
+ self.meta = { width: geometry.width.to_i, height: geometry.height.to_i }
+ end
+
+ def clear_cache
+ Rails.cache.delete(cache_key)
+ end
+end
diff --git a/app/presenters/instance_presenter.rb b/app/presenters/instance_presenter.rb
@@ -35,4 +35,8 @@ class InstancePresenter
def source_url
Mastodon::Version.source_url
end
+
+ def thumbnail
+ @thumbnail ||= Rails.cache.fetch('site_uploads/thumbnail') { SiteUpload.find_by(var: 'thumbnail') }
+ end
end
diff --git a/app/serializers/rest/instance_serializer.rb b/app/serializers/rest/instance_serializer.rb
@@ -1,8 +1,10 @@
# frozen_string_literal: true
class REST::InstanceSerializer < ActiveModel::Serializer
+ include RoutingHelper
+
attributes :uri, :title, :description, :email,
- :version, :urls, :stats
+ :version, :urls, :stats, :thumbnail
def uri
Rails.configuration.x.local_domain
@@ -24,6 +26,10 @@ class REST::InstanceSerializer < ActiveModel::Serializer
Mastodon::Version.to_s
end
+ def thumbnail
+ full_asset_url(instance_presenter.thumbnail.file.url) if instance_presenter.thumbnail
+ end
+
def stats
{
user_count: instance_presenter.user_count,
diff --git a/app/views/about/_og.html.haml b/app/views/about/_og.html.haml
@@ -0,0 +1,10 @@
+- thumbnail = @instance_presenter.thumbnail
+= opengraph 'og:site_name', t('about.hosted_on', domain: site_hostname)
+= opengraph 'og:url', about_url
+= opengraph 'og:type', 'website'
+= opengraph 'og:title', @instance_presenter.site_title
+= opengraph 'og:description', strip_tags(@instance_presenter.site_description.presence || t('about.about_mastodon_html'))
+= opengraph 'og:image', full_asset_url(thumbnail&.file&.url || asset_pack_path('preview.jpg', protocol: :request))
+= opengraph 'og:image:width', thumbnail ? thumbnail.meta['width'] : '1200'
+= opengraph 'og:image:height', thumbnail ? thumbnail.meta['height'] : '630'
+= opengraph 'twitter:card', 'summary_large_image'
diff --git a/app/views/about/more.html.haml b/app/views/about/more.html.haml
@@ -3,16 +3,7 @@
- content_for :header_tags do
= javascript_pack_tag 'public', integrity: true, crossorigin: 'anonymous'
-
- %meta{ property: 'og:site_name', content: site_title }/
- %meta{ property: 'og:url', content: about_url }/
- %meta{ property: 'og:type', content: 'website' }/
- %meta{ property: 'og:title', content: site_hostname }/
- %meta{ property: 'og:description', content: strip_tags(@instance_presenter.site_description.presence || t('about.about_mastodon_html')) }/
- %meta{ property: 'og:image', content: asset_pack_path('mastodon_small.jpg', protocol: :request) }/
- %meta{ property: 'og:image:width', content: '400' }/
- %meta{ property: 'og:image:height', content: '400' }/
- %meta{ property: 'twitter:card', content: 'summary' }/
+ = render partial: 'og'
.landing-page
.header-wrapper.compact
diff --git a/app/views/about/show.html.haml b/app/views/about/show.html.haml
@@ -4,16 +4,7 @@
- content_for :header_tags do
%script#initial-state{ type: 'application/json' }!= json_escape(@initial_state_json)
= javascript_pack_tag 'about', integrity: true, crossorigin: 'anonymous'
-
- %meta{ property: 'og:site_name', content: site_title }/
- %meta{ property: 'og:url', content: about_url }/
- %meta{ property: 'og:type', content: 'website' }/
- %meta{ property: 'og:title', content: site_hostname }/
- %meta{ property: 'og:description', content: strip_tags(@instance_presenter.site_description.presence || t('about.about_mastodon_html')) }/
- %meta{ property: 'og:image', content: asset_pack_path('mastodon_small.jpg', protocol: :request) }/
- %meta{ property: 'og:image:width', content: '400' }/
- %meta{ property: 'og:image:height', content: '400' }/
- %meta{ property: 'twitter:card', content: 'summary' }/
+ = render partial: 'og'
.landing-page
.header-wrapper
diff --git a/app/views/admin/settings/edit.html.haml b/app/views/admin/settings/edit.html.haml
@@ -11,6 +11,11 @@
%hr/
.fields-group
+ = f.input :thumbnail, as: :file, wrapper: :with_block_label, label: t('admin.settings.thumbnail.title'), hint: t('admin.settings.thumbnail.desc_html')
+
+ %hr/
+
+ .fields-group
= f.input :timeline_preview, as: :boolean, wrapper: :with_label, label: t('admin.settings.timeline_preview.title'), hint: t('admin.settings.timeline_preview.desc_html')
.fields-group
diff --git a/config/locales/en.yml b/config/locales/en.yml
@@ -195,6 +195,9 @@ en:
desc_html: You can write your own privacy policy, terms of service or other legalese. You can use HTML tags
title: Custom terms of service
site_title: Instance name
+ thumbnail:
+ desc_html: Used for previews via OpenGraph and API. 1200x630px recommended
+ title: Instance thumbnail
timeline_preview:
desc_html: Display public timeline on landing page
title: Timeline preview
diff --git a/db/migrate/20170913000752_create_site_uploads.rb b/db/migrate/20170913000752_create_site_uploads.rb
@@ -0,0 +1,10 @@
+class CreateSiteUploads < ActiveRecord::Migration[5.1]
+ def change
+ create_table :site_uploads do |t|
+ t.string :var, default: '', null: false, index: { unique: true }
+ t.attachment :file
+ t.json :meta
+ t.timestamps
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20170905165803) do
+ActiveRecord::Schema.define(version: 20170913000752) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -288,6 +288,18 @@ ActiveRecord::Schema.define(version: 20170905165803) do
t.index ["thing_type", "thing_id", "var"], name: "index_settings_on_thing_type_and_thing_id_and_var", unique: true
end
+ create_table "site_uploads", force: :cascade do |t|
+ t.string "var", default: "", null: false
+ t.string "file_file_name"
+ t.string "file_content_type"
+ t.integer "file_file_size"
+ t.datetime "file_updated_at"
+ t.json "meta"
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ t.index ["var"], name: "index_site_uploads_on_var", unique: true
+ end
+
create_table "status_pins", force: :cascade do |t|
t.bigint "account_id", null: false
t.bigint "status_id", null: false
diff --git a/spec/fabricators/site_upload_fabricator.rb b/spec/fabricators/site_upload_fabricator.rb
@@ -0,0 +1,3 @@
+Fabricator(:site_upload) do
+
+end
diff --git a/spec/models/site_upload_spec.rb b/spec/models/site_upload_spec.rb
@@ -0,0 +1,5 @@
+require 'rails_helper'
+
+RSpec.describe SiteUpload, type: :model do
+
+end
diff --git a/spec/views/about/show.html.haml_spec.rb b/spec/views/about/show.html.haml_spec.rb
@@ -15,15 +15,16 @@ describe 'about/show.html.haml', without_verify_partial_doubles: true do
version_number: '1.0',
source_url: 'https://github.com/tootsuite/mastodon',
open_registrations: false,
+ thumbnail: nil,
closed_registrations_message: 'yes')
assign(:instance_presenter, instance_presenter)
render
header_tags = view.content_for(:header_tags)
- expect(header_tags).to match(%r{<meta content='.+' property='og:title'>})
- expect(header_tags).to match(%r{<meta content='website' property='og:type'>})
- expect(header_tags).to match(%r{<meta content='.+' property='og:image'>})
- expect(header_tags).to match(%r{<meta content='http://.+' property='og:url'>})
+ expect(header_tags).to match(%r{<meta content=".+" property="og:title" />})
+ expect(header_tags).to match(%r{<meta content="website" property="og:type" />})
+ expect(header_tags).to match(%r{<meta content=".+" property="og:image" />})
+ expect(header_tags).to match(%r{<meta content="http://.+" property="og:url" />})
end
end