<commit_before>import angular from 'angular';
import angularRoute from 'angular-route';
import angularSanitize from 'angular-sanitize';
import angularResource from 'angular-resource';
import uiMessages from './directives/messages/messages';
import uiAlert from './directives/alert/alert';
import wizMarkdown from './lib/wiz-markdown/wizMarkdown/wizMarkdown';

const APP_NAME = 'app';
angular.module( APP_NAME, [ 'ngRoute', 'ngResource', 'uiMessages', 'uiAlert', 'wiz.markdown', 'flow' ] );

export default APP_NAME;
<commit_msg>[UPDATE]: ESlinter foi desabilitado para esse arquivo.<commit_after>/* eslint-disable */

import angular from 'angular';
import angularRoute from 'angular-route';
import angularSanitize from 'angular-sanitize';
import angularResource from 'angular-resource';
import uiMessages from './directives/messages/messages';
import uiAlert from './directives/alert/alert';
import wizMarkdown from './lib/wiz-markdown/wizMarkdown/wizMarkdown';

const APP_NAME = 'app';
angular.module( APP_NAME, [ 'ngRoute', 'ngResource', 'uiMessages', 'uiAlert', 'wiz.markdown', 'flow' ] );

export default APP_NAME;
<|endoftext|>


<commit_before><commit_msg>Fixed broken reference<commit_after><|endoftext|>


<commit_before>/**
 * Created by out_xu on 16/12/21.
 */
export default {
  mobile: /^1[3|4|5|7|8][0-9]\d{8}$/,
  password: /^\w{6,18}$/,
  mail: /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/,
  phone: /^1[3|4|5|7|8][0-9]\d{8}$/,
  stuCode: /^\d{2,}$/,
  qq: /[1-9][0-9]{4,}/,
  number: /^[0-9]\d*$/,
  age: /^(?:[1-9][0-9]?|1[01][0-9]|120)$/,
  chinese: /[\u4E00-\u9FA5\uF900-\uFA2D]/,
  IDCard: /^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$|^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/
}
<commit_msg>更改手机验证规则<commit_after>/**
 * Created by out_xu on 16/12/21.
 */
export default {
  mobile: /^(1+\d{10})$/,
  password: /^\w{6,18}$/,
  mail: /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/,
  phone: /^1[3|4|5|7|8][0-9]\d{8}$/,
  stuCode: /^\d{2,}$/,
  qq: /[1-9][0-9]{4,}/,
  number: /^[0-9]\d*$/,
  age: /^(?:[1-9][0-9]?|1[01][0-9]|120)$/,
  chinese: /[\u4E00-\u9FA5\uF900-\uFA2D]/,
  IDCard: /^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$|^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/
}
<|endoftext|>


<commit_before>define(function(require) {

  var fabric = require("fabric"),
      brushDistanceUtil = require("canvasUtils/brushDistance");

  var isFarEnough = brushDistanceUtil.isFarEnough,
      getClosestPoint = brushDistanceUtil.getClosestPoint;

  var _distance = 0;

  function _hijack(brush) {
    if (brush.hasBeenHijacked) {
      return brush;
    }

    var brushOnMouseMove = brush.onMouseMove;

    brush.onMouseMove = function(pointer) {
      var points = brush.points ? brush.points : brush._points;

      var length = points.length,
          lastPoint = points[length - 1];

      if (isFarEnough(lastPoint, pointer, _distance)) {
        return brushOnMouseMove.call(brush, getClosestPoint(lastPoint, pointer, _distance));
      }
    };

    brush.hasBeenHijacked = true;

    return brush;
  }

  return {
    hijack: function(brush) {
      return _hijack(brush);
    },

    setDistance: function(distance) {
      _distance = distance;
    },

    getDistance: function() {
      return _distance;
    }
  };

});<commit_msg>place the internal points property detection outside of mousemove handler<commit_after>define(function(require) {

  var fabric = require("fabric"),
      brushDistanceUtil = require("canvasUtils/brushDistance");

  var isFarEnough = brushDistanceUtil.isFarEnough,
      getClosestPoint = brushDistanceUtil.getClosestPoint;

  var _distance = 0;

  function _hijack(brush) {
    if (brush.hasBeenHijacked) {
      return brush;
    }

    var brushOnMouseMove = brush.onMouseMove,
        points = brush.points ? brush.points : brush._points;

    brush.onMouseMove = function(pointer) {
      var length = points.length,
          lastPoint = points[length - 1];

      if (isFarEnough(lastPoint, pointer, _distance)) {
        return brushOnMouseMove.call(brush, getClosestPoint(lastPoint, pointer, _distance));
      }
    };

    brush.hasBeenHijacked = true;

    return brush;
  }

  return {
    hijack: function(brush) {
      return _hijack(brush);
    },

    setDistance: function(distance) {
      _distance = distance;
    },

    getDistance: function() {
      return _distance;
    }
  };

});<|endoftext|>


<commit_before>/*
 * Clean up unnecessary elements from 'Sign In' path based pages.
 */
(function (d) {

    d.querySelector(".header_nav").style.display = 'none';

    d.querySelector("#page_contents > .align_center:last-child").style.display = 'none';
    d.querySelector("#page_contents").style.paddingBottom = 0;

}(document));
<commit_msg>Improve CSS elements clean up script<commit_after>/*
 * Clean up unnecessary elements from 'Sign In' path based pages.
 */
(function (d) {

    d.querySelector("header .header_nav").style.display = 'none';

    d.querySelector("#page").style.minHeight = 0;

    d.querySelector("#page_contents").style.paddingBottom = 0;
    d.querySelector("#page_contents > .align_center:last-child").style.display = 'none';

}(document));
<|endoftext|>


<commit_before>'use strict'

module.exports = data => {
  const report = []

  data.forEach(item => {
    if (item.documentCategory ===  'fag') {
      item.coursesList.split('\n').forEach(course => {
        report.push({
          studentName: item.studentName,
          period: item.period,
          category: item.documentCategory,
          course: course,
          description: item.gradesCategories,
          date: item.timeStamp
        })
      })
    } else {
      report.push({
        studentName: item.studentName,
        period: item.period,
        category: item.documentCategory,
        course: '',
        description: item.gradesCategories || item.orderCategories || item.behaviourCategories || '',
        date: item.timeStamp
      })
    }
  })

  return report
}
<commit_msg>Standard fixes<commit_after>'use strict'

module.exports = data => {
  const report = []

  data.forEach(item => {
    if (item.documentCategory === 'fag') {
      item.coursesList.split('\n').forEach(course => {
        report.push({
          studentName: item.studentName,
          period: item.period,
          category: item.documentCategory,
          course: course,
          description: item.gradesCategories,
          date: item.timeStamp
        })
      })
    } else {
      report.push({
        studentName: item.studentName,
        period: item.period,
        category: item.documentCategory,
        course: '',
        description: item.gradesCategories || item.orderCategories || item.behaviourCategories || '',
        date: item.timeStamp
      })
    }
  })

  return report
}
<|endoftext|>


<commit_before>/*
 * Copyright 2012 Amadeus s.a.s.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * It is on purpose that this file does not have any external dependency,
 * so that it is easy to import this file in any other context (browser...)
 */

function JsonReport() {
    this.flatReport = [];
    this.stats = {
        tasksIgnored: 0,
        tasksStarted: 0,
        tasksFinished: 0,
        tasksRestarts: 0,
        tasksSuccess: 0,
        tasksError: 0,
        testsStarted: 0,
        testsFinished: 0,
        testCases: 0,
        testMethods: 0,
        asserts: 0,
        failures: 0,
        errors: 0
    };
    this.report = {
        campaignId: null,
        stats: this.stats,
        tasks: this.treeReport
    };
    this.tasks = {};

    /**
     * keys are browser names, values: array of tuples [{ taskName, method, errorMessage }, ...]
     */
    this.tasksErrors = {};
    this.remainingTasks = 0;
}

function addToFlatReport(task) {
    var subTests = task.subTests;
    /*if (task.errors) {
            // don't loose those errors
        }*/
    if (subTests) {
        var noGrandChildren = true,
            i, l = subTests.length;
        for (i = 0; i < l; i++) {
            var curSubTest = subTests[i];
            if (curSubTest.subTests) {
                noGrandChildren = false;
                break;
            }
        }
        if (noGrandChildren) {
            this.flatReport.push(task);
        } else {
            for (i = 0; i < l; i++) {
                addToFlatReport.call(this, subTests[i]);
            }
        }
    } else {
        this.flatReport.push(task);
    }
}

function processTask(task) {
    var reportTask = {
        name: task.name,
        url: task.url
    };
    this.tasks[task.taskId] = reportTask;
    var subTasks = task.subTasks;
    if (subTasks) {
        reportTask.subTasks = processTasksList.call(this, subTasks);
    } else {
        reportTask.subTests = [];
    }
    return reportTask;
}

function processTasksList(tasks) {
    var res = [];
    for (var i = 0, l = tasks.length; i < l; i++) {
        res[i] = processTask.call(this, tasks[i]);
    }
    return res;
}

function getRunningTask(event) {
    var taskId = event.taskId;
    var task = this.tasks[taskId];
    if (!task || !task.events) {
        // TODO: error
        return;
    }
    return task;
}

var eventTypes = {
    tasksList: function tasksList(event) {
        this.report.tasks = processTasksList.call(this, event.tasks);
        this.report.campaignId = event.campaignId;
    },
    taskStarted: function taskStarted(event) {
        var taskId = event.taskId;
        var task = this.tasks[taskId];
        if (!task || task.startTime) {
            // TODO: error
            return;
        }
        task.nbAsserts = 0;
        task.nbFailures = 0;
        task.nbErrors = 0;
        task.startTime = event.time;
        task.slaveNumber = event.slave ? event.slave.slaveNumber : null;
        task.events = [];
        this.stats.tasksStarted++;
    },
    taskFinished: function taskFinished(event) {
        var task = getRunningTask.call(this, event);
        if (!task) {
            return;
        }
        task.duration = event.time - task.startTime;
        var events = task.events;
        delete task.events;
        if (event.restartPlanned) {
            // undo what was done in taskStarted:
            delete task.startTime;
            this.stats.tasksStarted--;
            // counts the number of tasks restarts:
            this.stats.tasksRestarts++;
            return;
            // do not reset nbFailures or nbErrors to 0, the restart will do it
            // the values might be useful for console report
        }
        processTaskEvents.call(this, task, events);
        task.endTime = event.time;
        addToFlatReport.call(this, task);
        this.stats.tasksFinished++;
    },
    taskIgnored: function taskIgnored(event) {
        var taskId = event.taskId;
        var task = this.tasks[taskId];
        if (!task || task.startTime) {
            // TODO: error
            return;
        }
        task.startTime = event.time;
        task.endTime = event.time;
        task.duration = 0;
        task.ignored = true;
        delete task.subTests;
        addToFlatReport.call(this, task);
        this.stats.tasksIgnored++;
    },
    testStarted: queueTaskEvent,
    testFinished: function testFinished(event) {
        if (event.asserts) {
            // increase number of asserts so that console report can read and display it immediately
            // in case of task restart, the value will be reset to 0 in 'taskStarted'
            var task = getRunningTask.call(this, event);
            task.nbAsserts += event.asserts;
        }

        // enqueue for final processing (only processed when there are no restarts anymore)
        queueTaskEvent.call(this, event);
    },
    error: function error(event) {
        // mark failure/error on task so that console report can read and display it immediately;
        // in case of task restart, those values will be reset to 0 in 'taskStarted'
        var err = event.error;
        var task = getRunningTask.call(this, event);
        if (err.failure) {
            task.nbFailures++;
        } else {
            task.nbErrors++;
        }

        // enqueue for final processing (only processed when there are no restarts anymore)
        queueTaskEvent.call(this, event);
    }
};

var queuedEventTypes = {
    testStarted: function testStarted(task, event, runningTests) {
        var parent = task;
        var test = {
            name: event.name,
            startTime: event.time
        };
        var parentId = event.parentTestId;
        if (parentId) {
            parent = runningTests[parentId] || task;
        }
        if (event.method) {
            test.method = event.method;
            this.stats.testMethods++;
            if (!parent.subTests) {
                // count the parent as a test case
                this.stats.testCases++;
            }
        }
        if (!parent.subTests) {
            parent.subTests = [];
        }
        parent.subTests.push(test);
        runningTests[event.testId] = test;
        this.stats.testsStarted++;
    },
    testFinished: function testFinished(task, event, runningTests) {
        var test = runningTests[event.testId];
        test.asserts = event.asserts;
        if (event.asserts) {
            this.stats.asserts += event.asserts;
        }
        test.endTime = event.time;
        test.duration = event.duration;
        this.stats.testsFinished++;
    },
    error: function error(task, event, runningTests) {
        var parent = task;
        if (event.testId) {
            parent = runningTests[event.testId] || task;
        }
        parent.errors = parent.errors || [];
        var err = event.error;
        parent.errors.push(err);

        var taskAndBrowserName = task.name.split(" on "); // "taskX on browserY"
        var browserName = taskAndBrowserName[1] || "default browser";
        this.tasksErrors[browserName] = this.tasksErrors[browserName] || [];
        this.tasksErrors[browserName].push({
            taskName: taskAndBrowserName[0],
            method: event.method || "",
            errorMessage: err.message
        });

        if (err.failure) {
            this.stats.failures++;
        } else {
            this.stats.errors++;
        }
    }
};

function queueTaskEvent(event) {
    var task = getRunningTask.call(this, event);
    if (!task) {
        return;
    }
    task.events.push(event);
}

function processTaskEvents(task, events) {
    var runningTests = {};
    var error = false;
    for (var i = 0, l = events.length; i < l; i++) {
        var curEvent = events[i];
        var eventName = curEvent.event;
        if (eventName == "error") {
            error = true;
        }
        queuedEventTypes[eventName].call(this, task, curEvent, runningTests);
    }
    if (error) {
        this.stats.tasksError++;
    } else {
        this.stats.tasksSuccess++;
    }
}

JsonReport.prototype = {};

JsonReport.prototype.addResult = function (event) {
    var eventName = event.event;
    var eventHandler = eventTypes[eventName];
    if (eventHandler) {
        eventHandler.call(this, event);
    }
};

module.exports = JsonReport;
<commit_msg>fix #157 uncaught exception when there is no error message<commit_after>/*
 * Copyright 2012 Amadeus s.a.s.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * It is on purpose that this file does not have any external dependency,
 * so that it is easy to import this file in any other context (browser...)
 */

function JsonReport() {
    this.flatReport = [];
    this.stats = {
        tasksIgnored: 0,
        tasksStarted: 0,
        tasksFinished: 0,
        tasksRestarts: 0,
        tasksSuccess: 0,
        tasksError: 0,
        testsStarted: 0,
        testsFinished: 0,
        testCases: 0,
        testMethods: 0,
        asserts: 0,
        failures: 0,
        errors: 0
    };
    this.report = {
        campaignId: null,
        stats: this.stats,
        tasks: this.treeReport
    };
    this.tasks = {};

    /**
     * keys are browser names, values: array of tuples [{ taskName, method, errorMessage }, ...]
     */
    this.tasksErrors = {};
    this.remainingTasks = 0;
}

function addToFlatReport(task) {
    var subTests = task.subTests;
    /*if (task.errors) {
            // don't loose those errors
        }*/
    if (subTests) {
        var noGrandChildren = true,
            i, l = subTests.length;
        for (i = 0; i < l; i++) {
            var curSubTest = subTests[i];
            if (curSubTest.subTests) {
                noGrandChildren = false;
                break;
            }
        }
        if (noGrandChildren) {
            this.flatReport.push(task);
        } else {
            for (i = 0; i < l; i++) {
                addToFlatReport.call(this, subTests[i]);
            }
        }
    } else {
        this.flatReport.push(task);
    }
}

function processTask(task) {
    var reportTask = {
        name: task.name,
        url: task.url
    };
    this.tasks[task.taskId] = reportTask;
    var subTasks = task.subTasks;
    if (subTasks) {
        reportTask.subTasks = processTasksList.call(this, subTasks);
    } else {
        reportTask.subTests = [];
    }
    return reportTask;
}

function processTasksList(tasks) {
    var res = [];
    for (var i = 0, l = tasks.length; i < l; i++) {
        res[i] = processTask.call(this, tasks[i]);
    }
    return res;
}

function getRunningTask(event) {
    var taskId = event.taskId;
    var task = this.tasks[taskId];
    if (!task || !task.events) {
        // TODO: error
        return;
    }
    return task;
}

var eventTypes = {
    tasksList: function tasksList(event) {
        this.report.tasks = processTasksList.call(this, event.tasks);
        this.report.campaignId = event.campaignId;
    },
    taskStarted: function taskStarted(event) {
        var taskId = event.taskId;
        var task = this.tasks[taskId];
        if (!task || task.startTime) {
            // TODO: error
            return;
        }
        task.nbAsserts = 0;
        task.nbFailures = 0;
        task.nbErrors = 0;
        task.startTime = event.time;
        task.slaveNumber = event.slave ? event.slave.slaveNumber : null;
        task.events = [];
        this.stats.tasksStarted++;
    },
    taskFinished: function taskFinished(event) {
        var task = getRunningTask.call(this, event);
        if (!task) {
            return;
        }
        task.duration = event.time - task.startTime;
        var events = task.events;
        delete task.events;
        if (event.restartPlanned) {
            // undo what was done in taskStarted:
            delete task.startTime;
            this.stats.tasksStarted--;
            // counts the number of tasks restarts:
            this.stats.tasksRestarts++;
            return;
            // do not reset nbFailures or nbErrors to 0, the restart will do it
            // the values might be useful for console report
        }
        processTaskEvents.call(this, task, events);
        task.endTime = event.time;
        addToFlatReport.call(this, task);
        this.stats.tasksFinished++;
    },
    taskIgnored: function taskIgnored(event) {
        var taskId = event.taskId;
        var task = this.tasks[taskId];
        if (!task || task.startTime) {
            // TODO: error
            return;
        }
        task.startTime = event.time;
        task.endTime = event.time;
        task.duration = 0;
        task.ignored = true;
        delete task.subTests;
        addToFlatReport.call(this, task);
        this.stats.tasksIgnored++;
    },
    testStarted: queueTaskEvent,
    testFinished: function testFinished(event) {
        if (event.asserts) {
            // increase number of asserts so that console report can read and display it immediately
            // in case of task restart, the value will be reset to 0 in 'taskStarted'
            var task = getRunningTask.call(this, event);
            task.nbAsserts += event.asserts;
        }

        // enqueue for final processing (only processed when there are no restarts anymore)
        queueTaskEvent.call(this, event);
    },
    error: function error(event) {
        // mark failure/error on task so that console report can read and display it immediately;
        // in case of task restart, those values will be reset to 0 in 'taskStarted'
        var err = event.error;
        var task = getRunningTask.call(this, event);
        if (err.failure) {
            task.nbFailures++;
        } else {
            task.nbErrors++;
        }

        // enqueue for final processing (only processed when there are no restarts anymore)
        queueTaskEvent.call(this, event);
    }
};

var queuedEventTypes = {
    testStarted: function testStarted(task, event, runningTests) {
        var parent = task;
        var test = {
            name: event.name,
            startTime: event.time
        };
        var parentId = event.parentTestId;
        if (parentId) {
            parent = runningTests[parentId] || task;
        }
        if (event.method) {
            test.method = event.method;
            this.stats.testMethods++;
            if (!parent.subTests) {
                // count the parent as a test case
                this.stats.testCases++;
            }
        }
        if (!parent.subTests) {
            parent.subTests = [];
        }
        parent.subTests.push(test);
        runningTests[event.testId] = test;
        this.stats.testsStarted++;
    },
    testFinished: function testFinished(task, event, runningTests) {
        var test = runningTests[event.testId];
        test.asserts = event.asserts;
        if (event.asserts) {
            this.stats.asserts += event.asserts;
        }
        test.endTime = event.time;
        test.duration = event.duration;
        this.stats.testsFinished++;
    },
    error: function error(task, event, runningTests) {
        var parent = task;
        if (event.testId) {
            parent = runningTests[event.testId] || task;
        }
        parent.errors = parent.errors || [];
        var err = event.error;
        parent.errors.push(err);

        var taskAndBrowserName = task.name.split(" on "); // "taskX on browserY"
        var browserName = taskAndBrowserName[1] || "default browser";
        this.tasksErrors[browserName] = this.tasksErrors[browserName] || [];
        this.tasksErrors[browserName].push({
            taskName: taskAndBrowserName[0],
            method: event.method || "",
            errorMessage: err.message || ""
        });

        if (err.failure) {
            this.stats.failures++;
        } else {
            this.stats.errors++;
        }
    }
};

function queueTaskEvent(event) {
    var task = getRunningTask.call(this, event);
    if (!task) {
        return;
    }
    task.events.push(event);
}

function processTaskEvents(task, events) {
    var runningTests = {};
    var error = false;
    for (var i = 0, l = events.length; i < l; i++) {
        var curEvent = events[i];
        var eventName = curEvent.event;
        if (eventName == "error") {
            error = true;
        }
        queuedEventTypes[eventName].call(this, task, curEvent, runningTests);
    }
    if (error) {
        this.stats.tasksError++;
    } else {
        this.stats.tasksSuccess++;
    }
}

JsonReport.prototype = {};

JsonReport.prototype.addResult = function (event) {
    var eventName = event.event;
    var eventHandler = eventTypes[eventName];
    if (eventHandler) {
        eventHandler.call(this, event);
    }
};

module.exports = JsonReport;
<|endoftext|>


<commit_before>/*jshint esversion: 6 */

/*
  Manage Menu View to select and unselect proposition of element/link
*/
class AskomicsMenu {

  constructor (nameMenu,buttonMenu,listObjectMenu,functFillMenu,removeWhenReset=true) {
    this.name = nameMenu;
    this.buttonMenu = buttonMenu;
    this.listObjectMenu = listObjectMenu ;
    this.func = functFillMenu ;
    this.removeWhenReset = removeWhenReset ;
  }

  reset() {
    let menu = this ;
    // Remove onclick
    $("#"+menu.buttonMenu).unbind();
    if (menu.removeWhenReset)
      $("#"+menu.listObjectMenu).empty();
  }

  start() {
    let menu = this ;
    $("#"+menu.buttonMenu).prop('disabled', false);
    $("#"+menu.buttonMenu)
    .on('mousedown', function(event) {
      if ( $("#"+menu.listObjectMenu).is(':visible') ) {
        $("#"+menu.listObjectMenu).slideUp();
      }
      else {
        menu.slideUp();
        $("#"+menu.listObjectMenu).slideDown();
      }
      event.stopPropagation();
    });
    menu.func(menu);
    //hide by default
    $("#"+menu.listObjectMenu).hide();
  }

  slideUp() {
    $("#menuGraph").find("ul").slideUp();
  }
}

/**************************************************************************/
/**/
/**/
/* Shortcuts Menu */
/**/
/**/
var fileFuncMenu = function(menu) {
  //$("#uploadedQuery")
  $("#dwl-query").on('click', function(d) {
    var date = new Date().getTime();
    $(this).attr("href", "data:application/octet-stream," + encodeURIComponent(__ihm.getGraphBuilder().getInternalState())).attr("download", "query-" + date + ".json");
  });

  $("#dwl-query-sparql").on('click', function(d) {
    let service = new RestServiceJs("getSparqlQueryInTextFormat");
    let jdata = new AskomicsJobsViewManager().prepareQuery();

    let current = this;
    $(current).removeAttr("href");
    service.postsync(jdata,function(data) {
      let date = new Date().getTime();
      $(current).attr("href", "data:application/sparql-query," + encodeURIComponent(data.query)).attr("download", "query-" + date + ".rq");
    });

  });
};

/**************************************************************************/
/**/
/**/
/* Shortcuts Menu */
/**/
/**/
var shortcutsFuncMenu = function(menu) {

  var buildLiView = function (uri,label,submenu) {

    var icheck = $("")
        .attr("class","glyphicon glyphicon-check")
        .css("visibility","hidden");

    var a = $("")
            .attr("href","#")
            .attr("class","small")
            .attr("tabIndex","-1") ;
    if (submenu) {
      a.html($("").append(label+"\t")).append(icheck);
    } else {
      a.html($("").append(label+"\t")).append(icheck);
    }
    var li = $("

");
    li.attr("uri",uri);
    li.css("display","table-cell");
    li.css("vertical-align","middle");
    li.append(a);
    return li;
  };

  let lshortcuts = new ShortcutsParametersView().getAllShortcuts();
  /*
  if (lshortcuts.length <= 0) {
    $("#buttonViewListShortcuts").removeClass('active');
    $("#buttonViewListShortcuts").addClass('disabled');

  } else {
    $("#buttonViewListShortcuts").removeClass('disabled');
    $("#buttonViewListShortcuts").addClass('active');
  }
*/
  //console.log(JSON.stringify(lshortcuts));
  $.each(lshortcuts, function(i) {
    var li = buildLiView(i,lshortcuts[i].label,false);
    __ihm.getSVGLayout().offProposedUri("shortcuts",i);

    li.on('click', function() {
      var span = $(this).find(".glyphicon");
      var cur_uri = $(this).attr("uri");
      if ( span.css("visibility") == "visible" ) {
        span.css("visibility","hidden");
        __ihm.getSVGLayout().offProposedUri("shortcuts",cur_uri);
      } else {
        span.css("visibility","visible");
        __ihm.getSVGLayout().onProposedUri("shortcuts",cur_uri);
      }
      // remove old suggestion
      __ihm.getSVGLayout().removeSuggestions();
      // insert new suggestion
      __ihm.getSVGLayout().insertSuggestions();
      // regenerate the graph
      __ihm.getSVGLayout().update();
    });
    $("#"+menu.listObjectMenu).append(li);
    $("#"+menu.listObjectMenu).append($("

").attr("class","divider"));
    /* next entity */
  });

  /* remove button if no shortcuts */
  if ( Object.keys(lshortcuts).length <= 0 ) {
    $("#"+menu.buttonMenu).prop('disabled', true);
  }

};
/**************************************************************************/
/**/
/**/
/* Shortcuts Menu */
/**/
/**/
var entitiesAndRelationsFuncMenu = function(menu) {
  var buildLiView = function(uri,label,submenu,hidden) {

    var icheck = $("")
        .attr("class","glyphicon glyphicon-check");

    if (hidden) {
      icheck.css("visibility","hidden");
    }
    var a = $("")
            .attr("href","#")
            .attr("class","small")
            .attr("tabIndex","-1") ;
    if (submenu) {
      a.html($("").append(label+"\t")).append(icheck);
    } else {
      a.html($("").append(label+"\t")).append(icheck);
    }
    var li = $("

");
    li.attr("uri",uri);
    li.css("display","table-cell");
    li.css("vertical-align","middle");
    li.append(a);
    return li;
  };
  var menuView = menu;
  //
<input type="checkbox"/> Option 1

  let lentities = Object.keys(__ihm.getAbstraction().getEntities());

  $.each(lentities, function(i) {

    let node = new GraphObject({'uri' : lentities[i]});
    let nodeuri = node.uri;
    var li = buildLiView(nodeuri,node.removePrefix(),false,false);

    li.on('click', function() {
      var span = $(this).find(".glyphicon");
      var cur_uri = $(this).attr("uri");
      if ( span.css("visibility") == "visible" ) {
        span.css("visibility","hidden");
        __ihm.getSVGLayout().offProposedUri("node",cur_uri);
        // disable all predicate associated with this node
        $(this).parent().parent().find("li[nodeuri='"+cur_uri+"']").attr("class","disabled");
      } else {
        span.css("visibility","visible");
        __ihm.getSVGLayout().onProposedUri("node",cur_uri);
        // enable all predicate associated with this node
        $(this).parent().parent().find("li[nodeuri='"+cur_uri+"']").removeAttr("class");
      }
      // remove old suggestion
      __ihm.getSVGLayout().removeSuggestions();
      // insert new suggestion
      __ihm.getSVGLayout().insertSuggestions();
      // regenerate the graph
      __ihm.getSVGLayout().update();
    });

    $("#"+menuView.listObjectMenu).append(li);
    /* --------------------------- */
    /* Adding filter on relations  */
    /* --------------------------- */

    let tab = __ihm.getAbstraction().getRelationsObjectsAndSubjectsWithURI(nodeuri);
    let listRelObj = tab[0];

    $.each(listRelObj, function(objecturi) {
      let object = new GraphObject({uri:objecturi});
      $.each(listRelObj[objecturi], function(idxrel) {
        let rel = listRelObj[objecturi][idxrel];
        let linkRel = new GraphObject({uri:rel});
        let li = buildLiView(rel,linkRel.removePrefix()+"→"+object.removePrefix(),true,false);

        li.attr("nodeuri",nodeuri)
          .on('click', function() {
            /* when this li is unavailable, we can do nothing */
            if ( $(this).attr("class") === "disabled" ) return ;

            var span = $(this).find(".glyphicon");
            var cur_uri = $(this).attr("uri");
            if ( span.css("visibility") == "visible" ) {
             span.css("visibility","hidden");
             __ihm.getSVGLayout().offProposedUri("link",cur_uri);
            } else {
             span.css("visibility","visible");
             __ihm.getSVGLayout().onProposedUri("link",cur_uri);
           }
           /* remove old suggestion */
           __ihm.getSVGLayout().removeSuggestions();
           /* insert new suggestion */
           __ihm.getSVGLayout().insertSuggestions();
           /* regenerate the graph */
           __ihm.getSVGLayout().update();
        });
        $("#"+menuView.listObjectMenu).append(li);
      });
    });
    $("#"+menuView.listObjectMenu).append($("

").attr("class","divider"));
    /* next entity */
  });

  let positionableEntities = __ihm.getAbstraction().getPositionableEntities();
  if (Object.keys(positionableEntities).length>0) {
    /* positionable object */
    let posuri = "positionable";
    let li = buildLiView(posuri,posuri,false,true);
    __ihm.getSVGLayout().offProposedUri("link",posuri);

    li.attr("nodeuri",posuri)
      .on('click', function() {
        var span = $(this).find(".glyphicon");
        var cur_uri = $(this).attr("uri");
        if ( span.css("visibility") == "visible" ) {
          span.css("visibility","hidden");
          __ihm.getSVGLayout().offProposedUri("link",cur_uri);
        } else {
          span.css("visibility","visible");
          __ihm.getSVGLayout().onProposedUri("link",cur_uri);
        }
        /* remove old suggestion */
        __ihm.getSVGLayout().removeSuggestions();
        /* insert new suggestion */
        __ihm.getSVGLayout().insertSuggestions();
        /* regenerate the graph */
        __ihm.getSVGLayout().update();
      });
      $("#"+menuView.listObjectMenu).append(li);
      //$("#viewListNodesAndLinks").append($("

").attr("class","divider"));
    }
};

/**************************************************************************/
/**/
/**/
/* Shortcuts Menu */
/**/
/**/
var graphFuncMenu = function(menu) {
  var buildLiView = function (uri,label,submenu) {

    var icheck = $("")
        .attr("class","glyphicon glyphicon-check");

    var a = $("")
            .attr("href","#")
            .attr("class","small")
            .attr("tabIndex","-1") ;
    if (submenu) {
      a.html($("").append(label+"\t")).append(icheck);
    } else {
      a.html($("").append(label+"\t")).append(icheck);
    }
    var li = $("

");
    li.attr("uri",uri);
    li.css("display","table-cell");
    li.css("vertical-align","middle");
    li.append(a);
    return li;
  };

  let listGraph = __ihm.getAbstraction().listGraphAvailable();

  $.each(listGraph, function(g) {
    let graph = g;
    let li = buildLiView(graph,__ihm.graphname(graph).name,true);
    li.on('click',function() {
        var span = $(this).find(".glyphicon");
        var cur_uri = $(this).attr("uri");
        if ( span.css("visibility") == "visible" ) {
          span.css("visibility","hidden");
          __ihm.getAbstraction().unactiveGraph(cur_uri);
        } else {
          span.css("visibility","visible");
          __ihm.getAbstraction().activeGraph(cur_uri);
        }
        /* update menu view with relations and objects availables */
        __ihm.menus.menuView.reset();
        __ihm.menus.menuView.start();

        /* remove old suggestion */
        __ihm.getSVGLayout().removeSuggestions();
        /* insert new suggestion */
        __ihm.getSVGLayout().insertSuggestions();
        /* regenerate the graph */
        __ihm.getSVGLayout().update();
      });
    $("#"+menu.listObjectMenu).append(li).append($("

"));
  });
};
<commit_msg>use let to replace var<commit_after>/*jshint esversion: 6 */

/*
  Manage Menu View to select and unselect proposition of element/link
*/
class AskomicsMenu {

  constructor (nameMenu,buttonMenu,listObjectMenu,functFillMenu,removeWhenReset=true) {
    this.name = nameMenu;
    this.buttonMenu = buttonMenu;
    this.listObjectMenu = listObjectMenu ;
    this.func = functFillMenu ;
    this.removeWhenReset = removeWhenReset ;
  }

  reset() {
    let menu = this ;
    // Remove onclick
    $("#"+menu.buttonMenu).unbind();
    if (menu.removeWhenReset)
      $("#"+menu.listObjectMenu).empty();
  }

  start() {
    let menu = this ;
    $("#"+menu.buttonMenu).prop('disabled', false);
    $("#"+menu.buttonMenu)
    .on('mousedown', function(event) {
      if ( $("#"+menu.listObjectMenu).is(':visible') ) {
        $("#"+menu.listObjectMenu).slideUp();
      }
      else {
        menu.slideUp();
        $("#"+menu.listObjectMenu).slideDown();
      }
      event.stopPropagation();
    });
    menu.func(menu);
    //hide by default
    $("#"+menu.listObjectMenu).hide();
  }

  slideUp() {
    $("#menuGraph").find("ul").slideUp();
  }
}

/**************************************************************************/
/**/
/**/
/* Shortcuts Menu */
/**/
/**/
var fileFuncMenu = function(menu) {

  $("#dwl-query").on('click', function(d) {
    let date = new Date().getTime();
    $(this).attr("href", "data:application/octet-stream," + encodeURIComponent(__ihm.getGraphBuilder().getInternalState())).attr("download", "query-" + date + ".json");
  });

  $("#dwl-query-sparql").on('click', function(d) {
    let service = new RestServiceJs("getSparqlQueryInTextFormat");
    let jdata = new AskomicsJobsViewManager().prepareQuery();

    let current = this;
    $(current).removeAttr("href");
    service.postsync(jdata,function(data) {
      let date = new Date().getTime();
      $(current).attr("href", "data:application/sparql-query," + encodeURIComponent(data.query)).attr("download", "query-" + date + ".rq");
    });

  });
};

/**************************************************************************/
/**/
/**/
/* Shortcuts Menu */
/**/
/**/
var shortcutsFuncMenu = function(menu) {

  var buildLiView = function (uri,label,submenu) {

    let icheck = $("")
        .attr("class","glyphicon glyphicon-check")
        .css("visibility","hidden");

    let a = $("")
            .attr("href","#")
            .attr("class","small")
            .attr("tabIndex","-1") ;
    if (submenu) {
      a.html($("").append(label+"\t")).append(icheck);
    } else {
      a.html($("").append(label+"\t")).append(icheck);
    }
    let li = $("

");
    li.attr("uri",uri);
    li.css("display","table-cell");
    li.css("vertical-align","middle");
    li.append(a);
    return li;
  };

  let lshortcuts = new ShortcutsParametersView().getAllShortcuts();
  /*
  if (lshortcuts.length <= 0) {
    $("#buttonViewListShortcuts").removeClass('active');
    $("#buttonViewListShortcuts").addClass('disabled');

  } else {
    $("#buttonViewListShortcuts").removeClass('disabled');
    $("#buttonViewListShortcuts").addClass('active');
  }
*/
  //console.log(JSON.stringify(lshortcuts));
  $.each(lshortcuts, function(i) {
    let li = buildLiView(i,lshortcuts[i].label,false);
    __ihm.getSVGLayout().offProposedUri("shortcuts",i);

    li.on('click', function() {
      let span = $(this).find(".glyphicon");
      let cur_uri = $(this).attr("uri");
      if ( span.css("visibility") == "visible" ) {
        span.css("visibility","hidden");
        __ihm.getSVGLayout().offProposedUri("shortcuts",cur_uri);
      } else {
        span.css("visibility","visible");
        __ihm.getSVGLayout().onProposedUri("shortcuts",cur_uri);
      }
      // remove old suggestion
      __ihm.getSVGLayout().removeSuggestions();
      // insert new suggestion
      __ihm.getSVGLayout().insertSuggestions();
      // regenerate the graph
      __ihm.getSVGLayout().update();
    });
    $("#"+menu.listObjectMenu).append(li);
    $("#"+menu.listObjectMenu).append($("

").attr("class","divider"));
    /* next entity */
  });

  /* remove button if no shortcuts */
  if ( Object.keys(lshortcuts).length <= 0 ) {
    $("#"+menu.buttonMenu).prop('disabled', true);
  }

};
/**************************************************************************/
/**/
/**/
/* Shortcuts Menu */
/**/
/**/
var entitiesAndRelationsFuncMenu = function(menu) {
  var buildLiView = function(uri,label,submenu,hidden) {

    let icheck = $("")
        .attr("class","glyphicon glyphicon-check");

    if (hidden) {
      icheck.css("visibility","hidden");
    }
    let a = $("")
            .attr("href","#")
            .attr("class","small")
            .attr("tabIndex","-1") ;
    if (submenu) {
      a.html($("").append(label+"\t")).append(icheck);
    } else {
      a.html($("").append(label+"\t")).append(icheck);
    }
    let li = $("

");
    li.attr("uri",uri);
    li.css("display","table-cell");
    li.css("vertical-align","middle");
    li.append(a);
    return li;
  };
  let menuView = menu;
  //
<input type="checkbox"/> Option 1

  let lentities = Object.keys(__ihm.getAbstraction().getEntities());

  $.each(lentities, function(i) {

    let node = new GraphObject({'uri' : lentities[i]});
    let nodeuri = node.uri;
    let li = buildLiView(nodeuri,node.removePrefix(),false,false);

    li.on('click', function() {
      let span = $(this).find(".glyphicon");
      let cur_uri = $(this).attr("uri");
      if ( span.css("visibility") == "visible" ) {
        span.css("visibility","hidden");
        __ihm.getSVGLayout().offProposedUri("node",cur_uri);
        // disable all predicate associated with this node
        $(this).parent().parent().find("li[nodeuri='"+cur_uri+"']").attr("class","disabled");
      } else {
        span.css("visibility","visible");
        __ihm.getSVGLayout().onProposedUri("node",cur_uri);
        // enable all predicate associated with this node
        $(this).parent().parent().find("li[nodeuri='"+cur_uri+"']").removeAttr("class");
      }
      // remove old suggestion
      __ihm.getSVGLayout().removeSuggestions();
      // insert new suggestion
      __ihm.getSVGLayout().insertSuggestions();
      // regenerate the graph
      __ihm.getSVGLayout().update();
    });

    $("#"+menuView.listObjectMenu).append(li);
    /* --------------------------- */
    /* Adding filter on relations  */
    /* --------------------------- */

    let tab = __ihm.getAbstraction().getRelationsObjectsAndSubjectsWithURI(nodeuri);
    let listRelObj = tab[0];

    $.each(listRelObj, function(objecturi) {
      let object = new GraphObject({uri:objecturi});
      $.each(listRelObj[objecturi], function(idxrel) {
        let rel = listRelObj[objecturi][idxrel];
        let linkRel = new GraphObject({uri:rel});
        let li = buildLiView(rel,linkRel.removePrefix()+"→"+object.removePrefix(),true,false);

        li.attr("nodeuri",nodeuri)
          .on('click', function() {
            /* when this li is unavailable, we can do nothing */
            if ( $(this).attr("class") === "disabled" ) return ;

            let span = $(this).find(".glyphicon");
            let cur_uri = $(this).attr("uri");
            if ( span.css("visibility") == "visible" ) {
             span.css("visibility","hidden");
             __ihm.getSVGLayout().offProposedUri("link",cur_uri);
            } else {
             span.css("visibility","visible");
             __ihm.getSVGLayout().onProposedUri("link",cur_uri);
           }
           /* remove old suggestion */
           __ihm.getSVGLayout().removeSuggestions();
           /* insert new suggestion */
           __ihm.getSVGLayout().insertSuggestions();
           /* regenerate the graph */
           __ihm.getSVGLayout().update();
        });
        $("#"+menuView.listObjectMenu).append(li);
      });
    });
    $("#"+menuView.listObjectMenu).append($("

").attr("class","divider"));
    /* next entity */
  });

  let positionableEntities = __ihm.getAbstraction().getPositionableEntities();
  if (Object.keys(positionableEntities).length>0) {
    /* positionable object */
    let posuri = "positionable";
    let li = buildLiView(posuri,posuri,false,true);
    __ihm.getSVGLayout().offProposedUri("link",posuri);

    li.attr("nodeuri",posuri)
      .on('click', function() {
        let span = $(this).find(".glyphicon");
        let cur_uri = $(this).attr("uri");
        if ( span.css("visibility") == "visible" ) {
          span.css("visibility","hidden");
          __ihm.getSVGLayout().offProposedUri("link",cur_uri);
        } else {
          span.css("visibility","visible");
          __ihm.getSVGLayout().onProposedUri("link",cur_uri);
        }
        /* remove old suggestion */
        __ihm.getSVGLayout().removeSuggestions();
        /* insert new suggestion */
        __ihm.getSVGLayout().insertSuggestions();
        /* regenerate the graph */
        __ihm.getSVGLayout().update();
      });
      $("#"+menuView.listObjectMenu).append(li);
      //$("#viewListNodesAndLinks").append($("

").attr("class","divider"));
    }
};

/**************************************************************************/
/**/
/**/
/* Shortcuts Menu */
/**/
/**/
var graphFuncMenu = function(menu) {
  var buildLiView = function (uri,label,submenu) {

    let icheck = $("")
        .attr("class","glyphicon glyphicon-check");

    let a = $("")
            .attr("href","#")
            .attr("class","small")
            .attr("tabIndex","-1") ;
    if (submenu) {
      a.html($("").append(label+"\t")).append(icheck);
    } else {
      a.html($("").append(label+"\t")).append(icheck);
    }
    let li = $("

");
    li.attr("uri",uri);
    li.css("display","table-cell");
    li.css("vertical-align","middle");
    li.append(a);
    return li;
  };

  let listGraph = __ihm.getAbstraction().listGraphAvailable();

  $.each(listGraph, function(g) {
    let graph = g;
    let li = buildLiView(graph,__ihm.graphname(graph).name,true);
    li.on('click',function() {
        let span = $(this).find(".glyphicon");
        let cur_uri = $(this).attr("uri");
        if ( span.css("visibility") == "visible" ) {
          span.css("visibility","hidden");
          __ihm.getAbstraction().unactiveGraph(cur_uri);
        } else {
          span.css("visibility","visible");
          __ihm.getAbstraction().activeGraph(cur_uri);
        }
        /* update menu view with relations and objects availables */
        __ihm.menus.menuView.reset();
        __ihm.menus.menuView.start();

        /* remove old suggestion */
        __ihm.getSVGLayout().removeSuggestions();
        /* insert new suggestion */
        __ihm.getSVGLayout().insertSuggestions();
        /* regenerate the graph */
        __ihm.getSVGLayout().update();
      });
    $("#"+menu.listObjectMenu).append(li).append($("

"));
  });
};
<|endoftext|>


<commit_before>
/**
 * Internal dependencies
 */
import createDataLayerPush from './createDataLayerPush';

/**
 * Returns a function which, when invoked tracks a single event.
 *
 * @since 1.3.0
 *
 * @param {Object} config          Tracking configuration.
 * @param {Object} dataLayerTarget Data layer parent object.
 * @param {Object} _global         The global window object.
 * @return {Function} Function that tracks an event.
 */
export default function createTrackEvent( config, dataLayerTarget, _global ) {
	const dataLayerPush = createDataLayerPush( dataLayerTarget );

	/**
	 * Send an Analytics tracking event.
	 *
	 * @since 1.3.0
	 *
	 * @param {string} category The category of the event.
	 * @param {string} action   The value that will appear as the event action in Google Analytics Event reports.
	 * @param {string} [label]  The label of the event. Optional.
	 * @param {number} [value]  A non-negative integer that will appear as the event value. Optional.
	 * @return {Promise} Promise that always resolves.
	 */
	return async function trackEvent( category, action, label, value ) {
		const {
			isFirstAdmin,
			referenceSiteURL,
			trackingEnabled,
			trackingID,
			userIDHash,
		} = config;

		if ( _global._gaUserPrefs?.ioo?.() ) {
			return;
		}

		if ( ! trackingEnabled ) {
			// Resolve immediately if tracking is disabled.
			return;
		}

		const eventData = {
			send_to: trackingID,
			event_category: category,
			event_label: label,
			value,
			dimension1: referenceSiteURL,
			dimension2: isFirstAdmin ? 'true' : 'false',
			dimension3: userIDHash,
		};

		return new Promise( ( resolve ) => {
			// This timeout ensures a tracking event does not block the user
			// event if it is not sent (in time).
			// If this fails, it shouldn't reject the promise since event
			// tracking should not result in user-facing errors. It will just
			// trigger a console warning.
			const failTimeout = setTimeout( () => {
				global.console.warn( `Tracking event "${ action }" (category "${ category }") took too long to fire.` );
				resolve();
			}, 1000 );

			dataLayerPush( 'event', action, {
				...eventData,
				event_callback: () => {
					clearTimeout( failTimeout );
					resolve();
				},
			} );
		} );
	};
}
<commit_msg>Update docs for trackEvent.<commit_after>
/**
 * Internal dependencies
 */
import createDataLayerPush from './createDataLayerPush';

/**
 * Returns a function which, when invoked tracks a single event.
 *
 * @since 1.3.0
 *
 * @param {Object} config          Tracking configuration.
 * @param {Object} dataLayerTarget Data layer parent object.
 * @param {Object} _global         The global window object.
 * @return {Function} Function that tracks an event.
 */
export default function createTrackEvent( config, dataLayerTarget, _global ) {
	const dataLayerPush = createDataLayerPush( dataLayerTarget );

	/**
	 * Send an Analytics tracking event.
	 *
	 * @since 1.3.0
	 *
	 * @param {string} category The category of the event.
	 * @param {string} action   The action name of the event.
	 * @param {string} [label]  Optional. The label of the event.
	 * @param {number} [value]  Optional. A non-negative integer that will appear as the event value.
	 * @return {Promise} Promise that always resolves.
	 */
	return async function trackEvent( category, action, label, value ) {
		const {
			isFirstAdmin,
			referenceSiteURL,
			trackingEnabled,
			trackingID,
			userIDHash,
		} = config;

		if ( _global._gaUserPrefs?.ioo?.() ) {
			return;
		}

		if ( ! trackingEnabled ) {
			// Resolve immediately if tracking is disabled.
			return;
		}

		const eventData = {
			send_to: trackingID,
			event_category: category,
			event_label: label,
			value,
			dimension1: referenceSiteURL,
			dimension2: isFirstAdmin ? 'true' : 'false',
			dimension3: userIDHash,
		};

		return new Promise( ( resolve ) => {
			// This timeout ensures a tracking event does not block the user
			// event if it is not sent (in time).
			// If this fails, it shouldn't reject the promise since event
			// tracking should not result in user-facing errors. It will just
			// trigger a console warning.
			const failTimeout = setTimeout( () => {
				global.console.warn( `Tracking event "${ action }" (category "${ category }") took too long to fire.` );
				resolve();
			}, 1000 );

			dataLayerPush( 'event', action, {
				...eventData,
				event_callback: () => {
					clearTimeout( failTimeout );
					resolve();
				},
			} );
		} );
	};
}
<|endoftext|>


<commit_before>/*
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * External dependencies
 */
import styled from 'styled-components';
import {
  useEffect,
  useLayoutEffect,
  useRef,
  useCallback,
  useMemo,
} from 'react';
import PropTypes from 'prop-types';

/**
 * Internal dependencies
 */
import { useStory, useFont, useTransform } from '../../app';
import RichTextEditor from '../../components/richText/editor';
import { getHTMLInfo } from '../../components/richText/htmlManipulation';
import { useUnits } from '../../units';
import {
  elementFillContent,
  elementWithFont,
  elementWithTextParagraphStyle,
  elementWithBackgroundColor,
} from '../shared';
import StoryPropTypes from '../../types';
import { BACKGROUND_TEXT_MODE } from '../../constants';
import useUnmount from '../../utils/useUnmount';
import stripHTML from '../../utils/stripHTML';
import calcRotatedResizeOffset from '../../utils/calcRotatedResizeOffset';
import generatePatternStyles from '../../utils/generatePatternStyles';
import useRichText from '../../components/richText/useRichText';
import { useTransformHandler } from '../../components/transform';
import {
  calcFontMetrics,
  generateParagraphTextStyle,
  getHighlightLineheight,
} from './util';

// Wrapper bounds the text editor within the element bounds. The resize
// logic updates the height of this element to show the new height based
// on the content and properties.
const Wrapper = styled.div`
  ${elementFillContent}
  ${elementWithBackgroundColor}

  span {
    box-decoration-break: clone;
  }
`;

// TextBox defines all text display properties and is used for measuring
// of text height. This element has an unbounded height (bottom) so that
// it can be used for height measurement.
const TextBox = styled.div`
  ${elementWithFont}
  ${elementWithTextParagraphStyle}

  opacity: ${({ opacity }) =>
    typeof opacity !== 'undefined' ? opacity / 100 : null};
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
`;

const Highlight = styled.span`
  ${({ highlightColor }) => generatePatternStyles(highlightColor)};
  color: transparent !important;
  * {
    color: transparent !important;
  }
  padding: ${({ padding }) => padding};
  width: ${({ verticalPadding }) => `calc(100% - ${verticalPadding}px)`};
`;

function TextEdit({
  element,
  box: { x, y, height, rotationAngle },
  editWrapper,
  onResize,
}) {
  const {
    id,
    content,
    backgroundColor,
    backgroundTextMode,
    opacity,
    height: elementHeight,
    ...rest
  } = element;
  const { font } = rest;
  const fontFaceSetConfigs = useMemo(() => {
    const htmlInfo = getHTMLInfo(content);
    return {
      fontStyle: htmlInfo.isItalic ? 'italic' : 'normal',
      fontWeight: htmlInfo.fontWeight,
      content: stripHTML(content),
    };
  }, [content]);

  const {
    dataToEditorX,
    dataToEditorY,
    editorToDataX,
    editorToDataY,
  } = useUnits(
    ({
      actions: { dataToEditorX, dataToEditorY, editorToDataX, editorToDataY },
    }) => ({
      dataToEditorX,
      dataToEditorY,
      editorToDataX,
      editorToDataY,
    })
  );

  const textProps = {
    ...generateParagraphTextStyle(
      rest,
      dataToEditorX,
      dataToEditorY,
      undefined,
      element
    ),
    font,
    element,
    backgroundColor,
    opacity,
    ...(backgroundTextMode === BACKGROUND_TEXT_MODE.HIGHLIGHT && {
      lineHeight: getHighlightLineheight(
        rest.lineHeight,
        dataToEditorX(rest.padding?.vertical || 0)
      ),
      backgroundColor: null,
      highlightColor: backgroundColor,
    }),
    ...(backgroundTextMode === BACKGROUND_TEXT_MODE.NONE && {
      backgroundColor: null,
    }),
  };

  const { padding: _, ...highlightTextProps } = textProps;

  const {
    actions: { maybeEnqueueFontStyle },
  } = useFont();
  const { updateElementById } = useStory((state) => ({
    updateElementById: state.actions.updateElementById,
  }));

  const { isAnythingTransforming } = useTransform((state) => ({
    isAnythingTransforming: state.state.isAnythingTransforming,
  }));

  const setProperties = useCallback(
    (properties) => updateElementById({ elementId: id, properties }),
    [id, updateElementById]
  );

  const wrapperRef = useRef(null);
  const highlightRef = useRef(null);
  const textBoxRef = useRef(null);
  const editorRef = useRef(null);
  const boxRef = useRef();
  const contentRef = useRef();
  const editorHeightRef = useRef(0);

  // x, y, height, rotationAngle changes should not update the content while in edit mode.
  // updateContent should be only called on unmount.
  useEffect(() => {
    boxRef.current = { x, y, height, rotationAngle };
  }, [x, y, height, rotationAngle]);

  // Make sure to allow the user to click in the text box while working on the text.
  const onClick = (evt) => {
    const editor = editorRef.current;
    // Refocus the editor if the container outside it is clicked.
    if (!editor.getNode().contains(evt.target)) {
      editor.focus();
    }
    evt.stopPropagation();
  };

  // Set focus when initially rendered.
  useLayoutEffect(() => {
    if (editorRef.current) {
      editorRef.current.focus();
    }
  }, []);

  const updateContent = useCallback(() => {
    const newHeight = editorHeightRef.current;
    wrapperRef.current.style.height = '';
    if (contentRef.current) {
      // Remove manual line breaks and remember to trim any trailing non-breaking space.
      const properties = { content: contentRef.current };
      // Recalculate the new height and offset.
      if (newHeight) {
        const [dx, dy] = calcRotatedResizeOffset(
          boxRef.current.rotationAngle,
          0,
          0,
          0,
          newHeight - boxRef.current.height
        );
        properties.height = editorToDataY(newHeight);
        properties.x = editorToDataX(boxRef.current.x + dx);
        properties.y = editorToDataY(boxRef.current.y + dy);
      }
      setProperties(properties);
    }
  }, [editorToDataX, editorToDataY, setProperties]);

  // Update content for element on unmount.
  useUnmount(updateContent);

  useEffect(() => {
    // If there are any moveable actions happening, let's update the content
    // Otherwise the font size and measures will not be correct.
    if (isAnythingTransforming) {
      updateContent();
    }
  }, [isAnythingTransforming, updateContent]);

  // A function to remeasure height
  const handleResize = useCallback(() => {
    const wrapper = wrapperRef.current;
    const textBox = textBoxRef.current;
    const { marginOffset } = calcFontMetrics(element);
    editorHeightRef.current =
      textBox.offsetHeight - dataToEditorY(marginOffset);
    wrapper.style.height = `${editorHeightRef.current}px`;
    textBox.style.margin = '';
    if (editWrapper) {
      const [dx, dy] = calcRotatedResizeOffset(
        boxRef.current.rotationAngle,
        0,
        0,
        0,
        editorHeightRef.current - boxRef.current.height
      );
      editWrapper.style.height = `${editorHeightRef.current}px`;
      editWrapper.style.left = `${boxRef.current.x + dx}px`;
      editWrapper.style.top = `${boxRef.current.y + dy}px`;
      onResize && onResize();
    }
  }, [dataToEditorY, editWrapper, element, onResize]);
  // Invoke on each content update.
  const handleUpdate = useCallback(
    (newContent) => {
      contentRef.current = newContent;
      handleResize();
    },
    [handleResize]
  );
  // Also invoke if the raw element height ever changes
  useEffect(handleResize, [elementHeight, handleResize]);

  useEffect(() => {
    maybeEnqueueFontStyle([
      {
        ...fontFaceSetConfigs,
        font,
      },
    ]);
  }, [font, fontFaceSetConfigs, maybeEnqueueFontStyle]);

  useTransformHandler(id, (transform) => {
    const target = textBoxRef.current;
    const wrapper = wrapperRef.current;
    const highlight = highlightRef.current;
    const updatedFontSize = transform?.updates?.fontSize;
    target.style.fontSize = updatedFontSize
      ? `${dataToEditorY(updatedFontSize)}px`
      : '';
    if (highlight) {
      const updatedMargin = transform?.updates?.marginOffset;
      highlight.style.fontSize = target.style.fontSize;
      highlight.style.margin = `${dataToEditorY(-updatedMargin) / 2}px 0`;
      target.style.margin = `${dataToEditorY(-updatedMargin) / 2}px 0`;
    }

    if (transform === null) {
      wrapper.style.width = '';
      wrapper.style.height = '';
    } else {
      const { resize } = transform;
      if (resize && resize[0] !== 0 && resize[1] !== 0) {
        wrapper.style.width = `${resize[0]}px`;
        wrapper.style.height = `${resize[1]}px`;
      }
    }
  });

  const {
    state: { editorState },
    actions: { getContentFromState },
  } = useRichText();

  const editorContent = editorState && getContentFromState(editorState);
  const wrapperBackgroundColor =
    backgroundTextMode === BACKGROUND_TEXT_MODE.FILL && backgroundColor;

  return (
    <Wrapper
      ref={wrapperRef}
      onClick={onClick}
      data-testid="textEditor"
      backgroundColor={wrapperBackgroundColor}
    >
      {editorContent && backgroundTextMode === BACKGROUND_TEXT_MODE.HIGHLIGHT && (
        <TextBox ref={highlightRef} {...highlightTextProps}>
          <Highlight
            dangerouslySetInnerHTML={{ __html: editorContent }}
            {...textProps}
          />
        </TextBox>
      )}
      <TextBox className="syncMargin" ref={textBoxRef} {...textProps}>
        <RichTextEditor
          ref={editorRef}
          content={content}
          onChange={handleUpdate}
        />
      </TextBox>
    </Wrapper>
  );
}

TextEdit.propTypes = {
  element: StoryPropTypes.elements.text.isRequired,
  box: StoryPropTypes.box.isRequired,
  onResize: PropTypes.func,
  editWrapper: PropTypes.object,
};

export default TextEdit;
<commit_msg>Ensure Highlight Background looks the same between edit and display modes.<commit_after>/*
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * External dependencies
 */
import styled from 'styled-components';
import {
  useEffect,
  useLayoutEffect,
  useRef,
  useCallback,
  useMemo,
} from 'react';
import PropTypes from 'prop-types';

/**
 * Internal dependencies
 */
import { useStory, useFont, useTransform } from '../../app';
import RichTextEditor from '../../components/richText/editor';
import { getHTMLInfo } from '../../components/richText/htmlManipulation';
import { useUnits } from '../../units';
import {
  elementFillContent,
  elementWithFont,
  elementWithTextParagraphStyle,
  elementWithBackgroundColor,
} from '../shared';
import StoryPropTypes from '../../types';
import { BACKGROUND_TEXT_MODE } from '../../constants';
import useUnmount from '../../utils/useUnmount';
import stripHTML from '../../utils/stripHTML';
import calcRotatedResizeOffset from '../../utils/calcRotatedResizeOffset';
import generatePatternStyles from '../../utils/generatePatternStyles';
import useRichText from '../../components/richText/useRichText';
import { useTransformHandler } from '../../components/transform';
import {
  calcFontMetrics,
  generateParagraphTextStyle,
  getHighlightLineheight,
} from './util';

// Wrapper bounds the text editor within the element bounds. The resize
// logic updates the height of this element to show the new height based
// on the content and properties.
const Wrapper = styled.div`
  ${elementFillContent}
  ${elementWithBackgroundColor}

  span {
    box-decoration-break: clone;
  }
`;

// TextBox defines all text display properties and is used for measuring
// of text height. This element has an unbounded height (bottom) so that
// it can be used for height measurement.
const TextBox = styled.div`
  ${elementWithFont}
  ${elementWithTextParagraphStyle}

  opacity: ${({ opacity }) =>
    typeof opacity !== 'undefined' ? opacity / 100 : null};
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  width: ${({ verticalPadding }) => `calc(100% - ${verticalPadding}px)`};
`;

const Highlight = styled.span`
  ${({ highlightColor }) => generatePatternStyles(highlightColor)};
  color: transparent !important;
  * {
    color: transparent !important;
  }
  padding: ${({ padding }) => padding};
  width: ${({ verticalPadding }) => `calc(100% - ${verticalPadding}px)`};
`;

function TextEdit({
  element,
  box: { x, y, height, rotationAngle },
  editWrapper,
  onResize,
}) {
  const {
    id,
    content,
    backgroundColor,
    backgroundTextMode,
    opacity,
    height: elementHeight,
    ...rest
  } = element;
  const { font } = rest;
  const fontFaceSetConfigs = useMemo(() => {
    const htmlInfo = getHTMLInfo(content);
    return {
      fontStyle: htmlInfo.isItalic ? 'italic' : 'normal',
      fontWeight: htmlInfo.fontWeight,
      content: stripHTML(content),
    };
  }, [content]);

  const {
    dataToEditorX,
    dataToEditorY,
    editorToDataX,
    editorToDataY,
  } = useUnits(
    ({
      actions: { dataToEditorX, dataToEditorY, editorToDataX, editorToDataY },
    }) => ({
      dataToEditorX,
      dataToEditorY,
      editorToDataX,
      editorToDataY,
    })
  );

  const textProps = {
    ...generateParagraphTextStyle(
      rest,
      dataToEditorX,
      dataToEditorY,
      undefined,
      element
    ),
    font,
    element,
    backgroundColor,
    opacity,
    verticalPadding: dataToEditorX(rest.padding?.vertical || 0),
    ...(backgroundTextMode === BACKGROUND_TEXT_MODE.HIGHLIGHT && {
      lineHeight: getHighlightLineheight(
        rest.lineHeight,
        dataToEditorX(rest.padding?.vertical || 0)
      ),
      backgroundColor: null,
      highlightColor: backgroundColor,
    }),
    ...(backgroundTextMode === BACKGROUND_TEXT_MODE.NONE && {
      backgroundColor: null,
    }),
  };

  const { padding: _, ...highlightTextProps } = textProps;

  const {
    actions: { maybeEnqueueFontStyle },
  } = useFont();
  const { updateElementById } = useStory((state) => ({
    updateElementById: state.actions.updateElementById,
  }));

  const { isAnythingTransforming } = useTransform((state) => ({
    isAnythingTransforming: state.state.isAnythingTransforming,
  }));

  const setProperties = useCallback(
    (properties) => updateElementById({ elementId: id, properties }),
    [id, updateElementById]
  );

  const wrapperRef = useRef(null);
  const highlightRef = useRef(null);
  const textBoxRef = useRef(null);
  const editorRef = useRef(null);
  const boxRef = useRef();
  const contentRef = useRef();
  const editorHeightRef = useRef(0);

  // x, y, height, rotationAngle changes should not update the content while in edit mode.
  // updateContent should be only called on unmount.
  useEffect(() => {
    boxRef.current = { x, y, height, rotationAngle };
  }, [x, y, height, rotationAngle]);

  // Make sure to allow the user to click in the text box while working on the text.
  const onClick = (evt) => {
    const editor = editorRef.current;
    // Refocus the editor if the container outside it is clicked.
    if (!editor.getNode().contains(evt.target)) {
      editor.focus();
    }
    evt.stopPropagation();
  };

  // Set focus when initially rendered.
  useLayoutEffect(() => {
    if (editorRef.current) {
      editorRef.current.focus();
    }
  }, []);

  const updateContent = useCallback(() => {
    const newHeight = editorHeightRef.current;
    wrapperRef.current.style.height = '';
    if (contentRef.current) {
      // Remove manual line breaks and remember to trim any trailing non-breaking space.
      const properties = { content: contentRef.current };
      // Recalculate the new height and offset.
      if (newHeight) {
        const [dx, dy] = calcRotatedResizeOffset(
          boxRef.current.rotationAngle,
          0,
          0,
          0,
          newHeight - boxRef.current.height
        );
        properties.height = editorToDataY(newHeight);
        properties.x = editorToDataX(boxRef.current.x + dx);
        properties.y = editorToDataY(boxRef.current.y + dy);
      }
      setProperties(properties);
    }
  }, [editorToDataX, editorToDataY, setProperties]);

  // Update content for element on unmount.
  useUnmount(updateContent);

  useEffect(() => {
    // If there are any moveable actions happening, let's update the content
    // Otherwise the font size and measures will not be correct.
    if (isAnythingTransforming) {
      updateContent();
    }
  }, [isAnythingTransforming, updateContent]);

  // A function to remeasure height
  const handleResize = useCallback(() => {
    const wrapper = wrapperRef.current;
    const textBox = textBoxRef.current;
    const { marginOffset } = calcFontMetrics(element);
    editorHeightRef.current =
      textBox.offsetHeight - dataToEditorY(marginOffset);
    wrapper.style.height = `${editorHeightRef.current}px`;
    textBox.style.margin = '';
    if (editWrapper) {
      const [dx, dy] = calcRotatedResizeOffset(
        boxRef.current.rotationAngle,
        0,
        0,
        0,
        editorHeightRef.current - boxRef.current.height
      );
      editWrapper.style.height = `${editorHeightRef.current}px`;
      editWrapper.style.left = `${boxRef.current.x + dx}px`;
      editWrapper.style.top = `${boxRef.current.y + dy}px`;
      onResize && onResize();
    }
  }, [dataToEditorY, editWrapper, element, onResize]);
  // Invoke on each content update.
  const handleUpdate = useCallback(
    (newContent) => {
      contentRef.current = newContent;
      handleResize();
    },
    [handleResize]
  );
  // Also invoke if the raw element height ever changes
  useEffect(handleResize, [elementHeight, handleResize]);

  useEffect(() => {
    maybeEnqueueFontStyle([
      {
        ...fontFaceSetConfigs,
        font,
      },
    ]);
  }, [font, fontFaceSetConfigs, maybeEnqueueFontStyle]);

  useTransformHandler(id, (transform) => {
    const target = textBoxRef.current;
    const wrapper = wrapperRef.current;
    const highlight = highlightRef.current;
    const updatedFontSize = transform?.updates?.fontSize;
    target.style.fontSize = updatedFontSize
      ? `${dataToEditorY(updatedFontSize)}px`
      : '';
    if (highlight) {
      const updatedMargin = transform?.updates?.marginOffset;
      highlight.style.fontSize = target.style.fontSize;
      highlight.style.margin = `${dataToEditorY(-updatedMargin) / 2}px 0`;
      target.style.margin = `${dataToEditorY(-updatedMargin) / 2}px 0`;
    }

    if (transform === null) {
      wrapper.style.width = '';
      wrapper.style.height = '';
    } else {
      const { resize } = transform;
      if (resize && resize[0] !== 0 && resize[1] !== 0) {
        wrapper.style.width = `${resize[0]}px`;
        wrapper.style.height = `${resize[1]}px`;
      }
    }
  });

  const {
    state: { editorState },
    actions: { getContentFromState },
  } = useRichText();

  const editorContent = editorState && getContentFromState(editorState);
  const wrapperBackgroundColor =
    backgroundTextMode === BACKGROUND_TEXT_MODE.FILL && backgroundColor;

  return (
    <Wrapper
      ref={wrapperRef}
      onClick={onClick}
      data-testid="textEditor"
      backgroundColor={wrapperBackgroundColor}
    >
      {editorContent && backgroundTextMode === BACKGROUND_TEXT_MODE.HIGHLIGHT && (
        <TextBox ref={highlightRef} {...highlightTextProps}>
          <Highlight
            dangerouslySetInnerHTML={{ __html: editorContent }}
            {...textProps}
          />
        </TextBox>
      )}
      <TextBox className="syncMargin" ref={textBoxRef} {...textProps}>
        <RichTextEditor
          ref={editorRef}
          content={content}
          onChange={handleUpdate}
        />
      </TextBox>
    </Wrapper>
  );
}

TextEdit.propTypes = {
  element: StoryPropTypes.elements.text.isRequired,
  box: StoryPropTypes.box.isRequired,
  onResize: PropTypes.func,
  editWrapper: PropTypes.object,
};

export default TextEdit;
<|endoftext|>


<commit_before>$(function(){

    window.TaskView = Backbone.View.extend({
      tagName: 'div',
      className: 'task',

      initialize: function() {
	      this.model.bind('change', this.render, this);
	      this.model.view = this;
	  },

      events: {
	     "click div.task-details"   : "showDetails",
	     "click div.description .content" : "editDescription",
	     "keypress .description-input" : "updateDescription"
	  },

	  showDetails: function(e) {
          var view = new TaskDetailsView({model: this.model});
          $("#projects-side").html(view.render().el);
	  },

	  editDescription: function(e) {
		  //alert("click");
		  $("div.description", this.el).addClass("editing");
		  input = $("input", $(this.el));
		  input.val(this.model.get('description'));
		  input.focus();

	  },

	  updateDescription: function(e) {
		  if (e.keyCode != 13) return;
		  $(".description", this.el).removeClass("editing");
		  value = $("input", $(this.el)).val();
		  this.model.save({"description": value});
	  },

      render: function(){
    	  var task = this.model.toJSON();
    	  $(this.el).addClass('tr');
    	  $(this.el).attr("id", "task-" + task.id);
          $(this.el).html(djProject.templates.taskTemplate({task: task}));
          return this;
      }
    });

    window.CommentView = Backbone.View.extend({
        tagName: 'li',
        className: 'comment',

        initialize: function() {
  	      this.model.bind('change', this.render, this);
  	      this.model.view = this;
  	    },

        render: function(){
      	  var comment = this.model.toJSON();
          $(this.el).html(djProject.templates.commentTemplate({comment: comment}));
          return this;
        }
    });

    window.TaskDetailsView = Backbone.View.extend({
        tagName: 'div',
        className: 'task',

        initialize: function() {
  	      this.model.bind('change', this.render, this);
  	      this.model.view = this;

    	  this.comments = new window.Comments({task: this.model});
    	  this.comments.bind('refresh', this.addComments);
    	  this.comments.view = this;
    	  window.comments = this.comments;

  	  	},

  	  	events: {
          //"keypress #new-todo":  "createOnEnter",
          //"keyup #new-todo":     "showTooltip",
          "keypress #new-comment":  "createOnEnter"
  	  	},

	  	addComments: function(){
	  		  $('#comments-list').html('');
	    	  this.each(this.view.addComment);
	    },

	    addComment: function(comment){
	          var view = new CommentView({model: comment});
	          $('#comments-list').append(view.render().el);
	    },

        render: function(){
      	    var task = this.model;
      	    $(this.el).addClass('tr');
      	    $(this.el).addClass('task');
      	    $(this.el).attr("id", "task-" + task.get('id'));
            $(this.el).html(djProject.templates.taskDetailsTemplate({task: task.toJSON()}));
            //get comments
            this.comments.filtered(task);
            return this;
        },

        createOnEnter: function(e){
      	    if (e.keyCode != 13) return;
      	    comment =  {}

      	    comment['task'] = this.model.get('resource_uri');
      	    comment['comment'] = $("#new-comment").val();
      	    comment['user'] = USER_URI;

      	    this.comments.create(comment);
      	    $("#new-comment").val('');
        }
    });

    window.SprintView = Backbone.View.extend({
        tagName: 'li',
        className: 'sprint',

	    initialize: function(options) {
	        this.model.bind('change', this.render, this);
	        this.model.view = this;
	    },

	    events: {
	        "click div.sprint"   : "showSprint",
	    },

	    showSprint: function() {
	    	window.tasks.filtered(null, this.model);
	    },

        render: function() {
            $(this.el).html(djProject.templates.sprintTemplate({sprint: this.model.toJSON()}));
            return this;
        }
      });

    window.ProjectView = Backbone.View.extend({
      tagName: 'li',
      classname: 'project',

      initialize: function() {
    	  this.model.bind('change', this.render, this);
    	  this.model.view = this;
    	  this.sprints = new window.Sprints({project: this.model});
    	  this.sprints.bind('refresh', this.addSprints);
    	  this.sprints.view = this;
    	  //this.model.sprint.bind('all', this.render, this);

      },

      events: {
    	  "click div.project"   : "showProject",
          "click div.backlog"   : "showBacklog",
	  },

      addSprints: function(){
    	  $(this.view.el).filter('.project-sprints').html('');
    	  this.each(this.view.addSprint);
      },

      addSprint: function(sprint){
          var view = new SprintView({model: sprint});
          $('ul[data-uri="'+sprint.get('project_uri')+'"]').prepend(view.render().el);
      },

      showProject: function() {
	    	window.tasks.filtered(this.model.get("id"));
	  },

	  showBacklog: function() {
	    	window.tasks.filtered(this.model.get("id"), 'backlog');
	  },

      render: function() {
          $(this.el).html(djProject.templates.projectTemplate({project: this.model.toJSON()}));
          this.sprints.fetch();
          return this;
      }
    });

    window.App = Backbone.View.extend({
      el: $('#main'),

      initialize: function() {
          _.bindAll(this, 'render');
          window.tasks = new window.Tasks();
          window.tasks.bind('refresh', this.addTasks, this);
          window.tasks.bind('all', this.render, this);
          window.tasks.fetch();

          window.projects = new window.Projects();
          window.projects.bind('refresh', this.addProjects, this);
          window.projects.bind('all', this.render, this);
          window.projects.fetch();
          window.current_project = null;
          window.current_sprint = null;

          $("#project-create").colorbox({width:"300px", height:"200px", iframe:true});

      },

      events: {
          //"keypress #new-todo":  "createOnEnter",
          //"keyup #new-todo":     "showTooltip",
          "click .project-link a": "projectTasks",
          "keypress #new-task":  "createOnEnter"
       },

      addTasks: function(){
    	  $('#projects-tasks').html(djProject.templates.tasksTableHeader({
    		  project: window.current_project,
    		  sprint: window.current_sprint
    	  }));
          window.tasks.each(window.app.addTask);
          window.app.input = $("#new-task");
      },

      addTask: function(task){
          var view = new TaskView({model: task});
          this.$('#projects-tasks-container').append(view.render().el);
      },

      addProjects: function(){
          window.projects.each(window.app.addProject);
      },

      addProject: function(project){
          var view = new ProjectView({model: project});
          this.$('#projects-container').prepend(view.render().el);
      },
      newAttributes: function() {

          data =  {}
          if (window.current_project) {
        	  data['project'] = window.current_project.get('resource_uri');
          }

          if (window.current_sprint) {
        	  data['sprint'] = window.current_sprint.get('resource_uri');
          }
          data['description'] = window.app.input.val();
          return data;
      },
      createOnEnter: function(e){
    	  if (e.keyCode != 13) return;
          window.tasks.create(this.newAttributes());
          this.input.val('');
      }

    });

    window.app = new App();
});<commit_msg>inline edit description<commit_after>$(function(){

    window.TaskView = Backbone.View.extend({
      tagName: 'div',
      className: 'task',

      initialize: function() {
	      this.model.bind('change', this.render);
	      this.model.view = this;
	  },

      events: {
	     "click div.task-details"   : "showDetails",
	     "click div.description .content" : "editDescription",
	     "keypress .description-input" : "updateDescription"
	  },

	  showDetails: function(e) {
          var view = new TaskDetailsView({model: this.model});
          $("#projects-side").html(view.render().el);
	  },

	  editDescription: function(e) {
		  //alert("click");
		  $("div.description", this.el).addClass("editing");
		  input = $("input", $(this.el));
		  input.val(this.model.get('description'));
		  input.focus();

	  },

	  updateDescription: function(e) {
		  if (e.keyCode != 13) return;
		  $(".description", this.el).removeClass("editing");
		  value = $("input", $(this.el)).val();
		  this.model.save({"description": value});
	  },

      render: function(){
    	  if (!this.model) return;
    	  var task = this.model.toJSON();
    	  $(this.el).addClass('tr');
    	  $(this.el).attr("id", "task-" + task.id);
          $(this.el).html(djProject.templates.taskTemplate({task: task}));
          return this;
      }
    });

    window.CommentView = Backbone.View.extend({
        tagName: 'li',
        className: 'comment',

        initialize: function() {
  	      this.model.bind('change', this.render, this);
  	      this.model.view = this;
  	    },

        render: function(){
      	  var comment = this.model.toJSON();
          $(this.el).html(djProject.templates.commentTemplate({comment: comment}));
          return this;
        }
    });

    window.TaskDetailsView = Backbone.View.extend({
        tagName: 'div',
        className: 'task',

        initialize: function() {
  	      this.model.bind('change', this.render, this);
  	      this.model.view = this;

    	  this.comments = new window.Comments({task: this.model});
    	  this.comments.bind('refresh', this.addComments);
    	  this.comments.view = this;
    	  window.comments = this.comments;

  	  	},

  	  	events: {
          //"keypress #new-todo":  "createOnEnter",
          //"keyup #new-todo":     "showTooltip",
          "keypress #new-comment":  "createOnEnter"
  	  	},

	  	addComments: function(){
	  		  $('#comments-list').html('');
	    	  this.each(this.view.addComment);
	    },

	    addComment: function(comment){
	          var view = new CommentView({model: comment});
	          $('#comments-list').append(view.render().el);
	    },

        render: function(){
      	    var task = this.model;
      	    $(this.el).addClass('tr');
      	    $(this.el).addClass('task');
      	    $(this.el).attr("id", "task-" + task.get('id'));
            $(this.el).html(djProject.templates.taskDetailsTemplate({task: task.toJSON()}));
            //get comments
            this.comments.filtered(task);
            return this;
        },

        createOnEnter: function(e){
      	    if (e.keyCode != 13) return;
      	    comment =  {}

      	    comment['task'] = this.model.get('resource_uri');
      	    comment['comment'] = $("#new-comment").val();
      	    comment['user'] = USER_URI;

      	    this.comments.create(comment);
      	    $("#new-comment").val('');
        }
    });

    window.SprintView = Backbone.View.extend({
        tagName: 'li',
        className: 'sprint',

	    initialize: function(options) {
	        this.model.bind('change', this.render, this);
	        this.model.view = this;
	    },

	    events: {
	        "click div.sprint"   : "showSprint",
	    },

	    showSprint: function() {
	    	window.tasks.filtered(null, this.model);
	    },

        render: function() {
            $(this.el).html(djProject.templates.sprintTemplate({sprint: this.model.toJSON()}));
            return this;
        }
      });

    window.ProjectView = Backbone.View.extend({
      tagName: 'li',
      classname: 'project',

      initialize: function() {
    	  this.model.bind('change', this.render, this);
    	  this.model.view = this;
    	  this.sprints = new window.Sprints({project: this.model});
    	  this.sprints.bind('refresh', this.addSprints);
    	  this.sprints.view = this;
    	  //this.model.sprint.bind('all', this.render, this);

      },

      events: {
    	  "click div.project"   : "showProject",
          "click div.backlog"   : "showBacklog",
	  },

      addSprints: function(){
    	  $(this.view.el).filter('.project-sprints').html('');
    	  this.each(this.view.addSprint);
      },

      addSprint: function(sprint){
          var view = new SprintView({model: sprint});
          $('ul[data-uri="'+sprint.get('project_uri')+'"]').prepend(view.render().el);
      },

      showProject: function() {
	    	window.tasks.filtered(this.model.get("id"));
	  },

	  showBacklog: function() {
	    	window.tasks.filtered(this.model.get("id"), 'backlog');
	  },

      render: function() {
          $(this.el).html(djProject.templates.projectTemplate({project: this.model.toJSON()}));
          this.sprints.fetch();
          return this;
      }
    });

    window.App = Backbone.View.extend({
      el: $('#main'),

      initialize: function() {
          _.bindAll(this, 'render');
          window.tasks = new window.Tasks();
          window.tasks.bind('refresh', this.addTasks, this);
          window.tasks.bind('all', this.render, this);
          window.tasks.fetch();

          window.projects = new window.Projects();
          window.projects.bind('refresh', this.addProjects, this);
          window.projects.bind('all', this.render, this);
          window.projects.fetch();
          window.current_project = null;
          window.current_sprint = null;

          $("#project-create").colorbox({width:"300px", height:"200px", iframe:true});

      },

      events: {
          //"keypress #new-todo":  "createOnEnter",
          //"keyup #new-todo":     "showTooltip",
          "click .project-link a": "projectTasks",
          "keypress #new-task":  "createOnEnter"
       },

      addTasks: function(){
    	  $('#projects-tasks').html(djProject.templates.tasksTableHeader({
    		  project: window.current_project,
    		  sprint: window.current_sprint
    	  }));
          window.tasks.each(window.app.addTask);
          window.app.input = $("#new-task");
      },

      addTask: function(task){
          var view = new TaskView({model: task});
          this.$('#projects-tasks-container').append(view.render().el);
      },

      addProjects: function(){
          window.projects.each(window.app.addProject);
      },

      addProject: function(project){
          var view = new ProjectView({model: project});
          this.$('#projects-container').prepend(view.render().el);
      },
      newAttributes: function() {

          data =  {}
          if (window.current_project) {
        	  data['project'] = window.current_project.get('resource_uri');
          }

          if (window.current_sprint) {
        	  data['sprint'] = window.current_sprint.get('resource_uri');
          }
          data['description'] = window.app.input.val();
          return data;
      },
      createOnEnter: function(e){
    	  if (e.keyCode != 13) return;
          window.tasks.create(this.newAttributes());
          this.input.val('');
      }

    });

    window.app = new App();
});<|endoftext|>


<commit_before>'use strict'

var miss = require('mississippi')
var Wreck = require('wreck')
var generateToken = require('../lib/generate-token')
var config = require('../config')
var token = generateToken({key: config.JWT_KEY, payload: {system: 'laurentius'}})
var wreckOptions = {
  json: true,
  headers: {
    Authorization: token
  }
}

var sendStatusMessage = miss.through(function (chunck, encoding, callback) {
  var item = JSON.parse(chunck)
  console.log(item)

  if (item.CALLBACK_STATUS_URL) {
    console.log(item._id + ': send-status-message')
    wreckOptions.payload = JSON.stringify({status: config.CALLBACK_STATUS_MESSAGE})
    Wreck.post(item.CALLBACK_STATUS_URL, wreckOptions, function (error, response, payload) {
      if (error) {
        return callback(error, null)
      } else {
        return callback(null, JSON.stringify(item))
      }
    })
  } else {
    console.log(item._id + ': send-status-message No message to send')
    return callback(null, JSON.stringify(item))
  }
})

module.exports = sendStatusMessage
<commit_msg>Removed logging<commit_after>'use strict'

var miss = require('mississippi')
var Wreck = require('wreck')
var generateToken = require('../lib/generate-token')
var config = require('../config')
var token = generateToken({key: config.JWT_KEY, payload: {system: 'laurentius'}})
var wreckOptions = {
  json: true,
  headers: {
    Authorization: token
  }
}

var sendStatusMessage = miss.through(function (chunck, encoding, callback) {
  var item = JSON.parse(chunck)

  if (item.CALLBACK_STATUS_URL) {
    console.log(item._id + ': send-status-message')
    wreckOptions.payload = JSON.stringify({status: config.CALLBACK_STATUS_MESSAGE})
    Wreck.post(item.CALLBACK_STATUS_URL, wreckOptions, function (error, response, payload) {
      if (error) {
        return callback(error, null)
      } else {
        return callback(null, JSON.stringify(item))
      }
    })
  } else {
    console.log(item._id + ': send-status-message No message to send')
    return callback(null, JSON.stringify(item))
  }
})

module.exports = sendStatusMessage
<|endoftext|>


<commit_before>const AppTokenUtil = {
  getAppTokensBasedOnQuery: getAppTokensBasedOnQuery
};

function getAppTokensBasedOnQuery(query, desktopAppId) {
  let userDisabledMap = new Map();
  let userIdsSet = new Set();

  let appTokens = Push.appTokens.find(query).fetch();

  if (!appTokens.length) {
    return [];
  }

  appTokens.forEach(function (appToken) {
    if (appToken.userId) {
      userIdsSet.add(appToken.userId);
    }
  });

  let vet = GlobalVets.findOne({appIdentifier: appTokens[0].appName});

  if (!vet && desktopAppId) {
    vet = GlobalVets.findOne({_id: desktopAppId});
  }

  if (!vet) {
    console.log(`Couldn't find vet for id ${desktopAppId} or app identifier ${appTokens[0].appName}`);
    return false;
  }

  let users = Meteor.users.find({_id: {$in: [...userIdsSet]}}).fetch();

  users.forEach(user => {
    let isUserDisabled = user.accountDisabledPerVet && user.accountDisabledPerVet[vet._id];
    userDisabledMap.set(user._id, isUserDisabled);
  });

  return appTokens.filter(appToken => {
    return !(appToken.userId && userDisabledMap.get(appToken.userId));
  });

}

export {AppTokenUtil};
<commit_msg>Remove vet check for desktop notifications in AppTokenUtil.<commit_after>const AppTokenUtil = {
  getAppTokensBasedOnQuery: getAppTokensBasedOnQuery
};

function getAppTokensBasedOnQuery(query, desktopAppId) {
  let userDisabledMap = new Map();
  let userIdsSet = new Set();

  let appTokens = Push.appTokens.find(query).fetch();

  if (!appTokens.length) {
    return [];
  }

  if (desktopAppId) {
    return appTokens;
  }

  appTokens.forEach(function (appToken) {
    if (appToken.userId) {
      userIdsSet.add(appToken.userId);
    }
  });

  let vet = GlobalVets.findOne({appIdentifier: appTokens[0].appName});

  if (!vet) {
    return [];
  }

  let users = Meteor.users.find({_id: {$in: [...userIdsSet]}}).fetch();

  users.forEach(user => {
    let isUserDisabled = user.accountDisabledPerVet && user.accountDisabledPerVet[vet._id];
    userDisabledMap.set(user._id, isUserDisabled);
  });

  return appTokens.filter(appToken => {
    return !(appToken.userId && userDisabledMap.get(appToken.userId));
  });

}

export {AppTokenUtil};
<|endoftext|>