forked from fedi/mastodon
Uploads for admin site settings (#4913)
* Improve OpenGraph tags for about pages * Add thumbnail admin setting * Fix error * Fix up
This commit is contained in:
parent
06f26e09b4
commit
9239e4ce4d
|
@ -14,6 +14,7 @@ module Admin
|
||||||
open_deletion
|
open_deletion
|
||||||
timeline_preview
|
timeline_preview
|
||||||
bootstrap_timeline_accounts
|
bootstrap_timeline_accounts
|
||||||
|
thumbnail
|
||||||
).freeze
|
).freeze
|
||||||
|
|
||||||
BOOLEAN_SETTINGS = %w(
|
BOOLEAN_SETTINGS = %w(
|
||||||
|
@ -22,15 +23,24 @@ module Admin
|
||||||
timeline_preview
|
timeline_preview
|
||||||
).freeze
|
).freeze
|
||||||
|
|
||||||
|
UPLOAD_SETTINGS = %w(
|
||||||
|
thumbnail
|
||||||
|
).freeze
|
||||||
|
|
||||||
def edit
|
def edit
|
||||||
@admin_settings = Form::AdminSettings.new
|
@admin_settings = Form::AdminSettings.new
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
settings_params.each do |key, value|
|
settings_params.each do |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 = Setting.where(var: key).first_or_initialize(var: key)
|
||||||
setting.update(value: value_for_update(key, value))
|
setting.update(value: value_for_update(key, value))
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
flash[:notice] = I18n.t('generic.changes_saved_msg')
|
flash[:notice] = I18n.t('generic.changes_saved_msg')
|
||||||
redirect_to edit_admin_settings_path
|
redirect_to edit_admin_settings_path
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 25 KiB |
BIN
app/javascript/images/preview.jpg
Normal file
BIN
app/javascript/images/preview.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 285 KiB |
44
app/models/site_upload.rb
Normal file
44
app/models/site_upload.rb
Normal file
|
@ -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
|
|
@ -35,4 +35,8 @@ class InstancePresenter
|
||||||
def source_url
|
def source_url
|
||||||
Mastodon::Version.source_url
|
Mastodon::Version.source_url
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def thumbnail
|
||||||
|
@thumbnail ||= Rails.cache.fetch('site_uploads/thumbnail') { SiteUpload.find_by(var: 'thumbnail') }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class REST::InstanceSerializer < ActiveModel::Serializer
|
class REST::InstanceSerializer < ActiveModel::Serializer
|
||||||
|
include RoutingHelper
|
||||||
|
|
||||||
attributes :uri, :title, :description, :email,
|
attributes :uri, :title, :description, :email,
|
||||||
:version, :urls, :stats
|
:version, :urls, :stats, :thumbnail
|
||||||
|
|
||||||
def uri
|
def uri
|
||||||
Rails.configuration.x.local_domain
|
Rails.configuration.x.local_domain
|
||||||
|
@ -24,6 +26,10 @@ class REST::InstanceSerializer < ActiveModel::Serializer
|
||||||
Mastodon::Version.to_s
|
Mastodon::Version.to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def thumbnail
|
||||||
|
full_asset_url(instance_presenter.thumbnail.file.url) if instance_presenter.thumbnail
|
||||||
|
end
|
||||||
|
|
||||||
def stats
|
def stats
|
||||||
{
|
{
|
||||||
user_count: instance_presenter.user_count,
|
user_count: instance_presenter.user_count,
|
||||||
|
|
10
app/views/about/_og.html.haml
Normal file
10
app/views/about/_og.html.haml
Normal file
|
@ -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'
|
|
@ -3,16 +3,7 @@
|
||||||
|
|
||||||
- content_for :header_tags do
|
- content_for :header_tags do
|
||||||
= javascript_pack_tag 'public', integrity: true, crossorigin: 'anonymous'
|
= javascript_pack_tag 'public', integrity: true, crossorigin: 'anonymous'
|
||||||
|
= render partial: 'og'
|
||||||
%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' }/
|
|
||||||
|
|
||||||
.landing-page
|
.landing-page
|
||||||
.header-wrapper.compact
|
.header-wrapper.compact
|
||||||
|
|
|
@ -4,16 +4,7 @@
|
||||||
- content_for :header_tags do
|
- content_for :header_tags do
|
||||||
%script#initial-state{ type: 'application/json' }!= json_escape(@initial_state_json)
|
%script#initial-state{ type: 'application/json' }!= json_escape(@initial_state_json)
|
||||||
= javascript_pack_tag 'about', integrity: true, crossorigin: 'anonymous'
|
= javascript_pack_tag 'about', integrity: true, crossorigin: 'anonymous'
|
||||||
|
= render partial: 'og'
|
||||||
%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' }/
|
|
||||||
|
|
||||||
.landing-page
|
.landing-page
|
||||||
.header-wrapper
|
.header-wrapper
|
||||||
|
|
|
@ -10,6 +10,11 @@
|
||||||
|
|
||||||
%hr/
|
%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
|
.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')
|
= f.input :timeline_preview, as: :boolean, wrapper: :with_label, label: t('admin.settings.timeline_preview.title'), hint: t('admin.settings.timeline_preview.desc_html')
|
||||||
|
|
||||||
|
|
|
@ -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
|
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
|
title: Custom terms of service
|
||||||
site_title: Instance name
|
site_title: Instance name
|
||||||
|
thumbnail:
|
||||||
|
desc_html: Used for previews via OpenGraph and API. 1200x630px recommended
|
||||||
|
title: Instance thumbnail
|
||||||
timeline_preview:
|
timeline_preview:
|
||||||
desc_html: Display public timeline on landing page
|
desc_html: Display public timeline on landing page
|
||||||
title: Timeline preview
|
title: Timeline preview
|
||||||
|
|
10
db/migrate/20170913000752_create_site_uploads.rb
Normal file
10
db/migrate/20170913000752_create_site_uploads.rb
Normal file
|
@ -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
|
14
db/schema.rb
14
db/schema.rb
|
@ -10,7 +10,7 @@
|
||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# 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
|
# These are extensions that must be enabled in order to support this database
|
||||||
enable_extension "plpgsql"
|
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
|
t.index ["thing_type", "thing_id", "var"], name: "index_settings_on_thing_type_and_thing_id_and_var", unique: true
|
||||||
end
|
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|
|
create_table "status_pins", force: :cascade do |t|
|
||||||
t.bigint "account_id", null: false
|
t.bigint "account_id", null: false
|
||||||
t.bigint "status_id", null: false
|
t.bigint "status_id", null: false
|
||||||
|
|
3
spec/fabricators/site_upload_fabricator.rb
Normal file
3
spec/fabricators/site_upload_fabricator.rb
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
Fabricator(:site_upload) do
|
||||||
|
|
||||||
|
end
|
5
spec/models/site_upload_spec.rb
Normal file
5
spec/models/site_upload_spec.rb
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe SiteUpload, type: :model do
|
||||||
|
|
||||||
|
end
|
|
@ -15,15 +15,16 @@ describe 'about/show.html.haml', without_verify_partial_doubles: true do
|
||||||
version_number: '1.0',
|
version_number: '1.0',
|
||||||
source_url: 'https://github.com/tootsuite/mastodon',
|
source_url: 'https://github.com/tootsuite/mastodon',
|
||||||
open_registrations: false,
|
open_registrations: false,
|
||||||
|
thumbnail: nil,
|
||||||
closed_registrations_message: 'yes')
|
closed_registrations_message: 'yes')
|
||||||
assign(:instance_presenter, instance_presenter)
|
assign(:instance_presenter, instance_presenter)
|
||||||
render
|
render
|
||||||
|
|
||||||
header_tags = view.content_for(:header_tags)
|
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=".+" property="og:title" />})
|
||||||
expect(header_tags).to match(%r{<meta content='website' property='og:type'>})
|
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=".+" property="og:image" />})
|
||||||
expect(header_tags).to match(%r{<meta content='http://.+' property='og:url'>})
|
expect(header_tags).to match(%r{<meta content="http://.+" property="og:url" />})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue