Skip to content

Commit

Permalink
Merge pull request #77 from rigdenlab/development
Browse files Browse the repository at this point in the history
Updates to GDPR, Travis CI and Docker deployment
  • Loading branch information
FilomenoSanchez authored Jul 9, 2020
2 parents 36b2809 + 05a049e commit 3f9d697
Show file tree
Hide file tree
Showing 14 changed files with 246 additions and 68 deletions.
6 changes: 3 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
language: python

python:
- "3.7"
- "3.6"

cache: pip

install:
- sudo apt-get update
- python3.7 -m pip install -r requirements.txt
- python3.6 -m pip install -r requirements.txt

script:
- python3.7 tests.py
- python3.6 tests.py
8 changes: 8 additions & 0 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,14 @@ def toggle_gdpr_policy_modal(n_clicks):
return callback_utils.toggle_modal(trigger)


@app.callback(Output('create-user-button', 'disabled'),
[Input('gdpr-agreement-checkbox', 'checked')],
[State('create-user-button', 'disabled')])
def toggle_createuser_button(checked, disabled):
trigger = dash.callback_context.triggered[0]
return callback_utils.toggle_createuserbutton(trigger, disabled)


@app.callback(Output({'type': 'tutorial-modal', 'index': MATCH}, 'is_open'),
[Input({'type': 'tutorial-button', 'index': MATCH}, 'n_clicks')])
def toggle_tutorial_modal(n_clicks):
Expand Down
42 changes: 42 additions & 0 deletions components/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,42 @@ def SessionStoreModal(*args, **kwargs):
return SessionStoreModal(*args, **kwargs)


def GdprPolicySectionOne(*args, **kwargs):
from components.paragraphs import GdprPolicySectionOne

return GdprPolicySectionOne(*args, **kwargs)


def GdprPolicySectionTwo(*args, **kwargs):
from components.paragraphs import GdprPolicySectionTwo

return GdprPolicySectionTwo(*args, **kwargs)


def GdprPolicySectionThree(*args, **kwargs):
from components.paragraphs import GdprPolicySectionThree

return GdprPolicySectionThree(*args, **kwargs)


def GdprPolicySectionFour(*args, **kwargs):
from components.paragraphs import GdprPolicySectionFour

return GdprPolicySectionFour(*args, **kwargs)


def GdprPolicySectionFive(*args, **kwargs):
from components.paragraphs import GdprPolicySectionFive

return GdprPolicySectionFive(*args, **kwargs)


def GdprPolicySectionSix(*args, **kwargs):
from components.paragraphs import GdprPolicySectionSix

return GdprPolicySectionSix(*args, **kwargs)


def TutorialOneModal(*args, **kwargs):
from components.modals import TutorialOneModal

Expand All @@ -39,6 +75,12 @@ def TutorialTwoModal(*args, **kwargs):
return TutorialTwoModal(*args, **kwargs)


def GdprAgreementCheckbox(*args, **kwargs):
from components.inputgroups import GdprAgreementCheckbox

return GdprAgreementCheckbox(*args, **kwargs)


def GdprPolicyModal(*args, **kwargs):
from components.modals import GdprPolicyModal

Expand Down
5 changes: 2 additions & 3 deletions components/cards.py
Original file line number Diff line number Diff line change
Expand Up @@ -322,11 +322,10 @@ def CreateUserCard():
components.InvalidNewUserCollapse(),
html.Br(),
dbc.Spinner(html.Div(id='success-create-user-alert-div')),
components.GdprAgreementCheckbox(),
html.Br(),
dbc.Button("Create new user", color="primary", block=True, id='create-user-button'),
html.Br(),
dbc.Button("Create new user", color="primary", block=True, id='create-user-button', disabled=True),
]),
dbc.CardFooter([components.GdprPolicyModal(), components.GdprPolicyAlert()])
])


Expand Down
13 changes: 13 additions & 0 deletions components/inputgroups.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import dash_bootstrap_components as dbc
import dash_html_components as html
from loaders import AdditionalDatasetReference
from parsers import ContactFormats
from components import EmailIssueReference, UserReadableTrackNames
from utils.plot_utils import DefaultTrackLayout
from utils import UrlIndex


def ContactFormatSelector():
Expand Down Expand Up @@ -178,3 +180,14 @@ def SuperimposeSwitch(superimpose):
),
], className='mr-1'
)


def GdprAgreementCheckbox():
return dbc.FormGroup(
[
dbc.Checkbox(id="gdpr-agreement-checkbox", className="form-check-input"),
dbc.Label([
"I read and agree to ConPlot ",
dbc.CardLink(html.U("Privacy Policy"), href=UrlIndex.PRIVACY_POLICY.value)
], html_for="standalone-checkbox", className="form-check-label", style={'margin-top': 2.5})
], check=True)
69 changes: 10 additions & 59 deletions components/modals.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from components import StartNewSessionLink, GdprRightsList, AutomaticInfoCollectedList, CustomFormatFieldsHelpList
import components
import dash_bootstrap_components as dbc
import dash_html_components as html
from utils import UrlIndex
Expand Down Expand Up @@ -86,7 +86,7 @@ def SessionTimedOutModal():
dbc.ModalBody([
html.P("""More than 15 minutes have passed since you last interacted with the website and your session has
timed-out.""", style={'text-align': "justify"}),
StartNewSessionLink()
components.StartNewSessionLink()
]),
], id='missing-fields-modal', is_open=True, backdrop='static', keyboard=False)

Expand Down Expand Up @@ -169,7 +169,7 @@ def CustomFormatDescriptionModal():
'this file is intended to be used with. Subsequent lines indicate records to be added in the '
'track, each defined using three fields, which are separated by white spaces:',
style={"text-align": "justify"}),
CustomFormatFieldsHelpList(),
components.CustomFormatFieldsHelpList(),
html.P('Bellow there is a sample of the first four lines of an example custom file. As you can see, '
'this sample corresponds with a file created for a protein containing 168 residues. In this '
'case, three records have been created, a record with color "3" that spans between residues 1 '
Expand All @@ -192,72 +192,23 @@ def GdprPolicyModal():
dbc.ModalBody([
dbc.Row([
html.H4('1. Introduction'),
html.P('ConPlot (also referred to as ‘we’ throughout this text) is committed to protect user data and '
'privacy. The purpose of this text is to provide you with information about how the data we '
'collect from users of ConPlot is used or shared. We may update this Privacy Notice from time '
'to time. We encourage you re-visit this text frequently and take note of the date of the last '
'update on the field above. We do not use or share any of your personal information for any '
'purpose unrelated to the functionality of the website; however, we do collect some '
'information to help us understand how our site is being used in order to improve community '
'support and to enhance the ConPlot user’s experience when visiting our site.'
, style={"text-align": "justify"}),
components.GdprPolicySectionOne(),
html.Br(),
html.H4('2. Information Automatically Collected'),
html.P(['When you browse ConPlot, certain information about your visit will be collected. We '
'automatically collect and store the following type of information about your visit:',
AutomaticInfoCollectedList(),
'This automatically collected information does not identify you personally unless you include '
'personally identifying information in a support form request; see the “Get in Touch” policy '
'below for details. We use this information to measure the number of visitors to our site. '
'The aggregate data may be included in prospectuses and reports to funding agencies.'
], style={"text-align": "justify"}),
components.GdprPolicySectionTwo(),
html.Br(),
html.H4('3. Information You Directly Provide'),
html.P('Storing, sharing sessions and any other user account related features of the ConPlot requires '
'that you register for an account. You will be required to provide an email address so we can '
'send you your temporary account password in case you forget this password. An anonymous email '
'service can be used if you do not want to provide personally identifying information. Your '
'email address will not be used to send you alerts or notifications. Any email address '
'provided in this site will only be used to get in touch with you in case your forget your '
'password or you request assistance from us. We do not sell or distribute email addresses to '
'third parties. We also ask for an user name when creating an account. If you share a session '
'with another user, this user name will be displayed with the shared session. We will not sell '
'or distribute your user name or institution to third parties. When you log in, the client IP '
'address is recorded. This IP address can be correlated with the address automatically '
'collected as noted above. If your user profile personally identifies you, then it may be '
'possible to associate you with your detailed activity on the ConPlot website.',
style={"text-align": "justify"}),
components.GdprPolicySectionThree(),
html.Br(),
html.H4('4. "Get in Touch" Form'),
html.P('The header on each ConPlot site includes a “Get in Touch” link to a form where users can '
'submit general inquiries, bug reports or request assistance if they forget their passwords. '
'Submissions through this form are emailed to members of the Rigden Lab at the University of '
'Liverpool. The form includes a field for an email address. If the email address identifies you '
'personally, say if you use your institutional email, then your correspondence with us will '
'likewise be linked to you. A valid email is not strictly required, although we cannot reply to '
'you without one. When you submit the form, your IP address and browser version will be '
'recorded for internal use. In the case of reported bugs or other site errors, this '
'information may be used by technical staff to help locate your session in the server logs to '
'aid in troubleshooting the issue. This does have the side effect of making it possible to '
'associate an IP address with an email address which may, in turn, personally identify you. '
'However, ConPlot does not publicly release this information.', style={"text-align": "justify"}),
components.GdprPolicySectionFour(),
html.Br(),
html.H4('5. How ConPlot uses cookies'),
html.P('ConPlot uses cookies to associate multiple requests by your web browser into a stateful '
'session. Cookies are essential to track the state of session. Some cookies persist only for a '
'single session. The information is recorded temporarily and is erased when the user quits the '
'session or closes the browser. Others may be persistently stored on the hard drive of your '
'computer until you manually delete them from a browser folder or until they expire, which can '
'be months after they were last used. Cookies can be disabled in your browser (refer to your '
'browser’s documentation for instructions); however, the majority of the website functionality '
'will be unavailable if cookies are disabled.', style={"text-align": "justify"}),
components.GdprPolicySectionFive(),
html.Br(),
html.H4('6. Your Rights based on the General Data Protection Regulation (GDPR)'),
html.P(['If you wish to know more about your rights under the General Data Protection Regulation '
'(GDPR), you can do this ', html.A(html.U('here'), href=UrlIndex.GDPR_WEBSITE.value),
'. Here is a summary of what this includes:'],
style={"text-align": "left"}),
GdprRightsList(),
components.GdprPolicySectionSix(),
components.GdprRightsList(),
], justify='center', align='center', className='m-0'),
]),
], id='gdpr-policy-modal', is_open=False, size='xl', scrollable=True, centered=True, autoFocus=True)
Expand Down
90 changes: 90 additions & 0 deletions components/paragraphs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import dash_html_components as html
from components import AutomaticInfoCollectedList
from utils import UrlIndex


def GdprPolicySectionOne():
return html.P(
'ConPlot (also referred to as ‘we’ throughout this text) is committed to protect user '
'data and privacy. The purpose of this text is to provide you with information about '
'how the data we collect from users of ConPlot is used or shared. We may update this '
'Privacy Notice from time to time. We encourage you re-visit this text frequently '
'and take note of the date of the last update on the field above. We do not use or '
'share any of your personal information for any purpose unrelated to the '
'functionality of the website; however, we do collect some information to help us '
'understand how our site is being used in order to improve community support and to '
'enhance the ConPlot user’s experience when visiting our site.'
, style={"text-align": "justify"})


def GdprPolicySectionTwo():
return html.P(
['When you browse ConPlot, certain information about your visit will be collected. We '
'automatically collect and store the following type of information about your visit:',
AutomaticInfoCollectedList(),
'This automatically collected information does not identify you personally unless you '
'include personally identifying information in a support form request; see the “Get '
'in Touch” policy below for details. We use this information to measure the number '
'of visitors to our site. '
'The aggregate data may be included in prospectuses and reports to funding agencies.'
], style={"text-align": "justify"})


def GdprPolicySectionThree():
return html.P(
'Storing, sharing sessions and any other user account related features of ConPlot require '
'that you register for an account. To register, you will be required to provide an email address, '
'a username and a password. By choosing to create a user account you give us permission to retain this '
'information, which will be used only for verification of you as a user and for anonymous '
'statistics. We require an email address so we can send you a temporary account password in '
'case you forget this password. An anonymous email service can be used if you do not want to provide '
'personally identifying information. Your email address will not be used to send you alerts or '
'notifications. Any email address provided in this site will only be used to get in touch with you '
'in case your forget your password or you request assistance from us. We do not sell or distribute '
'email addresses to third parties. We also ask for a user name when creating an account. We will '
'not sell or distribute your user name or institution to third parties. When you log '
'in, the client IP address is recorded. If your user profile personally identifies you, then it may be '
'possible to associate you with your detailed activity on the ConPlot website. After registering as a '
'user, by choosing to store a session you give us permission to retain the data you provided '
'within that session. This includes the contents and file names of all the files you have uploaded '
'to ConPlot, the name chosen for the session and the date in which the session was stored. If you '
'share a session with another user, all this data will be accessible to the other user, and '
'it will be displayed together with your username. All this information is visible by members of the '
'ConPlot team, however it will only be used for development purposes as we will not publicly '
'release this information or share it with any third parties.', style={"text-align": "justify"})


def GdprPolicySectionFour():
return html.P(
'The header on each ConPlot site includes a “Get in Touch” link to a form where users can '
'submit general inquiries, bug reports or request assistance if they forget their passwords. '
'Submissions through this form are emailed to members of the Rigden Lab at the University of '
'Liverpool. The form includes a field for an email address. If the email address identifies you '
'personally, say if you use your institutional email, then your correspondence with us will '
'likewise be linked to you. A valid email is not strictly required, although we cannot reply to '
'you without one. When you submit the form, your IP address and browser version will be '
'recorded for internal use. In the case of reported bugs or other site errors, this '
'information may be used by technical staff to help locate your session in the server logs to '
'aid in troubleshooting the issue. This does have the side effect of making it possible to '
'associate an IP address with an email address which may, in turn, personally identify you. '
'However, ConPlot does not publicly release this information.',
style={"text-align": "justify"})


def GdprPolicySectionFive():
return html.P(
'ConPlot uses cookies to associate multiple requests by your web browser into a stateful '
'session. Cookies are essential to track the state of session. Some cookies persist only for a '
'single session. The information is recorded temporarily and is erased when the user quits the '
'session or closes the browser. Others may be persistently stored on the hard drive of your '
'computer until you manually delete them from a browser folder or until they expire, which can '
'be months after they were last used. Cookies can be disabled in your browser (refer to your '
'browser’s documentation for instructions); however, the majority of the website functionality '
'will be unavailable if cookies are disabled.', style={"text-align": "justify"})


def GdprPolicySectionSix():
return html.P([
'If you wish to know more about your rights under the General Data Protection Regulation '
'(GDPR), you can do this ', html.A(html.U('here'), href=UrlIndex.GDPR_WEBSITE.value),
'. Here is a summary of what this includes:'], style={"text-align": "left"})
6 changes: 6 additions & 0 deletions layouts/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ def noPage(*args, **kwargs):
return noPage(*args, **kwargs)


def PrivacyPolicy(*args, **kwargs):
from layouts.privacypolicy import PrivacyPolicy

return PrivacyPolicy(*args, **kwargs)


def Home(*args, **kwargs):
from layouts.home import Home

Expand Down
Loading

0 comments on commit 3f9d697

Please sign in to comment.