Skip to content

Commit

Permalink
Merge pull request #47 from v17development/dev
Browse files Browse the repository at this point in the history
Update
  • Loading branch information
jaspervriends authored Feb 17, 2021
2 parents fb21bb6 + 637e55b commit 4ad3999
Show file tree
Hide file tree
Showing 10 changed files with 375 additions and 11 deletions.
3 changes: 3 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
"flarum/core": "^0.1.0-beta.15",
"ext-json": "*"
},
"conflict": {
"zerosonesfun/elint": "*"
},
"suggest": {
"fof/sitemap": "Allows you to generate powerful sitemap.xml files"
},
Expand Down
6 changes: 6 additions & 0 deletions extend.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@
use Extend\Locales;
use Extend\Routes;
use Illuminate\Contracts\Events\Dispatcher;
use V17Development\FlarumSeo\ConfigureLinks;
use V17Development\FlarumSeo\Api\DeleteSocialMediaImageController;
use V17Development\FlarumSeo\Api\UploadSocialMediaImageController;
use V17Development\FlarumSeo\Controller\Robots;
use V17Development\FlarumSeo\Formatter\FormatLinks;
use V17Development\FlarumSeo\Listeners\PageListener;
use V17Development\FlarumSeo\Listeners\BeforePageRenders;

Expand All @@ -25,6 +27,10 @@
->delete('/seo_social_media_image', 'pages.index', DeleteSocialMediaImageController::class),

new Extend\Locales(__DIR__ . '/locale'),

(new Extend\Formatter)
->render(FormatLinks::class)
->configure(ConfigureLinks::class),

// new BeforePageRenders()
];
2 changes: 1 addition & 1 deletion js/dist/admin.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/dist/admin.js.map

Large diffs are not rendered by default.

78 changes: 70 additions & 8 deletions js/src/admin/components/Forms/SeoSettings.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ import Component from 'flarum/Component';
import FieldSet from 'flarum/components/FieldSet';
import Button from 'flarum/components/Button';
import saveSettings from 'flarum/utils/saveSettings';
import Alert from 'flarum/components/Alert';
import Switch from 'flarum/components/Switch';
import UploadImageButton from 'flarum/components/UploadImageButton';
import CrawlPostModal from "../Modals/CrawlPostModal";
import RobotsModal from "../Modals/RobotsModal";
import countKeywords from '../../utils/countKeywords';
import Stream from 'flarum/utils/Stream';
import DoFollowListModal from '../Modals/DoFollowListModal';
import Select from 'flarum/components/Select';

export default class SeoSettings extends Component {
oninit(vnode) {
Expand All @@ -20,7 +21,8 @@ export default class SeoSettings extends Component {
'forum_title',
'forum_description',
'forum_keywords',
'seo_allow_all_bots'
'seo_allow_all_bots',
'seo_twitter_card_size'
];
this.values = {};

Expand Down Expand Up @@ -78,6 +80,32 @@ export default class SeoSettings extends Component {
}}>
<b>Note: Separate keywords with a comma.</b> Example: <i>flarum, web development, forum, apples, security</i>
</div>,
this.showField === "keywords" && Button.component({
type: 'submit',
className: 'Button Button--primary',
loading: this.saving,
disabled: !this.changed()
}, app.translator.trans('core.admin.basics.submit_button'))
])}

{FieldSet.component({
label: 'Twitter card size',
className: this.showField !== 'all' ? 'hidden' : ''
}, [
<div className="helpText">
When your forum is shared on Twitter, it will have an image (if a social media image has been set up). This can be a big card with a big image, or a small card (summary) with a smaller image.
</div>,
Select.component({
options: {
'large': 'Large card (large image)',
'summary': 'Summary card (smaller image)',
},
value: this.values.seo_twitter_card_size() || 'large',
onchange: (val) => {
this.values.seo_twitter_card_size(val);
this.hasChanges = true;
}
}),
Button.component({
type: 'submit',
className: 'Button Button--primary',
Expand All @@ -86,6 +114,18 @@ export default class SeoSettings extends Component {
}, app.translator.trans('core.admin.basics.submit_button'))
])}

{FieldSet.component({
label: 'Social media image',
className: 'social-media-uploader ' + (this.showField !== 'all' && this.showField !== 'social-media' ? 'hidden' : '')
}, [
<div className="helpText">
Expecting a square image. Recommended size is 1200x1200 pixels. Otherwise use a landscape image, recommended size is 1200x630.<br /><br />This image will be used by Social Media when a user shares a page on your website (Facebook, Twitter, Reddit).
</div>,
UploadImageButton.component({
name: 'seo_social_media_image'
})
])}

{FieldSet.component({
label: 'Discussion post crawl settings',
className: this.showField !== 'all' && this.showField !== 'discussion-post' ? 'hidden' : ''
Expand All @@ -100,15 +140,32 @@ export default class SeoSettings extends Component {
])}

{FieldSet.component({
label: 'Social media image',
className: 'social-media-uploader ' + (this.showField !== 'all' && this.showField !== 'social-media' ? 'hidden' : '')
label: 'No-follow links',
className: this.showField !== 'all' ? 'hidden' : '',
}, [
<div className="helpText">
Expecting a square image. Recommended size is 1200x1200 pixels. Otherwise use a landscape image, recommended size is 1200x630.<br /><br />This image will be used by Social Media when a user shares a page on your website (Facebook, Twitter, Reddit).
All links to external domains will receive a '<i>nofollow</i>' attribute by default. This will make sure people do not spam your forum with links to other domains in order to get more referrals.
</div>,
<div className="helpText">
With this setting you are able to add domains to the 'do-follow' list. For example, you can add <i>flarum.org</i> to make sure links to this website do not receive a 'nofollow' attribute. <a href={"https://community.v17.dev/knowledgebase/36"} target={"_blank"}>Learn more</a>.
</div>,
<div style="height: 5px;"></div>,
<div>
{Button.component({
className: 'Button',
loading: this.saving,
onclick: () => app.modal.show(DoFollowListModal)
}, 'Open domain do-follow list')}
</div>
])}

{FieldSet.component({
label: 'Open external links in new tab',
className: this.showField !== 'all' ? 'hidden' : '',
}, [
<div className="helpText">
This extension will also make sure that external links (to other domains) open in a new tab. Currently it is not possible to disable this setting.
</div>,
UploadImageButton.component({
name: 'seo_social_media_image'
})
])}

{FieldSet.component({
Expand Down Expand Up @@ -188,6 +245,11 @@ export default class SeoSettings extends Component {

this.fields.forEach(key => settings[key] = this.values[key]());

// Set twitter card size to large
if(settings.seo_twitter_card_size === "") {
settings.seo_twitter_card_size = "large";
}

saveSettings(settings)
.then(() => app.alerts.show({type: 'success' }, app.translator.trans('core.admin.basics.saved_message')))
.catch(() => {})
Expand Down
151 changes: 151 additions & 0 deletions js/src/admin/components/Modals/DoFollowListModal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
import Modal from 'flarum/components/Modal';
import Button from 'flarum/components/Button';
import saveSettings from 'flarum/utils/saveSettings';
import Stream from 'flarum/utils/Stream';

export default class DoFollowListModal extends Modal {
oninit(vnode) {
super.oninit(vnode);

this.domainDoFollowList = [];

this.baseUrl = app.forum.data.attributes.baseUrl.replace("http://", "").replace("https", "");
this.domainDoFollowList = typeof app.data.settings.seo_dofollow_domains === "undefined" ? Stream([]) : Stream(JSON.parse(app.data.settings.seo_dofollow_domains));

this.startValue = this.domainDoFollowList;

this.newDomain = Stream("");

this.hasChanges = false;
this.loading = false;
}

title() {
return 'Do-follow list';
}

content() {
return (
<div>
<div className="Modal-body">
<p>Enter the <b>hostnames</b> of the domains you want to add to the do-follow list.</p>

<p>The domain you use for your Flarum instance is added to the list by default.</p>

<p style={{ marginBottom: '15px' }}>
<a href={"https://community.v17.dev/knowledgebase/36"} target={"_blank"}>Learn more</a> about the do-follow list.
</p>

<div className={"FlarumSEO-DoFollowList"}>
<input type="text" value={this.baseUrl} readonly className={"FormControl"} />
<Button className={"Button"} icon={"fas fa-times"} disabled />
</div>

{this.domainDoFollowList().map((domain, key) => {
return (
<div className={"FlarumSEO-DoFollowList"}>
<input type="text" value={domain} onkeyup={(e) => this.updateDomain(key, e.target.value)} className={"FormControl"} />
<Button className={"Button"} icon={"fas fa-times"} onclick={() => this.removeDomain(key)} />
</div>
)
})}

<div className={"FlarumSEO-DoFollowList"}>
<input type="text" bidi={this.newDomain} placeholder={"Allow a domain"} onkeydown={(e) => {
if(e.keyCode === 13 && this.newDomain() !== '') {
e.preventDefault();
this.addDomain();
}
}} className={"FormControl"} />
<Button className={`Button ${this.newDomain() !== '' ? 'Button--primary' : ''}`} icon={"fas fa-plus"} onclick={this.addDomain.bind(this)} />
</div>
</div>
<div style="padding: 25px 30px; text-align: center;">
<Button
type="submit"
className="Button Button--primary"
loading={this.loading}>
{this.hasChanges ? 'Save changes' : 'Close'}
</Button>
</div>
</div>
);
}

/**
* Add new domain to the list
*/
addDomain() {
// Check if the domain is already present
if(this.domainDoFollowList().indexOf(this.newDomain()) >= 0) {
alert("This domain is already present in your do-follow list.");

this.newDomain("");
return;
}

let updatedData = [...this.domainDoFollowList()];

updatedData.push(this.newDomain());

this.domainDoFollowList(updatedData);

// Reset domain
this.newDomain("");

// Update the hasChanges
this.hasChanges = true;
}

/**
* Remove domain from the list
*
* @param {number} key
*/
removeDomain(key) {
let updatedData = [...this.domainDoFollowList()];

updatedData.splice(key, 1);

this.domainDoFollowList(updatedData);

// Update the hasChanges
this.hasChanges = true;
}

/**
* Update domain
*
* @param {*} e
*/
updateDomain(key, value) {
let updatedData = [...this.domainDoFollowList()];
updatedData[key] = value;

this.domainDoFollowList(updatedData);

// Update the hasChanges
this.hasChanges = true;
}

// Close or save setting
onsubmit(e) {
if(!this.hasChanges) {
this.hide();
return;
}

this.loading = true;

let data = {};
data.seo_dofollow_domains = JSON.stringify(this.domainDoFollowList().filter(val => val !== ""));

saveSettings(data).then(
this.onsaved.bind(this)
);
}

onsaved() {
this.hide();
}
}
21 changes: 21 additions & 0 deletions less/admin/Page.less
Original file line number Diff line number Diff line change
Expand Up @@ -115,4 +115,25 @@
margin: 0;
}
}
}

.FlarumSEO-DoFollowList {
display: flex;
margin: 10px 0;

input[type="text"] {
flex-grow: 1;
margin-right: 10px;
}

.Button {
flex-shrink: 0;
flex-grow: 0;
padding: 8px 13px !important;

i {
margin-right: 0;
display: inline-block;
}
}
}
24 changes: 24 additions & 0 deletions src/ConfigureLinks.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace V17Development\FlarumSeo;

use Flarum\Foundation\Application;
use s9e\TextFormatter\Configurator;
use Psr\Http\Message\ServerRequestInterface as Request;

class ConfigureLinks
{
public function __invoke(Configurator $configurator)
{
$configurator->templateNormalizer->append(
function (\DOMElement $template)
{
foreach ($template->getElementsByTagName('a') as $a)
{
$a->setAttribute('rel', "{@rel}");
$a->setAttribute('target', "{@target}");
}
}
);
}
}
Loading

0 comments on commit 4ad3999

Please sign in to comment.