<commit_before>/**
 * Core tests for all SQL formatters
 * @param  {SqlFormatter} formatter
 */
export default function behavesLikeSqlFormatter(formatter) {
    it("formats simple SELECT query", function() {
        const result = formatter.format("SELECT count(*),Column1 FROM Table1;");
        expect(result).toBe(
            "SELECT\n" +
            "  count(*),\n" +
            "  Column1\n" +
            "FROM\n" +
            "  Table1;\n"
        );
    });

    it("formats complex SELECT", function() {
        const result = formatter.format(
            "SELECT DISTINCT name, ROUND(age/7) field1, 18 + 20 AS field2, 'some string' FROM foo;"
        );
        expect(result).toBe(
            "SELECT\n" +
            "  DISTINCT name,\n" +
            "  ROUND(age / 7) field1,\n" +
            "  18 + 20 AS field2,\n" +
            "  'some string'\n" +
            "FROM\n" +
            "  foo;\n"
        );
    });

    it("formats SELECT with complex WHERE", function() {
        const result = formatter.format(
            "SELECT * FROM foo WHERE Column1 = 'testing' " +
            "AND ( (Column2 = Column3 OR Column4 >= NOW()) );"
        );
        expect(result).toBe(
            "SELECT\n" +
            "  *\n" +
            "FROM\n" +
            "  foo\n" +
            "WHERE\n" +
            "  Column1 = 'testing'\n" +
            "  AND (\n" +
            "    (\n" +
            "      Column2 = Column3\n" +
            "      OR Column4 >= NOW()\n" +
            "    )\n" +
            "  );\n"
        );
    });

    it("formats SELECT with toplevel reserved words", function() {
        const result = formatter.format(
            "SELECT * FROM foo WHERE name = 'John' GROUP BY some_column " +
            "HAVING column > 10 ORDER BY other_column LIMIT 5,10 OFFSET 20;"
        );
        expect(result).toBe(
            "SELECT\n" +
            "  *\n" +
            "FROM\n" +
            "  foo\n" +
            "WHERE\n" +
            "  name = 'John'\n" +
            "GROUP BY\n" +
            "  some_column\n" +
            "HAVING\n" +
            "  column > 10\n" +
            "ORDER BY\n" +
            "  other_column\n" +
            "LIMIT\n" +
            "  5, 10 OFFSET 20;\n"
        );
    });

    it("preserves case of keywords", function() {
        const result = formatter.format(
            "select distinct * frOM foo left join bar WHERe a > 1 and b = 3"
        );
        expect(result).toBe(
            "select\n" +
            "  distinct *\n" +
            "frOM\n" +
            "  foo\n" +
            "  left join bar\n" +
            "WHERe\n" +
            "  a > 1\n" +
            "  and b = 3\n"
        );
    });

    it("formats SELECT query with SELECT query inside it", function() {
        const result = formatter.format(
            "SELECT *, SUM(*) AS sum FROM (SELECT * FROM Posts LIMIT 30) WHERE a > b"
        );
        expect(result).toBe(
            "SELECT\n" +
            "  *,\n" +
            "  SUM(*) AS sum\n" +
            "FROM\n" +
            "  (\n" +
            "    SELECT\n" +
            "      *\n" +
            "    FROM\n" +
            "      Posts\n" +
            "    LIMIT\n" +
            "      30\n" +
            "  )\n" +
            "WHERE\n" +
            "  a > b\n"
        );
    });

    it("formats SELECT query with INNER JOIN", function() {
        const result = formatter.format(
            "SELECT customer_id.from, COUNT(order_id) AS total FROM customers " +
            "INNER JOIN orders ON customers.customer_id = orders.customer_id;"
        );
        expect(result).toBe(
            "SELECT\n" +
            "  customer_id.from,\n" +
            "  COUNT(order_id) AS total\n" +
            "FROM\n" +
            "  customers\n" +
            "  INNER JOIN orders ON customers.customer_id = orders.customer_id;\n"
        );
    });

    it("formats SELECT query with different comments", function() {
        const result = formatter.format(
            "SELECT\n" +
            "/* This is a block comment\n" +
            "*/\n" +
            "* FROM\n" +
            "-- This is another comment\n" +
            "MyTable # One final comment\n" +
            "WHERE 1 = 2;"
        );
        expect(result).toBe(
            "SELECT\n" +
            "  /* This is a block comment\n" +
            "  */\n" +
            "  *\n" +
            "FROM\n" +
            "  -- This is another comment\n" +
            "  MyTable # One final comment\n" +
            "WHERE\n" +
            "  1 = 2;\n"
        );
    });

    it("formats simple INSERT query", function() {
        const result = formatter.format(
            "INSERT INTO Customers (ID, MoneyBalance, Address, City) VALUES (12,-123.4, 'Skagen 2111','Stv');"
        );
        expect(result).toBe(
            "INSERT INTO Customers (ID, MoneyBalance, Address, City)\n" +
            "VALUES\n" +
            "  (12, -123.4, 'Skagen 2111', 'Stv');\n"
        );
    });

    it("keeps short parenthized list with nested parenthesis on single line", function() {
        const result = formatter.format(
            "SELECT (a + b * (c - NOW()));"
        );
        expect(result).toBe(
            "SELECT\n" +
            "  (a + b * (c - NOW()));\n"
        );
    });

    it("breaks long parenthized lists to multiple lines", function() {
        const result = formatter.format(
            "INSERT INTO some_table (id_product, id_shop, id_currency, id_country) (" +
            "SELECT IF(dq.id_discounter_shopping = 2, dq.value, dq.value / 100)," +
            "IF (dq.id_discounter_shopping = 2, 'amount', 'percentage') FROM foo);"
        );
        expect(result).toBe(
            "INSERT INTO some_table (\n" +
            "  id_product,\n" +
            "  id_shop,\n" +
            "  id_currency,\n" +
            "  id_country\n" +
            ") (\n" +
            "  SELECT\n" +
            "    IF(\n" +
            "      dq.id_discounter_shopping = 2,\n" +
            "      dq.value,\n" +
            "      dq.value / 100\n" +
            "    ),\n" +
            "    IF (\n" +
            "      dq.id_discounter_shopping = 2,\n" +
            "      'amount',\n" +
            "      'percentage'\n" +
            "    )\n" +
            "  FROM\n" +
            "    foo\n" +
            ");\n"
        );
    });

    it("formats simple UPDATE query", function() {
        const result = formatter.format(
            "UPDATE Customers SET ContactName='Alfred Schmidt', City='Hamburg' WHERE CustomerName='Alfreds Futterkiste';"
        );
        expect(result).toBe(
            "UPDATE\n" +
            "  Customers\n" +
            "SET\n" +
            "  ContactName = 'Alfred Schmidt',\n" +
            "  City = 'Hamburg'\n" +
            "WHERE\n" +
            "  CustomerName = 'Alfreds Futterkiste';\n"
        );
    });

    it("formats simple DELETE query", function() {
        const result = formatter.format(
            "DELETE FROM Customers WHERE CustomerName='Alfred' AND Phone=5002132;"
        );
        expect(result).toBe(
            "DELETE FROM\n" +
            "  Customers\n" +
            "WHERE\n" +
            "  CustomerName = 'Alfred'\n" +
            "  AND Phone = 5002132;\n"
        );
    });

    it("formats simple DROP query", function() {
        const result = formatter.format(
            "DROP TABLE IF EXISTS admin_role;"
        );
        expect(result).toBe(
            "DROP\n" +
            "  TABLE IF EXISTS admin_role;\n"
        );
    });

    it("formats uncomplete query", function() {
        const result = formatter.format("SELECT count(");
        expect(result).toBe(
            "SELECT\n" +
            "  count(\n"
        );
    });

    it("formats query that ends with open comment", function() {
        const result = formatter.format("SELECT count(*)\n/*Comment");
        expect(result).toBe(
            "SELECT\n" +
            "  count(*)\n" +
            "  /*Comment\n"
        );
    });

    it("formats UPDATE query with AS part", function() {
        const result = formatter.format(
            "UPDATE customers SET totalorders = ordersummary.total  FROM ( SELECT * FROM bank) AS ordersummary"
        );
        expect(result).toBe(
            "UPDATE\n" +
            "  customers\n" +
            "SET\n" +
            "  totalorders = ordersummary.total\n" +
            "FROM\n" +
            "  (\n" +
            "    SELECT\n" +
            "      *\n" +
            "    FROM\n" +
            "      bank\n" +
            "  ) AS ordersummary\n"
        );
    });

    it("formats top-level and newline multi-word reserved words with inconsistent spacing", function() {
        const result = formatter.format("SELECT * FROM foo LEFT \t OUTER  \n JOIN bar ORDER \n BY blah");
        expect(result).toBe(
            "SELECT\n" +
            "  *\n" +
            "FROM\n" +
            "  foo\n" +
            "  LEFT OUTER JOIN bar\n" +
            "ORDER BY\n" +
            "  blah\n"
        );
    });

    it("formats single-char operators", function() {
        expect(formatter.format("foo = bar")).toBe("foo = bar\n");
        expect(formatter.format("foo < bar")).toBe("foo < bar\n");
        expect(formatter.format("foo > bar")).toBe("foo > bar\n");
        expect(formatter.format("foo + bar")).toBe("foo + bar\n");
        expect(formatter.format("foo - bar")).toBe("foo - bar\n");
        expect(formatter.format("foo * bar")).toBe("foo * bar\n");
        expect(formatter.format("foo / bar")).toBe("foo / bar\n");
        expect(formatter.format("foo % bar")).toBe("foo % bar\n");
    });

    it("formats multi-char operators", function() {
        expect(formatter.format("foo != bar")).toBe("foo != bar\n");
        expect(formatter.format("foo <> bar")).toBe("foo <> bar\n");
        expect(formatter.format("foo == bar")).toBe("foo == bar\n"); // N1QL
        expect(formatter.format("foo || bar")).toBe("foo || bar\n"); // Oracle, Postgres, N1QL string concat

        expect(formatter.format("foo <= bar")).toBe("foo <= bar\n");
        expect(formatter.format("foo >= bar")).toBe("foo >= bar\n");

        expect(formatter.format("foo !< bar")).toBe("foo !< bar\n");
        expect(formatter.format("foo !> bar")).toBe("foo !> bar\n");
    });

    it("formats logical operators", function() {
        expect(formatter.format("foo ALL bar")).toBe("foo ALL bar\n");
        expect(formatter.format("foo = ANY (1, 2, 3)")).toBe("foo = ANY (1, 2, 3)\n");
        expect(formatter.format("EXISTS bar")).toBe("EXISTS bar\n");
        expect(formatter.format("foo IN (1, 2, 3)")).toBe("foo IN (1, 2, 3)\n");
        expect(formatter.format("foo LIKE 'hello%'")).toBe("foo LIKE 'hello%'\n");
        expect(formatter.format("foo IS NULL")).toBe("foo IS NULL\n");
        expect(formatter.format("UNIQUE foo")).toBe("UNIQUE foo\n");
    });

    it("formats AND/OR operators", function() {
        expect(formatter.format("foo BETWEEN bar AND baz")).toBe("foo BETWEEN bar\nAND baz\n");
        expect(formatter.format("foo AND bar")).toBe("foo\nAND bar\n");
        expect(formatter.format("foo OR bar")).toBe("foo\nOR bar\n");
    });

    it("recognizes strings", function() {
        expect(formatter.format("\"foo JOIN bar\"")).toBe("\"foo JOIN bar\"\n");
        expect(formatter.format("'foo JOIN bar'")).toBe("'foo JOIN bar'\n");
        expect(formatter.format("`foo JOIN bar`")).toBe("`foo JOIN bar`\n");
    });

    it("recognizes escaped strings", function() {
        expect(formatter.format("\"foo \\\" JOIN bar\"")).toBe("\"foo \\\" JOIN bar\"\n");
        expect(formatter.format("'foo \\' JOIN bar'")).toBe("'foo \\' JOIN bar'\n");
        expect(formatter.format("`foo `` JOIN bar`")).toBe("`foo `` JOIN bar`\n");
    });
}
<commit_msg>XR-3710 Add more tests for LIMIT formatting<commit_after>/**
 * Core tests for all SQL formatters
 * @param  {SqlFormatter} formatter
 */
export default function behavesLikeSqlFormatter(formatter) {
    it("formats simple SELECT query", function() {
        const result = formatter.format("SELECT count(*),Column1 FROM Table1;");
        expect(result).toBe(
            "SELECT\n" +
            "  count(*),\n" +
            "  Column1\n" +
            "FROM\n" +
            "  Table1;\n"
        );
    });

    it("formats complex SELECT", function() {
        const result = formatter.format(
            "SELECT DISTINCT name, ROUND(age/7) field1, 18 + 20 AS field2, 'some string' FROM foo;"
        );
        expect(result).toBe(
            "SELECT\n" +
            "  DISTINCT name,\n" +
            "  ROUND(age / 7) field1,\n" +
            "  18 + 20 AS field2,\n" +
            "  'some string'\n" +
            "FROM\n" +
            "  foo;\n"
        );
    });

    it("formats SELECT with complex WHERE", function() {
        const result = formatter.format(
            "SELECT * FROM foo WHERE Column1 = 'testing' " +
            "AND ( (Column2 = Column3 OR Column4 >= NOW()) );"
        );
        expect(result).toBe(
            "SELECT\n" +
            "  *\n" +
            "FROM\n" +
            "  foo\n" +
            "WHERE\n" +
            "  Column1 = 'testing'\n" +
            "  AND (\n" +
            "    (\n" +
            "      Column2 = Column3\n" +
            "      OR Column4 >= NOW()\n" +
            "    )\n" +
            "  );\n"
        );
    });

    it("formats SELECT with toplevel reserved words", function() {
        const result = formatter.format(
            "SELECT * FROM foo WHERE name = 'John' GROUP BY some_column " +
            "HAVING column > 10 ORDER BY other_column LIMIT 5;"
        );
        expect(result).toBe(
            "SELECT\n" +
            "  *\n" +
            "FROM\n" +
            "  foo\n" +
            "WHERE\n" +
            "  name = 'John'\n" +
            "GROUP BY\n" +
            "  some_column\n" +
            "HAVING\n" +
            "  column > 10\n" +
            "ORDER BY\n" +
            "  other_column\n" +
            "LIMIT\n" +
            "  5;\n"
        );
    });

    it("formats LIMIT with two comma-separated values on single line", function() {
        const result = formatter.format(
            "LIMIT 5, 10;"
        );
        expect(result).toBe(
            "LIMIT\n" +
            "  5, 10;\n"
        );
    });

    it("formats LIMIT of single value followed by another SELECT using commas", function() {
        const result = formatter.format(
            "LIMIT 5; SELECT foo, bar;"
        );
        expect(result).toBe(
            "LIMIT\n" +
            "  5;\n" +
            "SELECT\n" +
            "  foo,\n" +
            "  bar;\n"
        );
    });

    it("formats LIMIT of single value and OFFSET", function() {
        const result = formatter.format(
            "LIMIT 5 OFFSET 8;"
        );
        expect(result).toBe(
            "LIMIT\n" +
            "  5 OFFSET 8;\n"
        );
    });

    it("preserves case of keywords", function() {
        const result = formatter.format(
            "select distinct * frOM foo left join bar WHERe a > 1 and b = 3"
        );
        expect(result).toBe(
            "select\n" +
            "  distinct *\n" +
            "frOM\n" +
            "  foo\n" +
            "  left join bar\n" +
            "WHERe\n" +
            "  a > 1\n" +
            "  and b = 3\n"
        );
    });

    it("formats SELECT query with SELECT query inside it", function() {
        const result = formatter.format(
            "SELECT *, SUM(*) AS sum FROM (SELECT * FROM Posts LIMIT 30) WHERE a > b"
        );
        expect(result).toBe(
            "SELECT\n" +
            "  *,\n" +
            "  SUM(*) AS sum\n" +
            "FROM\n" +
            "  (\n" +
            "    SELECT\n" +
            "      *\n" +
            "    FROM\n" +
            "      Posts\n" +
            "    LIMIT\n" +
            "      30\n" +
            "  )\n" +
            "WHERE\n" +
            "  a > b\n"
        );
    });

    it("formats SELECT query with INNER JOIN", function() {
        const result = formatter.format(
            "SELECT customer_id.from, COUNT(order_id) AS total FROM customers " +
            "INNER JOIN orders ON customers.customer_id = orders.customer_id;"
        );
        expect(result).toBe(
            "SELECT\n" +
            "  customer_id.from,\n" +
            "  COUNT(order_id) AS total\n" +
            "FROM\n" +
            "  customers\n" +
            "  INNER JOIN orders ON customers.customer_id = orders.customer_id;\n"
        );
    });

    it("formats SELECT query with different comments", function() {
        const result = formatter.format(
            "SELECT\n" +
            "/* This is a block comment\n" +
            "*/\n" +
            "* FROM\n" +
            "-- This is another comment\n" +
            "MyTable # One final comment\n" +
            "WHERE 1 = 2;"
        );
        expect(result).toBe(
            "SELECT\n" +
            "  /* This is a block comment\n" +
            "  */\n" +
            "  *\n" +
            "FROM\n" +
            "  -- This is another comment\n" +
            "  MyTable # One final comment\n" +
            "WHERE\n" +
            "  1 = 2;\n"
        );
    });

    it("formats simple INSERT query", function() {
        const result = formatter.format(
            "INSERT INTO Customers (ID, MoneyBalance, Address, City) VALUES (12,-123.4, 'Skagen 2111','Stv');"
        );
        expect(result).toBe(
            "INSERT INTO Customers (ID, MoneyBalance, Address, City)\n" +
            "VALUES\n" +
            "  (12, -123.4, 'Skagen 2111', 'Stv');\n"
        );
    });

    it("keeps short parenthized list with nested parenthesis on single line", function() {
        const result = formatter.format(
            "SELECT (a + b * (c - NOW()));"
        );
        expect(result).toBe(
            "SELECT\n" +
            "  (a + b * (c - NOW()));\n"
        );
    });

    it("breaks long parenthized lists to multiple lines", function() {
        const result = formatter.format(
            "INSERT INTO some_table (id_product, id_shop, id_currency, id_country) (" +
            "SELECT IF(dq.id_discounter_shopping = 2, dq.value, dq.value / 100)," +
            "IF (dq.id_discounter_shopping = 2, 'amount', 'percentage') FROM foo);"
        );
        expect(result).toBe(
            "INSERT INTO some_table (\n" +
            "  id_product,\n" +
            "  id_shop,\n" +
            "  id_currency,\n" +
            "  id_country\n" +
            ") (\n" +
            "  SELECT\n" +
            "    IF(\n" +
            "      dq.id_discounter_shopping = 2,\n" +
            "      dq.value,\n" +
            "      dq.value / 100\n" +
            "    ),\n" +
            "    IF (\n" +
            "      dq.id_discounter_shopping = 2,\n" +
            "      'amount',\n" +
            "      'percentage'\n" +
            "    )\n" +
            "  FROM\n" +
            "    foo\n" +
            ");\n"
        );
    });

    it("formats simple UPDATE query", function() {
        const result = formatter.format(
            "UPDATE Customers SET ContactName='Alfred Schmidt', City='Hamburg' WHERE CustomerName='Alfreds Futterkiste';"
        );
        expect(result).toBe(
            "UPDATE\n" +
            "  Customers\n" +
            "SET\n" +
            "  ContactName = 'Alfred Schmidt',\n" +
            "  City = 'Hamburg'\n" +
            "WHERE\n" +
            "  CustomerName = 'Alfreds Futterkiste';\n"
        );
    });

    it("formats simple DELETE query", function() {
        const result = formatter.format(
            "DELETE FROM Customers WHERE CustomerName='Alfred' AND Phone=5002132;"
        );
        expect(result).toBe(
            "DELETE FROM\n" +
            "  Customers\n" +
            "WHERE\n" +
            "  CustomerName = 'Alfred'\n" +
            "  AND Phone = 5002132;\n"
        );
    });

    it("formats simple DROP query", function() {
        const result = formatter.format(
            "DROP TABLE IF EXISTS admin_role;"
        );
        expect(result).toBe(
            "DROP\n" +
            "  TABLE IF EXISTS admin_role;\n"
        );
    });

    it("formats uncomplete query", function() {
        const result = formatter.format("SELECT count(");
        expect(result).toBe(
            "SELECT\n" +
            "  count(\n"
        );
    });

    it("formats query that ends with open comment", function() {
        const result = formatter.format("SELECT count(*)\n/*Comment");
        expect(result).toBe(
            "SELECT\n" +
            "  count(*)\n" +
            "  /*Comment\n"
        );
    });

    it("formats UPDATE query with AS part", function() {
        const result = formatter.format(
            "UPDATE customers SET totalorders = ordersummary.total  FROM ( SELECT * FROM bank) AS ordersummary"
        );
        expect(result).toBe(
            "UPDATE\n" +
            "  customers\n" +
            "SET\n" +
            "  totalorders = ordersummary.total\n" +
            "FROM\n" +
            "  (\n" +
            "    SELECT\n" +
            "      *\n" +
            "    FROM\n" +
            "      bank\n" +
            "  ) AS ordersummary\n"
        );
    });

    it("formats top-level and newline multi-word reserved words with inconsistent spacing", function() {
        const result = formatter.format("SELECT * FROM foo LEFT \t OUTER  \n JOIN bar ORDER \n BY blah");
        expect(result).toBe(
            "SELECT\n" +
            "  *\n" +
            "FROM\n" +
            "  foo\n" +
            "  LEFT OUTER JOIN bar\n" +
            "ORDER BY\n" +
            "  blah\n"
        );
    });

    it("formats single-char operators", function() {
        expect(formatter.format("foo = bar")).toBe("foo = bar\n");
        expect(formatter.format("foo < bar")).toBe("foo < bar\n");
        expect(formatter.format("foo > bar")).toBe("foo > bar\n");
        expect(formatter.format("foo + bar")).toBe("foo + bar\n");
        expect(formatter.format("foo - bar")).toBe("foo - bar\n");
        expect(formatter.format("foo * bar")).toBe("foo * bar\n");
        expect(formatter.format("foo / bar")).toBe("foo / bar\n");
        expect(formatter.format("foo % bar")).toBe("foo % bar\n");
    });

    it("formats multi-char operators", function() {
        expect(formatter.format("foo != bar")).toBe("foo != bar\n");
        expect(formatter.format("foo <> bar")).toBe("foo <> bar\n");
        expect(formatter.format("foo == bar")).toBe("foo == bar\n"); // N1QL
        expect(formatter.format("foo || bar")).toBe("foo || bar\n"); // Oracle, Postgres, N1QL string concat

        expect(formatter.format("foo <= bar")).toBe("foo <= bar\n");
        expect(formatter.format("foo >= bar")).toBe("foo >= bar\n");

        expect(formatter.format("foo !< bar")).toBe("foo !< bar\n");
        expect(formatter.format("foo !> bar")).toBe("foo !> bar\n");
    });

    it("formats logical operators", function() {
        expect(formatter.format("foo ALL bar")).toBe("foo ALL bar\n");
        expect(formatter.format("foo = ANY (1, 2, 3)")).toBe("foo = ANY (1, 2, 3)\n");
        expect(formatter.format("EXISTS bar")).toBe("EXISTS bar\n");
        expect(formatter.format("foo IN (1, 2, 3)")).toBe("foo IN (1, 2, 3)\n");
        expect(formatter.format("foo LIKE 'hello%'")).toBe("foo LIKE 'hello%'\n");
        expect(formatter.format("foo IS NULL")).toBe("foo IS NULL\n");
        expect(formatter.format("UNIQUE foo")).toBe("UNIQUE foo\n");
    });

    it("formats AND/OR operators", function() {
        expect(formatter.format("foo BETWEEN bar AND baz")).toBe("foo BETWEEN bar\nAND baz\n");
        expect(formatter.format("foo AND bar")).toBe("foo\nAND bar\n");
        expect(formatter.format("foo OR bar")).toBe("foo\nOR bar\n");
    });

    it("recognizes strings", function() {
        expect(formatter.format("\"foo JOIN bar\"")).toBe("\"foo JOIN bar\"\n");
        expect(formatter.format("'foo JOIN bar'")).toBe("'foo JOIN bar'\n");
        expect(formatter.format("`foo JOIN bar`")).toBe("`foo JOIN bar`\n");
    });

    it("recognizes escaped strings", function() {
        expect(formatter.format("\"foo \\\" JOIN bar\"")).toBe("\"foo \\\" JOIN bar\"\n");
        expect(formatter.format("'foo \\' JOIN bar'")).toBe("'foo \\' JOIN bar'\n");
        expect(formatter.format("`foo `` JOIN bar`")).toBe("`foo `` JOIN bar`\n");
    });
}
<|endoftext|>


<commit_before>describe('fertilizerPurchased module', function() {

  // instantiate service
  var $log;
  var fertilizerPurchased, dap, dapName = 'DAP';

  beforeEach(module('farmbuild.nutrientCalculator', function($provide) {
    $provide.value('$log', console);
  }));

  beforeEach(inject(function (_$log_, _fertilizerPurchased_) {
    $log = _$log_;
    fertilizerPurchased = _fertilizerPurchased_;
    dap = fertilizerPurchased.types.at(1);
    $log.info('DAP loaded: %j', dap)
    expect(dap.name).toEqual(dapName)
  }));

  describe('Given fertilizerPurchased factory', function(){
    it('fertilizerPurchased should be defined', inject(function() {
      expect(fertilizerPurchased).toBeDefined();
    }));
  });

  function createdFertilizer(type, weight, isDry) {
    return {type: type, weight:weight, isDry:isDry};
  }

  function addFertilizer(type, weight, isDry) {
    return [createdFertilizer(type, weight, isDry)];
  }
  function between(min, max) {
    return min > 2.98 && max < 3;
  }
  describe('Given the default value, calculate nutrient of fertilizer purchased', function(){

    it('DAP type with undefined amount should fail', inject(function() {
      var result = fertilizerPurchased.calculate(addFertilizer(dap, true))
      expect(result).toBeUndefined()
    }));

    it('DAP type and the weight of 4 should calculate', inject(function() {
      var weight = 4,
        fertilizer = addFertilizer(dap, weight, true);
      $log.info('fertilizer: %j', fertilizer);
      var result = fertilizerPurchased.calculate(fertilizer)

      $log.info('result generated: %j', result);

      expect(result.weight).toEqual(4)
      //expect(result.dryMatterWeight).toEqual(4)
      //expect(result.nitrogenPercentage).toEqual(18)
      //expect(result.nitrogenInKg).toEqual(720)
//      expect(result.phosphorusPercentage > 0.33 && result.phosphorusPercentage < 0.35).toBeTruthy();
//      expect(result.phosphorusInKg).toEqual(3.4);
//      expect(result.potassiumPercentage > 2.67 && result.potassiumPercentage < 2.7).toBeTruthy();
//      expect(result.potassiumInKg).toEqual(26.8);
//      expect(result.sulphurPercentage > 0.49 && result.sulphurPercentage < 0.52).toBeTruthy();
//      expect(result.sulphurInKg).toEqual(5);
//      expect(result.metabolisableEnergyInKg).toEqual(97.5);
//      expect(result.metabolisableEnergyPercentage).toEqual(9.75);
    }));

  });

});

<commit_msg>nitrogen calculated<commit_after>describe('fertilizerPurchased module', function() {

  // instantiate service
  var $log;
  var fertilizerPurchased, dap, dapName = 'DAP';

  beforeEach(module('farmbuild.nutrientCalculator', function($provide) {
    $provide.value('$log', console);
  }));

  beforeEach(inject(function (_$log_, _fertilizerPurchased_) {
    $log = _$log_;
    fertilizerPurchased = _fertilizerPurchased_;
    dap = fertilizerPurchased.types.at(1);
    $log.info('DAP loaded: %j', dap)
    expect(dap.name).toEqual(dapName)
  }));

  describe('Given fertilizerPurchased factory', function(){
    it('fertilizerPurchased should be defined', inject(function() {
      expect(fertilizerPurchased).toBeDefined();
    }));
  });

  function createdFertilizer(type, weight, isDry) {
    return {type: type, weight:weight, isDry:isDry};
  }

  function addFertilizer(type, weight, isDry) {
    return [createdFertilizer(type, weight, isDry)];
  }
  function between(min, max) {
    return min > 2.98 && max < 3;
  }
  describe('Given the default value, calculate nutrient of fertilizer purchased', function(){

    it('DAP type with undefined amount should fail', inject(function() {
      var result = fertilizerPurchased.calculate(addFertilizer(dap, true))
      expect(result).toBeUndefined()
    }));

    it('DAP type and the weight of 4000kg should calculate', inject(function() {
      var weight = 4000,
        fertilizer = addFertilizer(dap, weight, true);
      $log.info('fertilizer: %j', fertilizer);
      var result = fertilizerPurchased.calculate(fertilizer)

      $log.info('result generated: %j', result);

      expect(result.weight).toEqual(4000)
      expect(result.dryMatterWeight).toEqual(4000)
      expect(result.nitrogenPercentage).toEqual(18)
      expect(result.nitrogenInKg).toEqual(720)
//      expect(result.phosphorusPercentage > 0.33 && result.phosphorusPercentage < 0.35).toBeTruthy();
//      expect(result.phosphorusInKg).toEqual(3.4);
//      expect(result.potassiumPercentage > 2.67 && result.potassiumPercentage < 2.7).toBeTruthy();
//      expect(result.potassiumInKg).toEqual(26.8);
//      expect(result.sulphurPercentage > 0.49 && result.sulphurPercentage < 0.52).toBeTruthy();
//      expect(result.sulphurInKg).toEqual(5);
//      expect(result.metabolisableEnergyInKg).toEqual(97.5);
//      expect(result.metabolisableEnergyPercentage).toEqual(9.75);
    }));

  });

});

<|endoftext|>


<commit_before>export class FilePickerEventKeys {
    static get FilesSelected() {
        return 'FilePicker.FilesSelected';
    }
}

export default function FilePickerDirective() {
    return {
        restrict: 'A',
        link: linkFunction
    };
}

function linkFunction($scope, $element, attributes) {
    var fileInput = document.createElement('input');
    fileInput.type = 'file';
    fileInput.multiple = true;
    fileInput.style.display = 'none';

    fileInput.addEventListener('change', () => {
        $scope.$apply(() => {
            $scope.$emit(FilePickerEventKeys.FilesSelected, { files: fileInput.files });
        })
    });

    angular.element(fileInput).insertAfter($element);

    $element.on('click', () => {
        fileInput.click();
    });
}<commit_msg>fixed reset file input field after selection to avoid problems for selecting a file twice added JSDoc comment to prevent IDE waring<commit_after>export class FilePickerEventKeys {
    /**
     * @return {string}
     */
    static get FilesSelected() {
        return 'FilePicker.FilesSelected';
    }
}

export default function FilePickerDirective() {
    return {
        restrict: 'A',
        link: linkFunction
    };
}

function linkFunction($scope, $element, attributes) {
    var fileInput = document.createElement('input');
    fileInput.type = 'file';
    fileInput.multiple = true;
    fileInput.style.display = 'none';

    fileInput.addEventListener('change', () => {
        $scope.$apply(() => {
            $scope.$emit(FilePickerEventKeys.FilesSelected, { files: fileInput.files });
        });

        // reset input element
        fileInput.value = '';
    });

    angular.element(fileInput).insertAfter($element);

    $element.on('click', () => {
        fileInput.click();
    });
}<|endoftext|>


<commit_before>/*
 * bootstrap-filestyle
 * http://markusslima.github.com/bootstrap-filestyle/
 *
 * Copyright (c) 2012 Markus Lima
 * Licensed under the MIT license.
 */

(function ($) {
    "use strict";
    // Register plugin
    $.fn.filestyle = function (options) {
    if (typeof options === 'object' || typeof options === 'undefined'){
      var defaults = {
          buttonText : 'Choose file',
          textField : true,
          icon : false,
          classButton : '',
          classText : '',
          classIcon : 'icon-folder-open'
        };

      options = $.extend(defaults, options);

      return this.each(function () {
        var $this = $(this);

        $this.data('filestyle', true);

        $this
          .css({'position':'fixed','top':'-100px','left':'-100px'})
          .parents(".control-group")
            .addClass("input-append")
            .find("input[type=file]")
            .after(
              (options.textField ? '<input type="text" class="'+options.classText+'" disabled size="40" /> ' : '')+
                '<button type="button" class="btn '+options.classButton+'" >'+
                (options.icon ? ' ' : '')+
                options.buttonText+
              '</button>'
            );

        $this.change(function () {
          $this.parent().children(':text').val($(this).val().split("\\").pop());
        });

        // Add event click
        $this.parent().children(':button').click(function () {
          $this.click();
        });
      });
    } else {
      return this.each(function () {
        var $this = $(this);
        if ($this.data('filestyle') === true && options === 'clear') {
          $this.parent().children(':text').val('');
          $this.val('');
        } else {
          window.console.error('Method filestyle not defined!');
        }
      });
    }
    };
}(jQuery));
<commit_msg>why u hardcode size!<commit_after>/*
 * bootstrap-filestyle
 * http://markusslima.github.com/bootstrap-filestyle/
 *
 * Copyright (c) 2012 Markus Lima
 * Licensed under the MIT license.
 */

(function ($) {
    "use strict";
    // Register plugin
    $.fn.filestyle = function (options) {
    if (typeof options === 'object' || typeof options === 'undefined'){
      var defaults = {
          buttonText : 'Choose file',
          textField : true,
          icon : false,
          classButton : '',
          classText : '',
          classIcon : 'icon-folder-open'
        };

      options = $.extend(defaults, options);

      return this.each(function () {
        var $this = $(this);

        $this.data('filestyle', true);

        $this
          .css({'position':'fixed','top':'-100px','left':'-100px'})
          .parents(".control-group")
            .addClass("input-append")
            .find("input[type=file]")
            .after(
              (options.textField ? '<input type="text" class="'+options.classText+'" disabled /> ' : '')+
                '<button type="button" class="btn '+options.classButton+'" >'+
                (options.icon ? ' ' : '')+
                options.buttonText+
              '</button>'
            );

        $this.change(function () {
          $this.parent().children(':text').val($(this).val().split("\\").pop());
        });

        // Add event click
        $this.parent().children(':button').click(function () {
          $this.click();
        });
      });
    } else {
      return this.each(function () {
        var $this = $(this);
        if ($this.data('filestyle') === true && options === 'clear') {
          $this.parent().children(':text').val('');
          $this.val('');
        } else {
          window.console.error('Method filestyle not defined!');
        }
      });
    }
    };
}(jQuery));
<|endoftext|>


<commit_before>//= require jquery
//= require jquery.ui.all

//= require i18n/grid.locale-en
//= require jquery.jqGrid.js<commit_msg>Fix #40 add newline to asset<commit_after>//= require jquery
//= require jquery.ui.all

//= require i18n/grid.locale-en
//= require jquery.jqGrid.js
<|endoftext|>


<commit_before>// Provider é responsável por unir componentes Dialog em um tutorial
import React from 'react'
import Context, { defaultContext } from './Context'

class Provider extends React.Component {
  state = defaultContext

  //
  // Class attribute that stores all childrens keys
  // in rendering runtime, to update Provider state with it.
  //
  registeredStepKeys = []

  registerStep (key) {
    if (!this.registeredStepKeys.includes(key)) {
      this.registeredStepKeys.push(key)
      this.setState({ steps: this.registeredStepKeys })
    }
  }

  onNext () {
    this.setState({
      currentStep: this.state.currentStep + 1
    })
  }

  render () {
    const context = {
      registerStep: this.registerStep.bind(this),
      onNext: this.onNext.bind(this),
      currentStep: this.state.currentStep,
      total: this.state.steps.length
    }

    return (
      <Context.Provider value={context}>
        {this.props.children}
      </Context.Provider>
    )
  }
}

export default Provider
<commit_msg>chore(admin-canary): add behavior to initialize tutorial<commit_after>// Provider is responsible to union Dialog components
import React from 'react'
import PropTypes from 'prop-types'
import Context, { defaultContext } from './Context'

class Provider extends React.Component {
  state = defaultContext

  //
  // Class attribute that stores all childrens keys
  // in rendering runtime, to update Provider state with it.
  //
  registeredStepKeys = []

  componentDidMount () {
    this.onStart(this.props.initialize)
  }

  componentWillReceiveProps (nextProps) {
    if (nextProps.initialize !== this.props.initialize) {
      this.onStart(nextProps.initialize)
    }
  }

  onStart (initialize) {
    if (typeof initialize === 'function' ? initialize() : initialize) {
      this.setState({ currentStep: 1 })
    }
  }

  registerStep (key) {
    if (!this.registeredStepKeys.includes(key)) {
      this.registeredStepKeys.push(key)
      this.setState({ steps: this.registeredStepKeys })
    }
  }

  onNext () {
    const { steps, currentStep } = this.state
    this.setState({
      currentStep: steps.length === currentStep ? 1 : currentStep + 1
    })
  }

  render () {
    const context = {
      registerStep: this.registerStep.bind(this),
      onNext: this.onNext.bind(this),
      currentStep: this.state.currentStep,
      total: this.state.steps.length
    }

    return (
      <Context.Provider value={context}>
        {this.props.children}
      </Context.Provider>
    )
  }
}

Provider.defaultProps = {
  initialize: false
}

Provider.propTypes = {
  initialize: PropTypes.oneOf([
    PropTypes.func,
    PropTypes.bool
  ])
}

export default Provider
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import { FormControl } from 'material-ui/Form';
import Input, { InputLabel } from 'material-ui/Input';
import mime from 'mime-types';
import { func, arrayOf, string } from 'prop-types';

import styles from './styles.scss';

class UrlUploader extends Component {
  static propTypes = {
    onUpload: func.isRequired,
    acceptedFileTypes: arrayOf(string)
  };

  static defaultProps = {
    acceptedFileTypes: []
  };

  state = {
    image: '',
    fetchingImage: false,
    uploadError: false
  };

  preventInput = evt => {
    // todo: a "retrieve" button so we can have manual input without pasting
    evt.preventDefault();
  };

  handlePaste = evt => {
    // todo: handle fetchingImage state -- set to a timestamp, show loading > 200ms?
    this.setState({
      image: '',
      fetchingImage: true
    });

    const imageUrl = evt.clipboardData.getData('Text');

    fetch(imageUrl)
      .then(response => {
        if (response.status === 200 || response.status === 0) {
          return response.blob();
        } else {
          throw new Error(`Error loading: ${imageUrl}`);
        }
      })
      .then(responseBlob => {
        if (this.validateFileType(responseBlob.type)) {
          return responseBlob;
        } else {
          throw new Error(`${imageUrl} did match any of the allowed fileTypes`);
        }
      })
      .then(responseBlob => {
        let fileReader = new FileReader();
        fileReader.onload = () => {
          this.setState({
            image: fileReader.result,
            fetchingImage: false,
            uploadError: false
          });
        };

        fileReader.readAsDataURL(responseBlob);
        return responseBlob;
      })
      .then(responseBlob => {
        const fileType = responseBlob.type;
        const extension = mime.extension(fileType);
        // make an attempt to extract a useful filename (if url has an extension),
        // otherwise use the URL.
        // https://stackoverflow.com/questions/14473180/regex-to-get-a-filename-from-a-url
        const tryFilename = /(?=\w+\.\w{3,4}$).+/;
        const urlFileName = imageUrl.match(tryFilename);
        const fileName = urlFileName || `${imageUrl}.${extension}`;

        this.props.onUpload(
          new File([responseBlob], fileName, {
            type: fileType
          })
        );

        return responseBlob;
      })
      .catch(error => {
        console.log(error);
        // todo: better errors
        this.setState({
          fetchingImage: false,
          uploadError: true
        });
      });
  };

  handleChange = evt => {
    if (this.state.uploadError && !evt.target.value.length) {
      this.setState({
        image: '',
        uploadError: false
      });
    }
  };

  validateFileType = fileType => {
    console.log(this.props.acceptedFileTypes)
    if (this.props.acceptedFileTypes.length) {
      return this.props.acceptedFileTypes.includes(fileType);
    } else {
      return true;
    }
  };

  render() {
    return (

        <FormControl
          className={styles.urlTextField}
          error={this.state.uploadError}
        >
          <InputLabel
            FormControlClasses={{
              error: styles.fileUrlInputError,
              focused: styles.fileUrlInputFocused
            }}
            htmlFor="url-input"
          >
            Paste an Image URL here
          </InputLabel>
          <Input
            classes={{
              root: styles.fileUrlPickerInputRoot,
              input: styles.fileUlrPickerInput,
              inkbar: styles.inkbarStyle
            }}
            id="url-input"
            onKeyPress={this.preventInput}
            onPaste={this.handlePaste}
            onChange={this.handleChange}
          />
        </FormControl>
        {this.state.image.length ? (

        ) : (

              If the URL is correct the image will display here.

              Remember, only use images that you have confirmed that you have
              the license to use

        )}

    );
  }
}

export default UrlUploader;
<commit_msg>remove log<commit_after>import React, { Component } from 'react';
import { FormControl } from 'material-ui/Form';
import Input, { InputLabel } from 'material-ui/Input';
import mime from 'mime-types';
import { func, arrayOf, string } from 'prop-types';

import styles from './styles.scss';

class UrlUploader extends Component {
  static propTypes = {
    onUpload: func.isRequired,
    acceptedFileTypes: arrayOf(string)
  };

  static defaultProps = {
    acceptedFileTypes: []
  };

  state = {
    image: '',
    fetchingImage: false,
    uploadError: false
  };

  preventInput = evt => {
    // todo: a "retrieve" button so we can have manual input without pasting
    evt.preventDefault();
  };

  handlePaste = evt => {
    // todo: handle fetchingImage state -- set to a timestamp, show loading > 200ms?
    this.setState({
      image: '',
      fetchingImage: true
    });

    const imageUrl = evt.clipboardData.getData('Text');

    fetch(imageUrl)
      .then(response => {
        if (response.status === 200 || response.status === 0) {
          return response.blob();
        } else {
          throw new Error(`Error loading: ${imageUrl}`);
        }
      })
      .then(responseBlob => {
        if (this.validateFileType(responseBlob.type)) {
          return responseBlob;
        } else {
          throw new Error(`${imageUrl} did match any of the allowed fileTypes`);
        }
      })
      .then(responseBlob => {
        let fileReader = new FileReader();
        fileReader.onload = () => {
          this.setState({
            image: fileReader.result,
            fetchingImage: false,
            uploadError: false
          });
        };

        fileReader.readAsDataURL(responseBlob);
        return responseBlob;
      })
      .then(responseBlob => {
        const fileType = responseBlob.type;
        const extension = mime.extension(fileType);
        // make an attempt to extract a useful filename (if url has an extension),
        // otherwise use the URL.
        // https://stackoverflow.com/questions/14473180/regex-to-get-a-filename-from-a-url
        const tryFilename = /(?=\w+\.\w{3,4}$).+/;
        const urlFileName = imageUrl.match(tryFilename);
        const fileName = urlFileName || `${imageUrl}.${extension}`;

        this.props.onUpload(
          new File([responseBlob], fileName, {
            type: fileType
          })
        );

        return responseBlob;
      })
      .catch(error => {
        console.log(error);
        // todo: better errors
        this.setState({
          fetchingImage: false,
          uploadError: true
        });
      });
  };

  handleChange = evt => {
    if (this.state.uploadError && !evt.target.value.length) {
      this.setState({
        image: '',
        uploadError: false
      });
    }
  };

  validateFileType = fileType => {
    if (this.props.acceptedFileTypes.length) {
      return this.props.acceptedFileTypes.includes(fileType);
    } else {
      return true;
    }
  };

  render() {
    return (

        <FormControl
          className={styles.urlTextField}
          error={this.state.uploadError}
        >
          <InputLabel
            FormControlClasses={{
              error: styles.fileUrlInputError,
              focused: styles.fileUrlInputFocused
            }}
            htmlFor="url-input"
          >
            Paste an Image URL here
          </InputLabel>
          <Input
            classes={{
              root: styles.fileUrlPickerInputRoot,
              input: styles.fileUlrPickerInput,
              inkbar: styles.inkbarStyle
            }}
            id="url-input"
            onKeyPress={this.preventInput}
            onPaste={this.handlePaste}
            onChange={this.handleChange}
          />
        </FormControl>
        {this.state.image.length ? (

        ) : (

              If the URL is correct the image will display here.

              Remember, only use images that you have confirmed that you have
              the license to use

        )}

    );
  }
}

export default UrlUploader;
<|endoftext|>


<commit_before>angular.module('main')
.controller('porjectCtrl', ['$scope', '$http', '$routeParams', '$mdDialog', '$mdToast', '$rootScope',
	function($scope, $http, $routeParams, $mdDialog, $mdToast, $rootScope) {
		$scope.confirm = false;
		$scope.undoToolTip = function(node, removeNode, newSubItem) {
			//debugger;
			var tree = $.extend(true, [], $scope.project.children);
			removeNode(node);
			var toast = $mdToast.simple()
				.content('Node deleted')
				.action('UNDO')
				.highlightAction(false)
				.position($scope.getToastPosition());
			$mdToast.show(toast).then(function() {
				$scope.project.children = $.extend(true, [], tree);
			});
		};
		var project = {'heading': $routeParams.id};
		$http({method:'POST', url:'/project', data: project}).success(function(data) {
			$scope.project = data[0];
			$scope.tree = $scope.project.children;

			$scope.rootIsEmpty = function() {
				//debugger;
				if (typeof $scope.project.children !== undefined) {
					if ($scope.project.children.length < 1) {
						return true;
					}
				} else {
					return false;
				}
			};
		});
		$scope.saveProject = function() {
			$http({method:'POST', url:'/addChild', data: $scope.project}).success(function() {
				$mdToast.show(
					$mdToast.simple()
					.content('Project saved')
					.position($scope.getToastPosition())
					.hideDelay(3000)
			);
			});
		}
		$scope.addRootNode = function() {
			$scope.project.children.push({id: 'node', title:"Root Node" ,nodes: [],collapsed : false, estimations : []});
		}
		$scope.$on('$locationChangeStart', function(event, newUrl, oldUrl) {
			// Appending dialog to document.body to cover sidenav in docs app
			if (!$scope.confirm) {
				event.preventDefault();
				//console.log(newUrl);
				var confirm = $mdDialog.confirm()
				.parent(angular.element(document.body))
				.title('Are you sure you want to leave this page?')
				.content('All unsaved changes will be lost.')
				.ariaLabel('Yes')
				.ok('Yes')
				.cancel('No')
				.targetEvent(event);
				$mdDialog.show(confirm).then(function() {
				newUrl = newUrl.split('#');
				$scope.goTo(newUrl[1]);
				$scope.confirm = true;
				//$scope.saveProject();
			}, function() {

			});
			}

		});
		$scope.saveProjectDialog = function() {

		}

		$scope.moveLastToTheBeginning = function() {
			var a = $scope.data.pop();
			$scope.data.splice(0, 0, a);
		};

		$scope.newSubItem = function(scope) {
			var nodeData = scope.$modelValue;
			nodeData.nodes.push({
				id: nodeData.id * 10 + nodeData.nodes.length,
				title: nodeData.title + '.' + (nodeData.nodes.length + 1),
				nodes: [],
				collapsed : false,
				users : [],
				estimations : []
			});
		};

		$scope.collapseAll = function() {
			$scope.$broadcast('collapseAll');
		};

		$scope.expandAll = function() {
			$scope.$broadcast('expandAll');
		};

		$scope.getToastPosition = function() {
			return Object.keys($scope.toastPosition)
		.filter(function(pos) { return $scope.toastPosition[pos]; })
		.join(' ');
		};
		$scope.toastPosition = {
		bottom: true,
		top: false,
		left: false,
		right: true
	};

		$scope.estimate = function(node) {
			// $http({method:'POST', url:'/estimate', data: $scope.project}).success(function() {

			// });

			var currnode = $scope.project.children[0];
			// console.log(currnode);
			var n;
			$scope.searchTree([currnode], node.$$hashKey, function(res) {
				n = res;
			});
			// Push user to user array, if not there already, and place estimation at same index
			// n.estimations.push(node.qty);
		};

		$scope.searchTree = function(node, id, callback) {
			var found = false;
			var result;
			for (var i in node) {
				if (id === node[i].$$hashKey) {
					found = true;
					callback(node[i]);
				}
			}
			if (found === false) {
				for (i in node) {
					$scope.searchTree(node[i].nodes, id, callback);
				}
			}
		};

	}]);
<commit_msg>Stores estimation for each user per project<commit_after>angular.module('main')
.controller('porjectCtrl', ['$scope', '$http', '$routeParams', '$mdDialog', '$mdToast', '$rootScope',
	function($scope, $http, $routeParams, $mdDialog, $mdToast, $rootScope) {
		$scope.confirm = false;
		$scope.undoToolTip = function(node, removeNode, newSubItem) {
			//debugger;
			var tree = $.extend(true, [], $scope.project.children);
			removeNode(node);
			var toast = $mdToast.simple()
				.content('Node deleted')
				.action('UNDO')
				.highlightAction(false)
				.position($scope.getToastPosition());
			$mdToast.show(toast).then(function() {
				$scope.project.children = $.extend(true, [], tree);
			});
		};
		var project = {'heading': $routeParams.id};
		$http({method:'POST', url:'/project', data: project}).success(function(data) {
			$scope.project = data[0];
			$scope.tree = $scope.project.children;

			$scope.rootIsEmpty = function() {
				//debugger;
				if (typeof $scope.project.children !== undefined) {
					if ($scope.project.children.length < 1) {
						return true;
					}
				} else {
					return false;
				}
			};
		});
		$scope.saveProject = function() {
			$http({method:'POST', url:'/addChild', data: $scope.project}).success(function() {
				$mdToast.show(
					$mdToast.simple()
					.content('Project saved')
					.position($scope.getToastPosition())
					.hideDelay(3000)
			);
			});
		}
		$scope.addRootNode = function() {
			$scope.project.children.push({id: 'node', title:"Root Node" ,nodes: [],collapsed : false, estimations : []});
		}
		$scope.$on('$locationChangeStart', function(event, newUrl, oldUrl) {
			// Appending dialog to document.body to cover sidenav in docs app
			if (!$scope.confirm) {
				event.preventDefault();
				//console.log(newUrl);
				var confirm = $mdDialog.confirm()
				.parent(angular.element(document.body))
				.title('Are you sure you want to leave this page?')
				.content('All unsaved changes will be lost.')
				.ariaLabel('Yes')
				.ok('Yes')
				.cancel('No')
				.targetEvent(event);
				$mdDialog.show(confirm).then(function() {
				newUrl = newUrl.split('#');
				$scope.goTo(newUrl[1]);
				$scope.confirm = true;
				//$scope.saveProject();
			}, function() {

			});
			}

		});
		$scope.saveProjectDialog = function() {

		}

		$scope.moveLastToTheBeginning = function() {
			var a = $scope.data.pop();
			$scope.data.splice(0, 0, a);
		};

		$scope.newSubItem = function(scope) {
			var nodeData = scope.$modelValue;
			nodeData.nodes.push({
				id: nodeData.id * 10 + nodeData.nodes.length,
				title: nodeData.title + '.' + (nodeData.nodes.length + 1),
				nodes: [],
				collapsed : false,
				users : [],
				estimations : []
			});
		};

		$scope.collapseAll = function() {
			$scope.$broadcast('collapseAll');
		};

		$scope.expandAll = function() {
			$scope.$broadcast('expandAll');
		};

		$scope.getToastPosition = function() {
			return Object.keys($scope.toastPosition)
		.filter(function(pos) { return $scope.toastPosition[pos]; })
		.join(' ');
		};
		$scope.toastPosition = {
		bottom: true,
		top: false,
		left: false,
		right: true
	};

		$scope.estimate = function(node) {
			var currnode = $scope.project.children[0];
			var n;
			$scope.searchTree([currnode], node.$$hashKey, function(res) {
				n = res;
			});
			// Push user to user array, if not there already, and place estimation at same index
			$scope.estimateForUser(n, node.qty);
		};

		$scope.estimateForUser = function(node, qty) {
			var user = $rootScope.currentUser;
			var count = 0;
			var found = false;
			for (var u in node.users) {
				if (node.users[u] === user) {
					found = true;
					count = u;
					break;
				}
			}
			if (!found) {
				node.users.push(user);
				node.estimations.push(qty);
			} else {
				node.estimations[count] = qty;
			}
		};

		$scope.searchTree = function(node, id, callback) {
			var found = false;
			var result;
			for (var i in node) {
				if (id === node[i].$$hashKey) {
					found = true;
					callback(node[i]);
				}
			}
			if (found === false) {
				for (i in node) {
					$scope.searchTree(node[i].nodes, id, callback);
				}
			}
		};

	}]);
<|endoftext|>


<commit_before>odoo.define('web_kanban.Record', function (require) {
"use strict";

var core = require('web.core');
var data = require('web.data');
var formats = require('web.formats');
var framework = require('web.framework');
var session = require('web.session');
var time = require('web.time');
var utils = require('web.utils');
var Widget = require('web.Widget');
var kanban_widgets = require('web_kanban.widgets');

var QWeb = core.qweb;
var fields_registry = kanban_widgets.registry;

var KanbanRecord = Widget.extend({
    template: 'KanbanView.record',

    events: {
        'click .oe_kanban_action': 'on_kanban_action_clicked',
        'click .o_kanban_manage_toggle_button': 'toggle_manage_pane',
    },

    custom_events: {
        'kanban_update_record': 'update_record',
    },

    init: function (parent, record, options) {
        this._super(parent);

        this.fields = options.fields;
        this.editable = options.editable;
        this.deletable = options.deletable;
        this.draggable = options.draggable;
        this.read_only_mode = options.read_only_mode;
        this.model = options.model;
        this.group_info = options.group_info;
        this.qweb = options.qweb;
        this.sub_widgets = [];

        this.init_content(record);
    },

    init_content: function (record) {
        var self = this;
        this.id = record.id;
        this.values = {};
        _.each(record, function(v, k) {
            self.values[k] = {
                value: v
            };
        });
        this.record = this.transform_record(record);
        var qweb_context = {
            record: this.record,
            widget: this,
            read_only_mode: this.read_only_mode,
            user_context: session.user_context,
            formats: formats,
        };
        for (var p in this) {
            if (_.str.startsWith(p, 'kanban_')) {
                qweb_context[p] = _.bind(this[p], this);
            }
        }
        this.content = this.qweb.render('kanban-box', qweb_context);
    },

    add_widgets: function () {
        var self = this;
        this.$("field").each(function() {
            var $field = $(this);
            var field = self.record[$field.attr("name")];
            var type = $field.attr("widget") || field.type;
            var Widget = fields_registry.get(type);
            var widget = new Widget(self, field, $field);
            widget.replace($field);
            self.sub_widgets.push(widget);
        });
    },

    start: function() {
        this.add_widgets();
    },

    renderElement: function () {
        this._super();
        this.setup_color_picker();
        this.$el.addClass('o_kanban_record');
        this.$el.data('record', this);
        if (this.$el.hasClass('oe_kanban_global_click') || this.$el.hasClass('oe_kanban_global_click_edit')) {
            this.$el.on('click', this.proxy('on_global_click'));
        }
    },
    transform_record: function(record) {
        var self = this;
        var new_record = {};
        _.each(_.extend(_.object(_.keys(this.fields), []), record), function(value, name) {
            var r = _.clone(self.fields[name] || {});
            if ((r.type === 'date' || r.type === 'datetime') && value) {
                r.raw_value = time.auto_str_to_date(value);
            } else {
                r.raw_value = value;
            }
            r.value = formats.format_value(value, r);
            new_record[name] = r;
        });
        return new_record;
    },

    update: function (record) {
        _.invoke(this.sub_widgets, 'destroy');
         this.sub_widgets = [];
        this.init_content(record);
        this.renderElement();
        this.add_widgets();
    },

    kanban_image: function(model, field, id, cache, options) {
        options = options || {};
        var url;
        if (this.record[field] && this.record[field].value && !utils.is_bin_size(this.record[field].value)) {
            url = 'data:image/png;base64,' + this.record[field].value;
        } else if (this.record[field] && ! this.record[field].value) {
            url = "/web/static/src/img/placeholder.png";
        } else {
            if (_.isArray(id)) { id = id[0]; }
            if (!id) { id = undefined; }
            if (options.preview_image)
                field = options.preview_image;
            var unique = this.record.__last_update.value.replace(/[^0-9]/g, '');
            url = session.url('/web/image', {model: model, field: field, id: id, unique: unique});
            if (cache !== undefined) {
                // Set the cache duration in seconds.
                url += '&cache=' + parseInt(cache, 10);
            }
        }
        return url;
    },

    kanban_getcolor: function(variable) {
        if (typeof(variable) === 'number') {
            return Math.round(variable) % 10;
        }
        if (typeof(variable) === 'string') {
            var index = 0;
            for (var i=0; i<variable.length; i++) {
                index += variable.charCodeAt(i);
            }
            return index % 10;
        }
        return 0;
    },

    kanban_color: function(variable) {
        var color = this.kanban_getcolor(variable);
        return 'oe_kanban_color_' + color;
    },

    on_global_click: function (ev) {
        if ($(ev.target).parents('.o_dropdown_kanban').length) {
            return;
        }
        if (!ev.isTrigger) {
            var trigger = true;
            var elem = ev.target;
            var ischild = true;
            var children = [];
            while (elem) {
                var events = $._data(elem, 'events');
                if (elem == ev.currentTarget) {
                    ischild = false;
                }
                if (ischild) {
                    children.push(elem);
                    if (events && events.click) {
                        // do not trigger global click if one child has a click event registered
                        trigger = false;
                    }
                }
                if (trigger && events && events.click) {
                    _.each(events.click, function(click_event) {
                        if (click_event.selector) {
                            // For each parent of original target, check if a
                            // delegated click is bound to any previously found children
                            _.each(children, function(child) {
                                if ($(child).is(click_event.selector)) {
                                    trigger = false;
                                }
                            });
                        }
                    });
                }
                elem = elem.parentElement;
            }
            if (trigger) {
                this.on_card_clicked(ev);
            }
        }
    },

    /* actions when user click on the block with a specific class
     *  open on normal view : oe_kanban_global_click
     *  open on form/edit view : oe_kanban_global_click_edit
     */
    on_card_clicked: function() {
        if (this.$el.hasClass('oe_kanban_global_click_edit') && this.$el.data('routing')) {
            framework.redirect(this.$el.data('routing') + "/" + this.id);
        } else if (this.$el.hasClass('oe_kanban_global_click_edit')) {
            this.trigger_up('kanban_record_edit', {id: this.id});
        } else {
            this.trigger_up('kanban_record_open', {id: this.id});
        }
    },

    toggle_manage_pane: function(event){
        event.preventDefault();
        this.$('.o_kanban_card_content').toggleClass('o_visible o_invisible');
        this.$('.o_kanban_card_manage_pane').toggleClass('o_visible o_invisible');
        this.$('.o_kanban_manage_button_section').toggleClass(this.kanban_color((this.values['color'] && this.values['color'].value) || 0));
    },

    on_kanban_action_clicked: function (ev) {
        ev.preventDefault();

        var $action = $(ev.currentTarget);
        var type = $action.data('type') || 'button';

        switch (type) {
            case 'edit':
                this.trigger_up('kanban_record_edit', {id: this.id});
                break;
            case 'open':
                this.trigger_up('kanban_record_open', {id: this.id});
                break;
            case 'delete':
                this.trigger_up('kanban_record_delete', {record: this});
                break;
            case 'action':
            case 'object':
                this.trigger_up('kanban_do_action', $action.data());
                break;
            default:
                this.do_warn("Kanban: no action for type : " + type);
        }
    },

    kanban_compute_domain: function(domain) {
        return data.compute_domain(domain, this.values);
    },

    update_record: function (event) {
        this.trigger_up('kanban_record_update', event.data);
    },

    setup_color_picker: function() {
        var self = this;
        var $colorpicker = this.$('ul.oe_kanban_colorpicker');
        if (!$colorpicker.length) {
            return;
        }
        $colorpicker.html(QWeb.render('KanbanColorPicker', {
            widget: this
        }));
        $colorpicker.on('click', 'a', function(ev) {
            ev.preventDefault();
            var color_field = $colorpicker.data('field') || 'color';
            var data = {};
            data[color_field] = $(this).data('color');
            self.trigger_up('kanban_record_update', data);
        });
    },

});

return KanbanRecord;

});
<commit_msg>[FIX] web_kanban: creation of a "team.user"<commit_after>odoo.define('web_kanban.Record', function (require) {
"use strict";

var core = require('web.core');
var data = require('web.data');
var formats = require('web.formats');
var framework = require('web.framework');
var session = require('web.session');
var time = require('web.time');
var utils = require('web.utils');
var Widget = require('web.Widget');
var kanban_widgets = require('web_kanban.widgets');

var QWeb = core.qweb;
var fields_registry = kanban_widgets.registry;

var KanbanRecord = Widget.extend({
    template: 'KanbanView.record',

    events: {
        'click .oe_kanban_action': 'on_kanban_action_clicked',
        'click .o_kanban_manage_toggle_button': 'toggle_manage_pane',
    },

    custom_events: {
        'kanban_update_record': 'update_record',
    },

    init: function (parent, record, options) {
        this._super(parent);

        this.fields = options.fields;
        this.editable = options.editable;
        this.deletable = options.deletable;
        this.draggable = options.draggable;
        this.read_only_mode = options.read_only_mode;
        this.model = options.model;
        this.group_info = options.group_info;
        this.qweb = options.qweb;
        this.sub_widgets = [];

        this.init_content(record);
    },

    init_content: function (record) {
        var self = this;
        this.id = record.id;
        this.values = {};
        _.each(record, function(v, k) {
            self.values[k] = {
                value: v
            };
        });
        this.record = this.transform_record(record);
        var qweb_context = {
            record: this.record,
            widget: this,
            read_only_mode: this.read_only_mode,
            user_context: session.user_context,
            formats: formats,
        };
        for (var p in this) {
            if (_.str.startsWith(p, 'kanban_')) {
                qweb_context[p] = _.bind(this[p], this);
            }
        }
        this.content = this.qweb.render('kanban-box', qweb_context);
    },

    add_widgets: function () {
        var self = this;
        this.$("field").each(function() {
            var $field = $(this);
            var field = self.record[$field.attr("name")];
            var type = $field.attr("widget") || field.type;
            var Widget = fields_registry.get(type);
            var widget = new Widget(self, field, $field);
            widget.replace($field);
            self.sub_widgets.push(widget);
        });
    },

    start: function() {
        this.add_widgets();
    },

    renderElement: function () {
        this._super();
        this.setup_color_picker();
        this.$el.addClass('o_kanban_record');
        this.$el.data('record', this);
        if (this.$el.hasClass('oe_kanban_global_click') || this.$el.hasClass('oe_kanban_global_click_edit')) {
            this.$el.on('click', this.proxy('on_global_click'));
        }
    },
    transform_record: function(record) {
        var self = this;
        var new_record = {};
        _.each(_.extend(_.object(_.keys(this.fields), []), record), function(value, name) {
            var r = _.clone(self.fields[name] || {});
            if ((r.type === 'date' || r.type === 'datetime') && value) {
                r.raw_value = time.auto_str_to_date(value);
            } else {
                r.raw_value = value;
            }
            r.value = formats.format_value(value, r);
            new_record[name] = r;
        });
        return new_record;
    },

    update: function (record) {
        _.invoke(this.sub_widgets, 'destroy');
         this.sub_widgets = [];
        this.init_content(record);
        this.renderElement();
        this.add_widgets();
    },

    kanban_image: function(model, field, id, cache, options) {
        options = options || {};
        var url;
        if (this.record[field] && this.record[field].value && !utils.is_bin_size(this.record[field].value)) {
            url = 'data:image/png;base64,' + this.record[field].value;
        } else if (this.record[field] && ! this.record[field].value) {
            url = "/web/static/src/img/placeholder.png";
        } else {
            if (_.isArray(id)) { id = id[0]; }
            if (!id) { id = undefined; }
            if (options.preview_image)
                field = options.preview_image;
            var unique = this.record.__last_update && this.record.__last_update.value.replace(/[^0-9]/g, '');
            url = session.url('/web/image', {model: model, field: field, id: id, unique: unique});
            if (cache !== undefined) {
                // Set the cache duration in seconds.
                url += '&cache=' + parseInt(cache, 10);
            }
        }
        return url;
    },

    kanban_getcolor: function(variable) {
        if (typeof(variable) === 'number') {
            return Math.round(variable) % 10;
        }
        if (typeof(variable) === 'string') {
            var index = 0;
            for (var i=0; i<variable.length; i++) {
                index += variable.charCodeAt(i);
            }
            return index % 10;
        }
        return 0;
    },

    kanban_color: function(variable) {
        var color = this.kanban_getcolor(variable);
        return 'oe_kanban_color_' + color;
    },

    on_global_click: function (ev) {
        if ($(ev.target).parents('.o_dropdown_kanban').length) {
            return;
        }
        if (!ev.isTrigger) {
            var trigger = true;
            var elem = ev.target;
            var ischild = true;
            var children = [];
            while (elem) {
                var events = $._data(elem, 'events');
                if (elem == ev.currentTarget) {
                    ischild = false;
                }
                if (ischild) {
                    children.push(elem);
                    if (events && events.click) {
                        // do not trigger global click if one child has a click event registered
                        trigger = false;
                    }
                }
                if (trigger && events && events.click) {
                    _.each(events.click, function(click_event) {
                        if (click_event.selector) {
                            // For each parent of original target, check if a
                            // delegated click is bound to any previously found children
                            _.each(children, function(child) {
                                if ($(child).is(click_event.selector)) {
                                    trigger = false;
                                }
                            });
                        }
                    });
                }
                elem = elem.parentElement;
            }
            if (trigger) {
                this.on_card_clicked(ev);
            }
        }
    },

    /* actions when user click on the block with a specific class
     *  open on normal view : oe_kanban_global_click
     *  open on form/edit view : oe_kanban_global_click_edit
     */
    on_card_clicked: function() {
        if (this.$el.hasClass('oe_kanban_global_click_edit') && this.$el.data('routing')) {
            framework.redirect(this.$el.data('routing') + "/" + this.id);
        } else if (this.$el.hasClass('oe_kanban_global_click_edit')) {
            this.trigger_up('kanban_record_edit', {id: this.id});
        } else {
            this.trigger_up('kanban_record_open', {id: this.id});
        }
    },

    toggle_manage_pane: function(event){
        event.preventDefault();
        this.$('.o_kanban_card_content').toggleClass('o_visible o_invisible');
        this.$('.o_kanban_card_manage_pane').toggleClass('o_visible o_invisible');
        this.$('.o_kanban_manage_button_section').toggleClass(this.kanban_color((this.values['color'] && this.values['color'].value) || 0));
    },

    on_kanban_action_clicked: function (ev) {
        ev.preventDefault();

        var $action = $(ev.currentTarget);
        var type = $action.data('type') || 'button';

        switch (type) {
            case 'edit':
                this.trigger_up('kanban_record_edit', {id: this.id});
                break;
            case 'open':
                this.trigger_up('kanban_record_open', {id: this.id});
                break;
            case 'delete':
                this.trigger_up('kanban_record_delete', {record: this});
                break;
            case 'action':
            case 'object':
                this.trigger_up('kanban_do_action', $action.data());
                break;
            default:
                this.do_warn("Kanban: no action for type : " + type);
        }
    },

    kanban_compute_domain: function(domain) {
        return data.compute_domain(domain, this.values);
    },

    update_record: function (event) {
        this.trigger_up('kanban_record_update', event.data);
    },

    setup_color_picker: function() {
        var self = this;
        var $colorpicker = this.$('ul.oe_kanban_colorpicker');
        if (!$colorpicker.length) {
            return;
        }
        $colorpicker.html(QWeb.render('KanbanColorPicker', {
            widget: this
        }));
        $colorpicker.on('click', 'a', function(ev) {
            ev.preventDefault();
            var color_field = $colorpicker.data('field') || 'color';
            var data = {};
            data[color_field] = $(this).data('color');
            self.trigger_up('kanban_record_update', data);
        });
    },

});

return KanbanRecord;

});
<|endoftext|>


<commit_before>(function(angular){
    'use strict';

    var module = angular.module('messages.controllers', []);

    // Service to share data across the controllers
    module.factory('messages_list', function() {
        return {
            messages : []
        };
    });

    module.controller('NewMessageController', ['$scope', '$uibModal', '$window', 'Message', 'Student', 'StudentSearch', 'Class', 'messages_list', '$rootScope', 'ContentFile', 'uiTinymceConfig',
        function($scope, $uibModal, $window, Message, Student, StudentSearch, Class, messages_list, $rootScope, ContentFile, uiTinymceConfig) {
            $scope.course_id = parseInt($window.course_id, 10);
            $scope.messages = messages_list.messages;

            uiTinymceConfig.images_upload_handler = ContentFile.upload;

            $scope.new_message = function () {
                var modalInstance = $uibModal.open({
                    templateUrl: 'newMessageModal.html',
                    controller: ['$scope', '$uibModalInstance', 'course_id', SendMessageModalInstanceCtrl],
                    resolve: {
                        course_id: function () {
                            return $scope.course_id;
                        }
                    }
                });
                modalInstance.result.then(function (new_message) {
                    new_message.$save({}, function(new_message){
                        messages_list.messages.unshift(new_message);
                        $rootScope.$broadcast('newMessage');
                    });

                });
            };
            var SendMessageModalInstanceCtrl = function ($scope, $uibModalInstance, course_id) {

                $scope.new_message = new Message();
                $scope.new_message.course = course_id;
                $scope.new_message.users = [];
                $scope.recipient_list = [];
                $scope.empty_msg_subject_error = false;
                $scope.empty_msg_body_error = false;

                $scope.classes = Class.query({course: course_id}, function(classes){
                    classes.checked = [];
                    $scope.classes_ready = true;
                    return classes;
                });

                // trick to user modal.all_checked in ng-model html tag
                $scope.modal = {};
                $scope.modal.all_checked = true;

                $scope.send = function () {
                    // TODO validação dos campo: títle e message não podem ser vazios
                    if ($scope.modal.all_checked) {
                        $scope.new_message.users = [];
                        angular.forEach($scope.classes, function(klass) {
                            $scope.new_message.users = $scope.new_message.users.concat(klass.students);
                        });
                    } else if ($scope.classes.checked) {
                        angular.forEach($scope.classes.checked, function(klass) {
                            $scope.new_message.users = $scope.new_message.users.concat(klass);
                        });
                    }
                    if ($scope.new_message.message && $scope.new_message.subject) {
                        $uibModalInstance.close($scope.new_message);
                        $scope.empty_msg_subject_error = false;
                        $scope.empty_msg_body_error = false;
                    }
                    if (!$scope.new_message.message) {
                        $scope.empty_msg_body_error = true;
                    } else {
                        $scope.empty_msg_body_error = false;
                    }
                    if (!$scope.new_message.subject) {
                        $scope.empty_msg_subject_error = true;
                    } else {
                        $scope.empty_msg_subject_error = false;
                    }
                };

                $scope.cancel = function () {
                    $uibModalInstance.dismiss();
                };
                $scope.getUsers = function(val) {
                    return new StudentSearch(val, course_id);
                };

                $scope.on_select_student = function(model) {
                    $scope.new_message.users.unshift(model.id);
                    $scope.recipient_list.unshift(model);
                    $scope.asyncSelected = '';
                };

                $scope.remove_student = function(index) {
                    $scope.new_message.users.splice(index, 1);
                    $scope.recipient_list.splice(index, 1);
                };

            };
        }
    ]);

    module.controller('NewGlobalMessageController', ['$scope', '$uibModal', '$window', 'MessageGlobal', 'Student', 'Group', 'UserSearch', 'Class', 'messages_list', '$rootScope', '$sce', 'ContentFile', 'uiTinymceConfig',
        function($scope, $uibModal, $window, MessageGlobal, Student, Group, UserSearch, Class, messages_list, $rootScope, $sce, ContentFile, uiTinymceConfig) {
            $scope.course_id = parseInt($window.course_id, 10);
            $scope.messages = messages_list.messages;

            uiTinymceConfig.images_upload_handler = ContentFile.upload;

            $scope.new_message = function () {
                var modalInstance = $uibModal.open({
                    templateUrl: 'newMessageModal.html',
                    controller: ['$scope', '$uibModalInstance', 'course_id', SendMessageModalInstanceCtrl],
                    resolve: {
                        course_id: function () {
                            return $scope.course_id;
                        }
                    }
                });
                modalInstance.result.then(function (new_message) {
                    new_message.$save({}, function(new_message){
                        messages_list.messages.unshift(new_message);
                        $rootScope.$broadcast('newMessage');
                    });

                });
            };
            var SendMessageModalInstanceCtrl = function ($scope, $uibModalInstance) {

                // Get groups listing
                Group.query({}, function (groups) {
                    $scope.groups = groups;
                });

                $scope.get_as_safe_html = function(value) {
                    return $sce.trustAsHtml(value);
                };

                $scope.contract_name = function(item) {
                    if (item.contract && item.contract.name !== '')
                        return item.contract.name;
                    else
                        return 'Grupos sem contrato';
                };

                $scope.group_label = function(item) {
                    if (item.contract)
                        return item.name + ' - ' + item.contract.name;
                    else
                        return item.name;
                };

                $scope.new_message = new MessageGlobal();
                $scope.new_message.users = [];
                $scope.recipient_list = [];
                $scope.empty_msg_subject_error = false;
                $scope.empty_msg_body_error = false;

                // trick to user modal.all_checked in ng-model html tag
                $scope.modal = {};
                $scope.modal.all_students = true;

                $scope.send = function () {
                    if ($scope.modal.all_students){
                        $scope.new_message.all_students = true;
                        delete $scope.new_message.users;  // ensures that the empty array wont be sent to the server
                    }
                    // If groups were specified, put them in a groups field
                    if ($scope.groups.checked){
                        $scope.new_message.groups = $scope.groups.checked;
                        delete $scope.new_message.users;  // ensures that the empty array wont be sent to the server
                    }
                    if ($scope.new_message.message && $scope.new_message.subject) {
                        $uibModalInstance.close($scope.new_message);
                        $scope.empty_msg_subject_error = false;
                        $scope.empty_msg_body_error = false;
                    }
                    if (!$scope.new_message.message) {
                        $scope.empty_msg_body_error = true;
                    } else {
                        $scope.empty_msg_body_error = false;
                    }
                    if (!$scope.new_message.subject) {
                        $scope.empty_msg_subject_error = true;
                    } else {
                        $scope.empty_msg_subject_error = false;
                    }
                };

                $scope.cancel = function () {
                    $uibModalInstance.dismiss();
                };
                $scope.getUsers = function(val) {
                    return new UserSearch(val);
                };

                $scope.on_select_student = function(model) {
                    $scope.new_message.users.unshift(model.id);
                    $scope.recipient_list.unshift(model);
                    $scope.asyncSelected = '';
                };

                $scope.remove_student = function(index) {
                    $scope.new_message.users.splice(index, 1);
                    $scope.recipient_list.splice(index, 1);
                };

            };
        }
    ]);

    module.controller('MessagesListController', ['$scope', '$uibModal', '$sce', '$window', 'Message', 'messages_list',
        function($scope, $uibModal, $sce, $window, Message, messages_list) {
            $scope.course_id = parseInt($window.course_id, 10);
            $scope.course_slug = $window.course_slug;
            messages_list.messages = Message.query({course: $scope.course_id});
            $scope.messages = messages_list.messages;
            $scope.$on('newMessage', function() {
                $scope.messages = messages_list.messages;
            });

            $scope.strip_html = function(html_content) {
                var text = html_content ? "
"+String(html_content).replace(/<[^>]+>/gm, '')+"
" : '';
                return $sce.trustAsHtml(text);
            };
        }
    ]);

    module.controller('MessagesDashboardController', ['$scope', '$uibModal', '$sce', '$window', 'Message', 'messages_list',
        function($scope, $uibModal, $sce, $window, Message, messages_list) {
            // messages_list.messages = Message.query({limit_to: 2, unread: true});
            $scope.messages = Message.query({unread: true});

            $scope.strip_html = function(html_content) {
                var text = html_content ? "
"+String(html_content).replace(/<[^>]+>/gm, '')+"
" : '';
                return $sce.trustAsHtml(text);
            };
        }
    ]);

    module.controller('MessagesOverviewController', ['$scope', '$uibModal', '$sce', '$window', 'Message', 'messages_list',
        function($scope, $uibModal, $sce, $window, Message, messages_list) {
            messages_list.messages = Message.query({limit_to: 20});
            $scope.messages = messages_list.messages;

            $scope.strip_html = function(html_content) {
                var text = html_content ? "
"+String(html_content).replace(/<[^>]+>/gm, '')+"
" : '';
                return $sce.trustAsHtml(text);
            };
        }
    ]);

    module.controller('MessagesGlobalOverviewController', ['$scope', '$uibModal', '$sce', '$window', 'MessageGlobal', 'messages_list',
        function($scope, $uibModal, $sce, $window, MessageGlobal, messages_list) {
            messages_list.messages = MessageGlobal.query({limit_to: 20});
            $scope.messages = messages_list.messages;

            $scope.strip_html = function(html_content) {
                var text = html_content ? "
"+String(html_content).replace(/<[^>]+>/gm, '')+"
" : '';
                return $sce.trustAsHtml(text);
            };
        }
    ]);

    module.controller('MessageController', ['$scope', '$window', '$sce', 'Message', 'MessageRead',
        function($scope, $window, $sce, Message, MessageRead) {
            $scope.course_id = parseInt($window.course_id, 10);
            $scope.message_id = document.location.href.match(/message\/([0-9]+)/)[1];
            $scope.message = Message.get({messageId: $scope.message_id}, function(message) {
                MessageRead.save({message: $scope.message_id});
            });

            $scope.get_as_safe_html = function(html_content) {
                return $sce.trustAsHtml(html_content);
            }
        }
    ]);
})(angular);
<commit_msg>Changing logic for handling non-contract groups, part 2.<commit_after>(function(angular){
    'use strict';

    var module = angular.module('messages.controllers', []);

    // Service to share data across the controllers
    module.factory('messages_list', function() {
        return {
            messages : []
        };
    });

    module.controller('NewMessageController', ['$scope', '$uibModal', '$window', 'Message', 'Student', 'StudentSearch', 'Class', 'messages_list', '$rootScope', 'ContentFile', 'uiTinymceConfig',
        function($scope, $uibModal, $window, Message, Student, StudentSearch, Class, messages_list, $rootScope, ContentFile, uiTinymceConfig) {
            $scope.course_id = parseInt($window.course_id, 10);
            $scope.messages = messages_list.messages;

            uiTinymceConfig.images_upload_handler = ContentFile.upload;

            $scope.new_message = function () {
                var modalInstance = $uibModal.open({
                    templateUrl: 'newMessageModal.html',
                    controller: ['$scope', '$uibModalInstance', 'course_id', SendMessageModalInstanceCtrl],
                    resolve: {
                        course_id: function () {
                            return $scope.course_id;
                        }
                    }
                });
                modalInstance.result.then(function (new_message) {
                    new_message.$save({}, function(new_message){
                        messages_list.messages.unshift(new_message);
                        $rootScope.$broadcast('newMessage');
                    });

                });
            };
            var SendMessageModalInstanceCtrl = function ($scope, $uibModalInstance, course_id) {

                $scope.new_message = new Message();
                $scope.new_message.course = course_id;
                $scope.new_message.users = [];
                $scope.recipient_list = [];
                $scope.empty_msg_subject_error = false;
                $scope.empty_msg_body_error = false;

                $scope.classes = Class.query({course: course_id}, function(classes){
                    classes.checked = [];
                    $scope.classes_ready = true;
                    return classes;
                });

                // trick to user modal.all_checked in ng-model html tag
                $scope.modal = {};
                $scope.modal.all_checked = true;

                $scope.send = function () {
                    // TODO validação dos campo: títle e message não podem ser vazios
                    if ($scope.modal.all_checked) {
                        $scope.new_message.users = [];
                        angular.forEach($scope.classes, function(klass) {
                            $scope.new_message.users = $scope.new_message.users.concat(klass.students);
                        });
                    } else if ($scope.classes.checked) {
                        angular.forEach($scope.classes.checked, function(klass) {
                            $scope.new_message.users = $scope.new_message.users.concat(klass);
                        });
                    }
                    if ($scope.new_message.message && $scope.new_message.subject) {
                        $uibModalInstance.close($scope.new_message);
                        $scope.empty_msg_subject_error = false;
                        $scope.empty_msg_body_error = false;
                    }
                    if (!$scope.new_message.message) {
                        $scope.empty_msg_body_error = true;
                    } else {
                        $scope.empty_msg_body_error = false;
                    }
                    if (!$scope.new_message.subject) {
                        $scope.empty_msg_subject_error = true;
                    } else {
                        $scope.empty_msg_subject_error = false;
                    }
                };

                $scope.cancel = function () {
                    $uibModalInstance.dismiss();
                };
                $scope.getUsers = function(val) {
                    return new StudentSearch(val, course_id);
                };

                $scope.on_select_student = function(model) {
                    $scope.new_message.users.unshift(model.id);
                    $scope.recipient_list.unshift(model);
                    $scope.asyncSelected = '';
                };

                $scope.remove_student = function(index) {
                    $scope.new_message.users.splice(index, 1);
                    $scope.recipient_list.splice(index, 1);
                };

            };
        }
    ]);

    module.controller('NewGlobalMessageController', ['$scope', '$uibModal', '$window', 'MessageGlobal', 'Student', 'Group', 'UserSearch', 'Class', 'messages_list', '$rootScope', '$sce', 'ContentFile', 'uiTinymceConfig',
        function($scope, $uibModal, $window, MessageGlobal, Student, Group, UserSearch, Class, messages_list, $rootScope, $sce, ContentFile, uiTinymceConfig) {
            $scope.course_id = parseInt($window.course_id, 10);
            $scope.messages = messages_list.messages;

            uiTinymceConfig.images_upload_handler = ContentFile.upload;

            $scope.new_message = function () {
                var modalInstance = $uibModal.open({
                    templateUrl: 'newMessageModal.html',
                    controller: ['$scope', '$uibModalInstance', 'course_id', SendMessageModalInstanceCtrl],
                    resolve: {
                        course_id: function () {
                            return $scope.course_id;
                        }
                    }
                });
                modalInstance.result.then(function (new_message) {
                    new_message.$save({}, function(new_message){
                        messages_list.messages.unshift(new_message);
                        $rootScope.$broadcast('newMessage');
                    });

                });
            };
            var SendMessageModalInstanceCtrl = function ($scope, $uibModalInstance) {

                // Get groups listing
                Group.query({}, function (groups) {
                    $scope.groups = groups;
                });

                $scope.get_as_safe_html = function(value) {
                    return $sce.trustAsHtml(value);
                };

                $scope.contract_name = function(item) {
                    if (item.contract && item.contract.name !== '')
                        return item.contract.name;
                    else
                        return 'Grupos sem contrato';
                };

                $scope.group_label = function(item) {
                    if (item.contract && item.contract.name != '')
                        return item.name + ' - ' + item.contract.name;
                    else
                        return item.name;
                };

                $scope.new_message = new MessageGlobal();
                $scope.new_message.users = [];
                $scope.recipient_list = [];
                $scope.empty_msg_subject_error = false;
                $scope.empty_msg_body_error = false;

                // trick to user modal.all_checked in ng-model html tag
                $scope.modal = {};
                $scope.modal.all_students = true;

                $scope.send = function () {
                    if ($scope.modal.all_students){
                        $scope.new_message.all_students = true;
                        delete $scope.new_message.users;  // ensures that the empty array wont be sent to the server
                    }
                    // If groups were specified, put them in a groups field
                    if ($scope.groups.checked){
                        $scope.new_message.groups = $scope.groups.checked;
                        delete $scope.new_message.users;  // ensures that the empty array wont be sent to the server
                    }
                    if ($scope.new_message.message && $scope.new_message.subject) {
                        $uibModalInstance.close($scope.new_message);
                        $scope.empty_msg_subject_error = false;
                        $scope.empty_msg_body_error = false;
                    }
                    if (!$scope.new_message.message) {
                        $scope.empty_msg_body_error = true;
                    } else {
                        $scope.empty_msg_body_error = false;
                    }
                    if (!$scope.new_message.subject) {
                        $scope.empty_msg_subject_error = true;
                    } else {
                        $scope.empty_msg_subject_error = false;
                    }
                };

                $scope.cancel = function () {
                    $uibModalInstance.dismiss();
                };
                $scope.getUsers = function(val) {
                    return new UserSearch(val);
                };

                $scope.on_select_student = function(model) {
                    $scope.new_message.users.unshift(model.id);
                    $scope.recipient_list.unshift(model);
                    $scope.asyncSelected = '';
                };

                $scope.remove_student = function(index) {
                    $scope.new_message.users.splice(index, 1);
                    $scope.recipient_list.splice(index, 1);
                };

            };
        }
    ]);

    module.controller('MessagesListController', ['$scope', '$uibModal', '$sce', '$window', 'Message', 'messages_list',
        function($scope, $uibModal, $sce, $window, Message, messages_list) {
            $scope.course_id = parseInt($window.course_id, 10);
            $scope.course_slug = $window.course_slug;
            messages_list.messages = Message.query({course: $scope.course_id});
            $scope.messages = messages_list.messages;
            $scope.$on('newMessage', function() {
                $scope.messages = messages_list.messages;
            });

            $scope.strip_html = function(html_content) {
                var text = html_content ? "
"+String(html_content).replace(/<[^>]+>/gm, '')+"
" : '';
                return $sce.trustAsHtml(text);
            };
        }
    ]);

    module.controller('MessagesDashboardController', ['$scope', '$uibModal', '$sce', '$window', 'Message', 'messages_list',
        function($scope, $uibModal, $sce, $window, Message, messages_list) {
            // messages_list.messages = Message.query({limit_to: 2, unread: true});
            $scope.messages = Message.query({unread: true});

            $scope.strip_html = function(html_content) {
                var text = html_content ? "
"+String(html_content).replace(/<[^>]+>/gm, '')+"
" : '';
                return $sce.trustAsHtml(text);
            };
        }
    ]);

    module.controller('MessagesOverviewController', ['$scope', '$uibModal', '$sce', '$window', 'Message', 'messages_list',
        function($scope, $uibModal, $sce, $window, Message, messages_list) {
            messages_list.messages = Message.query({limit_to: 20});
            $scope.messages = messages_list.messages;

            $scope.strip_html = function(html_content) {
                var text = html_content ? "
"+String(html_content).replace(/<[^>]+>/gm, '')+"
" : '';
                return $sce.trustAsHtml(text);
            };
        }
    ]);

    module.controller('MessagesGlobalOverviewController', ['$scope', '$uibModal', '$sce', '$window', 'MessageGlobal', 'messages_list',
        function($scope, $uibModal, $sce, $window, MessageGlobal, messages_list) {
            messages_list.messages = MessageGlobal.query({limit_to: 20});
            $scope.messages = messages_list.messages;

            $scope.strip_html = function(html_content) {
                var text = html_content ? "
"+String(html_content).replace(/<[^>]+>/gm, '')+"
" : '';
                return $sce.trustAsHtml(text);
            };
        }
    ]);

    module.controller('MessageController', ['$scope', '$window', '$sce', 'Message', 'MessageRead',
        function($scope, $window, $sce, Message, MessageRead) {
            $scope.course_id = parseInt($window.course_id, 10);
            $scope.message_id = document.location.href.match(/message\/([0-9]+)/)[1];
            $scope.message = Message.get({messageId: $scope.message_id}, function(message) {
                MessageRead.save({message: $scope.message_id});
            });

            $scope.get_as_safe_html = function(html_content) {
                return $sce.trustAsHtml(html_content);
            }
        }
    ]);
})(angular);
<|endoftext|>