mirror of
https://github.com/knadh/listmonk.git
synced 2025-10-02 11:25:56 +08:00
195 lines
6 KiB
Vue
195 lines
6 KiB
Vue
<template>
|
|
<section class="bounces">
|
|
<header class="page-header columns">
|
|
<div class="column is-two-thirds">
|
|
<h1 class="title is-4">
|
|
{{ $t('globals.terms.bounces') }}
|
|
<span v-if="bounces.total > 0">({{ bounces.total }})</span>
|
|
</h1>
|
|
</div>
|
|
<div class="column has-text-right buttons">
|
|
<b-button v-if="bulk.checked.length > 0 || bulk.all" type="is-primary" icon-left="trash-can-outline"
|
|
data-cy="btn-delete" @click.prevent="$utils.confirm(null, () => deleteBounces())">
|
|
{{ $t('globals.buttons.clear') }}
|
|
</b-button>
|
|
<b-button v-if="bounces.total" icon-left="trash-can-outline" data-cy="btn-delete"
|
|
@click.prevent="$utils.confirm(null, () => deleteBounces(true))">
|
|
{{ $t('globals.buttons.clearAll') }}
|
|
</b-button>
|
|
</div>
|
|
</header>
|
|
|
|
<b-table :data="bounces.results" :hoverable="true" :loading="loading.bounces" default-sort="createdAt" checkable
|
|
@check-all="onTableCheck" @check="onTableCheck" :checked-rows.sync="bulk.checked" detailed show-detail-icon
|
|
paginated backend-pagination pagination-position="both" @page-change="onPageChange" :current-page="queryParams.page" :per-page="bounces.perPage"
|
|
:total="bounces.total" backend-sorting @sort="onSort">
|
|
<b-table-column v-slot="props" field="email" :label="$t('subscribers.email')" :td-attrs="$utils.tdID" sortable>
|
|
<router-link :to="{ name: 'subscriber', params: { id: props.row.subscriberId } }">
|
|
{{ props.row.email }}
|
|
</router-link>
|
|
</b-table-column>
|
|
|
|
<b-table-column v-slot="props" field="campaign" :label="$tc('globals.terms.campaign')" sortable>
|
|
<router-link v-if="props.row.campaign" :to="{ name: 'bounces', query: { campaign_id: props.row.campaign.id } }">
|
|
{{ props.row.campaign.name }}
|
|
</router-link>
|
|
<span v-else>-</span>
|
|
</b-table-column>
|
|
|
|
<b-table-column v-slot="props" field="source" :label="$t('bounces.source')" sortable>
|
|
<router-link :to="{ name: 'bounces', query: { source: props.row.source } }">
|
|
{{ props.row.source }}
|
|
</router-link>
|
|
</b-table-column>
|
|
|
|
<b-table-column v-slot="props" field="type" :label="$t('globals.fields.type')" sortable>
|
|
<router-link :to="{ name: 'bounces', query: { type: props.row.type } }">
|
|
{{ $t(`bounces.${props.row.type}`) }}
|
|
</router-link>
|
|
</b-table-column>
|
|
|
|
<b-table-column v-slot="props" field="created_at" :label="$t('globals.fields.createdAt')" sortable>
|
|
{{ $utils.niceDate(props.row.createdAt, true) }}
|
|
</b-table-column>
|
|
|
|
<b-table-column v-slot="props" cell-class="actions" align="right">
|
|
<div>
|
|
<a v-if="!props.row.isDefault" href="#" @click.prevent="$utils.confirm(null, () => deleteBounce(props.row))"
|
|
data-cy="btn-delete" :aria-label="$t('globals.buttons.delete')">
|
|
<b-tooltip :label="$t('globals.buttons.delete')" type="is-dark">
|
|
<b-icon icon="trash-can-outline" size="is-small" />
|
|
</b-tooltip>
|
|
</a>
|
|
<span v-else class="a has-text-grey-light">
|
|
<b-icon icon="trash-can-outline" size="is-small" />
|
|
</span>
|
|
</div>
|
|
</b-table-column>
|
|
|
|
<template #detail="props">
|
|
<pre class="is-size-7">{{ props.row.meta }}</pre>
|
|
</template>
|
|
|
|
<template #empty v-if="!loading.templates">
|
|
<empty-placeholder />
|
|
</template>
|
|
</b-table>
|
|
</section>
|
|
</template>
|
|
|
|
<script>
|
|
import Vue from 'vue';
|
|
import { mapState } from 'vuex';
|
|
import EmptyPlaceholder from '../components/EmptyPlaceholder.vue';
|
|
|
|
export default Vue.extend({
|
|
components: {
|
|
EmptyPlaceholder,
|
|
},
|
|
|
|
data() {
|
|
return {
|
|
bounces: {},
|
|
|
|
// Table bulk row selection states.
|
|
bulk: {
|
|
checked: [],
|
|
all: false,
|
|
},
|
|
|
|
// Query params to filter the getSubscribers() API call.
|
|
queryParams: {
|
|
page: 1,
|
|
orderBy: 'created_at',
|
|
order: 'desc',
|
|
campaignID: 0,
|
|
source: '',
|
|
},
|
|
};
|
|
},
|
|
|
|
methods: {
|
|
onSort(field, direction) {
|
|
this.queryParams.orderBy = field;
|
|
this.queryParams.order = direction;
|
|
this.getBounces();
|
|
},
|
|
|
|
onPageChange(p) {
|
|
this.queryParams.page = p;
|
|
this.getBounces();
|
|
},
|
|
|
|
onTableCheck() {
|
|
// Disable bulk.all selection if there are no rows checked in the table.
|
|
if (this.bulk.checked.length !== this.bounces.total) {
|
|
this.bulk.all = false;
|
|
}
|
|
},
|
|
|
|
getBounces() {
|
|
this.bulk.checked = [];
|
|
this.bulk.all = false;
|
|
|
|
this.$api.getBounces({
|
|
page: this.queryParams.page,
|
|
order_by: this.queryParams.orderBy,
|
|
order: this.queryParams.order,
|
|
campaign_id: this.queryParams.campaign_id,
|
|
source: this.queryParams.source,
|
|
}).then((data) => {
|
|
this.bounces = data;
|
|
});
|
|
},
|
|
|
|
deleteBounce(b) {
|
|
this.$api.deleteBounce(b.id).then(() => {
|
|
this.getBounces();
|
|
this.$utils.toast(this.$t('globals.messages.deleted', { name: b.email }));
|
|
});
|
|
},
|
|
|
|
deleteBounces(all) {
|
|
const fnSuccess = () => {
|
|
this.getBounces();
|
|
this.$utils.toast(this.$t(
|
|
'globals.messages.deletedCount',
|
|
{ name: this.$tc('globals.terms.bounces'), num: this.bounces.total },
|
|
));
|
|
};
|
|
|
|
if (all) {
|
|
this.$api.deleteBounces({ all: true }).then(fnSuccess);
|
|
return;
|
|
}
|
|
|
|
const ids = this.bulk.checked.map((s) => s.id);
|
|
this.$api.deleteBounces({ id: ids }).then(fnSuccess);
|
|
},
|
|
},
|
|
|
|
computed: {
|
|
...mapState(['templates', 'loading']),
|
|
|
|
selectedBounces() {
|
|
if (this.bulk.all) {
|
|
return this.bounces.total;
|
|
}
|
|
return this.bulk.checked.length;
|
|
},
|
|
|
|
},
|
|
|
|
mounted() {
|
|
if (this.$route.query.campaign_id) {
|
|
this.queryParams.campaign_id = parseInt(this.$route.query.campaign_id, 10);
|
|
}
|
|
|
|
if (this.$route.query.source) {
|
|
this.queryParams.source = this.$route.query.source;
|
|
}
|
|
|
|
this.getBounces();
|
|
},
|
|
});
|
|
</script>
|