Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FIX: Don't render the connector when we shouldn't display an ad in the topic list item. #146

Merged
merged 1 commit into from Jul 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
18 changes: 6 additions & 12 deletions assets/javascripts/discourse/components/ad-component.js
Expand Up @@ -2,6 +2,10 @@ import Component from "@ember/component";
import { inject as service } from "@ember/service";
import { alias, or } from "@ember/object/computed";
import discourseComputed from "discourse-common/utils/decorators";
import {
isNthPost,
isNthTopicListItem,
} from "discourse/plugins/discourse-adplugin/discourse/helpers/slot-position";

export default Component.extend({
router: service(),
Expand Down Expand Up @@ -93,20 +97,10 @@ export default Component.extend({
},

isNthPost(n) {
if (n && n > 0) {
return this.get("postNumber") % n === 0;
} else {
return false;
}
return isNthPost(n, this.get("postNumber"));
},

isNthTopicListItem(n) {
let indexNumber = this.get("indexNumber");
indexNumber = indexNumber + 1;
if (n && n > 0 && indexNumber > 0) {
return indexNumber % n === 0;
} else {
return false;
}
return isNthTopicListItem(n, this.get("indexNumber"));
},
});
195 changes: 110 additions & 85 deletions assets/javascripts/discourse/components/ad-slot.js
Expand Up @@ -2,6 +2,10 @@ import EmberObject from "@ember/object";
import AdComponent from "discourse/plugins/discourse-adplugin/discourse/components/ad-component";
import discourseComputed, { observes } from "discourse-common/utils/decorators";
import { isBlank } from "@ember/utils";
import {
isNthPost,
isNthTopicListItem,
} from "discourse/plugins/discourse-adplugin/discourse/helpers/slot-position";

const adConfig = EmberObject.create({
"google-adsense": {
Expand Down Expand Up @@ -66,83 +70,125 @@ const displayCounts = {
allAds: 0,
};

export default AdComponent.extend({
needsUpdate: false,
tagName: "",
function _isNetworkAvailable(siteSettings, enabledNetworkSettingName) {
// False means there's no setting to enable or disable this ad network.
// Assume it's always enabled.
if (enabledNetworkSettingName === false) {
return true;
} else {
return (
enabledNetworkSettingName &&
!isBlank(siteSettings[enabledNetworkSettingName])
);
}
}

function _shouldPlaceAdInSlot(
siteSettings,
currentPostNumber,
positionToPlace
) {
return (
!currentPostNumber ||
!positionToPlace ||
isNthPost(parseInt(siteSettings[positionToPlace], 10), currentPostNumber)
);
}

export function slotContenders(
site,
siteSettings,
placement,
postNumber,
indexNumber
) {
let types = [];
const houseAds = site.get("house_creatives"),
placeUnderscored = placement.replace(/-/g, "_");

if (houseAds && houseAds.settings) {
const adsForSlot = houseAds.settings[placeUnderscored];

const adAvailable =
Object.keys(houseAds.creatives).length > 0 && !isBlank(adsForSlot);

// postNumber and indexNumber are both null for topic-list-top, topic-above-post-stream,
// and topic-above-suggested placements. Assume we want to place an ad outside the topic list.
const notPlacingBetweenTopics = !postNumber && !indexNumber;

const canBePlacedInBetweenTopics =
placeUnderscored === "topic_list_between" &&
isNthTopicListItem(
parseInt(houseAds.settings.after_nth_topic, 10),
indexNumber
);

/**
* 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.
*/
@discourseComputed("placement", "postNumber", "indexNumber")
availableAdTypes(placement, postNumber, indexNumber) {
let types = [];
const houseAds = this.site.get("house_creatives"),
placeUnderscored = placement.replace(/-/g, "_");
if (
adAvailable &&
(notPlacingBetweenTopics ||
canBePlacedInBetweenTopics ||
isNthPost(parseInt(houseAds.settings.after_nth_post, 10), postNumber))
) {
types.push("house-ad");
}
}

if (houseAds && houseAds.settings) {
const adsForSlot = houseAds.settings[placeUnderscored];
Object.keys(adConfig).forEach((adNetwork) => {
const config = adConfig[adNetwork];
let settingNames = null,
name;

const adAvailable =
Object.keys(houseAds.creatives).length > 0 && !isBlank(adsForSlot);
if (
_isNetworkAvailable(siteSettings, config.enabledSetting) &&
_shouldPlaceAdInSlot(siteSettings, postNumber, config.nthPost)
) {
if (site.mobileView) {
settingNames = config.mobile || config.desktop;
} else {
settingNames = config.desktop;
}

// postNumber and indexNumber are both null for topic-list-top, topic-above-post-stream,
// and topic-above-suggested placements. Assume we want to place an ad outside the topic list.
const notPlacingBetweenTopics = !postNumber && !indexNumber;
if (settingNames) {
name = settingNames[placement];
}

const canBePlacedInBetweenTopics =
placeUnderscored === "topic_list_between" &&
this.isNthTopicListItem(
parseInt(houseAds.settings.after_nth_topic, 10)
);
if (name === undefined) {
// follows naming convention: prefix_(mobile_)_{placement}_code
name = `${config.settingPrefix}_${
site.mobileView ? "mobile_" : ""
}${placeUnderscored}_code`;
}

if (
adAvailable &&
(notPlacingBetweenTopics ||
this.isNthPost(parseInt(houseAds.settings.after_nth_post, 10)) ||
canBePlacedInBetweenTopics)
name !== false &&
siteSettings[name] !== false &&
!isBlank(siteSettings[name])
) {
types.push("house-ad");
types.push(adNetwork);
}
}
});

Object.keys(adConfig).forEach((adNetwork) => {
const config = adConfig[adNetwork];
let settingNames = null,
name;
return types;
}

if (
this._isNetworkAvailable(config.enabledSetting) &&
this._shouldPlaceAdInSlot(postNumber, config.nthPost)
) {
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 &&
this.siteSettings[name] !== false &&
!isBlank(this.siteSettings[name])
) {
types.push(adNetwork);
}
}
});
export default AdComponent.extend({
needsUpdate: false,
tagName: "",

return types;
/**
* 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.
*/
@discourseComputed("placement", "postNumber", "indexNumber")
availableAdTypes(placement, postNumber, indexNumber) {
return slotContenders(
this.site,
this.siteSettings,
placement,
postNumber,
indexNumber
);
},

/**
Expand Down Expand Up @@ -205,25 +251,4 @@ export default AdComponent.extend({

return networkNames;
},

_isNetworkAvailable(enabledNetworkSettingName) {
// False means there's no setting to enable or disable this ad network.
// Assume it's always enabled.
if (enabledNetworkSettingName === false) {
return true;
} else {
return (
enabledNetworkSettingName &&
!isBlank(this.siteSettings[enabledNetworkSettingName])
);
}
},

_shouldPlaceAdInSlot(currentPostNumber, positionToPlace) {
return (
!currentPostNumber ||
!positionToPlace ||
this.isNthPost(parseInt(this.siteSettings[positionToPlace], 10))
);
},
});
15 changes: 15 additions & 0 deletions assets/javascripts/discourse/helpers/slot-position.js
@@ -0,0 +1,15 @@
export function isNthPost(every, currentPostNumber) {
if (every && every > 0) {
return currentPostNumber % every === 0;
} else {
return false;
}
}

export function isNthTopicListItem(every, currentIndexPosition) {
if (every && every > 0 && currentIndexPosition > 0) {
return (currentIndexPosition + 1) % every === 0;
} else {
return false;
}
}
@@ -0,0 +1,14 @@
import { slotContenders } from "discourse/plugins/discourse-adplugin/discourse/components/ad-slot";

export default {
shouldRender(args, component) {
return (
slotContenders(
component.site,
component.siteSettings,
"topic-list-between",
args.index
).length === 0
);
},
};