mirror of
https://gh.wpcy.net/https://github.com/discourse/discourse.git
synced 2026-05-24 14:49:57 +08:00
Started off attempting to fix filters, but was frustrated working with the old patterns and template duplication so I've updated everything and tried to consolidate into a `email-logs-list.gjs` component. The primary issue was that the filters only worked once, and if you needed to change them or remove them... you couldn't and had to refresh the page. Before: https://github.com/user-attachments/assets/9cfa0328-41d4-4178-ab87-ba2ff495d932 After: https://github.com/user-attachments/assets/febcff8f-3dfa-4b86-9be1-f333e6502648
206 lines
5.5 KiB
Text
Vendored
206 lines
5.5 KiB
Text
Vendored
import Component from "@glimmer/component";
|
|
import { tracked } from "@glimmer/tracking";
|
|
import { fn, get } from "@ember/helper";
|
|
import { on } from "@ember/modifier";
|
|
import { action } from "@ember/object";
|
|
import didInsert from "@ember/render-modifiers/modifiers/did-insert";
|
|
import ConditionalLoadingSpinner from "discourse/components/conditional-loading-spinner";
|
|
import HorizontalScrollSyncWrapper from "discourse/components/horizontal-scroll-sync-wrapper";
|
|
import LoadMore from "discourse/components/load-more";
|
|
import TextField from "discourse/components/text-field";
|
|
import discourseDebounce from "discourse/lib/debounce";
|
|
import { INPUT_DELAY } from "discourse/lib/environment";
|
|
import { i18n } from "discourse-i18n";
|
|
import EmailLog from "admin/models/email-log";
|
|
|
|
export default class EmailLogsList extends Component {
|
|
@tracked loading = false;
|
|
@tracked model = null;
|
|
@tracked filterValues = {};
|
|
@tracked initialized = false;
|
|
@tracked loadMoreEnabled = false;
|
|
|
|
sortWithAddressFilter = (addresses) => {
|
|
if (!Array.isArray(addresses) || addresses.length === 0) {
|
|
return [];
|
|
}
|
|
const targetEmail = this.filterValues.filterAddress;
|
|
|
|
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;
|
|
});
|
|
};
|
|
|
|
@action
|
|
initializeComponent() {
|
|
if (!this.initialized) {
|
|
this.initialized = true;
|
|
|
|
const initialValues = {};
|
|
this.args.filters?.forEach((filter) => {
|
|
initialValues[filter.property] = "";
|
|
});
|
|
this.filterValues = initialValues;
|
|
|
|
this.loadLogs();
|
|
}
|
|
}
|
|
|
|
get sourceModel() {
|
|
return this.args.sourceModel || EmailLog;
|
|
}
|
|
|
|
get filterArgs() {
|
|
const args = { status: this.args.status };
|
|
|
|
this.args.filters?.forEach(({ property, name }) => {
|
|
const value = this.filterValues[property];
|
|
if (value) {
|
|
args[name] = value;
|
|
}
|
|
});
|
|
|
|
return args;
|
|
}
|
|
|
|
get ccAddressDisplayThreshold() {
|
|
return this.args.ccAddressDisplayThreshold || 2;
|
|
}
|
|
|
|
get canLoadMore() {
|
|
return (
|
|
this.loadMoreEnabled &&
|
|
this.model &&
|
|
this.model.length > 0 &&
|
|
!this.model.allLoaded &&
|
|
!this.loading
|
|
);
|
|
}
|
|
|
|
@action
|
|
async loadLogs(loadMore = false) {
|
|
if ((loadMore && this.loading) || (loadMore && this.model?.allLoaded)) {
|
|
return;
|
|
}
|
|
|
|
this.loading = true;
|
|
|
|
if (!loadMore && this.model) {
|
|
this.model.set("allLoaded", false);
|
|
}
|
|
|
|
try {
|
|
const logs = await this.sourceModel.findAll(
|
|
this.filterArgs,
|
|
loadMore ? this.model?.length : null
|
|
);
|
|
|
|
if (this.model && loadMore) {
|
|
this.model.addObjects(logs);
|
|
if (logs.length < 50) {
|
|
this.model.set("allLoaded", true);
|
|
}
|
|
} else {
|
|
this.model = logs;
|
|
this.model.set("allLoaded", logs.length < 50);
|
|
this.loadMoreEnabled = true;
|
|
}
|
|
} finally {
|
|
this.loading = false;
|
|
}
|
|
}
|
|
|
|
@action
|
|
updateFilter(filterName, event) {
|
|
const filterConfig = this.args.filters.find((f) => f.name === filterName);
|
|
if (filterConfig) {
|
|
this.filterValues = {
|
|
...this.filterValues,
|
|
[filterConfig.property]: event.target.value,
|
|
};
|
|
this.loadMoreEnabled = false;
|
|
discourseDebounce(this, this.loadLogs, INPUT_DELAY);
|
|
}
|
|
}
|
|
|
|
@action
|
|
loadMore() {
|
|
this.loadLogs(true);
|
|
}
|
|
|
|
@action
|
|
handleShowIncomingEmail(id, event) {
|
|
event?.preventDefault();
|
|
if (this.args.onShowEmail) {
|
|
this.args.onShowEmail(id);
|
|
}
|
|
}
|
|
|
|
<template>
|
|
<LoadMore
|
|
@action={{this.loadMore}}
|
|
@enabled={{this.canLoadMore}}
|
|
@rootMargin="0px 0px 250px 0px"
|
|
{{didInsert this.initializeComponent}}
|
|
>
|
|
<HorizontalScrollSyncWrapper>
|
|
<table class="table email-list">
|
|
<thead>
|
|
<tr>
|
|
<th>{{i18n "admin.email.sent_at"}}</th>
|
|
{{#each @headers as |header|}}
|
|
<th colspan={{header.colspan}}>{{i18n header.key}}</th>
|
|
{{/each}}
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr class="filters">
|
|
<td><span class="sr-only">
|
|
{{i18n "admin.email.logs.filters.title"}}</span>
|
|
</td>
|
|
{{#each @filters as |filter|}}
|
|
<td>
|
|
<TextField
|
|
@value={{get this.filterValues filter.property}}
|
|
@placeholderKey={{filter.placeholder}}
|
|
{{on "input" (fn this.updateFilter filter.name)}}
|
|
/>
|
|
</td>
|
|
{{/each}}
|
|
{{#each @extraFilterCells as |cell|}}
|
|
<td>{{#if cell.content}}{{cell.content}}{{/if}}</td>
|
|
{{/each}}
|
|
</tr>
|
|
|
|
{{#each this.model as |emailLog|}}
|
|
{{yield
|
|
emailLog
|
|
this.ccAddressDisplayThreshold
|
|
this.sortWithAddressFilter
|
|
this.handleShowIncomingEmail
|
|
}}
|
|
{{else}}
|
|
{{#unless this.loading}}
|
|
<tr>
|
|
<td colspan="6">{{i18n "admin.email.logs.none"}}</td>
|
|
</tr>
|
|
{{/unless}}
|
|
{{/each}}
|
|
</tbody>
|
|
</table>
|
|
</HorizontalScrollSyncWrapper>
|
|
</LoadMore>
|
|
|
|
<ConditionalLoadingSpinner @condition={{this.loading}} />
|
|
</template>
|
|
}
|