From d3025a0e56da6198a8ecdb352c1e028c685686e5 Mon Sep 17 00:00:00 2001 From: Neil Lalonde Date: Fri, 10 May 2019 15:08:28 -0400 Subject: [PATCH] test widget in post-bottom placement --- .../templates/components/post-bottom-ad.hbs | 1 - .../post-bottom/discourse-adplugin.hbs | 1 - .../discourse/widgets/ad-slot.js.es6 | 194 ++++++++++++++++++ .../discourse/widgets/house-ad.js.es6 | 32 +++ .../initializers/initialize-ad-plugin.js.es6 | 12 +- 5 files changed, 235 insertions(+), 5 deletions(-) delete mode 100644 assets/javascripts/discourse/templates/components/post-bottom-ad.hbs delete mode 100644 assets/javascripts/discourse/templates/connectors/post-bottom/discourse-adplugin.hbs create mode 100644 assets/javascripts/discourse/widgets/ad-slot.js.es6 create mode 100644 assets/javascripts/discourse/widgets/house-ad.js.es6 diff --git a/assets/javascripts/discourse/templates/components/post-bottom-ad.hbs b/assets/javascripts/discourse/templates/components/post-bottom-ad.hbs deleted file mode 100644 index 7709c7c..0000000 --- a/assets/javascripts/discourse/templates/components/post-bottom-ad.hbs +++ /dev/null @@ -1 +0,0 @@ -{{ad-slot placement="post-bottom" category=model.topic.category.slug postNumber=model.post_number}} diff --git a/assets/javascripts/discourse/templates/connectors/post-bottom/discourse-adplugin.hbs b/assets/javascripts/discourse/templates/connectors/post-bottom/discourse-adplugin.hbs deleted file mode 100644 index f0287d1..0000000 --- a/assets/javascripts/discourse/templates/connectors/post-bottom/discourse-adplugin.hbs +++ /dev/null @@ -1 +0,0 @@ -{{post-bottom-ad model=this}} diff --git a/assets/javascripts/discourse/widgets/ad-slot.js.es6 b/assets/javascripts/discourse/widgets/ad-slot.js.es6 new file mode 100644 index 0000000..fdc250c --- /dev/null +++ b/assets/javascripts/discourse/widgets/ad-slot.js.es6 @@ -0,0 +1,194 @@ +import { createWidget } from "discourse/widgets/widget"; +import { h } from "virtual-dom"; + +const adConfig = Ember.Object.create({ + "google-adsense": { + settingPrefix: "adsense", // settings follow naming convention + enabledSetting: "adsense_publisher_code", + nthPost: "adsense_nth_post_code" + }, + "google-dfp-ad": { + settingPrefix: "dfp", // settings follow naming convention + enabledSetting: "dfp_publisher_id", + nthPost: "dfp_nth_post_code" + }, + "amazon-product-links": { + settingPrefix: "amazon", + enabledSetting: false, + nthPost: "amazon_nth_post_code", + desktop: { + "topic-list-top": "amazon_topic_list_top_src_code", + "post-bottom": "amazon_post_bottom_src_code", + "topic-above-post-stream": "amazon_topic_above_post_stream_src_code", + "topic-above-suggested": "amazon_topic_above_suggested_src_code" + }, + mobile: { + "topic-list-top": "amazon_mobile_topic_list_top_src_code", + "post-bottom": "amazon_mobile_post_bottom_src_code", + "topic-above-post-stream": + "amazon_mobile_topic_above_post_stream_src_code", + "topic-above-suggested": "amazon_mobile_topic_above_suggested_src_code" + } + }, + "codefund-ad": { + settingPrefix: "codefund", + enabledSetting: "codefund_property_id", + nthPost: "codefund_nth_post", + desktop: { + "topic-list-top": "codefund_top_of_topic_list_enabled", + "post-bottom": "codefund_below_post_enabled", + "topic-above-post-stream": "codefund_above_post_stream_enabled", + "topic-above-suggested": "codefund_above_suggested_enabled" + } + }, + "carbonads-ad": { + settingPrefix: "carbonads", + enabledSetting: "carbonads_serve_id", + desktop: { + "topic-list-top": "carbonads_topic_list_top_enabled", + "post-bottom": false, + "topic-above-post-stream": "carbonads_above_post_stream_enabled", + "topic-above-suggested": false + } + } +}); + +const displayCounts = { + houseAds: 0, + allAds: 0 +}; + +createWidget("ad-slot", { + tagName: "", + + html(attrs) { + const adsToShow = this.adComponents(); + + let output = []; + + adsToShow.forEach(widgetName => { + output.push(this.attach(widgetName, this.attrs)); + }); + + return output; + }, + + /** + * For a given ad placement and optionally a post number if in between posts, + * list all ad network names that are configured to show there. + */ + availableAdTypes() { + const placement = this.attrs.placement, + postNumber = this.attrs.postNumber; + + let types = []; + const houseAds = this.site.get("house_creatives"), + placeUnderscored = placement.replace(/-/g, "_"); + + if (houseAds && houseAds.settings) { + const adsForSlot = houseAds.settings[placeUnderscored]; + + if ( + Object.keys(houseAds.creatives).length > 0 && + !Ember.isBlank(adsForSlot) && + (!postNumber || + this.isNthPost(parseInt(houseAds.settings.after_nth_post, 10))) + ) { + types.push("house-ad"); + } + } + + Object.keys(adConfig).forEach(adNetwork => { + const config = adConfig[adNetwork]; + let settingNames = null, + name; + + if ( + config.enabledSetting && + !Ember.isBlank(this.siteSettings[config.enabledSetting]) && + (!postNumber || + !config.nthPost || + this.isNthPost(parseInt(this.siteSettings[config.nthPost], 10))) + ) { + if (this.site.mobileView) { + settingNames = config.mobile || config.desktop; + } else { + settingNames = config.desktop; + } + + if (settingNames) { + name = settingNames[placement]; + } + + if (name === undefined) { + // follows naming convention: prefix_(mobile_)_{placement}_code + name = `${config.settingPrefix}_${ + this.site.mobileView ? "mobile_" : "" + }${placeUnderscored}_code`; + } + + if (name !== false && !Ember.isBlank(this.siteSettings[name])) { + types.push(adNetwork); + } + } + }); + + return types; + }, + + /** + * Returns a list of the names of ad components that should be rendered + * in the given ad placement. It handles alternating between house ads + * and other ad networks. + */ + adComponents() { + const placement = this.attrs.placement, + availableAdTypes = this.availableAdTypes(); + + if ( + !availableAdTypes.includes("house-ad") || + availableAdTypes.length === 1 + ) { + // Current behaviour is to allow multiple ads from different networks + // to show in the same place. We could change this to choose one somehow. + return availableAdTypes; + } + + const houseAds = this.site.get("house_creatives"); + let houseAdsSkipped = false; + + if (houseAds.settings.house_ads_frequency === 100) { + // house always wins + return ["house-ad"]; + } else if (houseAds.settings.house_ads_frequency > 0) { + // show house ads the given percent of the time + if ( + displayCounts.allAds === 0 || + (100 * displayCounts.houseAds) / displayCounts.allAds < + houseAds.settings.house_ads_frequency + ) { + displayCounts.houseAds += 1; + displayCounts.allAds += 1; + return ["house-ad"]; + } else { + houseAdsSkipped = true; + } + } + + const networkNames = availableAdTypes.filter(x => x !== "house-ad"); + + if (houseAdsSkipped) { + displayCounts.allAds += networkNames.length; + } + + return networkNames; + }, + + isNthPost(n) { + if (this.attrs.postNumber && n && n > 0) { + return this.attrs.postNumber % n === 0; + } else { + return false; + } + } +}); diff --git a/assets/javascripts/discourse/widgets/house-ad.js.es6 b/assets/javascripts/discourse/widgets/house-ad.js.es6 new file mode 100644 index 0000000..38e6f1f --- /dev/null +++ b/assets/javascripts/discourse/widgets/house-ad.js.es6 @@ -0,0 +1,32 @@ +import { createWidget } from "discourse/widgets/widget"; +import { h } from "virtual-dom"; + +createWidget("house-ad", { + tagName: "", + + html(attrs) { + console.log('house-ad'); + + if (attrs.postNumber % 10 === 0) { + return h( + "div.house-creative.house-post-bottom", + h( + "a.h-create.h-socks", + { href: "#", target: "_blank" }, + h( + "div.container", + h( + "div.tall-image", + h("img", { + src: + "http://localhost:3000/uploads/default/original/1X/14844d926f49c3de68a91188661173f694e6b8bc.jpeg" + }) + ) + ) + ) + ); + } else { + return ''; + } + } +}); diff --git a/assets/javascripts/initializers/initialize-ad-plugin.js.es6 b/assets/javascripts/initializers/initialize-ad-plugin.js.es6 index cd4c40a..1832b79 100644 --- a/assets/javascripts/initializers/initialize-ad-plugin.js.es6 +++ b/assets/javascripts/initializers/initialize-ad-plugin.js.es6 @@ -8,9 +8,15 @@ export default { api.decorateWidget("post:after", dec => { if (dec.canConnectComponent) { if (!dec.attrs.cloaked) { - return dec.connect({ - component: "post-bottom-ad", - context: "model" + // return dec.connect({ + // component: "post-bottom-ad", + // context: "model" + // }); + console.log('initialize attach ad-slot'); + return dec.attach('ad-slot', { + placement: 'post-bottom', + category: 'TODO', + postNumber: dec.attrs.post_number }); } } else {