Skip to content

Commit

Permalink
Add redirect ordering (Closes #274)
Browse files Browse the repository at this point in the history
  • Loading branch information
Tam committed May 18, 2020
1 parent 58de8d6 commit 2e9a458
Show file tree
Hide file tree
Showing 12 changed files with 188 additions and 28 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 3.6.5 - 2020-05-18
### Added
- Add redirect ordering (Closes #274)

## 3.6.4 - 2020-04-15
### Fixed
- Fix JS error when `%` appeared in SEO snippet text
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "ether/seo",
"license": "MIT",
"description": "SEO utilities including a unique field type, sitemap, & redirect manager",
"version": "3.6.4",
"version": "3.6.5",
"type": "craft-plugin",
"minimum-stability": "dev",
"require": {
Expand Down
80 changes: 63 additions & 17 deletions resources/js/settings/Redirects.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,21 @@ export default class Redirects {

initTables () {
Object.keys(this.tables).forEach(key => {
if (this.tables[key].__sorter)
this.tables[key].__sorter.destroy();

this.tables[key].__sorter = new Craft.DataTableSorter(this.tables[key].parentNode, {
onSortChange: () => this.onSort(this.tables[key]),
});

[].slice.call(this.tables[key].getElementsByTagName("tr")).forEach(row => {
const links = row.getElementsByTagName("a");

links[0].addEventListener("click", e => {
this.onEditClick(key, e, row);
});

links[1].addEventListener("click", e => {
links[2].addEventListener("click", e => {
this.onDeleteClick(key, e, row);
});
});
Expand All @@ -80,18 +87,22 @@ export default class Redirects {
, type = form.elements[this.namespaceField("type")]
, siteId = form.elements[this.namespaceField("siteId")];

const order = this.tables[siteId.value].children.length;

// Validate
if (!Redirects._validate(uri, to, spinner))
return;

this.post("POST", {
action: 'seo/redirects/save',
order,
uri: uri.value,
to: to.value,
type: type.value,
siteId: siteId.value,
}, ({ id }) => {
this.tables[siteId.value].appendChild(this.rowStatic(
id, uri.value, to.value, type.value, siteId.value
id, order, uri.value, to.value, type.value, siteId.value
));

Craft.cp.displayNotice(
Expand All @@ -102,6 +113,7 @@ export default class Redirects {
uri.value = '';
to.value = '';
uri.focus();
this.initTables();
}, error => {
Craft.cp.displayError("<strong>SEO:</strong> " + error);
spinner.classList.add("hidden");
Expand Down Expand Up @@ -141,16 +153,17 @@ export default class Redirects {
type: type.value,
siteId: siteId.value,
}, ({ redirects: newRedirects }) => {
newRedirects.forEach(({ id, uri, to, type, siteId }) => {
newRedirects.forEach(({ id, order, uri, to, type, siteId }) => {
this.tables[siteId || 'null'].appendChild(this.rowStatic(
id, uri, to, type, siteId
id, order, uri, to, type, siteId
));
});

Craft.cp.displayNotice('<strong>SEO:</strong> Redirects added successfully!');
spinner.classList.add("hidden");

redirects.value = '';
this.initTables();
}, error => {
Craft.cp.displayError('<strong>SEO:</strong> ' + error);
spinner.classList.add("hidden");
Expand All @@ -164,17 +177,20 @@ export default class Redirects {
const form = e.target
, spinner = form.getElementsByClassName("spinner")[0];

const id = form.elements[this.namespaceField("id")]
, uri = form.elements[this.namespaceField("uri")]
, to = form.elements[this.namespaceField("to")]
, type = form.elements[this.namespaceField("type")];
const id = form.elements[this.namespaceField("id")]
, order = form.elements[this.namespaceField("order")]
, uri = form.elements[this.namespaceField("uri")]
, to = form.elements[this.namespaceField("to")]
, type = form.elements[this.namespaceField("type")];

// Validate
if (!Redirects._validate(uri, to, spinner))
return;

this.post("POST", {
action: 'seo/redirects/save',
id: id.value,
order: order.value,
uri: uri.value,
to: to.value,
type: type.value,
Expand All @@ -185,7 +201,7 @@ export default class Redirects {

this.tables[siteId].insertBefore(
this.rowStatic(
id.value, uri.value, to.value, type.value, siteId.value,
id.value, order.value, uri.value, to.value, type.value, siteId.value,
row.dataset.added
),
row
Expand All @@ -200,10 +216,10 @@ export default class Redirects {

onEditClick = (siteId, e, row) => {
e.preventDefault();
const { id, uri, to, type, added } = e.target.dataset;
const { id, order, uri, to, type, added } = e.target.dataset;
this.cancelCurrentEdit();

const editRows = this.rowEdit(id, uri, to, type);
const editRows = this.rowEdit(id, order, uri, to, type);

this.editRow = row;
this.editRow.setAttribute('data-added', added);
Expand Down Expand Up @@ -247,6 +263,27 @@ export default class Redirects {
Craft.cp.displayNotice('<strong>SEO:</strong> ' + error);
});
};

onSort = table => {
const rows = table.querySelectorAll('tr');
const post = [];

for (let i = 0, l = rows.length; i < l; i++) {
const row = rows[i];
row.dataset.order = i;
row.querySelector('a').dataset.order = i;
post.push({ id: row.dataset.id, order: row.dataset.order });
}

this.post('POST', {
action: 'seo/redirects/sort',
order: post,
}, () => {
Craft.cp.displayNotice('<strong>SEO:</strong> Redirect order saved');
}, error => {
Craft.cp.displayNotice('<strong>SEO:</strong> ' + error);
});
};

// Helpers
// =========================================================================
Expand All @@ -259,7 +296,7 @@ export default class Redirects {
method,
fields = {},
onSuccess = () => {},
onError = () => {}
onError = () => {},
) {
const jsonData = {};

Expand Down Expand Up @@ -294,7 +331,7 @@ export default class Redirects {
});
}

rowStatic (id = -1, uri = "", to = "", type = 301, siteId = null, dateCreated = null) {
rowStatic (id = -1, order = -1, uri = "", to = "", type = 301, siteId = null, dateCreated = null) {
const added = dateCreated || 'Now';

const row = c("tr", { "tabindex": 0, "data-id": id }, [
Expand All @@ -307,11 +344,12 @@ export default class Redirects {
"href": "#",
"title": "Edit Redirect",
"data-id": id,
"data-order": order,
"data-uri": uri,
"data-to": to,
"data-type": type,
"data-added": dateCreated,
"click": e => this.onEditClick(siteId, e, row)
"click": e => this.onEditClick(siteId, e, row),
}, uri)
])
])
Expand All @@ -327,14 +365,22 @@ export default class Redirects {
// Added
c("td", {}, added),

// Reorder
c("td", { "class": "thin action" }, [
c("a", {
"class": "move icon",
"title": "Reorder",
}),
]),

// Delete
c("td", { "class": "thin action" }, [
c("a", {
"class": "delete icon",
"title": "Delete",
"click": e => this.onDeleteClick(siteId, e, row)
})
])
"click": e => this.onDeleteClick(siteId, e, row),
}),
]),
]);

return row;
Expand Down
4 changes: 2 additions & 2 deletions src/Seo.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class Seo extends Plugin
public $documentationUrl =
'https://github.com/ethercreative/seo/blob/v3/README.md';

public $schemaVersion = '3.1.0';
public $schemaVersion = '3.1.1';

// Craft
// =========================================================================
Expand Down Expand Up @@ -236,7 +236,7 @@ public function onRegisterCPUrlRules (RegisterUrlRulesEvent $event)
// Redirects
// ---------------------------------------------------------------------
$event->rules['DELETE seo/redirects'] = 'seo/redirects/delete';
$event->rules['POST seo/redirects'] = 'seo/redirects/save';
//$event->rules['POST seo/redirects'] = 'seo/redirects/save';
$event->rules['PUT seo/redirects'] = 'seo/redirects/bulk';
$event->rules['seo/redirects'] = 'seo/redirects/index';

Expand Down
17 changes: 16 additions & 1 deletion src/controllers/RedirectsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,14 @@ public function actionSave ()

$request = Craft::$app->request;

$order = $request->getRequiredBodyParam('order');
$uri = $request->getRequiredBodyParam('uri');
$to = $request->getRequiredBodyParam('to');
$type = $request->getRequiredBodyParam('type');
$siteId = $request->getBodyParam('siteId', false);
$id = $request->getBodyParam('id');

$err = Seo::$i->redirects->save($uri, $to, $type, $siteId, $id);
$err = Seo::$i->redirects->save($order, $uri, $to, $type, $siteId, $id);

if (is_numeric($err))
{
Expand Down Expand Up @@ -107,6 +108,20 @@ public function actionBulk ()
}
}

public function actionSort ()
{
$order = Craft::$app->getRequest()->getBodyParam('order');

$error = Seo::$i->redirects->sort($order);

if ($error) return $this->asErrorJson($error);
else {
return $this->asJson([
'success' => true,
]);
}
}

/**
* @throws Exception
* @throws Throwable
Expand Down
51 changes: 51 additions & 0 deletions src/migrations/m200518_110721_add_order_to_redirects.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

namespace ether\seo\migrations;

use Craft;
use craft\db\Migration;
use ether\seo\records\RedirectRecord;

/**
* m200518_110721_add_order_to_redirects migration.
*/
class m200518_110721_add_order_to_redirects extends Migration
{
/**
* @inheritdoc
*/
public function safeUp()
{
$this->addColumn(
RedirectRecord::$tableName,
'order',
$this->integer()->null()
);

$rows = RedirectRecord::find()->select(['id', 'siteId'])->all();
$siteCounts = [];

foreach ($rows as $row)
{
if (!array_key_exists($row->siteId, $siteCounts))
$siteCounts[$row->siteId] = 0;

$record = RedirectRecord::findOne(['id' => $row->id]);
$record->order = $siteCounts[$row->siteId];
$record->save(false);

$siteCounts[$row->siteId]++;
}
}

/**
* @inheritdoc
*/
public function safeDown()
{
$this->dropColumn(
RedirectRecord::$tableName,
'order'
);
}
}
9 changes: 9 additions & 0 deletions src/models/Redirect.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ class Redirect extends Model
// Props: Public Instance
// -------------------------------------------------------------------------

/** @var int */
public $order;

/** @var string */
public $uri;

Expand All @@ -37,6 +40,12 @@ public function rules (): array
{
$rules = parent::rules();

$rules[] = [
['order'],
'integer',
'required',
];

$rules[] = [
['url', 'to', 'type'],
'string',
Expand Down
1 change: 1 addition & 0 deletions src/records/RedirectRecord.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* Class RedirectRecord
*
* @property int $id
* @property int $order
* @property string $uri
* @property string $to
* @property string $type
Expand Down
Loading

0 comments on commit 2e9a458

Please sign in to comment.