Skip to content

Commit

Permalink
Allowing unsetting of favourite program (#5151)
Browse files Browse the repository at this point in the history
Fixes #5132

**How to test:**
1. Login (have a public profile and a public program)
2. Click on favourite a program and unfavourite the program


https://github.com/hedyorg/hedy/assets/48122190/88bb0be2-16de-471b-ae10-92bfcaf07c55
  • Loading branch information
TiBiBa authored Apr 9, 2024
1 parent b3c1b02 commit d1ba0e8
Show file tree
Hide file tree
Showing 64 changed files with 474 additions and 93 deletions.
6 changes: 6 additions & 0 deletions messages.pot
Original file line number Diff line number Diff line change
Expand Up @@ -1793,6 +1793,12 @@ msgstr ""
msgid "unauthorized"
msgstr ""

msgid "unfavourite_confirm"
msgstr ""

msgid "unfavourite_success"
msgstr ""

msgid "unique_usernames"
msgstr ""

Expand Down
40 changes: 23 additions & 17 deletions static/js/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -719,47 +719,53 @@ export function viewProgramLink(programId: string) {
return window.location.origin + '/hedy/' + programId + '/view';
}

export async function delete_program(id: string, index: number, prompt: string) {
export async function delete_program(id: string, prompt: string) {
await modal.confirmP(prompt);
await tryCatchPopup(async () => {
const response = await postJsonWithAchievements('/programs/delete', { id });
showAchievements(response.achievement, true, "");
$('#program_' + index).remove();
$('#program_' + id).remove();
modal.notifySuccess(response.message);
});
}

function set_favourite(index: number) {
function set_favourite(id: string, set: boolean) {
$('.favourite_program_container').removeClass('text-yellow-400');
$('.favourite_program_container').addClass('text-white');
$('.favourite_program_container').attr("data-starred", "false");

$('#favourite_program_container_' + index).removeClass('text-white');
$('#favourite_program_container_' + index).addClass('text-yellow-400');
if (set) {
$('#favourite_program_container_' + id).removeClass('text-white');
$('#favourite_program_container_' + id).addClass('text-yellow-400');
}
$('#favourite_program_container_' + id).attr("data-starred", JSON.stringify(set));
}

export async function set_favourite_program(id: string, index: number, prompt: string) {
await modal.confirmP(prompt);
export async function set_favourite_program(id: string, promptSet: string, promptUnset: string) {
let set = JSON.parse($('#favourite_program_container_' + id).attr("data-starred")?.toLowerCase() || "");
await modal.confirmP(set ? promptUnset : promptSet);
await tryCatchPopup(async () => {
const response = await postJsonWithAchievements('/programs/set_favourite', { id });
set_favourite(index)
const response = await postJsonWithAchievements('/programs/set_favourite', { id, set: !set });
// TODO: response with 200, assumed.
set_favourite(id, !set)
modal.notifySuccess(response.message);
});
}

function change_to_submitted (index: number) {
function change_to_submitted (id: string) {
// Index is a front-end unique given to each program container and children
// This value enables us to remove, hide or show specific element without connecting to the server (again)
$('#non_submitted_button_container_' + index).remove();
$('#submitted_button_container_' + index).show();
$('#submitted_header_' + index).show();
$('#program_' + index).removeClass("border-orange-400");
$('#program_' + index).addClass("border-gray-400 bg-gray-400");
$('#non_submitted_button_container_' + id).remove();
$('#submitted_button_container_' + id).show();
$('#submitted_header_' + id).show();
$('#program_' + id).removeClass("border-orange-400");
$('#program_' + id).addClass("border-gray-400 bg-gray-400");
}

export function submit_program (id: string, index: number) {
export function submit_program (id: string) {
tryCatchPopup(async () => {
await postJsonWithAchievements('/programs/submit', { id });
change_to_submitted(index);
change_to_submitted(id);
});
}

Expand Down
40 changes: 23 additions & 17 deletions static/js/appbundle.js
Original file line number Diff line number Diff line change
Expand Up @@ -99205,40 +99205,46 @@ def note_with_error(value, err):
function viewProgramLink(programId) {
return window.location.origin + "/hedy/" + programId + "/view";
}
async function delete_program(id2, index3, prompt) {
async function delete_program(id2, prompt) {
await modal.confirmP(prompt);
await tryCatchPopup(async () => {
const response = await postJsonWithAchievements("/programs/delete", { id: id2 });
showAchievements(response.achievement, true, "");
$("#program_" + index3).remove();
$("#program_" + id2).remove();
modal.notifySuccess(response.message);
});
}
function set_favourite(index3) {
function set_favourite(id2, set2) {
$(".favourite_program_container").removeClass("text-yellow-400");
$(".favourite_program_container").addClass("text-white");
$("#favourite_program_container_" + index3).removeClass("text-white");
$("#favourite_program_container_" + index3).addClass("text-yellow-400");
$(".favourite_program_container").attr("data-starred", "false");
if (set2) {
$("#favourite_program_container_" + id2).removeClass("text-white");
$("#favourite_program_container_" + id2).addClass("text-yellow-400");
}
$("#favourite_program_container_" + id2).attr("data-starred", JSON.stringify(set2));
}
async function set_favourite_program(id2, index3, prompt) {
await modal.confirmP(prompt);
async function set_favourite_program(id2, promptSet, promptUnset) {
var _a3;
let set2 = JSON.parse(((_a3 = $("#favourite_program_container_" + id2).attr("data-starred")) == null ? void 0 : _a3.toLowerCase()) || "");
await modal.confirmP(set2 ? promptUnset : promptSet);
await tryCatchPopup(async () => {
const response = await postJsonWithAchievements("/programs/set_favourite", { id: id2 });
set_favourite(index3);
const response = await postJsonWithAchievements("/programs/set_favourite", { id: id2, set: !set2 });
set_favourite(id2, !set2);
modal.notifySuccess(response.message);
});
}
function change_to_submitted(index3) {
$("#non_submitted_button_container_" + index3).remove();
$("#submitted_button_container_" + index3).show();
$("#submitted_header_" + index3).show();
$("#program_" + index3).removeClass("border-orange-400");
$("#program_" + index3).addClass("border-gray-400 bg-gray-400");
function change_to_submitted(id2) {
$("#non_submitted_button_container_" + id2).remove();
$("#submitted_button_container_" + id2).show();
$("#submitted_header_" + id2).show();
$("#program_" + id2).removeClass("border-orange-400");
$("#program_" + id2).addClass("border-gray-400 bg-gray-400");
}
function submit_program(id2, index3) {
function submit_program(id2) {
tryCatchPopup(async () => {
await postJsonWithAchievements("/programs/submit", { id: id2 });
change_to_submitted(index3);
change_to_submitted(id2);
});
}
function unsubmit_program(id2) {
Expand Down
4 changes: 2 additions & 2 deletions static/js/appbundle.js.map

Large diffs are not rendered by default.

47 changes: 26 additions & 21 deletions templates/htmx-program.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<div id="program_{{ loop_index }}" class="program w-full border-solid border-2 {% if program.submitted %} border-gray-400 bg-gray-400 {% else %} border-orange-400 {% endif %} rounded p-4 mb-4">
<h3 id="submitted_header_{{ loop_index }}" class="mt-0 mb-4 text-red-500 text-center {% if not program.submitted %} hidden{% endif %}">{{_('submitted_header')}}</h3>
<div id="program_{{ program.id }}" data-name="{{program.name}}" data-id="{{program.id}}" class="program w-full border-solid border-2 {% if program.submitted %} border-gray-400 bg-gray-400 {% else %} border-orange-400 {% endif %} rounded p-4 mb-4">
<h3 id="submitted_header_{{ program.id }}" class="mt-0 mb-4 text-red-500 text-center {% if not program.submitted %} hidden{% endif %}">{{_('submitted_header')}}</h3>
<div class="flex flex-row">
<table class="table-auto mb-4">
<thead>
Expand All @@ -26,26 +26,31 @@ <h3 id="submitted_header_{{ loop_index }}" class="mt-0 mb-4 text-red-500 text-ce
</tbody>
</table>
{% if public_profile and not second_teachers_programs %}
<div class="ml-36 favourite_program_container {% if public_profile.favourite_program and public_profile.favourite_program == program.id %}text-yellow-400{% else %}text-white{% endif %} text-2xl{% if not program.public %} hidden{% endif %}" id="favourite_program_container_{{ loop_index }}">
<i class="fa fa-star p-4 bg-blue-300 rounded-full cursor-pointer hover:bg-blue-600" onclick="hedyApp.set_favourite_program('{{ program.id }}', {{ loop_index }}, '{{_('favourite_confirm')}}');" aria-hidden="true"></i>
{% set favourite_program = public_profile.favourite_program == program.id %}
<div
id="favourite_program_container_{{ program.id }}"
data-starred="{{favourite_program}}"
class="ml-auto mb-10 favourite_program_container {% if favourite_program %}text-yellow-400{% else %}text-white{% endif %} text-2xl{% if not program.public %} hidden{% endif %}">
<i class="fa fa-star p-4 bg-blue-300 rounded-full cursor-pointer hover:bg-blue-600"
onclick="hedyApp.set_favourite_program('{{ program.id }}', '{{_('favourite_confirm')}}', '{{_('unfavourite_confirm')}}');" aria-hidden="true"></i>
</div>
{% endif %}
<div class="ml-auto dropdown relative">
<button class="gray-btn text-gray-500 border border-gray-600 font-semibold rounded inline-flex items-center gap-2" id="more_options_{{ loop_index }}"
onclick="$('#program_options_dropdown_{{ loop_index }}').slideToggle('medium');">
<button class="gray-btn text-gray-500 border border-gray-600 font-semibold rounded inline-flex items-center gap-2" id="more_options_{{ program.id }}"
onclick="$('#program_options_dropdown_{{ program.id }}').slideToggle('medium');">
<span>{{_('more_options')}}</span>
</button>
<div class="dropdown-menu z-30 min-w-full" id="program_options_dropdown_{{ loop_index }}"
<div class="dropdown-menu z-30 min-w-full" id="program_options_dropdown_{{ program.id }}"
style="display: none; padding: 0px !important; margin: 0px; margin-top: 0.25rem;">
<button class="gray-btn text-blue-500 min-w-full flex justify-between items-center gap-2 border-b border-gray-500" onclick="hedyApp.copy_to_clipboard(`{{program.code}}`, '{{_('copy_clipboard')}}')">{{_('copy_code')}}</button>
{% if program.public %}
<button class="gray-btn text-blue-500 min-w-full flex justify-between items-center gap-2 border-b border-gray-500" onclick="hedyApp.copy_to_clipboard(hedyApp.viewProgramLink('{{program.id}}'), '{{_('copy_clipboard')}}')">{{_('copy_link_to_share')}}</button>
{% endif %}
{% if not second_teachers_programs %}
{% if not program.submitted %}
<button class="gray-btn text-red-500 min-w-full flex justify-between items-center gap-2" data-cy="delete_non_submitted_program_{{ loop_index }}" onclick="hedyApp.delete_program('{{ program.id }}', {{ loop_index }}, '{{_('delete_confirm')}}')">{{_('delete')}}</button>
<button class="gray-btn text-red-500 min-w-full flex justify-between items-center gap-2" data-cy="delete_non_submitted_program_{{ program.id }}" onclick="hedyApp.delete_program('{{ program.id }}', '{{_('delete_confirm')}}')">{{_('delete')}}</button>
{% else %}
<button class="gray-btn text-red-500 min-w-full flex justify-between items-center gap-2" data-cy="delete_submitted_program_{{ loop_index }}" onclick="hedyApp.delete_program('{{ program.id }}', {{ loop_index }}, '{{_('delete_confirm')}}')">{{_('delete')}}</button>
<button class="gray-btn text-red-500 min-w-full flex justify-between items-center gap-2" data-cy="delete_submitted_program_{{ program.id }}" onclick="hedyApp.delete_program('{{ program.id }}', '{{_('delete_confirm')}}')">{{_('delete')}}</button>
{% endif %}
{% endif %}
</div>
Expand All @@ -54,36 +59,36 @@ <h3 id="submitted_header_{{ loop_index }}" class="mt-0 mb-4 text-red-500 text-ce
<div class="w-3/4 turn-pre-into-ace mb-4">
<pre level="{{ program.level }}">{{program.preview_code }}</pre>
</div>
<div id="submitted_button_container_{{ loop_index }}" class="flex flex-row gap-2" {% if not program.submitted %} style="display: none;" {% endif %}>
<div id="submitted_button_container_{{ program.id }}" class="flex flex-row gap-2" {% if not program.submitted %} style="display: none;" {% endif %}>
<button class="blue-btn" onclick="window.open (hedyApp.viewProgramLink('{{program.id}}'))">{{_('open')}}</button>
</div>
<div id="non_submitted_button_container_{{ loop_index }}" class="flex flex-row w-full gap-2 {% if program.submitted %} hidden {% endif %}">
<div id="non_submitted_button_container_{{ program.id }}" class="flex flex-row w-full gap-2 {% if program.submitted %} hidden {% endif %}">
<a href="/hedy/{{program.level|string}}/{{program.id}}"><button class="blue-btn">{{_('open')}}</button></a>
<button class="green-btn" data-cy="submit-btn" {% if not program.public or second_teachers_programs %} style="display: none;" {% endif %} onclick="hedyApp.modal.confirm ('{{_('submit_warning')}}', function () {hedyApp.submit_program ('{{program.id}}', {{ loop_index }})})">{{_('submit_program')}}</button>
<button class="green-btn" data-cy="submit-btn" {% if not program.public or second_teachers_programs %} style="display: none;" {% endif %} onclick="hedyApp.modal.confirm ('{{_('submit_warning')}}', function () {hedyApp.submit_program ('{{program.id}}')})">{{_('submit_program')}}</button>
{% if not second_teachers_programs %}
<div class="dropdown relative">
<button class="white-btn inline-flex items-center gap-2" id="share_option_dropdown_{{ loop_index }}"
onclick="$('#share_dropdown_{{ loop_index }}').slideToggle('medium');">
<button class="white-btn inline-flex items-center gap-2" id="share_option_dropdown_{{ program.id }}"
onclick="$('#share_dropdown_{{ program.id }}').slideToggle('medium');">
<span class="fa fa-{% if program.public %}globe{% else %}lock{% endif %}"></span>
<span>{% if program.public %}{{_('public')}}{% else %}{{_('private')}}{% endif %}</span>
<svg id="share-arrow_{{ loop_index }}" class="fill-current h-6 w-6" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
<svg id="share-arrow_{{ program.id }}" class="fill-current h-6 w-6" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
<path d="M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z" />
</svg>
</button>
<div class="dropdown-menu z-30 min-w-full" id="share_dropdown_{{ loop_index }}"
<div class="dropdown-menu z-30 min-w-full" id="share_dropdown_{{ program.id }}"
style="display: none; padding: 0px !important; margin: 0px; margin-top: 0.25rem;"
_="on mutation of @style
set arrow to #share-arrow_{{ loop_index }}
set arrow to #share-arrow_{{ program.id }}
if *display == 'none'
remove .rotate-180 from arrow
else if not arrow.classList.contains('rotate-180')
add .rotate-180 to arrow
end">
<button id="share_button_{{ loop_index }}" class="gray-btn text-blue-500 min-w-full inline-flex items-center gap-2"
hx-post="/programs/share/{{program.id}}/{{loop_index}}/{{second_teachers_programs}}"
data-cy="unshare_program_{{ loop_index }}"
<button id="share_button_{{ program.id }}" class="gray-btn text-blue-500 min-w-full inline-flex items-center gap-2"
hx-post="/programs/share/{{program.id}}/{{second_teachers_programs}}"
data-cy="unshare_program_{{ program.id }}"
hx-swap="outerHTML"
hx-target="#program_{{ loop_index }}"
hx-target="#program_{{ program.id }}"
>
<span class="fa fa-{% if program.public %}lock{% else %}globe{% endif %}"></span>
<div class="mr-auto" tabindex=0>
Expand Down
4 changes: 2 additions & 2 deletions templates/profile.html
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ <h2 class="profile-section-body-header">{{_('my_messages')}}</h2>
{% endfor %}
</div>
{% endif %}
<h1 class="section-header" onclick="$ ('#public_profile_body').toggle()">{{_('public_profile')}}</h1>
<h1 id="public_profile_button" class="section-header" onclick="$ ('#public_profile_body').toggle()">{{_('public_profile')}}</h1>
<div id="public_profile_body" class="profile-section-body" {% if request.args.get('open') == "public-profile" %} style="display: inline;"{% endif %}>
<h2 class="profile-section-body-header">{{_('public_profile')}}</h2>
<form id="public_profile" class="flex flex-col gap-4">
Expand Down Expand Up @@ -74,7 +74,7 @@ <h3 class="px-2 pt-0 pb-2 my-0 font-semibold">{{_('favourite_program')}}</h3>
<label for="agree_terms" class="cursor-pointer w-full">{{_('public_profile_info')}}</label>
</div>
<div class="flex flex-row">
<button type="submit" class="green-btn">{{_('update_public')}}</button>
<button id="submit_public_profile" type="submit" class="green-btn">{{_('update_public')}}</button>
{% if public_settings %}
<button type="reset" class="ml-auto red-btn" onclick="event.preventDefault(); hedyApp.destroy_public('{{_('are_you_sure')}}');">{{_('delete_public')}}</button>
{% endif %}
Expand Down
2 changes: 1 addition & 1 deletion templates/programs.html
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
</div>
<div class="programs w-full">
{% for program in programs %}
{{ render_partial('htmx-program.html', program=program, adventure_names=adventure_names, public_profile=public_profile, loop_index=loop.index, second_teachers_programs=second_teachers_programs) }}
{{ render_partial('htmx-program.html', program=program, adventure_names=adventure_names, public_profile=public_profile, second_teachers_programs=second_teachers_programs) }}
{% endfor %}

{% if programs|length == 0 %}
Expand Down
Loading

0 comments on commit d1ba0e8

Please sign in to comment.