Skip to content

Commit c737e24

Browse files
✨ add certified flag (#337)
- This creates the certified flag that can be added by a specialist when one of his specialties matches one of the question's tags. - Automatically add the certified flag when the answer is edited by a specialist - Automatically remove the certified flag when the tag corresponding to the certified answer is removed
1 parent 7f04f6d commit c737e24

File tree

21 files changed

+443
-91
lines changed

21 files changed

+443
-91
lines changed

.circleci/config.yml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ executors:
4545
user: prisma
4646
password: prisma
4747
migrations: true
48-
4948
jobs:
5049
server-lint:
5150
executor: app-builder
@@ -174,7 +173,6 @@ jobs:
174173
clever login --secret=$CLEVER_SECRET --token=$CLEVER_TOKEN
175174
clever link << parameters.clever-app-id >>
176175
clever deploy --force
177-
178176
prisma-deploy-service:
179177
executor: app-builder
180178
steps:
@@ -220,7 +218,6 @@ jobs:
220218
clever login --secret=$CLEVER_SECRET --token=$CLEVER_TOKEN
221219
clever link << parameters.clever-app-id >>
222220
clever deploy --force
223-
224221
workflows:
225222
version: 2
226223
build-deploy:

client/src/components/Flags/Flag.jsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ const flagMeta = {
2121
unanswered: {
2222
icon: 'help_outline',
2323
color: '#157B5F'
24+
},
25+
certified: {
26+
icon: 'verified',
27+
color: '#caac00'
2428
}
2529
}
2630

@@ -52,13 +56,15 @@ Flag.translations = {
5256
duplicate: 'duplicate',
5357
outdated: 'outdated',
5458
incomplete: 'incomplete',
55-
unanswered: 'unanswered'
59+
unanswered: 'unanswered',
60+
certified: 'certified'
5661
},
5762
fr: {
5863
duplicate: 'doublon',
5964
outdated: 'obsolète',
6065
incomplete: 'incomplète',
61-
unanswered: 'sans réponse'
66+
unanswered: 'sans réponse',
67+
certified: 'certifiée'
6268
}
6369
}
6470

client/src/contexts/User/queries.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ export const GET_ME = gql`
88
name
99
email
1010
picture
11+
specialties {
12+
name
13+
}
1114
}
1215
}
1316
`
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
export const answerCanBeCertified = (specialties, tags, answer, flagTypes) => {
2+
if (answer) {
3+
tags.forEach(tag => {
4+
specialties.forEach(specialty => {
5+
if (tag.label.name === specialty.name) {
6+
flagTypes.push('certified')
7+
}
8+
})
9+
})
10+
}
11+
}

client/src/scenes/Question/queries.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ export const zNodeFragment = `
2626
id
2727
name
2828
picture
29+
specialties {
30+
name
31+
}
2932
}
3033
createdAt
3134
}

client/src/scenes/Question/scenes/Answer/Answer.jsx

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,28 @@
1-
import React, { useState } from 'react'
2-
import PropTypes from 'prop-types'
3-
import { Redirect, Prompt } from 'react-router-dom'
41
import { useApolloClient } from '@apollo/react-hooks'
2+
import PropTypes from 'prop-types'
3+
import { useState } from 'react'
4+
import { Prompt, Redirect } from 'react-router-dom'
55

6-
import { SUBMIT_ANSWER, EDIT_ANSWER } from './queries'
6+
import { EDIT_ANSWER, SUBMIT_ANSWER } from './queries'
77

8-
import { alert, markdown, getIntl } from 'services'
98
import { onListChange } from 'helpers'
9+
import { alert, getIntl, markdown } from 'services'
1010

1111
import NotFound from 'scenes/NotFound'
1212

13-
import { Loading, Flags, Button, MarkdownEditor, CtrlEnter, PairInputList } from 'components'
14-
import Card, { CardTitle, CardText, CardActions, PermanentClosableCard } from 'components/Card'
13+
import { Button, CtrlEnter, Flags, Loading, MarkdownEditor, PairInputList } from 'components'
14+
import Card, { CardActions, CardText, CardTitle, PermanentClosableCard } from 'components/Card'
1515

1616
import { ActionMenu } from '../../components'
1717

18-
import { sourcesToKeyValuePairs, keyValuePairsToSources, canSubmit } from './helpers'
18+
import { canSubmit, keyValuePairsToSources, sourcesToKeyValuePairs } from './helpers'
1919

2020
import Tips from './components/Tips'
2121

2222
const Answer = ({ zNode }) => {
23-
const [state, setState] = useState(() => {
24-
const answer = zNode && zNode.answer
23+
const answer = zNode && zNode.answer
2524

25+
const [state, setState] = useState(() => {
2626
const initialText = answer ? answer.content : ''
2727
const initialSources = sourcesToKeyValuePairs(answer ? answer.sources : [])
2828

@@ -44,7 +44,7 @@ const Answer = ({ zNode }) => {
4444

4545
const { loadingSubmit, slug, showTips, sources } = state
4646

47-
const onTextChange = value => setState(state => ({ ...state, answer: value }))
47+
const onTextChange = value => setState({ ...state, answer: value })
4848
const onSourcesChange = onListChange(
4949
changes => setState(state => ({ ...state, ...changes(state) })),
5050
'sources'

client/src/scenes/Question/scenes/Edit/Edit.jsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
import React, { useState } from 'react'
2-
import PropTypes from 'prop-types'
3-
import { Redirect, Prompt } from 'react-router-dom'
41
import { useApolloClient } from '@apollo/react-hooks'
2+
import PropTypes from 'prop-types'
3+
import { useState } from 'react'
4+
import { Prompt, Redirect } from 'react-router-dom'
55

6-
import { SUBMIT_QUESTION, EDIT_QUESTION } from './queries'
6+
import { EDIT_QUESTION, SUBMIT_QUESTION } from './queries'
77

88
import { alert, getIntl } from 'services'
99

10-
import Card, { CardText, CardActions, PermanentClosableCard } from 'components/Card'
11-
import { Loading, Button, Input, CtrlEnter, TagPicker } from 'components'
10+
import { Button, CtrlEnter, Input, Loading, TagPicker } from 'components'
11+
import Card, { CardActions, CardText, PermanentClosableCard } from 'components/Card'
1212

1313
import { ActionMenu } from '../../components'
1414

client/src/scenes/Question/scenes/Read/Read.jsx

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
1-
import React, { useState, useEffect } from 'react'
1+
import { useMutation } from '@apollo/react-hooks'
22
import PropTypes from 'prop-types'
3-
import { Link, Redirect } from 'react-router-dom'
3+
import { useEffect, useState } from 'react'
44
import { Helmet } from 'react-helmet'
5-
import { useMutation } from '@apollo/react-hooks'
5+
import { Link, Redirect } from 'react-router-dom'
66

7-
import { CREATE_FLAG, REMOVE_FLAG, INCREMENT_VIEWS_COUNTER } from './queries'
7+
import { CREATE_FLAG, INCREMENT_VIEWS_COUNTER, REMOVE_FLAG } from './queries'
88

9-
import { markdown, getIntl } from 'services'
9+
import { getIntl, markdown } from 'services'
1010

1111
import NotFound from 'scenes/NotFound'
1212

13-
import { Loading, Button, Flags, Tags } from 'components'
14-
import Card, { CardTitle, CardText } from 'components/Card'
13+
import { Button, Flags, Loading, Tags } from 'components'
14+
import Card, { CardText, CardTitle } from 'components/Card'
1515
import Dropdown, { DropdownItem } from 'components/Dropdown'
1616

1717
import { ActionMenu } from '../../components'
18-
import { Views, FlagsDropdown, Sources, Meta, Share, History } from './components'
18+
import { FlagsDropdown, History, Meta, Share, Sources, Views } from './components'
1919

2020
const Read = ({ history, match, zNode, loading }) => {
2121
const [loaded, setLoaded] = useState(false)
@@ -56,7 +56,7 @@ const Read = ({ history, match, zNode, loading }) => {
5656
</Helmet>
5757
<ActionMenu backLink="/" backLabel={intl('menu.home')} goBack>
5858
<FlagsDropdown
59-
flags={zNode.flags}
59+
zNode={zNode}
6060
onSelect={type => createFlag({ variables: { type, nodeId: zNode.id } })}
6161
onRemove={type => removeFlag({ variables: { type, nodeId: zNode.id } })}
6262
/>

client/src/scenes/Question/scenes/Read/components/FlagsDropdown/FlagsDropdown.jsx

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,26 @@
1-
import React from 'react'
21
import PropTypes from 'prop-types'
32

43
import { getIntl } from 'services'
54

6-
import { Flag, flagMeta } from 'components/Flags'
7-
import Dropdown, { DropdownItem } from 'components/Dropdown'
85
import Button from 'components/Button'
6+
import Dropdown, { DropdownItem } from 'components/Dropdown'
7+
import { Flag, flagMeta } from 'components/Flags'
98

109
import './FlagsDropdown.css'
10+
import { answerCanBeCertified } from 'helpers/answerCanBeCertified'
11+
import { useUser } from 'contexts'
1112

12-
const FlagsDropdown = ({ flags, onSelect, onRemove }) => {
13+
const FlagsDropdown = ({ zNode, onSelect, onRemove }) => {
1314
const intl = getIntl(FlagsDropdown)
1415
const flagIntl = getIntl(Flag)
1516

17+
const { flags, tags, answer } = zNode
18+
const { specialties } = useUser()
19+
1620
const flagTypes = ['incomplete', 'outdated', 'duplicate']
1721

22+
answerCanBeCertified(specialties, tags, answer, flagTypes)
23+
1824
const items = flagTypes.map(type => {
1925
const isSelected = flags.filter(f => f.type === type).length > 0
2026
return (

client/src/scenes/UserProfile/UserProfile.jsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { alert, getIntl } from 'services'
77
import { Avatar, Button, Card, Modal, Loading, Input } from 'components'
88

99
import Logs from './components/Logs'
10+
1011
import Specialties from './components/Specialties'
1112

1213
import { UPDATE_INDENTITY, DELETE_IDENTITY } from './queries'

0 commit comments

Comments
 (0)