Refactor frontend and 'reports' query again

This commit is contained in:
Wolfgang Huß 2019-11-07 15:54:26 +01:00
parent 446549d1b5
commit 2a23bbf101
12 changed files with 114 additions and 43 deletions

View File

@ -1,4 +1,5 @@
import uuid from 'uuid/v4' import uuid from 'uuid/v4'
import { undefinedToNullResolver } from './helpers/Resolver'
export default { export default {
Mutation: { Mutation: {
@ -38,17 +39,14 @@ export default {
if (disable === undefined) disable = false // default for creation if (disable === undefined) disable = false // default for creation
if (closed === undefined) closed = false // default for creation if (closed === undefined) closed = false // default for creation
cypherHeader = ` cypherHeader = `
MATCH (moderator:User {id: $moderatorId})
MATCH (resource {id: $resourceId}) MATCH (resource {id: $resourceId})
WHERE resource:User OR resource:Comment OR resource:Post WHERE resource: User OR resource: Comment OR resource: Post
OPTIONAL MATCH (:User)-[lastDecision:DECIDED {last: true}]->(resource)
SET (CASE WHEN lastDecision IS NOT NULL THEN lastDecision END).last = false
WITH resource
MATCH (moderator:User {id: $moderatorId})
CREATE (resource)<-[decision:DECIDED]-(moderator) CREATE (resource)<-[decision:DECIDED]-(moderator)
SET decision.last = true SET decision.last = true
WITH decision, resource, moderator
OPTIONAL MATCH (:User)-[lastDecision:DECIDED {last: true}]->(resource)
SET (
CASE
WHEN lastDecision IS NOT NULL
THEN lastDecision END).last = false
` `
} else { } else {
// an open decision … // an open decision …
@ -77,24 +75,20 @@ export default {
} }
let decisionUUID = null let decisionUUID = null
let cypherClosed = '' let cypherClosed = ''
// if (closed) { if (closed) {
// decisionUUID = uuid() decisionUUID = uuid()
// cypherClosed = ` cypherClosed = `
// OPTIONAL MATCH (:User)-[report:REPORTED {closed: false}]->(resource) WITH decision, resource, moderator
// SET report.closed = true, report.decisionUuid = $decisionUUID OPTIONAL MATCH (:User)-[report:REPORTED {closed: false}]->(resource)
// SET decision.uuid = $decisionUUID SET (CASE WHEN report IS NOT NULL THEN report END).closed = true
// ` SET (CASE WHEN report IS NOT NULL THEN report END).decisionUuid = $decisionUUID
// } SET decision.uuid = $decisionUUID
`
}
const cypher = const cypher =
cypherHeader + cypherHeader +
`SET ( `SET (CASE WHEN decision.createdAt IS NOT NULL THEN decision END).updatedAt = toString(datetime())
CASE SET (CASE WHEN decision.createdAt IS NULL THEN decision END).createdAt = toString(datetime())
WHEN decision.createdAt IS NOT NULL
THEN decision END).updatedAt = toString(datetime())
SET (
CASE
WHEN decision.createdAt IS NULL
THEN decision END).createdAt = toString(datetime())
SET decision.disable = $disable, decision.closed = $closed SET decision.disable = $disable, decision.closed = $closed
SET resource.disabled = $disable SET resource.disabled = $disable
` + ` +
@ -148,4 +142,7 @@ export default {
return createdRelationshipWithNestedAttributes return createdRelationshipWithNestedAttributes
}, },
}, },
DECIDED: {
...undefinedToNullResolver(['updatedAt', 'uuid']),
},
} }

View File

@ -1,3 +1,5 @@
import { undefinedToNullResolver } from './helpers/Resolver'
export default { export default {
Mutation: { Mutation: {
report: async (_parent, params, context, _resolveInfo) => { report: async (_parent, params, context, _resolveInfo) => {
@ -11,7 +13,7 @@ export default {
MATCH (submitter:User {id: $submitterId}) MATCH (submitter:User {id: $submitterId})
MATCH (resource {id: $resourceId}) MATCH (resource {id: $resourceId})
WHERE resource:User OR resource:Comment OR resource:Post WHERE resource:User OR resource:Comment OR resource:Post
CREATE (resource)<-[report:REPORTED {createdAt: $createdAt, reasonCategory: $reasonCategory, reasonDescription: $reasonDescription}]-(submitter) CREATE (resource)<-[report:REPORTED {createdAt: $createdAt, reasonCategory: $reasonCategory, reasonDescription: $reasonDescription, closed: false}]-(submitter)
RETURN report, submitter, resource, labels(resource)[0] as type RETURN report, submitter, resource, labels(resource)[0] as type
`, `,
{ {
@ -78,7 +80,9 @@ export default {
const cypher = ` const cypher = `
MATCH (submitter:User)-[report:REPORTED]->(resource) MATCH (submitter:User)-[report:REPORTED]->(resource)
WHERE resource:User OR resource:Comment OR resource:Post WHERE resource:User OR resource:Comment OR resource:Post
RETURN report, submitter, resource, labels(resource)[0] as type OPTIONAL MATCH (:User)-[decision:DECIDED {uuid: report.decisionUuid}]->(resource)
OPTIONAL MATCH (:User)-[decisionPending:DECIDED {last: true}]->(resource)
RETURN report, submitter, resource, labels(resource)[0] as type, decision, decisionPending
${orderByClause} ${orderByClause}
` `
const result = await session.run(cypher, {}) const result = await session.run(cypher, {})
@ -88,16 +92,28 @@ export default {
submitter: r.get('submitter'), submitter: r.get('submitter'),
resource: r.get('resource'), resource: r.get('resource'),
type: r.get('type'), type: r.get('type'),
decision: r.get('decision'),
decisionPending: r.get('decisionPending'),
} }
}) })
if (!dbResponse) return null if (!dbResponse) return null
response = [] response = []
dbResponse.forEach(ele => { dbResponse.forEach(ele => {
const { report, submitter, resource, type } = ele const { report, submitter, resource, type, decision, decisionPending } = ele
const responseEle = { const responseEle = {
...report.properties, ...report.properties,
decisionAt: decision
? decision.properties.updatedAt
: decisionPending
? decisionPending.properties.updatedAt
: null,
decisionDisable: decision
? decision.properties.disable
: decisionPending
? decisionPending.properties.disable
: null,
post: null, post: null,
comment: null, comment: null,
user: null, user: null,
@ -122,7 +138,19 @@ export default {
session.close() session.close()
} }
// Wolle console.log('response: ')
// response.forEach((ele, index) => {
// // console.log('ele #', index, ': ', ele)
// // if (ele.decision === undefined)
// // console.log('ele #', index, ': ', ele)
// if (ele.decision) console.log('ele #', index, ': ', ele)
// })
// // Wolle console.log('response: ', response)
return response return response
}, },
}, },
REPORTED: {
...undefinedToNullResolver(['decisionUuid', 'decisionAt', 'decisionDisable']),
},
} }

View File

@ -411,6 +411,7 @@ describe('report resources', () => {
}) })
}) })
}) })
describe('query for reported resource', () => { describe('query for reported resource', () => {
const reportsQuery = gql` const reportsQuery = gql`
query { query {

View File

@ -5,8 +5,7 @@ type DECIDED {
# reasonDescription: String # reasonDescription: String
disable: Boolean! disable: Boolean!
closed: Boolean! closed: Boolean!
uuid: ID
# internal
last: Boolean! last: Boolean!
moderator: User moderator: User
@ -15,7 +14,7 @@ type DECIDED {
# resource: ReportResource # resource: ReportResource
# @cypher(statement: "MATCH (resource)<-[:DECIDED]-(:User) RETURN resource") # @cypher(statement: "MATCH (resource)<-[:DECIDED]-(:User) RETURN resource")
type: String type: String
@cypher(statement: "MATCH (resource)<-[:DECIDED]-(:User) RETURN labels(resource)[0]") @cypher(statement: "MATCH (resource)<-[:DECIDED]-(user:User) RETURN labels(resource)[0]")
user: User user: User
post: Post post: Post
comment: Comment comment: Comment

View File

@ -1,7 +1,16 @@
type REPORTED { type REPORTED {
createdAt: String createdAt: String!
reasonCategory: ReasonCategory reasonCategory: ReasonCategory!
reasonDescription: String reasonDescription: String!
closed: Boolean!
decisionUuid: ID
decisionDisable: Boolean
decisionAt: String
# Wolle decision: DECIDED
# @cypher(statement: "MATCH (resource)<-[decision:DECIDED {uuid: $decisionUuid}]-(user:User) RETURN decision")
submitter: User submitter: User
@cypher(statement: "MATCH (resource)<-[:REPORTED]-(user:User) RETURN user") @cypher(statement: "MATCH (resource)<-[:REPORTED]-(user:User) RETURN user")
# not yet supported # not yet supported
@ -12,8 +21,6 @@ type REPORTED {
user: User user: User
post: Post post: Post
comment: Comment comment: Comment
# decided: DECIDED
} }
# this list equals the strings of an array in file "webapp/constants/modals.js" # this list equals the strings of an array in file "webapp/constants/modals.js"

View File

@ -697,6 +697,14 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
// report content a second time // report content a second time
authenticatedUser = await dewey.toJson() authenticatedUser = await dewey.toJson()
await Promise.all([ await Promise.all([
mutate({
mutation: reportMutation,
variables: {
resourceId: 'c5',
reasonCategory: 'doxing',
reasonDescription: "That's my friends privat data!",
},
}),
mutate({ mutate({
mutation: reportMutation, mutation: reportMutation,
variables: { variables: {

View File

@ -20,5 +20,8 @@ MATCH (moderator:User)-[disabled:DISABLED]->(resource)
DELETE disabled DELETE disabled
CREATE (moderator)-[decision:DECIDED]->(resource) CREATE (moderator)-[decision:DECIDED]->(resource)
SET decision.createdAt = toString(datetime()), decision.disable = true, decision.last = true, decision.closed = false SET decision.createdAt = toString(datetime()), decision.disable = true, decision.last = true, decision.closed = false
RETURN decision; WITH decision
MATCH (:User)-[report:REPORTED]->(resource)
SET report.closed = false
RETURN decision, report;
" | cypher-shell " | cypher-shell

View File

@ -8,6 +8,10 @@ export const reportListQuery = () => {
createdAt createdAt
reasonCategory reasonCategory
reasonDescription reasonDescription
closed
decisionUuid
decisionAt
decisionDisable
type type
submitter { submitter {
id id

View File

@ -454,8 +454,9 @@
"type": "Typ", "type": "Typ",
"content": "Inhalt", "content": "Inhalt",
"author": "Autor", "author": "Autor",
"decision": "Entscheidung", "decided": "Entschieden",
"noDecision": "Keine Entscheidung!", "noDecision": "Keine Entscheidung!",
"enabledBy": "Aktiviert von",
"disabledBy": "Deaktiviert von", "disabledBy": "Deaktiviert von",
"reasonCategory": "Kategorie", "reasonCategory": "Kategorie",
"reasonDescription": "Beschreibung", "reasonDescription": "Beschreibung",

View File

@ -455,8 +455,9 @@
"type": "Type", "type": "Type",
"content": "Content", "content": "Content",
"author": "Author", "author": "Author",
"decision": "Decision", "decided": "Decided",
"noDecision": "No decision!", "noDecision": "No decision!",
"enabledBy": "Enabled by",
"disabledBy": "Disabled by", "disabledBy": "Disabled by",
"reasonCategory": "Category", "reasonCategory": "Category",
"reasonDescription": "Description", "reasonDescription": "Description",

View File

@ -87,17 +87,30 @@
<span v-else></span> <span v-else></span>
</td> </td>
<td class="ds-table-col ds-table-head-col-border"> <td class="ds-table-col ds-table-head-col-border">
<!-- disabledBy --> <!-- closed -->
<span v-if="content.closed" class="decision">
{{ $t('moderation.reports.decided') }}
</span>
<span v-else class="no-decision">
{{ $t('moderation.reports.noDecision') }}
</span>
<!-- decidedByModerator -->
<div v-if="content.resource.decidedByModerator"> <div v-if="content.resource.decidedByModerator">
{{ $t('moderation.reports.disabledBy') }}
<br /> <br />
<div v-if="content.decisionDisable">
{{ $t('moderation.reports.disabledBy') }}
</div>
<div v-else>
{{ $t('moderation.reports.enabledBy') }}
</div>
<hc-user <hc-user
:user="content.resource.decidedByModerator" :user="content.resource.decidedByModerator"
:showAvatar="false" :showAvatar="false"
:trunc="30" :trunc="30"
:date-time="content.decisionAt"
positionDatetime="below"
/> />
</div> </div>
<span v-else class="no-decision">{{ $t('moderation.reports.noDecision') }}</span>
</td> </td>
</tr> </tr>
<tr> <tr>
@ -175,6 +188,7 @@ export default {
reports: { reports: {
immediate: true, immediate: true,
handler(newReports) { handler(newReports) {
// Wolle console.log('newReports: ', newReports)
const newReportedContentStructure = [] const newReportedContentStructure = []
newReports.forEach(report => { newReports.forEach(report => {
const resource = const resource =
@ -192,6 +206,10 @@ export default {
if (idx === -1) { if (idx === -1) {
idx = newReportedContentStructure.length idx = newReportedContentStructure.length
newReportedContentStructure.push({ newReportedContentStructure.push({
closed: report.closed,
decisionUuid: report.decisionUuid,
decisionAt: report.decisionAt,
decisionDisable: report.decisionDisable,
type: report.type, type: report.type,
resource, resource,
user: report.user, user: report.user,
@ -203,6 +221,7 @@ export default {
} }
newReportedContentStructure[idx].reports.push(report) newReportedContentStructure[idx].reports.push(report)
}) })
// Wolle console.log('newReportedContentStructure: ', newReportedContentStructure)
this.reportedContentStructure = newReportedContentStructure this.reportedContentStructure = newReportedContentStructure
}, },
}, },
@ -221,6 +240,9 @@ export default {
.ds-table-head-col-border { .ds-table-head-col-border {
border-bottom: $border-color-softer dotted $border-size-base; border-bottom: $border-color-softer dotted $border-size-base;
} }
.decision {
color: $color-secondary;
}
.no-decision { .no-decision {
color: $text-color-danger; color: $text-color-danger;
} }