mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-04 05:53:43 +00:00 
			
		
		
		
	todo_widget: Disable "Add task" button when a task cannot be added.
We want to prevent users from adding a duplicate or empty task to the todo list. For this purpose, we disable the "Add task" button in both the cases. Fixes: #20211
This commit is contained in:
		
				
					committed by
					
						
						Tim Abbott
					
				
			
			
				
	
			
			
			
						parent
						
							926716d9f2
						
					
				
				
					commit
					1878200402
				
			@@ -258,6 +258,20 @@ export function initialize(): void {
 | 
				
			|||||||
        appendTo: () => document.body,
 | 
					        appendTo: () => document.body,
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tippy.delegate("body", {
 | 
				
			||||||
 | 
					        target: ".add-task-wrapper",
 | 
				
			||||||
 | 
					        onShow(instance) {
 | 
				
			||||||
 | 
					            const $elem = $(instance.reference);
 | 
				
			||||||
 | 
					            const content = $elem.attr("data-tippy-content");
 | 
				
			||||||
 | 
					            if (content === undefined) {
 | 
				
			||||||
 | 
					                return false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            instance.setContent(content);
 | 
				
			||||||
 | 
					            return undefined;
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        appendTo: () => document.body,
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $("body").on(
 | 
					    $("body").on(
 | 
				
			||||||
        "blur",
 | 
					        "blur",
 | 
				
			||||||
        ".message_control_button, .delete-selected-drafts-button-container",
 | 
					        ".message_control_button, .delete-selected-drafts-button-container",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,5 @@
 | 
				
			|||||||
import $ from "jquery";
 | 
					import $ from "jquery";
 | 
				
			||||||
 | 
					import _ from "lodash";
 | 
				
			||||||
import assert from "minimalistic-assert";
 | 
					import assert from "minimalistic-assert";
 | 
				
			||||||
import {z} from "zod";
 | 
					import {z} from "zod";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -404,6 +405,13 @@ export function activate({
 | 
				
			|||||||
        const html = render_widgets_todo_widget();
 | 
					        const html = render_widgets_todo_widget();
 | 
				
			||||||
        $elem.html(html);
 | 
					        $elem.html(html);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // This throttling ensures that the function runs only after the user stops typing.
 | 
				
			||||||
 | 
					        const throttled_update_add_task_button = _.throttle(update_add_task_button, 300);
 | 
				
			||||||
 | 
					        $elem.find("input.add-task").on("keyup", (e) => {
 | 
				
			||||||
 | 
					            e.stopPropagation();
 | 
				
			||||||
 | 
					            throttled_update_add_task_button();
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $elem.find("input.todo-task-list-title").on("keyup", (e) => {
 | 
					        $elem.find("input.todo-task-list-title").on("keyup", (e) => {
 | 
				
			||||||
            e.stopPropagation();
 | 
					            e.stopPropagation();
 | 
				
			||||||
            update_edit_controls();
 | 
					            update_edit_controls();
 | 
				
			||||||
@@ -444,13 +452,10 @@ export function activate({
 | 
				
			|||||||
            const task = $elem.find<HTMLInputElement>("input.add-task").val()?.trim() ?? "";
 | 
					            const task = $elem.find<HTMLInputElement>("input.add-task").val()?.trim() ?? "";
 | 
				
			||||||
            const desc = $elem.find<HTMLInputElement>("input.add-desc").val()?.trim() ?? "";
 | 
					            const desc = $elem.find<HTMLInputElement>("input.add-desc").val()?.trim() ?? "";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (task === "") {
 | 
					 | 
				
			||||||
                return;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            $elem.find("input.add-task").val("").trigger("focus");
 | 
					            $elem.find("input.add-task").val("").trigger("focus");
 | 
				
			||||||
            $elem.find("input.add-desc").val("");
 | 
					            $elem.find("input.add-desc").val("");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // This case should not generally occur.
 | 
				
			||||||
            const task_exists = task_data.name_in_use(task);
 | 
					            const task_exists = task_data.name_in_use(task);
 | 
				
			||||||
            if (task_exists) {
 | 
					            if (task_exists) {
 | 
				
			||||||
                $elem.find(".widget-error").text($t({defaultMessage: "Task already exists"}));
 | 
					                $elem.find(".widget-error").text($t({defaultMessage: "Task already exists"}));
 | 
				
			||||||
@@ -462,6 +467,30 @@ export function activate({
 | 
				
			|||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function update_add_task_button(): void {
 | 
				
			||||||
 | 
					        const task = $elem.find<HTMLInputElement>("input.add-task").val()?.trim() ?? "";
 | 
				
			||||||
 | 
					        const task_exists = task_data.name_in_use(task);
 | 
				
			||||||
 | 
					        const $add_task_wrapper = $elem.find(".add-task-wrapper");
 | 
				
			||||||
 | 
					        const $add_task_button = $elem.find("button.add-task");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (task === "") {
 | 
				
			||||||
 | 
					            $add_task_wrapper.attr(
 | 
				
			||||||
 | 
					                "data-tippy-content",
 | 
				
			||||||
 | 
					                $t({defaultMessage: "Name the task before adding."}),
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					            $add_task_button.prop("disabled", true);
 | 
				
			||||||
 | 
					        } else if (task_exists) {
 | 
				
			||||||
 | 
					            $add_task_wrapper.attr(
 | 
				
			||||||
 | 
					                "data-tippy-content",
 | 
				
			||||||
 | 
					                $t({defaultMessage: "Cannot add duplicate task."}),
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					            $add_task_button.prop("disabled", true);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            $add_task_wrapper.removeAttr("data-tippy-content");
 | 
				
			||||||
 | 
					            $add_task_button.prop("disabled", false);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function render_results(): void {
 | 
					    function render_results(): void {
 | 
				
			||||||
        const widget_data = task_data.get_widget_data();
 | 
					        const widget_data = task_data.get_widget_data();
 | 
				
			||||||
        const html = render_widgets_todo_widget_tasks(widget_data);
 | 
					        const html = render_widgets_todo_widget_tasks(widget_data);
 | 
				
			||||||
@@ -487,6 +516,8 @@ export function activate({
 | 
				
			|||||||
            const data = task_data.handle.strike.outbound(key);
 | 
					            const data = task_data.handle.strike.outbound(key);
 | 
				
			||||||
            callback(data);
 | 
					            callback(data);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        update_add_task_button();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const handle_events = function (events: Event[]): void {
 | 
					    const handle_events = function (events: Event[]): void {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -237,6 +237,13 @@ button {
 | 
				
			|||||||
            transition: 0.2s ease;
 | 
					            transition: 0.2s ease;
 | 
				
			||||||
            transition-property: background-color, border-color, color;
 | 
					            transition-property: background-color, border-color, color;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        &:disabled {
 | 
				
			||||||
 | 
					            cursor: not-allowed;
 | 
				
			||||||
 | 
					            filter: saturate(0);
 | 
				
			||||||
 | 
					            background-color: var(--color-background-zulip-button-disabled);
 | 
				
			||||||
 | 
					            color: hsl(0deg 3% 52%);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -308,3 +315,17 @@ input {
 | 
				
			|||||||
.current-user-vote {
 | 
					.current-user-vote {
 | 
				
			||||||
    background-color: hsl(156deg 10% 90% / 90%);
 | 
					    background-color: hsl(156deg 10% 90% / 90%);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.add-task-wrapper {
 | 
				
			||||||
 | 
					    display: inline;
 | 
				
			||||||
 | 
					    position: relative;
 | 
				
			||||||
 | 
					    z-index: 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Unlike other browsers like Chrome, Microsoft Edge, etc.,
 | 
				
			||||||
 | 
					    Firefox does not automatically display the "not-allowed"
 | 
				
			||||||
 | 
					    cursor for disabled elements. The below css ensures that the
 | 
				
			||||||
 | 
					    correct cursor is shown across all browsers. */
 | 
				
			||||||
 | 
					    &:hover {
 | 
				
			||||||
 | 
					        cursor: not-allowed;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,7 +13,9 @@
 | 
				
			|||||||
    <div class="add-task-bar sea-green">
 | 
					    <div class="add-task-bar sea-green">
 | 
				
			||||||
        <input type="text" class="add-task" placeholder="{{t 'New task'}}" />
 | 
					        <input type="text" class="add-task" placeholder="{{t 'New task'}}" />
 | 
				
			||||||
        <input type="text" class="add-desc" placeholder="{{t 'Description'}}" />
 | 
					        <input type="text" class="add-desc" placeholder="{{t 'Description'}}" />
 | 
				
			||||||
 | 
					        <div class="add-task-wrapper">
 | 
				
			||||||
            <button class="add-task">{{t "Add task" }}</button>
 | 
					            <button class="add-task">{{t "Add task" }}</button>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
        <div class="widget-error"></div>
 | 
					        <div class="widget-error"></div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user