Skip to content

Commit 5092e06

Browse files
author
“Carmel
committed
Restructure repo to support an app for linking Ldot and Qualtrics. Rewrite funtions to fit with the UI. Leave space for Ldot API requests.
1 parent 387e733 commit 5092e06

21 files changed

Lines changed: 932 additions & 49 deletions

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
venv/
1+
venv/
2+
new_ldot_workflows/ldot_config.json
3+
new_ldot_workflows/qualtrics_settings.py
10.7 KB
Binary file not shown.
-662 Bytes
Binary file not shown.

add_individual_to_survey.py

Lines changed: 20 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,9 @@
11
import requests
2-
from qualtrics_settings import BASE_URL, HEADERS, SURVEYIDS, QualtricsAPIError
2+
from new_ldot_workflows.qualtrics_settings import BASE_URL, HEADERS, SURVEYIDS, QualtricsAPIError
33

44
def get_mailing_list_id_of_distribution(survey_id: str, distribution_id: str) -> str:
5-
"""Get the mailing list ID connected to a distribution
6-
7-
Args:
8-
survey_id (str): The ID of the survey to add someone to.
9-
distribution_id (str): The ID of the distribution to get the mailing list ID for.
10-
11-
Raises:
12-
QualtricsAPIError: If there is an error while fetching the mailing list ID or format is unexpected.
13-
14-
Returns:
15-
str: The mailing list ID connected to the distribution.
16-
"""
5+
"""Get the mailing list ID connected to a distribution"""
6+
177
print("Finding mailing list ID of distribution... ")
188
endpoint = f"{BASE_URL}/distributions/{distribution_id}"
199
parameters = {
@@ -25,6 +15,7 @@ def get_mailing_list_id_of_distribution(survey_id: str, distribution_id: str) ->
2515
mailing_list_id = response.json()["result"]["recipients"]["mailingListId"]
2616

2717
return mailing_list_id
18+
2819
except requests.exceptions.RequestException as exc:
2920
raise QualtricsAPIError(
3021
f"Error while fetching mailing list ID for distribution {distribution_id}."
@@ -180,25 +171,29 @@ def check_inputs_validity(participant_study_id: str, embedded_data_field: str, s
180171

181172
def add_individual_to_survey(participant_study_id, embedded_data_field, survey_id, distribution_id):
182173
check_inputs_validity(participant_study_id, embedded_data_field, survey_id, distribution_id)
183-
184174
mailing_list_id = get_mailing_list_id_of_distribution(survey_id, distribution_id)
185-
directory_id = get_directory_id()
186-
contact_exists = check_contact_in_mailing_list(participant_study_id, mailing_list_id, directory_id)
175+
print(mailing_list_id)
176+
177+
# directory_id = get_directory_id()
178+
# contact_exists = check_contact_in_mailing_list(participant_study_id, mailing_list_id, directory_id)
187179

188-
if not contact_exists:
189-
add_contact_to_mailing_list(participant_study_id, mailing_list_id, directory_id)
190-
else:
191-
print(f"Participant study ID {participant_study_id} already exists in this mailing list")
180+
# if not contact_exists:
181+
# add_contact_to_mailing_list(participant_study_id, mailing_list_id, directory_id)
182+
# else:
183+
# print(f"Participant study ID {participant_study_id} already exists in this mailing list")
192184

193-
personal_link = get_personal_link(survey_id, distribution_id, participant_study_id)
194-
return personal_link
185+
# personal_link = get_personal_link(survey_id, distribution_id, participant_study_id)
186+
# return personal_link
195187

196188
if __name__ == "__main__":
197-
# Example usage
189+
# # Example usage
198190
participant_study_id = "11111TEST11111"
199-
survey_id=SURVEYIDS.my_test_survey_id
191+
survey_id="SV_efCMOg6wHU0T8ii"
200192
distribution_id="EMD_SZFeoK7LAJBHU4d"
201193
embedded_data_field = "study_id_child"
202194

203195
link = add_individual_to_survey(participant_study_id, embedded_data_field, survey_id, distribution_id)
204-
print(link)
196+
197+
198+
# # print(link)
199+
# print(get_mailing_list_id_of_distribution("SV_efCMOg6wHU0T8ii", "EMD_SZFeoK7LAJBHU4d"))

app.py

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
from flask import Flask, render_template, request, jsonify
2+
import requests
3+
4+
from new_ldot_workflows.b_2_get_qualtrics_links import add_individuals_to_survey
5+
from new_ldot_workflows.b_2_send_links_to_ldot import send_links_to_ldot
6+
from new_ldot_workflows.b_4_get_individual_progress import get_individual_progress
7+
8+
app = Flask(__name__)
9+
10+
# Study configurations - modify these as needed
11+
STUDIES = {
12+
"LDOT-001": {"name": "PIAMA study", "variables": {"survey_id": "SV_efCMOg6wHU0T8ii",
13+
"directory_id": "POOL_10pyxk9leSUisrT",
14+
"distribution_id": "EMD_7AEa416lRwFhrkF",
15+
"mailing_list_id": "CG_2dMbO6WUBMnCeIK",
16+
"embedded_data_field": "study_id_child"}},
17+
"LDOT-002": {"name": "LDOT Study 002", "variables": {"survey_id": "value3",
18+
"directory_id": "POOL_10pyxk9leSUisrT",
19+
"distribution_id": "EMD_7AEa416lRwFhrkF",
20+
"mailing_list_id": "value4",
21+
"embedded_data_field": "study_id_child"}},
22+
"LDOT-003": {"name": "LDOT Study 003", "variables": {"survey_id": "value5",
23+
"directory_id": "POOL_10pyxk9leSUisrT",
24+
"distribution_id": "EMD_7AEa416lRwFhrkF",
25+
"mailing_list_id": "value6",
26+
"embedded_data_field": "study_id_child"}},
27+
}
28+
29+
30+
@app.route("/")
31+
def index():
32+
return render_template("index.html", studies=STUDIES)
33+
34+
35+
@app.route("/api/button1", methods=["POST"])
36+
def button1():
37+
"""First API call"""
38+
data = request.json
39+
study_id = data.get("study_id")
40+
41+
# TODO: Replace this with your actual API call that returns subject IDs
42+
subject_ids = ["subject1", "subject2", "subject3"]
43+
44+
message = f"Found {len(subject_ids)} subject IDs for study {study_id}" if study_id else f"Found {len(subject_ids)} subject IDs"
45+
return jsonify({"success": True, "message": message, "subject_ids": subject_ids})
46+
47+
48+
49+
@app.route("/api/button2", methods=["POST"])
50+
def button2():
51+
"""Second API call - uses subjectIDs from button1"""
52+
data = request.json
53+
study_id = data.get("study_id")
54+
subject_ids = data.get("subject_ids")
55+
56+
if not study_id:
57+
return jsonify({"success": False, "message": "Missing study_id in request"}), 400
58+
59+
if not subject_ids:
60+
return jsonify({"success": False, "message": "Missing subject_ids in request"}), 400
61+
62+
# Lookup study variables from STUDIES config
63+
study = STUDIES.get(study_id)
64+
if not study:
65+
return jsonify({"success": False, "message": f"Unknown study_id: {study_id}"}), 400
66+
67+
vars = study.get("variables", {})
68+
survey_id = vars.get("survey_id")
69+
mailing_list_id = vars.get("mailing_list_id")
70+
embedded_data_field = vars.get("embedded_data_field")
71+
directory_id = vars.get("directory_id")
72+
distribution_id = vars.get("distribution_id")
73+
debug_inputs = {
74+
"study_id": study_id,
75+
"subject_ids": subject_ids,
76+
"survey_id": survey_id,
77+
"mailing_list_id": mailing_list_id,
78+
"embedded_data_field": embedded_data_field,
79+
"directory_id": directory_id,
80+
"distribution_id": distribution_id
81+
}
82+
83+
participant_to_link_dict = add_individuals_to_survey(subject_ids, embedded_data_field, distribution_id, survey_id, mailing_list_id, directory_id)
84+
send_links_to_ldot(participant_to_link_dict)
85+
86+
87+
# return jsonify({
88+
# "success": True,
89+
# "message": "Button 2 inputs resolved successfully",
90+
# "debug_inputs": debug_inputs,
91+
# "participant_to_link_dict": participant_to_link_dict
92+
# })
93+
94+
95+
@app.route("/api/button3", methods=["POST"])
96+
def button3():
97+
"""Third API call - returns list of subjectIDs"""
98+
data = request.json
99+
study_id = data.get("study_id")
100+
101+
# TODO: Add your API call logic here - should return a list of subjectIDs
102+
try:
103+
result = f"Button 3 executed for study {study_id}"
104+
# Return both message and subject_ids list
105+
subject_ids = [] # TODO: Fill this with actual subjectIDs from your API call
106+
return jsonify({"success": True, "message": result, "subject_ids": subject_ids})
107+
except Exception as e:
108+
return jsonify({"success": False, "message": str(e)})
109+
110+
111+
@app.route("/api/button4", methods=["POST"])
112+
def button4():
113+
"""Fourth API call - uses subjectIDs from button3"""
114+
data = request.json
115+
study_id = data.get("study_id")
116+
subject_ids = data.get("subject_ids") # List of subjectIDs from button3
117+
118+
if not study_id:
119+
return jsonify({"success": False, "message": "Missing study_id in request"}), 400
120+
121+
if not subject_ids:
122+
return jsonify({"success": False, "message": "Missing subject_ids in request"}), 400
123+
124+
study = STUDIES.get(study_id)
125+
if not study:
126+
return jsonify({"success": False, "message": f"Unknown study_id: {study_id}"}), 400
127+
128+
vars = study.get("variables", {})
129+
survey_id = vars.get("survey_id")
130+
embedded_data_field = vars.get("embedded_data_field")
131+
132+
participant_to_progress_dict = get_individual_progress(subject_ids, embedded_data_field, survey_id)
133+
134+
135+
return jsonify({
136+
"success": True,
137+
"message": f"Retrieved progress for {len(participant_to_progress_dict)} subjects",
138+
"study_id": study_id,
139+
"survey_id": survey_id,
140+
"embedded_data_field": embedded_data_field,
141+
"progress_results": participant_to_progress_dict,
142+
})
143+
144+
145+
if __name__ == "__main__":
146+
app.run(debug=True)

get_distributions.py

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import requests
2-
from qualtrics_settings import BASE_URL, HEADERS, SURVEYIDS
2+
from new_ldot_workflows.qualtrics_settings import BASE_URL, HEADERS, QualtricsAPIError
33

44
def get_distributions(survey_id):
55
endpoint = f"{BASE_URL}/distributions"
@@ -21,8 +21,69 @@ def get_distributions(survey_id):
2121

2222
if __name__ == "__main__":
2323
# Example usage
24-
survey_id = SURVEYIDS.my_test_survey_id
25-
result = get_distributions(survey_id)
24+
result = get_distributions("SV_efCMOg6wHU0T8ii")
2625
for res in result:
2726
print(res)
2827

28+
def get_mailing_list_id_of_distribution(survey_id: str, distribution_id: str) -> str:
29+
"""Get the mailing list ID connected to a distribution
30+
31+
Args:
32+
survey_id (str): The ID of the survey to add someone to.
33+
distribution_id (str): The ID of the distribution to get the mailing list ID for.
34+
35+
Raises:
36+
QualtricsAPIError: If there is an error while fetching the mailing list ID or format is unexpected.
37+
38+
Returns:
39+
str: The mailing list ID connected to the distribution.
40+
"""
41+
print("Finding mailing list ID of distribution... ")
42+
endpoint = f"{BASE_URL}/distributions/{distribution_id}"
43+
parameters = {
44+
"surveyId": survey_id
45+
}
46+
try:
47+
response = requests.get(endpoint, headers=HEADERS, params=parameters)
48+
response.raise_for_status()
49+
mailing_list_id = response.json()["result"]["recipients"]["mailingListId"]
50+
51+
return mailing_list_id
52+
except requests.exceptions.RequestException as exc:
53+
raise QualtricsAPIError(
54+
f"Error while fetching mailing list ID for distribution {distribution_id}."
55+
) from exc
56+
except (KeyError, TypeError, ValueError) as exc:
57+
raise QualtricsAPIError(
58+
f"Unexpected response format when fetching mailing list ID for distribution {distribution_id}."
59+
) from exc
60+
61+
def get_directory_id() -> str:
62+
"""Get the directory ID for a Qualtrics, assuming there is just one.
63+
64+
Raises:
65+
QualtricsAPIError: If there is an error while fetching the directory ID or format is unexpected.
66+
67+
Returns:
68+
str: The directory ID for the Qualtrics account.
69+
"""
70+
print("Getting directory ID... ")
71+
endpoint = f"{BASE_URL}/directories"
72+
parameters = {
73+
"includeCount": False
74+
}
75+
try:
76+
response = requests.get(endpoint, headers=HEADERS, params=parameters)
77+
response.raise_for_status()
78+
data = response.json()
79+
directory_id = data["result"]["elements"][0]["directoryId"]
80+
81+
return directory_id
82+
except requests.exceptions.RequestException as exc:
83+
raise QualtricsAPIError(
84+
f"Error while getting the directory ID."
85+
) from exc
86+
except (KeyError, TypeError, ValueError) as exc:
87+
raise QualtricsAPIError(
88+
f"Unexpected response format when fetching directory ID."
89+
) from exc

get_individual_progress.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import requests
2-
from qualtrics_settings import BASE_URL, HEADERS, SURVEYIDS, QualtricsAPIError
2+
from new_ldot_workflows.qualtrics_settings import BASE_URL, HEADERS, SURVEYIDS, QualtricsAPIError
33
import time
44
import zipfile
55
import io

new_ldot_workflows/__init__.py

Whitespace-only changes.
206 Bytes
Binary file not shown.
Binary file not shown.

0 commit comments

Comments
 (0)