From 146f2eab7fcc4f27f2f69bb2d55a9775c5e7e059 Mon Sep 17 00:00:00 2001 From: Robin Ward Date: Thu, 20 Aug 2015 13:43:12 -0400 Subject: [PATCH] Can edit settings on the embedding page --- .../admin/components/embedding-setting.js.es6 | 23 ++++++ .../admin/components/highlighted-code.js.es6 | 12 +++ .../admin/controllers/admin-embedding.js.es6 | 39 +++++++++- .../components/embedding-setting.hbs | 11 +++ .../templates/components/highlighted-code.hbs | 1 + .../javascripts/admin/templates/embedding.hbs | 74 +++++++++++++++---- .../stylesheets/common/admin/admin_base.scss | 30 ++++++++ app/controllers/admin/embedding_controller.rb | 18 +++-- app/models/embedding.rb | 41 ++++++++++ app/serializers/embedding_serializer.rb | 12 ++- config/locales/client.en.yml | 17 +++++ config/site_settings.yml | 29 ++++++-- 12 files changed, 277 insertions(+), 30 deletions(-) create mode 100644 app/assets/javascripts/admin/components/embedding-setting.js.es6 create mode 100644 app/assets/javascripts/admin/components/highlighted-code.js.es6 create mode 100644 app/assets/javascripts/admin/templates/components/embedding-setting.hbs create mode 100644 app/assets/javascripts/admin/templates/components/highlighted-code.hbs create mode 100644 app/models/embedding.rb diff --git a/app/assets/javascripts/admin/components/embedding-setting.js.es6 b/app/assets/javascripts/admin/components/embedding-setting.js.es6 new file mode 100644 index 000000000..904afacfe --- /dev/null +++ b/app/assets/javascripts/admin/components/embedding-setting.js.es6 @@ -0,0 +1,23 @@ +import computed from 'ember-addons/ember-computed-decorators'; + +export default Ember.Component.extend({ + classNames: ['embed-setting'], + + @computed('field') + inputId(field) { return field.dasherize(); }, + + @computed('field') + translationKey(field) { return `admin.embedding.${field}`; }, + + @computed('type') + isCheckbox(type) { return type === "checkbox"; }, + + @computed('value') + checked: { + get(value) { return !!value; }, + set(value) { + this.set('value', value); + return value; + } + } +}); diff --git a/app/assets/javascripts/admin/components/highlighted-code.js.es6 b/app/assets/javascripts/admin/components/highlighted-code.js.es6 new file mode 100644 index 000000000..4fc413fd8 --- /dev/null +++ b/app/assets/javascripts/admin/components/highlighted-code.js.es6 @@ -0,0 +1,12 @@ +import { on, observes } from 'ember-addons/ember-computed-decorators'; +import highlightSyntax from 'discourse/lib/highlight-syntax'; + +export default Ember.Component.extend({ + + @on('didInsertElement') + @observes('code') + _refresh: function() { + highlightSyntax(this.$()); + } + +}); diff --git a/app/assets/javascripts/admin/controllers/admin-embedding.js.es6 b/app/assets/javascripts/admin/controllers/admin-embedding.js.es6 index d0e554831..780c61f3f 100644 --- a/app/assets/javascripts/admin/controllers/admin-embedding.js.es6 +++ b/app/assets/javascripts/admin/controllers/admin-embedding.js.es6 @@ -1,9 +1,46 @@ +import computed from 'ember-addons/ember-computed-decorators'; +import { popupAjaxError } from 'discourse/lib/ajax-error'; + export default Ember.Controller.extend({ + saved: false, embedding: null, + // show settings if we have at least one created host + @computed('embedding.embeddable_hosts.@each.isCreated') + showSecondary() { + const hosts = this.get('embedding.embeddable_hosts'); + return hosts.length && hosts.findProperty('isCreated'); + }, + + @computed('embedding.base_url') + embeddingCode(baseUrl) { + + const html = +`
+ +`; + + return html; + }, + actions: { saveChanges() { - this.get('embedding').update({}); + const embedding = this.get('embedding'); + const updates = embedding.getProperties(embedding.get('fields')); + + this.set('saved', false); + this.get('embedding').update(updates).then(() => { + this.set('saved', true); + }).catch(popupAjaxError); }, addHost() { diff --git a/app/assets/javascripts/admin/templates/components/embedding-setting.hbs b/app/assets/javascripts/admin/templates/components/embedding-setting.hbs new file mode 100644 index 000000000..36dbb8869 --- /dev/null +++ b/app/assets/javascripts/admin/templates/components/embedding-setting.hbs @@ -0,0 +1,11 @@ +{{#if isCheckbox}} + +{{else}} + + {{input value=value id=inputId}} +{{/if}} + +
diff --git a/app/assets/javascripts/admin/templates/components/highlighted-code.hbs b/app/assets/javascripts/admin/templates/components/highlighted-code.hbs new file mode 100644 index 000000000..4d67dd6fd --- /dev/null +++ b/app/assets/javascripts/admin/templates/components/highlighted-code.hbs @@ -0,0 +1 @@ +
{{code}}
diff --git a/app/assets/javascripts/admin/templates/embedding.hbs b/app/assets/javascripts/admin/templates/embedding.hbs index 838e3e8e9..15d021a9c 100644 --- a/app/assets/javascripts/admin/templates/embedding.hbs +++ b/app/assets/javascripts/admin/templates/embedding.hbs @@ -1,15 +1,61 @@ -{{#if embedding.embeddable_hosts}} - - - - - - - {{#each embedding.embeddable_hosts as |host|}} - {{embeddable-host host=host deleteHost="deleteHost"}} - {{/each}} -
{{i18n "admin.embedding.host"}}{{i18n "admin.embedding.category"}} 
+
+ {{#if embedding.embeddable_hosts}} + + + + + + + {{#each embedding.embeddable_hosts as |host|}} + {{embeddable-host host=host deleteHost="deleteHost"}} + {{/each}} +
{{i18n "admin.embedding.host"}}{{i18n "admin.embedding.category"}} 
+ {{else}} +

{{i18n "admin.embedding.get_started"}}

+ {{/if}} + + {{d-button label="admin.embedding.add_host" action="addHost" icon="plus" class="btn-primary add-host"}} +
+ +{{#if showSecondary}} +
+

{{{i18n "admin.embedding.sample"}}}

+ {{highlighted-code code=embeddingCode lang="html"}} +
+ +
+ +
+

{{i18n "admin.embedding.settings"}}

+ + {{embedding-setting field="embed_by_username" value=embedding.embed_by_username}} + {{embedding-setting field="embed_post_limit" value=embedding.embed_post_limit}} + {{embedding-setting field="embed_truncate" value=embedding.embed_truncate type="checkbox"}} +
+ +
+

{{i18n "admin.embedding.feed_settings"}}

+

{{i18n "admin.embedding.feed_description"}}

+ + {{embedding-setting field="feed_polling_enabled" value=embedding.feed_polling_enabled type="checkbox"}} + {{embedding-setting field="feed_polling_url" value=embedding.feed_polling_url}} + {{embedding-setting field="embed_username_key_from_feed" value=embedding.embed_username_key_from_feed}} +
+ +
+

{{i18n "admin.embedding.crawling_settings"}}

+

{{i18n "admin.embedding.crawling_description"}}

+ + {{embedding-setting field="embed_whitelist_selector" value=embedding.embed_whitelist_selector}} + {{embedding-setting field="embed_blacklist_selector" value=embedding.embed_blacklist_selector}} +
+ +
+ {{d-button label="admin.embedding.save" + action="saveChanges" + class="btn-primary embed-save" + disabled=embedding.isSaving}} + + {{#if saved}}{{i18n "saved"}}{{/if}} +
{{/if}} - -{{d-button label="admin.embedding.add_host" action="addHost" icon="plus" class="btn-primary"}} - diff --git a/app/assets/stylesheets/common/admin/admin_base.scss b/app/assets/stylesheets/common/admin/admin_base.scss index a988f5438..f58a79f1e 100644 --- a/app/assets/stylesheets/common/admin/admin_base.scss +++ b/app/assets/stylesheets/common/admin/admin_base.scss @@ -1648,6 +1648,36 @@ table#user-badges { margin-bottom: 10px; } + +// embedding + +.embeddable-hosts { + table { + margin-bottom: 1em; + } + margin-bottom: 2em; +} + +.embedding-secondary { + h3 { + margin: 1em 0; + } + margin-bottom: 2em; + + .embed-setting { + input[type=text] { + width: 50%; + } + margin: 0.75em 0; + } + + p.description { + color: dark-light-choose(scale-color($primary, $lightness: 50%), scale-color($secondary, $lightness: 50%)); + margin-bottom: 1em; + max-width: 700px; + } +} + // Mobile specific styles // Mobile view text-inputs need some padding .mobile-view .admin-contents { diff --git a/app/controllers/admin/embedding_controller.rb b/app/controllers/admin/embedding_controller.rb index 656ff25af..623c2a25a 100644 --- a/app/controllers/admin/embedding_controller.rb +++ b/app/controllers/admin/embedding_controller.rb @@ -1,3 +1,5 @@ +require_dependency 'embedding' + class Admin::EmbeddingController < Admin::AdminController before_filter :ensure_logged_in, :ensure_staff, :fetch_embedding @@ -7,15 +9,21 @@ class Admin::EmbeddingController < Admin::AdminController end def update - render_serialized(@embedding, EmbeddingSerializer, root: 'embedding', rest_serializer: true) + Embedding.settings.each do |s| + @embedding.send("#{s}=", params[:embedding][s]) + end + + if @embedding.save + fetch_embedding + render_serialized(@embedding, EmbeddingSerializer, root: 'embedding', rest_serializer: true) + else + render_json_error(@embedding) + end end protected def fetch_embedding - @embedding = OpenStruct.new({ - id: 'default', - embeddable_hosts: EmbeddableHost.all.order(:host) - }) + @embedding = Embedding.find end end diff --git a/app/models/embedding.rb b/app/models/embedding.rb new file mode 100644 index 000000000..c6081b189 --- /dev/null +++ b/app/models/embedding.rb @@ -0,0 +1,41 @@ +require 'has_errors' + +class Embedding < OpenStruct + include HasErrors + + def self.settings + %i(embed_by_username + embed_post_limit + embed_truncate + embed_whitelist_selector + embed_blacklist_selector + feed_polling_enabled + feed_polling_url + embed_username_key_from_feed) + end + + def base_url + Discourse.base_url + end + + def save + Embedding.settings.each do |s| + SiteSetting.send("#{s}=", send(s)) + end + true + rescue Discourse::InvalidParameters => p + errors.add :base, p.to_s + false + end + + def embeddable_hosts + EmbeddableHost.all.order(:host) + end + + def self.find + embedding_args = { id: 'default' } + + Embedding.settings.each {|s| embedding_args[s] = SiteSetting.send(s) } + Embedding.new(embedding_args) + end +end diff --git a/app/serializers/embedding_serializer.rb b/app/serializers/embedding_serializer.rb index 041357356..dda224edc 100644 --- a/app/serializers/embedding_serializer.rb +++ b/app/serializers/embedding_serializer.rb @@ -1,8 +1,14 @@ class EmbeddingSerializer < ApplicationSerializer - attributes :id + attributes :id, :fields, :base_url + attributes *Embedding.settings + has_many :embeddable_hosts, serializer: EmbeddableHostSerializer, embed: :ids - def id - object.id + def fields + Embedding.settings + end + + def read_attribute_for_serialization(attr) + object.respond_to?(attr) ? object.send(attr) : send(attr) end end diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 5ff7e9198..520b881c7 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -2492,12 +2492,29 @@ en: delete_confirm: "Are you sure you want to delete the :%{name}: emoji?" embedding: + get_started: "If you'd like to embed Discourse on another website, begin by adding its host." confirm_delete: "Are you sure you want to delete that host?" + sample: "Use the following HTML code into your site to create and embed discourse topics. Replace REPLACE_ME with the canonical URL of the page you are embedding it on." title: "Embedding" host: "Allowed Hosts" edit: "edit" category: "Post to Category" add_host: "Add Host" + settings: "Embedding Settings" + feed_settings: "Feed Settings" + feed_description: "Providing an RSS/ATOM feed for your site can improve Discourse's ability to import your content." + crawling_settings: "Crawler Settings" + crawling_description: "When Discourse creates topics for your posts, if no RSS/ATOM feed is present it will attempt to parse your content out of your HTML. Sometimes it can be challenging to extract your content, so we provide the ability to specify CSS rules to make extraction easier." + + embed_by_username: "Username for topic creation" + embed_post_limit: "Maximum number of posts to embed" + embed_username_key_from_feed: "Key to pull discourse username from feed" + embed_truncate: "Truncate the embedded posts" + embed_whitelist_selector: "CSS selector for elements that are allowed in embeds" + embed_blacklist_selector: "CSS selector for elements that are removed from embeds" + feed_polling_enabled: "Import posts via RSS/ATOM" + feed_polling_url: "URL of RSS/ATOM feed to crawl" + save: "Save Embedding Settings" permalink: title: "Permalinks" diff --git a/config/site_settings.yml b/config/site_settings.yml index 4e5b60d5e..c63954392 100644 --- a/config/site_settings.yml +++ b/config/site_settings.yml @@ -759,16 +759,31 @@ developer: default: false embedding: - feed_polling_enabled: false - feed_polling_url: '' + feed_polling_enabled: + default: false + hidden: true + feed_polling_url: + default: '' + hidden: true embed_by_username: default: '' type: username - embed_username_key_from_feed: '' - embed_post_limit: 100 - embed_truncate: false - embed_whitelist_selector: '' - embed_blacklist_selector: '' + hidden: true + embed_username_key_from_feed: + default: '' + hidden: true + embed_post_limit: + default: 100 + hidden: true + embed_truncate: + default: false + hidden: true + embed_whitelist_selector: + default: '' + hidden: true + embed_blacklist_selector: + default: '' + hidden: true legal: tos_url: