Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(Contributor Recognition Infrastructure) Milestone2.4: Add certificate generation for contributors (including service method, API controller) #16513

Merged
merged 156 commits into from
Jan 27, 2023
Merged
Show file tree
Hide file tree
Changes from 153 commits
Commits
Show all changes
156 commits
Select commit Hold shift + click to select a range
c798e78
service file name changed to backend-api
chris7716 Jan 9, 2021
218b79c
backend api file added
chris7716 Jan 9, 2021
d03d579
previous service file removed from CODEOWNERS
chris7716 Jan 9, 2021
536a551
new backend service file added to CODEOWNERS
chris7716 Jan 9, 2021
b853c9a
Merge remote-tracking branch 'upstream/develop' into develop
chris7716 Jan 18, 2021
cab061f
Merge remote-tracking branch 'upstream/develop' into develop
chris7716 Jan 19, 2021
7f746b9
Merge remote-tracking branch 'upstream/develop' into develop
chris7716 Jan 29, 2021
63a9988
Merge branch 'oppia:develop' into develop
chris7716 Oct 1, 2021
40e6c29
Merge branch 'oppia:develop' into develop
chris7716 Nov 12, 2021
1e042a8
Merge branch 'develop' of https://github.com/oppia/oppia into develop
chris7716 Aug 23, 2022
6d2e59b
Merge branch 'develop' of https://github.com/oppia/oppia into develop
chris7716 Aug 27, 2022
ec06909
Merge branch 'develop' of https://github.com/oppia/oppia into develop
chris7716 Sep 9, 2022
82b8dae
Merge branch 'develop' of https://github.com/oppia/oppia into develop
chris7716 Sep 20, 2022
ac53598
First pass
chris7716 Sep 27, 2022
e211ca5
First pass
chris7716 Sep 27, 2022
4573973
Finalize views
chris7716 Oct 12, 2022
fb63259
Add stats component
chris7716 Oct 12, 2022
09f468a
Resolve conflicts and refactor new component
chris7716 Oct 14, 2022
d214681
Cover tests for stats component
chris7716 Oct 17, 2022
53b2d18
Improve mobile views
chris7716 Oct 21, 2022
2fb9fee
Remove mock responses
chris7716 Oct 21, 2022
d0da489
Remove unwanted spaces
chris7716 Oct 21, 2022
99f6370
Add question stats update
chris7716 Oct 22, 2022
e7b36a9
First pass
chris7716 Nov 1, 2022
9f920c5
Add minor changes
chris7716 Nov 1, 2022
d0d071b
Address comments
chris7716 Nov 2, 2022
f9f5aea
First pass
chris7716 Nov 8, 2022
9b30d40
Add new component
chris7716 Nov 8, 2022
b531b27
Address changes
chris7716 Nov 10, 2022
0b3b099
Rollback unwanted changes
chris7716 Nov 10, 2022
b809d10
Add initial changes
chris7716 Nov 11, 2022
1ce5521
Address comments
chris7716 Nov 12, 2022
f25c22c
Merge branch 'develop' of https://github.com/oppia/oppia into milesto…
chris7716 Nov 14, 2022
fd17e52
AAddress comments
chris7716 Nov 15, 2022
71027ce
Address comments
chris7716 Nov 15, 2022
03f0520
Remove language from PageableStats
chris7716 Nov 15, 2022
464a643
Address more comments
chris7716 Nov 16, 2022
5185a0a
Merge branch 'milestone2.2' of https://github.com/chris7716/oppia int…
chris7716 Nov 16, 2022
4eb23e3
Address more comments
chris7716 Nov 16, 2022
4386afe
Remove unwanted changes
chris7716 Nov 16, 2022
0452ed7
Address more comments
chris7716 Nov 17, 2022
98a5b45
Fix checks
chris7716 Nov 17, 2022
b9988aa
Fix checks
chris7716 Nov 17, 2022
db831ae
Fix checks
chris7716 Nov 17, 2022
81d9631
Fix checks
chris7716 Nov 17, 2022
de42554
Fix checks
chris7716 Nov 17, 2022
37d34c5
Fix checks
chris7716 Nov 17, 2022
85ebdc4
Fix checks
chris7716 Nov 17, 2022
396ad54
Fix checks
chris7716 Nov 17, 2022
fbb9297
Fix checks
chris7716 Nov 17, 2022
3f6bce0
Fix checks
chris7716 Nov 17, 2022
dbc75cc
Fix checks
chris7716 Nov 17, 2022
235d239
Fix checks
chris7716 Nov 17, 2022
629ad5e
Fix checks
chris7716 Nov 17, 2022
6eca00f
Fix checks
chris7716 Nov 17, 2022
bc3a956
Fix checks
chris7716 Nov 17, 2022
cae961b
Address comments
chris7716 Nov 17, 2022
8f916fe
Fix checks
chris7716 Nov 18, 2022
d59efdc
Fix checks
chris7716 Nov 18, 2022
c82bd7d
Fix checks
chris7716 Nov 18, 2022
d42a694
Fix checks
chris7716 Nov 18, 2022
c91ea46
Fix checks
chris7716 Nov 18, 2022
a679859
Fix checks
chris7716 Nov 18, 2022
03b5447
Fix checks
chris7716 Nov 18, 2022
e17316d
Fix checks
chris7716 Nov 18, 2022
49c6873
Fix checks
chris7716 Nov 18, 2022
dfce935
Fix checks
chris7716 Nov 18, 2022
2536999
Fix checks
chris7716 Nov 18, 2022
ccb99ad
Fix checks
chris7716 Nov 18, 2022
990ed1d
Fix checks
chris7716 Nov 18, 2022
e5ded5d
Fix checks
chris7716 Nov 18, 2022
773fbe1
Fix checks
chris7716 Nov 18, 2022
cac4619
Fix checks
chris7716 Nov 18, 2022
d442f5c
Fix checks
chris7716 Nov 18, 2022
018f498
Fix checks
chris7716 Nov 18, 2022
f23b1bb
Fix checks
chris7716 Nov 18, 2022
8b3814c
Resolve conflicts
chris7716 Nov 18, 2022
a04050f
Addressed comments
chris7716 Nov 18, 2022
db8b955
Merge branch 'milestone2.2' of https://github.com/chris7716/oppia int…
chris7716 Nov 19, 2022
18058b6
Fix comments
chris7716 Nov 19, 2022
687c494
Address comments
chris7716 Nov 20, 2022
5c7b82d
Fix dates
chris7716 Nov 20, 2022
2146998
Update branch[C
chris7716 Nov 21, 2022
42216f4
Fix tests
chris7716 Nov 21, 2022
68ddfeb
Update branch[C
chris7716 Nov 21, 2022
b01fb27
Fix fe tests
chris7716 Nov 21, 2022
d360b8b
Address changes
chris7716 Nov 21, 2022
3a707c4
Address changes
chris7716 Nov 21, 2022
b24ed22
Address changes
chris7716 Nov 21, 2022
496ef43
Address changes
chris7716 Nov 21, 2022
31de14a
Address changes
chris7716 Nov 21, 2022
6643673
Address changes
chris7716 Nov 21, 2022
544acea
Address changes
chris7716 Nov 21, 2022
0f0ac82
Address changes
chris7716 Nov 21, 2022
9aeff51
Compress svgs
chris7716 Nov 21, 2022
e43bb52
Address changes
chris7716 Nov 22, 2022
e0709a1
Address changes
chris7716 Nov 22, 2022
0225537
Address changes
chris7716 Nov 22, 2022
d0e77ff
Address changes
chris7716 Nov 23, 2022
85b54fc
Resolve conflicts
chris7716 Nov 23, 2022
50d919a
Resolve conflicts
chris7716 Nov 25, 2022
31c86d4
Cooment address
chris7716 Nov 25, 2022
f8f4426
fix nits
chris7716 Nov 25, 2022
bbd2d18
Add logo for the certificate
chris7716 Nov 25, 2022
670bfe1
Address eval comments
chris7716 Nov 26, 2022
f782890
Update
chris7716 Nov 26, 2022
77493b7
Address comments
chris7716 Nov 26, 2022
41da8f3
Address comments
chris7716 Nov 26, 2022
aba7fe1
Address comments
chris7716 Nov 26, 2022
78652f8
Address comments
chris7716 Nov 26, 2022
4ca2bdf
Fix lint
chris7716 Nov 26, 2022
1cb6391
Fix lint
chris7716 Nov 26, 2022
e532dc9
Fix lint
chris7716 Nov 26, 2022
3dac23d
Fix lint
chris7716 Nov 26, 2022
b5ecdf5
Fix lint
chris7716 Nov 26, 2022
b2de5f9
Fix lint
chris7716 Nov 26, 2022
9ebc01d
Fix lint
chris7716 Nov 26, 2022
38e61d1
Address comments and fix checks
chris7716 Nov 27, 2022
ea61791
Address comments and fix checks
chris7716 Nov 27, 2022
861661e
Address comments and fix checks
chris7716 Nov 27, 2022
5e7db44
Address comments and fix checks
chris7716 Nov 27, 2022
66d57a9
Address comments and fix checks
chris7716 Nov 27, 2022
597bd42
Merge branch 'develop' of https://github.com/oppia/oppia into milesto…
chris7716 Nov 27, 2022
afabab3
Address comments and fix checks
chris7716 Nov 27, 2022
c9ef252
Address comments and fix checks
chris7716 Nov 27, 2022
ad379ed
Address comments and fix checks
chris7716 Nov 28, 2022
fb948aa
Address comments and fix checks
chris7716 Nov 28, 2022
0fd619d
Merge branch 'develop' of https://github.com/oppia/oppia into milesto…
chris7716 Nov 28, 2022
3d29a00
Address comments and fix checks
chris7716 Nov 28, 2022
a6a75ae
Address comments and fix checks
chris7716 Nov 28, 2022
3267f34
Address comments and fix checks
chris7716 Nov 28, 2022
4206987
Address comments and fix checks
chris7716 Nov 28, 2022
ad06a77
Remove lib and use html canvas
chris7716 Dec 5, 2022
32b26a4
fix tests
chris7716 Dec 5, 2022
40c4bf9
fix tests
chris7716 Dec 5, 2022
50e7978
Fix bugs
chris7716 Dec 6, 2022
a8b0f5a
Fix nits
chris7716 Dec 6, 2022
a9e2b60
Address changes
chris7716 Dec 11, 2022
6078309
Address changes
chris7716 Dec 12, 2022
d9bc1b6
Merge branch 'develop' of https://github.com/oppia/oppia into milesto…
chris7716 Dec 12, 2022
abbbd34
Address changes
chris7716 Dec 12, 2022
3a2d442
Address changes
chris7716 Dec 12, 2022
e1ac5e1
Resolve conflicts
chris7716 Dec 28, 2022
566bf72
Address changes
chris7716 Dec 29, 2022
12f3a76
Address changes
chris7716 Dec 29, 2022
3f9e963
Merge branch 'develop' of https://github.com/oppia/oppia into milesto…
chris7716 Jan 11, 2023
966e1b6
Merge branch 'develop' of https://github.com/oppia/oppia into milesto…
chris7716 Jan 12, 2023
27348f3
Address comments
chris7716 Jan 16, 2023
c46f507
Fix lint
chris7716 Jan 16, 2023
aaf02c0
Fix lint
chris7716 Jan 16, 2023
2ca1cb0
Merge branch 'develop' of https://github.com/oppia/oppia into milesto…
chris7716 Jan 26, 2023
43c8d6e
Address comments
chris7716 Jan 26, 2023
7596dbc
Reduce signature font size
chris7716 Jan 27, 2023
aa5f20d
Merge branch 'develop' of https://github.com/oppia/oppia into milesto…
chris7716 Jan 27, 2023
1d54ca8
Address comments
chris7716 Jan 27, 2023
718a103
Merge branch 'develop' of https://github.com/oppia/oppia into milesto…
chris7716 Jan 27, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion assets/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,10 @@ export default {
// eslint-disable-next-line max-len
"MATH_SVG_FILENAME_REGEX": "mathImg_[a-z0-9_]+_height_[0-9d]+_width_[0-9d]+_vertical_[0-9d]+.(svg)$",

// This regex validates whether a given string is in the format of YYYY-MM-DD
// format.
"DATE_REGEX": "^[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}$",

// The SVG tag-specific attribute allowlist is based on the list of tags and
// and attributes specified in this project:
// https://github.com/cure53/DOMPurify
Expand Down Expand Up @@ -6928,5 +6932,7 @@ export default {
"param_changes", "auto_tts_enabled", "correctness_feedback_enabled",
"edits_allowed"
],
"NON_METADATA_PROPERTIES": ["id", "states"]
"NON_METADATA_PROPERTIES": ["id", "states"],
"CONTRIBUTOR_CERTIFICATE_WIDTH": 1493,
"CONTRIBUTOR_CERTIFICATE_HEIGHT": 1313
} as const;
8 changes: 7 additions & 1 deletion assets/images/contributor_dashboard/locked-badge.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
79 changes: 79 additions & 0 deletions core/controllers/contributor_dashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

from __future__ import annotations

import datetime
import json

from core import feconf
Expand Down Expand Up @@ -935,6 +936,84 @@ def get(
self.render_json(self.values)


class ContributorCertificateHandler(
base.BaseHandler[Dict[str, str], Dict[str, str]]
):
"""Returns contributor certificate."""

GET_HANDLER_ERROR_RETURN_TYPE = feconf.HANDLER_TYPE_JSON
URL_PATH_ARGS_SCHEMAS = {
'username': {
'schema': {
'type': 'basestring',
'validators': [{
'id': 'has_length_at_most',
'max_value': constants.MAX_USERNAME_LENGTH
}]
}
},
'suggestion_type': {
'schema': {
'type': 'basestring',
'choices': feconf.SUGGESTION_TYPE_CHOICES
}
}
}
HANDLER_ARGS_SCHEMAS = {
'GET': {
'from_date': {
'schema': {
'type': 'basestring',
'validators': [{
'id': 'is_regex_matched',
'regex_pattern': constants.DATE_REGEX
}]
}
},
'to_date': {
'schema': {
'type': 'basestring',
'validators': [{
'id': 'is_regex_matched',
'regex_pattern': constants.DATE_REGEX
}]
}
},
'language': {
'schema': {
'type': 'basestring',
'validators': [{
'id': 'is_supported_audio_language_code'
}]
},
'default_value': None
},
}
}

@acl_decorators.can_fetch_all_contributor_dashboard_stats
def get(
self, username: str, suggestion_type: str
) -> None:
"""Handles GET requests."""
assert self.normalized_request is not None
from_date = self.normalized_request['from_date']
to_date = self.normalized_request['to_date']
language = self.normalized_request.get('language')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
language = self.normalized_request.get('language')
language = self.normalized_request['language']

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we will have to use the self.normalized_request.get('language') because when generating the question certificate, we do not include language param in the request and it throws KeyError: 'language' if we use self.normalized_request['language']

We can get the the default value which is set as None if we use self.normalized_request.get('language') when language is not included in the request.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, right, sorry.


from_datetime = datetime.datetime.strptime(from_date, '%Y-%m-%d')
to_datetime = datetime.datetime.strptime(to_date, '%Y-%m-%d')
if to_datetime.date() > datetime.datetime.now().date():
raise self.InvalidInputException(
'To date should not be a future date.')

response = suggestion_services.generate_contributor_certificate_data(
username, suggestion_type, language, from_datetime,
to_datetime)

self.render_json(response)


class ContributorAllStatsSummariesHandler(
base.BaseHandler[Dict[str, str], Dict[str, str]]
):
Expand Down
72 changes: 72 additions & 0 deletions core/controllers/contributor_dashboard_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1943,3 +1943,75 @@ def test_get_all_stats_of_other_users_raises_error(self) -> None:
self.OWNER_USERNAME))

self.logout()

def test_get_contributor_certificate(self) -> None:
score_category: str = (
suggestion_models.SCORE_TYPE_TRANSLATION +
suggestion_models.SCORE_CATEGORY_DELIMITER + 'English')
change_cmd = {
'cmd': 'add_translation',
'content_id': 'content',
'language_code': 'hi',
'content_html': '',
'state_name': 'Introduction',
'translation_html': '<p>Translation for content.</p>'
}
suggestion_models.GeneralSuggestionModel.create(
feconf.SUGGESTION_TYPE_TRANSLATE_CONTENT,
feconf.ENTITY_TYPE_EXPLORATION,
'exp1', 1, suggestion_models.STATUS_ACCEPTED, self.owner_id,
self.OWNER_USERNAME, change_cmd, score_category,
'exploration.exp1.thread_6', 'hi')
from_date = datetime.datetime.today() - datetime.timedelta(days=1)
from_date_str = from_date.strftime('%Y-%m-%d')
to_date = datetime.datetime.today()
to_date_str = to_date.strftime('%Y-%m-%d')

self.login(self.OWNER_EMAIL)

response = self.get_json(
'/contributorcertificate/%s/%s?language=%s&'
'from_date=%s&to_date=%s' % (
self.OWNER_USERNAME, feconf.SUGGESTION_TYPE_TRANSLATE_CONTENT,
'hi', from_date_str, to_date_str
)
)

self.assertEqual(
response,
{
'from_date': from_date.strftime('%d %b %Y'),
'to_date': to_date.strftime('%d %b %Y'),
'contribution_hours': '0.01',
'team_lead': feconf.TRANSLATION_TEAM_LEAD,
'language': 'Hindi'
}
)

self.logout()

def test_get_contributor_certificate_raises_invalid_date_exception(
self
) -> None:
from_date = datetime.datetime.today() - datetime.timedelta(days=1)
from_date_str = from_date.strftime('%Y-%m-%d')
to_date = datetime.datetime.today() + datetime.timedelta(days=1)
to_date_str = to_date.strftime('%Y-%m-%d')

self.login(self.OWNER_EMAIL)

response = self.get_json(
'/contributorcertificate/%s/%s?language=%s&'
'from_date=%s&to_date=%s' % (
self.OWNER_USERNAME, feconf.SUGGESTION_TYPE_TRANSLATE_CONTENT,
'hi', from_date_str, to_date_str
),
expected_status_int=400
)

self.assertEqual(
response['error'],
'To date should not be a future date.'
)

self.logout()
46 changes: 46 additions & 0 deletions core/domain/suggestion_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -1823,6 +1823,52 @@ def to_frontend_dict(self) -> QuestionReviewStatsFrontendDict:
}


class ContributorCertificateInfoDict(TypedDict):
"""Dictionary representing the ContributorCertificateInfo object."""

from_date: str
to_date: str
team_lead: str
contribution_hours: str
language: Optional[str]


class ContributorCertificateInfo:
"""Encapsulates key information that is used to generate contributor
certificate.
"""

def __init__(
self,
from_date: str,
to_date: str,
team_lead: str,
contribution_hours: str,
language: Optional[str]
) -> None:
self.from_date = from_date
self.to_date = to_date
self.team_lead = team_lead
self.contribution_hours = contribution_hours
self.language = language

def to_dict(self) -> ContributorCertificateInfoDict:
"""Returns a dict representation of a ContributorCertificateInfo
domain object.

Returns:
dict. A dict representation of a ContributorCertificateInfo
domain object.
"""
return {
'from_date': self.from_date,
'to_date': self.to_date,
'team_lead': self.team_lead,
'contribution_hours': self.contribution_hours,
'language': self.language
}


class ContributorMilestoneEmailInfo:
"""Encapsulates key information that is used to create the email content for
notifying contributors about milestones they achieved.
Expand Down
Loading