define(["ng.cla.core.lmsg","cla_angular","/intranet/projects/js/built/projects.libs.js","jquery","ng.cla.core.breadcrumb","user_picker","ng.cla.core.html_editor","url-parse","ng.cla.core.user_picker"], function(__WEBPACK_EXTERNAL_MODULE_0__, __WEBPACK_EXTERNAL_MODULE_1__, __WEBPACK_EXTERNAL_MODULE_2__, __WEBPACK_EXTERNAL_MODULE_3__, __WEBPACK_EXTERNAL_MODULE_4__, __WEBPACK_EXTERNAL_MODULE_5__, __WEBPACK_EXTERNAL_MODULE_7__, __WEBPACK_EXTERNAL_MODULE_8__, __WEBPACK_EXTERNAL_MODULE_13__) { return /******/ (function(modules) { // webpackBootstrap
/******/ 	// The module cache
/******/ 	var installedModules = {};
/******/
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/
/******/ 		// Check if module is in cache
/******/ 		if(installedModules[moduleId]) {
/******/ 			return installedModules[moduleId].exports;
/******/ 		}
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = installedModules[moduleId] = {
/******/ 			i: moduleId,
/******/ 			l: false,
/******/ 			exports: {}
/******/ 		};
/******/
/******/ 		// Execute the module function
/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ 		// Flag the module as loaded
/******/ 		module.l = true;
/******/
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
/******/
/******/
/******/ 	// expose the modules object (__webpack_modules__)
/******/ 	__webpack_require__.m = modules;
/******/
/******/ 	// expose the module cache
/******/ 	__webpack_require__.c = installedModules;
/******/
/******/ 	// identity function for calling harmony imports with the correct context
/******/ 	__webpack_require__.i = function(value) { return value; };
/******/
/******/ 	// define getter function for harmony exports
/******/ 	__webpack_require__.d = function(exports, name, getter) {
/******/ 		if(!__webpack_require__.o(exports, name)) {
/******/ 			Object.defineProperty(exports, name, {
/******/ 				configurable: false,
/******/ 				enumerable: true,
/******/ 				get: getter
/******/ 			});
/******/ 		}
/******/ 	};
/******/
/******/ 	// getDefaultExport function for compatibility with non-harmony modules
/******/ 	__webpack_require__.n = function(module) {
/******/ 		var getter = module && module.__esModule ?
/******/ 			function getDefault() { return module['default']; } :
/******/ 			function getModuleExports() { return module; };
/******/ 		__webpack_require__.d(getter, 'a', getter);
/******/ 		return getter;
/******/ 	};
/******/
/******/ 	// Object.prototype.hasOwnProperty.call
/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ 	// __webpack_public_path__
/******/ 	__webpack_require__.p = "/intranet/projects/js/built/";
/******/
/******/ 	// Load entry module and return exports
/******/ 	return __webpack_require__(__webpack_require__.s = 14);
/******/ })
/************************************************************************/
/******/ ({

/***/ "../../../node_modules/css-loader/index.js!../../../node_modules/sass-loader/lib/loader.js!./assets/css/ng-sortable.scss":
/***/ (function(module, exports, __webpack_require__) {

exports = module.exports = __webpack_require__("../../../node_modules/css-loader/lib/css-base.js")();
// imports


// module
exports.push([module.i, "/* ************************************** */\n/* Mandatory CSS required for ng-sortable */\n/* ************************************** */\n.as-sortable-item, .as-sortable-placeholder {\n  display: block;\n}\n\n.as-sortable-item {\n  -ms-touch-action: none;\n  touch-action: none;\n}\n\n.js-draggable .as-sortable-item-handle {\n  cursor: move;\n}\n\n.as-sortable-drag {\n  position: absolute;\n  pointer-events: none;\n  z-index: 9999;\n}\n\n.as-sortable-hidden {\n  display: none !important;\n}\n\n.as-sortable-un-selectable {\n  user-select: none;\n}\n\n/* Disables 'move' when a list item can't be moved due to permissions or screen size */\n.as-sortable-item .list-draggable-area[data-no-drag=true] {\n  cursor: default;\n}", ""]);

// exports


/***/ }),

/***/ "../../../node_modules/css-loader/index.js!../../../node_modules/sass-loader/lib/loader.js!./assets/css/style.scss":
/***/ (function(module, exports, __webpack_require__) {

exports = module.exports = __webpack_require__("../../../node_modules/css-loader/lib/css-base.js")();
// imports


// module
exports.push([module.i, ".task-section-edit-colour {\n  display: inline-block;\n}\n\n.tasks-board {\n  overflow-x: scroll;\n  overflow-y: hidden;\n}\n\n.tasks-board-scrollable {\n  display: flex;\n  flex-flow: row nowrap;\n  width: fit-content;\n  position: relative;\n}\n\n.task-board-list {\n  padding: 10px 0;\n}\n\n.status-dot {\n  height: 18px;\n  width: 18px;\n  display: block;\n  border-radius: 10rem;\n}\n\n.status-dot-history {\n  height: 10px;\n  width: 10px;\n  display: inline-block;\n  border-radius: 10rem;\n}\n\n.board-status-column.board-status-header {\n  background-color: hsl(204, 45%, 98%);\n  padding: 10px;\n  vertical-align: middle;\n  color: hsl(218, 21%, 23%);\n}\n\n.board-status-column {\n  width: 300px;\n  display: inline-block;\n  height: 100%;\n  background-color: hsl(204, 45%, 98%);\n  margin: 0 5px;\n  min-height: 40px;\n  border-radius: 5px;\n}\n\n.board-status-media {\n  overflow: visible;\n}\n\n/* Custom styling for the board column rename form input */\n.board-status-media .board-status-input {\n  width: 120px;\n  height: 30px;\n}\n\n.btn-board-status {\n  padding-top: 3px;\n  padding-bottom: 3px;\n}\n\n/* Board mode task item styling  */\n.task-item.board-task {\n  margin: 10px;\n}\n\n.task-item.list-task {\n  padding: 0.25rem 0.5rem;\n  margin-bottom: -1px;\n  border: 1px solid hsl(214, 32%, 91%);\n}\n\n.task-item.list-task .task-item-complete {\n  text-decoration: line-through;\n}\n\n.task-item.list-task .task-item-icon {\n  font-size: 1.15rem;\n  vertical-align: middle;\n}\n\n.task-item-icon-gray {\n  color: hsl(219, 10%, 49%);\n}\n\n.task-item-text {\n  color: hsl(219, 15%, 35%);\n}\n\n.board-task {\n  position: relative;\n  margin: 10px;\n}\n\n.board-task .board-task-title a {\n  color: hsl(218, 21%, 23%);\n}\n\n.board-task-drop-container {\n  display: inline-block;\n  height: 100%;\n  width: 100%;\n}\n\n.as-sortable-dragging,\n.as-sortable-dragging .task-item.board-task {\n  background: white;\n  position: relative;\n}\n\n.as-sortable-dragging .task-item.board-task .card {\n  box-shadow: 0px 12px 8px -6px rgba(0, 0, 0, 0.15);\n}\n\n.project-header .avatar {\n  margin-right: 5px;\n  width: 30px;\n  border-radius: 15px;\n}\n\n.menu-wrapper {\n  float: right;\n  margin-left: 5px;\n  margin-top: 5px;\n}\n\n.project-header-options {\n  float: right;\n  margin-top: 8px;\n}\n\n.header-row {\n  margin-bottom: 10px;\n}\n\n.projects.details .btn-rag {\n  border: none;\n  padding: 0;\n  font-size: 15px;\n  color: hsl(219, 15%, 35%);\n  background: hsl(210, 38%, 95%);\n  height: 30px;\n  width: 30px;\n  margin-left: 5px;\n  border-radius: 10rem;\n  font-weight: bold;\n}\n\n/* Changes text colour of active RAG item to #fff */\n.projects.details .btn-rag.active {\n  color: #fff;\n}\n\n.project-description img {\n  max-width: 100%;\n  height: auto !important;\n}\n\n.sub-header {\n  text-align: right;\n}\n\n.rag-status {\n  display: inline-block;\n}\n\n.project-image {\n  border-radius: var(--theme-rounded-corners);\n  max-width: 185px;\n}\n\n@media only screen and (max-width: 768px) {\n  .sub-header {\n    text-align: left;\n  }\n}\n.project-more-info {\n  margin-top: 10px;\n}\n\n.project-update-icon {\n  box-shadow: 0 0 9px 5px rgba(0, 0, 0, 0.07);\n  border-radius: 10rem;\n  padding: 0.6rem;\n  display: block;\n}\n\n.project-summary img {\n  border-radius: 50%;\n}\n\n.project-summary small {\n  display: block;\n}\n\n.tab-content .panel {\n  margin-top: 10px;\n}\n\n.tab-content .panel h3 {\n  margin: 5px 0;\n}\n\n.project-progress {\n  background-color: hsl(210, 38%, 95%);\n  padding: 15px 15px 0;\n}\n\n.project-list-details .project-progress {\n  padding-bottom: 15px;\n}\n\n.progress {\n  margin: 0;\n  height: 6px;\n  background-color: hsl(210, 38%, 95%);\n  border-radius: 0;\n  box-shadow: none;\n}\n\n.progress-bar {\n  box-shadow: none;\n}\n\n.files-show-more {\n  margin-top: 15px;\n  padding: 5px 10px;\n  display: block;\n  border: 1px solid hsl(210, 38%, 95%);\n  text-align: center;\n  -webkit-border-radius: 4px;\n  -moz-border-radius: 4px;\n  border-radius: 4px;\n}\n\n.files-show-more:hover {\n  border-color: hsl(214, 32%, 91%);\n  background-color: hsl(204, 45%, 98%);\n  text-decoration: none;\n}\n\n/* sections */\n.new-section {\n  border-bottom: 1px solid hsl(214, 32%, 91%);\n  background-color: hsl(204, 45%, 98%);\n}\n\n/* task list */\n.task-list-section {\n  margin-bottom: 0;\n}\n\n.task-list-section .panel-heading {\n  position: relative;\n  overflow: visible;\n}\n\n.task-list-section .kolorPicker,\n.task-list-section .kolorPicker-wrapper {\n  display: inline-block;\n}\n\n.task-list-items {\n  min-height: 10px; /* Used to keep a drag+drop placeholder visible when list is empty */\n  margin-bottom: 0;\n}\n\n/* Allows board cards to be dragged between status columns when empty */\n.board-status-column [as-sortable=\"ctrl.dragTaskListeners\"] {\n  min-height: 130px;\n  height: 100%;\n}\n\n/* Aligns text in add task button to the left, overrides standard .btn-block styling */\n.btn.btn-add-task {\n  text-align: left;\n}\n\n.task-list-item .sortable {\n  cursor: move;\n}\n\n@media only screen and (max-width: 767px) {\n  .task-list-section .form-inline > input {\n    margin-bottom: 10px;\n  }\n}\n.task-item .checkbox-inline {\n  margin-top: -22px;\n}\n\n.task-list-item .section {\n  min-width: 40px;\n  min-height: 1px;\n  margin-top: -7px;\n  display: block;\n  float: right;\n}\n\n.team-role-variant-1 {\n  background-color: hsl(0, 74%, 57%);\n}\n\n.team-role-variant-2 {\n  background-color: hsl(237, 45%, 52%);\n}\n\n.team-role-variant-2 ~ .team-role-variant-2 {\n  background-color: hsl(143, 53%, 62%);\n}\n\n.team-role-variant-3 {\n  background-color: hsl(207, 71%, 57%);\n}\n\n.team-role-variant-4 {\n  background-color: hsl(179, 49%, 39%);\n}\n\n.team-role-variant-5 {\n  background-color: hsl(152, 44%, 28%);\n}\n\n.team-role-variant-6 {\n  background-color: hsl(148, 46%, 43%);\n}\n\n.team-role-variant-7 {\n  background-color: hsl(33, 88%, 65%);\n}\n\n.team-role-variant-8 {\n  background-color: hsl(0, 59%, 48%);\n}\n\n.team-role-variant-8 ~ .team-role-variant-8 {\n  background-color: hsl(242, 36%, 41%);\n}\n\n.team-role-variant-9 {\n  background-color: hsl(16, 63%, 37%);\n}\n\n.team-role-variant-10 {\n  background-color: hsl(218, 21%, 23%);\n}\n\n.task-duration-unit {\n  padding-top: 7px;\n}\n\n.task-duration-unit.hide-unit {\n  visibility: hidden;\n}\n\n/* READY FOR CONVERSION TO SCSS */\n@media only screen and (min-width: 768px) {\n  .project-info {\n    display: flex;\n  }\n}\n.project-info {\n  margin-bottom: 10px;\n}\n\n.project-info .project-info-left {\n  position: relative;\n}\n\n.project-info-left::after {\n  content: \"\";\n  width: 1px;\n  top: 0;\n  bottom: 0;\n  right: 0;\n  background: hsl(210, 38%, 95%);\n  position: absolute;\n  margin: 0 7px;\n}\n\n@media only screen and (max-width: 768px) {\n  .project-info .project-info-left {\n    margin-bottom: 15px;\n    padding-bottom: 15px;\n  }\n  .project-info .project-info-left::after {\n    left: 0;\n    top: unset;\n    height: 1px;\n    width: auto;\n    margin: 0 15px;\n  }\n}\n/* Allows media to display overflow so custom border can be displayed on meta data */\n.meta-custom-wrapper {\n  overflow: visible;\n}\n\n.meta-custom {\n  position: relative;\n}\n\n/* Adds left-hand side border to meta blocks */\n.meta-custom::after {\n  content: \"\";\n  top: 0;\n  bottom: 10px;\n  left: 0;\n  border-left: 1px solid hsl(210, 38%, 95%);\n  position: absolute;\n  margin-left: -10px;\n}\n\n/* Hides left hand border on smaller screens */\n@media only screen and (max-width: 768px) {\n  .meta-custom::after {\n    display: none;\n  }\n}\n/* Adds custom margin to the bottom of the 'last modified' text so the 'created on' text aligns with the RAG status */\n.meta-custom-spacing {\n  margin-bottom: 18px;\n}\n\n/* Resets custom margin on smaller screens */\n@media only screen and (max-width: 768px) {\n  .meta-custom-spacing {\n    margin-bottom: 10.5px;\n  }\n}\n.loading-table {\n  opacity: 0.4;\n}\n\n.team-list-spinner {\n  left: 50%;\n  top: 50%;\n}\n\n.tasks-profile-img {\n  width: 25px;\n  height: 25px;\n}\n\n.btn.btn-custom-due-date {\n  padding-left: 0;\n}\n\n/* Custom position of completed toggle switch which aligns it right on desktop and left on smaller screens */\n.custom-toggle-position {\n  text-align: right;\n}\n\n@media only screen and (max-width: 768px) {\n  .custom-toggle-position {\n    text-align: left;\n  }\n}\n/* Adds custom styling to task priotity badge so it is vertically aligned with other items */\n.task-badge {\n  margin-right: 10px;\n  margin-top: 10px;\n  display: inline-block;\n}\n\n.delete-confirm-icon {\n  line-height: 70px;\n  font-size: 50px;\n  color: hsl(219, 10%, 49%);\n}\n\n/* Board mode - 'Saving' dialog box, which appears when a card has been moved */\n.tasks-board-saving {\n  position: fixed;\n  z-index: 99;\n  background: #fff;\n  bottom: 0;\n  left: 0;\n  right: 0;\n  margin: 0 auto 20px;\n  padding: 10px;\n  width: 160px;\n  border-radius: 8px;\n  box-shadow: 0px 0px 18px 3px rgba(0, 0, 0, 0.1);\n}\n\n.overview-page-wrapper .card-overview {\n  box-shadow: none;\n  margin-bottom: 1rem;\n}\n\n.overview-page-wrapper .card-overview .card-header-overview {\n  padding: 0;\n}\n\n.overview-page-wrapper .card-header-overview .card-title {\n  font-weight: bold;\n}\n\n.overview-page-wrapper .card-header-overview .show-all-text {\n  font-size: 14px;\n}\n\n.overview-page-wrapper .card-header-overview .card-title .btn-overview {\n  margin-top: -20px;\n  margin-bottom: -10px;\n}\n\n.dashboard-profile-img {\n  border-radius: 10rem;\n}\n\n.overview-page-wrapper .card-body-overview {\n  max-height: 300px;\n  overflow-y: auto;\n  padding-left: 0;\n  padding-right: 0;\n}\n\n/* Topics Styling */\n/* Topics table styling */\n.topics-table,\n.topics-table > tbody > tr > td,\n.topics-table > thead > tr > th {\n  border: none;\n}\n\n/* Topics table header styling */\n.topics-table thead tr th.sorting,\n.topics-table thead tr th.sorting_asc,\n.topics-table thead tr th.sorting_desc {\n  position: relative;\n  padding-left: 25px;\n}\n\n/* Workaround to show board tasks as like cla-card without actually being one */\n.card .card-status-border {\n  position: absolute;\n  width: 6px;\n  top: 0;\n  bottom: 0;\n  left: 0;\n  border-radius: 8px 0 0 8px;\n  z-index: 1;\n}\n\n/* Sets minimum width of pinnable wrapper to 120px */\n.pinnable {\n  min-width: 120px;\n}\n\n/* Styling for sorting arrows */\n.sorting::after, .sorting_asc::after, .sorting_desc::after,\n.sorting::before, .sorting_asc::before, .sorting_desc::before {\n  content: \"\";\n  position: absolute;\n  left: 9px;\n  border-style: solid;\n  border-width: 2px;\n  border-color: #fff;\n  width: 7px;\n  height: 7px;\n  transform: rotate(-45deg);\n}\n\n/* Positions top arrow to the top */\n.sorting::before, .sorting_asc::before, .sorting_desc::before {\n  top: 50%;\n  margin-top: -6px;\n}\n\n/* Positions bottom arrow to the bottom */\n.sorting::after, .sorting_asc::after, .sorting_desc::after {\n  bottom: 50%;\n  margin-bottom: -6px;\n}\n\n/* Sets inactive top arrow to light grey */\n.sorting::before, .sorting_desc::before {\n  border-top-color: hsl(219, 15%, 35%);\n  border-right-color: hsl(219, 15%, 35%);\n}\n\n/* Sets inactive bottom arrow to light grey */\n.sorting::after, .sorting_asc::after {\n  border-bottom-color: hsl(219, 15%, 35%);\n  border-left-color: hsl(219, 15%, 35%);\n}\n\n/* Sets active top arrow to dark grey */\n.sorting_desc::after {\n  border-bottom-color: hsl(220, 26%, 14%);\n  border-left-color: hsl(220, 26%, 14%);\n}\n\n/* Sets active bottom arrow to dark grey */\n.sorting_asc::before {\n  border-top-color: hsl(220, 26%, 14%);\n  border-right-color: hsl(220, 26%, 14%);\n}\n\n/* Adds margin to bottom of table to fix issue with the table having to scroll */\n.topic-table-info {\n  display: block;\n  margin-top: 30px;\n  margin-bottom: 35px;\n}\n\n/* Puts the topic user images into a wrapper which stops the items inside from breaking line and limits the width of the table */\n.user-images-wrapper {\n  white-space: nowrap;\n  position: relative;\n  overflow: hidden;\n  width: 100%;\n  max-width: 425px;\n}\n\n/* Adds right hand gradient to show when there are more users than can be displayed */\n.user-images-wrapper:after {\n  content: \"\";\n  position: absolute;\n  right: 0;\n  top: 0;\n  bottom: 0;\n  width: 40px;\n  background: linear-gradient(90deg, rgba(255, 255, 255, 0) 0%, rgb(255, 255, 255) 100%);\n}\n\n/* Limits the width of the topic user images on tablet sized screens */\n@media only screen and (max-width: 768px) {\n  .user-images-wrapper {\n    max-width: 225px;\n  }\n}\n/* Limits the width of the topic user images on mobile sized screens */\n@media only screen and (max-width: 450px) {\n  .user-images-wrapper {\n    max-width: 85px;\n  }\n}\n/* Individual topic page styling    */\n.topic-details-list td {\n  padding: 0 10px;\n}\n\n.topic-title {\n  display: inline-block;\n}\n\n/* Project overview page */\n/* Comments component */\n.comment-attachments .comment-attachments-icon,\n.comment-count .comment-count-icon {\n  color: hsl(219, 10%, 49%);\n}\n\n/* Added a max-width to images in history so they don't overflow  */\n.history-wrapper img {\n  max-width: 100%;\n  height: auto !important;\n}\n\n/* Code to reverse styling of the files component so it fits the asthetics of the projects tabs */\n.projects-file-component .dms-view {\n  padding: 0;\n}\n\n.projects-file-component .dms-view .panel-body {\n  padding-top: 0;\n  padding-left: 0;\n  padding-right: 0;\n}\n\n.modal-backdrop + .modal-backdrop {\n  opacity: 0;\n}\n\n.add-project-wrapper {\n  position: relative;\n}\n.add-project-wrapper + .add-project-wrapper::after {\n  content: \"\";\n  background: hsl(214, 32%, 91%);\n  position: absolute;\n  top: 0;\n  bottom: 0;\n  left: -8px;\n  width: 1px;\n}\n\n.tile-my-projects-component .table-responsive {\n  border-top: none;\n}\n\n.table-avatar {\n  width: 22px;\n  position: relative;\n  margin-top: -4px;\n  border-radius: 150%;\n}\n\n.rag-R {\n  background-color: hsl(0, 74%, 57%);\n}\n\n.rag-A {\n  background-color: hsl(27, 82%, 57%);\n}\n\n.rag-G {\n  background-color: hsl(145, 44%, 51%);\n}\n\n.project-bookmark {\n  color: hsl(24, 73%, 50%);\n}\n\n.project-bookmark:hover {\n  color: lignten(hsl(24, 73%, 50%), 10%);\n}\n\n.task-item .checkbox-inline {\n  margin-top: -22px;\n}\n\n/* ng-sortable drag and drop */\n.as-sortable-placeholder {\n  min-height: 20px;\n  border: 2px dashed hsl(214, 18%, 63%);\n  border-radius: 5px;\n}\n\n/* ng-sortable drag and drop specifically for task cards*/\n.tasks-board-scrollable.tasks-board-tasks .as-sortable-placeholder {\n  width: calc(100% - 20px) !important;\n  margin: 6px 10px;\n  border-radius: 8px;\n}\n\n/* ng-sortable drag and drop for Task List*/\n.task-list-items .as-sortable-placeholder {\n  background: hsl(204, 45%, 98%);\n  margin: 5px;\n  width: calc(100% - 10px) !important;\n}\n\n.as-sortable-drag {\n  opacity: 0.8;\n  position: absolute;\n  pointer-events: none;\n  z-index: 9999;\n}\n\n.task-priority-option {\n  display: inline-block;\n  width: 16px;\n  height: 16px;\n  margin-top: 5px;\n  vertical-align: text-bottom;\n}\n\n.task-priority-sidestrip {\n  position: absolute;\n  left: 0;\n  top: 0;\n  bottom: 0;\n  width: 8px;\n  z-index: 2;\n  border-radius: 0.25rem 0 0 0.25rem;\n}\n\n.task-priority-sidestrip .task-drag-area .drag-icon {\n  position: absolute;\n  top: 50%;\n  margin-top: -8px;\n}\n\n.task-priority-1 {\n  background-color: hsl(145, 44%, 51%);\n}\n\n.task-priority-2 {\n  background-color: hsl(27, 82%, 57%);\n}\n\n.task-priority-3 {\n  background-color: hsl(0, 84%, 68%);\n}\n\n.project-component-list-item td {\n  vertical-align: middle !important;\n}\n\n.project-component-rag {\n  border-radius: 50%;\n  padding: 4px 8px;\n}\n\n.projects-component-title-bar {\n  padding: 10px;\n  margin: 0 0 10px 0;\n  overflow: auto;\n  background-color: hsl(214, 32%, 91%);\n}\n\n.projects-component-title {\n  font-size: larger;\n}\n\n.project-component-services img {\n  padding-right: 5px;\n}\n\n.alert-full-width {\n  width: 100%;\n  display: inline-block;\n}\n\n.task-drag-area {\n  height: 100%;\n}\n\n.wysibb-text {\n  overflow: auto;\n}\n\n/* Tasks Component */\n.my-tasks-component .card-header-overview {\n  display: none;\n}\n\n.tile-my-tasks-component[data-gs-width=\"1\"] .task-item .task-project-name,\n.tile-my-tasks-component[data-gs-width=\"1\"] .task-item .task-date {\n  display: block;\n  float: none !important;\n}\n\n.history_type {\n  font-weight: bold;\n}\n\n.history_list_item_title {\n  font-weight: bold;\n}\n\n.history-status {\n  font-style: italic;\n}\n\n.history-list {\n  font-style: italic;\n}\n\n.card-wrapper:nth-child(4n+1) {\n  clear: both;\n}\n\n/* MAKE RIGHTS TABLE SCROLLABLE ON SMALL DEVICES */\n.rights-table-wrapper > div {\n  overflow-y: auto;\n}\n\n/* Spacing on My Tasks component */\n.sub-items .task-project-name {\n  margin-right: 10px;\n}\n\n.collapsable-info-panel .nav-stacked > li.active > a,\n.collapsable-info-panel .nav-stacked > li.active > a:hover {\n  background: hsl(207, 71%, 57%);\n}\n\n.tasks-profile-img {\n  width: 25px;\n  height: 25px;\n}\n\n/* Tasks item styling */\n.task-users {\n  padding: 6px 12px;\n}\n\n.extra-user-count {\n  padding: 2px 5px;\n  border-radius: 10rem;\n  background: hsl(210, 38%, 95%);\n  font-weight: bold;\n}\n\n.extra-user-count:hover {\n  background: hsl(210, 38%, 100%);\n  cursor: pointer;\n}\n\n.tasks-profile-img {\n  width: 25px;\n  height: 25px;\n}\n\n.cursor-default {\n  cursor: default;\n}\n\n/* Styles individual task profile images */\n.tasks-profile-single {\n  margin-left: 3px;\n  margin-bottom: 3px;\n  display: inline-block;\n}\n\n/* Adds a seperator line between the Polls and Surveys in Add modal. */\n.add-tasks-wrapper {\n  position: relative;\n}\n\n.add-tasks-wrapper + .add-tasks-wrapper::after {\n  content: \"\";\n  background: red;\n  position: absolute;\n  top: 0;\n  bottom: 0;\n  left: -8px;\n  width: 1px;\n}\n\n.projects-file-component .document-list .icons-view .document-item {\n  flex: 0 0 25%;\n  max-width: 25%;\n}\n\n.drag-container {\n  height: 100%;\n  position: relative;\n}", ""]);

// exports


/***/ }),

/***/ "../../../node_modules/css-loader/index.js!../../../node_modules/sass-loader/lib/loader.js!./js/ng/modules/widgets/css/user_list.component.scss":
/***/ (function(module, exports, __webpack_require__) {

exports = module.exports = __webpack_require__("../../../node_modules/css-loader/lib/css-base.js")();
// imports


// module
exports.push([module.i, ".user-list-component .user-list-wrapper {\n  white-space: nowrap;\n}\n.user-list-component .user-list-wrapper::after {\n  content: \"\";\n  clear: both;\n  height: 0;\n  display: block;\n}\n.user-list-component .user-list, .user-list-component .plus-number-wrapper {\n  margin: 0;\n  padding: 0;\n}\n.user-list-component .user-list {\n  margin-right: 3%;\n  display: inline;\n}\n.user-list-component .plus-number-wrapper {\n  width: 18%;\n  position: relative;\n  background: hsl(214, 32%, 91%); /* $gray-300 */\n  border-radius: 350px;\n  display: inline-block;\n  vertical-align: top;\n  cursor: pointer;\n}\n.user-list-component .plus-number-wrapper::after {\n  content: \"\";\n  display: block;\n  padding-bottom: 100%;\n}\n.user-list-component .plus-number-wrapper .plus-number {\n  position: absolute;\n  font-size: 14px;\n  top: 50%;\n  left: 0;\n  right: 0;\n  text-align: center;\n  transform: translate(0, -50%);\n  line-height: 0;\n}\n.user-list-component .plus-number-wrapper .plus-number:hover {\n  text-decoration: none;\n  color: var(--black);\n  opacity: 0.8;\n}\n.user-list-component .plus-number-wrapper .plus-number.plus-number[href=\"javascript:void(0);\"]:hover {\n  opacity: 1;\n  cursor: default;\n}\n.user-list-component .title {\n  font-size: 14px;\n}\n.user-list-component .title, .user-list-component .plus-number {\n  color: var(--black);\n}\n.user-list-component div.user-list-item {\n  float: left;\n  list-style: none;\n  width: 18%;\n  margin-right: 2%;\n}\n.user-list-component div.user-list-item a {\n  overflow: hidden;\n  border-radius: 350px;\n  display: block;\n}\n.user-list-component div.user-list-item a[href=\"javascript:void(0);\"]:hover {\n  opacity: 1;\n  cursor: default;\n}\n.user-list-component div.user-list-item a img {\n  width: 100%;\n}", ""]);

// exports


/***/ }),

/***/ "../../../node_modules/css-loader/lib/css-base.js":
/***/ (function(module, exports) {

/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/
// css base code, injected by the css-loader
module.exports = function() {
	var list = [];

	// return the list of modules as css string
	list.toString = function toString() {
		var result = [];
		for(var i = 0; i < this.length; i++) {
			var item = this[i];
			if(item[2]) {
				result.push("@media " + item[2] + "{" + item[1] + "}");
			} else {
				result.push(item[1]);
			}
		}
		return result.join("");
	};

	// import a list of modules into the list
	list.i = function(modules, mediaQuery) {
		if(typeof modules === "string")
			modules = [[null, modules, ""]];
		var alreadyImportedModules = {};
		for(var i = 0; i < this.length; i++) {
			var id = this[i][0];
			if(typeof id === "number")
				alreadyImportedModules[id] = true;
		}
		for(i = 0; i < modules.length; i++) {
			var item = modules[i];
			// skip already imported module
			// this implementation is not 100% perfect for weird media query combinations
			//  when a module is imported multiple times with different media queries.
			//  I hope this will never occur (Hey this way we have smaller bundles)
			if(typeof item[0] !== "number" || !alreadyImportedModules[item[0]]) {
				if(mediaQuery && !item[2]) {
					item[2] = mediaQuery;
				} else if(mediaQuery) {
					item[2] = "(" + item[2] + ") and (" + mediaQuery + ")";
				}
				list.push(item);
			}
		}
	};
	return list;
};


/***/ }),

/***/ "../../../node_modules/imports-loader/index.js?angular=cla_angular!./js/lib/ng-sortable.js":
/***/ (function(module, exports, __webpack_require__) {

/*** IMPORTS FROM imports-loader ***/
var angular = __webpack_require__(1);

/*
 The MIT License (MIT)

 Copyright (c) 2014 Muhammed Ashik

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in all
 copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 SOFTWARE.
 */

/*jshint indent: 2 */
/*global angular: false */

(function () {
  'use strict';
  angular.module('ui.sortable', [])
    .constant('sortableConfig', {
      itemClass: 'as-sortable-item',
      handleClass: 'as-sortable-item-handle',
      placeHolderClass: 'as-sortable-placeholder',
      dragClass: 'as-sortable-drag',
      hiddenClass: 'as-sortable-hidden',
      dragging: 'as-sortable-dragging'
    });
}());

/*jshint indent: 2 */
/*global angular: false */

(function () {
  'use strict';

  var mainModule = angular.module('ui.sortable');

  /**
   * Helper factory for sortable.
   */
  mainModule.factory('$helper', ['$document', '$window',
    function ($document, $window) {
      return {

        /**
         * Get the height of an element.
         *
         * @param {Object} element Angular element.
         * @returns {String} Height
         */
        height: function (element) {
          return element[0].getBoundingClientRect().height;
        },

        /**
         * Get the width of an element.
         *
         * @param {Object} element Angular element.
         * @returns {String} Width
         */
        width: function (element) {
          return element[0].getBoundingClientRect().width;
        },

        /**
         * Get the offset values of an element.
         *
         * @param {Object} element Angular element.
         * @param {Object} [scrollableContainer] Scrollable container object for calculating relative top & left (optional, defaults to Document)
         * @returns {Object} Object with properties width, height, top and left
         */
        offset: function (element, scrollableContainer) {
          var boundingClientRect = element[0].getBoundingClientRect();
          if (!scrollableContainer) {
            scrollableContainer = $document[0].documentElement;
          }

          return {
            width: boundingClientRect.width || element.prop('offsetWidth'),
            height: boundingClientRect.height || element.prop('offsetHeight'),
            top: boundingClientRect.top + ($window.pageYOffset || scrollableContainer.scrollTop - scrollableContainer.offsetTop),
            left: boundingClientRect.left + ($window.pageXOffset || scrollableContainer.scrollLeft - scrollableContainer.offsetLeft)
          };
        },

        /**
         * get the event object for touch.
         *
         * @param  {Object} event the touch event
         * @return {Object} the touch event object.
         */
        eventObj: function (event) {
          var obj = event;
          if (event.targetTouches !== undefined) {
            obj = event.targetTouches.item(0);
          } else if (event.originalEvent !== undefined && event.originalEvent.targetTouches !== undefined) {
            obj = event.originalEvent.targetTouches.item(0);
          }
          return obj;
        },

        /**
         * Checks whether the touch is valid and multiple.
         *
         * @param event the event object.
         * @returns {boolean} true if touch is multiple.
         */
        isTouchInvalid: function (event) {

          var touchInvalid = false;
          if (event.touches !== undefined && event.touches.length > 1) {
            touchInvalid = true;
          } else if (event.originalEvent !== undefined &&
            event.originalEvent.touches !== undefined && event.originalEvent.touches.length > 1) {
            touchInvalid = true;
          }
          return touchInvalid;
        },

        /**
         * Get the start position of the target element according to the provided event properties.
         *
         * @param {Object} event Event
         * @param {Object} target Target element
         * @param {Object} [scrollableContainer] (optional) Scrollable container object
         * @returns {Object} Object with properties offsetX, offsetY.
         */
        positionStarted: function (event, target, scrollableContainer) {
          var pos = {};
          pos.offsetX = event.pageX - this.offset(target, scrollableContainer).left;
          pos.offsetY = event.pageY - this.offset(target, scrollableContainer).top;
          pos.startX = pos.lastX = event.pageX;
          pos.startY = pos.lastY = event.pageY;
          pos.nowX = pos.nowY = pos.distX = pos.distY = pos.dirAx = 0;
          pos.dirX = pos.dirY = pos.lastDirX = pos.lastDirY = pos.distAxX = pos.distAxY = 0;
          return pos;
        },

        /**
         * Calculates the event position and sets the direction
         * properties.
         *
         * @param pos the current position of the element.
         * @param event the move event.
         */
        calculatePosition: function (pos, event) {
          // mouse position last events
          pos.lastX = pos.nowX;
          pos.lastY = pos.nowY;

          // mouse position this events
          pos.nowX = event.pageX;
          pos.nowY = event.pageY;

          // distance mouse moved between events
          pos.distX = pos.nowX - pos.lastX;
          pos.distY = pos.nowY - pos.lastY;

          // direction mouse was moving
          pos.lastDirX = pos.dirX;
          pos.lastDirY = pos.dirY;

          // direction mouse is now moving (on both axis)
          pos.dirX = pos.distX === 0 ? 0 : pos.distX > 0 ? 1 : -1;
          pos.dirY = pos.distY === 0 ? 0 : pos.distY > 0 ? 1 : -1;

          // axis mouse is now moving on
          var newAx = Math.abs(pos.distX) > Math.abs(pos.distY) ? 1 : 0;

          // calc distance moved on this axis (and direction)
          if (pos.dirAx !== newAx) {
            pos.distAxX = 0;
            pos.distAxY = 0;
          } else {
            pos.distAxX += Math.abs(pos.distX);
            if (pos.dirX !== 0 && pos.dirX !== pos.lastDirX) {
              pos.distAxX = 0;
            }

            pos.distAxY += Math.abs(pos.distY);
            if (pos.dirY !== 0 && pos.dirY !== pos.lastDirY) {
              pos.distAxY = 0;
            }
          }
          pos.dirAx = newAx;
        },

        /**
         * Move the position by applying style.
         *
         * @param event the event object
         * @param element - the dom element
         * @param pos - current position
         * @param container - the bounding container.
         * @param containerPositioning - absolute or relative positioning.
         * @param {Object} [scrollableContainer] (optional) Scrollable container object
         */
        movePosition: function (event, element, pos, container, containerPositioning, scrollableContainer) {
          var bounds;
          var useRelative = (containerPositioning === 'relative');

          element.x = event.pageX - pos.offsetX;
          element.y = event.pageY - pos.offsetY;

          if (container) {
            bounds = this.offset(container, scrollableContainer);

            if (useRelative) {
              // reduce positioning by bounds
              element.x -= bounds.left;
              element.y -= bounds.top;

              // reset bounds
              bounds.left = 0;
              bounds.top = 0;
            }

            if (element.x < bounds.left) {
              element.x = bounds.left;
            } else if (element.x >= bounds.width + bounds.left - this.offset(element).width) {
              element.x = bounds.width + bounds.left - this.offset(element).width;
            }
            if (element.y < bounds.top) {
              element.y = bounds.top;
            } else if (element.y >= bounds.height + bounds.top - this.offset(element).height) {
              element.y = bounds.height + bounds.top - this.offset(element).height;
            }
          }

          element.css({
            'left': element.x + 'px',
            'top': element.y + 'px'
          });

          this.calculatePosition(pos, event);
        },

        /**
         * The drag item info and functions.
         * retains the item info before and after move.
         * holds source item and target scope.
         *
         * @param item - the drag item
         * @returns {{index: *, parent: *, source: *,
                 *          sourceInfo: {index: *, itemScope: (*|.dragItem.sourceInfo.itemScope|$scope.itemScope|itemScope), sortableScope: *},
                 *         moveTo: moveTo, isSameParent: isSameParent, isOrderChanged: isOrderChanged, eventArgs: eventArgs, apply: apply}}
         */
        dragItem: function (item) {

          return {
            index: item.itemScope.index(),
            parent: item.sortableScope,
            source: item,
            sourceInfo: {
              index: item.itemScope.index(),
              itemScope: item.itemScope,
              sortableScope: item.sortableScope
            },
            moveTo: function (parent, index) { // Move the item to a new position
              this.parent = parent;
              //If source Item is in the same Parent.
              if (this.isSameParent() && this.source.itemScope.index() < index) { // and target after
                index = index - 1;
              }
              this.index = index;
            },
            isSameParent: function () {
              return this.parent.element === this.sourceInfo.sortableScope.element;
            },
            isOrderChanged: function () {
              return this.index !== this.sourceInfo.index;
            },
            eventArgs: function () {
              return {
                source: this.sourceInfo,
                dest: {
                  index: this.index,
                  sortableScope: this.parent
                }
              };
            },
            apply: function () {
              var item = this.sourceInfo.sortableScope.removeItem(this.sourceInfo.index); // Remove from source.
              this.parent.insertItem(this.index, item); // Insert in to destination.
            }
          };
        },

        /**
         * Check the drag is not allowed for the element.
         *
         * @param element - the element to check
         * @returns {boolean} - true if drag is not allowed.
         */
        noDrag: function (element) {
          return element.attr('no-drag') !== undefined || element.attr('data-no-drag') !== undefined;
        }
      };
    }
  ]);

}());
/*jshint undef: false, unused: false, indent: 2*/
/*global angular: false */

(function () {

  'use strict';
  var mainModule = angular.module('ui.sortable');

  /**
   * Controller for Sortable.
   * @param $scope - the sortable scope.
   */
  mainModule.controller('ui.sortable.sortableController', ['$scope', function ($scope) {

    this.scope = $scope;

    $scope.modelValue = null; // sortable list.
    $scope.callbacks = null;
    $scope.type = 'sortable';
    $scope.options = {};
    $scope.isDisabled = false;

    /**
     * Inserts the item in to the sortable list.
     *
     * @param index - the item index.
     * @param itemData - the item model data.
     */
    $scope.insertItem = function (index, itemData) {
      $scope.modelValue.splice(index, 0, itemData);
    };

    /**
     * Removes the item from the sortable list.
     *
     * @param index - index to be removed.
     * @returns {*} - removed item.
     */
    $scope.removeItem = function (index) {
      var removedItem = null;
      if (index > -1) {
        removedItem = $scope.modelValue.splice(index, 1)[0];
      }
      return removedItem;
    };

    /**
     * Checks whether the sortable list is empty.
     *
     * @returns {null|*|$scope.modelValue|boolean}
     */
    $scope.isEmpty = function () {
      return ($scope.modelValue && $scope.modelValue.length === 0);
    };

    /**
     * Wrapper for the accept callback delegates to callback.
     *
     * @param sourceItemHandleScope - drag item handle scope.
     * @param destScope - sortable target scope.
     * @param destItemScope - sortable destination item scope.
     * @returns {*|boolean} - true if drop is allowed for the drag item in drop target.
     */
    $scope.accept = function (sourceItemHandleScope, destScope, destItemScope) {
      return $scope.callbacks.accept(sourceItemHandleScope, destScope, destItemScope);
    };

  }]);

  /**
   * Sortable directive - defines callbacks.
   * Parent directive for draggable and sortable items.
   * Sets modelValue, callbacks, element in scope.
   */
  mainModule.directive('asSortable',
    function ($parse) {
      return {
        require: 'ngModel', // get a hold of NgModelController
        restrict: 'A',
        scope: { asSortable: '&' },
        controller: 'ui.sortable.sortableController',
        link: function (scope, element, attrs, ngModelController) {

          var ngModel, callbacks;

          ngModel = ngModelController;

          if (!ngModel) {
            return; // do nothing if no ng-model
          }

          // Set the model value in to scope.
          ngModel.$render = function () {
            //set an empty array, in case if none is provided.
            if (!ngModel.$modelValue || !angular.isArray(ngModel.$modelValue)) {
              ngModel.$setViewValue([]);
            }
            scope.modelValue = ngModel.$modelValue;
          };
          //set the element in scope to be accessed by its sub scope.
          scope.element = element;

          callbacks = {accept: null, orderChanged: null, itemMoved: null, dragStart: null, dragMove:null, dragCancel: null, dragEnd: null};

          /**
           * Invoked to decide whether to allow drop.
           *
           * @param sourceItemHandleScope - the drag item handle scope.
           * @param destSortableScope - the drop target sortable scope.
           * @param destItemScope - the drop target item scope.
           * @returns {boolean} - true if allowed for drop.
           */
          callbacks.accept = function (sourceItemHandleScope, destSortableScope, destItemScope) {
            return true;
          };

          /**
           * Invoked when order of a drag item is changed.
           *
           * @param event - the event object.
           */
          callbacks.orderChanged = function (event) {
          };

          /**
           * Invoked when the item is moved to other sortable.
           *
           * @param event - the event object.
           */
          callbacks.itemMoved = function (event) {
          };

          /**
           * Invoked when the drag started successfully.
           *
           * @param event - the event object.
           */
          callbacks.dragStart = function (event) {
          };

          /**
           * Invoked when the drag started successfully.
           *
           * @param event - the event object.
          */
          callbacks.dragMove = function (event) {
          };

          /**
           * Invoked when the drag cancelled.
           *
           * @param event - the event object.
           */
          callbacks.dragCancel = function (event) {
          };

          /**
           * Invoked when the drag stopped.
           *
           * @param event - the event object.
           */
          callbacks.dragEnd = function (event) {
          };

          //Set the sortOptions callbacks else set it to default.
          scope.$watch(scope.asSortable, function (newVal, oldVal) {
            angular.forEach(newVal, function (value, key) {
              if (callbacks[key]) {
                if (typeof value === 'function') {
                  callbacks[key] = value;
                }
              } else {
                scope.options[key] = value;
              }
            });
            scope.callbacks = callbacks;
          }, true);

          // Set isDisabled if attr is set, if undefined isDisabled = false
          if (angular.isDefined(attrs.isDisabled)) {
            scope.$watch(attrs.isDisabled, function (newVal, oldVal) {
              if (!angular.isUndefined(newVal)) {
                scope.isDisabled = newVal;
              }
            }, true);
          }
        }
      };
    });

}());

/*jshint indent: 2 */
/*global angular: false */

(function () {

  'use strict';
  var mainModule = angular.module('ui.sortable');

  /**
   * Controller for sortableItemHandle
   *
   * @param $scope - item handle scope.
   */
  mainModule.controller('ui.sortable.sortableItemHandleController', ['$scope', function ($scope) {

    this.scope = $scope;

    $scope.itemScope = null;
    $scope.type = 'handle';
  }]);

  /**
   * Directive for sortable item handle.
   */
  mainModule.directive('asSortableItemHandle', ['sortableConfig', '$helper', '$window', '$document',
    function (sortableConfig, $helper, $window, $document) {
      return {
        require: '^asSortableItem',
        scope: {},
        restrict: 'A',
        controller: 'ui.sortable.sortableItemHandleController',
        link: function (scope, element, attrs, itemController) {

          var dragElement, //drag item element.
            placeHolder, //place holder class element.
            placeElement,//hidden place element.
            itemPosition, //drag item element position.
            dragItemInfo, //drag item data.
            containment,//the drag container.
            containerPositioning, // absolute or relative positioning.
            dragListen,// drag listen event.
            scrollableContainer, //the scrollable container
            dragStart,// drag start event.
            dragMove,//drag move event.
            dragEnd,//drag end event.
            dragCancel,//drag cancel event.
            isDraggable,//is element draggable.
            isDragBefore,//is element moved up direction.
            isPlaceHolderPresent,//is placeholder present.
            bindDrag,//bind drag events.
            unbindDrag,//unbind drag events.
            bindEvents,//bind the drag events.
            unBindEvents,//unbind the drag events.
            hasTouch,// has touch support.
            dragHandled, //drag handled.
            createPlaceholder,
            isDisabled = false; // drag enabled

          hasTouch = $window.hasOwnProperty('ontouchstart');

          if (sortableConfig.handleClass) {
            element.addClass(sortableConfig.handleClass);
          }

          scope.itemScope = itemController.scope;
	      scope.sortableScope = scope.itemScope.sortableScope;

          scope.$watch('sortableScope.isDisabled', function (newVal) {
            if (isDisabled !== newVal) {
              isDisabled = newVal;
              if (isDisabled) {
                unbindDrag();
              } else {
                bindDrag();
              }
            }
          });

          createPlaceholder = function(itemScope) {
            if(typeof scope.sortableScope.options.placeholder === 'function') {
              return angular.element(scope.sortableScope.options.placeholder(itemScope));
            } else if(typeof scope.sortableScope.options.placeholder === 'string') {
              return angular.element(scope.sortableScope.options.placeholder);
            } else {
              return angular.element($document[0].createElement(itemScope.element.prop('tagName')));
            }
          };

          /**
           * Listens for a 10px movement before
           * dragStart is called to allow for
           * a click event on the element.
           *
           * @param event - the event object.
           */
          dragListen = function (event) {

            var unbindMoveListen = function () {
              angular.element($document).unbind('mousemove', moveListen);
              angular.element($document).unbind('touchmove', moveListen);
              element.unbind('mouseup', unbindMoveListen);
              element.unbind('touchend', unbindMoveListen);
              element.unbind('touchcancel', unbindMoveListen);
            };

            var startPosition;
            var moveListen = function (e) {
              e.preventDefault();
              var eventObj = $helper.eventObj(e);
              if (!startPosition) {
                startPosition = { clientX: eventObj.clientX, clientY: eventObj.clientY };
              }
              if (Math.abs(eventObj.clientX - startPosition.clientX) + Math.abs(eventObj.clientY - startPosition.clientY) > 10) {
                unbindMoveListen();
                dragStart(event);
              }
            };

            angular.element($document).bind('mousemove', moveListen);
            angular.element($document).bind('touchmove', moveListen);
            element.bind('mouseup', unbindMoveListen);
            element.bind('touchend', unbindMoveListen);
            element.bind('touchcancel', unbindMoveListen);
          };

          /**
           * Triggered when drag event starts.
           *
           * @param event the event object.
           */
          dragStart = function (event) {

            var eventObj, tagName;

            if (!hasTouch && (event.button === 2 || event.which === 3)) {
              // disable right click
              return;
            }
            if (hasTouch && $helper.isTouchInvalid(event)) {
              return;
            }
            if (dragHandled || !isDraggable(event)) {
              // event has already fired in other scope.
              return;
            }
            // Set the flag to prevent other items from inheriting the drag event
            dragHandled = true;
            event.preventDefault();
            eventObj = $helper.eventObj(event);

	        // sortableScope may not be setup yet
	        if (scope.sortableScope === null)
	        {
		        scope.sortableScope = scope.itemScope.sortableScope;
	        }

            // (optional) Scrollable container as reference for top & left offset calculations, defaults to Document
            scrollableContainer = angular.element($document[0].querySelector(scope.sortableScope.options.scrollableContainer)).length > 0 ?
              $document[0].querySelector(scope.sortableScope.options.scrollableContainer) : $document[0].documentElement;

            containment = angular.element($document[0].querySelector(scope.sortableScope.options.containment)).length > 0 ?
              angular.element($document[0].querySelector(scope.sortableScope.options.containment)) : angular.element($document[0].body);
            //capture mouse move on containment.
            containment.css('cursor', 'move');
            containment.addClass('as-sortable-un-selectable');

            // container positioning
            containerPositioning = scope.sortableScope.options.containerPositioning || 'absolute';

            dragItemInfo = $helper.dragItem(scope);
            tagName = scope.itemScope.element.prop('tagName');

            dragElement = angular.element($document[0].createElement(scope.sortableScope.element.prop('tagName')))
              .addClass(scope.sortableScope.element.attr('class')).addClass(sortableConfig.dragClass);
            dragElement.css('width', $helper.width(scope.itemScope.element) + 'px');
            dragElement.css('height', $helper.height(scope.itemScope.element) + 'px');

            placeHolder = createPlaceholder(scope.itemScope)
              .addClass(sortableConfig.placeHolderClass).addClass(scope.sortableScope.options.additionalPlaceholderClass);
            placeHolder.css('width', $helper.width(scope.itemScope.element) + 'px');
            placeHolder.css('height', $helper.height(scope.itemScope.element) + 'px');

            placeElement = angular.element($document[0].createElement(tagName));
            if (sortableConfig.hiddenClass) {
              placeElement.addClass(sortableConfig.hiddenClass);
            }

            itemPosition = $helper.positionStarted(eventObj, scope.itemScope.element, scrollableContainer);
            //fill the immediate vacuum.
            scope.itemScope.element.after(placeHolder);
            //hidden place element in original position.
            scope.itemScope.element.after(placeElement);
            dragElement.append(scope.itemScope.element);

            containment.append(dragElement);
            $helper.movePosition(eventObj, dragElement, itemPosition, containment, containerPositioning, scrollableContainer);

            scope.sortableScope.$apply(function () {
              scope.sortableScope.callbacks.dragStart(dragItemInfo.eventArgs());
            });
            bindEvents();
          };

          /**
           * Allow Drag if it is a proper item-handle element.
           *
           * @param event - the event object.
           * @return boolean - true if element is draggable.
           */
          isDraggable = function (event) {

            var elementClicked, sourceScope, isDraggable;

            elementClicked = angular.element(event.target);
            sourceScope = scope;//elementClicked.scope();

            // look for the handle on the current scope or parent scopes
            isDraggable = false;
            while (!isDraggable && sourceScope !== undefined) {
              if (sourceScope.type && sourceScope.type === 'handle') {
                isDraggable = true;
              } else {
                sourceScope = sourceScope.$parent;
              }
            }

            //If a 'no-drag' element inside item-handle if any.
            while (isDraggable && elementClicked[0] !== element[0]) {
              if ($helper.noDrag(elementClicked)) {
                isDraggable = false;
              }
              elementClicked = elementClicked.parent();
            }
            return isDraggable;
          };

          /**
           * Inserts the placeHolder in to the targetScope.
           *
           * @param targetElement the target element
           * @param targetScope the target scope
           */
          function insertBefore(targetElement, targetScope) {
            targetElement[0].parentNode.insertBefore(placeHolder[0], targetElement[0]);
            dragItemInfo.moveTo(targetScope.sortableScope, targetScope.index());
          }

          /**
           * Inserts the placeHolder next to the targetScope.
           *
           * @param targetElement the target element
           * @param targetScope the target scope
           */
          function insertAfter(targetElement, targetScope) {
            targetElement.after(placeHolder);
            dragItemInfo.moveTo(targetScope.sortableScope, targetScope.index() + 1);
          }

			/** Find the closest ancestor that is a sortable element **/
		  function findDropScope(targetElement)
		  {
			  var iterations = 0;
			  var targetScope = targetElement.isolateScope();
			  while ((typeof targetScope === 'undefined') ||
			  		 (typeof targetScope.type === 'undefined'))
			  {
				  targetElement = angular.element(targetElement).parent();
				  targetScope = targetElement.isolateScope();

				  // Exit if nothing found (may be nested too deep, or the mouse isn't over the sortable container, or even not on the page anymore)
				  iterations++;
				  if (iterations > 32)
				  	return null;
			  }

			  return targetScope;
		  }

          /**
           * Triggered when drag is moving.
           *
           * @param event - the event object.
           */
          dragMove = function (event) {

            var eventObj, targetX, targetY, targetScope, targetElement;

            if (hasTouch && $helper.isTouchInvalid(event)) {
              return;
            }
            // Ignore event if not handled
            if (!dragHandled) {
              return;
            }
            if (dragElement) {

              event.preventDefault();

              eventObj = $helper.eventObj(event);
              scope.sortableScope.$apply(function () {
                scope.sortableScope.callbacks.dragMove(itemPosition, containment);
              });
              $helper.movePosition(eventObj, dragElement, itemPosition, containment, containerPositioning, scrollableContainer);

              targetX = eventObj.pageX - $document[0].documentElement.scrollLeft;
              targetY = eventObj.pageY - ($window.pageYOffset || $document[0].documentElement.scrollTop);

              //IE fixes: hide show element, call element from point twice to return pick correct element.
              dragElement.addClass(sortableConfig.hiddenClass);
              $document[0].elementFromPoint(targetX, targetY);
              targetElement = angular.element($document[0].elementFromPoint(targetX, targetY));

              dragElement.removeClass(sortableConfig.hiddenClass);

              //Set Class as dragging starts
              dragElement.addClass(sortableConfig.dragging);

			  // Find the nearest sortable parent container if one exists
              targetScope = findDropScope(targetElement);

              if (!targetScope || !targetScope.type) {
                return;
              }
              if (targetScope.type === 'handle') {
                targetScope = targetScope.itemScope;
              }
              if (targetScope.type !== 'item' && targetScope.type !== 'sortable') {
                return;
              }

              if (targetScope.type === 'item') {
                targetElement = targetScope.element;
                if (targetScope.sortableScope.accept(scope, targetScope.sortableScope, targetScope)) {
                  if (itemPosition.dirAx && //move horizontal
                    scope.itemScope.sortableScope.$id === targetScope.sortableScope.$id) { //move same column
                    itemPosition.distAxX = 0;
                    if (itemPosition.distX < 0) {//move left
                      insertBefore(targetElement, targetScope);
                    } else if (itemPosition.distX > 0) {//move right
                      insertAfter(targetElement, targetScope);
                    }
                  } else { //move vertical
                    if (isDragBefore(eventObj, targetElement)) {//move up
                      insertBefore(targetElement, targetScope);
                    } else {//move bottom
                      insertAfter(targetElement, targetScope);
                    }
                  }
                }
              }
              if (targetScope.type === 'sortable') {//sortable scope.
                if (targetScope.accept(scope, targetScope) &&
                  targetElement[0].parentNode !== targetScope.element[0]) {
                  //moving over sortable bucket. not over item.
                  if (!isPlaceHolderPresent(targetElement)) {
                    //append to bottom.
                    targetElement[0].appendChild(placeHolder[0]);
                    dragItemInfo.moveTo(targetScope, targetScope.modelValue.length);
                  }
                }
              }
            }
          };

          /**
           * Check there is no place holder placed by itemScope.
           * @param targetElement the target element to check with.
           * @returns {*} true if place holder present.
           */
          isPlaceHolderPresent = function (targetElement) {
            var itemElements, hasPlaceHolder, i;

            itemElements = targetElement.children();
            for (i = 0; i < itemElements.length; i += 1) {
              if (angular.element(itemElements[i]).hasClass(sortableConfig.placeHolderClass)) {
                hasPlaceHolder = true;
                break;
              }
            }
            return hasPlaceHolder;
          };


          /**
           * Determines whether the item is dragged upwards.
           *
           * @param eventObj - the event object.
           * @param targetElement - the target element.
           * @returns {boolean} - true if moving upwards.
           */
          isDragBefore = function (eventObj, targetElement) {
            var dragBefore, targetOffset;

            dragBefore = false;
            // check it's new position
            targetOffset = $helper.offset(targetElement);
            if ($helper.offset(placeHolder).top > targetOffset.top) { // the move direction is up?
              dragBefore = $helper.offset(dragElement).top < targetOffset.top + $helper.height(targetElement) / 2;
            } else {
              dragBefore = eventObj.pageY < targetOffset.top;
            }
            return dragBefore;
          };

          /**
           * Rollback the drag data changes.
           */

          function rollbackDragChanges() {
            placeElement.replaceWith(scope.itemScope.element);
            placeHolder.remove();
            dragElement.remove();
            dragElement = null;
            dragHandled = false;
            containment.css('cursor', '');
            containment.removeClass('as-sortable-un-selectable');
          }

          /**
           * triggered while drag ends.
           *
           * @param event - the event object.
           */
          dragEnd = function (event) {
            // Ignore event if not handled
            if (!dragHandled) {
              return;
            }
            event.preventDefault();
            if (dragElement) {
              //rollback all the changes.
              rollbackDragChanges();
              // update model data
              dragItemInfo.apply();
              scope.sortableScope.$apply(function () {
                if (dragItemInfo.isSameParent()) {
                  if (dragItemInfo.isOrderChanged()) {
                    scope.sortableScope.callbacks.orderChanged(dragItemInfo.eventArgs());
                  }
                } else {
                  scope.sortableScope.callbacks.itemMoved(dragItemInfo.eventArgs());
                }
              });
              scope.sortableScope.$apply(function () {
                scope.sortableScope.callbacks.dragEnd(dragItemInfo.eventArgs());
              });
              dragItemInfo = null;
            }
            unBindEvents();
          };

          /**
           * triggered while drag is cancelled.
           *
           * @param event - the event object.
           */
          dragCancel = function (event) {
            // Ignore event if not handled
            if (!dragHandled) {
              return;
            }
            event.preventDefault();

            if (dragElement) {
              //rollback all the changes.
              rollbackDragChanges();
              scope.sortableScope.$apply(function () {
                scope.sortableScope.callbacks.dragCancel(dragItemInfo.eventArgs());
              });
              dragItemInfo = null;
            }
            unBindEvents();
          };

          /**
           * Binds the drag start events.
           */
          bindDrag = function () {
            element.bind('touchstart', dragListen);
            element.bind('mousedown', dragListen);
          };

          /**
           * Unbinds the drag start events.
           */
          unbindDrag = function () {
            element.unbind('touchstart', dragListen);
            element.unbind('mousedown', dragListen);
          };

          //bind drag start events.
          bindDrag();

          //Cancel drag on escape press.
          angular.element($document[0].body).bind('keydown', function (event) {
            if (event.keyCode === 27) {
              dragCancel(event);
            }
          });

          /**
           * Binds the events based on the actions.
           */
          bindEvents = function () {
            angular.element($document).bind('touchmove', dragMove);
            angular.element($document).bind('touchend', dragEnd);
            angular.element($document).bind('touchcancel', dragCancel);
            angular.element($document).bind('mousemove', dragMove);
            angular.element($document).bind('mouseup', dragEnd);
          };

          /**
           * Un binds the events for drag support.
           */
          unBindEvents = function () {
            angular.element($document).unbind('touchend', dragEnd);
            angular.element($document).unbind('touchcancel', dragCancel);
            angular.element($document).unbind('touchmove', dragMove);
            angular.element($document).unbind('mouseup', dragEnd);
            angular.element($document).unbind('mousemove', dragMove);
          };
        }
      };
    }]);
}());

/*jshint indent: 2 */
/*global angular: false */

(function () {

  'use strict';
  var mainModule = angular.module('ui.sortable');

  /**
   * Controller for sortable item.
   *
   * @param $scope - drag item scope
   */
  mainModule.controller('ui.sortable.sortableItemController', ['$scope', function ($scope) {

    this.scope = $scope;

    $scope.sortableScope = null;
    $scope.modelValue = null; // sortable item.
    $scope.type = 'item';

    /**
     * returns the index of the drag item from the sortable list.
     *
     * @returns {*} - index value.
     */
    $scope.index = function () {
      return $scope.$parent.$index;
    };

    /**
     * Returns the item model data.
     *
     * @returns {*} - item model value.
     */
    $scope.itemData = function () {
      return $scope.sortableScope.modelValue[$scope.$index];
    };

  }]);

  /**
   * sortableItem directive.
   */
  mainModule.directive('asSortableItem', ['sortableConfig',
    function (sortableConfig) {
      return {
        require: ['^asSortable', '?ngModel'],
        restrict: 'A',
	    scope: {},
        controller: 'ui.sortable.sortableItemController',
        link: function (scope, element, attrs, ctrl) {
          var sortableController = ctrl[0];
          var ngModelController = ctrl[1];
          if (sortableConfig.itemClass) {
            element.addClass(sortableConfig.itemClass);
          }
          scope.sortableScope = sortableController.scope;
          if (ngModelController) {
            ngModelController.$render = function () {
              scope.modelValue = ngModelController.$modelValue;
            };
          } else {
		    scope.modelValue = sortableController.scope.modelValue[scope.$index];
          }
          scope.element = element;
        }
      };
    }]);

}());



/***/ }),

/***/ "../../../node_modules/style-loader/addStyles.js":
/***/ (function(module, exports, __webpack_require__) {

/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/
var stylesInDom = {},
	memoize = function(fn) {
		var memo;
		return function () {
			if (typeof memo === "undefined") memo = fn.apply(this, arguments);
			return memo;
		};
	},
	isOldIE = memoize(function() {
		// Test for IE <= 9 as proposed by Browserhacks
		// @see http://browserhacks.com/#hack-e71d8692f65334173fee715c222cb805
		// Tests for existence of standard globals is to allow style-loader 
		// to operate correctly into non-standard environments
		// @see https://github.com/webpack-contrib/style-loader/issues/177
		return window && document && document.all && !window.atob;
	}),
	getElement = (function(fn) {
		var memo = {};
		return function(selector) {
			if (typeof memo[selector] === "undefined") {
				memo[selector] = fn.call(this, selector);
			}
			return memo[selector]
		};
	})(function (styleTarget) {
		return document.querySelector(styleTarget)
	}),
	singletonElement = null,
	singletonCounter = 0,
	styleElementsInsertedAtTop = [],
	fixUrls = __webpack_require__("../../../node_modules/style-loader/fixUrls.js");

module.exports = function(list, options) {
	if(typeof DEBUG !== "undefined" && DEBUG) {
		if(typeof document !== "object") throw new Error("The style-loader cannot be used in a non-browser environment");
	}

	options = options || {};
	options.attrs = typeof options.attrs === "object" ? options.attrs : {};

	// Force single-tag solution on IE6-9, which has a hard limit on the # of <style>
	// tags it will allow on a page
	if (typeof options.singleton === "undefined") options.singleton = isOldIE();

	// By default, add <style> tags to the <head> element
	if (typeof options.insertInto === "undefined") options.insertInto = "head";

	// By default, add <style> tags to the bottom of the target
	if (typeof options.insertAt === "undefined") options.insertAt = "bottom";

	var styles = listToStyles(list);
	addStylesToDom(styles, options);

	return function update(newList) {
		var mayRemove = [];
		for(var i = 0; i < styles.length; i++) {
			var item = styles[i];
			var domStyle = stylesInDom[item.id];
			domStyle.refs--;
			mayRemove.push(domStyle);
		}
		if(newList) {
			var newStyles = listToStyles(newList);
			addStylesToDom(newStyles, options);
		}
		for(var i = 0; i < mayRemove.length; i++) {
			var domStyle = mayRemove[i];
			if(domStyle.refs === 0) {
				for(var j = 0; j < domStyle.parts.length; j++)
					domStyle.parts[j]();
				delete stylesInDom[domStyle.id];
			}
		}
	};
};

function addStylesToDom(styles, options) {
	for(var i = 0; i < styles.length; i++) {
		var item = styles[i];
		var domStyle = stylesInDom[item.id];
		if(domStyle) {
			domStyle.refs++;
			for(var j = 0; j < domStyle.parts.length; j++) {
				domStyle.parts[j](item.parts[j]);
			}
			for(; j < item.parts.length; j++) {
				domStyle.parts.push(addStyle(item.parts[j], options));
			}
		} else {
			var parts = [];
			for(var j = 0; j < item.parts.length; j++) {
				parts.push(addStyle(item.parts[j], options));
			}
			stylesInDom[item.id] = {id: item.id, refs: 1, parts: parts};
		}
	}
}

function listToStyles(list) {
	var styles = [];
	var newStyles = {};
	for(var i = 0; i < list.length; i++) {
		var item = list[i];
		var id = item[0];
		var css = item[1];
		var media = item[2];
		var sourceMap = item[3];
		var part = {css: css, media: media, sourceMap: sourceMap};
		if(!newStyles[id])
			styles.push(newStyles[id] = {id: id, parts: [part]});
		else
			newStyles[id].parts.push(part);
	}
	return styles;
}

function insertStyleElement(options, styleElement) {
	var styleTarget = getElement(options.insertInto)
	if (!styleTarget) {
		throw new Error("Couldn't find a style target. This probably means that the value for the 'insertInto' parameter is invalid.");
	}
	var lastStyleElementInsertedAtTop = styleElementsInsertedAtTop[styleElementsInsertedAtTop.length - 1];
	if (options.insertAt === "top") {
		if(!lastStyleElementInsertedAtTop) {
			styleTarget.insertBefore(styleElement, styleTarget.firstChild);
		} else if(lastStyleElementInsertedAtTop.nextSibling) {
			styleTarget.insertBefore(styleElement, lastStyleElementInsertedAtTop.nextSibling);
		} else {
			styleTarget.appendChild(styleElement);
		}
		styleElementsInsertedAtTop.push(styleElement);
	} else if (options.insertAt === "bottom") {
		styleTarget.appendChild(styleElement);
	} else {
		throw new Error("Invalid value for parameter 'insertAt'. Must be 'top' or 'bottom'.");
	}
}

function removeStyleElement(styleElement) {
	styleElement.parentNode.removeChild(styleElement);
	var idx = styleElementsInsertedAtTop.indexOf(styleElement);
	if(idx >= 0) {
		styleElementsInsertedAtTop.splice(idx, 1);
	}
}

function createStyleElement(options) {
	var styleElement = document.createElement("style");
	options.attrs.type = "text/css";

	attachTagAttrs(styleElement, options.attrs);
	insertStyleElement(options, styleElement);
	return styleElement;
}

function createLinkElement(options) {
	var linkElement = document.createElement("link");
	options.attrs.type = "text/css";
	options.attrs.rel = "stylesheet";

	attachTagAttrs(linkElement, options.attrs);
	insertStyleElement(options, linkElement);
	return linkElement;
}

function attachTagAttrs(element, attrs) {
	Object.keys(attrs).forEach(function (key) {
		element.setAttribute(key, attrs[key]);
	});
}

function addStyle(obj, options) {
	var styleElement, update, remove;

	if (options.singleton) {
		var styleIndex = singletonCounter++;
		styleElement = singletonElement || (singletonElement = createStyleElement(options));
		update = applyToSingletonTag.bind(null, styleElement, styleIndex, false);
		remove = applyToSingletonTag.bind(null, styleElement, styleIndex, true);
	} else if(obj.sourceMap &&
		typeof URL === "function" &&
		typeof URL.createObjectURL === "function" &&
		typeof URL.revokeObjectURL === "function" &&
		typeof Blob === "function" &&
		typeof btoa === "function") {
		styleElement = createLinkElement(options);
		update = updateLink.bind(null, styleElement, options);
		remove = function() {
			removeStyleElement(styleElement);
			if(styleElement.href)
				URL.revokeObjectURL(styleElement.href);
		};
	} else {
		styleElement = createStyleElement(options);
		update = applyToTag.bind(null, styleElement);
		remove = function() {
			removeStyleElement(styleElement);
		};
	}

	update(obj);

	return function updateStyle(newObj) {
		if(newObj) {
			if(newObj.css === obj.css && newObj.media === obj.media && newObj.sourceMap === obj.sourceMap)
				return;
			update(obj = newObj);
		} else {
			remove();
		}
	};
}

var replaceText = (function () {
	var textStore = [];

	return function (index, replacement) {
		textStore[index] = replacement;
		return textStore.filter(Boolean).join('\n');
	};
})();

function applyToSingletonTag(styleElement, index, remove, obj) {
	var css = remove ? "" : obj.css;

	if (styleElement.styleSheet) {
		styleElement.styleSheet.cssText = replaceText(index, css);
	} else {
		var cssNode = document.createTextNode(css);
		var childNodes = styleElement.childNodes;
		if (childNodes[index]) styleElement.removeChild(childNodes[index]);
		if (childNodes.length) {
			styleElement.insertBefore(cssNode, childNodes[index]);
		} else {
			styleElement.appendChild(cssNode);
		}
	}
}

function applyToTag(styleElement, obj) {
	var css = obj.css;
	var media = obj.media;

	if(media) {
		styleElement.setAttribute("media", media)
	}

	if(styleElement.styleSheet) {
		styleElement.styleSheet.cssText = css;
	} else {
		while(styleElement.firstChild) {
			styleElement.removeChild(styleElement.firstChild);
		}
		styleElement.appendChild(document.createTextNode(css));
	}
}

function updateLink(linkElement, options, obj) {
	var css = obj.css;
	var sourceMap = obj.sourceMap;

	/* If convertToAbsoluteUrls isn't defined, but sourcemaps are enabled
	and there is no publicPath defined then lets turn convertToAbsoluteUrls
	on by default.  Otherwise default to the convertToAbsoluteUrls option
	directly
	*/
	var autoFixUrls = options.convertToAbsoluteUrls === undefined && sourceMap;

	if (options.convertToAbsoluteUrls || autoFixUrls){
		css = fixUrls(css);
	}

	if(sourceMap) {
		// http://stackoverflow.com/a/26603875
		css += "\n/*# sourceMappingURL=data:application/json;base64," + btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))) + " */";
	}

	var blob = new Blob([css], { type: "text/css" });

	var oldSrc = linkElement.href;

	linkElement.href = URL.createObjectURL(blob);

	if(oldSrc)
		URL.revokeObjectURL(oldSrc);
}


/***/ }),

/***/ "../../../node_modules/style-loader/fixUrls.js":
/***/ (function(module, exports) {


/**
 * When source maps are enabled, `style-loader` uses a link element with a data-uri to
 * embed the css on the page. This breaks all relative urls because now they are relative to a
 * bundle instead of the current page.
 *
 * One solution is to only use full urls, but that may be impossible.
 *
 * Instead, this function "fixes" the relative urls to be absolute according to the current page location.
 *
 * A rudimentary test suite is located at `test/fixUrls.js` and can be run via the `npm test` command.
 *
 */

module.exports = function (css) {
  // get current location
  var location = typeof window !== "undefined" && window.location;

  if (!location) {
    throw new Error("fixUrls requires window.location");
  }

	// blank or null?
	if (!css || typeof css !== "string") {
	  return css;
  }

  var baseUrl = location.protocol + "//" + location.host;
  var currentDir = baseUrl + location.pathname.replace(/\/[^\/]*$/, "/");

	// convert each url(...)
	/*
	This regular expression is just a way to recursively match brackets within
	a string.

	 /url\s*\(  = Match on the word "url" with any whitespace after it and then a parens
	   (  = Start a capturing group
	     (?:  = Start a non-capturing group
	         [^)(]  = Match anything that isn't a parentheses
	         |  = OR
	         \(  = Match a start parentheses
	             (?:  = Start another non-capturing groups
	                 [^)(]+  = Match anything that isn't a parentheses
	                 |  = OR
	                 \(  = Match a start parentheses
	                     [^)(]*  = Match anything that isn't a parentheses
	                 \)  = Match a end parentheses
	             )  = End Group
              *\) = Match anything and then a close parens
          )  = Close non-capturing group
          *  = Match anything
       )  = Close capturing group
	 \)  = Match a close parens

	 /gi  = Get all matches, not the first.  Be case insensitive.
	 */
	var fixedCss = css.replace(/url\s*\(((?:[^)(]|\((?:[^)(]+|\([^)(]*\))*\))*)\)/gi, function(fullMatch, origUrl) {
		// strip quotes (if they exist)
		var unquotedOrigUrl = origUrl
			.trim()
			.replace(/^"(.*)"$/, function(o, $1){ return $1; })
			.replace(/^'(.*)'$/, function(o, $1){ return $1; });

		// already a full url? no change
		if (/^(#|data:|http:\/\/|https:\/\/|file:\/\/\/)/i.test(unquotedOrigUrl)) {
		  return fullMatch;
		}

		// convert the url to a full url
		var newUrl;

		if (unquotedOrigUrl.indexOf("//") === 0) {
		  	//TODO: should we add protocol?
			newUrl = unquotedOrigUrl;
		} else if (unquotedOrigUrl.indexOf("/") === 0) {
			// path should be relative to the base url
			newUrl = baseUrl + unquotedOrigUrl; // already starts with '/'
		} else {
			// path should be relative to current directory
			newUrl = currentDir + unquotedOrigUrl.replace(/^\.\//, ""); // Strip leading './'
		}

		// send back the fixed url(...)
		return "url(" + JSON.stringify(newUrl) + ")";
	});

	// send back the fixed css
	return fixedCss;
};


/***/ }),

/***/ "./assets/css/ng-sortable.scss":
/***/ (function(module, exports, __webpack_require__) {

// style-loader: Adds some css to the DOM by adding a <style> tag

// load the styles
var content = __webpack_require__("../../../node_modules/css-loader/index.js!../../../node_modules/sass-loader/lib/loader.js!./assets/css/ng-sortable.scss");
if(typeof content === 'string') content = [[module.i, content, '']];
// add the styles to the DOM
var update = __webpack_require__("../../../node_modules/style-loader/addStyles.js")(content, {});
if(content.locals) module.exports = content.locals;
// Hot Module Replacement
if(false) {
	// When the styles change, update the <style> tags
	if(!content.locals) {
		module.hot.accept("!!../../../../../node_modules/css-loader/index.js!../../../../../node_modules/sass-loader/lib/loader.js!./ng-sortable.scss", function() {
			var newContent = require("!!../../../../../node_modules/css-loader/index.js!../../../../../node_modules/sass-loader/lib/loader.js!./ng-sortable.scss");
			if(typeof newContent === 'string') newContent = [[module.id, newContent, '']];
			update(newContent);
		});
	}
	// When the module is disposed, remove the <style> tags
	module.hot.dispose(function() { update(); });
}

/***/ }),

/***/ "./assets/css/style.scss":
/***/ (function(module, exports, __webpack_require__) {

// style-loader: Adds some css to the DOM by adding a <style> tag

// load the styles
var content = __webpack_require__("../../../node_modules/css-loader/index.js!../../../node_modules/sass-loader/lib/loader.js!./assets/css/style.scss");
if(typeof content === 'string') content = [[module.i, content, '']];
// add the styles to the DOM
var update = __webpack_require__("../../../node_modules/style-loader/addStyles.js")(content, {});
if(content.locals) module.exports = content.locals;
// Hot Module Replacement
if(false) {
	// When the styles change, update the <style> tags
	if(!content.locals) {
		module.hot.accept("!!../../../../../node_modules/css-loader/index.js!../../../../../node_modules/sass-loader/lib/loader.js!./style.scss", function() {
			var newContent = require("!!../../../../../node_modules/css-loader/index.js!../../../../../node_modules/sass-loader/lib/loader.js!./style.scss");
			if(typeof newContent === 'string') newContent = [[module.id, newContent, '']];
			update(newContent);
		});
	}
	// When the module is disposed, remove the <style> tags
	module.hot.dispose(function() { update(); });
}

/***/ }),

/***/ "./html/directives/task.directive.html":
/***/ (function(module, exports) {

var path = '/html/directives/task.directive.html';
var html = "<!--- START View Task -->\n<div ng-if=\"item.display !== 'board'\">\n\t<div class=\"task-item list-task\">\n\t\t<div as-sortable-item-handle=\"\">\n\t\t\t<!-- start bootstrap grid -->\n\t\t\t<div class=\"list-draggable-area\" ng-attr-data-no-drag=\"{{item.noDrag()}}\">\n\t\t\t\t<div class=\"media\">\n\t\t\t\t\t<div class=\"mr-1\">\n\t\t\t\t\t\t<clang-checkbox name=\"checkbox_{{item.task.id}}\" large=\"1\" ng-model=\"item.task.is_complete\" ng-change=\"item.completeToggled($event)\" ng-show=\"item.task.perms.can_update\"></clang-checkbox>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"media-body\">\n\t\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t\t<div class=\"col-12\">\n\t\t\t\t\t\t\t\t<div class=\"media\">\n\t\t\t\t\t\t\t\t\t<div class=\"media-body\">\n\t\t\t\t\t\t\t\t\t\t<span ng-class=\"{'task-item-complete': item.task.is_complete}\">\n\t\t\t\t\t\t\t\t\t\t\t<a ng-if=\"item.task.title !== item.task.title_truncated\" ng-href=\"/projects/task/{{item.task.id}}\" rel=\"tooltip\" data-original-title=\"{{item.task.title}}\">{{item.task.title_truncated}}</a>\n\t\t\t\t\t\t\t\t\t\t\t<a ng-if=\"item.task.title === item.task.title_truncated\" ng-href=\"/projects/task/{{item.task.id}}\">{{item.task.title}}</a>\n\t\t\t\t\t\t\t\t\t\t\t<a ng-href=\"{{item.task.source.link}}\" ng-show=\"(item.showSource) && (item.task.source) && (item.task.source.name !== '')\"><span class=\"text-muted\">({{item.task.source.name}})</span></a>\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t\t<div class=\"ml-2\">\n\t\t\t\t\t\t\t\t\t\t<!--- edit -->\n\t\t\t\t\t\t\t\t\t\t<span ng-if=\"item.showEdit\" >\n\t\t\t\t\t\t\t\t\t\t\t<button class=\"js-task_edit_button_{{item.task.id}} btn btn-link btn-sm\" rel=\"tooltip\" lmsg=\"title:common.edit\" name=\"projects:task:edit\" ng-click=\"item.startTaskEdit($event, item.task.id)\" ng-if=\"item.task.perms.can_edit\">\n\t\t\t\t\t\t\t\t\t\t\t\t<ion-icon name=\"create-outline\"></ion-icon>\n\t\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\n\n\t\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t\t<div class=\"col-12 align-self-center\">\n\t\t\t\t\t\t\t\t<!--- due date -->\n\t\t\t\t\t\t\t\t<span ng-if=\"item.showDate\">\n\t\t\t\t\t\t\t\t\t<span class=\"py-1 pl-0 pr-2 pl-0 mr-2 float-left align-middle\" ng-if=\"item.task.due_date_formatted != ''\">\n\t\t\t\t\t\t\t\t\t\t<span ng-class=\"{'text-danger': item.task.due_date_type=='overdue', 'text-info': item.task.due_date_type=='today'}\">\n\t\t\t\t\t\t\t\t\t\t\t<ion-icon class=\"task-item-icon task-item-icon-gray\" name=\"calendar-outline\"></ion-icon>\n\t\t\t\t\t\t\t\t\t\t\t<span class=\"align-middle small\" ng-if=\"item.task.due_date_type!='today' && item.task.due_date_type!='tomorrow'\">{{item.task.due_date_formatted}}</span>\n\t\t\t\t\t\t\t\t\t\t\t<span class=\"align-middle small\" ng-if=\"item.task.due_date_type=='today'\" rel=\"tooltip\" data-original-title=\"{{item.task.due_date_formatted}}\">Today</span>\n\t\t\t\t\t\t\t\t\t\t\t<span class=\"align-middle small task-item-text\" ng-if=\"item.task.due_date_type=='tomorrow'\" rel=\"tooltip\" data-original-title=\"{{item.task.due_date_formatted}}\">Tomorrow</span>\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t</span>\n\n\t\t\t\t\t\t\t\t<!--- Status indicator -->\n\t\t\t\t\t\t\t\t<span ng-if=\"item.task.priority !== 0\" ng-switch=\"item.task.priority\" class=\"py-1 pl-0 pr-2 pl-0 mr-2 float-left align-middle\">\n\t\t\t\t\t\t\t\t\t<span class=\"priority-low text-success\" ng-switch-when=\"1\">\n\t\t\t\t\t\t\t\t\t\t<ion-icon class=\"task-item-icon\" name=\"arrow-down-outline\"></ion-icon>\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t<span class=\"priority-medium text-warning\" ng-switch-when=\"2\">\n\t\t\t\t\t\t\t\t\t\t<ion-icon class=\"task-item-icon\" name=\"arrow-up-outline\"></ion-icon>\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t<span class=\"priority-high text-danger\" ng-switch-when=\"3\">\n\t\t\t\t\t\t\t\t\t\t<ion-icon class=\"task-item-icon\" name=\"arrow-up-outline\"></ion-icon>\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t</span>\n\n\t\t\t\t\t\t\t\t<!--- private note -->\n\t\t\t\t\t\t\t\t<span ng-if=\"item.showPrivate\" class=\"float-left align-middle\">\n\t\t\t\t\t\t\t\t\t<span class=\"py-1 pl-0 pr-2 pl-0 mr-2 float-left\" ng-if=\"item.task.is_private\">\n\t\t\t\t\t\t\t\t\t\t<ion-icon class=\"task-item-icon task-item-icon-gray\" name=\"lock-closed-outline\"></ion-icon>\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t</span>\n\n\t\t\t\t\t\t\t\t<!--- comments -->\n\t\t\t\t\t\t\t\t<span class=\"float-left align-middle\">\n\t\t\t\t\t\t\t\t\t<a href=\"/projects/task/{{item.task.id}}\" class=\"py-1 pl-0 pr-2 pl-0 mr-2 float-left text-reset\" ng-if=\"item.task.comments_count>0\">\n\t\t\t\t\t\t\t\t\t\t<ion-icon class=\"task-item-icon task-item-icon-gray\" name=\"chatbox-outline\"></ion-icon>\n\t\t\t\t\t\t\t\t\t\t<span class=\"small task-item-text\">{{item.task.comments_count}}</span>\n\t\t\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t\t\t</span>\n\n\t\t\t\t\t\t\t\t<!--- files -->\n\t\t\t\t\t\t\t\t<span ng-if=\"item.showFiles\" class=\"float-left align-middle\">\n\t\t\t\t\t\t\t\t\t<a href=\"/projects/task/{{item.task.id}}#/filesTab\" ng-if=\"item.task.has_file_storage\" class=\"py-1 pl-0 pr-2 pl-0 mr-2 d-inline-block text-reset\">\n\t\t\t\t\t\t\t\t\t\t<ion-icon class=\"task-item-icon task-item-icon-gray\" name=\"attach-outline\"></ion-icon>\n\t\t\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t\t\t</span>\n\n\t\t\t\t\t\t\t\t<!-- Status -->\n\t\t\t\t\t\t\t\t<span class=\"float-left align-middle py-1 pl-0 pr-2 pl-0 mr-2\">\n\t\t\t\t\t\t\t\t\t<cla-badge styleclass=\"badge badge-pill badge-secondary\">{{(item.task.status_list | filter : {id: item.task.status_id})[0].name }}</cla-badge>\n\t\t\t\t\t\t\t\t</span>\n\n\t\t\t\t\t\t\t\t<!--- assigned to -->\n\t\t\t\t\t\t\t\t<div ng-if=\"item.showAssignees && item.task.assignees.length !== 0\" class=\"py-1 pl-0 pr-2 pl-0 float-left align-middle\">\n\t\t\t\t\t\t\t\t\t<clang-user-list class=\"users d-inline-block mr-2\" style=\"width: 130px;\" plusnumber=\"{{item.task.assignees.length - 3}}\" on-plus-clicked=\"item.additionalAssigneesClick()\">\n\t\t\t\t\t\t\t\t\t\t<a ng-href=\"{{user.profile_url}}\" ng-repeat=\"assignee in item.task.assignees | limitTo: 3\">\n\t\t\t\t\t\t\t\t\t\t\t<clang-user-list-item img=\"{{assignee.profile_img }}\" name=\"{{assignee.name}}\" profile=\"{{assignee.profile_url}}\"></clang-user-list-item>\n\t\t\t\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t\t\t\t</clang-user-list>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n\n<div ng-if=\"item.display === 'board'\">\n\n\t<div class=\"task-item form-inline board-task\" as-sortable-item-handle=\"\">\n\t\t<div class=\"list-draggable-area card rounded-corners d-block w-100\" ng-attr-data-no-drag=\"{{item.noDrag()}}\">\n\t\t\t<span class=\"card-status-border\" ng-style=\"{'background-color': item.list.list.colour}\"></span>\n\t\t\t<div class=\"card-body\">\n\t\t\t\t<div class=\"row\">\n\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t<div class=\"text-break board-task-title\">\n\t\t\t\t\t\t\t<a ng-if=\"item.task.title !== item.task.title_truncated\" ng-href=\"/projects/task/{{item.task.id}}\" rel=\"tooltip\" data-original-title=\"{{item.task.title}}\">{{item.task.title_truncated}}</a>\n\t\t\t\t\t\t\t<a ng-if=\"item.task.title === item.task.title_truncated\" ng-href=\"/projects/task/{{item.task.id}}\">{{item.task.title}}</a>\n\t\t\t\t\t\t\t<a ng-href=\"{{item.task.source.link}}\" ng-show=\"(item.showSource) && (item.task.source) && (item.task.source.name !== '')\">\n\t\t\t\t\t\t\t\t<span class=\"text-muted\">({{item.task.source.name}})</span>\n\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t<!--- due date -->\n\t\t\t\t\t\t<div class=\"mt-1\" ng-if=\"item.showDate\">\n\t\t\t\t\t\t\t<span ng-if=\"item.task.due_date_formatted != ''\">\n\t\t\t\t\t\t\t\t<span ng-class=\"{'text-danger': item.task.due_date_type=='overdue'}\">\n\t\t\t\t\t\t\t\t\t<span>Due: </span> {{item.task.due_date_formatted}}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"row mt-2\">\n\t\t\t\t\t<div class=\"col-7\">\n\t\t\t\t\t\t<!--- assigned to -->\n\t\t\t\t\t\t<div ng-if=\"item.showAssignees\" class=\"mt-1\">\n\t\t\t\t\t\t\t<clang-user-list class=\"users d-inline-block mr-2\" style=\"width:145px;\" plusnumber=\"{{item.task.assignees.length - 3}}\" on-plus-clicked=\"item.additionalAssigneesClick()\">\n\t\t\t\t\t\t\t\t<a ng-href=\"{{user.profile_url}}\" ng-repeat=\"assignee in item.task.assignees | limitTo: 3\">\n\t\t\t\t\t\t\t\t\t<clang-user-list-item img=\"{{assignee.profile_img }}\" name=\"{{assignee.name}}\" profile=\"{{assignee.profile_url}}\"></clang-user-list-item>\n\t\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t\t</clang-user-list>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"col-5\">\n\t\t\t\t\t\t<!--- Status indicator -->\n\t\t\t\t\t\t<span class=\"float-right mt-1\" ng-switch=\"item.task.priority\">\n\t\t\t\t\t\t\t<cla-status-indicator color=\"#5cb85c\" badgestyle=\"true\" size=\"x-small\" ng-switch-when=\"1\"><small>Low</small></cla-status-indicator>\n\t\t\t\t\t\t\t<cla-status-indicator color=\"#f0ad4e\" badgestyle=\"true\" size=\"x-small\" ng-switch-when=\"2\"><small>Medium</small></cla-status-indicator>\n\t\t\t\t\t\t\t<cla-status-indicator color=\"#d9534f\" badgestyle=\"true\" size=\"x-small\" ng-switch-when=\"3\"><small>High</small></cla-status-indicator>\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\n</div>\n<!--- END View Task -->\n";
window.angular.module('ng').run(['$templateCache', function(c) { c.put(path, html) }]);
module.exports = path;

/***/ }),

/***/ "./html/directives/taskAddButton.directive.html":
/***/ (function(module, exports) {

var path = '/html/directives/taskAddButton.directive.html';
var html = "<button class=\"btn btn-secondary btn-block btn-add-task\" ng-attr-id=\"{{add.id}}\" ng-click=\"add.startTaskEdit($event, add.sectionId)\">\n\t<ion-icon name=\"add-outline\"></ion-icon>\n\t<lmsg src=\"projects.task.add_task\">[Add Task]</lmsg>\n</button>\n";
window.angular.module('ng').run(['$templateCache', function(c) { c.put(path, html) }]);
module.exports = path;

/***/ }),

/***/ "./html/directives/taskEdit.directive.html":
/***/ (function(module, exports) {

var path = '/html/directives/taskEdit.directive.html';
var html = "<div class=\"modal fade js-task-edit-modal\" id=\"task-edit-modal\" tabindex=\"-2\" role=\"dialog\" aria-labelledby=\"task-edit-modal\">\n\t<div class=\"modal-dialog modal-xl\" role=\"document\">\n\t\t<div class=\"modal-content\" ng-if=\"edit.visible\">\n\n\t\t\t<div class=\"modal-header\">\n\t\t\t\t<h5 class=\"modal-title\" id=\"more-info--label\">\n\t\t\t\t\t<span lmsg=\"projects.task.modal.add_task\" ng-if=\"edit.task.id==0\">[Add task]</span>\n\t\t\t\t\t<span lmsg=\"projects.task.modal.edit_task\" ng-if=\"edit.task.id!=0\">[Edit task]</span>\n\t\t\t\t</h5>\n\t\t\t\t<button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Cancel\">\n\t\t\t\t\t<span aria-hidden=\"true\">\n\t\t\t\t\t\t<ion-icon name=\"close-outline\"></ion-icon>\n\t\t\t\t\t</span>\n\t\t\t\t</button>\n\t\t\t</div>\n\n\t\t\t<div class=\"modal-body\">\n\t\t\t\t<div class=\"form-horizontal\">\n\t\t\t\t\t<form id=\"task-edit-form\" class=\"form-horizontal\" name=\"taskForm\">\n\t\t\t\t\t\t<div class=\"form-group row\">\n\t\t\t\t\t\t\t<label for=\"\" class=\"col-form-label col-lg-2\" lmsg=\"projects.task.edit.task_name\">[Task Name]</label>\n\n\t\t\t\t\t\t\t<div class=\"col-lg-10\">\n\t\t\t\t\t\t\t\t<input type=\"text\" maxlength=\"255\" class=\"form-control\" placeholder=\"Task Name\" ng-model=\"edit.task.title\" lmsg=\"placeholder:projects.task.edit.task_name\">\n\t\t\t\t\t\t\t\t<div ng-show=\"edit.task.title.length > 255\">\n\t\t\t\t\t\t\t\t\t<br>\n\t\t\t\t\t\t\t\t\t<div class=\"alert alert-warning\">\n\t\t\t\t\t\t\t\t\t\t<lmsg src=\"projects.warning.field_longer_than_255\">[Length warning]</lmsg>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"form-group row\">\n\t\t\t\t\t\t\t<label for=\"taskDescription\" class=\"col-form-label col-lg-2\" lmsg=\"projects.task.edit.description\">[Description]</label>\n\t\t\t\t\t\t\t<div class=\"col-lg-10\">\n\t\t\t\t\t\t\t\t<cla-html-editor ng-model=\"edit.task.description\" application=\"projects\" control=\"edit.htmlControl\"></cla-html-editor>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t<div class=\"form-group row\">\n\t\t\t\t\t\t\t<label for=\"task-edit-user-picker-inner\" class=\"col-form-label col-lg-2\" name=\"projects:task:assigned_to\" lmsg=\"projects.task.assigned_to\">[Assigned to]</label>\n\n\t\t\t\t\t\t\t<div class=\"col-lg-10\">\n\t\t\t\t\t\t\t\t<clang-projects-user-picker select_id=\"{{edit.listPrefix}}user-picker-{{edit.unique_id}}\" ng-model=\"edit.task.assignees\" ng-change=\"taskAssigneeChanged(edit.task)\" project_id=\"{{edit.task.project_id}}\" user_name=\"{{edit.task.assigned_to.name}}\" allow_unset=\"0\" control=\"edit.userControl\"></clang-projects-user-picker>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"form-group row\">\n\t\t\t\t\t\t\t<label for=\"{{edit.listPrefix}}due_date-{{edit.unique_id}}-inner\" class=\"col-form-label col-lg-2\" lmsg=\"projects.task.properties.due_date\">[Due date]</label>\n\n\t\t\t\t\t\t\t<div class=\"col-lg-4\">\n\t\t\t\t\t\t\t\t<cla-date-picker id=\"task-edit-due_date\" ng-model=\"edit.task.due_date\" control=\"edit.task.control\"></cla-date-picker>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"form-group row\">\n\t\t\t\t\t\t\t<label for=\"task-edit-priority\" class=\"col-form-label col-lg-2\" lmsg=\"projects.task.properties.priority\">[Priority]</label>\n\n\t\t\t\t\t\t\t<div class=\"col-lg-4\">\n\t\t\t\t\t\t\t\t<div class=\"form-inline\">\n\t\t\t\t\t\t\t\t<select id=\"task-edit-priority\" name=\"priority\" ng-model=\"edit.task.priority\" class=\"form-control js-task-priorities js-task-edit-priority\">\n\t\t\t\t\t\t\t\t\t<option value=\"0\" lmsg=\"projects.task.priority.none\">[No priority]</option>\n\t\t\t\t\t\t\t\t\t<option value=\"1\" lmsg=\"projects.task.priority.low\">[Low priority]</option>\n\t\t\t\t\t\t\t\t\t<option value=\"2\" lmsg=\"projects.task.priority.medium\">[Medium priority]</option>\n\t\t\t\t\t\t\t\t\t<option value=\"3\" lmsg=\"projects.task.priority.high\">[High priority]</option>\n\t\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"form-group row\">\n\t\t\t\t\t\t\t<div class=\"col-md-12 col-sm-12\" ng-if=\"edit.task.project_id == 0\"></div>\n\t\t\t\t\t\t\t<div class=\"offset-lg-2 col-lg-10\" ng-if=\"edit.task.project_id > 0\">\n\t\t\t\t\t\t\t\t<div ng-if=\"edit.task.project_id > 0\">\n\t\t\t\t\t\t\t\t<div class=\"checkbox\">\n\t\t\t\t\t\t\t\t\t<label for=\"task-edit-private\">\n\t\t\t\t\t\t\t\t\t\t<input type=\"checkbox\" id=\"task-edit-private\" ng-model=\"edit.task.is_private\">\n\t\t\t\t\t\t\t\t\t\t<ion-icon name=\"lock-closed-outline\"></ion-icon>\n\t\t\t\t\t\t\t\t\t\t<lmsg src=\"projects.task.properties.is_private\">[Private Task]</lmsg>\n\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<p class=\"text-muted\">\n\t\t\t\t\t\t\t\t\t<span lmsg=\"projects.task.properties.is_private_message\">[Users can always see tasks assigned to them]</span>\n\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"form-group row\">\n\t\t\t\t\t\t\t<label for=\"task-edit-duration\" class=\"col-lg-2 col-form-label\" lmsg=\"projects.task.expected_duration\">\n\t\t\t\t\t\t\t\t[expected duration]\n\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t<div class=\"col-lg-10\">\n\t\t\t\t\t\t\t\t<div class=\"form-inline\">\n\t\t\t\t\t\t\t\t<input type=\"text\" name=\"duration\" id=\"task-edit-duration\" class=\"form-control mr-2\" size=\"2\" ng-model=\"edit.task.duration\" ng-pattern=\"/^$|^(0|[1-9]\\d*)([.]\\d+)?$/\" value=\"0\">\n\t\t\t\t\t\t\t\t<span ng-class=\"{'hide-unit': edit.task.project_id < 1}\">{{edit.task.duration_units}}</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<p class=\"text-danger\" ng-if=\"taskForm.duration.$invalid\">\n\t\t\t\t\t\t\t\t\t<lmsg src=\"projects.task.duration_value_warning\">[Please input a valid duration value (number)]</lmsg>\n\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</form>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"modal-footer\">\n\t\t\t\t<button class=\"btn btn-primary\" ng-click=\"edit.saveTaskEdit($event, task)\" ng-disabled=\"taskForm.duration.$invalid\" lmsg=\"projects.task.save_task\">[Save]</button>\n\t\t\t\t<button class=\"btn btn-danger\" rel=\"tooltip\" ng-click=\"edit.deleteTask($event, task)\" ng-show=\"edit.task.perms.can_edit\"><lmsg src=\"projects.task.delete\">[Delete]</lmsg></button>\n\t\t\t\t<button class=\"btn btn-link\" ng-click=\"edit.cancelTaskEdit($event, task)\" lmsg=\"projects.task.cancel\">[Cancel]</button>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n";
window.angular.module('ng').run(['$templateCache', function(c) { c.put(path, html) }]);
module.exports = path;

/***/ }),

/***/ "./html/directives/tasklist/tasklist.directive.html":
/***/ (function(module, exports) {

var path = '/html/directives/tasklist/tasklist.directive.html';
var html = "<div class=\"row\">\n\t<div class=\"col-md-4 align-self-center task-toolbar-section\">\n\t\t<div id=\"js-jump-to-top-of-list\"></div>\n\t\t<form action=\"\" role=\"inline\">\n\t\t\t<div class=\"input-group\">\n\t\t\t\t<input class=\"form-control\" ng-model=\"ctrl.searchTerms\" ng-change=\"ctrl.search()\" type=\"text\" lmsg=\"placeholder:projects.tasks.list.search.placeholder\" id=\"\" placeholder=\"[Search tasks...]\">\n\n\t\t\t\t<div class=\"input-group-append\">\n\t\t\t\t\t<button ng-click=\"ctrl.search($event)\" class=\"btn btn-primary\" type=\"submit\">\n\t\t\t\t\t\t<ion-icon name=\"search-outline\"></ion-icon>\n\t\t\t\t\t</button>\n\t\t\t\t\t<a class=\"btn btn-secondary\" data-toggle=\"collapse\" data-target=\"#taskFilterCollapse\" rel=\"tooltip\" title=\"[Advanced Filter]\" lmsg=\"title:projects.tasks.list.advanced.filter\" role=\"button\" aria-expanded=\"false\" aria-controls=\"taskFilterCollapse\">\n\t\t\t\t\t\t<ion-icon name=\"filter-outline\"></ion-icon>\n\t\t\t\t\t</a>\n\t\t\t\t</div>\t\n\t\t\t</div>\n\t\t</form>\n\t</div>\n\n\t<div class=\"col-md-4 offset-md-4 align-self-center task-toolbar-section\">\n\t\t<clang-task-list-type ng-if=\"ctrl.currentTaskFilter === 'my_tasks'\" ng-model=\"ctrl.view_mode\" list-name=\"{{ctrl.customOrderTitle}}\" date-name=\"{{ctrl.dateCategoriesTitle}}\"></clang-task-list-type>\n\t\t<clang-task-list-type ng-if=\"ctrl.currentTaskFilter !== 'my_tasks'\" ng-model=\"ctrl.view_mode\" list-name=\"{{ctrl.defaultOrderTitle}}\" date-name=\"{{ctrl.dateCategoriesTitle}}\"></clang-task-list-type>\n\t</div>\n</div>\n\n<div class=\"row my-3\">\n\t<div id=\"taskFilterCollapse\" class=\"col-md-8 align-self-center task-toolbar-section collapse\">\n\t\t<clang-projects-user-picker ng-change=\"ctrl.userFilterChange()\" ng-model=\"ctrl.userFilter\" allow_unset=\"0\" project_id=\"0\" allow_blocked=\"1\"></clang-projects-user-picker>\n\t</div>\n</div>\n\n<div class=\"row\" ng-if=\"ctrl.getTaskFilter() === 'my_tasks' && ctrl.tasks.length === 0\">\n\t<br>\n\t<div class=\"col-md-12\">\n\t\t<span class=\"alert alert-info alert-full-width\" lmsg=\"projects.tasks.no_tasks_assigned\">[You don't have any tasks assigned to you]</span>\n\t</div>\n</div>\n\n<div class=\"row\" ng-if=\"ctrl.getTaskFilter() === 'all_tasks' && ctrl.tasks.length === 0\">\n\t<br>\n\t<div class=\"col-md-12\">\n\t\t<span class=\"alert alert-info alert-full-width\" lmsg=\"projects.tasks.no_tasks_found\">[No tasks were found to match your search]</span>\n\t</div>\n</div>\n\n<div class=\"row project-list\" ng-if=\"ctrl.view_mode=='list_view' || ctrl.getStatusFilter() != 'open'\">\n\t<div class=\"col-md-12\">\n\t\t<ul class=\"list-unstyled task-list-items\" ng-model=\"ctrl.tasks\">\n\t\t\t<li dir-paginate=\"task in ctrl.tasks | itemsPerPage: ctrl.tasksPerPage\" pagination-id=\"list_view\" total-items=\"ctrl.allTasksCount\" current-page=\"ctrl.currentPage\" ng-show=\"false\">\n\t\t\t</li>\n\t\t</ul>\n\n\t\t<ul class=\"list-unstyled task-list-items js-draggable\" ng-if=\"ctrl.getTaskFilter()==='my_tasks'\" as-sortable=\"ctrl.dragTaskListeners\" ng-model=\"ctrl.tasks\" id=\"myTasks\">\n\t\t\t<li ng-repeat=\"task in ctrl.tasks\" class=\"task-list-item as-sortable-item\" as-sortable-item=\"\" data-task-id=\"{{task.id}}\">\n\t\t\t\t<project-task-item show-source=\"true\" use-drag-and-drop=\"true\" task=\"task\" list_prefix=\"all_\" task_update=\"ctrl.taskUpdatedCallback(task);\" task_delete=\"ctrl.taskDeletedCallback(task);\" task_complete_toggled=\"ctrl.taskCompleteToggledCallback(task);\" allow-drag=\"!ctrl.isMobile\"></project-task-item>\n\t\t\t</li>\n\t\t</ul>\n\t\t<ul class=\"list-unstyled task-list-items\" ng-if=\"ctrl.getTaskFilter()!=='my_tasks'\" ng-model=\"ctrl.tasks\" as-sortable=\"\" is-disabled=\"true\">\n\t\t\t<li ng-repeat=\"task in ctrl.tasks\" class=\"task-list-item\" as-sortable-item=\"\">\n\t\t\t\t<project-task-item show-source=\"true\"  task=\"task\" list_prefix=\"all_\" task_update=\"ctrl.taskUpdatedCallback(task);\" task_delete=\"ctrl.taskDeletedCallback(task);\" task_complete_toggled=\"ctrl.taskCompleteToggledCallback(task);\"></project-task-item>\n\t\t\t</li>\n\t\t</ul>\n\n\t\t<div class=\"text-center clearfix mt-2\">\n\t\t\t<dir-pagination-controls pagination-id=\"list_view\" on-page-change=\"ctrl.pageChanged(newPageNumber, 'list_view')\" template-url=\"/intranet/projects/html/components/project_list/pagination.html\"></dir-pagination-controls>\n\t\t</div>\n\t</div>\n</div>\n\n<div class=\"row project-list\" ng-if=\"ctrl.view_mode=='date_view' && ctrl.getStatusFilter() == 'open'\">\n\t<div class=\"col-md-12\">\n\t\t<div dir-paginate=\"masterTask in ctrl.tasks | itemsPerPage: ctrl.tasksPerPage\" pagination-id=\"date_view\" total-items=\"ctrl.allTasksCount\" current-page=\"ctrl.currentPage\" class=\"task-list-item\" ng-show=\"false\">\n\t\t</div>\n\t\t<div ng-show=\"ctrl.due_date_counts.overdue > 0\">\n\t\t\t<h5 class=\"mb-0 mt-3\" lmsg=\"projects.tasks.overdue\">[Overdue]</h5>\n\t\t\t<ul class=\"list-unstyled task-list-items\" ng-model=\"ctrl.tasks\" as-sortable=\"\" is-disabled=\"true\">\n\t\t\t\t<li ng-repeat=\"task in ctrl.tasks\" class=\"task-list-item\" ng-if=\"task.due_date_type=='overdue'\" as-sortable-item=\"\">\n\t\t\t\t\t<project-task-item show-source=\"true\" task=\"task\" list_prefix=\"dd_\" task_update=\"ctrl.taskUpdatedCallback(task);\" task_delete=\"ctrl.taskDeletedCallback(task);\" task_complete_toggled=\"ctrl.taskCompleteToggledCallback(task);\"></project-task-item>\n\t\t\t\t</li>\n\t\t\t</ul>\n\t\t</div>\n\n\t\t<div ng-show=\"ctrl.due_date_counts.today > 0\">\n\t\t\t<h5 class=\"mb-0 mt-3\" lmsg=\"projects.tasks.today\">[Today]</h5>\n\t\t\t<ul class=\"list-unstyled task-list-items\" ng-model=\"ctrl.tasks\" as-sortable=\"\" is-disabled=\"true\">\n\t\t\t\t<li ng-repeat=\"task in ctrl.tasks\" class=\"task-list-item\" ng-if=\"task.due_date_type=='today'\" as-sortable-item=\"\">\n\t\t\t\t\t<project-task-item show-source=\"true\" task=\"task\" list_prefix=\"dd_\" task_update=\"ctrl.taskUpdatedCallback(task);\" task_delete=\"ctrl.taskDeletedCallback(task);\" task_complete_toggled=\"ctrl.taskCompleteToggledCallback(task);\"></project-task-item>\n\t\t\t\t</li>\n\t\t\t</ul>\n\t\t</div>\n\n\t\t<div ng-show=\"ctrl.due_date_counts.tomorrow > 0\">\n\t\t\t<h5 class=\"mb-0 mt-3\" lmsg=\"projects.tasks.tomorrow\">[Tomorrow]</h5>\n\t\t\t<ul class=\"list-unstyled task-list-items\" ng-model=\"ctrl.tasks\" as-sortable=\"\" is-disabled=\"true\">\n\t\t\t\t<li ng-repeat=\"task in ctrl.tasks\" class=\"task-list-item\" ng-if=\"task.due_date_type=='tomorrow'\" as-sortable-item=\"\">\n\t\t\t\t\t<project-task-item show-source=\"true\" task=\"task\" list_prefix=\"dd_\" task_update=\"ctrl.taskUpdatedCallback(task);\" task_delete=\"ctrl.taskDeletedCallback(task);\" task_complete_toggled=\"ctrl.taskCompleteToggledCallback(task);\"></project-task-item>\n\t\t\t\t</li>\n\t\t\t</ul>\n\t\t</div>\n\n\t\t<div ng-show=\"ctrl.due_date_counts.later > 0\">\n\t\t\t<h5 class=\"mb-0 mt-3\" lmsg=\"projects.tasks.later\">[Later]</h5>\n\t\t\t<ul class=\"list-unstyled task-list-items\" ng-model=\"ctrl.tasks\" as-sortable=\"\" is-disabled=\"true\">\n\t\t\t\t<li ng-repeat=\"task in ctrl.tasks\" class=\"task-list-item\" ng-if=\"task.due_date_type=='later'\" as-sortable-item=\"\">\n\t\t\t\t\t<project-task-item show-source=\"true\" task=\"task\" list_prefix=\"dd_\" task_update=\"ctrl.taskUpdatedCallback(task);\" task_delete=\"ctrl.taskDeletedCallback(task);\" task_complete_toggled=\"ctrl.taskCompleteToggledCallback(task);\"></project-task-item>\n\t\t\t\t</li>\n\t\t\t</ul>\n\t\t</div>\n\n\t\t<div ng-show=\"ctrl.due_date_counts.no_due_date > 0\">\n\t\t\t<h5 class=\"mb-0 mt-3\" lmsg=\"projects.tasks.no_due_date\">[No Due Date]</h5>\n\t\t\t<ul class=\"list-unstyled task-list-items\" ng-model=\"ctrl.tasks\" as-sortable=\"\" is-disabled=\"true\">\n\t\t\t\t<li ng-repeat=\"task in ctrl.tasks\" class=\"task-list-item\" ng-if=\"task.due_date_type=='no_due_date'\" as-sortable-item=\"\">\n\t\t\t\t\t<project-task-item show-source=\"true\" task=\"task\" list_prefix=\"dd_\" task_update=\"ctrl.taskUpdatedCallback(task);\" task_delete=\"ctrl.taskDeletedCallback(task);\" task_complete_toggled=\"ctrl.taskCompleteToggledCallback(task);\"></project-task-item>\n\t\t\t\t</li>\n\t\t\t</ul>\n\t\t</div>\n\t\t<div class=\"text-center clearfix mt-2\">\n\t\t\t<dir-pagination-controls pagination-id=\"date_view\" on-page-change=\"ctrl.pageChanged(newPageNumber, 'date_view')\" template-url=\"/intranet/projects/html/components/project_list/pagination.html\"></dir-pagination-controls>\n\t\t</div>\n\t</div>\n</div>\n<div class=\"row\">\n\t<div class=\"col-md-12\">\n\t\t<project-task-add section_id=\"0\" project_id=\"0\" on_task_added=\"ctrl.taskAddedCallback(task)\"></project-task-add>\n\t</div>\n</div>\n";
window.angular.module('ng').run(['$templateCache', function(c) { c.put(path, html) }]);
module.exports = path;

/***/ }),

/***/ "./html/directives/tasklist/tasklist_filters.directive.html":
/***/ (function(module, exports) {

var path = '/html/directives/tasklist/tasklist_filters.directive.html';
var html = "<div class=\"p-3\">\n\t<ul class=\"nav flex-column\">\n\t\t<li class=\"nav-item\">\n\t\t\t<h5 class=\"nav-title\">Tasks</h5>\n\t\t</li>\n\t\t<li class=\"nav-item\" ng-class=\"{active: filter.type === ctrl.currentTaskFilter}\" ng-repeat=\"filter in ctrl.task_filters\">\n\t\t\t<a class=\"nav-link\" ng-class=\"{disabled: filter.count === ''}\"  href=\"/projects/tasks?task_filter={{filter.type}}\" ng-click=\"ctrl.setTaskFilter($event, filter.type, filter.count);\">\n\t\t\t\t<span class=\"badge badge-light badge-pill float-right\">{{filter.count}}</span>\n\t\t\t\t{{filter.label}}\n\t\t\t</a>\n\t\t</li>\n\t</ul>\n\n\t<ul class=\"nav flex-column\">\n\t\t<li class=\"nav-item\">\n\t\t\t<h5 class=\"nav-title\">Status</h5>\n\t\t</li>\n\t\t<li class=\"nav-item\" ng-class=\"{active: filter.type === ctrl.currentStatusFilter}\" ng-repeat=\"filter in ctrl.status_filters\">\n\t\t\t<a class=\"nav-link\" ng-class=\"{disabled: filter.count === ''}\" href=\"/projects/tasks?status_filter={{filter.type}}\" ng-click=\"ctrl.setStatusFilter($event, filter.type, filter.count);\" >\n\t\t\t\t<span class=\"badge badge-light badge-pill float-right\">{{filter.count}}</span>\n\t\t\t\t{{filter.label}}\n\t\t\t</a>\n\t\t</li>\n\t</ul>\n</div>\n";
window.angular.module('ng').run(['$templateCache', function(c) { c.put(path, html) }]);
module.exports = path;

/***/ }),

/***/ "./js/controller/taskListCtrl.js":
/***/ (function(module, exports) {

(function()
{
	var moduleName = 'taskListApp';

	angular.module(moduleName)
		.controller("taskListCtrl", ['breadcrumb.service', taskListController]);

	function taskListController(breadcrumbService)
	{
		breadcrumbService.setCrumbs(
		[
			{
				'url': '/projects',
				'name': lmsg('projects.breadcrumb.projects')
			},
			{
				'url': '/projects/tasks',
				'name': lmsg('projects.breadcrumb.tasks')
			}
		]);
	}
}());


/***/ }),

/***/ "./js/directive/datePicker.js":
/***/ (function(module, exports) {

(function()
{
	var moduleName = 'claromentis.project';
	var module;

	try {
		module = angular.module(moduleName);
	} catch(err) {
		// named module does not exist, so create one
		module = angular.module(moduleName, []);
	}

	module
		.directive('claDatePicker', ['$timeout', claDatePicker]);

	function claDatePicker($timeout)
	{
		controller.$inject = ['$scope'];
		return {
			restrict: 'E',
			require: '^ngModel',
			templateUrl: '/intranet/projects/html/components/date_picker.html',
			scope: {
				ngModel: '=',
				control: '='
			},
			controller: controller,
			link: link
		};

		function controller($scope)
		{
            this.$onInit = function() {
                $scope.control.reset = function(){
                    angular.element('#' + $scope.id + '-inner').datetimepicker('clear');
                };
            };
		}

		function link(scope, iElement, iAttrs, ctrl)
		{
			scope.id = iAttrs.id;
			scope.name = iAttrs.name;
			scope.ctrl = ctrl;


			ctrl.$viewChangeListeners.push(function() {
				scope.$eval(iAttrs.ngChange);
			});

			angular.element('#' + scope.id + '-inner').on('blur', function(){
				element = $('#' + scope.id + '-inner');
				newval = element.val();
				ctrl.$setViewValue(newval);
			});

			$timeout(function()
			{
				date_picker_init(angular.element('#' + scope.id + '-inner'));
			}, 0);
		}
	}
}());


/***/ }),

/***/ "./js/directive/tasklist/tasklist.directive.js":
/***/ (function(module, exports, __webpack_require__) {

(function()
{
    var moduleName = 'taskListApp';
    var template = __webpack_require__("./html/directives/tasklist/tasklist.directive.html");

    angular.module(moduleName)
        .directive('clangTasklist', taskList);

    taskList.$inject = ['$http', 'tasklistService', 'Task', '$anchorScroll'];
    function taskList($http, service, Task, $anchorScroll)
    {
        return {
            restrict: 'E',
            templateUrl: template,
            scope: {},
            controllerAs: 'ctrl',
            bindToController: true,
            controller: controller,
            link: link
        };

        function controller()
        {
            var ctrl = this;

            ctrl.searchTerms = service.searchTerms;
            ctrl.tasks = [];
            ctrl.isMobile = true ;
            ctrl.view_mode = 'list_view';

            ctrl.currentTaskFilter = 'my_tasks';
            ctrl.listViewName = lmsg('projects.tasks.custom_order');

            // Label for view type
            ctrl.listViewName = lmsg('projects.tasks.list_view');

            ctrl.customOrderTitle = lmsg('projects.tasks.display.custom_order');
            ctrl.dateCategoriesTitle = lmsg('projects.tasks.display.due_date');
            ctrl.defaultOrderTitle = lmsg('projects.tasks.display.default_order');

            this.$onInit = function() {
                $anchorScroll.yOffset = angular.element(".claro-navbar")
                ctrl.replaceTasks(service.tasks, service.task_count, service.tasks_per_page, service.currentPage);
                ctrl.countDueDateTypes();

                service.onChange(function(new_tasks, count, limit, current_page)
                {
                    ctrl.replaceTasks(new_tasks, count, limit, current_page)
                    ctrl.countDueDateTypes();
                });
            };

            ctrl.resetNewTask = function()
            {
                ctrl.new_task.loadFromArray(
                    {
                        id: 0,
                        project_id: 0,
                        section_id: 0,
                        title: '',
                        description: '',
                        due_date: '',
                        due_date_formatted: '',
                        due_date_type: 'no_due_date',
                        is_private: false,
                        assigned_to: '',
                        priority: '0',
                        is_complete: false,
                        duration: '',
                        duration_units: ctrl.duration_units,
                        orders: [],

                        is_complete_server: false,
                        is_edit: false
                    });
                ctrl.new_task.assigned_to_id = null;
            };

            ctrl.new_task = new Task();
            ctrl.resetNewTask();

            ctrl.removeTask = function(task)
            {
                // Delete the task from the master list
                var task_list = [];
                for (var i = 0; i < ctrl.tasks.length; i++)
                {
                    if (ctrl.tasks[i].id != task.id)
                        task_list.push(ctrl.tasks[i]);
                }

                ctrl.replaceTasks(task_list);

                // Get full page data to fill in permissions and filter counts
                service.getResultsPage();
            };

            ctrl.countDueDateTypes = function()
            {
                ctrl.due_date_counts = {overdue:0, today:0, tomorrow:0, later:0, no_due_date:0};

                for (var i = 0; i < ctrl.tasks.length; i++)
                {
                    var task = ctrl.tasks[i];

                    switch(task.due_date_type)
                    {
                        case 'overdue':
                        {
                            ctrl.due_date_counts.overdue++;
                            break;
                        }
                        case 'today':
                        {
                            ctrl.due_date_counts.today++;
                            break;
                        }
                        case 'tomorrow':
                        {
                            ctrl.due_date_counts.tomorrow++;
                            break;
                        }
                        case 'later':
                        {
                            ctrl.due_date_counts.later++;
                            break;
                        }
                        default:
                        {
                            ctrl.due_date_counts.no_due_date++;
                            break;
                        }
                    }
                }
            };

            // Can't use the orderBy clause of ng-repeat for this because it automatically reorders it when using drag and drop before I have a chance to get the new order.
            ctrl.putTasksInDisplayOrder = function()
            {
                ctrl.tasks.sort(function(a, b)
                {
                    if (a.orders.my_tasks > b.orders.my_tasks)
                        return 1;
                    if (a.orders.my_tasks < b.orders.my_tasks)
                        return -1;
                    return 0;
                });
            };

            ctrl.replaceTasks = function(new_tasks, count, limit, current_page)
            {
                ctrl.tasks.length = 0;
                for (var i = 0; i < new_tasks.length; i++)
                {
                    var task = new Task();
                    task.loadFromArray(new_tasks[i]);
                    task.due_date_type = new_tasks[i].due_date_type;
                    task.is_complete_server = new_tasks[i].is_complete;
                    task.due_date_formatted = new_tasks[i].due_date_formatted;
                    ctrl.tasks.push(task);
                }

                ctrl.currentTaskFilter = service.currentTaskFilter;
                if (ctrl.view_mode === 'list_view' && ctrl.currentTaskFilter === 'my_tasks')
                    ctrl.putTasksInDisplayOrder();

                ctrl.allTasksCount = count;
                ctrl.tasksPerPage = limit;
                ctrl.currentPage = current_page;
            };

            ctrl.search = function (event)
            {
                // event will only be valid if this came from the search button, typing won't have one.
                if (typeof event === 'object')
                    event.preventDefault();
                ctrl.currentPage = 1;
                service.setSearch(ctrl.searchTerms);
                service.getResultsPage();
            };

            ctrl.taskOrderChanged = function(event)
            {
                var newOrder = [];
                var index = 1;
                var tasks = event.dest.sortableScope.$parent.ctrl.tasks;
                for (var task_index = 0; task_index < tasks.length; task_index++)
                {
                    var id = tasks[task_index].id;
                    for (var i = 0; i < ctrl.tasks.length; i++)
                    {
                        if (ctrl.tasks[i].id == id)
                            ctrl.tasks[i].orders.list = index;
                    }

                    newOrder.push(id);
                }

                $http.post('/api/projects/task/order',
                    {
                        'newOrder': {'order': newOrder},
                        'taskFilter': ctrl.currentTaskFilter
                    }).then(null, function(response)
                {
                    cla.showMessage(response.data.error, response.data.message, true);
                });
            };

            ctrl.dragTaskListeners =
            {
                orderChanged: ctrl.taskOrderChanged,
                containment: '.js-drag-container',
                containerPositioning: 'relative'
            };

            ctrl.userFilterChange = function()
            {
                service.setUser(ctrl.userFilter);
                service.getResultsPage();
            };

            ctrl.startTaskAdd = function(event)
            {
                event.preventDefault();
                ctrl.new_task.is_edit = true;
                ctrl.enableNewTaskPriority();
            };



            ctrl.taskUpdatedCallback = function(task)
            {
                ctrl.countDueDateTypes();
            };

            ctrl.taskDeletedCallback = function(task)
            {
                ctrl.removeTask(task);
            };

            ctrl.taskCompleteToggledCallback = function(task)
            {
                var master_task_index = 0;
                for (var i = 0; i < ctrl.tasks.length; i++)
                {
                    if (ctrl.tasks[i].id == task.id)
                        master_task_index = i;
                }

                if (task.is_complete)
                {
                    task.setComplete(function()
                    {
                        service.getResultsPage();
                    }, function(task, response)
                    {
                        task.is_complete = false;
                        cla.showMessage(response.error, '', true);
                    });
                    ctrl.tasks[master_task_index] = task;
                } else
                {
                    task.setIncomplete(function()
                    {
                        service.getResultsPage();
                    }, function(task, response)
                    {
                        task.is_complete = true;
                        cla.showMessage(response.error, '', true);
                    });
                    ctrl.tasks[master_task_index] = task;
                }
            };

            ctrl.taskAddedCallback = function(task)
            {
                // Add the task to the list manually  to give quick feedback.
                var new_task = angular.extend(new Task(), task);
                new_task.assigned_to = task.assigned_to;
                new_task.source = {name:'', link:''};
                ctrl.tasks.push(new_task);
                ctrl.countDueDateTypes();

                ctrl.resetNewTask();

                // Get full page data to fill in permissions and filter counts
                service.getResultsPage();
            };

            ctrl.enableNewTaskPriority = function()
            {
                var select = $('#new-task-edit-section-0 .js-task-priorities');
                if (select.hasClass('select2-container'))
                    return;

                // This should be automatic but it is invisible still at this point so not processed yet.
                select.val(ctrl.new_task.priority);

                ctrl.colourSelect(select);
            };

            ctrl.updateHistoryLog = function()
            {
                $scope.$root.$broadcast('updateHistoryLog', null);
            };

            ctrl.colourSelect = function(target)
            {
                target.select2({
                    formatResult: function (data)
                    {
                        if (!data.id) { return data.text; }
                        return '<span class="task-priority-option task-priority-' + data.id + '" style="display:inline-block; margin-right:0;">&nbsp</span> ' + data.text;
                    },
                    formatSelection: function formatPrioritySelection (data)
                    {
                        if (!data.id) { return data.text; }
                        return '<span class="task-priority-option task-priority-' + data.id + '" style="display:inline-block; margin-right:0;">&nbsp</span> ' + data.text;
                    },
                    escapeMarkup: function(markup)
                    {
                        return markup;
                    },
                    minimumResultsForSearch: Infinity // Hide search box
                });
            };

            ctrl.pageChanged = function(newPageNumber, source)
            {
                if (source == ctrl.view_mode) {
                    $anchorScroll("js-jump-to-top-of-list");
                    service.changePage(newPageNumber);
                }
            };

            ctrl.getStatusFilter = function()
            {
                return service.currentStatusFilter;
            }

            ctrl.getTaskFilter = function()
            {
                return service.currentTaskFilter;
            }
        }

        function link(scope, element, attr, ctrl)
        {
            ctrl.isMobile = document.body.clientWidth <= 768;

            angular.element(window).on('resize', function(event) {
                ctrl.isMobile = document.body.clientWidth <= 768;
                scope.$digest();
            });
        }
    }
}());


/***/ }),

/***/ "./js/directive/tasklist/tasklist.service.js":
/***/ (function(module, exports, __webpack_require__) {

(function()
{
    var moduleName = 'taskListApp';

    var instance = new TaskListService();

    var Url = __webpack_require__(8);

    angular.module(moduleName)
        .service('tasklistService', ['$http', 'tasklistPreloadFactory', function($http, taskListPreloadFactory) {
            instance.setInjectables($http, taskListPreloadFactory);
            return instance;
        }]);

    function TaskListService()
    {
        var service = this;

        service.$http = undefined;

        service.due_date_counts = {overdue:0, today:0, tomorrow:0, later:0, no_due_date:0};

        service.changeCallbacks = [];
        service.onChange = function(callable)
        {
            service.changeCallbacks.push(callable);
        }

        service.changePage = function (new_page_number) {

            if (new_page_number != service.currentPage) {
                service.currentPage = new_page_number;
                service.getResultsPage();
            }
        }

        // Load new task list data, using the current filters
        service.getResultsPage = function(suppress_history)
        {
            var query_params = {
                'task_filter': service.currentTaskFilter,
                'status_filter': service.currentStatusFilter,
            }

            if (service.searchTerms.length > 0)
                query_params.search = service.searchTerms;

            if (service.currentPage > 1)
                query_params.page = service.currentPage;

            // for multiple assignees add users as a array to the GET request
            if (Array.isArray(service.userFilter) && service.userFilter.length > 0)
            {
                service.userFilter.forEach(function (user, index) {
                    query_params['user_filter[' + index + ']'] = user;
                });
            }

            if (suppress_history !== true) {
                var url_history = new Url('tasks', {}, true);
                url_history.set('query', query_params);

                window.history.pushState({}, '', url_history.href);
            }

            var url = new Url('/projects/tasks', {}, true);
            query_params.format = 'json';
            url.set('query', query_params);

            service.$http.get(url.href)
                .then(function(result) {
                    service.task_filters = result.data.task_filter_count;
                    service.status_filters = result.data.status_filter_count;

                    for (var i = 0; i < service.changeCallbacks.length; i++)
                    {
                        service.changeCallbacks[i](result.data.tasks, result.data.task_count, result.data.tasks_per_page, result.data.current_page);
                    }

                    // This is needed due to a conflict between Angular and select2. When choosing a user via the 'browse' popup window (using $.select2('data', ...)) it correctly
                    // updates the Angular model which triggers this AJAX request but does not display the user name. So it needs to be a applied a second time post-render.
                    // Update. It also has to run after the current $digest or $apply call finishes so applying a small delay before it is called.
                    if (result.data.filtered_user_ids !== null)
                        setTimeout(function(id, name){window.UserPicker_SetUser('user_filter', id, name);}, 50, result.data.filtered_user_ids, result.data.user_filter_name);
                }
            );
        };

        service.setSearch = function(search)
        {
            service.searchTerms = search;
        }

        service.setUser = function(user_id)
        {
            service.userFilter = user_id;
        }

        service.setInjectables = function($http, factory)
        {
            service.$http = $http;

            // Set up filter vars and highlight the right one
            service.tasks = factory.tasks;
            service.task_count = factory.task_count;
            service.currentPage = factory.current_page;
            service.tasks_per_page = factory.tasks_per_page;
            service.task_filters = factory.task_filters;
            service.status_filters = factory.status_filters;
            service.currentTaskFilter = factory.current_task_filter;
            service.currentStatusFilter = factory.current_status_filter;
            service.searchTerms = factory.searchTerms;
            service.userFilter = factory.initial_user_filter;
            service.duration_units = factory.duration_units;
        }
    }
}());


/***/ }),

/***/ "./js/directive/tasklist/tasklist_filters.directive.js":
/***/ (function(module, exports, __webpack_require__) {

(function()
{
    var moduleName = 'taskListApp';
    var template = __webpack_require__("./html/directives/tasklist/tasklist_filters.directive.html");

    angular.module(moduleName)
        .directive('clangTasklistFilters', taskListFilters);

    taskListFilters.$inject = ['tasklistService'];
    function taskListFilters(service)
    {
        return {
            restrict: 'E',
            templateUrl: template,
            scope: {},
            controllerAs: 'ctrl',
            bindToController: true,
            controller: controller
        };

        function controller($scope, $timeout)
        {
            var ctrl = this;

            ctrl.task_filters = [];
            ctrl.status_filters = [];

            this.$onInit = function() {
                ctrl.initData();

                service.onChange(function()
                {
                    ctrl.initData();
                });
            };

            ctrl.initData = function()
            {
                ctrl.currentTaskFilter = service.currentTaskFilter;
                ctrl.task_filters.length = 0;
                for (var i = 0; i < service.task_filters.length; i++)
                {
                    ctrl.task_filters.push(service.task_filters[i]);
                }

                ctrl.currentStatusFilter = service.currentStatusFilter;
                ctrl.status_filters.length = 0;
                for (var i = 0; i < service.status_filters.length; i++)
                {
                    ctrl.status_filters.push(service.status_filters[i]);
                }

                // Force a directive redraw after this one has finished (ng doesn't know that visible data has changed to do it automatically)
                $timeout(function() {
                    $scope.$digest();
                }, 0);
            }

            // Listen for the back or forward buttons being pressed and adjust the page content according to the URL
            window.addEventListener('popstate', function()
            {
                // Store current state to check if anything changed later
                var oldTaskFilter = ctrl.currentTaskFilter;
                var oldStatusFilter = ctrl.currentStatusFilter;
                var oldPage = ctrl.currentPage;
                var oldUserFilter = ctrl.userFilter;
                var oldSearchTerms = ctrl.searchTerms;

                // Reset all filters to default values
                ctrl.currentTaskFilter = 'my_tasks';
                ctrl.currentStatusFilter = 'open';
                ctrl.userFilter = null;
                ctrl.currentPage = 1;
                ctrl.searchTerms = '';

                // Set filters according to URL
                var params = History.getState().hash.split('?')[1];
                if (typeof params !== 'undefined')
                {
                    var parts = params.split('&');

                    for (var i = 0; i < parts.length; i++)
                    {
                        var vars = parts[i].split('=');
                        switch (vars[0])
                        {
                            case 'task_filter':
                            {
                                ctrl.currentTaskFilter = vars[1];
                                break;
                            }
                            case 'status_filter':
                            {
                                ctrl.currentStatusFilter = vars[1];
                                break;
                            }
                            case 'page':
                            {
                                ctrl.currentPage = vars[1];
                                break;
                            }
                            case 'user_filter':
                            {
                                ctrl.userFilter = vars[1];
                                break;
                            }
                            case 'search':
                            {
                                ctrl.searchTerms = vars[1];
                                break;
                            }
                        }
                    }
                }

                // Only reload if something has actually changed
                if ((oldTaskFilter != ctrl.currentTaskFilter) ||
                    (oldStatusFilter != ctrl.currentStatusFilter) ||
                    (oldPage != ctrl.currentPage) ||
                    (oldUserFilter != ctrl.userFilter) ||
                    (oldSearchTerms != ctrl.searchTerms))
                {
                    ctrl.getResultsPage(true);
                }
            });

            // If a filter is clicked
            ctrl.setTaskFilter = function($event, type, count) {
                $event.preventDefault();
                if (count === '')
                    return;
                ctrl.currentTaskFilter = type;
                if (ctrl.currentTaskFilter === 'my_tasks')
                    ctrl.listViewName = lmsg('projects.tasks.custom_order');
                else
                    ctrl.listViewName = lmsg('projects.tasks.list_view');
                ctrl.currentPage = 1;
                service.currentTaskFilter = ctrl.currentTaskFilter;
                service.getResultsPage();
            };

            ctrl.setStatusFilter = function($event, type, count) {
                $event.preventDefault();
                if (count === '')
                    return;

                // Make sure completed tasks don't see the 'by due date' view
                if ((ctrl.view_mode === 'due_date') &&
                    (type !== 'open'))
                {
                    ctrl.view_mode = 'list_view';
                }

                ctrl.currentStatusFilter = type;
                ctrl.currentPage = 1;
                service.currentStatusFilter = ctrl.currentStatusFilter;
                service.getResultsPage();
            };
        }
    }
}());


/***/ }),

/***/ "./js/model/projectTaskModel.js":
/***/ (function(module, exports) {

(function () {
    var moduleName = 'claromentis.project.tasks_util';
    var module;

    try {
        module = angular.module(moduleName);
    } catch (err) {
        // named module does not exist, so create one
        module = angular.module(moduleName, []);
    }

    module
        .factory('Task', ['$http', taskModelFactory]);

	function taskModelFactory($http)
	{
		var Task = function()
		{
		};

        Task.prototype =
            {
                // Constant to mean 'unsorted' at the end of the list
                DISPLAY_ORDER_NONE: 1e6,
                STATUS_TODO: -1,
                STATUS_COMPLETED: -2,

                restUrl: '/api/projects/task/',

                id: 0,
                project_id: 0,
                title: '',
                description: '',
                due_date: null,
                due_date_formatted: '',
                section_id: 0,
                is_private: false,
                created_by:
                {
                    id: null,
                    name: '',
                    profile_url: '#'
                },
                assignees: [],
                priority: '0',
                is_complete: false,
                date_completed: null,
                duration: '',
                duration_units: '',
                comments_count: 0,
                has_file_storage: false,
                orders: {
                    task: this.DISPLAY_ORDER_NONE,
                    board: this.DISPLAY_ORDER_NONE,
                    board_no_list: this.DISPLAY_ORDER_NONE,
                    my_tasks: this.DISPLAY_ORDER_NONE
                },
                status_id: 0,
                status_list: [],
                source: null,

			    control: {}, // datepicker

                // Using is_complete directly for list visibility and checkbox model causes issues with click events (the model is updated, then visibility assessed and if not visible, the ng-click callback is never run).
                // So use this second copy for visibility that gets updated when the server responds.
                is_complete_server: true,

                tasks: [],
                new_task: new Task(),

			loadFromArray: function(data)
			{
				this.id = data.id;
				this.project_id = data.project_id;
				this.title = data.title;
                this.description = data.description;
                this.due_date = data.due_date;
				this.due_date_formatted = data.due_date_formatted;
				this.due_date_type = data.due_date_type;
                this.section_id = data.section_id;
                this.section_name = data.section_name;
                this.is_private = data.is_private;
				this.created_by = data.created_by;
				this.priority = parseInt(data.priority);
				this.assignees = data.assignees;
				this.is_complete = data.is_complete;
				this.is_complete_server = data.is_complete;
                this.date_completed = data.date_completed === null ? null : parseInt(data.date_completed);
				this.duration = data.duration == null ? '' : data.duration;
				this.duration_units = data.duration_units;
				this.date_created = data.date_created;
				this.comments_count = data.comments_count;
				this.perms = data.perms;
				if (data.source !== undefined)
                {
					this.source = {
						name: data.source.name,
						link: data.source.link
					};
				}
				this.has_file_storage = data.has_file_storage;

				this.orders = {
					list: data.orders.list,
					board: data.orders.board,
					board_no_list: data.orders.board_no_list,
					my_tasks: data.orders.my_tasks
				};

				this.status_id = data.status_id;
				this.status_list = data.status_list;
			},
			add: function(successCallback, errorCallback)
			{
				var data =
				{
                    project_id: this.project_id,
					title: this.title.length <= 255 ? this.title : this.title.substr(0, 255),
                    description: this.description,
					due_date: this.due_date,
					section_id: this.section_id,
					is_private: this.is_private,
                    assignees: this.assignees,
					priority: this.priority,
					duration: this.duration,
					is_complete: this.is_complete
				};
				$http(
					{
						method:'POST',
						url: this.restUrl + 'add',
						data: data,
						task: this,
						successCallback: successCallback,
						errorCallback: errorCallback
					}).then(function(response)
					{
						var task = response.config.task;
						task.id = response.data.id;
						task.project_id = response.data.project_id;
						task.title = response.data.title;
						task.description = response.data.description;
						task.due_date = response.data.due_date;
						task.due_date_formatted = response.data.due_date_formatted;
						task.due_date_type = response.data.due_date_type;
						task.section_id = response.data.section_id;
						task.is_private = response.data.is_private;
						task.created_by = response.data.created_by;
						task.assignees = response.data.assignees;
						task.perms = response.data.perms;
						task.priority = response.data.priority;
						task.is_complete = response.data.is_complete;
						task.duration = response.data.duration;
						task.duration_units = response.data.duration_units;
						task.is_complete_server = task.is_complete;

                        response.config.successCallback(response.data);
                    }, function (response) {
                        response.config.errorCallback(response.data);
					});
			},
			update: function(successCallback, errorCallback)
			{
				var data =
				{
					project_id: this.project_id,
					title: this.title.length <= 255 ? this.title : this.title.substr(0, 255),
                    description: this.description,
					due_date: this.due_date,
					is_private: this.is_private,
                    assignees: this.assignees,
                    priority: this.priority,
					duration: this.duration,
					is_complete: this.is_complete
				};

                // An array should contains only ids not user's objects
                if (Array.isArray(this.assignees) &&
                    this.assignees.length > 0  &&
                    this.assignees[0].hasOwnProperty('id')
                ) {
                    data.assignees = this.getUsersIds(this.assignees);
                }

				$http(
					{
						method:'PUT',
						url: this.restUrl + this.id,
						data: data,
						task: this,
						successCallback: successCallback,
						errorCallback: errorCallback
					}).then(function(response)
                    {
                        var task                = response.config.task;
                        task.id                 = response.data.id;
                        task.project_id         = response.data.project_id;
                        task.title              = response.data.title;
                        task.description        = response.data.description;
                        task.due_date           = response.data.due_date;
                        task.due_date_formatted = response.data.due_date_formatted;
                        task.due_date_type      = response.data.due_date_type;
                        task.is_private         = response.data.is_private;
                        task.created_by         = response.data.created_by;
                        task.assignees          = response.data.assignees;
                        task.perms              = response.data.perms;
                        task.priority           = response.data.priority;
                        task.is_complete        = response.data.is_complete;
                        task.duration           = response.data.duration;
                        task.duration_units     = response.data.duration_units;
                        task.is_complete_server = task.is_complete;

                        response.config.successCallback(task);
                    }, function (response) {
                        response.config.errorCallback(response.data);
                    });
				},
                delete: function (successCallback, errorCallback) {
                    $http(
                        {
                            method: 'DELETE',
                            url: this.restUrl + this.id,
                            section: this,
                            successCallback: successCallback,
                            errorCallback: errorCallback
                        }).then(function (response) {
                        response.config.successCallback(response.data.id);
                    }, function (response) {
                        response.config.errorCallback(response.data);
                    });
                },
                setComplete: function (successCallback, errorCallback) {
                    $http(
                        {
                            method: 'PUT',
                            url: this.restUrl + this.id + '/complete',
                            task: this,
                            successCallback: successCallback,
                            errorCallback: errorCallback
                        }).then(function (response) {
                        response.config.task.is_complete_server = true;
                        response.config.task.status_id = response.config.task.STATUS_COMPLETED;
                        response.config.successCallback(response.config.task, response.data);
                    }, function (response) {
                        response.config.errorCallback(response.config.task, response.data);
                    });
                },
                setIncomplete: function (successCallback, errorCallback) {
                    $http(
                        {
                            method: 'PUT',
                            url: this.restUrl + this.id + '/incomplete',
                            task: this,
                            successCallback: successCallback,
                            errorCallback: errorCallback
                        }).then(function (response) {
                        response.config.task.is_complete_server = false;
                        response.config.task.status_id = response.config.task.STATUS_TODO;
                        response.config.successCallback(response.config.task, response.data);
                    }, function (response) {
                        response.config.errorCallback(response.config.task, response.data);
                    });
                },
                setStatus: function (successCallback, errorCallback) {
                    if (!successCallback)
                        successCallback = function () {
                        };

                    if (!errorCallback)
                        errorCallback = function () {
                        };

                    var status      = this.status_id;
                    var is_complete = this.status_id === this.STATUS_COMPLETED;

                    $http({
                        method: "PUT",
                        url: '/api/projects/task/' + this.id + '/status',
                        task: this,
                        data: {
                            status: status
                        },
                        successCallback: successCallback,
                        errorCallback: errorCallback
                    }).then(function (response) {
                        response.config.task.is_complete_server = is_complete;
                        response.config.task.is_complete        = is_complete;
                        response.config.successCallback(response.config.task, response.data);
                    }, function (response) {
                        response.config.errorCallback(response.config.task, response.data);
                    });
                },
                moveToSectionId: function (section_id) {
                    this.section_id = section_id;
                },
                setDisplayOrder: function (display_order) {
                    this.display_order = display_order;
                },

                /**
                 * Change an array with objects contains assigned user to array with ids
                 *
                 * @param associative_array Array
                 * @returns [1,2,3,..] Array
                 */
                getUsersIds: function (associative_array) {
                    var assignees = [];

                    associative_array.map(function(assignee) {
                        if (!assignee.hasOwnProperty('id'))
                            return;

                        assignees.push(assignee.id);
                    })

                    return assignees;
                }
            };

        return Task;
    }
}());


/***/ }),

/***/ "./js/ng/modules/tasks/component/task_list_type.component.html":
/***/ (function(module, exports) {

var path = '/js/ng/modules/tasks/component/task_list_type.component.html';
var html = "<div class=\"text-left text-md-right mt-md-0 mt-2\">\n\t<label class=\"mr-2 align-middle mb-0\" name=\"projects:tasks:sort_by\">Sort by</label>\n\t<div class=\"d-md-inline-block d-block\">\n\t\t<a ng-class=\"{active: $ctrl.ngModel === 'list_view'}\" ng-click=\"$ctrl.changeView('list_view',$event);\"\n\t\tclass=\"btn btn-secondary btn-sm\" ng-href=\"#0\">\n\t\t<span>{{$ctrl.listName}}</span>\n\t</a>\n\n\t<a ng-class=\"{active: $ctrl.ngModel === 'date_view'}\" ng-click=\"$ctrl.changeView('date_view',$event)\"\n\tclass=\"btn btn-secondary btn-sm\" ng-href=\"#0\">\n\t<span>{{$ctrl.dateName}}</span>\n</a>\n</div>\n</div>\n";
window.angular.module('ng').run(['$templateCache', function(c) { c.put(path, html) }]);
module.exports = path;

/***/ }),

/***/ "./js/ng/modules/tasks/component/task_list_type.component.js":
/***/ (function(module, exports, __webpack_require__) {

var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__("./js/ng/modules/tasks/component/task_list_type.component.html")], __WEBPACK_AMD_DEFINE_RESULT__ = function (template)
{
    var TaskListType = {
        bindings: {
            ngModel: '=',
            listName: '@',
            dateName: '@'
        },
        templateUrl: template,
        transclude: true,
        controller: [
            function () {
                var ctrl = this;

                ctrl.$onInit = function() {
                    if ((ctrl.ngModel !== 'list_view') &&
                        (ctrl.ngModel !== 'date_view'))
                    {
                        ctrl.ngModel = 'list_view';
                    }
                };

                ctrl.changeView = function(view, $event)
                {
                    $event.preventDefault();

                    ctrl.ngModel = view === 'list_view' ? 'list_view' : 'date_view';
                };
            }
        ]
    };

    return TaskListType;
}.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));


/***/ }),

/***/ "./js/ng/modules/tasks/tasks.module.js":
/***/ (function(module, exports, __webpack_require__) {

var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
    __webpack_require__("./js/ng/modules/tasks/component/task_list_type.component.js")
], __WEBPACK_AMD_DEFINE_RESULT__ = function (
    TaskListType
) {
    return angular
        .module('claromentis.projects.tasks', [])

        .component('clangTaskListType', TaskListType)
}.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));


/***/ }),

/***/ "./js/ng/modules/widgets/component/checkbox.component.html":
/***/ (function(module, exports) {

var path = '/js/ng/modules/widgets/component/checkbox.component.html';
var html = "<span>\n\t<cla-checkbox large=\"{{$ctrl.large}}\" name=\"{{$ctrl.name}}\" ng-attr-checked=\"{{$ctrl.ngModel?true:undefined}}\" ng-attr-disabled=\"{{$ctrl.disabled?true:undefined}}\" ng-on-selected=\"$ctrl.onChecked($event)\" ng-on-unselected=\"$ctrl.onUnchecked($event)\" ng-transclude></cla-checkbox>\n</span>\n";
window.angular.module('ng').run(['$templateCache', function(c) { c.put(path, html) }]);
module.exports = path;

/***/ }),

/***/ "./js/ng/modules/widgets/component/checkbox.component.js":
/***/ (function(module, exports, __webpack_require__) {

var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__("./js/ng/modules/widgets/component/checkbox.component.html")], __WEBPACK_AMD_DEFINE_RESULT__ = function (template)
{
    var Checkbox = {
        bindings: {
            ngModel: '=',
            large: '@',
            name: '@',
            disabled: '@',
        },
        require: { ngModelCtrl: 'ngModel' },
        templateUrl: template,
        transclude: true,
        controller: function () {
            var ctrl = this;

            ctrl.$onInit = function() {
                if (ctrl.disabled === undefined)
                    ctrl.disabled = false;
            };

            ctrl.onChecked = function($event) {
                $event.preventDefault();

                ctrl.ngModel = true;
                ctrl.ngModelCtrl.$setViewValue(ctrl.ngModel);
            }

            ctrl.onUnchecked = function($event) {
                $event.preventDefault();

                ctrl.ngModel = false;
                ctrl.ngModelCtrl.$setViewValue(ctrl.ngModel);
            }
        }
    };

    return Checkbox;
}.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));


/***/ }),

/***/ "./js/ng/modules/widgets/component/confirm.component.html":
/***/ (function(module, exports) {

var path = '/js/ng/modules/widgets/component/confirm.component.html';
var html = "<div class=\"modal fade\" id=\"projects-confirm\" tabindex=\"-1\" role=\"dialog\" aria-labelledby=\"more-info\">\n\t<div class=\"modal-dialog\" role=\"document\">\n\t\t<div class=\"modal-content\">\n\t\t\t<div class=\"modal-header\">\n\t\t\t\t<h5 class=\"modal-title\" id=\"more-info--label\">{{$ctrl.options.title}}</h5>\n\t\t\t\t<button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Cancel\">\n\t\t\t\t\t<span aria-hidden=\"true\">\n\t\t\t\t\t\t<ion-icon name=\"close-outline\"></ion-icon>\n\t\t\t\t\t</span>\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t\t<div class=\"modal-body\">\n\n\t\t\t\t<div class=\"media\">\n\t\t\t\t\t<div class=\"mr-3 align-self-center\">\n\t\t\t\t\t\t<span class=\"text-muted\">\n\t\t\t\t\t\t\t<ion-icon class=\"icon-xxl align-middle\" name=\"{{$ctrl.options.icon}}\"></ion-icon>\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"media-body align-self-center\">\n\t\t\t\t\t\t<p class=\"mb-0\">{{$ctrl.options.message}}</p>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\n\t\t\t</div>\n\t\t\t<div class=\"modal-footer\">\n\t\t\t\t<form id=\"task-edit-form\" class=\"form-horizontal\" name=\"taskForm\">\n\t\t\t\t\t<div ng-if=\"$ctrl.options.mode === 'cancel_delete'\">\n\t\t\t\t\t\t<button class=\"btn btn-link\" ng-click=\"$ctrl.cancel($event)\" lmsg=\"projects.task.cancel\">[Cancel]</button>\n\t\t\t\t\t\t<button class=\"btn btn-danger\" rel=\"tooltip\" ng-click=\"$ctrl.confirm($event)\"><lmsg src=\"projects.task.delete\">[Delete]</lmsg></button>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div ng-if=\"$ctrl.options.mode === 'ok'\">\n\t\t\t\t\t\t<button class=\"btn btn-primary\" ng-click=\"$ctrl.confirm($event)\" lmsg=\"common.ok\">[Ok]</button>\n\t\t\t\t\t</div>\n\t\t\t\t</form>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n";
window.angular.module('ng').run(['$templateCache', function(c) { c.put(path, html) }]);
module.exports = path;

/***/ }),

/***/ "./js/ng/modules/widgets/component/confirm.component.js":
/***/ (function(module, exports, __webpack_require__) {

var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__("./js/ng/modules/widgets/component/confirm.component.html")], __WEBPACK_AMD_DEFINE_RESULT__ = function (template)
{
    var Confirm = {
        bindings: {},
        templateUrl: template,
        transclude: true,
        controller: [
            'confirmService',
            function (confirmService) {
                var ctrl = this;

                ctrl.options = {
                    title: '',
                    message: '',
                    icon: '',
                    mode: ''
                };

                ctrl.settings = function(settings) {
                    var values = {
                        title: '',
                        message: '',
                        icon: 'alert-circle-outline',
                        mode: 'cancel_delete'
                    };
                    ctrl.options = angular.extend(values, settings);
                };
                confirmService.registerConfirmDialog(ctrl.settings);

                ctrl.confirm = function() {
                    confirmService.resolve();
                };

                ctrl.cancel = function() {
                    confirmService.reject();
                };
            }
        ]
    };

    return Confirm;
}.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));


/***/ }),

/***/ "./js/ng/modules/widgets/component/toggle_switch.component.html":
/***/ (function(module, exports) {

var path = '/js/ng/modules/widgets/component/toggle_switch.component.html';
var html = "<!-- Hack to assign different values to the \"ontext\" property which is interpreted as an event handler due to the name -->\n<span>\n\t<cla-toggle-switch ng-if=\"$ctrl.labels !== 'showhide'\" lmsg=\"ontext:projects.details.grouped\" offtext=\"{{$ctrl.offLabel()}}\" large=\"{{$ctrl.large}}\" ng-attr-checked=\"{{$ctrl.ngModel?true:undefined}}\" name=\"{{$ctrl.name}}\" ng-attr-disabled=\"{{$ctrl.disabled?true:undefined}}\" ng-on-selected=\"$ctrl.onToggledOn($event)\" ng-on-unselected=\"$ctrl.onToggledOff($event)\" ng-transclude></cla-toggle-switch>\n\t<cla-toggle-switch ng-if=\"$ctrl.labels === 'showhide'\" lmsg=\"ontext:projects.details.show\" offtext=\"{{$ctrl.offLabel()}}\" large=\"{{$ctrl.large}}\" ng-attr-checked=\"{{$ctrl.ngModel?true:undefined}}\" name=\"{{$ctrl.name}}\" ng-attr-disabled=\"{{$ctrl.disabled?true:undefined}}\" ng-on-selected=\"$ctrl.onToggledOn($event)\" ng-on-unselected=\"$ctrl.onToggledOff($event)\" ng-transclude></cla-toggle-switch>\n</span>\n";
window.angular.module('ng').run(['$templateCache', function(c) { c.put(path, html) }]);
module.exports = path;

/***/ }),

/***/ "./js/ng/modules/widgets/component/toggle_switch.component.js":
/***/ (function(module, exports, __webpack_require__) {

var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__("./js/ng/modules/widgets/component/toggle_switch.component.html")], __WEBPACK_AMD_DEFINE_RESULT__ = function (template)
{
    var ToggleSwitch = {
        bindings: {
            ngModel: '=',
            labels: '@',
            labelOn: '@',   // Can't be used until the web component property can be renamed away from 'ontext'
            labelOff: '@',  // Also not used due to above limitation
            large: '@',
            name: '@',
            disabled: '@'
        },
        require: { ngModelCtrl: 'ngModel' },
        templateUrl: template,
        transclude: true,
        controller: function () {
            var ctrl = this;

            ctrl.$onInit = function() {
                if (ctrl.disabled === undefined)
                    ctrl.disabled = false;
            };

            ctrl.offLabel = function() {
                if (ctrl.labels !== 'showhide')
                    return lmsg('projects.details.not_grouped');
                else
                    return lmsg('projects.details.hide');
            };

            ctrl.onToggledOn = function($event) {
                $event.preventDefault();

                ctrl.ngModel = true;
                ctrl.ngModelCtrl.$setViewValue(ctrl.ngModel);
            }

            ctrl.onToggledOff = function($event) {
                $event.preventDefault();

                ctrl.ngModel = false;
                ctrl.ngModelCtrl.$setViewValue(ctrl.ngModel);
            }
        }
    };

    return ToggleSwitch;
}.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));


/***/ }),

/***/ "./js/ng/modules/widgets/component/user_list.component.html":
/***/ (function(module, exports) {

var path = '/js/ng/modules/widgets/component/user_list.component.html';
var html = "<div class=\"user-list-wrapper user-list-component\">\n\t<div class=\"user-list\">\n\t\t<ng-transclude></ng-transclude>\n\t\t<div class=\"plus-number-wrapper\" ng-if=\"$ctrl.plusnumber > 0\" ng-click=\"$ctrl.plusClicked($event)\">\n\t\t\t<a ng-href=\"javascript:void(0)\" class=\"plus-number\">+{{$ctrl.plusnumber}}</a>\n\t\t</div>\n\t</div>\n</div>\n";
window.angular.module('ng').run(['$templateCache', function(c) { c.put(path, html) }]);
module.exports = path;

/***/ }),

/***/ "./js/ng/modules/widgets/component/user_list.component.js":
/***/ (function(module, exports, __webpack_require__) {

var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__("./js/ng/modules/widgets/component/user_list.component.html")], __WEBPACK_AMD_DEFINE_RESULT__ = function (template)
{
    var UserList = {
        bindings: {
            plusnumber: '@',
            onPlusClicked: '&'
        },
        transclude: true,
        templateUrl: template,
        controller: [
            function () {
                var ctrl = this;

                ctrl.plusClicked = function($event) {
                    $event.preventDefault();

                    ctrl.onPlusClicked();
                }
            }
        ]
    };

    return UserList;
}.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));


/***/ }),

/***/ "./js/ng/modules/widgets/component/user_list_item.component.html":
/***/ (function(module, exports) {

var path = '/js/ng/modules/widgets/component/user_list_item.component.html';
var html = "<div class=\"user-list-item square\" data-original-title=\"{{$ctrl.name}}\" rel=\"tooltip\"><a ng-href=\"{{$ctrl.profile}}\" target=\"_parent\"><img ng-src=\"{{$ctrl.img}}\"/></a></div>\n";
window.angular.module('ng').run(['$templateCache', function(c) { c.put(path, html) }]);
module.exports = path;

/***/ }),

/***/ "./js/ng/modules/widgets/component/user_list_item.component.js":
/***/ (function(module, exports, __webpack_require__) {

var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__("./js/ng/modules/widgets/component/user_list_item.component.html")], __WEBPACK_AMD_DEFINE_RESULT__ = function (template)
{
    var UserListItem = {
        bindings: {
            img: '@',
            name: '@',
            profile: '@'
        },
        templateUrl: template,
        controller: [
            function () {
                var ctrl = this;
            }
        ]
    };

    return UserListItem;
}.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));


/***/ }),

/***/ "./js/ng/modules/widgets/component/users_list_popup.component.html":
/***/ (function(module, exports) {

var path = '/js/ng/modules/widgets/component/users_list_popup.component.html';
var html = "<div class=\"modal fade js-users_list_modal\" role=\"dialog\">\n\t<div class=\"modal-dialog\" role=\"document\">\n\t\t<div class=\"modal-content\">\n\t\t\t<div class=\"modal-header\">\n\t\t\t\t<h5 class=\"modal-title\" lmsg=\"projects.task.user_list\">[User list]</h5>\n\t\t\t\t<button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Cancel\">\n\t\t\t\t\t<span aria-hidden=\"true\">\n\t\t\t\t\t\t<ion-icon name=\"close-outline\"></ion-icon>\n\t\t\t\t\t</span>\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t\t<div class=\"modal-body\">\n\t\t\t\t<div class=\"d-inline-flex\"\n\t\t\t\t\t dir-paginate=\"user in $ctrl.paginatedUsers | itemsPerPage: $ctrl.usersPerPage\"\n\t\t\t\t\t pagination-id=\"user_list_popup\"\n\t\t\t\t\t total-items=\"$ctrl.totalItems\"\n\t\t\t\t\t current-page=\"$ctrl.currentPage\">\n\t\t\t\t\t<span ng-if=\"user.profile_url === null\" class=\"btn btn-link disabled\">\n\t\t\t\t\t\t<img class=\"tasks-profile-img profile-img mr-2\" ng-src=\"{{user.profile_img}}\">{{user.name}}\n\t\t\t\t\t</span>\n\n\t\t\t\t\t<a ng-if=\"user.profile_url !== null && user.name != ''\" href=\"{{user.profile_url}}\" class=\"btn btn-link\" rel=\"tooltip\" title=\"{{user.name}}\">\n\t\t\t\t\t\t<img class=\"tasks-profile-img profile-img mr-2\" ng-src=\"{{user.profile_img}}\">{{user.name}}\n\t\t\t\t\t</a>\n\t\t\t\t</div>\n\n\t\t\t\t<div class=\"text-center clearfix\">\n\t\t\t\t\t<dir-pagination-controls\n\t\t\t\t\t\t\tpagination-id=\"user_list_popup\"\n\t\t\t\t\t\t\ton-page-change=\"$ctrl.pageChanged(newPageNumber)\"\n\t\t\t\t\t\t\ttemplate-url=\"/intranet/projects/html/components/project_list/pagination.html\"\n\t\t\t\t\t></dir-pagination-controls>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n";
window.angular.module('ng').run(['$templateCache', function(c) { c.put(path, html) }]);
module.exports = path;

/***/ }),

/***/ "./js/ng/modules/widgets/component/users_list_popup.component.js":
/***/ (function(module, exports, __webpack_require__) {

var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__("./js/ng/modules/widgets/component/users_list_popup.component.html")], __WEBPACK_AMD_DEFINE_RESULT__ = function (template)
{
    var UsersListPopup = {
        bindings: {},
        templateUrl: template,
        controller: [
            '$element',
            'userListService',
            function ($element, userListService) {
                var ctrl = this;

                ctrl.users = [];
                ctrl.currentPage = 1;
                ctrl.usersPerPage = 10;
                ctrl.totalItems = 0;
                ctrl.paginatedUsers = []

                ctrl.$onInit = function() {
                    $element.find('.js-users_list_modal').on('update', function(event, users) {
                        ctrl.users = users;

                        ctrl.currentPage = 1;
                        ctrl.totalItems = ctrl.users.length;
                        ctrl.pageChanged(ctrl.currentPage);
                    });
                };

                // If pagination is clicked
                ctrl.pageChanged = function(newPage)
                {
                    ctrl.paginatedUsers = paginate(ctrl.users, ctrl.usersPerPage, newPage);
                };

                function paginate(users, usersPerPage, currentPage) {
                    return users.slice((currentPage - 1) * usersPerPage, currentPage * usersPerPage);
                }
            }
        ]
    };

    return UsersListPopup;
}.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));


/***/ }),

/***/ "./js/ng/modules/widgets/css/user_list.component.scss":
/***/ (function(module, exports, __webpack_require__) {

// style-loader: Adds some css to the DOM by adding a <style> tag

// load the styles
var content = __webpack_require__("../../../node_modules/css-loader/index.js!../../../node_modules/sass-loader/lib/loader.js!./js/ng/modules/widgets/css/user_list.component.scss");
if(typeof content === 'string') content = [[module.i, content, '']];
// add the styles to the DOM
var update = __webpack_require__("../../../node_modules/style-loader/addStyles.js")(content, {});
if(content.locals) module.exports = content.locals;
// Hot Module Replacement
if(false) {
	// When the styles change, update the <style> tags
	if(!content.locals) {
		module.hot.accept("!!../../../../../../../../node_modules/css-loader/index.js!../../../../../../../../node_modules/sass-loader/lib/loader.js!./user_list.component.scss", function() {
			var newContent = require("!!../../../../../../../../node_modules/css-loader/index.js!../../../../../../../../node_modules/sass-loader/lib/loader.js!./user_list.component.scss");
			if(typeof newContent === 'string') newContent = [[module.id, newContent, '']];
			update(newContent);
		});
	}
	// When the module is disposed, remove the <style> tags
	module.hot.dispose(function() { update(); });
}

/***/ }),

/***/ "./js/ng/modules/widgets/directive/user_picker.directive.html":
/***/ (function(module, exports) {

var path = '/js/ng/modules/widgets/directive/user_picker.directive.html';
var html = "<div class=\"row\">\n\t<div class=\"col-md-8 mb-2 mb-sm-0\">\n\t\t<select name=\"user_picker_select\" id=\"{{id}}\" class=\"form-control\" size=\"30\" multiple=\"multiple\"></select>\n\t</div>\n\t<div class=\"col-md-4\">\n\t\t<a href=\"#\" id=\"browse_{{id}}\" class=\"btn btn-secondary\" name=\"select_link\" ng-click=\"browse($event)\"><txt name=\"common:user_picker:browse\">Browse</txt></a>\n\t</div>\n</div>\n";
window.angular.module('ng').run(['$templateCache', function(c) { c.put(path, html) }]);
module.exports = path;

/***/ }),

/***/ "./js/ng/modules/widgets/directive/user_picker.directive.js":
/***/ (function(module, exports, __webpack_require__) {

var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__("./js/ng/modules/widgets/directive/user_picker.directive.html"), __webpack_require__(3)], __WEBPACK_AMD_DEFINE_RESULT__ = function (template, $)
{
    UserPicker.$inject = ['$timeout'];
    function UserPicker($timeout)
    {
        return {
            restrict: 'E',
            require: '^ngModel',
            templateUrl: template,
            scope: {
                ngModel: '=',
                control: '=',
                allowBlocked: '@'
            },
            link: link
        };

        function link(scope, iElement, iAttrs, ctrl)
        {
            scope.id = iAttrs.selectId + '-inner';
            ctrl.user_name = iAttrs.userName;

            var allow_unset = iAttrs.allowUnset == 1;

            // Get project ID if there is one to limit search results
            scope.project_id = iAttrs.projectId || 0;
            scope.project_rights = iAttrs.projectRights || 0;
            scope.project_param = '';

            if ((typeof(scope.project_id) !== 'undefined') &&
                (scope.project_id > 0))
            {
                scope.project_param = '?project_id=' + scope.project_id;
            }

            // Don't use the system user_picker_popup.php because we need to filter results to a projects team members if needed
            ctrl.UserPicker_InitSelect2 = function (element_id, project_id, project_rights, placeholder, allow_unset) {
                var el = jq_$(element_id);
                var page_size = 50;

                var e = el.select2({
                    placeholder: placeholder,
                    minimumInputLength: 3,
                    width: '100%',
                    allowClear: allow_unset,
                    ajax: {
                        url: "/api/projects/v2/projects/" + project_id + "/users",
                        dataType: 'json',
                        delay: 250,
                        data: function (params) {
                            var page = params.page || 1;
                            return {
                                name: params.term, // search term
                                limit: page_size,
                                offset: (page-1) * page_size,
                                fields: "fullname"
                            };
                        },
                        processResults: function (data, params) {
                            params.page = params.page || 1;
                            var list = data.data.map(function(elem){
                                return {
                                    id: elem.id,
                                    text: elem.fullname
                                }
                            });

                            if (!!scope.allowBlocked) {
                                list.push({id: 0, text: lmsg('projects.task.user_blocked')});
                            }

                            return {
                                results: list,
                                pagination: {
                                    more: data.pagination.next != null
                                }
                            };
                        }
                    }
                });
            };

            // Angular won't have populated the control/browse ids yet so wait until the current event is finished
            $timeout(function(id, text, allow_unset, scope){
                scope.initSelect2(id, text, allow_unset)
            }, 0, true, scope.id, lmsg('projects.picker.select_user'), allow_unset, scope);

            if (scope.ngModel !== undefined && scope.ngModel !== null && Array.isArray(scope.ngModel)) {
                scope.ngModel.map(function (user) {
                    $('#' + scope.id).append($('<option>').attr('value', user.id).attr('selected', 'selected').text(user.name));
                });
            }

            ctrl.UserPicker_InitSelect2(scope.id, scope.project_id, scope.project_rights, lmsg('projects.picker.select_user'), allow_unset);

            ctrl.$viewChangeListeners.push(function() {
                scope.$eval(iAttrs.ngChange);
            });

            scope.initSelect2 = function(id, text, allow_unset)
            {
                var select = $('#' + id);
                select.find('option').remove();

                // Add an entry for the current user if needed
                if (scope.ngModel !== undefined && scope.ngModel !== null && Array.isArray(scope.ngModel)) {
                    scope.ngModel.map(function (user) {
                        select.append($('<option>').attr('value', user.id).text(user.name).attr('selected', 'selected'));
                    });
                }

                select.on('change', function() {
                    var $el = angular.element(this);
                    var user_ids = $el.val();

                    // cast variables to int
                    user_ids = user_ids.map(function (user_id) {
                        return parseInt(user_id);
                    });

                    var user_id = user_ids.slice(-1)[0];
                    var name = user_id === '' ? '' : $el.find('option[value=' + user_id + ']').text();

                    scope.change(user_ids, name);
                });

                ctrl.UserPicker_InitSelect2(scope.id, scope.project_id, scope.project_rights, text, allow_unset);
            };

            /**
             * @param user_ids Array
             * @param name string
             */
            scope.change = function(user_ids, name)
            {
                if (!Array.isArray(user_ids))
                    user_ids = [];

                scope.user_name = name;
                ctrl.$setViewValue(user_ids);
                ctrl.$render();

                $timeout(function(user_ids) {
                    ctrl.$setViewValue(user_ids);
                    ctrl.$render();
                }, 0, true, user_ids);
            };

            scope.browse = function(event)
            {
                event.preventDefault();
                var project_params = '';
                if (scope.project_id > 0)
                    project_params = '&project_id=' + scope.project_id;
                var recwnd = window.open('/projects/user_picker_popup?input_dom_id=' + scope.id + project_params + '&multi=1','user_picker_wnd','width=800,height=450,scrollbars=yes,resizable=yes,hotkeys=no,maximize=no');
                recwnd.focus();
            };

            scope.internalControl = scope.control || {};
            scope.internalControl.reset = function(user_name)
            {
                // Rebind the model. This shouldn't be needed but it never gets updated once reset otherwise
                ctrl.$setViewValue(scope.ngModel);

                scope.initSelect2(scope.id, lmsg('projects.picker.select_user'), true);

                var select = $('#' + scope.id);
                select.find('option').remove();
            };
        }
    }

    return UserPicker;
}.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));


/***/ }),

/***/ "./js/ng/modules/widgets/projects_widgets.module.js":
/***/ (function(module, exports, __webpack_require__) {

var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
    __webpack_require__("./js/ng/modules/widgets/directive/user_picker.directive.js"),
    __webpack_require__("./js/ng/modules/widgets/component/toggle_switch.component.js"),
    __webpack_require__("./js/ng/modules/widgets/component/confirm.component.js"),
    __webpack_require__("./js/ng/modules/widgets/component/user_list.component.js"),
    __webpack_require__("./js/ng/modules/widgets/component/user_list_item.component.js"),
    __webpack_require__("./js/ng/modules/widgets/component/users_list_popup.component.js"),
    __webpack_require__("./js/ng/modules/widgets/component/checkbox.component.js"),
    __webpack_require__("./js/ng/modules/widgets/service/confirm.service.js"),
    __webpack_require__("./js/ng/modules/widgets/service/user_list.service.js"),
    __webpack_require__("./node_modules/angular-utils-pagination/dirPagination.js"),
    __webpack_require__("./js/ng/modules/widgets/css/user_list.component.scss")

], __WEBPACK_AMD_DEFINE_RESULT__ = function (
    UserPicker,
    ToggleSwitch,
    Confirm,
    UserList,
    UserListItem,
    UsersListPopup,
    Checkbox,
    ConfirmService,
    UserListService
) {
    return angular
        .module('claromentis.projects.widgets', ['angularUtils.directives.dirPagination'])
        .directive('clangProjectsUserPicker', UserPicker)
        .component('clangToggleSwitch', ToggleSwitch)
        .component('clangConfirm', Confirm)
        .component('clangUserList', UserList)
        .component('clangUserListItem', UserListItem)
        .component('clangUsersListPopup', UsersListPopup)
        .component('clangCheckbox', Checkbox)
        .service('confirmService', ConfirmService)
        .service('userListService', UserListService);
}.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));


/***/ }),

/***/ "./js/ng/modules/widgets/service/confirm.service.js":
/***/ (function(module, exports, __webpack_require__) {

var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = function ()
{
    var ConfirmService = function($q) {
        var service = this;

        service.promise = null;
        service.confirmDialog = null;

        service.registerConfirmDialog = function(dialog) {
            if (service.confirmDialog !== null)
                console.error('ConfirmService error: Multiple <clang-confirm> instances exist, only one should be defined per page');

            service.confirmDialog = dialog;
        };

        service.show = function(settings) {
            if (service.confirmDialog === null)
            {
                console.error('Confirmation dialog not found');
                return;
            }
            service.confirmDialog(settings);

            angular.element('#projects-confirm').modal('show');
            service.promise = $q.defer();

            return service.promise.promise;
        };

        service.resolve = function() {
            angular.element('#projects-confirm').modal('hide');
            service.promise.resolve();
        };

        service.reject = function() {
            angular.element('#projects-confirm').modal('hide');
            service.promise.reject();
        };
    };
    ConfirmService.$inject = ['$q'];

    return ConfirmService;
}.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));


/***/ }),

/***/ "./js/ng/modules/widgets/service/user_list.service.js":
/***/ (function(module, exports, __webpack_require__) {

var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = function ()
{
    var template = '<clang-users-list-popup></clang-users-list-popup>';

    var UserListService = function($rootScope, $rootElement, $compile, $timeout) {
        var service = this;

        service.users = [];

        service.showUsersList = function(users) {
            service.users = users;

            var modal = $rootElement.find('.js-users_list_modal');
            if (modal.length === 0)
            {
                // Add the template to the end of this applications root element
                var newScope = $rootScope.$new(true);
                $rootElement.append($compile(template)(newScope));
            }

            $timeout(function() {
                $rootScope.$digest();

                modal = $rootElement.find('.js-users_list_modal');
                modal.trigger('update', [service.users]);
                modal.modal('show');
            }, 0);
        };
    };
    UserListService.$inject = ['$rootScope', '$rootElement', '$compile', '$timeout'];

    return UserListService;
}.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));


/***/ }),

/***/ "./js/projects.tasks.js":
/***/ (function(module, exports, __webpack_require__) {

var angular = __webpack_require__(1);
window.angular = angular;

__webpack_require__(2);
__webpack_require__(5);
__webpack_require__(4);
__webpack_require__(0);
__webpack_require__(7);
__webpack_require__("../../../node_modules/imports-loader/index.js?angular=cla_angular!./js/lib/ng-sortable.js");
__webpack_require__(13);
__webpack_require__("./js/directive/datePicker.js");

__webpack_require__("./js/projects.tasks_util.js");

// Other modules
__webpack_require__("./js/ng/modules/widgets/projects_widgets.module.js");
__webpack_require__("./js/ng/modules/tasks/tasks.module.js");

angular.module('taskListApp', ['ui.bootstrap', 'ui.sortable', 'claromentis.project', 'angularUtils.directives.dirPagination', 'cla.core.html_editor', 'cla.core.lmsg', 'cla.core.breadcrumb', 'claromentis.projects.widgets', 'claromentis.project.tasks_util']);

__webpack_require__("./js/controller/taskListCtrl.js");

__webpack_require__("./js/task/taskEdit.directive.js");
__webpack_require__("./js/task/taskAddButton.directive.js");
__webpack_require__("./js/task/taskEdit.service.js");
__webpack_require__("./js/directive/tasklist/tasklist.service.js");
__webpack_require__("./js/directive/tasklist/tasklist.directive.js");
__webpack_require__("./js/directive/tasklist/tasklist_filters.directive.js");


/***/ }),

/***/ "./js/projects.tasks_util.js":
/***/ (function(module, exports, __webpack_require__) {

angular.module('claromentis.project.tasks_util', ['claromentis.projects.widgets']);
__webpack_require__("./js/model/projectTaskModel.js");
__webpack_require__("./js/task/task.directive.js");


/***/ }),

/***/ "./js/task/task.directive.js":
/***/ (function(module, exports, __webpack_require__) {

var task_template = __webpack_require__("./html/directives/task.directive.html");
var taskItemLoaded = taskItemLoaded || false;

(function()
{
	var moduleName = 'claromentis.project.tasks_util';
	var module = angular.module(moduleName);

	if (!taskItemLoaded)
	{
		module
			.directive('projectTaskItem', projectTaskItem);

        projectTaskItem.$inject = ['task_edit_service', 'userListService'];
		function projectTaskItem(taskEditService, userListService) {
			return {
				restrict: 'E',
				templateUrl: function(elem,attrs) {
					return attrs.templateUrl || task_template
				},
				scope: {
					task: '=',
                    showProjectName: '=',
                    showSectionName: '=',
                    currentUserId: '@',
					useDragAndDrop: '@',
                    display: '@',
					listPrefix: '@',
					taskUpdate: '&',
					taskDelete: '&',
					taskCompleteToggled: '&',
					titleLength: '@',
                    showAssignees: '<',
                    list: '<',
                    showSource: '@',
                    allowDrag: '<'
				},
				controllerAs: 'item',
				bindToController: true,
				controller: controller,
				link: link
			};

			function controller()
			{
				var ctrl = this;
                ctrl.showSource = !!ctrl.showSource;
				ctrl.$element = null;

                this.$onInit = function() {
                    ctrl.updateTitle();

                    // Set default if needed
                    if ((ctrl.showAssignees !== 'others') &&
                        (ctrl.showAssignees !== 'none'))
                    {
                        ctrl.showAssignees = 'all';
                    }

                    if (ctrl.currentUserId === undefined)
                        ctrl.currentUserId = 0;
                    else
                        ctrl.currentUserId = parseInt(ctrl.currentUserId);

                    // Default to allowing dragging if unspecified
                    if (ctrl.allowDrag === undefined)
                        ctrl.allowDrag = true;
                };

				ctrl.startTaskEdit = function(event, id)
				{
					event.preventDefault();
					angular.element('.js-task_edit_button_' + id).tooltip('hide');
					taskEditService.startEdit(ctrl.task, ctrl.$element);
				};

				ctrl.completeToggled = function()
				{
					ctrl.taskCompleteToggled({task: ctrl.task});
				};

				ctrl.taskUpdated = function(task)
				{
                    ctrl.taskUpdate({task: ctrl.task});

                    ctrl.task.id = task.id;
                    ctrl.task.title = task.title;
                    ctrl.task.description = task.description;
                    ctrl.task.project_id = task.project_id;
                    ctrl.task.assignees = task.assignees;
                    ctrl.task.due_date = task.due_date;
                    ctrl.task.priority = parseInt(task.priority);
                    ctrl.task.is_private = task.is_private;
                    ctrl.task.duration = task.duration;
                    ctrl.task.duration_units = task.duration_units;
                    ctrl.task.due_date_type = task.due_date_type;
                    ctrl.task.due_date_formatted = task.due_date_formatted;
                    ctrl.task.perms = task.perms;

					ctrl.updateTitle();
				};

				ctrl.updateTitle = function()
				{
					// Truncate the title if needed and requested
					var max_length = parseInt(ctrl.titleLength);
					if (typeof ctrl.titleLength === 'undefined')
						max_length = 0;
					ctrl.task.title_truncated = ctrl.task.title;
					if ((max_length !== 0) &&
						(ctrl.task.title.length > max_length))
					{
						ctrl.task.title_truncated = ctrl.task.title_truncated.substring(max_length, 0) + '…';
					}
				};

				ctrl.taskDeleted = function(task)
                {
                    if (ctrl.taskDelete !== undefined)
                        ctrl.taskDelete(task);
                };

                ctrl.getAssignees = function()
                {
                    if (ctrl.showAssignees === 'none')
                        return [];
                    if (ctrl.showAssignees === 'all')
                        return ctrl.task.assignees;

                    // Must be 'others' so strip out current user
                    var userId = parseInt(ctrl.currentUserId);
                    var assignees = [];
                    for (var assigneeIndex = 0; assigneeIndex < ctrl.task.assignees.length; assigneeIndex++)
                    {
                        if(ctrl.task.assignees[assigneeIndex].id !== userId)
                            assignees.push(ctrl.task.assignees[assigneeIndex]);
                    }

                    return assignees;
                };

				ctrl.noDrag = function()
                {
                    return ctrl.allowDrag === false ? true : undefined;
                };

                ctrl.additionalAssigneesClick = function() {
                    userListService.showUsersList(ctrl.task.assignees);
                };
			}

			function link(scope, element, attrs, controller)
			{
			    controller.$element = element;
			    controller.$element.on('cancelEdit', function(event){
                });
                controller.$element.on('editComplete', function(event, task){
                    controller.taskUpdated(task);
                });
                controller.$element.on('taskDeleted', function(event, task){
                    controller.taskDeleted(task);
                });

				// Default to showing all parts unless told otherwise
				controller.showEdit = (attrs.showEdit !== 'false');
				controller.showPrivate = (attrs.showPrivate !== 'false');
				controller.showDate = (attrs.showDate !== 'false');
				controller.showFiles = (attrs.showFiles !== 'false');
				controller.showComments = (attrs.showComments !== 'false');
			}
		}
	}

	taskItemLoaded = true;
}());


/***/ }),

/***/ "./js/task/taskAddButton.directive.js":
/***/ (function(module, exports, __webpack_require__) {

(function()
{
    var template = __webpack_require__("./html/directives/taskAddButton.directive.html");

	var moduleName = 'claromentis.project';
	var module;

	try {
		module = angular.module(moduleName);
	} catch(err) {
		// named module does not exist, so create one
		module = angular.module(moduleName, []);
	}

	module
		.directive('projectTaskAdd', projectTaskAdd);

	projectTaskAdd.$inject = ['$timeout', 'task_edit_service', 'Task'];
	function projectTaskAdd($timeout, service, Task)
	{
		return {
			restrict: 'E',
			templateUrl: template,
			scope: {
                sectionId: '=',
                projectId: '=',
                onTaskAdded: '&'
			},
			controllerAs: 'add',
			bindToController: true,
			controller: controller,
            link: link
		};

		function controller()
		{
			var ctrl = this;
			ctrl.$element = null;
            ctrl.task = null;

            ctrl.$onInit = function()
            {
                ctrl.id = 'js-task_add_button_' + ctrl.sectionId;
                ctrl.blankTask = new Task();
                ctrl.blankTask.project_id = parseInt(ctrl.projectId);
                ctrl.blankTask.section_id = parseInt(ctrl.sectionId);
            }

            ctrl.startTaskEdit = function(event, section_id)
            {
                ctrl.task = angular.copy(ctrl.blankTask);

                event.preventDefault();
                angular.element('.js-task_add_button_' + section_id).tooltip('hide');
                service.startEdit(ctrl.task, ctrl.$element);
            };

			ctrl.taskAdded = function(task)
            {
                ctrl.onTaskAdded({task: task});
            }
		}

        function link(scope, element, attrs, controller)
        {
            controller.$element = element;
            controller.$element.on('editComplete', function(event, task){
                controller.taskAdded(task);
            });
        }
	}
}());


/***/ }),

/***/ "./js/task/taskEdit.directive.js":
/***/ (function(module, exports, __webpack_require__) {

(function()
{
    var template = __webpack_require__("./html/directives/taskEdit.directive.html");

	var moduleName = 'claromentis.project';
	var module;

	try {
		module = angular.module(moduleName);
	} catch(err) {
		// named module does not exist, so create one
		module = angular.module(moduleName, []);
	}

	module
		.directive('projectTaskEdit', projectTaskEdit);

	projectTaskEdit.$inject = ['$timeout', 'task_edit_service', 'Task', 'confirmService'];
	function projectTaskEdit($timeout, service, Task, confirmService)
	{
		return {
			restrict: 'E',
			templateUrl: template,
			scope: {
    			taskDelete: '&',
				taskUpdate: '&'
			},
			controllerAs: 'edit',
			bindToController: true,
			controller: controller,
			link: link
		};

		function controller()
		{
			var ctrl = this;

			ctrl.task = new Task();
			ctrl.visible = false;

            this.$onInit = function() {
                ctrl.unique_id = ctrl.task.id;
            };

			// ctrl.userControl gives us an object shared with the user picker to allow us to run methods inside its scope (needed to reset Select2)
			ctrl.userControl = {};
			ctrl.htmlControl = {};

			ctrl.startTaskEdit = function()
			{
			    ctrl.visible = true;

			    // Need to let the modal content become visible in DOM before resetting it
			    $timeout(function() {
			        // Reset priority picker
				    ctrl.enableEditTaskPriority(ctrl.task);

                    // Reset the user picker if this is a new task.
                    if (ctrl.task.assignees === undefined)
                        ctrl.userControl.reset();

                    ctrl.htmlControl.onOpen();

                    ctrl.$modal.modal('show');
                }, 0);
			};

			ctrl.cancelTaskEdit = function(event)
			{
				ctrl.endTaskEdit(event);
			};

            ctrl.endTaskEdit = function(event)
            {
                event.preventDefault();

                ctrl.$modal.modal('hide');
                ctrl.visible = false;
            }

			ctrl.saveTaskEdit = function(event)
			{
				event.preventDefault();

				var task = ctrl.task;

				task = service.taskUpdated(task, function(){
				    if (ctrl.taskUpdate !== undefined)
                        ctrl.taskUpdate({task: task})

                    ctrl.$modal.modal('hide');
                });
			};

			ctrl.deleteTask = function(event)
			{
				event.preventDefault();

                confirmService.show({
                    title: lmsg('projects.task.delete_task.title'),
                    message: lmsg('projects.task.delete_confirm'),
                }).then(function() {
                    ctrl.task.delete(function()
                    {
                        if (ctrl.taskDelete !== undefined)
                            ctrl.taskDelete({task: ctrl.task});

                        ctrl.$modal.modal('hide');
                        service.taskDeleted(ctrl.task);
                    }, function(data)
                    {
                        cla.showMessage(data.error, '', true);
                    });
                }, function() {});
			};

			ctrl.enableEditTaskPriority = function()
			{
				angular.element('.js-task-edit-priority').each(function()
				{
					if (angular.element(this).hasClass('select2-container'))
						return;

					// This should be automatic but it is invisible still at this point so not processed yet.
					angular.element(this).val(ctrl.task.priority);

					ctrl.colourSelect(angular.element(this));
				});
			};

			ctrl.colourSelect = function(target)
			{
				target.select2({
					templateResult: function (data)
					{
						if (!data.id) { return data.text; }
						return '<span class="task-priority-option task-priority-' + data.id + '" style="display:inline-block; margin-right:0;">&nbsp</span> ' + data.text;
					},
					templateSelection: function formatPrioritySelection (data)
					{
						if (!data.id) { return data.text; }
						return '<span class="task-priority-option task-priority-' + data.id + '" style="display:inline-block; margin-right:0;">&nbsp</span> ' + data.text;
					},
					escapeMarkup: function(markup)
					{
						return markup;
					},
					minimumResultsForSearch: Infinity, // Hide search box
					width: "100%"
				});
			};
		}

		function link(scope, element, attrs, controller)
		{
		    controller.$modal = angular.element('#task-edit-modal');
		    service.registerModal(controller.$modal);

		    controller.$modal.on('taskEdit', function(event, task){
		        controller.task = angular.copy(task);

                $timeout(function() {
                    controller.startTaskEdit();
                }, 0);
            });

            controller.$modal.on('taskEditFinished', function(event){
                controller.endTaskEdit(event);
            });

		    // Handle the modal closing for any reason
            controller.$modal.on('hidden.bs.modal', function(){
                controller.htmlControl.onClose();

                controller.visible = false;
            });
		}
	}
}());


/***/ }),

/***/ "./js/task/taskEdit.service.js":
/***/ (function(module, exports) {

(function()
{
    var moduleName = 'claromentis.project.tasks_util';
    var module;

    module = angular.module(moduleName);

    module.service('task_edit_service', TaskEditService);

    function TaskEditService()
    {
        var service = this;

        service.$currentElement = null
        service.$modalElement = null

        service.startEdit = function(task, $taskElement)
        {
            if (service.$currentElement !== null)
            {
                service.$currentElement.trigger('cancelEdit');
                service.$currentElement = null;
            }

            service.$currentElement = $taskElement;
            service.$modalElement.trigger('taskEdit', task);
        };

        service.taskUpdated = function(task, callback)
        {
            var updateFunc = 'update';
            if (task.id === 0)
                updateFunc = 'add';

            task[updateFunc](function(data)
            {
                service.$modalElement.trigger('taskEditFinished', task);

                if (service.$currentElement !== null)
                {
                    service.$currentElement.trigger('editComplete', task);
                    service.$currentElement = null;
                }

                cla.showMessage(lmsg('projects.history.type.task_updated'), '', false);

                callback();
            }, function(data)
            {
                cla.showMessage(data.error, '', true);
            });

            return task;
        };

        service.taskDeleted = function(task)
        {
            if (service.$currentElement !== null)
            {
                service.$currentElement.trigger('taskDeleted', task);
                service.$currentElement = null;
            }
        };

        service.registerModal = function($modalElement)
        {
          service.$modalElement = $modalElement;
        };
    }
}());


/***/ }),

/***/ "./node_modules/angular-utils-pagination/dirPagination.js":
/***/ (function(module, exports) {

/**
 * dirPagination - AngularJS module for paginating (almost) anything.
 *
 *
 * Credits
 * =======
 *
 * Daniel Tabuenca: https://groups.google.com/d/msg/angular/an9QpzqIYiM/r8v-3W1X5vcJ
 * for the idea on how to dynamically invoke the ng-repeat directive.
 *
 * I borrowed a couple of lines and a few attribute names from the AngularUI Bootstrap project:
 * https://github.com/angular-ui/bootstrap/blob/master/src/pagination/pagination.js
 *
 * Copyright 2014 Michael Bromley <michael@michaelbromley.co.uk>
 */

(function() {

    /**
     * Config
     */
    var moduleName = 'angularUtils.directives.dirPagination';
    var DEFAULT_ID = '__default';

    /**
     * Module
     */
    angular.module(moduleName, [])
        .directive('dirPaginate', ['$compile', '$parse', 'paginationService', dirPaginateDirective])
        .directive('dirPaginateNoCompile', noCompileDirective)
        .directive('dirPaginationControls', ['paginationService', 'paginationTemplate', dirPaginationControlsDirective])
        .filter('itemsPerPage', ['paginationService', itemsPerPageFilter])
        .service('paginationService', paginationService)
        .provider('paginationTemplate', paginationTemplateProvider)
        .run(['$templateCache',dirPaginationControlsTemplateInstaller]);

    function dirPaginateDirective($compile, $parse, paginationService) {

        return  {
            terminal: true,
            multiElement: true,
            priority: 100,
            compile: dirPaginationCompileFn
        };

        function dirPaginationCompileFn(tElement, tAttrs){

            var expression = tAttrs.dirPaginate;
            // regex taken directly from https://github.com/angular/angular.js/blob/v1.4.x/src/ng/directive/ngRepeat.js#L339
            var match = expression.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+track\s+by\s+([\s\S]+?))?\s*$/);

            var filterPattern = /\|\s*itemsPerPage\s*:\s*(.*\(\s*\w*\)|([^\)]*?(?=\s+as\s+))|[^\)]*)/;
            if (match[2].match(filterPattern) === null) {
                throw 'pagination directive: the \'itemsPerPage\' filter must be set.';
            }
            var itemsPerPageFilterRemoved = match[2].replace(filterPattern, '');
            var collectionGetter = $parse(itemsPerPageFilterRemoved);

            addNoCompileAttributes(tElement);

            // If any value is specified for paginationId, we register the un-evaluated expression at this stage for the benefit of any
            // dir-pagination-controls directives that may be looking for this ID.
            var rawId = tAttrs.paginationId || DEFAULT_ID;
            paginationService.registerInstance(rawId);

            return function dirPaginationLinkFn(scope, element, attrs){

                // Now that we have access to the `scope` we can interpolate any expression given in the paginationId attribute and
                // potentially register a new ID if it evaluates to a different value than the rawId.
                var paginationId = $parse(attrs.paginationId)(scope) || attrs.paginationId || DEFAULT_ID;
                
                // (TODO: this seems sound, but I'm reverting as many bug reports followed it's introduction in 0.11.0.
                // Needs more investigation.)
                // In case rawId != paginationId we deregister using rawId for the sake of general cleanliness
                // before registering using paginationId
                // paginationService.deregisterInstance(rawId);
                paginationService.registerInstance(paginationId);

                var repeatExpression = getRepeatExpression(expression, paginationId);
                addNgRepeatToElement(element, attrs, repeatExpression);

                removeTemporaryAttributes(element);
                var compiled =  $compile(element);

                var currentPageGetter = makeCurrentPageGetterFn(scope, attrs, paginationId);
                paginationService.setCurrentPageParser(paginationId, currentPageGetter, scope);

                if (typeof attrs.totalItems !== 'undefined') {
                    paginationService.setAsyncModeTrue(paginationId);
                    scope.$watch(function() {
                        return $parse(attrs.totalItems)(scope);
                    }, function (result) {
                        if (0 <= result) {
                            paginationService.setCollectionLength(paginationId, result);
                        }
                    });
                } else {
                    paginationService.setAsyncModeFalse(paginationId);
                    scope.$watchCollection(function() {
                        return collectionGetter(scope);
                    }, function(collection) {
                        if (collection) {
                            var collectionLength = (collection instanceof Array) ? collection.length : Object.keys(collection).length;
                            paginationService.setCollectionLength(paginationId, collectionLength);
                        }
                    });
                }

                // Delegate to the link function returned by the new compilation of the ng-repeat
                compiled(scope);
                 
                // (TODO: Reverting this due to many bug reports in v 0.11.0. Needs investigation as the
                // principle is sound)
                // When the scope is destroyed, we make sure to remove the reference to it in paginationService
                // so that it can be properly garbage collected
                // scope.$on('$destroy', function destroyDirPagination() {
                //     paginationService.deregisterInstance(paginationId);
                // });
            };
        }

        /**
         * If a pagination id has been specified, we need to check that it is present as the second argument passed to
         * the itemsPerPage filter. If it is not there, we add it and return the modified expression.
         *
         * @param expression
         * @param paginationId
         * @returns {*}
         */
        function getRepeatExpression(expression, paginationId) {
            var repeatExpression,
                idDefinedInFilter = !!expression.match(/(\|\s*itemsPerPage\s*:[^|]*:[^|]*)/);

            if (paginationId !== DEFAULT_ID && !idDefinedInFilter) {
                repeatExpression = expression.replace(/(\|\s*itemsPerPage\s*:\s*[^|\s]*)/, "$1 : '" + paginationId + "'");
            } else {
                repeatExpression = expression;
            }

            return repeatExpression;
        }

        /**
         * Adds the ng-repeat directive to the element. In the case of multi-element (-start, -end) it adds the
         * appropriate multi-element ng-repeat to the first and last element in the range.
         * @param element
         * @param attrs
         * @param repeatExpression
         */
        function addNgRepeatToElement(element, attrs, repeatExpression) {
            if (element[0].hasAttribute('dir-paginate-start') || element[0].hasAttribute('data-dir-paginate-start')) {
                // using multiElement mode (dir-paginate-start, dir-paginate-end)
                attrs.$set('ngRepeatStart', repeatExpression);
                element.eq(element.length - 1).attr('ng-repeat-end', true);
            } else {
                attrs.$set('ngRepeat', repeatExpression);
            }
        }

        /**
         * Adds the dir-paginate-no-compile directive to each element in the tElement range.
         * @param tElement
         */
        function addNoCompileAttributes(tElement) {
            angular.forEach(tElement, function(el) {
                if (el.nodeType === 1) {
                    angular.element(el).attr('dir-paginate-no-compile', true);
                }
            });
        }

        /**
         * Removes the variations on dir-paginate (data-, -start, -end) and the dir-paginate-no-compile directives.
         * @param element
         */
        function removeTemporaryAttributes(element) {
            angular.forEach(element, function(el) {
                if (el.nodeType === 1) {
                    angular.element(el).removeAttr('dir-paginate-no-compile');
                }
            });
            element.eq(0).removeAttr('dir-paginate-start').removeAttr('dir-paginate').removeAttr('data-dir-paginate-start').removeAttr('data-dir-paginate');
            element.eq(element.length - 1).removeAttr('dir-paginate-end').removeAttr('data-dir-paginate-end');
        }

        /**
         * Creates a getter function for the current-page attribute, using the expression provided or a default value if
         * no current-page expression was specified.
         *
         * @param scope
         * @param attrs
         * @param paginationId
         * @returns {*}
         */
        function makeCurrentPageGetterFn(scope, attrs, paginationId) {
            var currentPageGetter;
            if (attrs.currentPage) {
                currentPageGetter = $parse(attrs.currentPage);
            } else {
                // If the current-page attribute was not set, we'll make our own.
                // Replace any non-alphanumeric characters which might confuse
                // the $parse service and give unexpected results.
                // See https://github.com/michaelbromley/angularUtils/issues/233
                var defaultCurrentPage = (paginationId + '__currentPage').replace(/\W/g, '_');
                scope[defaultCurrentPage] = 1;
                currentPageGetter = $parse(defaultCurrentPage);
            }
            return currentPageGetter;
        }
    }

    /**
     * This is a helper directive that allows correct compilation when in multi-element mode (ie dir-paginate-start, dir-paginate-end).
     * It is dynamically added to all elements in the dir-paginate compile function, and it prevents further compilation of
     * any inner directives. It is then removed in the link function, and all inner directives are then manually compiled.
     */
    function noCompileDirective() {
        return {
            priority: 5000,
            terminal: true
        };
    }

    function dirPaginationControlsTemplateInstaller($templateCache) {
        $templateCache.put('angularUtils.directives.dirPagination.template', '<ul class="pagination" ng-if="1 < pages.length || !autoHide"><li ng-if="boundaryLinks" ng-class="{ disabled : pagination.current == 1 }"><a href="" ng-click="setCurrent(1)">&laquo;</a></li><li ng-if="directionLinks" ng-class="{ disabled : pagination.current == 1 }"><a href="" ng-click="setCurrent(pagination.current - 1)">&lsaquo;</a></li><li ng-repeat="pageNumber in pages track by tracker(pageNumber, $index)" ng-class="{ active : pagination.current == pageNumber, disabled : pageNumber == \'...\' || ( ! autoHide && pages.length === 1 ) }"><a href="" ng-click="setCurrent(pageNumber)">{{ pageNumber }}</a></li><li ng-if="directionLinks" ng-class="{ disabled : pagination.current == pagination.last }"><a href="" ng-click="setCurrent(pagination.current + 1)">&rsaquo;</a></li><li ng-if="boundaryLinks"  ng-class="{ disabled : pagination.current == pagination.last }"><a href="" ng-click="setCurrent(pagination.last)">&raquo;</a></li></ul>');
    }

    function dirPaginationControlsDirective(paginationService, paginationTemplate) {

        var numberRegex = /^\d+$/;

        var DDO = {
            restrict: 'AE',
            scope: {
                maxSize: '=?',
                onPageChange: '&?',
                paginationId: '=?',
                autoHide: '=?'
            },
            link: dirPaginationControlsLinkFn
        };

        // We need to check the paginationTemplate service to see whether a template path or
        // string has been specified, and add the `template` or `templateUrl` property to
        // the DDO as appropriate. The order of priority to decide which template to use is
        // (highest priority first):
        // 1. paginationTemplate.getString()
        // 2. attrs.templateUrl
        // 3. paginationTemplate.getPath()
        var templateString = paginationTemplate.getString();
        if (templateString !== undefined) {
            DDO.template = templateString;
        } else {
            DDO.templateUrl = function(elem, attrs) {
                return attrs.templateUrl || paginationTemplate.getPath();
            };
        }
        return DDO;

        function dirPaginationControlsLinkFn(scope, element, attrs) {

            // rawId is the un-interpolated value of the pagination-id attribute. This is only important when the corresponding dir-paginate directive has
            // not yet been linked (e.g. if it is inside an ng-if block), and in that case it prevents this controls directive from assuming that there is
            // no corresponding dir-paginate directive and wrongly throwing an exception.
            var rawId = attrs.paginationId ||  DEFAULT_ID;
            var paginationId = scope.paginationId || attrs.paginationId ||  DEFAULT_ID;

            if (!paginationService.isRegistered(paginationId) && !paginationService.isRegistered(rawId)) {
                var idMessage = (paginationId !== DEFAULT_ID) ? ' (id: ' + paginationId + ') ' : ' ';
                if (window.console) {
                    console.warn('Pagination directive: the pagination controls' + idMessage + 'cannot be used without the corresponding pagination directive, which was not found at link time.');
                }
            }

            if (!scope.maxSize) { scope.maxSize = 9; }
            scope.autoHide = scope.autoHide === undefined ? true : scope.autoHide;
            scope.directionLinks = angular.isDefined(attrs.directionLinks) ? scope.$parent.$eval(attrs.directionLinks) : true;
            scope.boundaryLinks = angular.isDefined(attrs.boundaryLinks) ? scope.$parent.$eval(attrs.boundaryLinks) : false;

            var paginationRange = Math.max(scope.maxSize, 5);
            scope.pages = [];
            scope.pagination = {
                last: 1,
                current: 1
            };
            scope.range = {
                lower: 1,
                upper: 1,
                total: 1
            };

            scope.$watch('maxSize', function(val) {
                if (val) {
                    paginationRange = Math.max(scope.maxSize, 5);
                    generatePagination();
                }
            });

            scope.$watch(function() {
                if (paginationService.isRegistered(paginationId)) {
                    return (paginationService.getCollectionLength(paginationId) + 1) * paginationService.getItemsPerPage(paginationId);
                }
            }, function(length) {
                if (0 < length) {
                    generatePagination();
                }
            });

            scope.$watch(function() {
                if (paginationService.isRegistered(paginationId)) {
                    return (paginationService.getItemsPerPage(paginationId));
                }
            }, function(current, previous) {
                if (current != previous && typeof previous !== 'undefined') {
                    goToPage(scope.pagination.current);
                }
            });

            scope.$watch(function() {
                if (paginationService.isRegistered(paginationId)) {
                    return paginationService.getCurrentPage(paginationId);
                }
            }, function(currentPage, previousPage) {
                if (currentPage != previousPage) {
                    goToPage(currentPage);
                }
            });

            scope.setCurrent = function(num) {
                if (paginationService.isRegistered(paginationId) && isValidPageNumber(num)) {
                    num = parseInt(num, 10);
                    paginationService.setCurrentPage(paginationId, num);
                }
            };

            /**
             * Custom "track by" function which allows for duplicate "..." entries on long lists,
             * yet fixes the problem of wrongly-highlighted links which happens when using
             * "track by $index" - see https://github.com/michaelbromley/angularUtils/issues/153
             * @param id
             * @param index
             * @returns {string}
             */
            scope.tracker = function(id, index) {
                return id + '_' + index;
            };

            function goToPage(num) {
                if (paginationService.isRegistered(paginationId) && isValidPageNumber(num)) {
                    var oldPageNumber = scope.pagination.current;

                    scope.pages = generatePagesArray(num, paginationService.getCollectionLength(paginationId), paginationService.getItemsPerPage(paginationId), paginationRange);
                    scope.pagination.current = num;
                    updateRangeValues();

                    // if a callback has been set, then call it with the page number as the first argument
                    // and the previous page number as a second argument
                    if (scope.onPageChange) {
                        scope.onPageChange({
                            newPageNumber : num,
                            oldPageNumber : oldPageNumber
                        });
                    }
                }
            }

            function generatePagination() {
                if (paginationService.isRegistered(paginationId)) {
                    var page = parseInt(paginationService.getCurrentPage(paginationId)) || 1;
                    scope.pages = generatePagesArray(page, paginationService.getCollectionLength(paginationId), paginationService.getItemsPerPage(paginationId), paginationRange);
                    scope.pagination.current = page;
                    scope.pagination.last = scope.pages[scope.pages.length - 1];
                    if (scope.pagination.last < scope.pagination.current) {
                        scope.setCurrent(scope.pagination.last);
                    } else {
                        updateRangeValues();
                    }
                }
            }

            /**
             * This function updates the values (lower, upper, total) of the `scope.range` object, which can be used in the pagination
             * template to display the current page range, e.g. "showing 21 - 40 of 144 results";
             */
            function updateRangeValues() {
                if (paginationService.isRegistered(paginationId)) {
                    var currentPage = paginationService.getCurrentPage(paginationId),
                        itemsPerPage = paginationService.getItemsPerPage(paginationId),
                        totalItems = paginationService.getCollectionLength(paginationId);

                    scope.range.lower = (currentPage - 1) * itemsPerPage + 1;
                    scope.range.upper = Math.min(currentPage * itemsPerPage, totalItems);
                    scope.range.total = totalItems;
                }
            }
            function isValidPageNumber(num) {
                return (numberRegex.test(num) && (0 < num && num <= scope.pagination.last));
            }
        }

        /**
         * Generate an array of page numbers (or the '...' string) which is used in an ng-repeat to generate the
         * links used in pagination
         *
         * @param currentPage
         * @param rowsPerPage
         * @param paginationRange
         * @param collectionLength
         * @returns {Array}
         */
        function generatePagesArray(currentPage, collectionLength, rowsPerPage, paginationRange) {
            var pages = [];
            var totalPages = Math.ceil(collectionLength / rowsPerPage);
            var halfWay = Math.ceil(paginationRange / 2);
            var position;

            if (currentPage <= halfWay) {
                position = 'start';
            } else if (totalPages - halfWay < currentPage) {
                position = 'end';
            } else {
                position = 'middle';
            }

            var ellipsesNeeded = paginationRange < totalPages;
            var i = 1;
            while (i <= totalPages && i <= paginationRange) {
                var pageNumber = calculatePageNumber(i, currentPage, paginationRange, totalPages);

                var openingEllipsesNeeded = (i === 2 && (position === 'middle' || position === 'end'));
                var closingEllipsesNeeded = (i === paginationRange - 1 && (position === 'middle' || position === 'start'));
                if (ellipsesNeeded && (openingEllipsesNeeded || closingEllipsesNeeded)) {
                    pages.push('...');
                } else {
                    pages.push(pageNumber);
                }
                i ++;
            }
            return pages;
        }

        /**
         * Given the position in the sequence of pagination links [i], figure out what page number corresponds to that position.
         *
         * @param i
         * @param currentPage
         * @param paginationRange
         * @param totalPages
         * @returns {*}
         */
        function calculatePageNumber(i, currentPage, paginationRange, totalPages) {
            var halfWay = Math.ceil(paginationRange/2);
            if (i === paginationRange) {
                return totalPages;
            } else if (i === 1) {
                return i;
            } else if (paginationRange < totalPages) {
                if (totalPages - halfWay < currentPage) {
                    return totalPages - paginationRange + i;
                } else if (halfWay < currentPage) {
                    return currentPage - halfWay + i;
                } else {
                    return i;
                }
            } else {
                return i;
            }
        }
    }

    /**
     * This filter slices the collection into pages based on the current page number and number of items per page.
     * @param paginationService
     * @returns {Function}
     */
    function itemsPerPageFilter(paginationService) {

        return function(collection, itemsPerPage, paginationId) {
            if (typeof (paginationId) === 'undefined') {
                paginationId = DEFAULT_ID;
            }
            if (!paginationService.isRegistered(paginationId)) {
                throw 'pagination directive: the itemsPerPage id argument (id: ' + paginationId + ') does not match a registered pagination-id.';
            }
            var end;
            var start;
            if (angular.isObject(collection)) {
                itemsPerPage = parseInt(itemsPerPage) || 9999999999;
                if (paginationService.isAsyncMode(paginationId)) {
                    start = 0;
                } else {
                    start = (paginationService.getCurrentPage(paginationId) - 1) * itemsPerPage;
                }
                end = start + itemsPerPage;
                paginationService.setItemsPerPage(paginationId, itemsPerPage);

                if (collection instanceof Array) {
                    // the array just needs to be sliced
                    return collection.slice(start, end);
                } else {
                    // in the case of an object, we need to get an array of keys, slice that, then map back to
                    // the original object.
                    var slicedObject = {};
                    angular.forEach(keys(collection).slice(start, end), function(key) {
                        slicedObject[key] = collection[key];
                    });
                    return slicedObject;
                }
            } else {
                return collection;
            }
        };
    }

    /**
     * Shim for the Object.keys() method which does not exist in IE < 9
     * @param obj
     * @returns {Array}
     */
    function keys(obj) {
        if (!Object.keys) {
            var objKeys = [];
            for (var i in obj) {
                if (obj.hasOwnProperty(i)) {
                    objKeys.push(i);
                }
            }
            return objKeys;
        } else {
            return Object.keys(obj);
        }
    }

    /**
     * This service allows the various parts of the module to communicate and stay in sync.
     */
    function paginationService() {

        var instances = {};
        var lastRegisteredInstance;

        this.registerInstance = function(instanceId) {
            if (typeof instances[instanceId] === 'undefined') {
                instances[instanceId] = {
                    asyncMode: false
                };
                lastRegisteredInstance = instanceId;
            }
        };

        this.deregisterInstance = function(instanceId) {
            delete instances[instanceId];
        };
        
        this.isRegistered = function(instanceId) {
            return (typeof instances[instanceId] !== 'undefined');
        };

        this.getLastInstanceId = function() {
            return lastRegisteredInstance;
        };

        this.setCurrentPageParser = function(instanceId, val, scope) {
            instances[instanceId].currentPageParser = val;
            instances[instanceId].context = scope;
        };
        this.setCurrentPage = function(instanceId, val) {
            instances[instanceId].currentPageParser.assign(instances[instanceId].context, val);
        };
        this.getCurrentPage = function(instanceId) {
            var parser = instances[instanceId].currentPageParser;
            return parser ? parser(instances[instanceId].context) : 1;
        };

        this.setItemsPerPage = function(instanceId, val) {
            instances[instanceId].itemsPerPage = val;
        };
        this.getItemsPerPage = function(instanceId) {
            return instances[instanceId].itemsPerPage;
        };

        this.setCollectionLength = function(instanceId, val) {
            instances[instanceId].collectionLength = val;
        };
        this.getCollectionLength = function(instanceId) {
            return instances[instanceId].collectionLength;
        };

        this.setAsyncModeTrue = function(instanceId) {
            instances[instanceId].asyncMode = true;
        };

        this.setAsyncModeFalse = function(instanceId) {
            instances[instanceId].asyncMode = false;
        };

        this.isAsyncMode = function(instanceId) {
            return instances[instanceId].asyncMode;
        };
    }

    /**
     * This provider allows global configuration of the template path used by the dir-pagination-controls directive.
     */
    function paginationTemplateProvider() {

        var templatePath = 'angularUtils.directives.dirPagination.template';
        var templateString;

        /**
         * Set a templateUrl to be used by all instances of <dir-pagination-controls>
         * @param {String} path
         */
        this.setPath = function(path) {
            templatePath = path;
        };

        /**
         * Set a string of HTML to be used as a template by all instances
         * of <dir-pagination-controls>. If both a path *and* a string have been set,
         * the string takes precedence.
         * @param {String} str
         */
        this.setString = function(str) {
            templateString = str;
        };

        this.$get = function() {
            return {
                getPath: function() {
                    return templatePath;
                },
                getString: function() {
                    return templateString;
                }
            };
        };
    }
})();


/***/ }),

/***/ 0:
/***/ (function(module, exports) {

module.exports = __WEBPACK_EXTERNAL_MODULE_0__;

/***/ }),

/***/ 1:
/***/ (function(module, exports) {

module.exports = __WEBPACK_EXTERNAL_MODULE_1__;

/***/ }),

/***/ 13:
/***/ (function(module, exports) {

module.exports = __WEBPACK_EXTERNAL_MODULE_13__;

/***/ }),

/***/ 14:
/***/ (function(module, exports, __webpack_require__) {

__webpack_require__("./assets/css/style.scss");
__webpack_require__("./assets/css/ng-sortable.scss");
module.exports = __webpack_require__("./js/projects.tasks.js");


/***/ }),

/***/ 2:
/***/ (function(module, exports) {

module.exports = __WEBPACK_EXTERNAL_MODULE_2__;

/***/ }),

/***/ 3:
/***/ (function(module, exports) {

module.exports = __WEBPACK_EXTERNAL_MODULE_3__;

/***/ }),

/***/ 4:
/***/ (function(module, exports) {

module.exports = __WEBPACK_EXTERNAL_MODULE_4__;

/***/ }),

/***/ 5:
/***/ (function(module, exports) {

module.exports = __WEBPACK_EXTERNAL_MODULE_5__;

/***/ }),

/***/ 7:
/***/ (function(module, exports) {

module.exports = __WEBPACK_EXTERNAL_MODULE_7__;

/***/ }),

/***/ 8:
/***/ (function(module, exports) {

module.exports = __WEBPACK_EXTERNAL_MODULE_8__;

/***/ })

/******/ })});;