Commit Graph

41 Commits

Author SHA1 Message Date
Anders Kaseorg eb2c822d3f eslint: Enable object-shorthand avoidExplicitReturnArrows option.
This is equivalent in the absence of ‘this’ (which ESLint knows to
check for).

Signed-off-by: Anders Kaseorg <anders@zulip.com>
2022-11-17 16:48:44 -08:00
Anders Kaseorg da0658967c js: Fix no-jquery/no-event-shorthand.
The event shorthand methods were deprecated in jQuery 3.3.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
2022-03-17 13:10:23 -07:00
Anders Kaseorg f84a2c08d5 js: Prefix jQuery object variable names with $.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2022-03-16 12:52:07 -07:00
Anders Kaseorg b0ce4f1bce docs: Fix many spelling mistakes.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2022-02-07 18:51:06 -08:00
N-Shar-ma 6d2de28bf0 todo_widget: Fix bug where new todos sometimes replaced old todos.
Initialised `this.me` for the TaskData using a constructor to the
current user id.

The bug was caused due to `this.me` never being initialised, and hence
`idx` wasn't incremented on page reload, which resulted in duplicate
`data-key` attributes and hence new todos overwriting older todos with
the same `data-key`

Fixes: #20698
2022-01-24 11:25:32 -08:00
Julia Bichler b673e966ca spectators: Prevent toggling TODO checkboxes.
Checkboxes now don't change if a user who is not logged in
clicks on them.

Fixes #20300.
2021-12-29 17:10:21 -08:00
Manan Rathi f3469ac3c8 todo_widget: Fix /todo checkboxes to match style used in menus.
Fixes #20212
2021-11-16 15:02:53 -08:00
Steve Howell e98e4b5b02 todo widget: Check types for inbound events. 2021-06-14 17:46:16 -07:00
Steve Howell 99cdfbcbe5 widgets: Clean up index handling.
We only need to bump up indexes if inbound
events suggest that we have incremented our
personal index from another device.

We don't want somebody else's runaway index
to affect our index.

(For both widgets the sender_id is part of
the key, so uniqueness across all senders is
not required for the integer part.)
2021-06-14 17:46:16 -07:00
Steve Howell 91b8049ecf minor: Add permission-related comments to widgets. 2021-06-14 17:46:16 -07:00
m-e-l-u-h-a-n 712e32805e todo_widget: Use util.strcmp instead of localeCompare for sorting. 2021-06-12 08:16:19 -07:00
Anders Kaseorg 2004a85fb1 i18n: Automatically convert remaining JavaScript messages to FormatJS.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2021-04-13 17:41:10 -07:00
Anders Kaseorg bb1b2048bd js: Convert static/js/i18n.js to ES6 module.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2021-03-26 10:17:56 -07:00
Anders Kaseorg 3ef6f6e2e2 js: Convert static/js/blueslip.js to ES6 module.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2021-03-17 08:47:15 -04:00
Anders Kaseorg ea9ca6b7d0 js: Use jQuery as a module.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2021-03-12 10:08:25 -08:00
Anders Kaseorg 4513ef8861 js: Convert static/js/todo_widget.js to ES6 module.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2021-02-10 10:27:14 -08:00
Anders Kaseorg d72423ef21 eslint: Replace empty-returns with consistent-return.
Instead of prohibiting ‘return undefined’ (#8669), we require that a
function must return an explicit value always or never.  This prevents
you from forgetting to return a value in some cases.  It will also be
important for TypeScript, which distinguishes between undefined and
void.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
2020-09-25 15:17:59 -07:00
Anders Kaseorg 6ec808b8df js: Add "use strict" directive to CommonJS files.
ES and TypeScript modules are strict by default and don’t need this
directive.  ESLint will remind us to add it to new CommonJS files and
remove it from ES and TypeScript modules.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
2020-07-31 22:09:46 -07:00
Anders Kaseorg 4517c48de2 todo_widget: Convert task_data_holder to an ES6 class TaskData.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2020-07-24 16:58:22 -07:00
Anders Kaseorg 96dcc0ce6e js: Use ES6 object literal shorthand syntax.
Generated by ESLint.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
2020-07-21 12:42:22 -07:00
Anders Kaseorg a9ca5f603b js: Replace deprecated jQuery event trigger shorthand.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2020-07-21 12:01:26 -07:00
Anders Kaseorg f3726db89a js: Normalize strings to double quotes.
Prettier would do this anyway, but it’s separated out for a more
reviewable diff.  Generated by ESLint.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
2020-07-17 14:31:24 -07:00
Anders Kaseorg a79322bc94 eslint: Enable prefer-arrow-callback.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2020-07-03 16:55:50 -07:00
Steve Howell 026474921a todo widget: Downgrade error to warning.
We were creating errors for task keys that were
from older versions of the widget.  We don't migrate
data for the widgets yet (they're all still considered
to be somewhat beta); instead, we just drop bad data
on the floor.

Rohitt and I re-tested the widget on czo pretty
extensively to verify that these errors don't show
up for newly created widgets.
2020-05-06 09:35:04 -04:00
Steve Howell de97351b5a todo widget: Simplify idx calculation.
We now only compute idx on the outbound side,
instead of spreading out the responsibility.

We just iterate through all our items to find
the next available number.
2020-04-08 16:01:54 -04:00
Steve Howell eb83b9a960 todo widget: Remove user_id from data structure.
The only place we use the user_id in the todo
widget is in our keys, which prevents duplicate
keys across senders.
2020-04-08 16:01:54 -04:00
Steve Howell 91a37e7237 todo widget: Use a Map to track items.
This is a more natural data structure and
removes the need for `get_task_index`.
2020-04-08 16:01:54 -04:00
Steve Howell b5e6d872e6 todo widget: Rename function to name_in_use().
The name here is a bit more precise, as we're
not checking whether a task exists so much
as whether just a particular name is in use.

We also move the function out of the `check_task`
layer, which feels a bit overkill in terms
of nesting (plus, we're gonna remove the other
function inside of `check_task` soon).
2020-04-08 16:01:54 -04:00
Steve Howell 4eafaf1302 todo widget: Sort items alphabetically.
We still keep pending tasks above unfinished
tasks, but otherwise the sort is alphabetic.
2020-04-08 16:01:54 -04:00
Steve Howell 8c73375f10 todo widget: Avoid completed/pending complexity.
We now only compute these two sublists when we
need them, rather than having to splice and
unshift them every time.
2020-04-08 16:01:54 -04:00
majordwarf 8ea3bfb927 todo_list: Fix list item indexing in race condition.
The todo_widget was using the using a counter to store the key value of
every task. This would cause assiging multiple tasks the same key value
in a race condition. To avoid this we make "sender_id" a part of the key
along with the counter.

Also the `key` now not being a integer value, we can't use it to find the
index of the task using it. Thus, a function is made that will find the
index of task whose key is sent by the user to strike.
2020-04-08 06:56:21 -04:00
majordwarf 68dcdcd28e todo_list: Add task description and index numbers.
The user can pass description along with the task name by splitting the input string with hyphen.

Eg: Task Title - Task Description
todo_list: Add index numbers to task.
2020-03-12 08:02:06 -04:00
Anders Kaseorg 70ff164f89 js: Convert _.any(a, …), _.some(a, …) to a.some(…).
And convert the corresponding function expressions to arrow style
while we’re here.

Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-10 14:08:12 -08:00
Anders Kaseorg 02511bff1c js: Automatically convert _.each to for…of.
This commit was automatically generated by the following script,
followed by lint --fix and a few small manual lint-related cleanups.

import * as babelParser from "recast/parsers/babel";
import * as recast from "recast";
import * as tsParser from "recast/parsers/typescript";
import { builders as b, namedTypes as n } from "ast-types";
import { Context } from "ast-types/lib/path-visitor";
import K from "ast-types/gen/kinds";
import { NodePath } from "ast-types/lib/node-path";
import assert from "assert";
import fs from "fs";
import path from "path";
import process from "process";

const checkExpression = (node: n.Node): node is K.ExpressionKind =>
  n.Expression.check(node);
const checkStatement = (node: n.Node): node is K.StatementKind =>
  n.Statement.check(node);

for (const file of process.argv.slice(2)) {
  console.log("Parsing", file);
  const ast = recast.parse(fs.readFileSync(file, { encoding: "utf8" }), {
    parser: path.extname(file) === ".ts" ? tsParser : babelParser,
  });
  let changed = false;
  let inLoop = false;
  let replaceReturn = false;

  const visitLoop = (...args: string[]) =>
    function(this: Context, path: NodePath) {
      for (const arg of args) {
        this.visit(path.get(arg));
      }
      const old = { inLoop };
      inLoop = true;
      this.visit(path.get("body"));
      inLoop = old.inLoop;
      return false;
    };

  recast.visit(ast, {
    visitDoWhileStatement: visitLoop("test"),

    visitExpressionStatement(path) {
      const { expression, comments } = path.node;
      let valueOnly;
      if (
        n.CallExpression.check(expression) &&
        n.MemberExpression.check(expression.callee) &&
        !expression.callee.computed &&
        n.Identifier.check(expression.callee.object) &&
        expression.callee.object.name === "_" &&
        n.Identifier.check(expression.callee.property) &&
        ["each", "forEach"].includes(expression.callee.property.name) &&
        [2, 3].includes(expression.arguments.length) &&
        checkExpression(expression.arguments[0]) &&
        (n.FunctionExpression.check(expression.arguments[1]) ||
          n.ArrowFunctionExpression.check(expression.arguments[1])) &&
        [1, 2].includes(expression.arguments[1].params.length) &&
        n.Identifier.check(expression.arguments[1].params[0]) &&
        ((valueOnly = expression.arguments[1].params[1] === undefined) ||
          n.Identifier.check(expression.arguments[1].params[1])) &&
        (expression.arguments[2] === undefined ||
          n.ThisExpression.check(expression.arguments[2]))
      ) {
        const old = { inLoop, replaceReturn };
        inLoop = false;
        replaceReturn = true;
        this.visit(
          path
            .get("expression")
            .get("arguments")
            .get(1)
            .get("body")
        );
        inLoop = old.inLoop;
        replaceReturn = old.replaceReturn;

        const [right, { body, params }] = expression.arguments;
        const loop = b.forOfStatement(
          b.variableDeclaration("let", [
            b.variableDeclarator(
              valueOnly ? params[0] : b.arrayPattern([params[1], params[0]])
            ),
          ]),
          valueOnly
            ? right
            : b.callExpression(
                b.memberExpression(right, b.identifier("entries")),
                []
              ),
          checkStatement(body) ? body : b.expressionStatement(body)
        );
        loop.comments = comments;
        path.replace(loop);
        changed = true;
      }
      this.traverse(path);
    },

    visitForStatement: visitLoop("init", "test", "update"),

    visitForInStatement: visitLoop("left", "right"),

    visitForOfStatement: visitLoop("left", "right"),

    visitFunction(path) {
      this.visit(path.get("params"));
      const old = { replaceReturn };
      replaceReturn = false;
      this.visit(path.get("body"));
      replaceReturn = old.replaceReturn;
      return false;
    },

    visitReturnStatement(path) {
      if (replaceReturn) {
        assert(!inLoop); // could use labeled continue if this ever fires
        const { argument, comments } = path.node;
        if (argument === null) {
          const s = b.continueStatement();
          s.comments = comments;
          path.replace(s);
        } else {
          const s = b.expressionStatement(argument);
          s.comments = comments;
          path.replace(s, b.continueStatement());
        }
        return false;
      }
      this.traverse(path);
    },

    visitWhileStatement: visitLoop("test"),
  });

  if (changed) {
    console.log("Writing", file);
    fs.writeFileSync(file, recast.print(ast).code, { encoding: "utf8" });
  }
}

Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-07 14:09:47 -08:00
Anders Kaseorg 28f3dfa284 js: Automatically convert var to let and const in most files.
This commit was originally automatically generated using `tools/lint
--only=eslint --fix`.  It was then modified by tabbott to contain only
changes to a set of files that are unlikely to result in significant
merge conflicts with any open pull request, excluding about 20 files.
His plan is to merge the remaining changes with more precise care,
potentially involving merging parts of conflicting pull requests
before running the `eslint --fix` operation.

Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2019-11-03 12:42:39 -08:00
Anders Kaseorg d17b577d0c js: Purge useless IIFEs.
With webpack, variables declared in each file are already file-local
(Global variables need to be explicitly exported), so these IIFEs are
no longer needed.

Signed-off-by: Anders Kaseorg <andersk@mit.edu>
2019-10-25 13:51:21 -07:00
Anders Kaseorg db0b33842c templates: Replace templates.render with require calls.
This removes an unnecessary layer of indirection and allows webpack to
catch filename mistakes.

Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2019-07-12 21:11:14 -07:00
Anders Kaseorg 3c3471b720 templates: Rename *.handlebars ↦ *.hbs and - ↦ _.
Tweaked by tabbott to avoid accidentally disabling the linter for
handlebars templates.

Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2019-07-12 21:11:03 -07:00
Thomas Ip f6aaf43029 refactor: Use explicit path when referencing handlebars templates. 2019-07-02 16:23:30 -07:00
Steve Howell d8c454b097 todo lists: Make lists sharable.
We no longer restrict who can add tasks or check
them off.

Fixes #10440
2018-12-17 07:40:27 -08:00
Rhea Parekh fe4cad15a4 widgets: Add todo widget. 2018-07-10 11:18:05 +05:30