From 11c21159c73bfd6c5c90611be59352ce9198803a Mon Sep 17 00:00:00 2001 From: Jaimos Skriletz Date: Sat, 12 Sep 2026 20:18:23 -0600 Subject: [PATCH] Move system achievements out of modelCourse. System achievements should not be placed in a course. This way any changes to them will propagate to all courses using them. Instead courses should be able to create local overrides of system achievements as needed. This moves all of the default achievement evaluators and icons out of the modelCourse and places them in a system location. Then logic is added to determine if an achievement asset, either an icon or an evaluator, has a course override, or the system default should be used. In order to better validate path names, icons, evaluators, and notification templates are no longer allowed to have a slash in their name and be an absolute or relative path. In addition all paths are checked they are actual files and not directories. All course achievement assets must be placed in their appropriate directory without any subdirectories. The achievement list editor will add a message if the name is invalid (contains a slash) or is overriding a system asset, and now has javascript validation to not allow saving new data unless the evaluator file and icon file do not contain a slash. The achievement evaluator editor has been updated to inform the user if they are editing a system achievement and will create a course override, and provide a tab to revert to the system achievement. In addition JavaScript validation has been added to the achievement evaluator editor and achievement notification editor. Some icons were updated in this change to better work with dark mode. This includes adding a default achievement which is white circle with a black outline and a "?" in it to match other badges, a white background inside two icons in which this was not done, and there was a small white boundary around some of the level achievements that was removed. This patch was designed and mostly written by me, but Claude helped test it and provided some feedback, along with Claude mostly wrote the achievement notifications editor code based on what I already did to the achievement editor and help write the javascript validation for the slash in filenames on the AchivementList editor. One thing Claude pointed out was I didn't consider if an asset name was "." or "..", which would not lead to accessing the directory so wasn't technically needed. This lead me to change the tests from '-e' to '-f' to ensure a file exists that isn't a directory. --- .typos.toml | 2 +- .../achievementEvaluators}/back_for_more.at | 0 .../achievementEvaluators}/challenge_eight.at | 0 .../achievementEvaluators}/challenge_five.at | 0 .../achievementEvaluators}/challenge_four.at | 0 .../achievementEvaluators}/challenge_nine.at | 0 .../achievementEvaluators}/challenge_one.at | 0 .../achievementEvaluators}/challenge_seven.at | 0 .../achievementEvaluators}/challenge_six.at | 0 .../achievementEvaluators}/challenge_ten.at | 0 .../achievementEvaluators}/challenge_three.at | 0 .../achievementEvaluators}/challenge_two.at | 0 .../achievementEvaluators}/challenger.at | 0 .../achievementEvaluators}/chipping_away.at | 0 .../complete_n_problems.at | 0 .../achievementEvaluators}/complete_n_sets.at | 0 .../achievementEvaluators}/crack_o_dawn.at | 0 .../default_achievements.axp | 0 .../achievementEvaluators}/early_bird.at | 0 .../earn_n_achievements.at | 0 .../example_complete_n_specific_problems.at | 0 .../example_complete_n_specific_sets.at | 0 .../example_complete_specific_problem.at | 0 .../example_complete_specific_set.at | 0 .../achievementEvaluators}/extensions.at | 0 .../achievementEvaluators}/extensions.axp | 0 .../hows_your_finger.at | 0 .../achievementEvaluators}/last_minute.at | 0 .../achievementEvaluators}/level_eight.at | 0 .../achievementEvaluators}/level_five.at | 0 .../achievementEvaluators}/level_four.at | 0 .../achievementEvaluators}/level_nine.at | 0 .../achievementEvaluators}/level_one.at | 0 .../achievementEvaluators}/level_seven.at | 0 .../achievementEvaluators}/level_six.at | 0 .../achievementEvaluators}/level_ten.at | 0 .../achievementEvaluators}/level_three.at | 0 .../achievementEvaluators}/level_two.at | 0 .../n_correct_in_a_row.at | 0 .../achievementEvaluators}/night_owl.at | 0 .../achievementEvaluators}/on_one_hand.at | 0 .../achievementEvaluators}/on_the_hour.at | 0 .../achievementEvaluators}/one_click.at | 0 .../achievementEvaluators}/persistence.at | 0 .../really_early_bird.at | 0 .../achievementEvaluators}/seeing_green.at | 0 .../achievementEvaluators}/speed_mather.at | 0 .../achievementEvaluators}/still_not_right.at | 0 .../super_persistence.at | 0 .../super_speed_math.at | 0 .../achievementEvaluators}/third_time.at | 0 conf/defaults.config | 9 +- .../modelCourse/html/achievements/README | 1 + .../html/achievements/back_for_more.png | Bin 11521 -> 0 bytes .../html/achievements/defaulticon.png | Bin 4498 -> 0 bytes .../html/achievements/level_eight.png | Bin 19314 -> 0 bytes .../html/achievements/level_five.png | Bin 9068 -> 0 bytes .../html/achievements/level_four.png | Bin 6757 -> 0 bytes .../html/achievements/level_one.png | Bin 14558 -> 0 bytes .../html/achievements/level_seven.png | Bin 14177 -> 0 bytes .../html/achievements/level_two.png | Bin 20105 -> 0 bytes .../images}/achievements/2nd_order_ode.png | Bin .../achievements/Fractal-Cornucopia.svg | 0 .../images}/achievements/add_anything.png | Bin htdocs/images/achievements/back_for_more.png | Bin 0 -> 9435 bytes .../images}/achievements/bug_sqush.png | Bin .../images}/achievements/by_definition.png | Bin .../images}/achievements/calendar.png | Bin .../images}/achievements/challenge_eight.png | Bin .../images}/achievements/challenge_five.png | Bin .../images}/achievements/challenge_four.png | Bin .../images}/achievements/challenge_nine.png | Bin .../images}/achievements/challenge_one.png | Bin .../images}/achievements/challenge_seven.png | Bin .../images}/achievements/challenge_six.png | Bin .../images}/achievements/challenge_ten.png | Bin .../images}/achievements/challenge_three.png | Bin .../images}/achievements/challenge_two.png | Bin .../images}/achievements/challenger.png | Bin .../achievements/change_of_variables.png | Bin .../images}/achievements/chipping_away.png | Bin .../achievements/complete_100_problems.png | Bin .../achievements/complete_10_problems.png | Bin .../achievements/complete_150_problems.png | Bin .../achievements/complete_25_problems.png | Bin .../achievements/complete_50_problems.png | Bin .../achievements/complete_all_sets.png | Bin .../achievements/complete_five_sets.png | Bin .../achievements/complete_one_problem.png | Bin .../images}/achievements/complete_one_set.png | Bin .../achievements/complete_ten_sets.png | Bin .../achievements/complete_thirty_sets.png | Bin .../achievements/complete_twenty_sets.png | Bin .../images}/achievements/crack_o_dawn.png | Bin .../images}/achievements/curvature.png | Bin .../images}/achievements/curvy_geometry.png | Bin htdocs/images/achievements/defaulticon.png | Bin 0 -> 4681 bytes .../achievements/derivative_master.png | Bin .../achievements/doing_it_backwards.png | Bin .../images}/achievements/double_integral.png | Bin .../images}/achievements/early_bird.png | Bin .../achievements/earn_10_achievements.png | Bin .../achievements/earn_20_achievements.png | Bin .../achievements/earn_30_achievements.png | Bin .../achievements/earn_40_achievements.png | Bin .../achievements/earn_50_achievements.png | Bin .../images}/achievements/eigenvector.png | Bin .../images}/achievements/first_order_ode.png | Bin .../images}/achievements/heart_area.png | Bin .../images}/achievements/hows_your_finger.png | Bin .../images}/achievements/integral_master.png | Bin .../images}/achievements/its_all_relative.png | Bin .../images}/achievements/la_revolucion.png | Bin .../achievements/lagrange_multipliers.png | Bin .../images}/achievements/laplace.png | Bin .../images}/achievements/last_minute.png | Bin htdocs/images/achievements/level_eight.png | Bin 0 -> 15303 bytes htdocs/images/achievements/level_five.png | Bin 0 -> 8483 bytes htdocs/images/achievements/level_four.png | Bin 0 -> 6279 bytes .../images}/achievements/level_nine.png | Bin htdocs/images/achievements/level_one.png | Bin 0 -> 9865 bytes htdocs/images/achievements/level_seven.png | Bin 0 -> 9661 bytes .../images}/achievements/level_six.png | Bin .../images}/achievements/level_ten.png | Bin .../images}/achievements/level_three.png | Bin htdocs/images/achievements/level_two.png | Bin 0 -> 15546 bytes .../images}/achievements/line_integrals.png | Bin .../images}/achievements/lines_and_planes.png | Bin .../images}/achievements/many_fractions.png | Bin .../images}/achievements/night_owl.png | Bin .../images}/achievements/ode_systems.png | Bin .../images}/achievements/on_fire.png | Bin .../images}/achievements/on_one_hand.png | Bin .../images}/achievements/on_the_hour.png | Bin .../images}/achievements/one_click.png | Bin .../images}/achievements/optimizer_prime.png | Bin .../achievements/partial_derivatives.png | Bin .../achievements/pattern_recognition.png | Bin .../images}/achievements/persistence.png | Bin .../images}/achievements/put_me_in_coach.png | Bin .../images}/achievements/reaching_a_limit.png | Bin .../achievements/really_early_bird.png | Bin .../images}/achievements/revolucion_redux.png | Bin .../images}/achievements/roman_numeral_I.png | Bin .../images}/achievements/roman_numeral_II.png | Bin .../images}/achievements/seeing_green.png | Bin .../images}/achievements/speed_mather.png | Bin .../images}/achievements/step_by_step_1.png | Bin .../images}/achievements/step_by_step_10.png | Bin .../images}/achievements/step_by_step_20.png | Bin .../images}/achievements/step_by_step_30.png | Bin .../images}/achievements/step_by_step_5.png | Bin .../images}/achievements/still_not_right.png | Bin .../achievements/super_persistence.png | Bin .../images}/achievements/super_speed_math.png | Bin .../images}/achievements/tangent_plane.png | Bin .../images}/achievements/taylor_hero.png | Bin .../images}/achievements/tea_time.png | Bin .../images}/achievements/the_biologist.png | Bin .../images}/achievements/the_fundamentals.png | Bin .../images}/achievements/the_lhopital.png | Bin .../images}/achievements/third_time.png | Bin .../images}/achievements/three_in_a_row.png | Bin .../images}/achievements/to_infinity.png | Bin .../images}/achievements/trig_ninja.png | Bin .../images}/achievements/triple_integral.png | Bin .../images}/achievements/vector_fields.png | Bin .../js/AchievementEditor/achievementeditor.js | 87 ++++++ htdocs/js/AchievementList/achievementlist.js | 32 ++ .../achievementnotificationeditor.js | 69 +++++ .../WeBWorK/Tasks/AchievementNotification.pm | 8 +- lib/WeBWorK/AchievementEvaluator.pm | 25 +- .../Instructor/AchievementEditor.pm | 288 ++++++++---------- .../Instructor/AchievementList.pm | 80 +++-- .../AchievementNotificationEditor.pm | 211 ++++++------- lib/WeBWorK/Utils.pm | 42 +++ .../cheevoMessage.html.ep | 10 +- .../Achievements/achievement_badges.html.ep | 6 +- .../Achievements/cheevobigbox.html.ep | 6 +- .../AchievementsLeaderboard.html.ep | 10 +- .../Instructor/AchievementEditor.html.ep | 13 +- .../AchievementEditor/revert_form.html.ep | 26 ++ .../AchievementEditor/save_as_form.html.ep | 32 +- .../AchievementEditor/save_form.html.ep | 11 +- .../AchievementList/default_table.html.ep | 4 +- .../AchievementList/edit_table.html.ep | 5 +- .../AchievementList/edit_table_row.html.ep | 31 +- .../AchievementList/save_edit_form.html.ep | 5 +- .../AchievementNotificationEditor.html.ep | 11 +- .../disable_form.html.ep | 4 +- .../existing_form.html.ep | 12 +- .../save_as_form.html.ep | 15 +- .../save_form.html.ep | 2 +- 193 files changed, 693 insertions(+), 364 deletions(-) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/back_for_more.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/challenge_eight.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/challenge_five.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/challenge_four.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/challenge_nine.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/challenge_one.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/challenge_seven.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/challenge_six.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/challenge_ten.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/challenge_three.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/challenge_two.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/challenger.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/chipping_away.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/complete_n_problems.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/complete_n_sets.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/crack_o_dawn.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/default_achievements.axp (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/early_bird.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/earn_n_achievements.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/example_complete_n_specific_problems.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/example_complete_n_specific_sets.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/example_complete_specific_problem.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/example_complete_specific_set.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/extensions.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/extensions.axp (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/hows_your_finger.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/last_minute.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/level_eight.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/level_five.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/level_four.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/level_nine.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/level_one.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/level_seven.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/level_six.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/level_ten.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/level_three.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/level_two.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/n_correct_in_a_row.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/night_owl.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/on_one_hand.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/on_the_hour.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/one_click.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/persistence.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/really_early_bird.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/seeing_green.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/speed_mather.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/still_not_right.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/super_persistence.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/super_speed_math.at (100%) rename {courses.dist/modelCourse/templates/achievements => assets/achievementEvaluators}/third_time.at (100%) create mode 100644 courses.dist/modelCourse/html/achievements/README delete mode 100644 courses.dist/modelCourse/html/achievements/back_for_more.png delete mode 100644 courses.dist/modelCourse/html/achievements/defaulticon.png delete mode 100644 courses.dist/modelCourse/html/achievements/level_eight.png delete mode 100644 courses.dist/modelCourse/html/achievements/level_five.png delete mode 100644 courses.dist/modelCourse/html/achievements/level_four.png delete mode 100644 courses.dist/modelCourse/html/achievements/level_one.png delete mode 100644 courses.dist/modelCourse/html/achievements/level_seven.png delete mode 100644 courses.dist/modelCourse/html/achievements/level_two.png rename {courses.dist/modelCourse/html => htdocs/images}/achievements/2nd_order_ode.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/Fractal-Cornucopia.svg (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/add_anything.png (100%) create mode 100644 htdocs/images/achievements/back_for_more.png rename {courses.dist/modelCourse/html => htdocs/images}/achievements/bug_sqush.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/by_definition.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/calendar.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/challenge_eight.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/challenge_five.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/challenge_four.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/challenge_nine.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/challenge_one.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/challenge_seven.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/challenge_six.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/challenge_ten.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/challenge_three.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/challenge_two.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/challenger.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/change_of_variables.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/chipping_away.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/complete_100_problems.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/complete_10_problems.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/complete_150_problems.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/complete_25_problems.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/complete_50_problems.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/complete_all_sets.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/complete_five_sets.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/complete_one_problem.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/complete_one_set.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/complete_ten_sets.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/complete_thirty_sets.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/complete_twenty_sets.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/crack_o_dawn.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/curvature.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/curvy_geometry.png (100%) create mode 100644 htdocs/images/achievements/defaulticon.png rename {courses.dist/modelCourse/html => htdocs/images}/achievements/derivative_master.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/doing_it_backwards.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/double_integral.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/early_bird.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/earn_10_achievements.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/earn_20_achievements.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/earn_30_achievements.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/earn_40_achievements.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/earn_50_achievements.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/eigenvector.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/first_order_ode.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/heart_area.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/hows_your_finger.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/integral_master.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/its_all_relative.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/la_revolucion.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/lagrange_multipliers.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/laplace.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/last_minute.png (100%) create mode 100644 htdocs/images/achievements/level_eight.png create mode 100644 htdocs/images/achievements/level_five.png create mode 100644 htdocs/images/achievements/level_four.png rename {courses.dist/modelCourse/html => htdocs/images}/achievements/level_nine.png (100%) create mode 100644 htdocs/images/achievements/level_one.png create mode 100644 htdocs/images/achievements/level_seven.png rename {courses.dist/modelCourse/html => htdocs/images}/achievements/level_six.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/level_ten.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/level_three.png (100%) create mode 100644 htdocs/images/achievements/level_two.png rename {courses.dist/modelCourse/html => htdocs/images}/achievements/line_integrals.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/lines_and_planes.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/many_fractions.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/night_owl.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/ode_systems.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/on_fire.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/on_one_hand.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/on_the_hour.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/one_click.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/optimizer_prime.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/partial_derivatives.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/pattern_recognition.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/persistence.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/put_me_in_coach.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/reaching_a_limit.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/really_early_bird.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/revolucion_redux.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/roman_numeral_I.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/roman_numeral_II.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/seeing_green.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/speed_mather.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/step_by_step_1.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/step_by_step_10.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/step_by_step_20.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/step_by_step_30.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/step_by_step_5.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/still_not_right.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/super_persistence.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/super_speed_math.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/tangent_plane.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/taylor_hero.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/tea_time.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/the_biologist.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/the_fundamentals.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/the_lhopital.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/third_time.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/three_in_a_row.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/to_infinity.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/trig_ninja.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/triple_integral.png (100%) rename {courses.dist/modelCourse/html => htdocs/images}/achievements/vector_fields.png (100%) create mode 100644 htdocs/js/AchievementEditor/achievementeditor.js create mode 100644 htdocs/js/AchievementNotificationEditor/achievementnotificationeditor.js create mode 100644 templates/ContentGenerator/Instructor/AchievementEditor/revert_form.html.ep diff --git a/.typos.toml b/.typos.toml index 44a547f652..1f4be05722 100644 --- a/.typos.toml +++ b/.typos.toml @@ -1,7 +1,7 @@ [files] extend-exclude = [ "lib/WeBWorK/Localize/*", - "courses.dist/modelCourse/html/achievements/*.png", + "htdocs/images/achievements/*.png", ] [default] diff --git a/courses.dist/modelCourse/templates/achievements/back_for_more.at b/assets/achievementEvaluators/back_for_more.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/back_for_more.at rename to assets/achievementEvaluators/back_for_more.at diff --git a/courses.dist/modelCourse/templates/achievements/challenge_eight.at b/assets/achievementEvaluators/challenge_eight.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/challenge_eight.at rename to assets/achievementEvaluators/challenge_eight.at diff --git a/courses.dist/modelCourse/templates/achievements/challenge_five.at b/assets/achievementEvaluators/challenge_five.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/challenge_five.at rename to assets/achievementEvaluators/challenge_five.at diff --git a/courses.dist/modelCourse/templates/achievements/challenge_four.at b/assets/achievementEvaluators/challenge_four.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/challenge_four.at rename to assets/achievementEvaluators/challenge_four.at diff --git a/courses.dist/modelCourse/templates/achievements/challenge_nine.at b/assets/achievementEvaluators/challenge_nine.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/challenge_nine.at rename to assets/achievementEvaluators/challenge_nine.at diff --git a/courses.dist/modelCourse/templates/achievements/challenge_one.at b/assets/achievementEvaluators/challenge_one.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/challenge_one.at rename to assets/achievementEvaluators/challenge_one.at diff --git a/courses.dist/modelCourse/templates/achievements/challenge_seven.at b/assets/achievementEvaluators/challenge_seven.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/challenge_seven.at rename to assets/achievementEvaluators/challenge_seven.at diff --git a/courses.dist/modelCourse/templates/achievements/challenge_six.at b/assets/achievementEvaluators/challenge_six.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/challenge_six.at rename to assets/achievementEvaluators/challenge_six.at diff --git a/courses.dist/modelCourse/templates/achievements/challenge_ten.at b/assets/achievementEvaluators/challenge_ten.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/challenge_ten.at rename to assets/achievementEvaluators/challenge_ten.at diff --git a/courses.dist/modelCourse/templates/achievements/challenge_three.at b/assets/achievementEvaluators/challenge_three.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/challenge_three.at rename to assets/achievementEvaluators/challenge_three.at diff --git a/courses.dist/modelCourse/templates/achievements/challenge_two.at b/assets/achievementEvaluators/challenge_two.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/challenge_two.at rename to assets/achievementEvaluators/challenge_two.at diff --git a/courses.dist/modelCourse/templates/achievements/challenger.at b/assets/achievementEvaluators/challenger.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/challenger.at rename to assets/achievementEvaluators/challenger.at diff --git a/courses.dist/modelCourse/templates/achievements/chipping_away.at b/assets/achievementEvaluators/chipping_away.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/chipping_away.at rename to assets/achievementEvaluators/chipping_away.at diff --git a/courses.dist/modelCourse/templates/achievements/complete_n_problems.at b/assets/achievementEvaluators/complete_n_problems.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/complete_n_problems.at rename to assets/achievementEvaluators/complete_n_problems.at diff --git a/courses.dist/modelCourse/templates/achievements/complete_n_sets.at b/assets/achievementEvaluators/complete_n_sets.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/complete_n_sets.at rename to assets/achievementEvaluators/complete_n_sets.at diff --git a/courses.dist/modelCourse/templates/achievements/crack_o_dawn.at b/assets/achievementEvaluators/crack_o_dawn.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/crack_o_dawn.at rename to assets/achievementEvaluators/crack_o_dawn.at diff --git a/courses.dist/modelCourse/templates/achievements/default_achievements.axp b/assets/achievementEvaluators/default_achievements.axp similarity index 100% rename from courses.dist/modelCourse/templates/achievements/default_achievements.axp rename to assets/achievementEvaluators/default_achievements.axp diff --git a/courses.dist/modelCourse/templates/achievements/early_bird.at b/assets/achievementEvaluators/early_bird.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/early_bird.at rename to assets/achievementEvaluators/early_bird.at diff --git a/courses.dist/modelCourse/templates/achievements/earn_n_achievements.at b/assets/achievementEvaluators/earn_n_achievements.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/earn_n_achievements.at rename to assets/achievementEvaluators/earn_n_achievements.at diff --git a/courses.dist/modelCourse/templates/achievements/example_complete_n_specific_problems.at b/assets/achievementEvaluators/example_complete_n_specific_problems.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/example_complete_n_specific_problems.at rename to assets/achievementEvaluators/example_complete_n_specific_problems.at diff --git a/courses.dist/modelCourse/templates/achievements/example_complete_n_specific_sets.at b/assets/achievementEvaluators/example_complete_n_specific_sets.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/example_complete_n_specific_sets.at rename to assets/achievementEvaluators/example_complete_n_specific_sets.at diff --git a/courses.dist/modelCourse/templates/achievements/example_complete_specific_problem.at b/assets/achievementEvaluators/example_complete_specific_problem.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/example_complete_specific_problem.at rename to assets/achievementEvaluators/example_complete_specific_problem.at diff --git a/courses.dist/modelCourse/templates/achievements/example_complete_specific_set.at b/assets/achievementEvaluators/example_complete_specific_set.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/example_complete_specific_set.at rename to assets/achievementEvaluators/example_complete_specific_set.at diff --git a/courses.dist/modelCourse/templates/achievements/extensions.at b/assets/achievementEvaluators/extensions.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/extensions.at rename to assets/achievementEvaluators/extensions.at diff --git a/courses.dist/modelCourse/templates/achievements/extensions.axp b/assets/achievementEvaluators/extensions.axp similarity index 100% rename from courses.dist/modelCourse/templates/achievements/extensions.axp rename to assets/achievementEvaluators/extensions.axp diff --git a/courses.dist/modelCourse/templates/achievements/hows_your_finger.at b/assets/achievementEvaluators/hows_your_finger.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/hows_your_finger.at rename to assets/achievementEvaluators/hows_your_finger.at diff --git a/courses.dist/modelCourse/templates/achievements/last_minute.at b/assets/achievementEvaluators/last_minute.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/last_minute.at rename to assets/achievementEvaluators/last_minute.at diff --git a/courses.dist/modelCourse/templates/achievements/level_eight.at b/assets/achievementEvaluators/level_eight.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/level_eight.at rename to assets/achievementEvaluators/level_eight.at diff --git a/courses.dist/modelCourse/templates/achievements/level_five.at b/assets/achievementEvaluators/level_five.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/level_five.at rename to assets/achievementEvaluators/level_five.at diff --git a/courses.dist/modelCourse/templates/achievements/level_four.at b/assets/achievementEvaluators/level_four.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/level_four.at rename to assets/achievementEvaluators/level_four.at diff --git a/courses.dist/modelCourse/templates/achievements/level_nine.at b/assets/achievementEvaluators/level_nine.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/level_nine.at rename to assets/achievementEvaluators/level_nine.at diff --git a/courses.dist/modelCourse/templates/achievements/level_one.at b/assets/achievementEvaluators/level_one.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/level_one.at rename to assets/achievementEvaluators/level_one.at diff --git a/courses.dist/modelCourse/templates/achievements/level_seven.at b/assets/achievementEvaluators/level_seven.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/level_seven.at rename to assets/achievementEvaluators/level_seven.at diff --git a/courses.dist/modelCourse/templates/achievements/level_six.at b/assets/achievementEvaluators/level_six.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/level_six.at rename to assets/achievementEvaluators/level_six.at diff --git a/courses.dist/modelCourse/templates/achievements/level_ten.at b/assets/achievementEvaluators/level_ten.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/level_ten.at rename to assets/achievementEvaluators/level_ten.at diff --git a/courses.dist/modelCourse/templates/achievements/level_three.at b/assets/achievementEvaluators/level_three.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/level_three.at rename to assets/achievementEvaluators/level_three.at diff --git a/courses.dist/modelCourse/templates/achievements/level_two.at b/assets/achievementEvaluators/level_two.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/level_two.at rename to assets/achievementEvaluators/level_two.at diff --git a/courses.dist/modelCourse/templates/achievements/n_correct_in_a_row.at b/assets/achievementEvaluators/n_correct_in_a_row.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/n_correct_in_a_row.at rename to assets/achievementEvaluators/n_correct_in_a_row.at diff --git a/courses.dist/modelCourse/templates/achievements/night_owl.at b/assets/achievementEvaluators/night_owl.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/night_owl.at rename to assets/achievementEvaluators/night_owl.at diff --git a/courses.dist/modelCourse/templates/achievements/on_one_hand.at b/assets/achievementEvaluators/on_one_hand.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/on_one_hand.at rename to assets/achievementEvaluators/on_one_hand.at diff --git a/courses.dist/modelCourse/templates/achievements/on_the_hour.at b/assets/achievementEvaluators/on_the_hour.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/on_the_hour.at rename to assets/achievementEvaluators/on_the_hour.at diff --git a/courses.dist/modelCourse/templates/achievements/one_click.at b/assets/achievementEvaluators/one_click.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/one_click.at rename to assets/achievementEvaluators/one_click.at diff --git a/courses.dist/modelCourse/templates/achievements/persistence.at b/assets/achievementEvaluators/persistence.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/persistence.at rename to assets/achievementEvaluators/persistence.at diff --git a/courses.dist/modelCourse/templates/achievements/really_early_bird.at b/assets/achievementEvaluators/really_early_bird.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/really_early_bird.at rename to assets/achievementEvaluators/really_early_bird.at diff --git a/courses.dist/modelCourse/templates/achievements/seeing_green.at b/assets/achievementEvaluators/seeing_green.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/seeing_green.at rename to assets/achievementEvaluators/seeing_green.at diff --git a/courses.dist/modelCourse/templates/achievements/speed_mather.at b/assets/achievementEvaluators/speed_mather.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/speed_mather.at rename to assets/achievementEvaluators/speed_mather.at diff --git a/courses.dist/modelCourse/templates/achievements/still_not_right.at b/assets/achievementEvaluators/still_not_right.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/still_not_right.at rename to assets/achievementEvaluators/still_not_right.at diff --git a/courses.dist/modelCourse/templates/achievements/super_persistence.at b/assets/achievementEvaluators/super_persistence.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/super_persistence.at rename to assets/achievementEvaluators/super_persistence.at diff --git a/courses.dist/modelCourse/templates/achievements/super_speed_math.at b/assets/achievementEvaluators/super_speed_math.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/super_speed_math.at rename to assets/achievementEvaluators/super_speed_math.at diff --git a/courses.dist/modelCourse/templates/achievements/third_time.at b/assets/achievementEvaluators/third_time.at similarity index 100% rename from courses.dist/modelCourse/templates/achievements/third_time.at rename to assets/achievementEvaluators/third_time.at diff --git a/conf/defaults.config b/conf/defaults.config index d28b39e71f..46788a851e 100644 --- a/conf/defaults.config +++ b/conf/defaults.config @@ -283,12 +283,15 @@ $webworkDirs{conf} = "$webworkDirs{root}/conf"; # Location of add-on configuration files. $webworkDirs{addOnConf} = "$webworkDirs{conf}/addon"; -# Location of assets (tex, pg, themes) +# Location of assets (tex, pg, themes, achievement evaluators) $webworkDirs{assets} = "$webworkDirs{root}/assets"; # Location of the distribution hardcopy themes. $webworkDirs{hardcopyThemes} = "$webworkDirs{assets}/hardcopyThemes"; +# Location of system achievement evaluators. +$webworkDirs{achievementEvaluators} = "$webworkDirs{assets}/achievementEvaluators"; + # Location of course directories. $webworkDirs{courses} = "$webwork_courses_dir" || "$webworkDirs{root}/courses"; @@ -327,6 +330,10 @@ $webworkURLs{htdocs_temp} = "$webworkURLs{htdocs}/tmp"; # Location of theme templates. $webworkDirs{themes} = "$webworkDirs{htdocs}/themes"; +# Location of system achievement badge icons. +$webworkDirs{achievementIcons} = "$webworkDirs{htdocs}/images/achievements"; +$webworkURLs{achievementIcons} = "$webworkURLs{htdocs}/images/achievements"; + # Location of localization directory. $webworkDirs{localize} = "$webworkDirs{root}/lib/WeBWorK/Localize"; diff --git a/courses.dist/modelCourse/html/achievements/README b/courses.dist/modelCourse/html/achievements/README new file mode 100644 index 0000000000..1afe5d8c51 --- /dev/null +++ b/courses.dist/modelCourse/html/achievements/README @@ -0,0 +1 @@ +Place course specific achievement image icons/overrides here. diff --git a/courses.dist/modelCourse/html/achievements/back_for_more.png b/courses.dist/modelCourse/html/achievements/back_for_more.png deleted file mode 100644 index cd63b56f2bb943e90281793e3f0c7c7ee24ac4b8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11521 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 UC!HFSU|bnekWrPcftiH-2kT2Rh5!Hn diff --git a/courses.dist/modelCourse/html/achievements/defaulticon.png b/courses.dist/modelCourse/html/achievements/defaulticon.png deleted file mode 100644 index 2f660e72f7740d5d39d78e036fea0ca363ee0297..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4498 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 X|MoA4n@RxpCma?gw#F1guNVIZpg`U2 diff --git a/courses.dist/modelCourse/html/achievements/level_eight.png b/courses.dist/modelCourse/html/achievements/level_eight.png deleted file mode 100644 index c5e793ffcac64d77b53b8a2fd362c9f1eacd73fc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19314 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 D-m2mO diff --git a/courses.dist/modelCourse/html/achievements/level_five.png b/courses.dist/modelCourse/html/achievements/level_five.png deleted file mode 100644 index 598adc678d95e5d89fcbc2b64941d9bdd875f100..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9068 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 DaCD5# diff --git a/courses.dist/modelCourse/html/achievements/level_four.png b/courses.dist/modelCourse/html/achievements/level_four.png deleted file mode 100644 index e027fabb231682b1f70960332af69dbc2119e520..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6757 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 diff --git a/courses.dist/modelCourse/html/achievements/level_one.png b/courses.dist/modelCourse/html/achievements/level_one.png deleted file mode 100644 index 552010f4723923c0b4f3756d42036e0031a03976..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14558 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 KldYFF5B(q2`?*X2 diff --git a/courses.dist/modelCourse/html/achievements/level_seven.png b/courses.dist/modelCourse/html/achievements/level_seven.png deleted file mode 100644 index 3f9b1d9cd2bc688dca7a799dcb3ade132b4080d6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14177 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 diff --git a/courses.dist/modelCourse/html/achievements/level_two.png b/courses.dist/modelCourse/html/achievements/level_two.png deleted file mode 100644 index b86afcc186c286c80a935a4a7ad32fd2b30b0737..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20105 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 xG|GQ#+@eBa`S{-}_{d;3!fd4(BrbFNZ#Z6sK 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 literal 0 HcmV?d00001 diff --git a/courses.dist/modelCourse/html/achievements/bug_sqush.png b/htdocs/images/achievements/bug_sqush.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/bug_sqush.png rename to htdocs/images/achievements/bug_sqush.png diff --git a/courses.dist/modelCourse/html/achievements/by_definition.png b/htdocs/images/achievements/by_definition.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/by_definition.png rename to htdocs/images/achievements/by_definition.png diff --git a/courses.dist/modelCourse/html/achievements/calendar.png b/htdocs/images/achievements/calendar.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/calendar.png rename to htdocs/images/achievements/calendar.png diff --git a/courses.dist/modelCourse/html/achievements/challenge_eight.png b/htdocs/images/achievements/challenge_eight.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/challenge_eight.png rename to htdocs/images/achievements/challenge_eight.png diff --git a/courses.dist/modelCourse/html/achievements/challenge_five.png b/htdocs/images/achievements/challenge_five.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/challenge_five.png rename to htdocs/images/achievements/challenge_five.png diff --git a/courses.dist/modelCourse/html/achievements/challenge_four.png b/htdocs/images/achievements/challenge_four.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/challenge_four.png rename to htdocs/images/achievements/challenge_four.png diff --git a/courses.dist/modelCourse/html/achievements/challenge_nine.png b/htdocs/images/achievements/challenge_nine.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/challenge_nine.png rename to htdocs/images/achievements/challenge_nine.png diff --git a/courses.dist/modelCourse/html/achievements/challenge_one.png b/htdocs/images/achievements/challenge_one.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/challenge_one.png rename to htdocs/images/achievements/challenge_one.png diff --git a/courses.dist/modelCourse/html/achievements/challenge_seven.png b/htdocs/images/achievements/challenge_seven.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/challenge_seven.png rename to htdocs/images/achievements/challenge_seven.png diff --git a/courses.dist/modelCourse/html/achievements/challenge_six.png b/htdocs/images/achievements/challenge_six.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/challenge_six.png rename to htdocs/images/achievements/challenge_six.png diff --git a/courses.dist/modelCourse/html/achievements/challenge_ten.png b/htdocs/images/achievements/challenge_ten.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/challenge_ten.png rename to htdocs/images/achievements/challenge_ten.png diff --git a/courses.dist/modelCourse/html/achievements/challenge_three.png b/htdocs/images/achievements/challenge_three.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/challenge_three.png rename to htdocs/images/achievements/challenge_three.png diff --git a/courses.dist/modelCourse/html/achievements/challenge_two.png b/htdocs/images/achievements/challenge_two.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/challenge_two.png rename to htdocs/images/achievements/challenge_two.png diff --git a/courses.dist/modelCourse/html/achievements/challenger.png b/htdocs/images/achievements/challenger.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/challenger.png rename to htdocs/images/achievements/challenger.png diff --git a/courses.dist/modelCourse/html/achievements/change_of_variables.png b/htdocs/images/achievements/change_of_variables.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/change_of_variables.png rename to htdocs/images/achievements/change_of_variables.png diff --git a/courses.dist/modelCourse/html/achievements/chipping_away.png b/htdocs/images/achievements/chipping_away.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/chipping_away.png rename to htdocs/images/achievements/chipping_away.png diff --git a/courses.dist/modelCourse/html/achievements/complete_100_problems.png b/htdocs/images/achievements/complete_100_problems.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/complete_100_problems.png rename to htdocs/images/achievements/complete_100_problems.png diff --git a/courses.dist/modelCourse/html/achievements/complete_10_problems.png b/htdocs/images/achievements/complete_10_problems.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/complete_10_problems.png rename to htdocs/images/achievements/complete_10_problems.png diff --git a/courses.dist/modelCourse/html/achievements/complete_150_problems.png b/htdocs/images/achievements/complete_150_problems.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/complete_150_problems.png rename to htdocs/images/achievements/complete_150_problems.png diff --git a/courses.dist/modelCourse/html/achievements/complete_25_problems.png b/htdocs/images/achievements/complete_25_problems.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/complete_25_problems.png rename to htdocs/images/achievements/complete_25_problems.png diff --git a/courses.dist/modelCourse/html/achievements/complete_50_problems.png b/htdocs/images/achievements/complete_50_problems.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/complete_50_problems.png rename to htdocs/images/achievements/complete_50_problems.png diff --git a/courses.dist/modelCourse/html/achievements/complete_all_sets.png b/htdocs/images/achievements/complete_all_sets.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/complete_all_sets.png rename to htdocs/images/achievements/complete_all_sets.png diff --git a/courses.dist/modelCourse/html/achievements/complete_five_sets.png b/htdocs/images/achievements/complete_five_sets.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/complete_five_sets.png rename to htdocs/images/achievements/complete_five_sets.png diff --git a/courses.dist/modelCourse/html/achievements/complete_one_problem.png b/htdocs/images/achievements/complete_one_problem.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/complete_one_problem.png rename to htdocs/images/achievements/complete_one_problem.png diff --git a/courses.dist/modelCourse/html/achievements/complete_one_set.png b/htdocs/images/achievements/complete_one_set.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/complete_one_set.png rename to htdocs/images/achievements/complete_one_set.png diff --git a/courses.dist/modelCourse/html/achievements/complete_ten_sets.png b/htdocs/images/achievements/complete_ten_sets.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/complete_ten_sets.png rename to htdocs/images/achievements/complete_ten_sets.png diff --git a/courses.dist/modelCourse/html/achievements/complete_thirty_sets.png b/htdocs/images/achievements/complete_thirty_sets.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/complete_thirty_sets.png rename to htdocs/images/achievements/complete_thirty_sets.png diff --git a/courses.dist/modelCourse/html/achievements/complete_twenty_sets.png b/htdocs/images/achievements/complete_twenty_sets.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/complete_twenty_sets.png rename to htdocs/images/achievements/complete_twenty_sets.png diff --git a/courses.dist/modelCourse/html/achievements/crack_o_dawn.png b/htdocs/images/achievements/crack_o_dawn.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/crack_o_dawn.png rename to htdocs/images/achievements/crack_o_dawn.png diff --git a/courses.dist/modelCourse/html/achievements/curvature.png b/htdocs/images/achievements/curvature.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/curvature.png rename to htdocs/images/achievements/curvature.png diff --git a/courses.dist/modelCourse/html/achievements/curvy_geometry.png b/htdocs/images/achievements/curvy_geometry.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/curvy_geometry.png rename to htdocs/images/achievements/curvy_geometry.png diff --git a/htdocs/images/achievements/defaulticon.png b/htdocs/images/achievements/defaulticon.png new file mode 100644 index 0000000000000000000000000000000000000000..add5258aa571eb737237e8ffdc2ee3dcdbb79eed GIT binary patch literal 4681 zcmX|_byO5xAIE2xl1>2;k=Uhck#3OgrKLecKx*lBDd|Q)q(lW2R-{2%Vo3pckdjiu zr5EI(;hpE7cjnxlIrpA9_kO>h-y|9tXi}1~kO2Tdsja1E43_Bs(k)^z?^Sdh0Skzq zv8F0yZb71>}9sgKqpKXB@q{}M!%_jNGXN#d`quTHW>N(qGv z@z41%003>Owwj7*@cgcAgh%!?%MC{089j3f*~>adOs~)*FXd4e;uZ&$IFBTJiS49~ zwlbaYb7_;NLix|0K@G{m1YSmS{vMfset!Tt3;Q!i1d}grpl~ml9Y19F)Ou-`-p4F zR6;y9bA;;<%I}S7U+Tb{X-;LVDoxa>!BzGG*Br0>KTM0h(&H5rWED9(I~yDtQV9(F zH~5u|A2+~GbE|v*B%LW8OOQ80R52xE_tQ&CLsRqpyOG<#&4xdzcA_3|@oskRS)-Mc z7b*Qdk>%d6oIg5}?pm%m`9Ag;}gz0&HIdo2iHW9hnG z#k0PAk)~^%b%sfBK5p5gWx`bAvmA)V&IsPmhHn(zgmeB9S;ofMKK;!QtZVqFk^L^IrKF#mD zK72cCr^R=j>`|lp%L(g&_?**qxwFXQ#>Ph2w2`&7fU~3zzZ-Xcf6)94&cAQfC&M(Z zca>eX$Y9Wy{i2vXdH+RCWo3eYKtQIcriBF)A3r}`9U^DfKcnZQ(gKN8X}1&6<|3|{ z(dFmok7cEOGD*L)IkmdAEnY(cgOG!=51Y4b|pY5rRg|lB6zMZ6LTP)uAEB<+5 zSMBZO!6fs5zGor!cFz%7uEMA&>8BwvG?~w>7?t#&z~vZ zzn@y_T!btBJwAR@Q9%+B5z!KHAsHGLh7c7+D_x%wfY<5KxDsmnhfuyA_u9sW(^7j# zzFd%SiUyajpC5iDhT5qon#i)jb+TnlxgE9ol}P^hACp`0y@KgQBnJ#=#E0|7^ni%0 z(0S_k-nGN^k+naQZ`aoI>>01pB9Au4`n;O6t1M~;Y$ZIK7ta2Ml;q^fBY#kqnEu(_ zg&!XuI}c^SQ4f~+1q8S>)7jvQi;F0FDBIm$-Vus1r`{9#ZKPq+;`PJ?&4-#Ap1HZX zy7|M7i@i3~V$Zbv-z{oKpL;qBu?B%>#j z-;AMWN7WP#b|xll)50Eyd+Dm%ORaRt-a3$h^xR<@sZN>qvd5U~mM!e>?C9N+yBQeJ zpi9+&cgQ)kE4$MSUrGoPX8ba*X>PVi_;h*mFTBE_h_l&ik+ZkA*V)4(g%Aq)zObPC ztw@eXjb6%5@%#^$c3f#wQ*NVSw0uV8Vxu|63Ot#5odvqjg75k zYO>M(^MlDgoCD|E?P}E`Xt^wULGH~F0gJVh5G z5^w4*Vw>F0Iize@D9tfUEJSllwD}5;y-)6b0_Hq1F)>-BQT4dtIWh82WR2cFUs}sq-j%~vo7`8l7krQW->;A!+tf2fP}Dl zKd=q{Hhs+HF>VB9wQ<+YtW)DH()jAM$#a2__GY(vnem@UP0e@*$mu~ZHT(xFX?Jx|=A2kX_eK`* zA?Mb!D<*w){%yOM9`;sj+7yoA?{TY*u*$9`IHR#KXE0++=w@;$jg<+qbsp*(g*M!@T_fo1cEPSFuuN(x2JOHyjw)bup`PO3NyW#G=NioUTP znPWwP(|HM_6^8M(ly_RPW8XmPT|BO$L`=!T*f@G;$D?O=yhzUCK<<-m8#iC7r1ug9 zxH+t^ro%{;8PR#JOP?dJLPuXc;1Pyqyn2;rVHZL)Q)7?aTWtGK61G!|Rdcha;9y~9 z&dAa5+ZgRRKi+n$x}m4n8#2qLQ1mzD{JT|!lFGDd4@UgEGZ%Ax9a$(JLN`4VoDw}vt1jwYc&`ba+iasg!2n7kIW8j!+v=TC}w#*b8z0bn(6;xlsuFci>`)Rt* zEvhY5!dUWALHA3Y9^K@L*nji=sTG{i7&0=FY}hS=F&`4{1+bezp=4EP{4kIzYfw}?nS0_I@xZ%1>b4dH!%^||R?M)Nbp>~GSQt`qJ`dEJT}_ZwGWnu#3GN5rgK z+LV?RU6YfOo4B9f9FB+(bv<4me#y(nml(EuC)g~X5zTi1s^i=8a*czq!2Knmkq?Px zz~L11fC)5G)Sn5Cp8dHN6xXOrz2IYq6|+vV+LVGM+2O%NlL~{?gVo;X@vE?ty_cTj zece^8x36_dLT?IC6HiAd^G4!?tee2qY?eGvQ%`0blB6QG8#Cv~eHdhwfD-xS{P*PK zcjJuR+YbFU9)n`}#FqjV!?KLTc2BC@o}!%@(LFsX?f8Mau3lb@e~b4!FQ^Qat{QfJ zJFZN70DmfwEEJTK@b_OU+S;tOQWT+R!AEs!z9&9E*jaKS_DRqO{ zyot{hvi`*)_JT2IZsIE+9{}pZ+SSQ2Q}qT06x~%H%go2lwCJ2i&=>LXLl*WCa7%2L z+Z4AtR>s8^>NR1yhr?UYW;D>r&p0n`@Foo-E#ZwF#+2@9DfM*KlOCHQ)QTHDawJc|H$k7L@0m9ytB*6iCNrXF$6(pW`o&#vd;lTSTf&@lr?Kle-Z- zRf5({dWcBs@SbjgJTj9O3LX$|yWgfO>X?ZXH-(YW0#9{rDSLSdn<>QfWMn~=*V}di z+h`Nj=(5-w!hrcu9Ss;=)WU8#CQ`q@2wHxOX1;gtcE7$3)gOOTgYn>%C=xn5K-jK5 zVR8~#@KGVi5K?MO{H;(XJ45Xa>0w4*UY^m@2-@H^!fRg&w~COjt3EIo(v{iT&Ms|q zbTpO;AZBYcWB~YU-JU&r$jhK3T{c>*&@rZqL?XXFP+}l^gTbVR*5&g8n-Dcu7FSPC zed(_gt_1yLyc|4M*4A!H6SuHOcz_nt=R0YzeX%$@oA09-4Qemwyd5H_EJtEj507`4 z`5yeGH-rNNTtD6!cMXQBgcWd!KHy^8f%O_g0xrR%-xS$XRGM(dL6ms~G@*2+!htJVs(44S zSFXSB*!IG_4?cYDHyMK}C@4t#u4xqzi2WYS> zJ5$oqsBF3-?}0wg%g?WhLLqX6ZIgce`W1VGZd%xF7$w1)Yz-%AvA`L695Tek#f{+4 zhrfN}E(t#*#a~>Ju5PmjeCJh$xc!a|#kOCcZ;yVvFVgWh>m6>14(`cXitfu)Jy;6c z$Nvk=e+dvUDH{srvPi z;f&f?;^P#~IjATS-_NA3Evq0eU(LJ`6c9jLWPtttTnQ_O{9F|0qpq&rw|zXUQ5_u( zMG~%nWRv93IkUY^Kjhq&uba-&Z76uJva&M6lcz`zDk>>C!1H3#@Wkkl^lNtMC|`K9 zsf9&F9uQUe>66QD5CeT(bYf~mwOYf%E{bO!bXCF!UDefk|LT`6dTmafL>L#Via{Da z`)j?O%xG$AYN7j7TZ{Y*gdg;f)QNS0+uBu}o1d`j=DN)R z@@Ho!=jB;wM{(mgfz#f3#Y36xNRS5l0%R&NnDw!6kdhYudV}y8euhlrLG?!}_F+DK zN*lqkgV9ToT+ksIWD_6kJhyu^d$1^Uu|A>W0!R;3^xnRG8#PHE+w182tB>?!3mTju z{NK5!bvu_Gb~PD3jab)|pgpV_#~^fqaOKVqlH{bMiP>4^JbA(>WuU02sKp;gCo3y^ zuwB!|$x4-eHx`r^ivIq7Q^i=P-gRHctMlVikdsg4ukWEZft0}zB?LLbg3ARrjq^`x zk;^b?9*n&SJTEhg+Xh)*Em zYnzy4m*vL)KNN&dx;K{DsQZZvXlAjeA2ViZ_*s~lsk2g%kP^qBo`#At!>Hn8OwG*j ztu1d_r$-)Uab&kur6uVJmQA}S&UtW~SG{a#YSPKthy=q{uto=ls-PL?+n=xTJ-3(t zhbkry)OR;j_SfbRt3X~2bOG|0H!=t0j?ChAGogKWd6l*v;4SIS1z6e`7iEtjd zL4{v?%c9r(t-^2=QFj-DBUDrDVQT(lnSFFk!k0=@{`nm%V@4&-2*^N2q-a(uU+M4?``9GW$56nBQ{PLEnFlh{CcEPF zln3NmJMT_;Fp#`Y=tr=cicXQVD&}%$bt+C~^yBEv2}B8aA)*hhY$|QWyJ4y=06FQ*|-VI;>)2qL`%Q`h4ll-NqQi~XpPgYM$9{6bRWjG-7^JXqP vGRkrZcJt1j+DYbikxeV{uwYeU>Ja@um1@H+ literal 0 HcmV?d00001 diff --git a/courses.dist/modelCourse/html/achievements/derivative_master.png b/htdocs/images/achievements/derivative_master.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/derivative_master.png rename to htdocs/images/achievements/derivative_master.png diff --git a/courses.dist/modelCourse/html/achievements/doing_it_backwards.png b/htdocs/images/achievements/doing_it_backwards.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/doing_it_backwards.png rename to htdocs/images/achievements/doing_it_backwards.png diff --git a/courses.dist/modelCourse/html/achievements/double_integral.png b/htdocs/images/achievements/double_integral.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/double_integral.png rename to htdocs/images/achievements/double_integral.png diff --git a/courses.dist/modelCourse/html/achievements/early_bird.png b/htdocs/images/achievements/early_bird.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/early_bird.png rename to htdocs/images/achievements/early_bird.png diff --git a/courses.dist/modelCourse/html/achievements/earn_10_achievements.png b/htdocs/images/achievements/earn_10_achievements.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/earn_10_achievements.png rename to htdocs/images/achievements/earn_10_achievements.png diff --git a/courses.dist/modelCourse/html/achievements/earn_20_achievements.png b/htdocs/images/achievements/earn_20_achievements.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/earn_20_achievements.png rename to htdocs/images/achievements/earn_20_achievements.png diff --git a/courses.dist/modelCourse/html/achievements/earn_30_achievements.png b/htdocs/images/achievements/earn_30_achievements.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/earn_30_achievements.png rename to htdocs/images/achievements/earn_30_achievements.png diff --git a/courses.dist/modelCourse/html/achievements/earn_40_achievements.png b/htdocs/images/achievements/earn_40_achievements.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/earn_40_achievements.png rename to htdocs/images/achievements/earn_40_achievements.png diff --git a/courses.dist/modelCourse/html/achievements/earn_50_achievements.png b/htdocs/images/achievements/earn_50_achievements.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/earn_50_achievements.png rename to htdocs/images/achievements/earn_50_achievements.png diff --git a/courses.dist/modelCourse/html/achievements/eigenvector.png b/htdocs/images/achievements/eigenvector.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/eigenvector.png rename to htdocs/images/achievements/eigenvector.png diff --git a/courses.dist/modelCourse/html/achievements/first_order_ode.png b/htdocs/images/achievements/first_order_ode.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/first_order_ode.png rename to htdocs/images/achievements/first_order_ode.png diff --git a/courses.dist/modelCourse/html/achievements/heart_area.png b/htdocs/images/achievements/heart_area.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/heart_area.png rename to htdocs/images/achievements/heart_area.png diff --git a/courses.dist/modelCourse/html/achievements/hows_your_finger.png b/htdocs/images/achievements/hows_your_finger.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/hows_your_finger.png rename to htdocs/images/achievements/hows_your_finger.png diff --git a/courses.dist/modelCourse/html/achievements/integral_master.png b/htdocs/images/achievements/integral_master.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/integral_master.png rename to htdocs/images/achievements/integral_master.png diff --git a/courses.dist/modelCourse/html/achievements/its_all_relative.png b/htdocs/images/achievements/its_all_relative.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/its_all_relative.png rename to htdocs/images/achievements/its_all_relative.png diff --git a/courses.dist/modelCourse/html/achievements/la_revolucion.png b/htdocs/images/achievements/la_revolucion.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/la_revolucion.png rename to htdocs/images/achievements/la_revolucion.png diff --git a/courses.dist/modelCourse/html/achievements/lagrange_multipliers.png b/htdocs/images/achievements/lagrange_multipliers.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/lagrange_multipliers.png rename to htdocs/images/achievements/lagrange_multipliers.png diff --git a/courses.dist/modelCourse/html/achievements/laplace.png b/htdocs/images/achievements/laplace.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/laplace.png rename to htdocs/images/achievements/laplace.png diff --git a/courses.dist/modelCourse/html/achievements/last_minute.png b/htdocs/images/achievements/last_minute.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/last_minute.png rename to htdocs/images/achievements/last_minute.png diff --git a/htdocs/images/achievements/level_eight.png b/htdocs/images/achievements/level_eight.png new file mode 100644 index 0000000000000000000000000000000000000000..72053bb476d8a0feef94b773da2867dfad585d98 GIT binary patch literal 15303 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 literal 0 HcmV?d00001 diff --git a/courses.dist/modelCourse/html/achievements/level_nine.png b/htdocs/images/achievements/level_nine.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/level_nine.png rename to htdocs/images/achievements/level_nine.png diff --git a/htdocs/images/achievements/level_one.png b/htdocs/images/achievements/level_one.png new file mode 100644 index 0000000000000000000000000000000000000000..2e8f6ad83ff64e667d53c3fc42132b1b5eb764f1 GIT binary patch literal 9865 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 T;yJHeFMzVVhFqNtF!X-_iIOSJ literal 0 HcmV?d00001 diff --git a/htdocs/images/achievements/level_seven.png b/htdocs/images/achievements/level_seven.png new file mode 100644 index 0000000000000000000000000000000000000000..b64a3ca7ada47ef1805f00572233281fb667d42b GIT binary patch literal 9661 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 aOx$hE3#>&1r4M`*Kt@7Qyh_v{@c#kEY>_(v literal 0 HcmV?d00001 diff --git a/courses.dist/modelCourse/html/achievements/level_six.png b/htdocs/images/achievements/level_six.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/level_six.png rename to htdocs/images/achievements/level_six.png diff --git a/courses.dist/modelCourse/html/achievements/level_ten.png b/htdocs/images/achievements/level_ten.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/level_ten.png rename to htdocs/images/achievements/level_ten.png diff --git a/courses.dist/modelCourse/html/achievements/level_three.png b/htdocs/images/achievements/level_three.png similarity index 100% rename from courses.dist/modelCourse/html/achievements/level_three.png rename to htdocs/images/achievements/level_three.png diff --git a/htdocs/images/achievements/level_two.png b/htdocs/images/achievements/level_two.png new file mode 100644 index 0000000000000000000000000000000000000000..90030bc517bbccb8b8b553ad30eeb9aa020447b0 GIT binary patch literal 15546 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 { + // Action form validation. + // Store event listeners so they can be removed. + const event_listeners = {}; + + const show_errors = (ids, elements) => { + for (const id of ids) elements.push(document.getElementById(id)); + for (const element of elements) { + if (element?.id.endsWith('_err_msg')) { + element.classList.remove('d-none'); + } else if (element) { + element.classList.add('is-invalid'); + if (!(element.id in event_listeners)) { + event_listeners[element.id] = hide_errors([], elements); + element.addEventListener('change', event_listeners[element.id]); + } + } + } + }; + + const hide_errors = (ids, elements) => { + return () => { + for (const id of ids) elements.push(document.getElementById(id)); + for (const element of elements) { + if (element?.id.endsWith('_err_msg')) { + element.classList.add('d-none'); + } else if (element) { + element.classList.remove('is-invalid'); + if (element.id in event_listeners) { + element.removeEventListener('change', event_listeners[element.id]); + delete event_listeners[element.id]; + } + } + } + }; + }; + + document.getElementById('editor')?.addEventListener('submit', (e) => { + const action = document.getElementById('current_action')?.value || ''; + if (action === 'save_as') { + const target_file_input = document.getElementById('action.save_as.target_file_id'); + const filename = (target_file_input?.value || '') + (target_file_input?.value.endsWith('.at') ? '' : '.at'); + if (filename.trim() === '' || filename.trim() == '.at') { + e.preventDefault(); + e.stopPropagation(); + show_errors(['blank_filename_err_msg'], [target_file_input]); + } else if (filename == target_file_input.dataset.originalName) { + e.preventDefault(); + e.stopPropagation(); + show_errors(['change_filename_err_msg'], [target_file_input]); + } else if (filename.includes('/')) { + e.preventDefault(); + e.stopPropagation(); + show_errors(['invalid_filename_err_msg'], [target_file_input]); + } else { + const selectedOption = + document.querySelector('input[name="action.save_as.saveMode"]:checked')?.value || ''; + if (selectedOption === 'use_in_new') { + const newFilename = document.getElementById('action.save_as.new_id'); + if (newFilename?.value.trim() === '') { + e.preventDefault(); + e.stopPropagation(); + show_errors(['blank_id_err_msg'], [newFilename]); + } + } + } + } else if (action === 'revert') { + const delete_confirm = document.getElementById('delete_select'); + if (delete_confirm.value != 'yes') { + e.preventDefault(); + e.stopPropagation(); + show_errors(['delete_confirm_err_msg'], [delete_confirm]); + } + } + }); + + // Remove all error messages when changing tabs. + for (const tab of document.querySelectorAll('a[data-bs-toggle="tab"]')) { + tab.addEventListener('shown.bs.tab', () => { + if (Object.keys(event_listeners) != 0) + hide_errors( + [], + document.getElementById('editor')?.querySelectorAll('div[id$=_err_msg], .is-invalid') + )(); + }); + } +})(); diff --git a/htdocs/js/AchievementList/achievementlist.js b/htdocs/js/AchievementList/achievementlist.js index 08406848b1..ae747bbc96 100644 --- a/htdocs/js/AchievementList/achievementlist.js +++ b/htdocs/js/AchievementList/achievementlist.js @@ -108,6 +108,38 @@ e.stopPropagation(); show_errors(['delete_confirm_err_msg'], [delete_confirm]); } + } else if (action === 'save_edit') { + const invalid_inputs = Array.from( + document.querySelectorAll('input[name$=".test"], input[name$=".icon"]') + ).filter((input) => input.value.includes('/')); + if (invalid_inputs.length) { + e.preventDefault(); + e.stopPropagation(); + const err_msg = document.getElementById('save_edit_filename_err_msg'); + err_msg?.classList.remove('d-none'); + for (const input of invalid_inputs) { + input.classList.add('is-invalid'); + if (!(input.id in event_listeners)) { + event_listeners[input.id] = () => { + // Only clear this field's own invalid marking, and only once it is valid. + if (input.value.includes('/')) return; + input.classList.remove('is-invalid'); + input.removeEventListener('change', event_listeners[input.id]); + delete event_listeners[input.id]; + + // Hide the shared error message once no fields remain invalid. + if ( + !document.querySelector( + 'input[name$=".test"].is-invalid, input[name$=".icon"].is-invalid' + ) + ) { + err_msg?.classList.add('d-none'); + } + }; + input.addEventListener('change', event_listeners[input.id]); + } + } + } } }); diff --git a/htdocs/js/AchievementNotificationEditor/achievementnotificationeditor.js b/htdocs/js/AchievementNotificationEditor/achievementnotificationeditor.js new file mode 100644 index 0000000000..5174a519e2 --- /dev/null +++ b/htdocs/js/AchievementNotificationEditor/achievementnotificationeditor.js @@ -0,0 +1,69 @@ +(() => { + // Action form validation. + // Store event listeners so they can be removed. + const event_listeners = {}; + + const show_errors = (ids, elements) => { + for (const id of ids) elements.push(document.getElementById(id)); + for (const element of elements) { + if (element?.id.endsWith('_err_msg')) { + element.classList.remove('d-none'); + } else if (element) { + element.classList.add('is-invalid'); + if (!(element.id in event_listeners)) { + event_listeners[element.id] = hide_errors([], elements); + element.addEventListener('change', event_listeners[element.id]); + } + } + } + }; + + const hide_errors = (ids, elements) => { + return () => { + for (const id of ids) elements.push(document.getElementById(id)); + for (const element of elements) { + if (element?.id.endsWith('_err_msg')) { + element.classList.add('d-none'); + } else if (element) { + element.classList.remove('is-invalid'); + if (element.id in event_listeners) { + element.removeEventListener('change', event_listeners[element.id]); + delete event_listeners[element.id]; + } + } + } + }; + }; + + document.getElementById('editor')?.addEventListener('submit', (e) => { + const action = document.getElementById('current_action')?.value || ''; + if (action === 'save_as') { + const target_file_input = document.getElementById('action.save_as.target_file_id'); + const filename = target_file_input?.value || ''; + if (filename.trim() === '') { + e.preventDefault(); + e.stopPropagation(); + show_errors(['blank_filename_err_msg'], [target_file_input]); + } else if (filename == target_file_input.dataset.originalName) { + e.preventDefault(); + e.stopPropagation(); + show_errors(['change_filename_err_msg'], [target_file_input]); + } else if (filename.includes('/')) { + e.preventDefault(); + e.stopPropagation(); + show_errors(['invalid_filename_err_msg'], [target_file_input]); + } + } + }); + + // Remove all error messages when changing tabs. + for (const tab of document.querySelectorAll('a[data-bs-toggle="tab"]')) { + tab.addEventListener('shown.bs.tab', () => { + if (Object.keys(event_listeners).length) + hide_errors( + [], + document.getElementById('editor')?.querySelectorAll('div[id$=_err_msg], .is-invalid') + )(); + }); + } +})(); diff --git a/lib/Mojolicious/WeBWorK/Tasks/AchievementNotification.pm b/lib/Mojolicious/WeBWorK/Tasks/AchievementNotification.pm index c2d45f6618..338b88f2cb 100644 --- a/lib/Mojolicious/WeBWorK/Tasks/AchievementNotification.pm +++ b/lib/Mojolicious/WeBWorK/Tasks/AchievementNotification.pm @@ -52,6 +52,10 @@ sub send_achievement_notification ($job, $ce, $db, $mail_data) { die "User $mail_data->{recipient} does not have an email address -- skipping\n" unless ($user_record->email_address =~ /\S/); + my $email_template = $mail_data->{achievement}{email_template}; + die "Achievement notification template file \"$email_template\" contains a slash and cannot be used.\n" + if $email_template =~ /\//; + my $compartment = WeBWorK::WWSafe->new; $compartment->share_from('main', [qw(%Encode:: %Mojo::Base:: %Mojo::Exception:: %Mojo::Template:: %WeBWorK::SafeTemplate::)]); @@ -74,9 +78,7 @@ sub send_achievement_notification ($job, $ce, $db, $mail_data) { pointsEarned => $mail_data->{pointsEarned} }; - our $template = - Mojo::File->new("$ce->{courseDirs}{achievement_notifications}/$mail_data->{achievement}{email_template}") - ->slurp; + our $template = Mojo::File->new("$ce->{courseDirs}{achievement_notifications}/$email_template")->slurp; $compartment->share(qw($template $template_vars)); my $body = $compartment->reval( diff --git a/lib/WeBWorK/AchievementEvaluator.pm b/lib/WeBWorK/AchievementEvaluator.pm index bf4d0cf9de..0389cf32ce 100644 --- a/lib/WeBWorK/AchievementEvaluator.pm +++ b/lib/WeBWorK/AchievementEvaluator.pm @@ -195,18 +195,31 @@ sub checkForAchievements ($problem_in, $c, %options) { $counter = $userAchievement->counter; $maxCounter = $achievement->max_counter; + # Determine location of achievement evaluator. + my $sourceFilePath; + my $sourceFile = $achievement->test; + if (!$sourceFile) { + warn qq{No achievement evaluator provided for "$achievement_id".}; + next; + } elsif ($sourceFile =~ /\//) { + warn qq{Achievement evaluator "$sourceFile" for "$achievement_id" contains a slash.}; + next; + } elsif (-f "$ce->{courseDirs}{achievements}/$sourceFile") { + $sourceFilePath = "$ce->{courseDirs}{achievements}/$sourceFile"; + } elsif (-f "$ce->{webworkDirs}{achievementEvaluators}/$sourceFile") { + $sourceFilePath = "$ce->{webworkDirs}{achievementEvaluators}/$sourceFile"; + } else { + warn qq{Could not find achievement evaluator file "$sourceFile" for "$achievement_id".}; + next; + } + # Check the achievement using Safe. - my $sourceFilePath = $ce->{courseDirs}{achievements} . '/' . $achievement->test; - if (-e $sourceFilePath) { + { local $/ = undef; open(my $SOURCE, '<', $sourceFilePath); $source = <$SOURCE>; close($SOURCE); - } else { - warn('Couldnt find achievement evaluator $sourceFilePath'); - next; } - my $earned = $compartment->reval($preamble . "\n" . $source); warn "There were errors in achievement $achievement_id\n" . $@ if $@; diff --git a/lib/WeBWorK/ContentGenerator/Instructor/AchievementEditor.pm b/lib/WeBWorK/ContentGenerator/Instructor/AchievementEditor.pm index 149282e78e..fc6e5cd7f9 100644 --- a/lib/WeBWorK/ContentGenerator/Instructor/AchievementEditor.pm +++ b/lib/WeBWorK/ContentGenerator/Instructor/AchievementEditor.pm @@ -11,12 +11,13 @@ use HTML::Entities; use File::Copy; use WeBWorK::Utils qw(fix_newlines not_blank x); -use WeBWorK::Utils::Files qw(surePathToFile readFile path_is_subdir); +use WeBWorK::Utils::Files qw(readFile); -use constant ACTION_FORMS => [qw(save save_as)]; +use constant ACTION_FORMS => [qw(save save_as revert)]; use constant ACTION_FORM_TITLES => { save => x('Save'), save_as => x('Save As'), + revert => x('Revert') }; use constant DEFAULT_ICON => 'defaulticon.png'; @@ -31,23 +32,36 @@ sub pre_header_initialize ($c) { $c->stash->{actionFormTitles} = ACTION_FORM_TITLES(); $c->stash->{achievementContents} = ''; - # Check permissions - return unless ($authz->hasPermissions($user, 'edit_achievements')); + return unless $authz->hasPermissions($user, 'edit_achievements'); - # Get the achievement my $Achievement = $c->db->getAchievement($c->stash('achievementID')); + unless ($Achievement) { + $c->addbadmessage($c->maketext('Achievement "[_1]" not found!', $c->stash('achievementID'))); + return; + } - if (!$Achievement) { - $c->addbadmessage($c->maketext("Achievement [_1] not found!", $c->stash('achievementID'))); + my $sourceFile = $Achievement->test; + if ($sourceFile =~ /\//) { + $c->addbadmessage($c->maketext( + 'Achievement evaluator "[_1]" file contains a invalid character "/", and cannot be edited.', + $sourceFile + )); + return; + } + if (-f "$ce->{courseDirs}{achievements}/$sourceFile") { + $c->{sourceFilePath} = "$ce->{courseDirs}{achievements}/$sourceFile"; + } elsif (-f "$ce->{webworkDirs}{achievementEvaluators}/$sourceFile") { + $c->{sourceFilePath} = "$ce->{webworkDirs}{achievementEvaluators}/$sourceFile"; + $c->{sourceFileIsProtected} = 1; + } else { + $c->addbadmessage($c->maketext('The achievement evaluator "[_1]" cannot be found.', $sourceFile)); return; } - $c->{achievement} = $Achievement; - $c->{sourceFilePath} = $ce->{courseDirs}{achievements} . '/' . $Achievement->test; + $c->{achievement} = $Achievement; + $c->{sourceFile} = $sourceFile; my $actionID = $c->param('action'); - - # Perform a save or save_as action if ($actionID) { unless (grep { $_ eq $actionID } @{ ACTION_FORMS() }) { die "Action $actionID not found"; @@ -65,23 +79,10 @@ sub initialize ($c) { my $user = $c->param('user'); my $sourceFilePath = $c->{sourceFilePath}; - return unless ($authz->hasPermissions($user, 'edit_achievements')); - - $c->addmessage($c->authen->flash('status_message') || ''); # Record status messages carried over from a redirect - - # Check source file path - if (not(-e $sourceFilePath)) { - $c->addbadmessage('The file "' . $c->shortPath($sourceFilePath) . '" cannot be found.'); - return; - } + return unless $authz->hasPermissions($user, 'edit_achievements') && $c->{achievement} && $sourceFilePath; # Find the text for the achievement. - unless ($c->stash->{achievementContents} =~ /\S/) { - unless (path_is_subdir($sourceFilePath, $c->ce->{courseDirs}{achievements}, 1)) { - $c->addbadmessage('Path is Unsafe!'); - return; - } - + unless (not_blank($c->stash->{achievementContents})) { eval { $c->stash->{achievementContents} = readFile($sourceFilePath) }; $c->stash->{achievementContents} = $@ if $@; } @@ -89,187 +90,130 @@ sub initialize ($c) { return; } -# Convert long paths to [ACHEVDIR] +# Append [ACHEVDIR] to filename. sub shortPath ($c, $file) { - my $ache = $c->ce->{courseDirs}{achievements}; - $file =~ s|^$ache|[ACHEVDIR]|; - return $file; + return "[ACHEVDIR]/$file"; } -sub getRelativeSourceFilePath ($c, $sourceFilePath) { - my $achievementsDir = $c->ce->{courseDirs}{achievements}; - $sourceFilePath =~ s|^${achievementsDir}/*||; # remove templates path and any slashes that follow - return $sourceFilePath; -} - -# saveFileChanges does most of the work. It is a separate method so that it can -# be called from either pre_header_initialize or initialize, depending on -# whether a redirect is needed or not. -sub saveFileChanges ($c, $outputFilePath, $achievementContents = undef) { +# saveFileChanges does the work of saving the file for both the save_handler +# and the save_as_handler. Be sure that $outputFile is validated before calling +# this method (defined, not blank, and does not contain a slash). +sub saveFileChanges ($c, $outputFile) { my $ce = $c->ce; - if (defined($achievementContents) and ref($achievementContents)) { - $achievementContents = ${$achievementContents}; - } elsif (!not_blank($achievementContents)) { # if the AchievementContents is undefined or empty - $achievementContents = $c->stash->{achievementContents}; - } - - unless (not_blank($outputFilePath)) { - $c->addbadmessage($c->maketext('You must specify an file name in order to save a new file.')); - return ''; - } - my $do_not_save = 0; # flag to prevent saving of file - my $editErrors = ''; - - # write changes to the appropriate files - # FIXME make sure that the permissions are set correctly!!! - # Make sure that the warning is being transmitted properly. - - my $writeFileErrors; - if (not_blank($outputFilePath)) { # save file + # This shouldn't be needed, but one last check for safety. + return 0 if !$outputFile || $outputFile =~ /\//; - # make sure any missing directories are created - surePathToFile($ce->{courseDirs}{achievements}, $outputFilePath); - die 'outputFilePath is unsafe!' - unless path_is_subdir($outputFilePath, $ce->{courseDirs}{achievements}, 1); - - eval { - open my $OUTPUTFILE, '>', $outputFilePath or die "Failed to open $outputFilePath"; - print $OUTPUTFILE $achievementContents; - close $OUTPUTFILE; - }; - - $writeFileErrors = $@ if $@; - } - - # Catch errors in saving files, - $c->{saveError} = $do_not_save; # Don't do redirects if the file was not saved. - # Don't unlink files or send success messages + my $outputFilePath = "$ce->{courseDirs}{achievements}/$outputFile"; + eval { + open my $OUTPUTFILE, '>', $outputFilePath or die "Failed to open $outputFilePath"; + print $OUTPUTFILE $c->stash->{achievementContents}; + close $OUTPUTFILE; + }; + my $writeFileErrors = $@; if ($writeFileErrors) { - # Get the current directory from the outputFilePath - $outputFilePath =~ m|^(/.*?/)[^/]+$|; - my $currentDirectory = $1; - my $errorMessage; - # Check why we failed to give better error messages - if (not -w $ce->{courseDirs}{achievements}) { + # Check why we failed to give better error messages. + if (not -d $ce->{courseDirs}{achievements}) { + $errorMessage = $c->maketext('Course achievements directory does not exist. File not saved.'); + } elsif (not -w $ce->{courseDirs}{achievements}) { $errorMessage = $c->maketext( 'Write permissions have not been enabled in the templates directory. No changes can be made.'); - } elsif (not -w $currentDirectory) { - $errorMessage = $c->maketext( - 'Write permissions have not been enabled in "[_1]". ' - . 'Changes must be saved to a different directory for viewing.', - $c->shortPath($currentDirectory) - ); - } elsif (-e $outputFilePath and not -w $outputFilePath) { + } elsif (-f $outputFilePath and not -w $outputFilePath) { $errorMessage = $c->maketext( 'Write permissions have not been enabled for "[_1]". ' . 'Changes must be saved to another file for viewing.', - $c->shortPath($outputFilePath) + $c->shortPath($outputFile) ); } else { $errorMessage = - $c->maketext('Unable to write to "[_1]": [_2]', $c->shortPath($outputFilePath), $writeFileErrors); + $c->maketext('Unable to write to "[_1]": [_2]', $c->shortPath($outputFile), $writeFileErrors); } - - $c->{failure} = 1; $c->addbadmessage($errorMessage); + } else { + $c->addgoodmessage($c->maketext('Saved to file "[_1]".', $c->shortPath($outputFile))); } - if (!$writeFileErrors && !$do_not_save && defined $outputFilePath && !$c->{failure}) { - $c->addgoodmessage($c->maketext('Saved to file "[_1]"', $c->shortPath($outputFilePath))); - } - - return; + return $writeFileErrors ? 0 : 1; } +# This is only called after $c->{sourceFile} has been validated and no additional +# validation is needed. sub save_handler ($c) { - my $courseName = $c->stash('courseID'); - my $achievementName = $c->stash('achievementID'); + my $ce = $c->ce; - # Grab the achievementContents from the form in order to save it to the source path $c->stash->{achievementContents} = fix_newlines($c->param('achievementContents')); - - # Construct the output file path - $c->saveFileChanges($c->{sourceFilePath}); - + # Update source file if file is successfully saved. + if ($c->saveFileChanges($c->{sourceFile})) { + $c->{sourceFilePath} = "$ce->{courseDirs}{achievements}/$c->{sourceFile}"; + $c->{sourceFileIsProtected} = 0; + } return; } sub save_as_handler ($c) { my $db = $c->db; - $c->{status_message} = $c->c; ## DPVC -- remove bogus old messages + my $ce = $c->ce; + my $courseName = $c->stash('courseID'); my $achievementName = $c->stash('achievementID'); my $effectiveUserName = $c->param('effectiveUser'); - my $do_not_save = 0; my $saveMode = $c->param('action.save_as.saveMode') || 'no_save_mode_selected'; my $new_file_name = $c->param('action.save_as.target_file') || ''; - my $sourceFilePath = $c->param('action.save_as.source_file') || ''; my $targetAchievementID = $c->param('action.save_as.id') || ''; - $c->{sourceFilePath} = $sourceFilePath; # store for use in saveFileChanges - $new_file_name =~ s/^\s*//; #remove initial and final white space + $c->stash->{achievementContents} = fix_newlines($c->param('achievementContents')); + + $new_file_name =~ s/^\s*//; # Remove initial and final white space. $new_file_name =~ s/\s*$//; - if ($new_file_name !~ /\S/) { # need a non-blank file name - # setting $c->{failure} stops saving and any redirects - $do_not_save = 1; + if ($new_file_name !~ /\S/) { $c->addbadmessage($c->maketext('Please specify a file to save to.')); + return; + } elsif ($new_file_name =~ /\//) { + $c->addbadmessage($c->maketext('Achievement files names cannot contain a slash.')); + return; } - # Grab the achievementContents from the form in order to save it to a new permanent file - $c->stash->{achievementContents} = fix_newlines($c->param('achievementContents')); - warn 'achievement contents is empty' unless $c->stash->{achievementContents}; - - # Rescue the user in case they forgot to end the file name with .at - $new_file_name =~ s/\.at$//; # remove it if it is there - $new_file_name .= '.at'; # put it there + # Rescue the user in case they forgot to end the file name with .at. + $new_file_name =~ s/\.at$//; + $new_file_name .= '.at'; - # Construct the output file path - my $outputFilePath = $c->ce->{courseDirs}{achievements} . '/' . $new_file_name; - if (defined $outputFilePath and -e $outputFilePath) { - # setting $do_not_save stops saving and any redirects - $do_not_save = 1; + my $outputFilePath = "$ce->{courseDirs}{achievements}/$new_file_name"; + if (-f $outputFilePath) { $c->addbadmessage($c->maketext( 'File "[_1]" exists. File not saved. No changes have been made.', - $c->shortPath($outputFilePath) + $c->shortPath($new_file_name) )); + return; } elsif ($saveMode eq 'use_in_new' && !$targetAchievementID) { $c->addbadmessage( $c->maketext('No new Achievement ID specified. No new achievement created. File not saved.')); - $do_not_save = 1; - + return; } elsif ($saveMode eq 'use_in_new' && $db->existsAchievement($targetAchievementID)) { $c->addbadmessage($c->maketext('Achievement ID exists! No new achievement created. File not saved.')); - $do_not_save = 1; - } else { - $c->{editFilePath} = $outputFilePath; - $c->{inputFilePath} = ''; + return; + } + return unless $c->saveFileChanges($new_file_name); + unless ($saveMode eq 'dont_use') { + $c->{sourceFile} = $new_file_name; + $c->{sourceFilePath} = $outputFilePath; } - - return '' if $do_not_save; - - #Save changes - $c->saveFileChanges($outputFilePath); if ($saveMode eq 'use_in_current' and -r $outputFilePath) { - # Modify evaluator path in current achievement - my $achievement = $c->db->getAchievement($achievementName); + my $achievement = $c->{achievement}; $achievement->test($new_file_name); if ($c->db->putAchievement($achievement)) { $c->addgoodmessage($c->maketext( 'The evaluator for [_1] has been renamed to "[_2]".', $achievementName, - $c->shortPath($outputFilePath) + $c->shortPath($new_file_name) )); } else { $c->addbadmessage( $c->maketext('Unable to change the evaluator for set [_1]. Unknown error.', $achievementName)); } - } elsif ($saveMode eq 'use_in_new') { - # Create a new achievement to use the evaluator in my $achievement = $c->db->newAchievement(); $achievement->achievement_id($targetAchievementID); $achievement->test($new_file_name); @@ -278,27 +222,61 @@ sub save_as_handler ($c) { $c->db->addAchievement($achievement); $c->addgoodmessage($c->maketext( 'Achievement [_1] created with evaluator "[_2]".', $targetAchievementID, - $c->shortPath($outputFilePath) + $c->shortPath($new_file_name) )); - + $c->{achievement} = $achievement; } elsif ($saveMode eq 'dont_use') { - # Don't change any achievements - just report - $c->addgoodmessage($c->maketext('A new file has been created at "[_1]"', $c->shortPath($outputFilePath))); + # Don't change any achievements - just report. + $c->addgoodmessage($c->maketext( + 'A new file has been created at "[_1]". Editing original achievement evaluator "[_2]".', + $c->shortPath($new_file_name), + $c->{sourceFile} + )); + # FIXME: Currently editor cannot edit a file not associated with an achievement. + # Update saved data so the editor correctly shows/edits the original achievement evaluator. + $c->stash->{achievementContents} = ''; } else { $c->addbadmessage($c->maketext(q{Don't recognize saveMode: |[_1]|. Unknown error.}, $saveMode)); } - # Set up redirect - # The redirect gives the server time to detect that the new file exists. - $c->authen->flash(status_message => $c->{status_message}->join('')); - $c->reply_with_redirect($c->systemLink( - $c->url_for( - 'instructor_achievement_editor', - achievementID => $saveMode eq 'use_in_new' ? $targetAchievementID : $achievementName - ), - params => { sourceFilePath => $c->getRelativeSourceFilePath($outputFilePath) } + return; +} + +sub revert_handler ($c) { + my $ce = $c->ce; + my $sourceFile = $c->{sourceFile}; + my $confirmDelete = $c->param('action.delete.confirm') // ''; + my $deletePath = "$ce->{courseDirs}{achievements}/$sourceFile"; + my $systemPath = "$ce->{webworkDirs}{achievementEvaluators}/$sourceFile"; + + # Use form contents in case there is a validation error. + $c->stash->{achievementContents} = fix_newlines($c->param('achievementContents')); + + unless ($confirmDelete eq 'yes') { + $c->addbadmessage($c->maketext('Missing delete confirmation of course override. Not deleting.')); + return; + } + unless (-f $systemPath) { + $c->addbadmessage( + $c->maketext('Achievement evaluator "[_1]" is not a course override. Not deleting.', $sourceFile)); + return; + } + unless (-f $deletePath) { + $c->addbadmessage($c->maketext( + 'Achievement evaluator course override "[_1]" does not exist. Not deleting.', + $c->shortPath($sourceFile) + )); + return; + } + unlink($deletePath); + $c->addgoodmessage($c->maketext( + 'Course override "[_1]" deleted. Reverted to using system achievement.', + $c->shortPath($sourceFile) )); + $c->{sourceFilePath} = $systemPath; + $c->{sourceFileIsProtected} = 1; + $c->stash->{achievementContents} = ''; # Force loading original system achievement contents. return; } diff --git a/lib/WeBWorK/ContentGenerator/Instructor/AchievementList.pm b/lib/WeBWorK/ContentGenerator/Instructor/AchievementList.pm index b8c38350d4..cca2a0518a 100644 --- a/lib/WeBWorK/ContentGenerator/Instructor/AchievementList.pm +++ b/lib/WeBWorK/ContentGenerator/Instructor/AchievementList.pm @@ -56,6 +56,13 @@ use constant FORM_TITLES => { cancel_export => x('Cancel Export') }; +# These fields store the filename of an achievement asset, which cannot contain a slash. +use constant FILENAME_FIELDS => { + test => 'achievement evaluator', + icon => 'icon', + email_template => 'email template' +}; + sub initialize ($c) { my $db = $c->db; my $ce = $c->ce; @@ -399,18 +406,29 @@ sub import_handler ($c) { my $ce = $c->ce; my $db = $c->db; - my $fileName = $c->param('action.import.source'); - my $assign = $c->param('action.import.assign'); - my @users = $db->listUsers; - my %allAchievementIDs = map { $_ => 1 } @{ $c->{allAchievementIDs} }; - my %visibleAchievementIDs = map { $_ => 1 } @{ $c->{visibleAchievementIDs} }; - my $filePath = $ce->{courseDirs}{achievements} . '/' . $fileName; + my $fileName = $c->param('action.import.source') // ''; + + return (0, $c->maketext('File "[_1]" contains a slash and is invalid.', $fileName)) if $fileName =~ /\//; + + my $filePath; + if (-f "$ce->{courseDirs}{achievements}/$fileName") { + $filePath = "$ce->{courseDirs}{achievements}/$fileName"; + } elsif (-f "$ce->{webworkDirs}{achievementEvaluators}/$fileName") { + $filePath = "$ce->{webworkDirs}{achievementEvaluators}/$fileName"; + } else { + return (0, $c->maketext('File "[_1]" does not exist.', $fileName)); + } my @userAchievementRecordsToAdd; # Open file name my $fh = Mojo::File->new($filePath)->open('<:encoding(UTF-8)') - or return (0, $c->maketext("Failed to open [_1]", $filePath)); + or return (0, $c->maketext('Failed to open "[_1]".', $filePath)); + + my @users = $db->listUsers; + my $assign = $c->param('action.import.assign'); + my %allAchievementIDs = map { $_ => 1 } @{ $c->{allAchievementIDs} }; + my %visibleAchievementIDs = map { $_ => 1 } @{ $c->{visibleAchievementIDs} }; # Read in lines from file my $count = 0; @@ -436,9 +454,9 @@ sub import_handler ($c) { $achievement->description($$data[5]); $achievement->points($$data[6]); $achievement->max_counter($$data[7]); - $achievement->test($$data[8]); - $achievement->icon($$data[9]); - $achievement->email_template($$data[10] // ''); + $achievement->test($$data[8] =~ /\// ? '' : $$data[8]); # Don't allow / in paths. + $achievement->icon($$data[9] =~ /\// ? '' : $$data[9]); + $achievement->email_template(!$$data[10] || $$data[10] =~ /\// ? '' : $$data[10]); $achievement->enabled($assign eq "all" ? 1 : 0); @@ -566,21 +584,33 @@ sub save_edit_handler ($c) { for my $achievementID (@selectedAchievementIDs) { my $Achievement = $db->getAchievement($achievementID); + unless ($Achievement) { + $c->addbadmessage($c->maketext('No record for achievement "[_1]" found. Skipping.', $achievementID)); + next; + } - # FIXME: we may not want to die on bad achievements, they're not as bad as bad users - die "record for achievement $achievementID not found" unless $Achievement; - - # Update fields + # Update fields. for my $field ($Achievement->NONKEYFIELDS()) { my $param = "achievement.${achievementID}.${field}"; if ($field eq 'assignment_type') { my @types = $c->param($param); $Achievement->assignment_type(join(',', @types)); - } else { - - if (defined $c->param($param)) { - $Achievement->$field($c->param($param)); + } elsif (defined $c->param($param)) { + my $value = $c->param($param); + + # Filename fields test, icon, and email_template cannot contain a slash. + if (FILENAME_FIELDS->{$field} && $value =~ /\//) { + # Skip filename error message for previous saved values. + $c->addbadmessage($c->maketext( + 'Filename "[_1]" for "[_2]" in achievement "[_3]" contains a slash, "/", and is invalid. ' + . 'Not updating.', + $value, FILENAME_FIELDS->{$field}, + $achievementID + )) + unless $value eq $Achievement->$field; + } else { + $Achievement->$field($value); } } } @@ -595,7 +625,19 @@ sub save_edit_handler ($c) { # Get list of files that can be imported. sub getAxpList ($c) { - return @{ Mojo::File->new($c->ce->{courseDirs}{achievements})->list->grep(qr/.*\.axp/)->map('basename') }; + my $ce = $c->ce; + my %fileList; + + # Find all system .apx files. + for (@{ Mojo::File->new($ce->{webworkDirs}{achievementEvaluators})->list->grep(qr/.*\.axp/)->map('basename') }) { + $fileList{$_} = 1; + } + # Find all course .apx files, overriding any system files. + for (@{ Mojo::File->new($c->ce->{courseDirs}{achievements})->list->grep(qr/.*\.axp/)->map('basename') }) { + $fileList{$_} = 1; + } + + return (sort keys %fileList); } 1; diff --git a/lib/WeBWorK/ContentGenerator/Instructor/AchievementNotificationEditor.pm b/lib/WeBWorK/ContentGenerator/Instructor/AchievementNotificationEditor.pm index fa012ee23e..532fe45885 100644 --- a/lib/WeBWorK/ContentGenerator/Instructor/AchievementNotificationEditor.pm +++ b/lib/WeBWorK/ContentGenerator/Instructor/AchievementNotificationEditor.pm @@ -8,7 +8,7 @@ WeBWorK::ContentGenerator::Instructor::AchievementNotificationEditor - edit the =cut use WeBWorK::Utils qw(fix_newlines not_blank x); -use WeBWorK::Utils::Files qw(surePathToFile readFile path_is_subdir); +use WeBWorK::Utils::Files qw(readFile); use constant ACTION_FORMS => [qw(save save_as existing disable)]; use constant ACTION_FORM_TITLES => { @@ -19,32 +19,37 @@ use constant ACTION_FORM_TITLES => { }; sub pre_header_initialize ($c) { - my $courseID = $c->stash('courseID'); - my $achievementID = $c->stash('achievementID'); + my $ce = $c->ce; + my $authz = $c->authz; + my $user = $c->param('user'); # Make sure that are defined for the templates. $c->stash->{formsToShow} = ACTION_FORMS(); $c->stash->{actionFormTitles} = ACTION_FORM_TITLES(); $c->stash->{achievementNotification} = ''; - # Check permissions - return unless ($c->authz->hasPermissions($c->param('user'), 'edit_achievements')); + return unless $authz->hasPermissions($user, 'edit_achievements'); - # Get the achievement - $c->{achievement} = $c->db->getAchievement($achievementID); + my $achievement = $c->db->getAchievement($c->stash('achievementID')); + unless ($achievement) { + $c->addbadmessage($c->maketext('Achievement "[_1]" not found!', $c->stash('achievementID'))); + return; + } - if (!$c->{achievement}) { - $c->addbadmessage($c->maketext('Achievement [_1] not found!', $achievementID)); + my $sourceFile = $achievement->email_template || 'default.txt.epl'; + if ($sourceFile =~ /\//) { + $c->addbadmessage($c->maketext( + 'Achievement notification template "[_1]" filename contains a slash, "/", and cannot be edited.', + $sourceFile + )); return; } - $c->{sourceFilePath} = - $c->ce->{courseDirs}{achievement_notifications} . '/' - . ($c->{achievement}->email_template || 'default.txt.epl'); + $c->{achievement} = $achievement; + $c->{sourceFile} = $sourceFile; + $c->{sourceFilePath} = "$ce->{courseDirs}{achievement_notifications}/$sourceFile"; my $actionID = $c->param('action'); - - # Perform a save or save_as action if ($actionID) { die "Action $actionID not found" unless (grep { $_ eq $actionID } @{ ACTION_FORMS() }); @@ -60,197 +65,163 @@ sub initialize ($c) { my $user = $c->param('user'); my $sourceFilePath = $c->{sourceFilePath}; - return unless ($authz->hasPermissions($user, 'edit_achievements')); - - $c->addmessage($c->authen->flash('status_message') || ''); # Record status messages carried over from a redirect + return unless $authz->hasPermissions($user, 'edit_achievements') && $c->{achievement} && $sourceFilePath; - # Check source file path - if (!-e $sourceFilePath) { - $c->addbadmessage($c->maketext('The file [_1] cannot be found.', $sourceFilePath)); + # Check source file path. + unless (-f $sourceFilePath) { + $c->addbadmessage($c->maketext( + 'The achievement notification template file "[_1]" cannot be found.', + $c->shortPath($c->{sourceFile}) + )); return; } # Find the text for the achievement. - unless ($c->stash('achievementNotification') =~ /\S/) { - unless (path_is_subdir($sourceFilePath, $c->ce->{courseDirs}{achievement_notifications}, 1)) { - $c->addbadmessage('Path is Unsafe!'); - return; - } - - eval { $c->stash->{achievementNotification} = readFile($sourceFilePath); }; + unless (not_blank($c->stash->{achievementNotification})) { + eval { $c->stash->{achievementNotification} = readFile($sourceFilePath) }; $c->stash->{achievementNotification} = $@ if $@; } return; } -# Convert long paths to [ACHEVNOTIFYDIR] +# Append [ACHEVNOTIFYDIR] to filename. sub shortPath ($c, $file) { - my $achievementsDir = $c->ce->{courseDirs}{achievement_notifications}; - return $file =~ s|^$achievementsDir|[ACHEVNOTIFYDIR]|r; -} - -sub getRelativeSourceFilePath ($c, $sourceFilePath) { - my $achievementsDir = $c->ce->{courseDirs}{achievement_notifications}; - return $sourceFilePath =~ s|^$achievementsDir/*||r; # remove templates path and any slashes that follow + return "[ACHEVNOTIFYDIR]/$file"; } -# saveFileChanges does most of the work. It is a separate method so that it can -# be called from either pre_header_initialize or initialize, depending on -# whether a redirect is needed or not. -sub saveFileChanges ($c, $outputFilePath) { +# saveFileChanges does the work of saving the file for both the save_handler +# and the save_as_handler. Be sure that $outputFile is validated before calling +# this method (defined, not blank, and does not contain a slash). +sub saveFileChanges ($c, $outputFile) { my $ce = $c->ce; - unless (not_blank($outputFilePath)) { - $c->addbadmessage($c->maketext('You must specify an file name in order to save a new file.')); - return; - } + # This shouldn't be needed, but one last check for safety. + return 0 if !$outputFile || $outputFile =~ /\//; - # make sure any missing directories are created - surePathToFile($ce->{courseDirs}{achievement_notifications}, $outputFilePath); - die 'outputFilePath is unsafe!' - unless path_is_subdir($outputFilePath, $ce->{courseDirs}{achievement_notifications}, 1); + my $outputFilePath = "$ce->{courseDirs}{achievement_notifications}/$outputFile"; eval { - # Write changes to the file. - open my $OUTPUTFILE, '>', $outputFilePath - or die "Failed to open $outputFilePath"; - print $OUTPUTFILE $c->stash('achievementNotification'); + open my $OUTPUTFILE, '>', $outputFilePath or die "Failed to open $outputFilePath"; + print $OUTPUTFILE $c->stash->{achievementNotification}; close $OUTPUTFILE; }; - my $writeFileErrors = $@; - # Catch errors in saving files, + my $writeFileErrors = $@; if ($writeFileErrors) { - # Get the current directory from the outputFilePath - $outputFilePath =~ m|^(/.*?/)[^/]+$|; - my $currentDirectory = $1; - my $errorMessage; - - # Check why we failed to give better error messages - if (!-w $ce->{courseDirs}{achievement_notifications}) { + # Check why we failed to give better error messages. + if (not -d $ce->{courseDirs}{achievement_notifications}) { + $errorMessage = $c->maketext('Course achievement notifications directory does not exist. File not saved.'); + } elsif (not -w $ce->{courseDirs}{achievement_notifications}) { $errorMessage = $c->maketext( 'Write permissions have not been enabled in the templates directory. No changes can be made.'); - } elsif (!-w $currentDirectory) { - $errorMessage = $c->maketext( - 'Write permissions have not been enabled in "[_1]". ' - . 'Changes must be saved to a different directory for viewing.', - $c->shortPath($currentDirectory) - ); - } elsif (-e $outputFilePath && !-w $outputFilePath) { + } elsif (-f $outputFilePath and not -w $outputFilePath) { $errorMessage = $c->maketext( 'Write permissions have not been enabled for "[_1]". ' . 'Changes must be saved to another file for viewing.', - $c->shortPath($outputFilePath) + $c->shortPath($outputFile) ); } else { $errorMessage = - $c->maketext('Unable to write to "[_1]": [_2]', $c->shortPath($outputFilePath), $writeFileErrors); + $c->maketext('Unable to write to "[_1]": [_2]', $c->shortPath($outputFile), $writeFileErrors); } - $c->addbadmessage($errorMessage); } else { - $c->addgoodmessage($c->maketext('Saved to file "[_1]"', $c->shortPath($outputFilePath))); + $c->addgoodmessage($c->maketext('Saved to file "[_1]".', $c->shortPath($outputFile))); } - return; + return $writeFileErrors ? 0 : 1; } +# This is only called after $c->{sourceFile} has been validated and no additional +# validation is needed. sub save_handler ($c) { - # Grab the achievementNotification from the form in order to save it to the source path $c->stash->{achievementNotification} = fix_newlines($c->param('achievementNotification')); - - # Construct the output file path - $c->saveFileChanges($c->{sourceFilePath}); + $c->saveFileChanges($c->{sourceFile}); return; } sub save_as_handler ($c) { - $c->{status_message} = $c->c; - my $courseName = $c->stash('courseID'); - my $achievementName = $c->stash('achievementID'); - my $effectiveUserName = $c->param('effectiveUser'); + my $ce = $c->ce; + my $achievementName = $c->stash('achievementID'); + + my $new_file_name = $c->param('action.save_as.target_file') || ''; - my $new_file_name = $c->param('action.save_as.target_file') || ''; - my $targetAchievementID = $c->param('action.save_as.id') || ''; + $c->stash->{achievementNotification} = fix_newlines($c->param('achievementNotification')); - $new_file_name =~ s/^\s*|\s*$//g; # remove initial and final white space - if ($new_file_name !~ /\S/) { # need a non-blank file name + $new_file_name =~ s/^\s*//; # Remove initial and final white space. + $new_file_name =~ s/\s*$//; + if ($new_file_name !~ /\S/) { $c->addbadmessage($c->maketext('Please specify a file to save to.')); return; + } elsif ($new_file_name =~ /\//) { + $c->addbadmessage($c->maketext('Achievement notification template filenames cannot contain a slash, "/".')); + return; } - # Grab the achievementNotification from the form in order to save it to a new permanent file - $c->stash->{achievementNotification} = fix_newlines($c->param('achievementNotification')); - $c->addbadmessage($c->maketext('Achievement notification contents is empty.')) - unless $c->stash->{achievementNotification}; - - # Rescue the user in case they forgot to end the file name with .txt.epl + # Rescue the user in case they forgot to end the filename with .txt.epl. $new_file_name =~ s/(\.html|\.txt)?(\.epl?)?$/.txt.epl/; - # Construct the output file path. - my $outputFilePath = $c->ce->{courseDirs}{achievement_notifications} . '/' . $new_file_name; - if (defined $outputFilePath && -e $outputFilePath) { + my $outputFilePath = "$ce->{courseDirs}{achievement_notifications}/$new_file_name"; + if (-e $outputFilePath) { $c->addbadmessage($c->maketext( 'File "[_1]" exists. File not saved. No changes have been made.', - $c->shortPath($outputFilePath) + $c->shortPath($new_file_name) )); return; - } else { - $c->{editFilePath} = $outputFilePath; - $c->{inputFilePath} = ''; } - $c->saveFileChanges($outputFilePath); + return unless $c->saveFileChanges($new_file_name); + + $c->{sourceFile} = $new_file_name; + $c->{sourceFilePath} = $outputFilePath; - # Modify achievement notification template path for the current achievement $c->{achievement}->email_template($new_file_name); if ($c->db->putAchievement($c->{achievement})) { $c->addgoodmessage($c->maketext( - 'The achievement notification template for [_1] has been renamed to "[_2]".', $achievementName, - $c->shortPath($outputFilePath) + 'The achievement notification template for "[_1]" has been renamed to "[_2]".', $achievementName, + $c->shortPath($new_file_name) )); } else { $c->addbadmessage($c->maketext( - 'Unable to change the achievement notification template for achievement [_1]. Unknown error.', + 'Unable to change the achievement notification template for achievement "[_1]". Unknown error.', $achievementName )); } - # A redirect is needed to ensure that all data and parameters for page display are updated correctly. - # FIXME: This could be done without a redirect if the data and parameters were updated here instead. - $c->authen->flash(status_message => $c->{status_message}->join('')); - $c->reply_with_redirect($c->systemLink( - $c->url_for('instructor_achievement_notification', achievementID => $achievementName))); return; } # use an existing template file sub existing_handler ($c) { + my $ce = $c->ce; my $achievementID = $c->stash('achievementID'); + my $sourceFile = $c->param('action.existing.target_file') || ''; - # Get the desired file name from form data. - my $sourceFile = $c->param('action.existing.target_file') || ''; + if ($sourceFile =~ /\//) { + $c->addbadmessage($c->maketext('Achievement notification template filenames cannot contain a slash, "/".')); + return; + } - if (-e $c->ce->{courseDirs}{achievement_notifications} . "/$sourceFile") { + if (-f "$ce->{courseDirs}{achievement_notifications}/$sourceFile") { # If it exists, update the achievement to use the existing email template. $c->{achievement}->email_template($sourceFile); if ($c->db->putAchievement($c->{achievement})) { + $c->{sourceFile} = $sourceFile; + $c->{sourceFilePath} = "$ce->{courseDirs}{achievement_notifications}/$sourceFile"; + $c->stash->{achievementNotification} = ''; # Force loading the newly selected template's contents. $c->addgoodmessage($c->maketext( - 'The notification for [_1] has been changed to "[_2]".', $achievementID, $sourceFile)); + 'The notification for "[_1]" has been changed to "[_2]".', + $achievementID, $sourceFile + )); } else { $c->addbadmessage($c->maketext( - 'Unable to change the notification for [_1]. Unknown error.', $achievementID)); + 'Unable to change the notification for "[_1]". Unknown error.', $achievementID)); } } else { - $c->addbadmessage($c->maketext('The file "[_1]" cannot be found.', $sourceFile)); + $c->addbadmessage($c->maketext('The file "[_1]" cannot be found.', $c->shortPath($sourceFile))); } - # A redirect is needed to ensure that all data and parameters for page display are updated correctly. - # FIXME: This could be done without a redirect if the data and parameters were updated here instead. - $c->authen->flash(status_message => $c->{status_message}->join('')); - $c->reply_with_redirect($c->systemLink( - $c->url_for('instructor_achievement_notification', achievementID => $achievementID))); return; } @@ -259,7 +230,7 @@ sub disable_handler ($c) { if ($c->db->putAchievement($c->{achievement})) { $c->addgoodmessage($c->maketext( - 'The achievement notification template for achievement [_1] has been disabled.', + 'The achievement notification template for "[_1]" has been disabled.', $c->stash('achievementID') )); @@ -268,7 +239,7 @@ sub disable_handler ($c) { $c->reply_with_redirect($c->systemLink($c->url_for('instructor_achievement_list'))); } else { $c->addbadmessage($c->maketext( - 'Unable to disable the achievement notification template for achievement [_1]. Unknown error.', + 'Unable to disable the achievement notification template for "[_1]". Unknown error.', $c->stash('achievementID') )); } diff --git a/lib/WeBWorK/Utils.pm b/lib/WeBWorK/Utils.pm index 391930c0af..7734c60562 100644 --- a/lib/WeBWorK/Utils.pm +++ b/lib/WeBWorK/Utils.pm @@ -32,6 +32,8 @@ our @EXPORT_OK = qw( generateURLs formatEmailSubject getAssetURL + getAchievementIconURL + isAchievementAssetOverridden points_stepsize round_nearest_stepsize x @@ -535,6 +537,28 @@ sub getAssetURL ($ce, $file, $isThemeFile = 0) { return "$ce->{webworkURLs}{htdocs}/$file"; } +sub getAchievementIconURL ($ce, $icon) { + return "$ce->{webworkURLs}{achievementIcons}/defaulticon.png" if !$icon || $icon =~ /\//; + + if (-f "$ce->{courseDirs}{achievements_html}/$icon") { + return "$ce->{courseURLs}{achievements}/$icon"; + } + if (-f "$ce->{webworkDirs}{achievementIcons}/$icon") { + return "$ce->{webworkURLs}{achievementIcons}/$icon"; + } + return "$ce->{webworkURLs}{achievementIcons}/defaulticon.png"; +} + +sub isAchievementAssetOverridden ($ce, $type, $asset) { + return 0 if !$asset || $asset =~ /\//; + return ($type eq 'icon' + && -f "$ce->{courseDirs}{achievements_html}/$asset" + && -f "$ce->{webworkDirs}{achievementIcons}/$asset") + || ($type eq 'test' + && -f "$ce->{courseDirs}{achievements}/$asset" + && -f "$ce->{webworkDirs}{achievementEvaluators}/$asset"); +} + sub points_stepsize ($points) { my $stepsize; if ($points == 1) { @@ -787,6 +811,24 @@ Returns the URL for the asset specified in C<$file>. If C<$isThemeFile> is true, then the asset will be assumed to be located in a theme directory. The parameter C<$ce> must be a valid C object. +=head2 getAchievementIconURL + +Usage: C + +Returns the URL path for an achievement icon for a given course environment. +This checks if the icon provided is a valid icon file (defined and doesn't contain +a slash), then checks if the icon file exists in the course templates directory, +and finally if the icon file exists in the WeBWorK images directory. It returns the +URL to the first valid file found, or the URL to the system default icon otherwise. + +=head2 isAchievementAssetOverridden + +Usage: C + +This tests if an achievement icon, C<$type='icon'>, or an achievement evaluator, +C<$type='test'>, file name C<$asset> is a system file being overridden by a course +file of the same name in the given course environment. + =head2 points_stepsize Usage: C diff --git a/templates/AchievementEvaluator/cheevoMessage.html.ep b/templates/AchievementEvaluator/cheevoMessage.html.ep index 5f795567a0..15f34882d1 100644 --- a/templates/AchievementEvaluator/cheevoMessage.html.ep +++ b/templates/AchievementEvaluator/cheevoMessage.html.ep @@ -1,10 +1,10 @@ +% use WeBWorK::Utils qw(getAchievementIconURL); +%