mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06:00
FEAT: add cc addresses and post_id to sent email logs (#25014)
* add cc addresses and post_id to sent email logs * sort cc addresses by email address filter value and collapse additional addreses into tooltip * add slice helper for use in ember tempaltes
This commit is contained in:
@@ -4,6 +4,28 @@ import discourseDebounce from "discourse-common/lib/debounce";
|
||||
import AdminEmailLogsController from "admin/controllers/admin-email-logs";
|
||||
|
||||
export default class AdminEmailSentController extends AdminEmailLogsController {
|
||||
ccAddressDisplayThreshold = 2;
|
||||
sortWithAddressFilter = (addresses) => {
|
||||
if (!Array.isArray(addresses) || addresses.length === 0) {
|
||||
return [];
|
||||
}
|
||||
const targetEmail = this.filter.address;
|
||||
|
||||
if (!targetEmail) {
|
||||
return addresses;
|
||||
}
|
||||
|
||||
return addresses.sort((a, b) => {
|
||||
if (a.includes(targetEmail) && !b.includes(targetEmail)) {
|
||||
return -1;
|
||||
}
|
||||
if (!a.includes(targetEmail) && b.includes(targetEmail)) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
};
|
||||
|
||||
@observes("filter.{status,user,address,type,reply_key}")
|
||||
filterEmailLogs() {
|
||||
discourseDebounce(this, this.loadLogs, INPUT_DELAY);
|
||||
|
||||
@@ -54,7 +54,53 @@
|
||||
"redo"
|
||||
title="admin.email.bounced"
|
||||
}}{{/if}}
|
||||
<a href="mailto:{{l.to_address}}">{{l.to_address}}</a>
|
||||
<p><a
|
||||
href="mailto:{{l.to_address}}"
|
||||
title="TO"
|
||||
>{{l.to_address}}</a></p>
|
||||
{{#if l.cc_addresses}}
|
||||
{{#if (gt l.cc_addresses.length this.ccAddressDisplayThreshold)}}
|
||||
{{#each
|
||||
(slice
|
||||
0
|
||||
this.ccAddressDisplayThreshold
|
||||
(fn this.sortWithAddressFilter l.cc_addresses)
|
||||
)
|
||||
as |cc|
|
||||
}}
|
||||
<p><a href="mailto:{{cc}}" title="CC">{{cc}}</a></p>
|
||||
{{/each}}
|
||||
<DTooltip
|
||||
@placement="right-start"
|
||||
@arrow={{true}}
|
||||
@identifier="email-log-cc-addresses"
|
||||
@interactive={{true}}
|
||||
>
|
||||
<:trigger>
|
||||
{{i18n "admin.email.logs.email_addresses.see_more"}}
|
||||
</:trigger>
|
||||
<:content>
|
||||
<ul>
|
||||
{{#each
|
||||
(slice this.ccAddressDisplayThreshold l.cc_addresses)
|
||||
as |cc|
|
||||
}}
|
||||
<li>
|
||||
<span>
|
||||
<a href="mailto:{{cc}}" title="CC">{{cc}}</a>
|
||||
</span>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</:content>
|
||||
</DTooltip>
|
||||
|
||||
{{else}}
|
||||
{{#each l.cc_addresses as |cc|}}
|
||||
<p><a href="mailto:{{cc}}" title="CC">{{cc}}</a></p>
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</td>
|
||||
<td class="sent-email-type">{{l.email_type}}</td>
|
||||
<td class="sent-email-reply-key">
|
||||
@@ -62,8 +108,12 @@
|
||||
</td>
|
||||
<td class="sent-email-post-link-with-smtp-response">
|
||||
{{#if l.post_url}}
|
||||
<a href={{l.post_url}}>{{l.post_description}}</a><br />
|
||||
{{/if}}
|
||||
<a href={{l.post_url}}>
|
||||
{{l.post_description}}
|
||||
</a>
|
||||
{{i18n "admin.email.logs.post_id" post_id=l.post_id}}
|
||||
<br />
|
||||
/{{/if}}
|
||||
<code
|
||||
title={{l.smtp_transaction_response}}
|
||||
>{{l.smtp_transaction_response}}</code>
|
||||
|
||||
10
app/assets/javascripts/discourse/app/helpers/slice.js
Normal file
10
app/assets/javascripts/discourse/app/helpers/slice.js
Normal file
@@ -0,0 +1,10 @@
|
||||
export default function slice(...args) {
|
||||
let array = args.pop();
|
||||
if (array instanceof Function) {
|
||||
array = array.call();
|
||||
}
|
||||
if (!Array.isArray(array) || array.length === 0) {
|
||||
return [];
|
||||
}
|
||||
return array.slice(...args);
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
import { run } from "@ember/runloop";
|
||||
import { render } from "@ember/test-helpers";
|
||||
import { hbs } from "ember-cli-htmlbars";
|
||||
import { setupRenderingTest } from "ember-qunit";
|
||||
import { module, test } from "qunit";
|
||||
|
||||
module("Integration | Helper | {{slice}}", function (hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
|
||||
test("it slices an array with positional params", async function (assert) {
|
||||
this.set("array", [2, 4, 6]);
|
||||
|
||||
await render(hbs`
|
||||
{{slice 1 3 this.array}}
|
||||
`);
|
||||
|
||||
assert.dom().hasText("4,6", "sliced values");
|
||||
});
|
||||
|
||||
test("it slices when only 2 params are passed", async function (assert) {
|
||||
this.set("array", [2, 4, 6]);
|
||||
|
||||
await render(hbs`
|
||||
{{slice 1 this.array}}
|
||||
`);
|
||||
|
||||
assert.dom().hasText("4,6", "sliced values");
|
||||
});
|
||||
|
||||
test("it recomputes the slice if an item in the array changes", async function (assert) {
|
||||
let array = [2, 4, 6];
|
||||
this.set("array", array);
|
||||
|
||||
await render(hbs`
|
||||
{{slice 1 3 this.array}}
|
||||
`);
|
||||
|
||||
assert.dom().hasText("4,6", "sliced values");
|
||||
|
||||
run(() => array.replace(2, 1, [5]));
|
||||
|
||||
assert.dom().hasText("4,5", "sliced values");
|
||||
});
|
||||
|
||||
test("it allows null array", async function (assert) {
|
||||
this.set("array", null);
|
||||
|
||||
await render(hbs`
|
||||
this is all that will render
|
||||
{{#each (slice 1 2 this.array) as |value|}}
|
||||
{{value}}
|
||||
{{/each}}
|
||||
`);
|
||||
|
||||
assert.dom().hasText("this is all that will render", "no error is thrown");
|
||||
});
|
||||
|
||||
test("it allows undefined array", async function (assert) {
|
||||
this.set("array", undefined);
|
||||
|
||||
await render(hbs`
|
||||
this is all that will render
|
||||
{{#each (slice 1 2 this.array) as |value|}}
|
||||
{{value}}
|
||||
{{/each}}
|
||||
`);
|
||||
|
||||
assert.dom().hasText("this is all that will render", "no error is thrown");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user