From 1cfc4fd9d14f4b2197ff4e77a2df7b7801f643d5 Mon Sep 17 00:00:00 2001 From: Norm Rasmussen Date: Tue, 7 Mar 2023 17:52:36 -0500 Subject: [PATCH] Added instructions for the bulk add page. Starting to consolidate. Offloaded some get functions to a backup file that I don't need right now. --- app/__pycache__/routes.cpython-311.pyc | Bin 22215 -> 19016 bytes app/_old_functions.py | 76 +++++++++++ app/routes.py | 181 ++++++------------------- app/static/css/styles.css | 19 ++- app/templates/bulk_add.html | 35 ++++- app/templates/csv.html | 10 +- 6 files changed, 177 insertions(+), 144 deletions(-) create mode 100644 app/_old_functions.py diff --git a/app/__pycache__/routes.cpython-311.pyc b/app/__pycache__/routes.cpython-311.pyc index 74b9faf1e1fc3592eb8915d96ec1e48a88c6f4e0..3c3a805e781aa8c30345c3e61c96db6f604d5631 100644 GIT binary patch delta 2965 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 diff --git a/app/_old_functions.py b/app/_old_functions.py new file mode 100644 index 0000000..802b338 --- /dev/null +++ b/app/_old_functions.py @@ -0,0 +1,76 @@ + +@app.route("/get_courses", methods=["GET", "POST"]) +def get_courses(): + array = [] + course_dict = {} + pd.set_option("display.max_colwidth", 100) + count = 0 + dataframe = pd.DataFrame() + + if request.method == "POST": + while True: + count += 1 + endpoint = f"v2/courses?page={count}" + headers = {"accept": "application/json", "X-Api-Key": session["key"]} + response = requests.get(url + endpoint, headers=headers) + data = response.json() + nextlink = data["links"] + + for response in data["data"]: + uuid = response["id"] + course_dict = {"id": uuid} + for keys, values in response["attributes"].items(): + course_dict[keys] = values + array.append(course_dict) + dataframe = pd.DataFrame(array).drop( + ["list_image_url", "permalink"], axis=1 + ) + dataframe["full_description"] = dataframe[ + "full_description" + ].str.replace(r"<[^<>]*>", "", regex=True) + print(dataframe) + + if "next" not in nextlink: + break + + dfcourse = dataframe.to_html() + session["dfcsv"] = dataframe.to_csv() + return render_template("get.html", table=dfcourse, title="List of Courses") + else: + return "This isn't working. Let's go our own way." + + +@app.route("/get_people", methods=["GET", "POST"]) +def get_people(): + array = [] + ppl_dict = {} + count = 0 + dataframe = pd.DataFrame() + + if request.method == "POST": + print("get People POST") + while True: + count += 1 + endpoint = f"v2/people?page={count}" + headers = {"accept": "application/json", "X-Api-Key": session["key"]} + response = requests.get(url + endpoint, headers=headers) + data = response.json() + nextlink = data["links"] + + for response in data["data"]: + uuid = response["id"] + ppl_dict = {"id": uuid} + for keys, values in response["attributes"].items(): + ppl_dict[keys] = values + array.append(ppl_dict) + dataframe = pd.DataFrame(array).drop("custom_avatar_url", axis=1) + print(dataframe) + + if "next" not in nextlink: + break + + dfppl = dataframe.to_html() + session["dfcsv"] = dataframe.to_csv() + return render_template("get.html", table=dfppl, title="List of People") + else: + return render_template("get.html", error="Something went wrong") diff --git a/app/routes.py b/app/routes.py index c3a50d6..7e3db66 100644 --- a/app/routes.py +++ b/app/routes.py @@ -59,23 +59,13 @@ def correct_key(response): def allowed_file(filename): return "." in filename and filename.rsplit(".", 1)[1].lower() in ALLOWED_EXTENSIONS - @app.route("/dev", methods=["GET", "POST"]) def dev_test(): return render_template("options.html", title="Dev Test") # DONE: Remove header for main page. -# TODO: Leave boxes but change outcome depending if file has been uploaded. -""" -So create a session['file'] variable with the recently uploaded file name. -Then, when someone clicks one of the buttons, -after that if request == "POST", -create a secondary if statement for if file == session['file'], -directly upload emails etc else, -bring to the secondary pages already created and -allow them to copy and paste. -""" +# DONE: Leave boxes but change outcome depending if file has been uploaded. @app.route("/", methods=["GET", "POST"]) @@ -160,83 +150,6 @@ def table(): return render_template("table.html", tables=[session["dfhtml"]], titles=["Table"]) -@app.route("/get_courses", methods=["GET", "POST"]) -def get_courses(): - array = [] - course_dict = {} - pd.set_option("display.max_colwidth", 100) - count = 0 - dataframe = pd.DataFrame() - - if request.method == "POST": - while True: - count += 1 - endpoint = f"v2/courses?page={count}" - headers = {"accept": "application/json", "X-Api-Key": session["key"]} - response = requests.get(url + endpoint, headers=headers) - data = response.json() - nextlink = data["links"] - - for response in data["data"]: - uuid = response["id"] - course_dict = {"id": uuid} - for keys, values in response["attributes"].items(): - course_dict[keys] = values - array.append(course_dict) - dataframe = pd.DataFrame(array).drop( - ["list_image_url", "permalink"], axis=1 - ) - dataframe["full_description"] = dataframe[ - "full_description" - ].str.replace(r"<[^<>]*>", "", regex=True) - print(dataframe) - - if "next" not in nextlink: - break - - dfcourse = dataframe.to_html() - session["dfcsv"] = dataframe.to_csv() - return render_template("get.html", table=dfcourse, title="List of Courses") - else: - return "This isn't working. Let's go our own way." - - -@app.route("/get_people", methods=["GET", "POST"]) -def get_people(): - array = [] - ppl_dict = {} - count = 0 - dataframe = pd.DataFrame() - - if request.method == "POST": - print("get People POST") - while True: - count += 1 - endpoint = f"v2/people?page={count}" - headers = {"accept": "application/json", "X-Api-Key": session["key"]} - response = requests.get(url + endpoint, headers=headers) - data = response.json() - nextlink = data["links"] - - for response in data["data"]: - uuid = response["id"] - ppl_dict = {"id": uuid} - for keys, values in response["attributes"].items(): - ppl_dict[keys] = values - array.append(ppl_dict) - dataframe = pd.DataFrame(array).drop("custom_avatar_url", axis=1) - print(dataframe) - - if "next" not in nextlink: - break - - dfppl = dataframe.to_html() - session["dfcsv"] = dataframe.to_csv() - return render_template("get.html", table=dfppl, title="List of People") - else: - return render_template("get.html", error="Something went wrong") - - @app.route("/bulk_add_opts", methods=["GET", "POST"]) def bulk_add_opts(): array = [] @@ -327,12 +240,11 @@ def bulk_add(): if request.method == "POST": emails = request.form.get("emails") groups = request.form.get("groups") - print(emails) - print(type(emails)) if emails: if "\n" in emails: emails = emails.split("\n") emails = [email.strip() for email in emails] + emails = [re.sub(r'[,]', "", email) for email in emails] print(emails) print(type(emails)) # return api_add_ppl_groups(emails, groups) @@ -342,23 +254,18 @@ def bulk_add(): # return api_add_ppl_groups(emails, groups) if groups: if "\n" in groups: - groups.split("\n") + groups = groups.split("\n") groups = [group.strip() for group in groups] elif "," in groups: - groups.split(",") + groups = groups.split(",") groups = [group.strip() for group in groups] -# print(groups) -# print(type(groups)) -# print(emails) -# print(type(emails)) - return render_template('bulk_add.html') # for group in groups: # groupdict = {} - groupdict["name"] = group +# groupdict["name"] = group def api_add_ppl(emails): pass @@ -369,46 +276,14 @@ def api_add_groups(groups): def api_add_ppl_groups(emails, groups): - if not emails: - if not groups: - endpoint = "v2/bulk/people" - combinations = list(itertools.product(emails, groups)) - print(combinations) - payload = { - "data": { - "attributes": {"people": [{"email": emails, "groups": groups}]} - } - } - headers = { - "accept": "application/json", - "content-type": "application/json", - "X-Api-Key": session["key"], - } - response = requests.post(url + endpoint, json=payload, headers=headers) - response = str(response) - if "202" in response: - error = "Success! People have been added successfully." - return render_template( - "bulk_add_ppl.html", - table=session["dfgroups"], - title="People Added", - error=error, - ) - elif "403" in response: - error = "Uh oh. Looks like you don't have appropriate privileges." - elif "422" in response: - error = "Hm. Looks like something was wrong with the names." - return render_template( - "bulk_add_people.html", - table=session["dfgroups"], - title="People Added", - error=error, - ) - else: - error = "Shrug" - return render_template("bulk_add_ppl.html", title="Shrug", errors=error) endpoint = "v2/bulk/people" - payload = {"data": {"attributes": {"people": [{"email": emails}]}}} + combinations = list(itertools.product(emails, groups)) + print(combinations) + payload = { + "data": { + "attributes": {"people": [{"email": emails, "groups": groups}]} + } + } headers = { "accept": "application/json", "content-type": "application/json", @@ -437,6 +312,38 @@ def api_add_ppl_groups(emails, groups): else: error = "Shrug" return render_template("bulk_add_ppl.html", title="Shrug", errors=error) + +def api_add_ppl(): + endpoint = "v2/bulk/people" + payload = {"data": {"attributes": {"people": [{"email": emails}]}}} + headers = { + "accept": "application/json", + "content-type": "application/json", + "X-Api-Key": session["key"], + } + response = requests.post(url + endpoint, json=payload, headers=headers) + response = str(response) + if "202" in response: + error = "Success! People have been added successfully." + return render_template( + "bulk_add_ppl.html", + table=session["dfgroups"], + title="People Added", + error=error, + ) + elif "403" in response: + error = "Uh oh. Looks like you don't have appropriate privileges." + elif "422" in response: + error = "Hm. Looks like something was wrong with the names." + return render_template( + "bulk_add_people.html", + table=session["dfgroups"], + title="People Added", + error=error, + ) + else: + error = "Shrug" + return render_template("bulk_add_ppl.html", title="Shrug", errors=error) error = "No Data was Loaded. Try again, bozo." return render_template("bulk_add_ppl.html", title="No Data", errors=error) diff --git a/app/static/css/styles.css b/app/static/css/styles.css index c9d9872..8955a2c 100644 --- a/app/static/css/styles.css +++ b/app/static/css/styles.css @@ -132,14 +132,25 @@ img { text-decoration: none; } +.instructions-list{ + display:flex; + justify-content: center; + width: 100%; +} + li { - display: flex; + display: block; } .button-background { margin-right: 8px; } +.radio-options { + display: flex; + justify-content: inherit; +} + .navbutton { border-radius: 4px; margin-right: 4px; @@ -152,7 +163,8 @@ li { } .man-csv-opts { - display: flex + display: flex; + justify-content: space-evenly; } .csv-upload { @@ -193,7 +205,8 @@ li { } } ul { - display: flex; + display: block; + text-align: left; } /* 1.? - Card Layout in options.html only */ diff --git a/app/templates/bulk_add.html b/app/templates/bulk_add.html index c9f5e95..04c7108 100644 --- a/app/templates/bulk_add.html +++ b/app/templates/bulk_add.html @@ -4,15 +4,44 @@ {% include 'logo.html' %} {% block content %}

Please find your options below. Some things to note:

- {% if error %} +
+
+
    +
  • Left side - Manual entry: +
      +
    • Both fields don't need to be filled out!
    • +
    • You can add just people or just groups.
    • +
    • Adding both Emails and Groups will add all people to all groups.
    • +
    +
  • +
+
+ +
+
    +
  • Right side - CSV Upload: +
      +
    • The CSV will only look for one or both columns with the exact wording as the header row!
    • +
    • The Header rows must be Email and/or Groups
    • +
    • You can easily add people to multiple groups.
    • +
    • To add every person to every group, simply upload the CSV and select option 1 below.
    • +
    • For adding people to specific groups, format the csv as | Name | Group 1 | Group 2 | and select option 2 below.
    • +
    • There are no limits the number of people or groups that can be added.
    • +
    +
  • +
+
+
+{% if error %}

{{ error }}

{% endif %}

 

-

+

-

Please Copy and Paste Emails of learners you'd like to add

+

Emails

Please paste in the Group Names which these learners should be added to.

diff --git a/app/templates/csv.html b/app/templates/csv.html index c3069b1..82e66d8 100644 --- a/app/templates/csv.html +++ b/app/templates/csv.html @@ -1,11 +1,19 @@
-

If you'd like to upload a CSV. Please do so here:

+

If you'd like to upload a CSV. Please do so here:

+
+ + +
+
+ + +