Paginate moderations page without losing filtering

Co-authored-by: Tirokk <wolle.huss@pjannto.com>
This commit is contained in:
mattwr18 2019-12-09 16:37:04 +01:00
parent f41b52f6e0
commit 79c6bd5c20
7 changed files with 102 additions and 34 deletions

View File

@ -52,7 +52,7 @@ export default {
reports: async (_parent, params, context, _resolveInfo) => { reports: async (_parent, params, context, _resolveInfo) => {
const { driver } = context const { driver } = context
const session = driver.session() const session = driver.session()
let reports, orderByClause let reports, orderByClause, filterClause
switch (params.orderBy) { switch (params.orderBy) {
case 'createdAt_asc': case 'createdAt_asc':
orderByClause = 'ORDER BY report.createdAt ASC' orderByClause = 'ORDER BY report.createdAt ASC'
@ -63,17 +63,37 @@ export default {
default: default:
orderByClause = '' orderByClause = ''
} }
switch (params.reviewed) {
case true:
filterClause = 'AND ((report)<-[:REVIEWED]-(:User))'
break
case false:
filterClause = 'AND NOT ((report)<-[:REVIEWED]-(:User))'
break
default:
filterClause = ''
}
if (params.closed) filterClause = 'AND report.closed = true'
const offset =
params.offset && typeof params.offset === 'number' ? `SKIP ${params.offset}` : ''
const limit = params.first && typeof params.first === 'number' ? `LIMIT ${params.first}` : ''
const reportReadTxPromise = session.readTransaction(async tx => { const reportReadTxPromise = session.readTransaction(async tx => {
const allReportsTransactionResponse = await tx.run( const allReportsTransactionResponse = await tx.run(
` `
MATCH (report:Report)-[:BELONGS_TO]->(resource) MATCH (report:Report)-[:BELONGS_TO]->(resource)
WHERE resource:User OR resource:Post OR resource:Comment WHERE (resource:User OR resource:Post OR resource:Comment)
WITH report, resource, ${filterClause}
[(submitter:User)-[filed:FILED]->(report) | filed {.*, submitter: properties(submitter)} ] as filed, WITH report, resource,
[(moderator:User)-[reviewed:REVIEWED]->(report) | reviewed {.*, moderator: properties(moderator)} ] as reviewed, [(submitter:User)-[filed:FILED]->(report) | filed {.*, submitter: properties(submitter)} ] as filed,
resource {.*, __typename: labels(resource)[0] } as resourceWithType [(moderator:User)-[reviewed:REVIEWED]->(report) | reviewed {.*, moderator: properties(moderator)} ] as reviewed,
RETURN report {.*, resource: resourceWithType, filed: filed, reviewed: reviewed} resource {.*, __typename: labels(resource)[0] } as resourceWithType
${orderByClause} RETURN report {.*, resource: resourceWithType, filed: filed, reviewed: reviewed}
${orderByClause}
${offset} ${limit}
`, `,
) )
return allReportsTransactionResponse.records.map(record => record.get('report')) return allReportsTransactionResponse.records.map(record => record.get('report'))

View File

@ -16,8 +16,3 @@ enum ReasonCategory {
advert_products_services_commercial advert_products_services_commercial
criminal_behavior_violation_german_law criminal_behavior_violation_german_law
} }
enum ReportOrdering {
createdAt_asc
createdAt_desc
}

View File

@ -6,7 +6,7 @@ type Report {
disable: Boolean! disable: Boolean!
closed: Boolean! closed: Boolean!
filed: [FILED] filed: [FILED]
reviewed: [REVIEWED] reviewed: [REVIEWED]!
resource: ReportedResource resource: ReportedResource
} }
@ -21,5 +21,10 @@ type Mutation {
} }
type Query { type Query {
reports(orderBy: ReportOrdering): [Report] reports(orderBy: ReportOrdering, first: Int, offset: Int, reviewed: Boolean, closed: Boolean): [Report]
}
enum ReportOrdering {
createdAt_asc
createdAt_desc
} }

View File

@ -670,10 +670,12 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
factory.create('Report'), factory.create('Report'),
factory.create('Report'), factory.create('Report'),
factory.create('Report'), factory.create('Report'),
factory.create('Report'),
]) ])
const reportAgainstDagobert = reports[0] const reportAgainstDagobert = reports[0]
const reportAgainstTrollingPost = reports[1] const reportAgainstTrollingPost = reports[1]
const reportAgainstTrollingComment = reports[2] const reportAgainstTrollingComment = reports[2]
const reportAgainstDewey = reports[3]
// report resource first time // report resource first time
await Promise.all([ await Promise.all([
@ -695,6 +697,12 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
reasonDescription: 'This comment is bigoted', reasonDescription: 'This comment is bigoted',
}), }),
reportAgainstTrollingComment.relateTo(trollingComment, 'belongsTo'), reportAgainstTrollingComment.relateTo(trollingComment, 'belongsTo'),
reportAgainstDewey.relateTo(dagobert, 'filed', {
resourceId: 'u5',
reasonCategory: 'discrimination_etc',
reasonDescription: 'This user is harassing me!',
}),
reportAgainstDewey.relateTo(dewey, 'belongsTo'),
]) ])
// report resource a second time // report resource a second time

View File

@ -1731,7 +1731,7 @@ apollo-server-caching@^0.5.0:
dependencies: dependencies:
lru-cache "^5.0.0" lru-cache "^5.0.0"
apollo-server-core@^2.9.12, apollo-server-core@^2.9.13: apollo-server-core@^2.9.13:
version "2.9.13" version "2.9.13"
resolved "https://registry.yarnpkg.com/apollo-server-core/-/apollo-server-core-2.9.13.tgz#29fee69be56d30605b0a06cd755fd39e0409915f" resolved "https://registry.yarnpkg.com/apollo-server-core/-/apollo-server-core-2.9.13.tgz#29fee69be56d30605b0a06cd755fd39e0409915f"
integrity sha512-iXTGNCtouB0Xe37ySovuZO69NBYOByJlZfUc87gj0pdcz0WbdfUp7qUtNzy3onp63Zo60TFkHWhGNcBJYFluzw== integrity sha512-iXTGNCtouB0Xe37ySovuZO69NBYOByJlZfUc87gj0pdcz0WbdfUp7qUtNzy3onp63Zo60TFkHWhGNcBJYFluzw==
@ -7452,11 +7452,6 @@ serve-static@1.14.1:
version "1.14.1" version "1.14.1"
resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9"
integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==
dependencies:
encodeurl "~1.0.2"
escape-html "~1.0.3"
parseurl "~1.3.3"
send "0.17.1"
set-blocking@^2.0.0, set-blocking@~2.0.0: set-blocking@^2.0.0, set-blocking@~2.0.0:
version "2.0.0" version "2.0.0"

View File

@ -7,6 +7,7 @@
</client-only> </client-only>
</div> </div>
<reports-table :reports="reports" @confirm="openModal" /> <reports-table :reports="reports" @confirm="openModal" />
<paginate :hasNext="hasNext" :hasPrevious="hasPrevious" @back="back" @next="next" />
</ds-card> </ds-card>
</template> </template>
<script> <script>
@ -14,32 +15,41 @@ import { mapMutations } from 'vuex'
import DropdownFilter from '~/components/DropdownFilter/DropdownFilter' import DropdownFilter from '~/components/DropdownFilter/DropdownFilter'
import ReportsTable from '~/components/features/ReportsTable/ReportsTable' import ReportsTable from '~/components/features/ReportsTable/ReportsTable'
import { reportsListQuery, reviewMutation } from '~/graphql/Moderation.js' import { reportsListQuery, reviewMutation } from '~/graphql/Moderation.js'
import Paginate from '~/components/Paginate/Paginate'
export default { export default {
components: { components: {
DropdownFilter, DropdownFilter,
ReportsTable, ReportsTable,
Paginate,
}, },
data() { data() {
const pageSize = 25
return { return {
reports: [], reports: [],
allReports: [], allReports: [],
unreviewedReports: [], unreviewedReports: [],
reviewedReports: [], reviewedReports: [],
closedReports: [], closedReports: [],
pageSize,
first: pageSize,
offset: 0,
reviewed: null,
closed: null,
hasNext: false,
selected: this.$t('moderation.reports.filterLabel.all'), selected: this.$t('moderation.reports.filterLabel.all'),
} }
}, },
computed: { computed: {
filterOptions() { filterOptions() {
return [ return [
{ label: this.$t('moderation.reports.filterLabel.all'), value: this.allReports }, { label: this.$t('moderation.reports.filterLabel.all'), value: { reviewed: null } },
{ {
label: this.$t('moderation.reports.filterLabel.unreviewed'), label: this.$t('moderation.reports.filterLabel.unreviewed'),
value: this.unreviewedReports, value: { reviewed: false },
}, },
{ label: this.$t('moderation.reports.filterLabel.reviewed'), value: this.reviewedReports }, { label: this.$t('moderation.reports.filterLabel.reviewed'), value: { reviewed: true } },
{ label: this.$t('moderation.reports.filterLabel.closed'), value: this.closedReports }, { label: this.$t('moderation.reports.filterLabel.closed'), value: { closed: true } },
] ]
}, },
modalData() { modalData() {
@ -86,14 +96,24 @@ export default {
} }
} }
}, },
hasPrevious() {
return this.offset > 0
},
}, },
methods: { methods: {
...mapMutations({ ...mapMutations({
commitModalData: 'modal/SET_OPEN', commitModalData: 'modal/SET_OPEN',
}), }),
filter(option) { filter(option) {
this.reports = option.value
this.selected = option.label this.selected = option.label
this.offset = 0
if (option.value.closed) {
this.closed = option.value.closed
this.reviewed = null
return
}
this.closed = null
this.reviewed = option.value.reviewed
}, },
async confirmCallback(resource) { async confirmCallback(resource) {
const { disabled: disable, id: resourceId } = resource const { disabled: disable, id: resourceId } = resource
@ -111,16 +131,30 @@ export default {
openModal(report) { openModal(report) {
this.commitModalData(this.modalData(report)) this.commitModalData(this.modalData(report))
}, },
back() {
this.offset = Math.max(this.offset - this.pageSize, 0)
},
next() {
this.offset += this.pageSize
},
}, },
apollo: { apollo: {
reportsList: { reportsList: {
query: reportsListQuery(), query: reportsListQuery(),
variables() {
const { first, offset, reviewed, closed } = this
return {
orderBy: 'createdAt_desc',
reviewed,
closed,
first,
offset,
}
},
update({ reports }) { update({ reports }) {
if (!reports) return []
this.hasNext = reports.length >= this.pageSize
this.reports = reports this.reports = reports
this.allReports = reports
this.unreviewedReports = reports.filter(report => !report.reviewed)
this.reviewedReports = reports.filter(report => report.reviewed)
this.closedReports = reports.filter(report => report.closed)
}, },
fetchPolicy: 'cache-and-network', fetchPolicy: 'cache-and-network',
}, },

View File

@ -3,8 +3,20 @@ import gql from 'graphql-tag'
export const reportsListQuery = () => { export const reportsListQuery = () => {
// no limit for the moment like before: "reports(first: 20, orderBy: createdAt_desc)" // no limit for the moment like before: "reports(first: 20, orderBy: createdAt_desc)"
return gql` return gql`
query { query(
reports(orderBy: createdAt_desc) { $orderBy: ReportOrdering
$first: Int
$offset: Int
$reviewed: Boolean
$closed: Boolean
) {
reports(
orderBy: $orderBy
first: $first
offset: $offset
reviewed: $reviewed
closed: $closed
) {
id id
createdAt createdAt
updatedAt updatedAt
@ -114,7 +126,6 @@ export const reviewMutation = () => {
mutation($resourceId: ID!, $disable: Boolean, $closed: Boolean) { mutation($resourceId: ID!, $disable: Boolean, $closed: Boolean) {
review(resourceId: $resourceId, disable: $disable, closed: $closed) { review(resourceId: $resourceId, disable: $disable, closed: $closed) {
disable disable
closed
} }
} }
` `