(window["webpackJsonp"] = window["webpackJsonp"] || []).push([[3],{

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

module.exports = function escape(url) {
    if (typeof url !== 'string') {
        return url
    }
    // If url is already wrapped in quotes, remove them
    if (/^['"].*['"]$/.test(url)) {
        url = url.slice(1, -1);
    }
    // Should url be wrapped?
    // See https://drafts.csswg.org/css-values-3/#urls
    if (/["'() \t\n]/.test(url)) {
        return '"' + url.replace(/"/g, '\\"').replace(/\n/g, '\\n') + '"'
    }

    return url
}


/***/ }),

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

module.exports = "data:image/gif;base64,R0lGODlhQAASAMZzACYmJllZWRzE9y3I9y3J9y7I9y7J92HW+Xfc+oWFhYiIiJiYmKGhoaampqmpqby8vILf+6Xk+aXm+6fk+abm+6jn+6nn+67n+q/n+q7o+rDo+7Po+7Pp+8nJyd/f38Xu/Mfv/Mjv/M3u+8rw/NDv+9Dy/dXw+tfx/Nfy/Nny/Nry/Nzy+93y+9/z+9zz/N70/eLi4unp6ezs7O3t7e7u7uDz++H0++P0++L1/eP2/eX1++b1++f2++T2/eX2/eb3/ef3/ej2++j3/er3/Ov3/O33/On4/er4/ev4/ev4/u/4++34/Oz5/u35/u74/O/4/O75/u/5/u/6/vLy8vH4+/L5+/P5+/D4/PD6/vH6/vL6/vL7/vP7/vT5+/X6+/X6/PT7/vb6/Pf6/PX8/vb8/vf8/vj7/Pn7/Pr7/Pj9/vj9//n9//v8/Pr9//v+//z8/Pz+//3+//7//////////////////////////////////////////////////////yH5BAEAAH8ALAAAAABAABIAAAfGgH+Cg4SFhoeIiYqLjI2Oj5CRkpOUlZaXkUxCmIcdU5yEPQgfoIQNDjCRDwqJLwIEEpEZBzuJDTMMHo8PAACJKgIYAxSPEwICNrZ/Mgs0jbwBvogoAiIXBCCNEQIQAi3KfzEJM4vQ0Ykn1SQcAiWLxhDdNcrMzorm54gpAiQaBiGLMnCLJ+CGLVy6Fino1YsVIhcCNhCowOjAsWMHgthCVeoPDgEFLDTaYaNFjRtBniTy1PGPEQQjWsoUlAXKzJs4c+rcCSkQADs="

/***/ }),

/***/ 16:
/***/ (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(useSourceMap) {
	var list = [];

	// return the list of modules as css string
	list.toString = function toString() {
		return this.map(function (item) {
			var content = cssWithMappingToString(item, useSourceMap);
			if(item[2]) {
				return "@media " + item[2] + "{" + content + "}";
			} else {
				return content;
			}
		}).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;
};

function cssWithMappingToString(item, useSourceMap) {
	var content = item[1] || '';
	var cssMapping = item[3];
	if (!cssMapping) {
		return content;
	}

	if (useSourceMap && typeof btoa === 'function') {
		var sourceMapping = toComment(cssMapping);
		var sourceURLs = cssMapping.sources.map(function (source) {
			return '/*# sourceURL=' + cssMapping.sourceRoot + source + ' */'
		});

		return [content].concat(sourceURLs).concat([sourceMapping]).join('\n');
	}

	return [content].join('\n');
}

// Adapted from convert-source-map (MIT)
function toComment(sourceMap) {
	// eslint-disable-next-line no-undef
	var base64 = btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap))));
	var data = 'sourceMappingURL=data:application/json;charset=utf-8;base64,' + base64;

	return '/*# ' + data + ' */';
}


/***/ }),

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

/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/

var stylesInDom = {};

var	memoize = function (fn) {
	var memo;

	return function () {
		if (typeof memo === "undefined") memo = fn.apply(this, arguments);
		return memo;
	};
};

var 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;
});

var getElement = (function (fn) {
	var memo = {};

	return function(selector) {
		if (typeof memo[selector] === "undefined") {
			var styleTarget = fn.call(this, selector);
			// Special case to return head of iframe instead of iframe itself
			if (styleTarget instanceof window.HTMLIFrameElement) {
				try {
					// This will throw an exception if access to iframe is blocked
					// due to cross-origin restrictions
					styleTarget = styleTarget.contentDocument.head;
				} catch(e) {
					styleTarget = null;
				}
			}
			memo[selector] = styleTarget;
		}
		return memo[selector]
	};
})(function (target) {
	return document.querySelector(target)
});

var singleton = null;
var	singletonCounter = 0;
var	stylesInsertedAtTop = [];

var	fixUrls = __webpack_require__(40);

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 (!options.singleton && typeof options.singleton !== "boolean") options.singleton = isOldIE();

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

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

	var styles = listToStyles(list, options);

	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, options);
			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, options) {
	var styles = [];
	var newStyles = {};

	for (var i = 0; i < list.length; i++) {
		var item = list[i];
		var id = options.base ? item[0] + options.base : 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, style) {
	var target = getElement(options.insertInto)

	if (!target) {
		throw new Error("Couldn't find a style target. This probably means that the value for the 'insertInto' parameter is invalid.");
	}

	var lastStyleElementInsertedAtTop = stylesInsertedAtTop[stylesInsertedAtTop.length - 1];

	if (options.insertAt === "top") {
		if (!lastStyleElementInsertedAtTop) {
			target.insertBefore(style, target.firstChild);
		} else if (lastStyleElementInsertedAtTop.nextSibling) {
			target.insertBefore(style, lastStyleElementInsertedAtTop.nextSibling);
		} else {
			target.appendChild(style);
		}
		stylesInsertedAtTop.push(style);
	} else if (options.insertAt === "bottom") {
		target.appendChild(style);
	} else if (typeof options.insertAt === "object" && options.insertAt.before) {
		var nextSibling = getElement(options.insertInto + " " + options.insertAt.before);
		target.insertBefore(style, nextSibling);
	} else {
		throw new Error("[Style Loader]\n\n Invalid value for parameter 'insertAt' ('options.insertAt') found.\n Must be 'top', 'bottom', or Object.\n (https://github.com/webpack-contrib/style-loader#insertat)\n");
	}
}

function removeStyleElement (style) {
	if (style.parentNode === null) return false;
	style.parentNode.removeChild(style);

	var idx = stylesInsertedAtTop.indexOf(style);
	if(idx >= 0) {
		stylesInsertedAtTop.splice(idx, 1);
	}
}

function createStyleElement (options) {
	var style = document.createElement("style");

	options.attrs.type = "text/css";

	addAttrs(style, options.attrs);
	insertStyleElement(options, style);

	return style;
}

function createLinkElement (options) {
	var link = document.createElement("link");

	options.attrs.type = "text/css";
	options.attrs.rel = "stylesheet";

	addAttrs(link, options.attrs);
	insertStyleElement(options, link);

	return link;
}

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

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

	// If a transform function was defined, run it on the css
	if (options.transform && obj.css) {
	    result = options.transform(obj.css);

	    if (result) {
	    	// If transform returns a value, use that instead of the original css.
	    	// This allows running runtime transformations on the css.
	    	obj.css = result;
	    } else {
	    	// If the transform function returns a falsy value, don't add this css.
	    	// This allows conditional loading of css
	    	return function() {
	    		// noop
	    	};
	    }
	}

	if (options.singleton) {
		var styleIndex = singletonCounter++;

		style = singleton || (singleton = createStyleElement(options));

		update = applyToSingletonTag.bind(null, style, styleIndex, false);
		remove = applyToSingletonTag.bind(null, style, styleIndex, true);

	} else if (
		obj.sourceMap &&
		typeof URL === "function" &&
		typeof URL.createObjectURL === "function" &&
		typeof URL.revokeObjectURL === "function" &&
		typeof Blob === "function" &&
		typeof btoa === "function"
	) {
		style = createLinkElement(options);
		update = updateLink.bind(null, style, options);
		remove = function () {
			removeStyleElement(style);

			if(style.href) URL.revokeObjectURL(style.href);
		};
	} else {
		style = createStyleElement(options);
		update = applyToTag.bind(null, style);
		remove = function () {
			removeStyleElement(style);
		};
	}

	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 (style, index, remove, obj) {
	var css = remove ? "" : obj.css;

	if (style.styleSheet) {
		style.styleSheet.cssText = replaceText(index, css);
	} else {
		var cssNode = document.createTextNode(css);
		var childNodes = style.childNodes;

		if (childNodes[index]) style.removeChild(childNodes[index]);

		if (childNodes.length) {
			style.insertBefore(cssNode, childNodes[index]);
		} else {
			style.appendChild(cssNode);
		}
	}
}

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

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

	if(style.styleSheet) {
		style.styleSheet.cssText = css;
	} else {
		while(style.firstChild) {
			style.removeChild(style.firstChild);
		}

		style.appendChild(document.createTextNode(css));
	}
}

function updateLink (link, 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 = link.href;

	link.href = URL.createObjectURL(blob);

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


/***/ }),

/***/ 1728:
/***/ (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__(1729);
if(typeof content === 'string') content = [[module.i, content, '']];
// Prepare cssTransformation
var transform;

var options = {"hmr":true}
options.transform = transform
// add the styles to the DOM
var update = __webpack_require__(17)(content, options);
if(content.locals) module.exports = content.locals;
// Hot Module Replacement
if(false) {}

/***/ }),

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

var escape = __webpack_require__(103);
exports = module.exports = __webpack_require__(16)(false);
// imports


// module
exports.push([module.i, ".cal-print-marker { /* NOTE: this has to be the first line here. @see js/Printer/DaysView.js */\n    top:0;\n}\n.CalendarIconCls, .CalendarEvent {\n    background-image:url(" + escape(__webpack_require__(640)) + ");\n}\n\n.PreferencesTreePanel-CalendarIconCls {\n    background-image:url(" + escape(__webpack_require__(640)) + ") !important;\n}\n\n.cal-today-action {\n    background-image:url(" + escape(__webpack_require__(641)) + ") !important;\n}\n\n.cal-split-view {\n    background-image:url(" + escape(__webpack_require__(531)) + ") !important;\n}\n\n.cal-sheet-view-type {\n    background-image:url(" + escape(__webpack_require__(1730)) + ") !important;\n}\n\n.cal-grid-view-type {\n    background-image:url(" + escape(__webpack_require__(1731)) + ") !important;\n}\n\n.cal-timeline-view-type {\n    background-image:url(" + escape(__webpack_require__(1732)) + ") !important;\n}\n\n.cal-print-loose-leaf {\n    background-image:url(" + escape(__webpack_require__(1733)) + ") !important;\n}\n\n.cal-day-view {\n    background-image:url(" + escape(__webpack_require__(361)) + ") !important;\n}\n\n.cal-week-view {\n    background-image:url(" + escape(__webpack_require__(1734)) + ") !important;\n}\n\n.cal-month-view {\n    background-image:url(" + escape(__webpack_require__(542)) + ") !important;\n}\n\n.cal-year-view {\n    background-image: url(" + escape(__webpack_require__(1735)) + ") !important;\n}\n\n.cal-customperiod-view {\n    background-image:url(" + escape(__webpack_require__(1736)) + ") !important;\n}\n\n.cal-resource, .CalendarResource {\n    background-image:url(" + escape(__webpack_require__(364)) + ") !important;\n}\n\n.cal-calendartree-resource-icon .x-tree-node-icon {\n    background-image: none;\n}\n\n.cal-action_fretimesearch {\n    background-image:url(" + escape(__webpack_require__(1737)) + ") !important;\n}\n\n.cal-attendee-type-memberOf,\n.cal-attendee-type-groupmember {\n    background-image:url(" + escape(__webpack_require__(527)) + ") !important;\n}\n\n.cal-attendee-type-resource {\n    background-image:url(" + escape(__webpack_require__(364)) + ") !important;\n}\n\n.cal-attendee-resource-hierarchy {\n    font-size: 9px;\n    color: grey;\n    text-overflow: ellipsis;\n    white-space: nowrap;\n    overflow: hidden;\n    display: block;\n}\n\n.x-cal-add-attendee-row .x-grid3-col-checked {\n    display: none;\n}\n.x-cal-attendee-filter-grid .x-grid3-dirty-cell {\n    background-image:none;\n}\n\n/**** calendar select widget ****/\n.cal-calselectwidget-faketriggerwrap {\n    position: absolute;\n    top: 0;\n    right: 0;\n}\n\n.cal-calselectwidget-fakelist-item {\n    position: relative;\n    padding: 0;\n    border: 0;\n}\n\n.cal-calselectwidget-fakelist-calendar {\n    /*width: 290px;*/\n    float: left;\n    padding-left: 5px;\n}\n\n.cal-calselectwidget-fakelist-account {\n    width: 160px;\n    position: absolute;\n    right: 0;\n    border-left: 1px solid #B5B8C8;\n    padding-left: 5px;\n    background:url(" + escape(__webpack_require__(642)) + ") repeat-x #EFEFEF;\n}\n\n/*** container select widget\n * @todo move to container\n */\nspan.tw-containerselect-trigger2 img.tw-containerselect-trigger2-bg {\n    background:url(" + escape(__webpack_require__(642)) + ") repeat-x;\n    width: 150px;\n    cursor:pointer;\n}\n.tw-containerselect-trigger2 {position: relative;}\n\n/*.x-form-trigger-over .tw-containerselect-trigger2-bg {background-position: 0 -24px;}*/\n/*.x-form-trigger-over .tw-containerselect-trigger2 {background-position: -17px 0;}*/\n\n/*.x-form-trigger-click .tw-containerselect-trigger2-bg {background-position: 0 -48px;}*/\n/*.x-form-trigger-click .tw-containerselect-trigger2 {background-position: -34px 0;}*/\n\n/*.x-form-field-wrap .x-form-arrow-trigger-rectangle {*/\n    /*background-image: url(../../images/trigger-rect.gif);*/\n    /*cursor:pointer;*/\n/*}*/\n\n.cal-calselectwdgt {\n    position: relative;\n}\n\n/**** date picker ****/\n.cal-tree .x-date-picker {\n    border: 0;\n}\n\n.cal-datepicker-background .x-panel-body {\n    background-color: #EEEEEF;\n}\n\n.cal-event-icon {\n    /*background-image:url(../../images/icon-set/icon_event.svg) !important;*/\n    background-position: 8px;\n    background-repeat:no-repeat;\n    padding: 2px 0px 2px 6px;\n}\n\n/**** conflict window ****/\n.cal-conflict-heading {\n    height: 32px;\n}\n\n.cal-conflict-attendername {\n    white-space: nowrap;\n    text-overflow: ellipsis;\n    font-weight: bold;\n    background-position: 0;\n    height: 14px;\n    padding-left: 20px;\n}\n\n.cal-conflict-eventinfos {\n    margin-left: 20px;\n}\n\n.cal-conflict-eventinfos-unavailable {\n    padding-left: 5px;\n    font-style: italic;\n    color: red;\n}\n\n/**** status icons ****/\n.cal-status-icon {\n    background-size: 13px 13px;\n    background-repeat:no-repeat;\n    background-position: 0px -1px;\n    margin: 0px -1px 0px -1px;\n    width: 13px;\n    height: 13px;\n    cursor: pointer;\n\n}\n\n.cal-recurring {\n    background-image: url(" + escape(__webpack_require__(643)) + ") !important;\n    background-repeat:no-repeat;\n    width: 12px;\n    height: 12px;\n    padding: 0 2px;\n    vertical-align: text-bottom;\n    background-size: 13px 13px;\n}\n\n.cal-recurring.exception {\n    background-image: url(" + escape(__webpack_require__(644)) + ") !important;\n}\n\n.private-white      { background-image: url(" + escape(__webpack_require__(1738)) + ") !important; }\n.private-black      { background-image: url(" + escape(__webpack_require__(1739)) + ") !important; }\n.recur-white        { background-image: url(" + escape(__webpack_require__(1740)) + ") !important; }\n.recur-black        { background-image: url(" + escape(__webpack_require__(643)) + ") !important; }\n.recurex-white      { background-image: url(" + escape(__webpack_require__(1741)) + ") !important; }\n.recurex-black      { background-image: url(" + escape(__webpack_require__(644)) + ") !important; }\n.alarm-white        { background-image: url(" + escape(__webpack_require__(1742)) + ") !important; }\n.alarm-black        { background-image: url(" + escape(__webpack_require__(543)) + ") !important; }\n.NEEDS-ACTION-white { background-image: url(" + escape(__webpack_require__(1743)) + ") !important; }\n.NEEDS-ACTION-black { background-image: url(" + escape(__webpack_require__(1744)) + ") !important; }\n.ACCEPTED-white     { background-image: url(" + escape(__webpack_require__(1745)) + ") !important; }\n.ACCEPTED-black     { background-image: url(" + escape(__webpack_require__(544)) + ") !important; }\n.DECLINED-white     { background-image: url(" + escape(__webpack_require__(1746)) + ") !important; }\n.DECLINED-black     { background-image: url(" + escape(__webpack_require__(645)) + ") !important; }\n.TENTATIVE-white    { background-image: url(" + escape(__webpack_require__(1747)) + ") !important; }\n.TENTATIVE-black    { background-image: url(" + escape(__webpack_require__(1748)) + ") !important; }\n.attachment-white   { background-image: url(" + escape(__webpack_require__(1749)) + ") !important; }\n.attachment-black   { background-image: url(" + escape(__webpack_require__(525)) + ") !important; }\n.poll-white         { background-image: url(" + escape(__webpack_require__(1750)) + ") !important; }\n.poll-black         { background-image: url(" + escape(__webpack_require__(1751)) + ") !important; }\n\n.cal-status-TENTATIVE,\n.cal-status-TENTATIVE .x-grid3-cell-inner {\n    font-style: italic !important;\n}\n\n.cal-status-CANCELED,\n.cal-status-CANCELED .cal-daysviewpanel-event-body,\n.cal-status-CANCELED .cal-daysviewpanel-event-header-inner,\n.cal-status-CANCELED .x-grid3-cell-inner {\n    text-decoration: line-through !important;\n    opacity: 0.7;\n}\n\n.inline {\n    height: 24px;\n    padding: 0;\n    margin: 0;\n}\n.inline input {\n    margin-top: -14px;\n}\n.inline input,\n.inline table {\n    display: inline-block;\n}\n\n.cal-attendee-picker-combo-list-item .x-combo-list-item {\n    border: none;\n}\n\n.cal-fbinfo-state {\n    min-width: 16px;\n    min-height: 16px;\n    background-repeat: no-repeat;\n    background-size: 14px 14px;\n    opacity: 0.8;\n}\n\n.cal-fbinfo-state-free {\n    background-image: url(" + escape(__webpack_require__(1752)) + ") !important;\n}\n\n.cal-fbinfo-state-tentative {\n    background-image: url(" + escape(__webpack_require__(1753)) + ") !important;\n}\n\n.cal-fbinfo-state-busy {\n    background-image: url(" + escape(__webpack_require__(1754)) + ") !important;\n}\n\n.cal-fbinfo-state-unavailable {\n    background-image: url(" + escape(__webpack_require__(645)) + ") !important;\n}\n\n.cal-urlfield {\n    padding: 0 !important;\n    margin: 0 !important;\n}\n\n.x-grid3-cell .x-grid3-col-fbInfo {\n    padding-left: 2px;\n    padding-top: 1px;\n    padding-bottom: 0px;\n}\n\n.cal-poll-event {\n    opacity: 0.7;\n}\n\n.t-contenttype-event .action_add {\n    background-image:url(" + escape(__webpack_require__(1755)) + ") !important;\n}\n\n.t-contenttype-event .action_edit {\n    background-image:url(" + escape(__webpack_require__(1756)) + ") !important;\n}\n\n.t-contenttype-event .action_delete {\n    background-image:url(" + escape(__webpack_require__(1757)) + ") !important;\n}\n\n.t-contenttype-event .action_export {\n    background-image:url(" + escape(__webpack_require__(1758)) + ") !important;\n}\n\n.t-contenttype-event .action_import {\n    background-image:url(" + escape(__webpack_require__(1759)) + ") !important;\n}\n", ""]);

// exports


/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 23.0.6, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cstyle type='text/css'%3E .st0%7Bfill:%2304BAEE;%7D %3C/style%3E %3Cpath d='M7.4,35.6h5.5v-5.5H7.4V35.6z M14.1,35.6h6.1v-5.5h-6.1V35.6z M7.4,21.6h5.5v-5.5H7.4V21.6z M21.4,35.6h6.1v-5.5h-6.1V35.6z M14.1,21.6h6.1v-5.5h-6.1V21.6z M28.7,35.6h5.5v-5.5h-5.5V35.6z M14.7,12.5V7c0-0.2-0.1-0.3-0.2-0.4s-0.3-0.2-0.4-0.2h-1.2 c-0.2,0-0.3,0.1-0.4,0.2c-0.1,0.1-0.2,0.3-0.2,0.4v5.5c0,0.2,0.1,0.3,0.2,0.4c0.1,0.1,0.3,0.2,0.4,0.2h1.2c0.2,0,0.3-0.1,0.4-0.2 C14.7,12.8,14.7,12.7,14.7,12.5z M21.4,21.6h6.1v-5.5h-6.1V21.6z M28.7,21.6h5.5v-5.5h-5.5V21.6z M29.3,12.5V7 c0-0.2-0.1-0.3-0.2-0.4s-0.3-0.2-0.4-0.2h-1.2c-0.2,0-0.3,0.1-0.4,0.2S26.9,6.9,26.9,7v5.5c0,0.2,0.1,0.3,0.2,0.4 c0.1,0.1,0.3,0.2,0.4,0.2h1.2c0.2,0,0.3-0.1,0.4-0.2S29.3,12.7,29.3,12.5z M36.6,11.3v24.3c0,0.7-0.2,1.2-0.7,1.7S34.8,38,34.2,38 H7.4c-0.7,0-1.2-0.2-1.7-0.7S5,36.2,5,35.6V11.3c0-0.7,0.2-1.2,0.7-1.7s1.1-0.7,1.7-0.7h2.4V7c0-0.8,0.3-1.6,0.9-2.1S12.1,4,12.9,4 h1.2c0.8,0,1.6,0.3,2.1,0.9c0.6,0.6,0.9,1.3,0.9,2.1v1.8h7.3V7c0-0.8,0.3-1.6,0.9-2.1C25.9,4.3,26.6,4,27.5,4h1.2 c0.8,0,1.6,0.3,2.1,0.9s0.9,1.3,0.9,2.1v1.8h2.4c0.7,0,1.2,0.2,1.7,0.7C36.3,10.1,36.6,10.6,36.6,11.3z'/%3E %3Cpath class='st0' d='M34.2,22.8H7.4v6.1h26.7L34.2,22.8L34.2,22.8z'/%3E %3C/svg%3E\""

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 23.0.6, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cstyle type='text/css'%3E .st0%7Bfill:%2304BAEE;%7D .st1%7Bfill:%231D1D1B;%7D %3C/style%3E %3Cpath class='st0' d='M14,22.7h-4v-4h4V22.7z M32.2,18.7H15.6v4h16.6V18.7z M14,23.9h-4v4h4V23.9z M32.2,23.9H15.6v4h16.6V23.9z M14,29.2h-4v4h4V29.2z M32.2,29.2H15.6v4h16.6V29.2z'/%3E %3Cpath class='st1' d='M7.4,35.6h27.2V16.1H7.4V35.6z M14.7,12.5V7c0-0.2-0.1-0.3-0.2-0.4s-0.3-0.2-0.4-0.2h-1.2 c-0.2,0-0.3,0.1-0.4,0.2c-0.1,0.1-0.2,0.3-0.2,0.4v5.5c0,0.2,0.1,0.3,0.2,0.4c0.1,0.1,0.3,0.2,0.4,0.2h1.2c0.2,0,0.3-0.1,0.4-0.2 S14.7,12.7,14.7,12.5z M29.3,12.5V7c0-0.2-0.1-0.3-0.2-0.4s-0.3-0.2-0.4-0.2h-1.2c-0.2,0-0.3,0.1-0.4,0.2S26.9,6.9,26.9,7v5.5 c0,0.2,0.1,0.3,0.2,0.4s0.3,0.2,0.4,0.2h1.2c0.2,0,0.3-0.1,0.4-0.2S29.3,12.7,29.3,12.5z M36.6,11.3v24.3c0,0.7-0.2,1.2-0.7,1.7 S34.8,38,34.2,38H7.4c-0.7,0-1.2-0.2-1.7-0.7S5,36.2,5,35.6V11.3c0-0.7,0.2-1.2,0.7-1.7s1.1-0.7,1.7-0.7h2.4V7 c0-0.8,0.3-1.6,0.9-2.1S12.1,4,12.9,4h1.2c0.8,0,1.6,0.3,2.1,0.9c0.6,0.6,0.9,1.3,0.9,2.1v1.8h7.3V7c0-0.8,0.3-1.6,0.9-2.1 C25.9,4.3,26.6,4,27.5,4h1.2c0.8,0,1.6,0.3,2.1,0.9s0.9,1.3,0.9,2.1v1.8h2.4c0.7,0,1.2,0.2,1.7,0.7C36.3,10.1,36.6,10.6,36.6,11.3z'/%3E %3C/svg%3E\""

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 23.0.6, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cstyle type='text/css'%3E .st0%7Bfill:%2304BAEE;%7D %3C/style%3E %3Cpath class='st0' d='M12.9,21.6H7.4v-5.5h5.5V21.6z M20.8,22.8H14v6.1h6.7L20.8,22.8L20.8,22.8z M27.8,30.1h-7.2v5.5h7.2V30.1z'/%3E %3Cpath d='M7.4,35.6h5.5v-5.5H7.4V35.6z M14.1,35.6h6.1v-5.5h-6.1V35.6z M7.4,28.9h5.5v-6.1H7.4V28.9z M14.1,28.9h6.1v-6.1h-6.1V28.9z M7.4,21.6h5.5v-5.5H7.4V21.6z M21.4,35.6h6.1v-5.5h-6.1V35.6z M14.1,21.6h6.1v-5.5h-6.1V21.6z M28.7,35.6h5.5v-5.5h-5.5V35.6z M21.4,28.9h6.1v-6.1h-6.1V28.9z M14.7,12.5V7c0-0.2-0.1-0.3-0.2-0.4s-0.3-0.2-0.4-0.2h-1.2c-0.2,0-0.3,0.1-0.4,0.2 c-0.1,0.1-0.2,0.3-0.2,0.4v5.5c0,0.2,0.1,0.3,0.2,0.4c0.1,0.1,0.3,0.2,0.4,0.2h1.2c0.2,0,0.3-0.1,0.4-0.2 C14.7,12.8,14.7,12.7,14.7,12.5z M28.7,28.9h5.5v-6.1h-5.5V28.9z M21.4,21.6h6.1v-5.5h-6.1V21.6z M28.7,21.6h5.5v-5.5h-5.5V21.6z M29.3,12.5V7c0-0.2-0.1-0.3-0.2-0.4s-0.3-0.2-0.4-0.2h-1.2c-0.2,0-0.3,0.1-0.4,0.2S26.9,6.9,26.9,7v5.5c0,0.2,0.1,0.3,0.2,0.4 c0.1,0.1,0.3,0.2,0.4,0.2h1.2c0.2,0,0.3-0.1,0.4-0.2S29.3,12.7,29.3,12.5z M36.6,11.3v24.3c0,0.7-0.2,1.2-0.7,1.7S34.8,38,34.2,38 H7.4c-0.7,0-1.2-0.2-1.7-0.7S5,36.2,5,35.6V11.3c0-0.7,0.2-1.2,0.7-1.7s1.1-0.7,1.7-0.7h2.4V7c0-0.8,0.3-1.6,0.9-2.1S12.1,4,12.9,4 h1.2c0.8,0,1.6,0.3,2.1,0.9c0.6,0.6,0.9,1.3,0.9,2.1v1.8h7.3V7c0-0.8,0.3-1.6,0.9-2.1C25.9,4.3,26.6,4,27.5,4h1.2 c0.8,0,1.6,0.3,2.1,0.9s0.9,1.3,0.9,2.1v1.8h2.4c0.7,0,1.2,0.2,1.7,0.7C36.3,10.1,36.6,10.6,36.6,11.3z'/%3E %3C/svg%3E\""

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 43 43' style='enable-background:new 0 0 43 43;' xml:space='preserve' width='43' height='43'%3E %3Cpath d='M33.6,4.5c-1,0-4.5,0-4.5,0v1.1C29.6,5.9,30,6.4,30,7c0,0.9-0.8,1.7-1.7,1.7c-0.9,0-1.7-0.8-1.7-1.7c0-0.6,0.4-1.2,0.9-1.5 V4.5h-5.3v1.1C22.6,5.9,23,6.4,23,7c0,0.9-0.6,1.7-1.6,1.7c-0.9,0-1.7-0.8-1.7-1.7c0-0.6,0.4-1.2,0.9-1.5V4.5h-5.1v1.1 C16,5.9,16.2,6.4,16.2,7c0,0.9-0.6,1.7-1.6,1.7C13.7,8.7,13,8,13,7c0-0.6,0.4-1.2,0.9-1.5V4.5c0,0-3.4,0-4.8,0s-2.1,0.8-2.1,2 c0,6.8,0,28.2,0,29.5c0,2,0,2.5,2.3,2.5s22.5,0,24.5,0s2.3-0.6,2.3-2.4c0-1.4,0-23.1,0-29.7C36,4.5,34.6,4.5,33.6,4.5z M33.6,36.1 H9.3V9.9h24.3V36.1z M29.8,19.3c0,0.2-0.1,0.3-0.2,0.4c-0.1,0.1-0.3,0.2-0.5,0.2H14.1c-0.2,0-0.4-0.1-0.5-0.2 c-0.1-0.1-0.2-0.3-0.2-0.4v-1.2c0-0.2,0.1-0.3,0.2-0.4c0.1-0.1,0.3-0.2,0.5-0.2h15.1c0.2,0,0.4,0.1,0.5,0.2c0.1,0.1,0.2,0.3,0.2,0.4 V19.3z M29.1,22.4c0.2,0,0.4,0.1,0.5,0.2c0.1,0.1,0.2,0.3,0.2,0.4v1.2c0,0.2-0.1,0.3-0.2,0.4c-0.1,0.1-0.3,0.2-0.5,0.2H14.1 c-0.2,0-0.4-0.1-0.5-0.2c-0.1-0.1-0.2-0.3-0.2-0.4V23c0-0.2,0.1-0.3,0.2-0.4c0.1-0.1,0.3-0.2,0.5-0.2H29.1z M29.1,27.2 c0.2,0,0.4,0.1,0.5,0.2c0.1,0.1,0.2,0.3,0.2,0.4v1.2c0,0.2-0.1,0.3-0.2,0.4c-0.1,0.1-0.3,0.2-0.5,0.2H14.1c-0.2,0-0.4-0.1-0.5-0.2 c-0.1-0.1-0.2-0.3-0.2-0.4v-1.2c0-0.2,0.1-0.3,0.2-0.4c0.1-0.1,0.3-0.2,0.5-0.2H29.1z'/%3E %3C/svg%3E\""

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cstyle type='text/css'%3E .st0%7Bfill:%23FFFFFF;%7D .st1%7Bfill:%2304BAEE;%7D %3C/style%3E %3Crect x='7.4' y='16.1' class='st0' width='26.7' height='19.6'/%3E %3Cpath d='M7.4,35.6h5.5v-5.5H7.4V35.6z M14.1,35.6h6.1v-5.5h-6.1V35.6z M7.4,21.6h5.5v-5.5H7.4V21.6z M21.4,35.6h6.1v-5.5h-6.1V35.6z M14.1,21.6h6.1v-5.5h-6.1V21.6z M28.7,35.6h5.5v-5.5h-5.5V35.6z M14.7,12.5V7c0-0.2-0.1-0.3-0.2-0.4s-0.3-0.2-0.4-0.2h-1.2 c-0.2,0-0.3,0.1-0.4,0.2c-0.1,0.1-0.2,0.3-0.2,0.4v5.5c0,0.2,0.1,0.3,0.2,0.4c0.1,0.1,0.3,0.2,0.4,0.2h1.2c0.2,0,0.3-0.1,0.4-0.2 C14.7,12.8,14.7,12.7,14.7,12.5z M21.4,21.6h6.1v-5.5h-6.1V21.6z M28.7,21.6h5.5v-5.5h-5.5V21.6z M29.3,12.5V7 c0-0.2-0.1-0.3-0.2-0.4s-0.3-0.2-0.4-0.2h-1.2c-0.2,0-0.3,0.1-0.4,0.2S26.9,6.9,26.9,7v5.5c0,0.2,0.1,0.3,0.2,0.4 c0.1,0.1,0.3,0.2,0.4,0.2h1.2c0.2,0,0.3-0.1,0.4-0.2C29.2,12.8,29.3,12.7,29.3,12.5z M36.6,11.3v24.3c0,0.7-0.2,1.2-0.7,1.7 c-0.5,0.5-1.1,0.7-1.7,0.7H7.4c-0.7,0-1.2-0.2-1.7-0.7C5.2,36.8,5,36.2,5,35.6V11.3c0-0.7,0.2-1.2,0.7-1.7c0.5-0.5,1.1-0.7,1.7-0.7 h2.4V7c0-0.8,0.3-1.6,0.9-2.1S12.1,4,12.9,4h1.2c0.8,0,1.6,0.3,2.1,0.9c0.6,0.6,0.9,1.3,0.9,2.1v1.8h7.3V7c0-0.8,0.3-1.6,0.9-2.1 C25.9,4.3,26.6,4,27.5,4h1.2c0.8,0,1.6,0.3,2.1,0.9s0.9,1.3,0.9,2.1v1.8h2.4c0.7,0,1.2,0.2,1.7,0.7C36.3,10.1,36.6,10.6,36.6,11.3z'/%3E %3Cpath class='st1' d='M34.2,22.8H7.4v6.1h26.7V22.8z'/%3E %3C/svg%3E\""

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 24.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cstyle type='text/css'%3E .st0%7Bfill:%23FFFFFF;%7D %3C/style%3E %3Cpath d='M7.4,35.6h27.2V16.1H7.4V35.6z M14.7,12.5V7c0-0.2-0.1-0.3-0.2-0.4s-0.3-0.2-0.4-0.2h-1.2c-0.2,0-0.3,0.1-0.4,0.2 c-0.1,0.1-0.2,0.3-0.2,0.4v5.5c0,0.2,0.1,0.3,0.2,0.4c0.1,0.1,0.3,0.2,0.4,0.2h1.2c0.2,0,0.3-0.1,0.4-0.2S14.7,12.7,14.7,12.5z M29.3,12.5V7c0-0.2-0.1-0.3-0.2-0.4s-0.3-0.2-0.4-0.2h-1.2c-0.2,0-0.3,0.1-0.4,0.2S26.9,6.9,26.9,7v5.5c0,0.2,0.1,0.3,0.2,0.4 s0.3,0.2,0.4,0.2h1.2c0.2,0,0.3-0.1,0.4-0.2S29.3,12.7,29.3,12.5z M36.6,11.3v24.3c0,0.7-0.2,1.2-0.7,1.7S34.8,38,34.2,38H7.4 c-0.7,0-1.2-0.2-1.7-0.7S5,36.2,5,35.6V11.3c0-0.7,0.2-1.2,0.7-1.7s1.1-0.7,1.7-0.7h2.4V7c0-0.8,0.3-1.6,0.9-2.1S12.1,4,12.9,4h1.2 c0.8,0,1.6,0.3,2.1,0.9c0.6,0.6,0.9,1.3,0.9,2.1v1.8h7.3V7c0-0.8,0.3-1.6,0.9-2.1C25.9,4.3,26.6,4,27.5,4h1.2c0.8,0,1.6,0.3,2.1,0.9 s0.9,1.3,0.9,2.1v1.8h2.4c0.7,0,1.2,0.2,1.7,0.7C36.3,10.1,36.6,10.6,36.6,11.3z M23.4,19.5v2.2h-0.1c-0.9,0-1.6,0.3-2.2,0.7 c-0.5,0.4-0.9,1.2-1.1,2.1c0.5-0.6,1.3-0.9,2-0.9c0.9,0,1.6,0.4,2.1,1.2s0.8,1.7,0.8,3c0,0.7-0.2,1.4-0.5,2.1 c-0.3,0.6-0.8,1.2-1.3,1.4c-0.5,0.4-1.2,0.5-1.9,0.5c-0.7,0-1.4-0.2-2-0.5c-0.5-0.4-1-0.9-1.3-1.6c-0.3-0.7-0.5-1.5-0.5-2.4v-1.1 c0-1.3,0.2-2.3,0.7-3.3s1.1-1.7,2-2.3c0.9-0.5,1.8-0.8,2.8-0.8L23.4,19.5L23.4,19.5z M25.7,25.8l0.6-6.1h6v2.2h-4.1l-0.2,2.3 c0.2-0.1,0.4-0.2,0.7-0.3s0.5-0.1,0.8-0.1c1,0,1.8,0.4,2.4,1.1s0.9,1.7,0.9,3c0,0.7-0.2,1.4-0.5,2.1C32,30.6,31.6,31,31,31.4 c-0.5,0.4-1.2,0.5-1.9,0.5c-0.6,0-1.3-0.2-1.8-0.4c-0.5-0.3-1-0.7-1.3-1.3c-0.3-0.5-0.5-1.2-0.5-1.8H28c0,0.4,0.2,0.8,0.4,1.1 c0.2,0.3,0.5,0.4,0.9,0.4c0.8,0,1.2-0.7,1.2-2.1c0-1.3-0.5-1.9-1.5-1.9c-0.5,0-0.9,0.2-1.3,0.6L25.7,25.8z M11.8,24.7h1.1 c0.9,0,1.3-0.5,1.3-1.5c0-0.4-0.1-0.7-0.3-1c-0.2-0.3-0.5-0.4-0.9-0.4c-0.3,0-0.6,0.1-0.9,0.4c-0.2,0.3-0.3,0.4-0.3,0.8H9.3 c0-0.6,0.2-1.2,0.5-1.7c0.3-0.4,0.7-0.9,1.3-1.2c0.5-0.3,1.1-0.4,1.8-0.4c1.2,0,2,0.3,2.7,0.9c0.7,0.6,1,1.4,1,2.5 c0,0.5-0.2,1-0.4,1.4c-0.2,0.4-0.7,0.8-1.2,1.1c0.5,0.3,1,0.5,1.3,1.1c0.3,0.4,0.5,1.1,0.5,1.7c0,1.1-0.4,1.9-1.1,2.5 c-0.7,0.6-1.6,1-2.8,1c-0.7,0-1.3-0.2-1.9-0.4c-0.5-0.3-1-0.7-1.3-1.3c-0.3-0.5-0.5-1.1-0.5-1.8h2.4c0,0.4,0.2,0.7,0.4,1 c0.2,0.3,0.5,0.4,0.9,0.4s0.8-0.2,1-0.4s0.4-0.6,0.4-1c0-0.6-0.2-1-0.4-1.3s-0.6-0.4-1.1-0.4h-1.2V24.7z'/%3E %3Cellipse class='st0' cx='21.4' cy='27.7' rx='1.6' ry='2'/%3E %3C/svg%3E\""

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 24.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cstyle type='text/css'%3E .st0%7Bfill:%2304BAEE;%7D .st1%7Bfill:%23FFFFFF;%7D %3C/style%3E %3Cpath class='st0' d='M18.3,26.6h-2.6v-2.3h2.6V26.6z M22.2,24.3h-2.6v2.3h2.6V24.3z M26,24.3h-2.6v2.3H26V24.3z M29.8,24.3h-2.6v2.3 h2.6V24.3z M33.7,24.3h-2.6v2.3h2.6V24.3z M18.3,22.7h-2.6v-2.3h2.6V22.7z M22.2,20.4h-2.6v2.3h2.6V20.4z M26,20.4h-2.6v2.3H26V20.4 z M29.8,20.4h-2.6v2.3h2.6V20.4z M33.7,20.4h-2.6v2.3h2.6V20.4z M18.3,28h-2.6v2.3h2.6V28z M22.2,28h-2.6v2.3h2.6V28z M26,28h-2.6 v2.3H26V28z M29.8,28h-2.6v2.3h2.6V28z M33.7,28h-2.6v2.3h2.6V28z M22.2,31.8h-2.6v2.3h2.6V31.8z'/%3E %3Cpath d='M14.5,16.7h-2.6V19h2.6V16.7z M18.3,16.7h-2.6V19h2.6V16.7z M22.2,16.7h-2.6V19h2.6V16.7z M26,16.7h-2.6V19H26V16.7z M29.8,16.7h-2.6V19h2.6V16.7z M33.7,16.7h-2.6V19h2.6V16.7z M10.7,31.8H8v2.3h2.6L10.7,31.8L10.7,31.8z M14.5,31.8h-2.6v2.3h2.6 V31.8z M6.5,14.8h28.7v20.8H6.5V14.8z M14.5,12.9c-0.1,0.1-0.3,0.2-0.4,0.2h-1.2c-0.2,0-0.3-0.1-0.4-0.2c-0.1-0.1-0.2-0.3-0.2-0.4V7 c0-0.2,0.1-0.3,0.2-0.4c0.1-0.1,0.3-0.2,0.4-0.2h1.2c0.2,0,0.3,0.1,0.4,0.2s0.2,0.3,0.2,0.4v5.5C14.7,12.7,14.7,12.8,14.5,12.9z M29.1,12.9c-0.1,0.1-0.3,0.2-0.4,0.2h-1.2c-0.2,0-0.3-0.1-0.4-0.2s-0.2-0.3-0.2-0.4V7c0-0.2,0.1-0.3,0.2-0.4s0.3-0.2,0.4-0.2h1.2 c0.2,0,0.3,0.1,0.4,0.2s0.2,0.3,0.2,0.4v5.5C29.3,12.7,29.2,12.8,29.1,12.9z M35.9,9.6c-0.5-0.5-1.1-0.7-1.7-0.7h-2.4V7 c0-0.8-0.3-1.6-0.9-2.1S29.5,4,28.7,4h-1.2c-0.8,0-1.6,0.3-2.1,0.9c-0.6,0.6-0.9,1.3-0.9,2.1v1.8h-7.3V7c0-0.8-0.3-1.6-0.9-2.1 C15.7,4.3,14.9,4,14.1,4h-1.2c-0.8,0-1.6,0.3-2.1,0.9S9.9,6.2,9.9,7v1.8H7.4C6.7,8.8,6.2,9,5.7,9.5S5,10.6,5,11.3v24.3 c0,0.7,0.2,1.2,0.7,1.7S6.8,38,7.4,38h26.7c0.7,0,1.2-0.2,1.7-0.7s0.7-1.1,0.7-1.7V11.3C36.6,10.6,36.3,10.1,35.9,9.6z M25.9,31.8 h-2.6v2.3h2.6V31.8z M10.6,16.6H8v2.3h2.6V16.6z'/%3E %3Cg%3E %3Ccircle class='st1' cx='14.5' cy='17.3' r='2'/%3E %3C/g%3E %3Cg%3E %3Cpath d='M12.4,40.8c-0.9,0-1.7-0.2-2.4-0.7l-5.2-3c-1.6-0.9-2.5-2.7-2.4-4.6L3,20.9l0.7-0.1c0.2,0,0.4-0.1,0.6-0.1 c0.5,0,1,0.2,1.5,0.5c0.6,0.4,1,1.1,1.1,1.8l0.4,2.3l5.3-9.1l3.1,1.9l-4.4,7.6l1.7-2.9c0.3-0.6,1-0.9,1.6-0.9 c0.3,0,0.6,0.1,0.9,0.2c0.9,0.5,1.2,1.7,0.6,2.6l-1.5,2.6l1.2-2c0.4-0.6,1-1,1.7-1c0.3,0,0.6,0.1,0.9,0.2c0.9,0.5,1.1,1.7,0.6,2.6 l-1.1,1.9l0.6-1c0.4-0.6,1-1,1.7-1c0.3,0,0.6,0.1,0.9,0.2c0.9,0.5,1.2,1.7,0.6,2.6c-1.3,2.2-1.7,3-2.9,5l-1.7,3 C16.1,39.8,14.3,40.8,12.4,40.8L12.4,40.8z'/%3E %3Cpath class='st1' d='M12.7,16.9l2.4,1.5L11,25.6c-0.1,0.2-0.1,0.5,0.2,0.6c0.1,0,0.1,0.1,0.2,0.1c0.1,0,0.3-0.1,0.4-0.2l1.7-2.9 c0.3-0.5,0.8-0.7,1.3-0.7c0.2,0,0.5,0.1,0.7,0.2l0,0c0.7,0.4,0.9,1.3,0.5,2l-1.5,2.6c-0.1,0.2-0.1,0.5,0.2,0.6 c0.1,0,0.1,0.1,0.2,0.1c0.1,0,0.3-0.1,0.4-0.2l1.2-2c0.3-0.5,0.8-0.8,1.3-0.8c0.2,0,0.5,0.1,0.7,0.2c0.7,0.4,0.9,1.3,0.4,2.1 L17.6,29c-0.1,0.2-0.1,0.5,0.2,0.6c0.1,0,0.1,0.1,0.2,0.1c0.1,0,0.3-0.1,0.4-0.2l0.6-1c0.3-0.5,0.8-0.8,1.3-0.8 c0.2,0,0.5,0.1,0.7,0.2l0,0c0.7,0.4,0.9,1.3,0.5,2c-1.3,2.2-1.7,3-2.9,5c-0.4,0.8-1,1.7-1.7,3c-1,1.6-2.7,2.6-4.3,2.6 c-0.8,0-1.5-0.2-2.2-0.6l-5.2-3c-1.4-0.8-2.3-2.5-2.2-4.3l0.6-11.3l0.4-0.1c0,0,0,0,0,0c0.2,0,0.3-0.1,0.5-0.1 c0.4,0,0.9,0.1,1.3,0.4c0.5,0.4,0.9,0.9,1,1.6l0.4,2.3c0,0.2,0.2,0.3,0.3,0.4c0,0,0.1,0,0.1,0c0.2,0,0.3-0.1,0.4-0.2L12.7,16.9 M12.5,15.7L12,16.4l-4.5,7.8L7.3,23c-0.1-0.8-0.6-1.6-1.3-2.1c-0.5-0.3-1.1-0.5-1.7-0.5c-0.2,0-0.5,0-0.7,0.1l-0.4,0.1l-0.6,0.1 l0,0.7L2,32.5c-0.1,2.1,0.9,4,2.6,5l5.2,3c0.8,0.5,1.7,0.7,2.6,0.7c2,0,4-1.1,5-3l1.7-3c1.2-2,1.6-2.8,2.9-5 c0.7-1.1,0.3-2.5-0.7-3.2c-0.4-0.2-0.8-0.3-1.2-0.3c-0.2,0-0.4,0-0.6,0.1c0.3-1-0.1-2-1-2.5C18.4,24.1,18,24,17.6,24 c-0.2,0-0.5,0-0.7,0.1c0-0.3,0-0.5,0-0.8c-0.1-0.6-0.5-1.1-1-1.4c-0.4-0.2-0.8-0.3-1.1-0.3c-0.2,0-0.3,0-0.5,0.1l1.7-2.9l0.4-0.7 l-0.7-0.4l-2.4-1.5L12.5,15.7L12.5,15.7z'/%3E %3C/g%3E %3Cg%3E %3Ccircle cx='14' cy='17.5' r='1.4'/%3E %3C/g%3E %3C/svg%3E\""

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cstyle type='text/css'%3E .st0%7Bfill:%23FFFFFF;%7D %3C/style%3E %3Cpath d='M14.7,12.5V7c0-0.2-0.1-0.3-0.2-0.4s-0.3-0.2-0.4-0.2h-1.2c-0.2,0-0.3,0.1-0.4,0.2c-0.1,0.1-0.2,0.3-0.2,0.4v5.5 c0,0.2,0.1,0.3,0.2,0.4c0.1,0.1,0.3,0.2,0.4,0.2h1.2c0.2,0,0.3-0.1,0.4-0.2C14.7,12.8,14.7,12.7,14.7,12.5z M29.3,12.5V7 c0-0.2-0.1-0.3-0.2-0.4s-0.3-0.2-0.4-0.2h-1.2c-0.2,0-0.3,0.1-0.4,0.2S26.9,6.9,26.9,7v5.5c0,0.2,0.1,0.3,0.2,0.4 c0.1,0.1,0.3,0.2,0.4,0.2h1.2c0.2,0,0.3-0.1,0.4-0.2C29.2,12.8,29.3,12.7,29.3,12.5z M36.6,11.3v24.3c0,0.7-0.2,1.2-0.7,1.7 c-0.5,0.5-1.1,0.7-1.7,0.7H7.4c-0.7,0-1.2-0.2-1.7-0.7C5.2,36.8,5,36.2,5,35.6V11.3c0-0.7,0.2-1.2,0.7-1.7c0.5-0.5,1.1-0.7,1.7-0.7 h2.4V7c0-0.8,0.3-1.6,0.9-2.1S12.1,4,12.9,4h1.2c0.8,0,1.6,0.3,2.1,0.9c0.6,0.6,0.9,1.3,0.9,2.1v1.8h7.3V7c0-0.8,0.3-1.6,0.9-2.1 C25.9,4.3,26.6,4,27.5,4h1.2c0.8,0,1.6,0.3,2.1,0.9s0.9,1.3,0.9,2.1v1.8h2.4c0.7,0,1.2,0.2,1.7,0.7C36.3,10.1,36.6,10.6,36.6,11.3z'/%3E %3Cpath class='st0' d='M34.2,14.5h-27v21.3h27V14.5z'/%3E %3Cpath d='M26.5,29.1c2-4,0.8-8.9-3-11.4c-4.1-2.7-9.6-1.6-12.3,2.5c-2.7,4.1-1.6,9.6,2.5,12.3c3.8,2.5,8.8,1.8,11.7-1.6 M14.6,31.1 c-3.3-2.2-4.2-6.7-2-10.1c2.2-3.3,6.7-4.2,10.1-2c3.3,2.2,4.2,6.7,2,10.1C22.4,32.4,17.9,33.3,14.6,31.1z M26.5,29.1l4.8,3.2 c0.2,0.2,0.4,0.4,0.4,0.7c0.1,0.3,0,0.5-0.2,0.8c-0.2,0.2-0.4,0.4-0.7,0.5c-0.3,0.1-0.6,0-0.8-0.2l-4.8-3.2'/%3E %3C/svg%3E\""

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cpath stroke='white' fill='white' d='M34.1,20.1c-0.4-0.5-1-0.7-1.6-0.7h-0.8v-4.6c0-2.9-1.1-5.5-3.2-7.6C26.4,5.1,23.9,4,20.9,4s-5.5,1.2-7.6,3.3 c-2.1,2.1-3.2,4.6-3.2,7.6v4.6H9.3c-0.6,0-1.1,0.2-1.6,0.7c-0.5,0.4-0.7,1-0.7,1.6v13.9c0,0.6,0.2,1.1,0.7,1.6 c0.4,0.5,1,0.7,1.6,0.7h23.2c0.6,0,1.1-0.2,1.6-0.7c0.5-0.4,0.7-1,0.7-1.6V21.8C34.8,21.1,34.6,20.6,34.1,20.1z M12.5,15.1 c0-2.4,0.8-4.4,2.5-6.1s3.6-2.5,6-2.5s4,0.8,5.7,2.5s2.5,3.7,2.5,6.1v4.4H12.5V15.1z M31.8,33.5c0,0.4-0.2,0.8-0.5,1.1 c-0.4,0.3-0.8,0.5-1.2,0.5H12c-0.5,0-0.9-0.1-1.2-0.5c-0.4-0.3-0.5-0.7-0.5-1.1V24c0-0.4,0.2-0.8,0.5-1.1c0.4-0.3,0.8-0.5,1.2-0.5 h0.6l16.8-0.1H30c0.5,0,0.9,0.1,1.2,0.5c0.4,0.3,0.5,0.7,0.5,1.2V33.5z M27.6,28.2H14.2c-0.2,0-0.3,0.1-0.4,0.2 c-0.1,0.1-0.2,0.3-0.2,0.4V30c0,0.2,0.1,0.3,0.2,0.4c0.1,0.1,0.3,0.2,0.4,0.2h13.4c0.2,0,0.3-0.1,0.4-0.2c0.1-0.1,0.2-0.3,0.2-0.4 v-1.2c0-0.2-0.1-0.3-0.2-0.4C27.9,28.2,27.8,28.2,27.6,28.2z'/%3E %3C/svg%3E\""

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cpath d='M34.1,20.1c-0.4-0.5-1-0.7-1.6-0.7h-0.8v-4.6c0-2.9-1.1-5.5-3.2-7.6C26.4,5.1,23.9,4,20.9,4s-5.5,1.2-7.6,3.3 c-2.1,2.1-3.2,4.6-3.2,7.6v4.6H9.3c-0.6,0-1.1,0.2-1.6,0.7c-0.5,0.4-0.7,1-0.7,1.6v13.9c0,0.6,0.2,1.1,0.7,1.6 c0.4,0.5,1,0.7,1.6,0.7h23.2c0.6,0,1.1-0.2,1.6-0.7c0.5-0.4,0.7-1,0.7-1.6V21.8C34.8,21.1,34.6,20.6,34.1,20.1z M12.5,15.1 c0-2.4,0.8-4.4,2.5-6.1s3.6-2.5,6-2.5s4,0.8,5.7,2.5s2.5,3.7,2.5,6.1v4.4H12.5V15.1z M31.8,33.5c0,0.4-0.2,0.8-0.5,1.1 c-0.4,0.3-0.8,0.5-1.2,0.5H12c-0.5,0-0.9-0.1-1.2-0.5c-0.4-0.3-0.5-0.7-0.5-1.1V24c0-0.4,0.2-0.8,0.5-1.1c0.4-0.3,0.8-0.5,1.2-0.5 h0.6l16.8-0.1H30c0.5,0,0.9,0.1,1.2,0.5c0.4,0.3,0.5,0.7,0.5,1.2V33.5z M27.6,28.2H14.2c-0.2,0-0.3,0.1-0.4,0.2 c-0.1,0.1-0.2,0.3-0.2,0.4V30c0,0.2,0.1,0.3,0.2,0.4c0.1,0.1,0.3,0.2,0.4,0.2h13.4c0.2,0,0.3-0.1,0.4-0.2c0.1-0.1,0.2-0.3,0.2-0.4 v-1.2c0-0.2-0.1-0.3-0.2-0.4C27.9,28.2,27.8,28.2,27.6,28.2z'/%3E %3C/svg%3E\""

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cpath stroke='white' fill='white' d='M36.5,21.4v8.2c0,0.2-0.1,0.3-0.2,0.5c-0.1,0.1-0.3,0.2-0.5,0.2H16.4v4.7c0,0.5-0.2,0.9-0.7,1.2c-0.5,0.2-1,0.2-1.4-0.2 l-7.7-6.4c-0.3-0.2-0.4-0.6-0.4-1c0-0.4,0.1-0.7,0.4-1l7.7-6.4c0.4-0.3,0.9-0.4,1.4-0.2c0.5,0.2,0.7,0.6,0.7,1.2v4.5h16v-2.9 c0-0.2,0.1-0.4,0.2-0.5l2.8-2.3c0.2-0.2,0.4-0.2,0.7-0.1C36.4,20.9,36.5,21.1,36.5,21.4z'/%3E %3Cpath stroke='white' fill='white' d='M6.1,20.8v-8.2c0-0.2,0.1-0.3,0.2-0.5C6.5,12,6.6,12,6.8,12h19.4V7.3c0-0.5,0.2-0.9,0.7-1.2c0.5-0.2,1-0.2,1.4,0.2l7.7,6.4 c0.3,0.2,0.4,0.6,0.4,1c0,0.4-0.1,0.7-0.4,1l-7.7,6.4c-0.4,0.3-0.9,0.4-1.4,0.2c-0.5-0.2-0.7-0.6-0.7-1.2v-4.5h-16v2.9 c0,0.2-0.1,0.4-0.2,0.5l-2.8,2.3c-0.2,0.2-0.4,0.2-0.7,0.1C6.3,21.3,6.1,21.1,6.1,20.8z'/%3E %3C/svg%3E\""

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cpath stroke='white' fill='white' d='M30.4,8l-7.7,7.7H10.3v2.9c0,0.2-0.1,0.4-0.2,0.5l-2.8,2.3c-0.2,0.2-0.4,0.2-0.7,0.1c-0.3-0.1-0.4-0.3-0.4-0.6v-8.2 c0-0.2,0.1-0.3,0.2-0.5C6.5,12,6.6,12,6.8,12h19.4V7.3c0-0.5,0.2-0.9,0.7-1.2s1-0.2,1.4,0.2L30.4,8z M26.2,20.2 c0,0.5,0.2,0.9,0.7,1.2c0.5,0.2,1,0.2,1.4-0.2l7.7-6.4c0.3-0.2,0.4-0.6,0.4-1s-0.1-0.7-0.4-1l-1.5-1.2l-8.4,8.4V20.2z M36.2,20.8 c-0.3-0.1-0.5-0.1-0.7,0.1l-2.8,2.3c-0.1,0.1-0.2,0.3-0.2,0.5v2.9H19.6L12.1,34l2.2,1.8c0.4,0.4,0.9,0.4,1.4,0.2 c0.5-0.2,0.7-0.6,0.7-1.2v-4.7h19.4c0.2,0,0.3-0.1,0.5-0.2s0.2-0.3,0.2-0.5v-8.2C36.5,21.1,36.4,20.9,36.2,20.8z M15.7,20.8 c-0.5-0.2-1-0.2-1.4,0.2l-7.7,6.4c-0.3,0.2-0.4,0.6-0.4,1s0.1,0.7,0.4,1l1.3,1.1l8.6-8.6C16.4,21.4,16.2,21.1,15.7,20.8z M31.1,9.4 L9.4,31.1l1.8,1.8l21.7-21.7L31.1,9.4z'/%3E %3C/svg%3E\""

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cpath stroke='white' fill='white' d='M36.6,30.7c0,0.7-0.2,1.2-0.7,1.7c-0.5,0.5-1,0.7-1.7,0.7h-8.5c0,1.3-0.5,2.5-1.4,3.4c-0.9,0.9-2.1,1.4-3.4,1.4 c-1.3,0-2.5-0.5-3.4-1.4c-0.9-0.9-1.4-2.1-1.4-3.4H7.4c-0.7,0-1.2-0.2-1.7-0.7c-0.5-0.5-0.7-1-0.7-1.7c0.6-0.5,1.2-1.1,1.7-1.7 c0.5-0.6,1.1-1.3,1.6-2.3c0.6-0.9,1-1.9,1.4-3s0.7-2.4,0.9-3.9c0.2-1.5,0.4-3.2,0.4-4.9c0-1.9,0.7-3.7,2.2-5.4s3.4-2.7,5.8-3 C19,6.3,19,6.1,19,5.8c0-0.5,0.2-0.9,0.5-1.3C19.8,4.2,20.3,4,20.8,4s0.9,0.2,1.3,0.5s0.5,0.8,0.5,1.3c0,0.3-0.1,0.5-0.2,0.7 c2.4,0.4,4.3,1.4,5.8,3s2.2,3.4,2.2,5.4c0,1.8,0.1,3.4,0.4,4.9c0.2,1.5,0.6,2.8,0.9,3.9c0.4,1.1,0.9,2.1,1.4,3 c0.6,0.9,1.1,1.7,1.6,2.3C35.4,29.6,35.9,30.2,36.6,30.7z'/%3E %3C/svg%3E\""

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3Csvg version='1.1' id='Ebene_1' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xmlns='http://www.w3.org/2000/svg' width='42.5' height='42.5'%3E %3Cstyle type='text/css'%3E .st0%7Bfill:%23FFFFFF;%7D %3C/style%3E %3Cpath class='st0' d='M 9.762 15.885 C 10.101 16.169 11.252 17.126 13.079 18.747 C 14.905 20.272 16.327 21.514 17.273 22.371 C 17.408 22.468 17.611 22.658 17.95 22.945 C 18.289 23.231 18.557 23.515 18.828 23.708 C 19.033 23.898 19.369 24.089 19.642 24.376 C 19.981 24.567 20.25 24.758 20.59 24.948 C 20.86 25.043 21.131 25.139 21.402 25.139 L 21.402 25.139 C 21.671 25.139 21.941 25.043 22.213 24.948 C 22.482 24.851 22.821 24.661 23.16 24.376 C 23.498 24.089 23.768 23.898 23.972 23.708 C 24.174 23.515 24.513 23.231 24.852 22.945 C 25.19 22.658 25.461 22.468 25.528 22.371 C 26.543 21.514 29.047 19.414 33.038 15.885 C 33.85 15.217 34.46 14.358 35.001 13.403 C 35.541 12.449 35.812 11.496 35.812 10.448 C 35.812 9.586 35.541 8.825 35.067 8.157 C 34.526 7.49 33.985 7.203 33.241 7.203 L 9.561 7.203 C 8.746 7.3 8.071 7.679 7.666 8.346 C 7.192 9.015 6.988 9.876 6.988 10.921 C 6.988 11.783 7.26 12.641 7.87 13.594 C 8.477 14.548 9.086 15.312 9.762 15.885 L 9.762 15.885 Z M 9.762 15.885 M 34.121 18.079 C 30.601 21.036 27.962 23.327 26.137 24.948 C 25.528 25.521 25.055 25.899 24.649 26.282 C 24.243 26.569 23.768 26.95 23.16 27.234 C 22.551 27.524 21.941 27.714 21.402 27.714 L 21.402 27.714 C 20.86 27.714 20.25 27.524 19.642 27.234 C 19.033 26.95 18.491 26.569 18.153 26.282 C 17.747 25.996 17.273 25.521 16.664 24.948 C 15.244 23.612 12.535 21.321 8.681 18.079 C 8.071 17.601 7.53 17.028 7.057 16.362 L 7.057 32.102 C 7.057 32.96 7.327 33.727 7.799 34.393 C 8.275 35.06 8.884 35.347 9.628 35.347 L 33.241 35.347 C 33.917 35.347 34.526 35.06 35.067 34.393 C 35.541 33.727 35.812 33.058 35.812 32.102 L 35.812 16.265 C 35.272 16.935 34.73 17.506 34.121 18.079 L 34.121 18.079 Z M 34.121 18.079' style=''/%3E %3C/svg%3E\""

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3Csvg version='1.1' id='Ebene_1' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xmlns='http://www.w3.org/2000/svg' width='42.5' height='42.5'%3E %3Cpath d='M 9.762 15.885 C 10.101 16.169 11.252 17.126 13.079 18.747 C 14.905 20.272 16.327 21.514 17.273 22.371 C 17.408 22.468 17.611 22.658 17.95 22.945 C 18.289 23.231 18.557 23.515 18.828 23.708 C 19.033 23.898 19.369 24.089 19.642 24.376 C 19.981 24.567 20.25 24.758 20.59 24.948 C 20.86 25.043 21.131 25.139 21.402 25.139 L 21.402 25.139 C 21.671 25.139 21.941 25.043 22.213 24.948 C 22.482 24.851 22.821 24.661 23.16 24.376 C 23.498 24.089 23.768 23.898 23.972 23.708 C 24.174 23.515 24.513 23.231 24.852 22.945 C 25.19 22.658 25.461 22.468 25.528 22.371 C 26.543 21.514 29.047 19.414 33.038 15.885 C 33.85 15.217 34.46 14.358 35.001 13.403 C 35.541 12.449 35.812 11.496 35.812 10.448 C 35.812 9.586 35.541 8.825 35.067 8.157 C 34.526 7.49 33.985 7.203 33.241 7.203 L 9.561 7.203 C 8.746 7.3 8.071 7.679 7.666 8.346 C 7.192 9.015 6.988 9.876 6.988 10.921 C 6.988 11.783 7.26 12.641 7.87 13.594 C 8.477 14.548 9.086 15.312 9.762 15.885 L 9.762 15.885 Z M 9.762 15.885 M 34.121 18.079 C 30.601 21.036 27.962 23.327 26.137 24.948 C 25.528 25.521 25.055 25.899 24.649 26.282 C 24.243 26.569 23.768 26.95 23.16 27.234 C 22.551 27.524 21.941 27.714 21.402 27.714 L 21.402 27.714 C 20.86 27.714 20.25 27.524 19.642 27.234 C 19.033 26.95 18.491 26.569 18.153 26.282 C 17.747 25.996 17.273 25.521 16.664 24.948 C 15.244 23.612 12.535 21.321 8.681 18.079 C 8.071 17.601 7.53 17.028 7.057 16.362 L 7.057 32.102 C 7.057 32.96 7.327 33.727 7.799 34.393 C 8.275 35.06 8.884 35.347 9.628 35.347 L 33.241 35.347 C 33.917 35.347 34.526 35.06 35.067 34.393 C 35.541 33.727 35.812 33.058 35.812 32.102 L 35.812 16.265 C 35.272 16.935 34.73 17.506 34.121 18.079 L 34.121 18.079 Z M 34.121 18.079' style=''/%3E %3C/svg%3E\""

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cstyle type='text/css'%3E .st0%7Bfill:%23FFFFFF;%7D %3C/style%3E %3Cpath class='st0' d='M32.1,7H10.2C8.5,7,7,8.5,7,10.2v21.9c0,1.8,1.5,3.2,3.2,3.2h21.9c1.8,0,3.2-1.5,3.2-3.2V10.2 C35.4,8.5,33.9,7,32.1,7z M32.5,31.1c0,0.8-0.6,1.4-1.4,1.4H11.3c-0.8,0-1.4-0.6-1.4-1.4V11.3c0-0.8,0.6-1.4,1.4-1.4h19.8 c0.8,0,1.4,0.6,1.4,1.4V31.1z M30.3,15.3c0.2,0.2,0.4,0.5,0.4,0.9s-0.1,0.6-0.4,0.9L19.2,28.2c-0.2,0.2-0.5,0.4-0.9,0.4 s-0.6-0.1-0.9-0.4l-5.3-5.3c-0.2-0.2-0.4-0.5-0.4-0.9c0-0.3,0.1-0.6,0.4-0.9l0.3-0.3c0.2-0.2,0.5-0.4,0.9-0.4c0.3,0,0.6,0.1,0.9,0.4 l4,4l9.9-9.9c0.2-0.2,0.5-0.4,0.9-0.4c0.3,0,0.6,0.1,0.9,0.4L30.3,15.3z'/%3E %3C/svg%3E\""

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3Csvg version='1.1' id='Ebene_1' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xmlns='http://www.w3.org/2000/svg' width='42.5' height='42.5'%3E %3Cstyle type='text/css'%3E .st0%7Bfill:%23FFFFFF;%7D %3C/style%3E %3Cpath class='st0' d='M 32.1 35.3 L 10.2 35.3 C 8.5 35.3 7 33.8 7 32.1 L 7 10.2 C 7 8.4 8.5 7 10.2 7 L 32.1 7 C 33.9 7 35.3 8.5 35.3 10.2 L 35.3 32.1 C 35.4 33.8 33.9 35.3 32.1 35.3 Z M 9.8 12 L 9.8 31.1 C 9.8 31.9 10.4 32.5 11.2 32.5 L 30.3 32.5 L 9.8 12 Z M 32.5 11.2 C 32.5 10.4 31.9 9.8 31.1 9.8 L 12.1 9.8 L 32.5 30.2 L 32.5 11.2 Z' transform='matrix(-1, 0, 0, -1, 42.304726, 42.299999)'/%3E %3C/svg%3E\""

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3Csvg version='1.1' id='Ebene_1' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xmlns='http://www.w3.org/2000/svg' width='42.5' height='42.5'%3E %3Cstyle type='text/css'%3E .st0%7Bfill:%23FFFFFF;%7D %3C/style%3E %3Cpath class='st0' d='M 32.1 35.3 L 10.2 35.3 C 8.5 35.3 7 33.8 7 32.1 L 7 10.2 C 7 8.4 8.5 7 10.2 7 L 32.1 7 C 33.9 7 35.3 8.5 35.3 10.2 L 35.3 32.1 C 35.4 33.8 33.9 35.3 32.1 35.3 Z M 9.8 12 L 9.8 31.1 C 9.8 31.9 10.4 32.5 11.2 32.5 L 30.3 32.5 L 9.8 12 Z' transform='matrix(-1, 0, 0, -1, 42.304726, 42.299999)'/%3E %3C/svg%3E\""

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3Csvg version='1.1' id='Ebene_1' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xmlns='http://www.w3.org/2000/svg' width='42.5' height='42.5'%3E %3Cpath d='M 32.1 35.3 L 10.2 35.3 C 8.5 35.3 7 33.8 7 32.1 L 7 10.2 C 7 8.4 8.5 7 10.2 7 L 32.1 7 C 33.9 7 35.3 8.5 35.3 10.2 L 35.3 32.1 C 35.4 33.8 33.9 35.3 32.1 35.3 Z M 9.8 12 L 9.8 31.1 C 9.8 31.9 10.4 32.5 11.2 32.5 L 30.3 32.5 L 9.8 12 Z' transform='matrix(-1, 0, 0, -1, 42.304726, 42.299999)'/%3E %3C/svg%3E\""

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cg%3E %3Cg%3E %3Cpath stroke='white' fill='white' d='M34,13.4c-0.2-1.7-1-3.3-2.4-4.4l-0.8-0.6C29.7,7.5,28.3,7,26.8,7c-2,0-3.8,0.9-5,2.4L9.9,24.1c-1.1,1.3-1.6,3-1.4,4.8 c0.2,1.7,1,3.3,2.4,4.4l0.8,0.6c1.1,0.9,2.6,1.4,4.1,1.4c0.2,0,0.5,0,0.7,0c1.7-0.2,3.3-1,4.3-2.3c0,0,0,0,8-9.9 c1.4-1.8,1.2-4.4-0.6-5.8l-0.4-0.3C27,16.3,26.1,16,25.1,16c-1.3,0-2.4,0.6-3.2,1.5l-8,9.9c-0.5,0.6-0.4,1.6,0.2,2.1 c0.3,0.2,0.6,0.3,0.9,0.3c0.5,0,0.9-0.2,1.2-0.6l8-9.9c0.2-0.3,0.5-0.4,0.9-0.4c0.3,0,0.5,0.1,0.7,0.2l0.4,0.3 c0.2,0.2,0.4,0.4,0.4,0.7c0,0.3-0.1,0.6-0.2,0.8l-8,9.9c-0.7,0.8-1.6,1.3-2.7,1.3c-0.8,0-1.6-0.3-2.2-0.8l-0.8-0.6 c-0.7-0.6-1.2-1.4-1.3-2.3c-0.1-0.9,0.2-1.8,0.8-2.5l11.9-14.7c0.7-0.8,1.6-1.3,2.7-1.3c0.8,0,1.6,0.3,2.2,0.8l0.8,0.6 c1.5,1.2,1.7,3.4,0.5,4.9C30,16.6,29.9,17,30,17.4c0,0.4,0.2,0.8,0.6,1c0.3,0.2,0.6,0.3,0.9,0.3c0.5,0,0.9-0.2,1.2-0.6 C33.7,16.8,34.2,15.1,34,13.4L34,13.4z M34,13.4'/%3E %3C/g%3E %3C/g%3E %3C/svg%3E\""

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cpath stroke='white' fill='white' d='M35.7,12.5c-1.5-2.6-3.6-4.7-6.2-6.2C26.9,4.8,24.1,4,21,4c-3.1,0-5.9,0.8-8.5,2.3c-2.6,1.5-4.7,3.6-6.2,6.2 C4.8,15.1,4,17.9,4,21c0,3.1,0.8,5.9,2.3,8.5s3.6,4.7,6.2,6.2c2.6,1.5,5.5,2.3,8.5,2.3c3.1,0,5.9-0.8,8.5-2.3 c2.6-1.5,4.7-3.6,6.2-6.2S38,24.1,38,21C38,17.9,37.2,15.1,35.7,12.5z M22.7,29c0,0.2-0.1,0.3-0.2,0.4s-0.2,0.2-0.4,0.2h-2.9 c-0.2,0-0.3-0.1-0.4-0.2s-0.2-0.2-0.2-0.4v-2.9c0-0.2,0.1-0.3,0.2-0.4s0.2-0.2,0.4-0.2h2.9c0.2,0,0.3,0.1,0.4,0.2s0.2,0.2,0.2,0.4 V29z M27,18.9c-0.2,0.5-0.5,0.9-0.8,1.2c-0.4,0.3-0.7,0.6-0.9,0.8s-0.6,0.4-1.1,0.6c-0.4,0.2-0.7,0.4-0.8,0.5s-0.3,0.3-0.5,0.4 c-0.1,0.2-0.2,0.3-0.2,0.5v0.6c0,0.2-0.1,0.3-0.2,0.4s-0.2,0.2-0.4,0.2h-2.9c-0.2,0-0.3-0.1-0.4-0.2s-0.2-0.2-0.2-0.4v-1.2 c0-0.4,0.1-0.8,0.2-1.2s0.3-0.6,0.4-0.9s0.4-0.4,0.7-0.6s0.6-0.4,0.7-0.5s0.5-0.2,0.8-0.4c0.6-0.3,1.1-0.6,1.3-0.8s0.4-0.5,0.4-0.9 c0-0.5-0.3-0.9-0.8-1.3c-0.5-0.4-1.1-0.5-1.7-0.5c-0.7,0-1.2,0.2-1.7,0.5c-0.3,0.2-0.8,0.7-1.4,1.5c-0.1,0.1-0.3,0.2-0.4,0.2 c-0.1,0-0.2,0-0.3-0.1L14.9,16c-0.1-0.1-0.2-0.2-0.2-0.4s0-0.3,0.1-0.4c1.5-2.3,3.5-3.4,6.3-3.4c1.5,0,3,0.5,4.3,1.6 c1.3,1.1,2,2.4,2,3.8C27.3,17.8,27.2,18.4,27,18.9z'/%3E %3C/svg%3E\""

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cpath d='M35.7,12.5c-1.5-2.6-3.6-4.7-6.2-6.2C26.9,4.8,24.1,4,21,4c-3.1,0-5.9,0.8-8.5,2.3c-2.6,1.5-4.7,3.6-6.2,6.2 C4.8,15.1,4,17.9,4,21c0,3.1,0.8,5.9,2.3,8.5s3.6,4.7,6.2,6.2c2.6,1.5,5.5,2.3,8.5,2.3c3.1,0,5.9-0.8,8.5-2.3 c2.6-1.5,4.7-3.6,6.2-6.2S38,24.1,38,21C38,17.9,37.2,15.1,35.7,12.5z M22.7,29c0,0.2-0.1,0.3-0.2,0.4s-0.2,0.2-0.4,0.2h-2.9 c-0.2,0-0.3-0.1-0.4-0.2s-0.2-0.2-0.2-0.4v-2.9c0-0.2,0.1-0.3,0.2-0.4s0.2-0.2,0.4-0.2h2.9c0.2,0,0.3,0.1,0.4,0.2s0.2,0.2,0.2,0.4 V29z M27,18.9c-0.2,0.5-0.5,0.9-0.8,1.2c-0.4,0.3-0.7,0.6-0.9,0.8s-0.6,0.4-1.1,0.6c-0.4,0.2-0.7,0.4-0.8,0.5s-0.3,0.3-0.5,0.4 c-0.1,0.2-0.2,0.3-0.2,0.5v0.6c0,0.2-0.1,0.3-0.2,0.4s-0.2,0.2-0.4,0.2h-2.9c-0.2,0-0.3-0.1-0.4-0.2s-0.2-0.2-0.2-0.4v-1.2 c0-0.4,0.1-0.8,0.2-1.2s0.3-0.6,0.4-0.9s0.4-0.4,0.7-0.6s0.6-0.4,0.7-0.5s0.5-0.2,0.8-0.4c0.6-0.3,1.1-0.6,1.3-0.8s0.4-0.5,0.4-0.9 c0-0.5-0.3-0.9-0.8-1.3c-0.5-0.4-1.1-0.5-1.7-0.5c-0.7,0-1.2,0.2-1.7,0.5c-0.3,0.2-0.8,0.7-1.4,1.5c-0.1,0.1-0.3,0.2-0.4,0.2 c-0.1,0-0.2,0-0.3-0.1L14.9,16c-0.1-0.1-0.2-0.2-0.2-0.4s0-0.3,0.1-0.4c1.5-2.3,3.5-3.4,6.3-3.4c1.5,0,3,0.5,4.3,1.6 c1.3,1.1,2,2.4,2,3.8C27.3,17.8,27.2,18.4,27,18.9z'/%3E %3C/svg%3E\""

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cstyle type='text/css'%3E .st0%7Bfill:%2316A086;%7D %3C/style%3E %3Ccircle id='_x31_6a086' class='st0' cx='21.2' cy='21.2' r='14.2'/%3E %3C/svg%3E\""

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cstyle type='text/css'%3E .st0%7Bfill:%23FDD835;%7D %3C/style%3E %3Ccircle id='_x31_6a086_1_' class='st0' cx='21.2' cy='21.2' r='14.2'/%3E %3C/svg%3E\""

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cstyle type='text/css'%3E .st0%7Bfill:%23E4003A;%7D %3C/style%3E %3Ccircle id='e4003a' class='st0' cx='21.2' cy='21.2' r='14.2'/%3E %3C/svg%3E\""

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cstyle type='text/css'%3E .st0%7Bfill:%231D1D1B;%7D %3C/style%3E %3Cpath class='st0' d='M35.9,9.6c-0.5-0.5-1.1-0.7-1.7-0.7h-2.4V7c0-0.8-0.3-1.6-0.9-2.1C30.2,4.3,29.5,4,28.7,4h-1.2 c-0.8,0-1.6,0.3-2.1,0.9S24.4,6.2,24.4,7v1.8h-7.3V7c0-0.8-0.3-1.6-0.9-2.1C15.7,4.3,14.9,4,14.1,4h-1.2c-0.8,0-1.6,0.3-2.1,0.9 C10.2,5.5,9.9,6.2,9.9,7v1.8H7.4c-0.7,0-1.2,0.2-1.7,0.7S5,10.6,5,11.3v24.3c0,0.7,0.2,1.2,0.7,1.7C6.2,37.8,6.8,38,7.4,38h26.7 c0.7,0,1.2-0.2,1.7-0.7c0.5-0.5,0.7-1.1,0.7-1.7V11.3C36.6,10.6,36.3,10.1,35.9,9.6z M26.9,7c0-0.2,0.1-0.3,0.2-0.4s0.3-0.2,0.4-0.2 h1.2c0.2,0,0.3,0.1,0.4,0.2s0.2,0.3,0.2,0.4v5.5c0,0.2-0.1,0.3-0.2,0.4s-0.3,0.2-0.4,0.2h-1.2c-0.2,0-0.3-0.1-0.4-0.2 s-0.2-0.3-0.2-0.4V7z M12.3,7c0-0.2,0.1-0.3,0.2-0.4s0.3-0.2,0.4-0.2h1.2c0.2,0,0.3,0.1,0.4,0.2s0.2,0.3,0.2,0.4v5.5 c0,0.2-0.1,0.3-0.2,0.4s-0.3,0.2-0.4,0.2h-1.2c-0.2,0-0.3-0.1-0.4-0.2s-0.2-0.3-0.2-0.4V7z M34.2,35.6H7.4V16.1h26.7V35.6z M14.9,26.9c-0.1-0.1-0.2-0.3-0.2-0.4v-1.2c0-0.2,0.1-0.3,0.2-0.4s0.3-0.2,0.4-0.2h4.3v-4.3c0-0.2,0.1-0.3,0.2-0.4s0.3-0.2,0.4-0.2 h1.2c0.2,0,0.3,0.1,0.4,0.2s0.2,0.3,0.2,0.4v4.3h4.3c0.2,0,0.3,0.1,0.4,0.2s0.2,0.3,0.2,0.4v1.2c0,0.2-0.1,0.3-0.2,0.4 s-0.3,0.2-0.4,0.2H22v4.3c0,0.2-0.1,0.3-0.2,0.4s-0.3,0.2-0.4,0.2h-1.2c-0.2,0-0.3-0.1-0.4-0.2s-0.2-0.3-0.2-0.4v-4.3h-4.3 C15.1,27.1,15,27,14.9,26.9z'/%3E %3C/svg%3E\""

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cstyle type='text/css'%3E .st0%7Bfill:%231D1D1B;%7D %3C/style%3E %3Cpath class='st0' d='M33.9,9.6c-0.5-0.5-1.1-0.7-1.7-0.7h-2.4V7c0-0.8-0.3-1.6-0.9-2.1C28.2,4.3,27.5,4,26.7,4h-1.2 c-0.8,0-1.6,0.3-2.1,0.9S22.4,6.2,22.4,7v1.8h-7.3V7c0-0.8-0.3-1.6-0.9-2.1C13.7,4.3,12.9,4,12.1,4h-1.2c-0.8,0-1.6,0.3-2.1,0.9 C8.2,5.5,7.9,6.2,7.9,7v1.8H5.4c-0.7,0-1.2,0.2-1.7,0.7S3,10.6,3,11.3v24.3c0,0.7,0.2,1.2,0.7,1.7C4.2,37.8,4.8,38,5.4,38h26.7 c0.7,0,1.2-0.2,1.7-0.7c0.5-0.5,0.7-1.1,0.7-1.7H5.4V16.1h29.2v-4.9C34.6,10.6,34.3,10.1,33.9,9.6z M12.7,12.5 c0,0.2-0.1,0.3-0.2,0.4s-0.3,0.2-0.4,0.2h-1.2c-0.2,0-0.3-0.1-0.4-0.2s-0.2-0.3-0.2-0.4V7c0-0.2,0.1-0.3,0.2-0.4s0.3-0.2,0.4-0.2 h1.2c0.2,0,0.3,0.1,0.4,0.2s0.2,0.3,0.2,0.4V12.5z M27.3,12.5c0,0.2-0.1,0.3-0.2,0.4s-0.3,0.2-0.4,0.2h-1.2c-0.2,0-0.3-0.1-0.4-0.2 s-0.2-0.3-0.2-0.4V7c0-0.2,0.1-0.3,0.2-0.4s0.3-0.2,0.4-0.2h1.2c0.2,0,0.3,0.1,0.4,0.2s0.2,0.3,0.2,0.4V12.5z M23.7,32.5l2.1-1.6 l-2.1-2.7l-2.1,1.6l-0.1,0.9l1.5,0.2l-0.2,1.5L23.7,32.5z M32.2,21.8c-0.2-0.2-0.3-0.2-0.5,0l-6.3,4.9c-0.2,0.2-0.2,0.3-0.1,0.5 c0.2,0.2,0.3,0.2,0.5,0l6.3-4.9C32.3,22.2,32.3,22,32.2,21.8z M32.2,19.5l4.1,5.2l-12.1,9.5l-4.6-0.6l0.6-4.6L32.2,19.5z M39.1,22.5 l-1.7,1.3l-4.1-5.2l1.7-1.3c0.3-0.3,0.7-0.4,1.1-0.3c0.4,0.1,0.8,0.2,1,0.6l2.1,2.7c0.3,0.3,0.4,0.7,0.3,1.1S39.4,22.2,39.1,22.5z'/%3E %3C/svg%3E\""

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cpath d='M28.2,32.1L27,33.3c-0.2,0.2-0.4,0.2-0.6,0.2s-0.4-0.1-0.6-0.2l-5-5l-5,5c-0.2,0.2-0.4,0.2-0.6,0.2c-0.2,0-0.4-0.1-0.6-0.2 l-1.2-1.2c-0.2-0.2-0.2-0.4-0.2-0.6c0-0.2,0.1-0.4,0.2-0.6l5-5l-5-5c-0.2-0.2-0.2-0.4-0.2-0.6s0.1-0.4,0.2-0.6l1.2-1.2 c0.2-0.2,0.4-0.2,0.6-0.2c0.2,0,0.4,0.1,0.6,0.2l5,5l5-5c0.2-0.2,0.4-0.2,0.6-0.2s0.4,0.1,0.6,0.2l1.2,1.2c0.2,0.2,0.2,0.4,0.2,0.6 s-0.1,0.4-0.2,0.6l-5,5l5,5c0.2,0.2,0.2,0.4,0.2,0.6C28.5,31.7,28.4,31.9,28.2,32.1z M7.4,35.6h26.7V16.1H7.4V35.6z M14.7,12.5V7 c0-0.2-0.1-0.3-0.2-0.4c-0.1-0.1-0.3-0.2-0.4-0.2h-1.2c-0.2,0-0.3,0.1-0.4,0.2c-0.1,0.1-0.2,0.3-0.2,0.4v5.5c0,0.2,0.1,0.3,0.2,0.4 c0.1,0.1,0.3,0.2,0.4,0.2h1.2c0.2,0,0.3-0.1,0.4-0.2C14.7,12.8,14.7,12.7,14.7,12.5z M29.3,12.5V7c0-0.2-0.1-0.3-0.2-0.4 s-0.3-0.2-0.4-0.2h-1.2c-0.2,0-0.3,0.1-0.4,0.2S26.9,6.9,26.9,7v5.5c0,0.2,0.1,0.3,0.2,0.4c0.1,0.1,0.3,0.2,0.4,0.2h1.2 c0.2,0,0.3-0.1,0.4-0.2C29.2,12.8,29.3,12.7,29.3,12.5z M36.6,11.3v24.3c0,0.7-0.2,1.2-0.7,1.7c-0.5,0.5-1.1,0.7-1.7,0.7H7.4 c-0.7,0-1.2-0.2-1.7-0.7C5.2,36.8,5,36.2,5,35.6V11.3c0-0.7,0.2-1.2,0.7-1.7s1.1-0.7,1.7-0.7h2.4V7c0-0.8,0.3-1.6,0.9-2.1 S12.1,4,12.9,4h1.2c0.8,0,1.6,0.3,2.1,0.9c0.6,0.6,0.9,1.3,0.9,2.1v1.8h7.3V7c0-0.8,0.3-1.6,0.9-2.1C25.9,4.3,26.6,4,27.5,4h1.2 c0.8,0,1.6,0.3,2.1,0.9s0.9,1.3,0.9,2.1v1.8h2.4c0.7,0,1.2,0.2,1.7,0.7C36.3,10.1,36.6,10.6,36.6,11.3z'/%3E %3C/svg%3E\""

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cpath d='M31.9,9.6c-0.5-0.5-1.1-0.7-1.7-0.7h-2.4V7c0-0.8-0.3-1.6-0.9-2.1C26.2,4.3,25.5,4,24.7,4h-1.2c-0.8,0-1.6,0.3-2.1,0.9 S20.4,6.2,20.4,7v1.8h-7.3V7c0-0.8-0.3-1.6-0.9-2.1C11.7,4.3,10.9,4,10.1,4H8.9C8.1,4,7.3,4.3,6.8,4.9C6.2,5.5,5.9,6.2,5.9,7v1.8 H3.4c-0.7,0-1.2,0.2-1.7,0.7S1,10.6,1,11.3v24.3c0,0.7,0.2,1.2,0.7,1.7C2.2,37.8,2.8,38,3.4,38h26.7c0.7,0,1.2-0.2,1.7-0.7 c0.5-0.5,0.7-1.1,0.7-1.7H3.4V16.1h29.2v-4.9C32.6,10.6,32.3,10.1,31.9,9.6z M10.7,12.5c0,0.2-0.1,0.3-0.2,0.4s-0.3,0.2-0.4,0.2H8.9 c-0.2,0-0.3-0.1-0.4-0.2s-0.2-0.3-0.2-0.4V7c0-0.2,0.1-0.3,0.2-0.4s0.3-0.2,0.4-0.2h1.2c0.2,0,0.3,0.1,0.4,0.2s0.2,0.3,0.2,0.4V12.5 z M25.3,12.5c0,0.2-0.1,0.3-0.2,0.4s-0.3,0.2-0.4,0.2h-1.2c-0.2,0-0.3-0.1-0.4-0.2s-0.2-0.3-0.2-0.4V7c0-0.2,0.1-0.3,0.2-0.4 s0.3-0.2,0.4-0.2h1.2c0.2,0,0.3,0.1,0.4,0.2s0.2,0.3,0.2,0.4V12.5z M41.6,25.7c0,0.3-0.1,0.5-0.3,0.7l-5.2,5.2 c-0.2,0.2-0.4,0.3-0.7,0.3c-0.3,0-0.5-0.1-0.7-0.3L34.1,31c-0.2-0.2-0.3-0.4-0.3-0.7s0.1-0.5,0.3-0.7l2.3-2.3H21.3 c-0.3,0-0.5-0.1-0.7-0.3s-0.3-0.4-0.3-0.7v-1c0-0.3,0.1-0.5,0.3-0.7s0.4-0.3,0.7-0.3h15.2l-2.3-2.3c-0.2-0.2-0.3-0.4-0.3-0.7 c0-0.3,0.1-0.5,0.3-0.7l0.6-0.6c0.2-0.2,0.4-0.3,0.7-0.3c0.3,0,0.5,0.1,0.7,0.3l5.2,5.2C41.5,25.1,41.6,25.4,41.6,25.7z'/%3E %3C/svg%3E\""

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cpath d='M10,11.3v4.9h29.2v19.4H10c0,0.7,0.2,1.2,0.7,1.7c0.5,0.5,1.1,0.7,1.7,0.7h26.7c0.7,0,1.2-0.2,1.7-0.7 c0.5-0.5,0.7-1.1,0.7-1.7V11.3c0-0.7-0.2-1.2-0.7-1.7s-1.1-0.7-1.7-0.7h-2.4V7c0-0.8-0.3-1.6-0.9-2.1C35.3,4.3,34.6,4,33.7,4h-1.2 c-0.8,0-1.6,0.3-2.1,0.9c-0.6,0.6-0.9,1.3-0.9,2.1v1.8h-7.3V7c0-0.8-0.3-1.6-0.9-2.1S20,4,19.1,4h-1.2c-0.8,0-1.6,0.3-2.1,0.9 c-0.6,0.6-0.9,1.3-0.9,2.1v1.8h-2.4c-0.7,0-1.2,0.2-1.7,0.7S10,10.6,10,11.3z M31.9,7c0-0.2,0.1-0.3,0.2-0.4s0.3-0.2,0.4-0.2h1.2 c0.2,0,0.3,0.1,0.4,0.2s0.2,0.3,0.2,0.4v5.5c0,0.2-0.1,0.3-0.2,0.4s-0.3,0.2-0.4,0.2h-1.2c-0.2,0-0.3-0.1-0.4-0.2s-0.2-0.3-0.2-0.4 V7z M17.3,7c0-0.2,0.1-0.3,0.2-0.4s0.3-0.2,0.4-0.2h1.2c0.2,0,0.3,0.1,0.4,0.2s0.2,0.3,0.2,0.4v5.5c0,0.2-0.1,0.3-0.2,0.4 s-0.3,0.2-0.4,0.2h-1.2c-0.2,0-0.3-0.1-0.4-0.2s-0.2-0.3-0.2-0.4V7z M22.3,25.7c0,0.3-0.1,0.5-0.3,0.7l-5.2,5.2 c-0.2,0.2-0.4,0.3-0.7,0.3c-0.3,0-0.5-0.1-0.7-0.3L14.8,31c-0.2-0.2-0.3-0.4-0.3-0.7s0.1-0.5,0.3-0.7l2.3-2.3H1.9 c-0.3,0-0.5-0.1-0.7-0.3S1,26.4,1,26.2v-1c0-0.3,0.1-0.5,0.3-0.7s0.4-0.3,0.7-0.3h15.2l-2.3-2.3c-0.2-0.2-0.3-0.4-0.3-0.7 c0-0.3,0.1-0.5,0.3-0.7l0.6-0.6c0.2-0.2,0.4-0.3,0.7-0.3c0.3,0,0.5,0.1,0.7,0.3l5.2,5.2C22.2,25.1,22.3,25.4,22.3,25.7z'/%3E %3C/svg%3E\""

/***/ }),

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

/*
 * Tine 2.0
 *
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2009-2017 Metaways Infosystems GmbH (http://www.metaways.de)
 */
Ext.namespace('Tine.Calendar');
/**
 * @namespace   Tine.Calendar
 * @class       Tine.Calendar.Application
 * @extends     Tine.Tinebase.Application
 * Calendar Application Object <br>
 *
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 */

Tine.Calendar.Application = Ext.extend(Tine.Tinebase.Application, {
  /**
   * auto hook text i18n._('New Event')
   */
  addButtonText: 'New Event',

  /**
   * Get translated application title of the calendar application
   *
   * @return {String}
   */
  getTitle: function getTitle() {
    return this.i18n.ngettext('Calendar', 'Calendars', 1);
  },

  /**
   * returns iconCls of this application
   *
   * @param {String} target
   * @return {String}
   */
  getIconCls: function getIconCls(target) {
    switch (target) {
      case 'PreferencesTreePanel':
        return 'PreferencesTreePanel-CalendarIconCls';
        break;

      default:
        return 'CalendarIconCls';
        break;
    }
  },
  init: function init() {
    this.updateIcon();
    Tine.Calendar.Application.superclass.init.apply(this.arguments);
    new Tine.Calendar.AddressbookGridPanelHook({
      app: this
    });

    if (Tine.Felamimail && Tine.Felamimail.MimeDisplayManager) {
      Tine.Felamimail.MimeDisplayManager.register('text/calendar', Tine.Calendar.iMIPDetailsPanel);
    }

    this.postalSubscriptions = [];
    this.postalSubscriptions.push(postal.subscribe({
      channel: "thirdparty",
      topic: "data.changed",
      callback: function callback(data, envelope) {
        Tine.Tinebase.appMgr.get('Calendar').getMainScreen().getCenterPanel().autoRefreshTask.delay(0);
      }
    }));
  },
  registerCoreData: function registerCoreData() {
    Tine.CoreData.Manager.registerGrid('cal_resources', Tine.Calendar.ResourceGridPanel, {
      ownActionToolbar: false
    });
  },
  updateIcon: function updateIcon() {
    var imageUrl = Tine.Tinebase.common.getUrl('full') + '/images/icon-set/icon_cal_' + new Date().getDate() + '.svg';
    Ext.util.CSS.updateRule('.CalendarIconCls', 'background-image', 'url(' + imageUrl + ')');
  },
  routes: {
    'showEvent/(.*)': 'showEvent',
    'pollFBView/(.*)/(.*)/(.*)': 'pollFBView' // hack: as we have no local storage window manager yet

  },

  /**
   *
   * @param attendee
   * @param date
   *
   * example
   * http://tine20.example.com:10443/#/Calendar/pollFBView/user/89192f9d3ce44ed3681a1b73d5ca491e766c4d62/2017-12-08
   */
  pollFBView: function pollFBView(user_type, user_id, date) {
    var cp = this.getMainScreen().getCenterPanel(),
        activePanel = cp.getCalendarPanel(cp.activeView),
        activeView = activePanel.getView(),
        store = activeView.store;
    cp.initialLoadAfterRender = false;
    Tine.Tinebase.MainScreenPanel.show(this); // mhh - if the user already declined we can't see the event

    activeView.updatePeriod({
      from: new Date(date)
    });
    cp.filterToolbar.setValue([{
      field: 'attender',
      operator: 'in',
      value: [{
        user_type: user_type,
        user_id: user_id
      }]
    }, {
      field: 'attender_status',
      operator: 'notin',
      value: ['DECLINED']
    }]);
    cp.refresh();
    cp.toggleFullScreen.handler.apply(cp);
    cp.toggleFullScreen.hide();
  },

  /**
   * display event in mainscreen
   * @param {String} id
   *
   * example:
   * http://tine20.example.com:10443/#/Calendar/showEvent/89192f9d3ce44ed3681a1b73d5ca491e766c4d62
   */
  showEvent: function showEvent(id) {
    var cp = this.getMainScreen().getCenterPanel(),
        activePanel = cp.getCalendarPanel(cp.activeView),
        activeView = activePanel.getView(),
        store = activeView.store;
    cp.initialLoadAfterRender = false;
    Tine.Tinebase.MainScreenPanel.show(this);

    if (cp.loadMask) {
      cp.loadMask.show();
    }

    Tine.Calendar.backend.loadRecord(id, {
      success: function success(record) {
        // @TODO timeline view
        store.on('load', function () {
          // NOTE: the store somehow changes, so refetch it
          var activePanel = cp.getCalendarPanel(cp.activeView),
              activeView = activePanel.getView(),
              sm = activeView.getSelectionModel(),
              store = activeView.store,
              event = store.getById(record.get('id'));

          if (!event) {
            store.add([record]);
            event = record;
          }

          sm.selectRecords.defer(250, sm, [[event]]);
        }, this, {
          single: true
        });
        activeView.updatePeriod({
          from: record.get('dtstart')
        });
        cp.selectFavorite();
      },
      failure: function failure() {
        cp.selectFavorite();
        Ext.Msg.alert(this.i18n._('Event not found'), this.i18n._("The Event was deleted in the meantime or you don't have access rights to it."));
      }
    });
  }
});

/***/ }),

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

/*
 * Tine 2.0
 *
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2009-2017 Metaways Infosystems GmbH (http://www.metaways.de)
 */
Ext.namespace('Tine.Calendar');
/**
 * @namespace Tine.Calendar
 * @class Tine.Calendar.MainScreen
 * @extends Tine.widgets.MainScreen
 * MainScreen of the Calendar Application <br>
 *
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2009 Metaways Infosystems GmbH (http://www.metaways.de)
 * @constructor
 * Constructs mainscreen of the calendar application
 */

Tine.Calendar.MainScreen = function (config) {
  Ext.apply(this, config);
  var prefs = this.app.getRegistry().get('preferences');
  Ext.DatePicker.prototype.startDay = parseInt(prefs ? prefs.get('firstdayofweek') : 1, 10);
  Tine.Calendar.MainScreen.superclass.constructor.apply(this, arguments);
};

Ext.extend(Tine.Calendar.MainScreen, Tine.widgets.MainScreen, {
  /**
   * Get content panel of calendar application
   *
   * @return {Tine.Calendar.MainScreenCenterPanel}
   */
  getCenterPanel: function getCenterPanel() {
    if (!this.contentPanel) {
      this.contentPanel = new Tine.Calendar.MainScreenCenterPanel({
        detailsPanel: new Tine.Calendar.EventDetailsPanel({
          recordClass: Tine.Calendar.Model.Event
        })
      });
    }

    return this.contentPanel;
  },

  /**
   * get north panel for given contentType
   *
   * @param {String} contentType
   * @return {Ext.Panel}
   */
  getNorthPanel: function getNorthPanel(contentType) {
    if (!this.actionToolbar) {
      this.actionToolbar = this.contentPanel.getActionToolbar();

      if (this.actionToolbar.cls) {
        this.actionToolbar.cls = this.actionToolbar.cls + ' t-contenttype-event';
      } else {
        this.actionToolbar.cls = 't-contenttype-event';
      }
    }

    return this.actionToolbar;
  }
});

/***/ }),

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

Ext.ns('Tine.Calendar.Printer');
/**
 * @class   Tine.Calendar.Printer.BaseRenderer
 * @extends Ext.ux.Printer.BaseRenderer
 * 
 * Printig renderer for Ext.ux.printing
 */

Tine.Calendar.Printer.BaseRenderer = Ext.extend(Ext.ux.Printer.BaseRenderer, {
  stylesheetPath: 'Calendar/css/print.css',
  extraTitle: '',
  titleStyle: '',
  //    generateBody: function(view) {
  //        var days = [];
  //        
  //        // iterate days
  //        for (var dayStart, dayEnd, dayEvents, i=0; i<view.numOfDays; i++) {
  //            dayStart = view.startDate.add(Date.DAY, i);
  //            dayEnd   = dayStart.add(Date.DAY, 1).add(Date.SECOND, -1);
  //            
  //            // get events in this day
  //            dayEvents = view.store.queryBy(function(event){
  //                return event.data.dtstart.getTime() < dayEnd.getTime() && event.data.dtend.getTime() > dayStart.getTime();
  //            });
  //            
  //            days.push(this.generateDay(dayStart, dayEnd, dayEvents));
  //        }
  //        
  //        var topic = this.generateHeader(view);
  //        var body  = 
  //        return view.numOfDays === 1 ? days[0] : String.format('<table>{0}</table>', this.generateCalRows(days, view.numOfDays < 9 ? 2 : 7));
  //    },
  generateTitle: function generateTitle(view) {
    return ['<table style="', this.titleStyle, '"><tr><th class="cal-print-title">', this.extraTitle, this.getTitle(view), '</th></tr></table>'].join('');
  },
  generateCalRows: function generateCalRows(days, numCols, alignHorizontal, hasRowHeader) {
    var row,
        col,
        cellsHtml,
        idx,
        numRows = Math.ceil(days.length / numCols),
        rowsHtml = '';

    for (row = 0; row < numRows; row++) {
      cellsHtml = ''; //offset = row*numCols;

      for (col = 0; col < numCols; col++) {
        idx = alignHorizontal ? row * numCols + col : col * numRows + row;
        rowheader = hasRowHeader && col == 0 ? 'cal-print-rowheader' : '';
        cellsHtml += String.format('<td class="cal-print-daycell ' + rowheader + '" style="vertical-align: top;">{0}</td>', days[idx] || '');
      }

      rowsHtml += String.format('<tr class="cal-print-dayrow" style="height: {1}mm">{0}</tr>', cellsHtml, this.paperHeight / numRows);
    }

    return rowsHtml;
  },
  generateDay: function generateDay(dayStart, dayEnd, dayEvents) {
    var dayBody = '';
    dayEvents.each(function (event) {
      var start = event.data.dtstart.getTime() <= dayStart.getTime() ? dayStart : event.data.dtstart,
          end = event.data.dtend.getTime() > dayEnd.getTime() ? dayEnd : event.data.dtend;
      dayBody += this.eventTpl.apply({
        color: event.colorSet.color,
        startTime: event.data.is_all_day_event ? '' : start.format('H:i'),
        untilseperator: event.data.is_all_day_event ? '' : '-',
        endTime: event.data.is_all_day_event ? '' : end.format('H:i'),
        summary: Ext.util.Format.htmlEncode(event.data.summary),
        duration: event.data.is_all_day_event ? Tine.Tinebase.appMgr.get('Calendar').i18n._('whole day') : Tine.Tinebase.common.minutesRenderer(Math.round((end.getTime() - start.getTime()) / (1000 * 60)), '{0}:{1}', 'i')
      });
    }, this);
    var dayHeader = this.dayTpl.apply({
      dayOfMonth: dayStart.format('j'),
      weekDay: dayStart.format('l')
    });
    return String.format('<table class="cal-print-daysview-day"><thead><tr>{0}</tr></thead><tbody>{1}</tbody></table>', dayHeader, dayBody);
  },
  splitDays: function splitDays(ds, startDate, numOfDays, returnData) {
    var days = []; // iterate days

    for (var dayStart, dayEnd, dayEvents, i = 0; i < numOfDays; i++) {
      dayStart = startDate.add(Date.DAY, i);
      dayEnd = dayStart.add(Date.DAY, 1).add(Date.SECOND, -1); // get events in this day

      dayEvents = ds.queryBy(function (event) {
        return event.data.dtstart.getTime() < dayEnd.getTime() && event.data.dtend.getTime() > dayStart.getTime();
      });
      days.push(returnData ? {
        dayStart: dayStart,
        dayEnd: dayEnd,
        dayEvents: dayEvents
      } : this.generateDay(dayStart, dayEnd, dayEvents));
    }

    return days;
  },
  dayTpl: new Ext.XTemplate('<tr>', '<th  colspan="5">', '<span class="cal-print-daysview-day-dayOfMonth">{dayOfMonth}</span>', '<span class="cal-print-daysview-day-weekDay">{weekDay}</span>', '</th>', '</tr>'),

  /**
   * @property eventTpl
   * @type Ext.XTemplate
   * The XTemplate used to create the headings row. By default this just uses <th> elements, override to provide your own
   */
  eventTpl: new Ext.XTemplate('<tr>', '<td class="cal-print-daysview-day-color"><span style="color: {color};">&#9673;</span></td>', '<td class="cal-print-daysview-day-starttime">{startTime}</td>', '<td class="cal-print-daysview-day-untilseperator">{untilseperator}</td>', '<td class="cal-print-daysview-day-endtime">{endTime}</td>', '<td class="cal-print-daysview-day-summary">{summary} (<span class="cal-print-daysview-day-duration">{duration}</span>)</td>', '</tr>')
});

/***/ }),

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

/*
 * Tine 2.0
 * 
 * @package     Calendar
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2009-2011 Metaways Infosystems GmbH (http://www.metaways.de)
 *
 */
Ext.ns('Tine.Calendar');
/**
 * @namespace   Tine.Calendar
 * @class       Tine.Calendar.AddressbookGridPanelHook
 * 
 * <p>Calendar Addressbook Hook</p>
 * <p>
 * </p>
 * 
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * 
 * @constructor
 */

Tine.Calendar.AddressbookGridPanelHook = Ext.extend(Tine.Addressbook.GenericContactGridPanelHook, {
  modelName: 'Event'
});

/***/ }),

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

/* 
 * Tine 2.0
 * 
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2007-2008 Metaways Infosystems GmbH (http://www.metaways.de)
 */
Ext.ns('Tine.Calendar');
/**
 * registry to cope with parallel events
 * 
 * @class Tine.Events.ParallelEventsRegistry
 * @constructor
 */

Tine.Calendar.ParallelEventsRegistry = function (config) {
  Ext.apply(this, config);
  this.dtStartTs = this.dtStart.getTime();
  this.dtEndTs = this.dtEnd.getTime();
  this.dt = this.granularity * Date.msMINUTE; // init map

  this.frameLength = Math.ceil((this.dtEndTs - this.dtStartTs) / this.dt);
  this.map = [];
};

Tine.Calendar.ParallelEventsRegistry.prototype = {
  /**
   * @cfg {Date} dtStart
   * start of range for this registry
   */
  dtStart: null,

  /**
   * @cfg {Date} dtEnd
   * end of range for this registry 
   */
  dtEnd: null,

  /**
   * @cfg {Number} granularity
   * granularity of this registry in minutes
   */
  granularity: 5,

  /**
   * @cfg {String} dtStartProperty
   */
  dtStartProperty: 'dtstart',

  /**
   * @cfg {String} dtEndProperty
   */
  dtEndProperty: 'dtend',

  /**
   * @private {Array} map
   * 
   * array of frames. a frames
   */
  map: null,

  /**
   * @private {Number} dtStartTs
   */
  dtStartTs: null,

  /**
   * @private {Number} dtEndTs
   */
  dtEndTs: null,

  /**
   * @private {Number} dt
   */
  dt: null,

  /**
   * register event
   * @param {Ext.data.Record} event
   * @param {bool} returnAffected
   * @return mixed
   */
  register: function register(event, returnAffected) {
    var dtStart = event.get(this.dtStartProperty);
    var dtStartTs = dtStart.getTime();
    var dtEnd = event.get(this.dtEndProperty);
    var dtEndTs = dtEnd.getTime() - 1000; // layout helper

    event.duration = dtEndTs - dtStartTs;
    var startIdx = this.tsToIdx(dtStart);
    var endIdx = this.tsToIdx(dtEndTs);
    var position = 0;
    var frame = this.getFrame(position);

    while (!this.isEmptySlice(frame, startIdx, endIdx)) frame = this.getFrame(++position);

    this.registerSlice(frame, startIdx, endIdx, event);
    event.parallelEventRegistry = {
      registry: this,
      position: position,
      startIdx: startIdx,
      endIdx: endIdx
    }; //console.info('pushed event in frame# ' + position + ' from startIdx"' + startIdx + '" to endIdx "' + endIdx + '".');

    if (returnAffected) {
      return this.getEvents(dtStart, dtEnd);
    }
  },

  /**
   * unregister event
   * 
   * @param {Ext.data.Record} event
   */
  unregister: function unregister(event) {
    var ri = event.parallelEventRegistry;
    var frame = this.getFrame(ri.position);

    if (!this.skipIntegrityChecks) {
      for (var idx = ri.startIdx; idx <= ri.endIdx; idx++) {
        if (frame[idx] !== event) {
          throw new Ext.Error('event is not registered at expected position');
        }
      }
    }

    this.unregisterSlice(frame, ri.startIdx, ri.endIdx);
    event.parallelEventRegistry = null;
  },

  /**
   * returns events of current range sorted by duration
   * 
   * @param  {Date} dtStart
   * @param  {Date} dtEnd
   * @return {Array}
   */
  getEvents: function getEvents(dtStart, dtEnd, sortByDtStart) {
    var dtStartTs = dtStart.getTime();
    var dtEndTs = dtEnd.getTime() - 1000;
    var startIdx = this.tsToIdx(dtStart);
    var endIdx = this.tsToIdx(dtEndTs);
    var events = this.getSliceInfo(startIdx, endIdx).events; // sort by duration and dtstart

    var scope = this;
    events.sort(function (a, b) {
      var d = b.duration - a.duration;
      var s = a.get(scope.dtStartProperty).getTime() - b.get(scope.dtStartProperty).getTime();
      return sortByDtStart ? s ? s : d : d ? d : s;
    });
    return events;
  },

  /**
   * get number of maximal parallel events in given time span
   * 
   * @param {Date} dtStart
   * @param {Date} dtEnd
   * @return {Number}
   */
  getMaxParalles: function getMaxParalles(dtStart, dtEnd) {
    var dtStartTs = dtStart.getTime();
    var dtEndTs = dtEnd.getTime() - 1000;
    var startIdx = this.tsToIdx(dtStart);
    var endIdx = this.tsToIdx(dtEndTs);
    return this.getSliceInfo(startIdx, endIdx).maxParallels;
  },

  /**
   * get position of given event
   * 
   * @param {Ext.data.Record} event
   * @return {Number}
   */
  getPosition: function getPosition(event) {
    if (!event.parallelEventRegistry) {
      throw new Ext.Error("can't compute position of a non registered event");
    }

    return event.parallelEventRegistry.position;
  },

  /**
   * @private
   * 
   * @param {Number} startIdx
   * @param {Number} endIdx
   * @return {Object}
   */
  getSliceInfo: function getSliceInfo(startIdx, endIdx) {
    var events = [];
    var maxParallels = 1;

    for (var idx, frame, position = 0; position < this.map.length; position++) {
      frame = this.map[position];

      for (idx = startIdx; idx <= endIdx; idx++) {
        if (frame[idx] && events.indexOf(frame[idx]) === -1) {
          maxParallels = Math.max(maxParallels, position + 1);
          events.push(frame[idx]);
        }
      }
    }

    return {
      events: events,
      maxParallels: maxParallels
    };
  },

  /*************************************** frame functions **********************************/

  /**
   * returns frame of given position. 
   * If no frame is found on given position it will be created implicitlty
   * 
   * @private
   * @param {Number} position
   * @return {Array}
   */
  getFrame: function getFrame(position) {
    if (position > this.map.length + 1) {
      throw new Ext.Error('skipping frames is not allowed');
    }

    if (!Ext.isArray(this.map[position])) {
      this.map[position] = new Array(this.frameLength);
    }

    return this.map[position];
  },

  /**
   * checks if a slice in a given frame is free
   * 
   * @private
   * @param {Array} frame
   * @param {Number} startIdx
   * @param {Number} endIdx
   */
  isEmptySlice: function isEmptySlice(frame, startIdx, endIdx) {
    for (var idx = startIdx; idx <= endIdx; idx++) {
      if (frame[idx]) {
        return false;
      }
    }

    return true;
  },

  /**
   * registers evnet in given frame for given slice
   * 
   * @private
   * @param {Array} frame
   * @param {Number} startIdx
   * @param {Number} endIdx
   * @param {Ext.data.Record} event
   * @return this
   */
  registerSlice: function registerSlice(frame, startIdx, endIdx, event) {
    for (var idx = startIdx; idx <= endIdx; idx++) {
      frame[idx] = event;
    }
  },

  /**
   * @private
   * @param  {Number} ts
   * @return {Number}
   */
  tsToIdx: function tsToIdx(ts) {
    return Math.floor((ts - this.dtStartTs) / this.dt);
  },

  /**
   * registers evnet in given frame for given slice 
   * 
   * @private
   * @param {Array} frame
   * @param {Number} startIdx
   * @param {Number} endIdx
   * @return this
   */
  unregisterSlice: function unregisterSlice(frame, startIdx, endIdx) {
    for (var idx = startIdx; idx <= endIdx; idx++) {
      frame[idx] = null;
    }

    return this;
  }
};

/***/ }),

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

/*
 * Tine 2.0
 * event combo box and store
 * 
 * @package     Calendar
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Alexander Stintzing <alex@stintzing.net>
 * @copyright   Copyright (c) 2007-2011 Metaways Infosystems GmbH (http://www.metaways.de)
 *
 */
Ext.ns('Tine.Calendar');
/**
 * event selection combo box
 *
 * @namespace   Tine.Calendar
 * @class       Tine.Calendar.SearchCombo
 * @extends     Ext.form.ComboBox
 *
 * <p>Event Search Combobox</p>
 *
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Alexander Stintzing <alex@stintzing.net>
 * @copyright   Copyright (c) 2007-2011 Metaways Infosystems GmbH (http://www.metaways.de)
 *
 * @param       {Object} config
 * @constructor
 * Create a new Tine.Calendar.SearchCombo
 *
 * @TODO        Extend Tine.Tinebase.widgets.form.RecordPickerComboBox once this class
 *              is rewritten to use beforeload/load events
 */

Tine.Calendar.SearchCombo = Ext.extend(Ext.ux.form.ClearableComboBox, {
  anchor: '100% 100%',
  margins: '10px 10px',
  app: null,
  appName: 'Calendar',
  store: null,
  allowBlank: false,
  triggerAction: 'all',
  itemSelector: 'div.search-item',
  forceSelection: true,
  minListWidth: 400,

  /*
   * shows date pager on bottom of the resultlist
   */
  showDatePager: true,

  /**
   * shows an reload button in the datepager
   */
  showReloadBtn: null,

  /**
   * shows an today button in the datepager
   */
  showTodayBtn: null,

  /**
   * To show or hide the paging toolbar
   */
  hasPaging: true,
  initComponent: function initComponent() {
    if (!this.app) {
      this.app = Tine.Tinebase.appMgr.get(this.appName);
    }

    this.listEmptyText = this.app.i18n._('no events found');
    this.loadingText = i18n._('Searching...');
    this.recordClass = Tine.Calendar.Model.Event;
    this.recordProxy = Tine.Calendar.backend;
    this.displayField = this.recordClass.getMeta('titleProperty');
    this.valueField = this.recordClass.getMeta('idProperty');
    this.emptyText = this.emptyText || this.app.i18n._('Search Event');
    this.fieldLabel = this.fieldLabel || this.app.i18n._('Event');
    this.disableClearer = !this.allowBlank;
    this.store = new Tine.Tinebase.data.RecordStore(Ext.copyTo({
      readOnly: true,
      sortInfo: {
        field: 'dtstart',
        direction: 'ASC'
      },
      proxy: this.recordProxy || undefined
    }, this, 'totalProperty,root,recordClass'));
    this.store.on('beforeload', this.onBeforeStoreLoad, this);
    this.store.on('load', this.onStoreLoad, this);
    this.initTemplate();
    Tine.Calendar.SearchCombo.superclass.initComponent.call(this);
  },
  setValue: Tine.Tinebase.widgets.form.RecordPickerComboBox.prototype.setValue,

  /**
   * @param {} store
   * @param {} records
   */
  onStoreLoad: function onStoreLoad(store, records) {// override, when required.
  },

  /**
   * sets period ans searchword as query parameter
   * @param {} store
   */
  onBeforeStoreLoad: function onBeforeStoreLoad(store) {
    store.baseParams.filter = [{
      field: 'query',
      operator: 'contains',
      value: this.getRawValue()
    }];

    if (this.hasPaging && this.pageTb) {
      store.baseParams.filter.push({
        field: 'period',
        operator: 'within',
        value: this.pageTb.getPeriod()
      });
    }
  },
  expand: function expand() {
    this.pageTb.setVisible(this.hasPaging);
    this.supr().expand.apply(this, arguments);
  },

  /**
   * collapses the result list only when periodpicker is not active
   * @return {Boolean}
   */
  collapse: function collapse() {
    if (this.hasPaging && this.pageTb.periodPickerActive == true) {
      return false;
    } else {
      Tine.Calendar.SearchCombo.superclass.collapse.call(this);
    }
  },

  /**
   * Reload store when combobox is cleared
   */
  clearValue: function clearValue() {
    this.supr().clearValue.apply(this, arguments);
    this.store.reload();
  },

  /**
   * is called, when list is initialized, appends a date-paging-toolbar instead a normal one
   */
  initList: function initList() {
    Tine.Calendar.SearchCombo.superclass.initList.call(this);
    var startDate = new Date().clearTime();
    this.footer = this.list.createChild({
      cls: 'list-ft'
    });
    this.pageTb = new Tine.Calendar.PagingToolbar({
      view: 'month',
      anchor: '100% 100%',
      store: this.store,
      dtStart: startDate,
      showReloadBtn: this.showReloadBtn,
      showTodayBtn: this.showTodayBtn,
      renderTo: this.footer,
      listeners: {
        scope: this,
        change: function change() {
          this.store.removeAll();
          this.store.load();
        }
      }
    });
    this.assetHeight += this.footer.getHeight();
  },
  onBlur: Ext.emptyFn,
  assertValue: Ext.emptyFn,

  /**
   * init template
   * @private
   */
  initTemplate: function initTemplate() {
    if (!this.tpl) {
      this.tpl = new Ext.XTemplate('<tpl for="."><div class="search-item">', '<table cellspacing="0" cellpadding="2" border="0" style="font-size: 11px;" width="100%">', '<tr>', '<td width="40%"><b>{[this.encode(values.summary)]}</b></td>', '<td width="60%">', '{[this.encodeDate(values)]}', '</td>', '</tr>', '</table>', '</div></tpl>', {
        encode: function encode(value) {
          if (value) {
            return Ext.util.Format.htmlEncode(value);
          } else {
            return '';
          }
        },
        encodeDate: function encodeDate(values) {
          var start = values.dtstart,
              end = values.dtend,
              _ = window.lodash;

          if (_.isString(start)) {
            start = Date.parseDate(start, Date.patterns.ISO8601Long);
          }

          if (_.isString(end)) {
            end = Date.parseDate(end, Date.patterns.ISO8601Long);
          }

          var duration = values.is_all_day_event ? Tine.Tinebase.appMgr.get('Calendar').i18n._('whole day') : Tine.Tinebase.common.minutesRenderer(Math.round((end.getTime() - start.getTime()) / (1000 * 60)), '{0}:{1}', 'i');
          return Tine.Tinebase.common.dateTimeRenderer(start) + ' (' + duration + ')';
        }
      });
    }
  }
});
Tine.widgets.form.RecordPickerManager.register('Calendar', 'Event', Tine.Calendar.SearchCombo);

/***/ }),

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

/* 
 * Tine 2.0
 * 
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2007-2015 Metaways Infosystems GmbH (http://www.metaways.de)
 */
Ext.ns('Tine.Calendar', 'Tine.Calendar.Model');
/**
 * @namespace Tine.Calendar.Model
 * @class Tine.Calendar.Model.Event
 * @extends Tine.Tinebase.data.Record
 * Event record definition
 */

Tine.Calendar.Model.Event = Tine.Tinebase.data.Record.create(Tine.Tinebase.Model.genericFields.concat([{
  name: 'id'
}, {
  name: 'dtend',
  type: 'date',
  dateFormat: Date.patterns.ISO8601Long
}, {
  name: 'transp'
}, // ical common fields
{
  name: 'class'
}, {
  name: 'description'
}, {
  name: 'geo'
}, {
  name: 'adr_lon'
}, {
  name: 'adr_lat'
}, {
  name: 'location'
}, {
  name: 'organizer'
}, {
  name: 'priority'
}, {
  name: 'status'
}, {
  name: 'summary'
}, {
  name: 'url'
}, {
  name: 'uid'
}, // ical common fields with multiple appearance
//{ name: 'attach' },
{
  name: 'attendee'
}, {
  name: 'alarms'
}, {
  name: 'tags'
}, {
  name: 'notes'
}, {
  name: 'attachments'
}, //{ name: 'contact' },
//{ name: 'related' },
//{ name: 'resources' },
//{ name: 'rstatus' },
// scheduleable interface fields
{
  name: 'dtstart',
  type: 'date',
  dateFormat: Date.patterns.ISO8601Long
}, {
  name: 'recurid'
}, {
  name: 'base_event_id'
}, // scheduleable interface fields with multiple appearance
{
  name: 'exdate'
}, //{ name: 'exrule' },
//{ name: 'rdate' },
{
  name: 'rrule'
}, {
  name: 'poll_id'
}, {
  name: 'mute'
}, {
  name: 'is_all_day_event',
  type: 'bool'
}, {
  name: 'rrule_until',
  type: 'date',
  dateFormat: Date.patterns.ISO8601Long
}, {
  name: 'rrule_constraints'
}, {
  name: 'originator_tz'
}, // grant helper fields
{
  name: 'addGrant',
  type: 'bool'
}, {
  name: 'readGrant',
  type: 'bool'
}, {
  name: 'editGrant',
  type: 'bool'
}, {
  name: 'deleteGrant',
  type: 'bool'
}, {
  name: 'exportGrant',
  type: 'bool'
}, {
  name: 'freebusyGrant',
  type: 'bool'
}, {
  name: 'privateGrant',
  type: 'bool'
}, {
  name: 'syncGrant',
  type: 'bool'
}, // relations
{
  name: 'relations',
  omitDuplicateResolving: true
}, {
  name: 'customfields',
  omitDuplicateResolving: true
}]), {
  appName: 'Calendar',
  modelName: 'Event',
  idProperty: 'id',
  titleProperty: 'summary',
  // ngettext('Event', 'Events', n); gettext('Events');
  recordName: 'Event',
  recordsName: 'Events',
  containerProperty: 'container_id',
  grantsPath: 'data',
  // ngettext('Calendar', 'Calendars', n); gettext('Calendars');
  containerName: 'Calendar',
  containersName: 'Calendars',
  copyOmitFields: ['uid', 'recurid'],
  allowBlankContainer: false,
  copyNoAppendTitle: true,

  /**
   * default duration for new events
   */
  defaultEventDuration: 60,

  /**
   * returns displaycontainer with orignialcontainer as fallback
   * 
   * @return {Array}
   */
  getDisplayContainer: function getDisplayContainer() {
    var displayContainer = this.get('container_id');
    var currentAccountId = Tine.Tinebase.registry.get('currentAccount').accountId;
    var attendeeStore = this.getAttendeeStore();
    attendeeStore.each(function (attender) {
      var userAccountId = attender.getUserAccountId();

      if (userAccountId == currentAccountId) {
        var container = attender.get('displaycontainer_id');

        if (container) {
          displayContainer = container;
        }

        return false;
      }
    }, this);
    return displayContainer;
  },

  /**
   * is this event a recuring base event?
   * 
   * @return {Boolean}
   */
  isRecurBase: function isRecurBase() {
    return !!this.get('rrule') && !this.get('recurid');
  },

  /**
   * is this event a recuring exception?
   * 
   * @return {Boolean}
   */
  isRecurException: function isRecurException() {
    return !!this.get('recurid') && !this.isRecurInstance();
  },

  /**
   * is this event an recuring event instance?
   * 
   * @return {Boolean}
   */
  isRecurInstance: function isRecurInstance() {
    return this.id && Ext.isFunction(this.id.match) && this.id.match(/^fakeid/);
  },

  /**
   * returns store of attender objects
   * 
   * @param  {Array} attendeeData
   * @return {Ext.data.Store}
   */
  getAttendeeStore: function getAttendeeStore() {
    return Tine.Calendar.Model.Attender.getAttendeeStore(this.get('attendee'));
  },

  /**
   * returns attender record of current account if exists, else false
   */
  getMyAttenderRecord: function getMyAttenderRecord() {
    var attendeeStore = this.getAttendeeStore();
    return Tine.Calendar.Model.Attender.getAttendeeStore.getMyAttenderRecord(attendeeStore);
  },
  getSchedulingData: function getSchedulingData() {
    var _ = window.lodash,
        schedulingData = _.pick(this.data, ['uid', 'originator_tz', 'dtstart', 'dtend', 'is_all_day_event', 'transp', 'recurid', 'base_event_id', 'rrule', 'rrule_until', 'exdate', 'rrule_constraints']); // NOTE: for transistent events id is not part of data but we need the transistent id e.g. for freeBusy info


    schedulingData.id = this.id;
    return schedulingData;
  },
  inPeriod: function inPeriod(period) {
    return this.get('dtstart').between(period.from, period.until) || this.get('dtend').between(period.from, period.until);
  },
  hasPoll: function hasPoll() {
    var _ = window.lodash;
    return !+_.get(this, 'data.poll_id.closed', true);
  },
  getPollUrl: function getPollUrl(pollId) {
    if (!pollId) {
      pollId = this.get('poll_id');

      if (pollId.id) {
        pollId = pollId.id;
      }
    }

    return Tine.Tinebase.common.getUrl() + 'Calendar/view/poll/' + pollId;
  },
  getTitle: function getTitle() {
    return this.get('summary') + (this.hasPoll() ? '\u00A0\uFFFD' : '');
  },
  isRescheduled: function isRescheduled(event) {
    return this.get('dtstart').toString() !== event.get('dtstart').toString() || this.get('dtend').toString() !== event.get('dtend').toString();
  },
  getComboBoxTitle: function getComboBoxTitle() {
    return this.get('summary') + ' (' + Tine.Tinebase.common.dateTimeRenderer(this.get('dtstart')) + ')';
  }
});
/**
 * get default data for a new event
 *  
 * @return {Object} default data
 * @static
 */

Tine.Calendar.Model.Event.getDefaultData = function () {
  var app = Tine.Tinebase.appMgr.get('Calendar'),
      prefs = app.getRegistry().get('preferences'),
      defaultAttendeeStrategy = prefs.get('defaultAttendeeStrategy') || 'me',
      interval = prefs.get('interval') || 15,
      mainScreen = app.getMainScreen(),
      centerPanel = mainScreen.getCenterPanel(),
      westPanel = mainScreen.getWestPanel(),
      container = westPanel.getContainerTreePanel().getDefaultContainer(),
      organizer = defaultAttendeeStrategy != 'me' && container && container.ownerContact ? container.ownerContact : Tine.Tinebase.registry.get('userContact'),
      dtstart = new Date().clearTime().add(Date.HOUR, new Date().getHours() + 1),
      makeEventsPrivate = prefs.get('defaultSetEventsToPrivat'),
      eventClass = null,
      period = centerPanel.getCalendarPanel(centerPanel.activeView).getView().getPeriod(); // if dtstart is out of current period, take start of current period

  if (period.from.getTime() > dtstart.getTime() || period.until.getTime() < dtstart.getTime()) {
    dtstart = period.from.clearTime(true).add(Date.HOUR, 9);
  }

  if (makeEventsPrivate == 1) {
    eventClass = 'PRIVATE';
  }

  var data = {
    id: 'new-' + Ext.id(),
    summary: '',
    'class': eventClass,
    dtstart: dtstart,
    dtend: dtstart.add(Date.MINUTE, Tine.Calendar.Model.Event.getMeta('defaultEventDuration')),
    status: 'CONFIRMED',
    container_id: container,
    transp: 'OPAQUE',
    editGrant: true,
    // needed for action updater / save and close in edit dialog
    readGrant: true,
    organizer: organizer,
    attendee: Tine.Calendar.Model.Event.getDefaultAttendee(organizer, container),
    mute: false
  };

  if (+prefs.get('defaultalarmenabled')) {
    data.alarms = [{
      minutes_before: parseInt(prefs.get('defaultalarmminutesbefore'), 10)
    }];
  }

  app.emit('createEvent', data);
  return data;
};

Tine.Calendar.Model.Event.getDefaultAttendee = function (organizer, container) {
  var app = Tine.Tinebase.appMgr.get('Calendar'),
      mainScreen = app.getMainScreen(),
      centerPanel = mainScreen.getCenterPanel(),
      westPanel = mainScreen.getWestPanel(),
      filteredAttendee = westPanel.getAttendeeFilter().getValue() || [],
      defaultAttendeeData = Tine.Calendar.Model.Attender.getDefaultData(),
      defaultResourceData = Tine.Calendar.Model.Attender.getDefaultResourceData(),
      filteredContainers = westPanel.getContainerTreePanel().getFilterPlugin().getFilter().value || [],
      prefs = app.getRegistry().get('preferences'),
      defaultAttendeeStrategy = prefs.get('defaultAttendeeStrategy') || 'me',
      // one of['me', 'intelligent', 'calendarOwner', 'filteredAttendee', 'none']
  defaultAttendee = [],
      calendarResources = app.getRegistry().get('calendarResources'); // shift -> change intelligent <-> me

  if (Ext.EventObject.shiftKey) {
    defaultAttendeeStrategy = defaultAttendeeStrategy == 'intelligent' ? 'me' : defaultAttendeeStrategy == 'me' ? 'intelligent' : defaultAttendeeStrategy;
  } // alt -> prefer calendarOwner in intelligent mode


  if (defaultAttendeeStrategy == 'intelligent') {
    defaultAttendeeStrategy = filteredAttendee.length && !Ext.EventObject.altKey > 0 ? 'filteredAttendee' : filteredContainers.length > 0 ? 'calendarOwner' : 'me';
  }

  switch (defaultAttendeeStrategy) {
    case 'none':
      break;

    case 'me':
      defaultAttendee.push(Ext.apply(Tine.Calendar.Model.Attender.getDefaultData(), {
        user_type: 'user',
        user_id: Tine.Tinebase.registry.get('userContact'),
        status: 'ACCEPTED'
      }));
      break;

    case 'filteredAttendee':
      var attendeeStore = Tine.Calendar.Model.Attender.getAttendeeStore(filteredAttendee),
          ownAttendee = Tine.Calendar.Model.Attender.getAttendeeStore.getMyAttenderRecord(attendeeStore);
      attendeeStore.each(function (attendee) {
        var attendeeData = Ext.applyIf(Ext.decode(Ext.encode(attendee.data)), defaultAttendeeData);

        switch (attendeeData.user_type.toLowerCase()) {
          case 'memberof':
            attendeeData.user_type = 'group';
            break;

          case 'resource':
            Ext.apply(attendeeData, defaultResourceData);
            break;

          default:
            break;
        }

        if (attendee == ownAttendee) {
          attendeeData.status = 'ACCEPTED';
        }

        defaultAttendee.push(attendeeData);
      }, this);
      break;

    case 'calendarOwner':
      var addedOwnerIds = [];
      Ext.each(filteredContainers, function (filteredContainer) {
        if (filteredContainer.ownerContact && filteredContainer.type && filteredContainer.type == 'personal') {
          var attendeeData = Ext.apply(Tine.Calendar.Model.Attender.getDefaultData(), {
            user_type: 'user',
            user_id: filteredContainer.ownerContact
          });

          if (attendeeData.user_id.id == organizer.id) {
            attendeeData.status = 'ACCEPTED';
          }

          if (addedOwnerIds.indexOf(filteredContainer.ownerContact.id) < 0) {
            defaultAttendee.push(attendeeData);
            addedOwnerIds.push(filteredContainer.ownerContact.id);
          }
        } else if (filteredContainer.type && filteredContainer.type == 'shared' && calendarResources) {
          Ext.each(calendarResources, function (calendarResource) {
            if (calendarResource.container_id == filteredContainer.id) {
              var attendeeData = Ext.apply(Tine.Calendar.Model.Attender.getDefaultData(), {
                user_type: 'resource',
                user_id: calendarResource,
                status: calendarResource.status
              });
              defaultAttendee.push(attendeeData);
            }
          }, this);
        }
      }, this);

      if (container && container.ownerContact && addedOwnerIds.indexOf(container.ownerContact.id) < 0) {
        var attendeeData = Ext.apply(Tine.Calendar.Model.Attender.getDefaultData(), {
          user_type: 'user',
          user_id: container.ownerContact
        });

        if (container.ownerContact.id == organizer.id) {
          attendeeData.status = 'ACCEPTED';
        }

        defaultAttendee.push(attendeeData);
        addedOwnerIds.push(container.ownerContact.id);
      }

      break;
  }

  return defaultAttendee;
};

Tine.Calendar.Model.Event.getFilterModel = function () {
  var app = Tine.Tinebase.appMgr.get('Calendar');
  return [{
    label: i18n._('Quick Search'),
    field: 'query',
    operators: ['contains']
  }, {
    label: app.i18n._('Summary'),
    field: 'summary'
  }, {
    label: app.i18n._('Location'),
    field: 'location'
  }, {
    label: app.i18n._('Description'),
    field: 'description',
    operators: ['contains', 'notcontains']
  }, // _('GENDER_Calendar')
  {
    filtertype: 'tine.widget.container.filtermodel',
    app: app,
    recordClass: Tine.Calendar.Model.Event,

    /*defaultOperator: 'in',*/
    defaultValue: {
      path: Tine.Tinebase.container.getMyNodePath()
    }
  }, {
    filtertype: 'calendar.attendee'
  }, {
    label: app.i18n._('Attendee Status'),
    gender: app.i18n._('GENDER_Attendee Status'),
    field: 'attender_status',
    filtertype: 'tine.widget.keyfield.filter',
    app: app,
    keyfieldName: 'attendeeStatus',
    defaultOperator: 'notin',
    defaultValue: ['DECLINED']
  }, {
    label: app.i18n._('Attendee Role'),
    gender: app.i18n._('GENDER_Attendee Role'),
    field: 'attender_role',
    filtertype: 'tine.widget.keyfield.filter',
    app: app,
    keyfieldName: 'attendeeRoles'
  }, {
    filtertype: 'addressbook.contact',
    field: 'organizer',
    label: app.i18n._('Organizer')
  }, {
    filtertype: 'tinebase.tag',
    app: app
  }, {
    label: app.i18n._('Status'),
    gender: app.i18n._('GENDER_Status'),
    field: 'status',
    filtertype: 'tine.widget.keyfield.filter',
    app: {
      name: 'Calendar'
    },
    keyfieldName: 'eventStatus',
    defaultAll: true
  }, {
    label: app.i18n._('Blocking'),
    gender: app.i18n._('GENDER_Blocking'),
    field: 'transp',
    filtertype: 'tine.widget.keyfield.filter',
    app: {
      name: 'Calendar'
    },
    keyfieldName: 'eventTransparencies',
    defaultAll: true
  }, {
    label: app.i18n._('Classification'),
    gender: app.i18n._('GENDER_Classification'),
    field: 'class',
    filtertype: 'tine.widget.keyfield.filter',
    app: {
      name: 'Calendar'
    },
    keyfieldName: 'eventClasses',
    defaultAll: true
  }, {
    label: i18n._('Last Modified Time'),
    field: 'last_modified_time',
    valueType: 'date'
  }, //{label: i18n._('Last Modified By'),                                                  field: 'last_modified_by',   valueType: 'user'},
  {
    label: i18n._('Creation Time'),
    field: 'creation_time',
    valueType: 'date'
  }, //{label: i18n._('Created By'),                                                        field: 'created_by',         valueType: 'user'},
  {
    filtertype: 'calendar.rrule',
    app: app
  }];
};

Tine.Calendar.Model.Event.datetimeRenderer = function (dt) {
  var app = Tine.Tinebase.appMgr.get('Calendar');

  if (!dt) {
    return app.i18n._('Unknown date');
  }

  return String.format(app.i18n._("{0} {1} o'clock"), dt.format('l') + ', ' + Tine.Tinebase.common.dateRenderer(dt), dt.format('H:i'));
}; // register calendar filters in addressbook


Tine.widgets.grid.ForeignRecordFilter.OperatorRegistry.register('Addressbook', 'Contact', {
  foreignRecordClass: 'Calendar.Event',
  linkType: 'foreignId',
  filterName: 'ContactAttendeeFilter',
  // i18n._('Event (as attendee)')
  label: 'Event (as attendee)'
});
Tine.widgets.grid.ForeignRecordFilter.OperatorRegistry.register('Addressbook', 'Contact', {
  foreignRecordClass: 'Calendar.Event',
  linkType: 'foreignId',
  filterName: 'ContactOrganizerFilter',
  // i18n._('Event (as organizer)')
  label: 'Event (as organizer)'
}); // example for explicit definition
//Tine.widgets.grid.FilterRegistry.register('Addressbook', 'Contact', {
//    filtertype: 'foreignrecord',
//    foreignRecordClass: 'Calendar.Event',
//    linkType: 'foreignId', 
//    filterName: 'ContactAttendeeFilter',
//    // i18n._('Event attendee')
//    label: 'Event attendee'
//});

/**
 * @namespace Tine.Calendar.Model
 * @class Tine.Calendar.Model.EventJsonBackend
 * @extends Tine.Tinebase.data.RecordProxy
 * 
 * JSON backend for events
 */

Tine.Calendar.Model.EventJsonBackend = Ext.extend(Tine.Tinebase.data.RecordProxy, {
  appName: 'Calendar',
  modelName: 'Event',
  recordClass: Tine.Calendar.Model.Event,

  /**
   * Creates a recuring event exception
   * 
   * @param {Tine.Calendar.Model.Event} event
   * @param {Boolean} deleteInstance
   * @param {Boolean} deleteAllFollowing
   * @param {Object} options
   * @return {String} transaction id
   */
  createRecurException: function createRecurException(event, deleteInstance, deleteAllFollowing, checkBusyConflicts, options) {
    options = options || {};
    options.params = options.params || {};

    options.beforeSuccess = function (response) {
      return [this.recordReader(response)];
    };

    var p = options.params;
    p.method = this.appName + '.createRecurException';
    p.recordData = event.data;
    p.deleteInstance = deleteInstance ? 1 : 0;
    p.deleteAllFollowing = deleteAllFollowing ? 1 : 0;
    p.checkBusyConflicts = checkBusyConflicts ? 1 : 0;
    return this.doXHTTPRequest(options);
  },
  promiseCreateRecurException: function promiseCreateRecurException(event, deleteInstance, deleteAllFollowing, checkBusyConflicts, options) {
    var me = this;
    return new Promise(function (fulfill, reject) {
      try {
        me.createRecurException(event, deleteInstance, deleteAllFollowing, checkBusyConflicts, Ext.apply(options || {}, {
          success: function success(r) {
            fulfill(r);
          },
          failure: function failure(error) {
            reject(new Error(error));
          }
        }));
      } catch (error) {
        if (Ext.isFunction(reject)) {
          reject(new Error(options));
        }
      }
    });
  },

  /**
   * delete a recuring event series
   * 
   * @param {Tine.Calendar.Model.Event} event
   * @param {Object} options
   * @return {String} transaction id
   */
  deleteRecurSeries: function deleteRecurSeries(event, options) {
    options = options || {};
    options.params = options.params || {};
    var p = options.params;
    p.method = this.appName + '.deleteRecurSeries';
    p.recordData = event.data;
    return this.doXHTTPRequest(options);
  },

  /**
   * updates a recuring event series
   * 
   * @param {Tine.Calendar.Model.Event} event
   * @param {Object} options
   * @return {String} transaction id
   */
  updateRecurSeries: function updateRecurSeries(event, checkBusyConflicts, options) {
    options = options || {};
    options.params = options.params || {};

    options.beforeSuccess = function (response) {
      return [this.recordReader(response)];
    };

    var p = options.params;
    p.method = this.appName + '.updateRecurSeries';
    p.recordData = event.data;
    p.checkBusyConflicts = checkBusyConflicts ? 1 : 0;
    return this.doXHTTPRequest(options);
  }
});
/*
 * default event backend
 */

if (Tine.Tinebase.widgets) {
  Tine.Calendar.backend = new Tine.Calendar.Model.EventJsonBackend({});
} else {
  Tine.Calendar.backend = new Tine.Tinebase.data.MemoryBackend({
    appName: 'Calendar',
    modelName: 'Event',
    recordClass: Tine.Calendar.Model.Event
  });
}
/**
 * @namespace Tine.Calendar.Model
 * @class Tine.Calendar.Model.Attender
 * @extends Tine.Tinebase.data.Record
 * Attender Record Definition
 */


Tine.Calendar.Model.Attender = Tine.Tinebase.data.Record.create([{
  name: 'id'
}, {
  name: 'cal_event_id'
}, {
  name: 'user_id',
  sortType: Tine.Tinebase.common.accountSortType
}, {
  name: 'user_type'
}, {
  name: 'role',
  type: 'keyField',
  keyFieldConfigName: 'attendeeRoles'
}, {
  name: 'quantity'
}, {
  name: 'status',
  type: 'keyField',
  keyFieldConfigName: 'attendeeStatus'
}, {
  name: 'status_authkey'
}, {
  name: 'displaycontainer_id'
}, {
  name: 'transp'
}, {
  name: 'checked'
}, // filter grid helper field
{
  name: 'fbInfo'
} // helper field
], {
  appName: 'Calendar',
  modelName: 'Attender',
  idProperty: 'id',
  titleProperty: 'name',
  // ngettext('Attender', 'Attendee', n); gettext('Attendee');
  recordName: 'Attender',
  recordsName: 'Attendee',
  containerProperty: 'cal_event_id',
  // ngettext('Event', 'Events', n); gettext('Events');
  containerName: 'Event',
  containersName: 'Events',

  /**
   * gets name of attender
   * 
   * @return {String}
   */
  getTitle: function getTitle() {
    var p = Tine.Calendar.AttendeeGridPanel.prototype;
    return p.renderAttenderName.call(p, this.get('user_id'), false, this);
  },
  getCompoundId: function getCompoundId(mapGroupmember) {
    var type = this.get('user_type');
    type = mapGroupmember && type == 'groupmember' ? 'user' : type;
    return type + '-' + this.getUserId();
  },

  /**
   * returns true for external contacts
   */
  isExternal: function isExternal() {
    var isExternal = false,
        user_type = this.get('user_type');

    if (user_type == 'user' || user_type == 'groupmember') {
      isExternal = !this.getUserAccountId();
    }

    return isExternal;
  },

  /**
   * returns account_id if attender is/has a user account
   * 
   * @return {String}
   */
  getUserAccountId: function getUserAccountId() {
    var user_type = this.get('user_type');

    if (user_type == 'user' || user_type == 'groupmember') {
      var user_id = this.get('user_id');

      if (!user_id) {
        return null;
      } // we expect user_id to be a user or contact object or record


      if (typeof user_id.get == 'function') {
        if (user_id.get('contact_id')) {
          // user_id is a account record
          return user_id.get('accountId');
        } else {
          // user_id is a contact record
          return user_id.get('account_id');
        }
      } else if (user_id.hasOwnProperty('contact_id')) {
        // user_id contains account data
        return user_id.accountId;
      } else if (user_id.hasOwnProperty('account_id')) {
        // user_id contains contact data
        return user_id.account_id;
      } // this might happen if contact resolved, due to right restrictions


      return user_id;
    }

    return null;
  },

  /**
   * returns id of attender of any kind
   */
  getUserId: function getUserId() {
    var user_id = this.get('user_id');

    if (!user_id) {
      return null;
    }

    var userData = typeof user_id.get == 'function' ? user_id.data : user_id;

    if (!userData) {
      return null;
    }

    if (typeof userData != 'object') {
      return userData;
    }

    switch (this.get('user_type')) {
      case 'user':
      case 'groupmember':
      case 'memberOf':
        if (userData.hasOwnProperty('contact_id')) {
          // userData contains account
          return userData.contact_id;
        } else if (userData.hasOwnProperty('account_id')) {
          // userData contains contact
          return userData.id;
        } else if (userData.group_id) {
          // userData contains list
          return userData.id;
        } else if (userData.list_id) {
          // userData contains group
          return userData.list_id;
        }

        break;

      default:
        return userData.id;
        break;
    }
  },
  getIconCls: function getIconCls() {
    var type = this.get('user_type'),
        cls = 'tine-grid-row-action-icon cal-attendee-type-';

    switch (type) {
      case 'user':
        cls = 'tine-grid-row-action-icon renderer_typeAccountIcon';
        break;

      case 'group':
        cls = 'tine-grid-row-action-icon renderer_accountGroupIcon';
        break;

      default:
        cls += type;
        break;
    }

    return cls;
  }
});

Tine.Calendar.Model.Attender.getSortOrder = function (user_type) {
  var sortOrders = {
    'user': 1,
    'groupmemeber': 1,
    'group': 2,
    'resource': 3
  };
  return sortOrders[user_type] || 4;
};
/**
 * @namespace Tine.Calendar.Model
 * 
 * get default data for a new attender
 *  
 * @return {Object} default data
 * @static
 */


Tine.Calendar.Model.Attender.getDefaultData = function (overrides) {
  return _.assign({
    // @TODO have some config here? user vs. default?
    user_type: 'any',
    role: 'REQ',
    quantity: 1,
    status: 'NEEDS-ACTION'
  }, overrides);
};
/**
 * @namespace Tine.Calendar.Model
 * 
 * get default data for a new resource
 *  
 * @return {Object} default data
 * @static
 */


Tine.Calendar.Model.Attender.getDefaultResourceData = function () {
  return {
    user_type: 'resource',
    role: 'REQ',
    quantity: 1,
    status: 'NEEDS-ACTION'
  };
};
/**
 * @namespace Tine.Calendar.Model
 * 
 * creates store of attender objects
 * 
 * @param  {Array} attendeeData
 * @return {Ext.data.Store}
 * @static
 */


Tine.Calendar.Model.Attender.getAttendeeStore = function (attendeeData) {
  var attendeeStore = new Ext.data.SimpleStore({
    fields: Tine.Calendar.Model.Attender.getFieldDefinitions(),
    sortInfo: {
      field: 'user_id',
      direction: 'ASC'
    }
  });

  if (Ext.isString(attendeeData)) {
    attendeeData = Ext.decode(attendeeData || null);
  }

  Ext.each(attendeeData, function (attender) {
    if (attender) {
      var record = new Tine.Calendar.Model.Attender(attender, attender.id && Ext.isString(attender.id) ? attender.id : Ext.id());

      if (record.get('user_id') == "currentContact") {
        record.set('user_id', Tine.Tinebase.registry.get('userContact'));
      }

      attendeeStore.addSorted(record);
    }
  });
  return attendeeStore;
};
/**
 * returns attender record of current account if exists, else false
 * @static
 */


Tine.Calendar.Model.Attender.getAttendeeStore.getMyAttenderRecord = function (attendeeStore) {
  var currentAccountId = Tine.Tinebase.registry.get('currentAccount').accountId;
  var myRecord = false;
  attendeeStore.each(function (attender) {
    var userAccountId = attender.getUserAccountId();

    if (userAccountId == currentAccountId) {
      myRecord = attender;
      return false;
    }
  }, this);
  return myRecord;
};
/**
 * returns attendee record of given attendee if exists, else false
 * @static
 */


Tine.Calendar.Model.Attender.getAttendeeStore.getAttenderRecord = function (attendeeStore, attendee) {
  var attendeeRecord = false;

  if (!Ext.isFunction(attendee.beginEdit)) {
    attendee = new Tine.Calendar.Model.Attender(attendee, attendee.id);
  }

  attendeeStore.each(function (r) {
    var attendeeType = [attendee.get('user_type')]; // add groupmember for user

    if (attendeeType[0] == 'user') {
      attendeeType.push('groupmember');
    }

    if (attendeeType[0] == 'groupmember') {
      attendeeType.push('user');
    }

    if (attendeeType.indexOf(r.get('user_type')) >= 0 && r.getUserId() == attendee.getUserId()) {
      attendeeRecord = r;
      return false;
    }
  }, this);
  return attendeeRecord;
};

Tine.Calendar.Model.Attender.getAttendeeStore.signatureDelimiter = ';';

Tine.Calendar.Model.Attender.getAttendeeStore.getSignature = function (attendee) {
  var _ = window.lodash;
  attendee = _.isFunction(attendee.beginEdit) ? attendee.data : attendee;
  return [attendee.cal_event_id, attendee.user_type, attendee.user_id.id || attendee.user_id, attendee.role].join(Tine.Calendar.Model.Attender.getAttendeeStore.signatureDelimiter);
};

Tine.Calendar.Model.Attender.getAttendeeStore.fromSignature = function (signatureId) {
  var ids = signatureId.split(Tine.Calendar.Model.Attender.getAttendeeStore.signatureDelimiter);
  return new Tine.Calendar.Model.Attender({
    cal_event_id: ids[0],
    user_type: ids[1],
    user_id: ids[2],
    role: ids[3]
  });
};
/**
 * returns attendee data
 * optinally fills into event record
 */


Tine.Calendar.Model.Attender.getAttendeeStore.getData = function (attendeeStore, event) {
  var attendeeData = [];
  Tine.Tinebase.common.assertComparable(attendeeData);
  attendeeStore.each(function (attender) {
    var user_id = attender.get('user_id');

    if (user_id
    /* && user_id.id*/
    ) {
        if (typeof user_id.get == 'function') {
          attender.data.user_id = user_id.data;
        }

        attendeeData.push(attender.data);
      }
  }, this);

  if (event) {
    event.set('attendee', attendeeData);
  }

  return attendeeData;
}; // PROXY


Tine.Calendar.Model.AttenderProxy = function (config) {
  Tine.Calendar.Model.AttenderProxy.superclass.constructor.call(this, config);
  this.jsonReader.readRecords = this.readRecords.createDelegate(this);
};

Ext.extend(Tine.Calendar.Model.AttenderProxy, Tine.Tinebase.data.RecordProxy, {
  /**
   * provide events to do an freeBusy info checkup for when searching attendee
   *
   * @cfg {Function} freeBusyEventsProvider
   */
  freeBusyEventsProvider: Ext.emptyFn,
  recordClass: Tine.Calendar.Model.Attender,
  searchRecords: function searchRecords(filter, paging, options) {
    var _ = window.lodash,
        fbEvents = _.union([].concat(this.freeBusyEventsProvider()));

    _.set(options, 'params.ignoreUIDs', _.union(_.map(fbEvents, 'data.uid')));

    _.set(options, 'params.events', _.map(fbEvents, function (event) {
      return event.getSchedulingData();
    }));

    return Tine.Calendar.Model.AttenderProxy.superclass.searchRecords.apply(this, arguments);
  },
  readRecords: function readRecords(resultData) {
    var _ = window.lodash,
        totalcount = 0,
        fbEvents = _.compact([].concat(this.freeBusyEventsProvider())),
        records = [],
        fbInfos = _.map(fbEvents, function (fbEvent) {
      return new Tine.Calendar.FreeBusyInfo(resultData.freeBusyInfo[fbEvent.id]);
    });

    _.each(['user', 'group', 'resource'], function (type) {
      var typeResult = _.get(resultData, type, {}),
          typeCount = _.get(typeResult, 'totalcount', 0),
          typeData = _.get(typeResult, 'results', []);

      totalcount += +typeCount;

      _.each(typeData, function (userData) {
        var id = type + '-' + userData.id,
            attendeeData = _.assign(Tine.Calendar.Model.Attender.getDefaultData(), {
          id: id,
          user_type: type,
          user_id: userData
        }),
            attendee = new Tine.Calendar.Model.Attender(attendeeData, id);

        if (fbEvents.length) {
          attendee.set('fbInfo', _.map(fbInfos, function (fbInfo, idx) {
            return fbInfo.getStateOfAttendee(attendee, fbEvents[idx]);
          }).join('<br >'));
        }

        records.push(attendee);
      });
    });

    return {
      success: true,
      records: records,
      totalRecords: totalcount
    };
  }
});
/**
 * @namespace Tine.Calendar.Model
 * @class Tine.Calendar.Model.Resource
 * @extends Tine.Tinebase.data.Record
 * Resource Record Definition
 */

Tine.Calendar.Model.Resource = Tine.Tinebase.data.Record.create(Tine.Tinebase.Model.genericFields.concat([{
  name: 'id'
}, {
  name: 'name'
}, {
  name: 'hierarchy'
}, {
  name: 'description'
}, {
  name: 'email'
}, {
  name: 'max_number_of_people',
  type: 'int'
}, {
  name: 'type',
  type: 'keyField',
  keyFieldConfigName: 'resourceTypes'
}, {
  name: 'status',
  type: 'keyField',
  keyFieldConfigName: 'attendeeStatus'
}, {
  name: 'busy_type',
  type: 'keyField',
  keyFieldConfigName: 'freebusyTypes'
}, {
  name: 'suppress_notification',
  type: 'bool'
}, {
  name: 'tags'
}, {
  name: 'notes'
}, {
  name: 'grants'
}, {
  name: 'attachments'
}, {
  name: 'relations',
  omitDuplicateResolving: true
}, {
  name: 'customfields',
  omitDuplicateResolving: true
}, {
  name: 'color'
}]), {
  appName: 'Calendar',
  modelName: 'Resource',
  idProperty: 'id',
  titleProperty: 'name',
  containerProperty: 'container_id',
  // ngettext('Resource', 'Resources', n); gettext('Resources');
  recordName: 'Resource',
  recordsName: 'Resources',
  initData: function initData() {
    if (Tine.Tinebase.common.hasRight('manage', 'Calendar', 'resources')) {
      var _ = window.lodash;
      account_grants = _.get(this, this.grantsPath, {});

      _.assign(account_grants, {
        'resourceInviteGrant': true,
        'resourceReadGrant': true,
        'resourceEditGrant': true,
        'resourceExportGrant': true,
        'resourceSyncGrant': true,
        'resourceAdminGrant': true
      });

      _.set(this, this.grantsPath, account_grants);
    }
  }
});
/**
 * get default data for a new resource
 *
 * @return {Object} default data
 * @static
 */

Tine.Calendar.Model.Resource.getDefaultData = function () {
  // add admin (and other) grant for resource managers
  var grants = Tine.Tinebase.common.hasRight('manage', 'Calendar', 'resources') ? [{
    account_id: Tine.Tinebase.registry.get('currentAccount').accountId,
    account_type: "user",
    account_name: Tine.Tinebase.registry.get('currentAccount').accountDisplayName,
    'resourceInviteGrant': true,
    'resourceReadGrant': true,
    'resourceEditGrant': true,
    'resourceExportGrant': true,
    'resourceSyncGrant': true,
    'resourceAdminGrant': true
  }] : [];
  grants.push({
    account_id: "0",
    account_type: "anyone",
    account_name: i18n._('Anyone'),
    resourceInviteGrant: true,
    eventsFreebusyGrant: true
  });
  var data = {
    grants: grants
  };
  return data;
};

Tine.Calendar.Model.Resource.getFilterModel = function () {
  var app = Tine.Tinebase.appMgr.get('Calendar');
  return [{
    label: i18n._('Quick Search'),
    field: 'query',
    operators: ['contains']
  }, {
    label: app.i18n._('Name'),
    field: 'name'
  }, {
    label: app.i18n._('Calendar Hierarchy/Name'),
    field: 'hierarchy'
  }, {
    label: app.i18n._('Email'),
    field: 'email'
  }, {
    label: app.i18n._('Description'),
    field: 'description',
    operators: ['contains', 'notcontains']
  }, {
    label: app.i18n._('Maximum number of attendee'),
    field: 'max_number_of_people'
  }, {
    label: app.i18n._('Type'),
    field: 'type',
    filtertype: 'tine.widget.keyfield.filter',
    app: app,
    keyfieldName: 'resourceTypes'
  }, {
    label: app.i18n._('Default attendee status'),
    field: 'status',
    filtertype: 'tine.widget.keyfield.filter',
    app: app,
    keyfieldName: 'attendeeStatus'
  }, {
    label: app.i18n._('Busy Type'),
    field: 'type',
    filtertype: 'tine.widget.keyfield.filter',
    app: app,
    keyfieldName: 'freebusyTypes'
  }, {
    filtertype: 'tinebase.tag',
    app: app
  }];
};
/**
 * @namespace   Tine.Calendar.Model
 * @class       Tine.Calendar.Model.ResourceType
 * @extends     Tine.Tinebase.data.Record
 * ResourceType Record Definition
 */


Tine.Calendar.Model.ResourceType = Tine.Tinebase.data.Record.create([{
  name: 'id'
}, {
  name: 'is_location'
}, {
  name: 'value'
}, {
  name: 'icon'
}, {
  name: 'color'
}, {
  name: 'system'
}], {
  appName: 'Calendar',
  modelName: 'ResourceType',
  idProperty: 'id'
});
/**
 * @namespace   Tine.Calendar.Model
 * @class       Tine.Calendar.Model.iMIP
 * @extends     Tine.Tinebase.data.Record
 * iMIP Record Definition
 */

Tine.Calendar.Model.iMIP = Tine.Tinebase.data.Record.create([{
  name: 'id'
}, {
  name: 'ics'
}, {
  name: 'method'
}, {
  name: 'originator'
}, {
  name: 'userAgent'
}, {
  name: 'event'
}, {
  name: 'existing_event'
}, {
  name: 'preconditions'
}], {
  appName: 'Calendar',
  modelName: 'iMIP',
  idProperty: 'id'
});

/***/ }),

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

/*
 * Tine 2.0
 *
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2018 Metaways Infosystems GmbH (http://www.metaways.de)
 */

/**
 * Model of a grant
 */
Tine.Calendar.Model.ResourceGrants = Tine.Tinebase.data.Record.create([{
  name: 'id'
}, {
  name: 'account_id'
}, {
  name: 'account_type'
}, {
  name: 'account_name'
}, {
  name: 'resourceInviteGrant',
  type: 'boolean'
}, {
  name: 'resourceReadGrant',
  type: 'boolean'
}, {
  name: 'resourceEditGrant',
  type: 'boolean'
}, {
  name: 'resourceExportGrant',
  type: 'boolean'
}, {
  name: 'resourceSyncGrant',
  type: 'boolean'
}, {
  name: 'resourceAdminGrant',
  type: 'boolean'
}, {
  name: 'eventsAddGrant',
  type: 'boolean'
}, {
  name: 'eventsReadGrant',
  type: 'boolean'
}, {
  name: 'eventsExportGrant',
  type: 'boolean'
}, {
  name: 'eventsSyncGrant',
  type: 'boolean'
}, {
  name: 'eventsFreebusyGrant',
  type: 'boolean'
}, {
  name: 'eventsEditGrant',
  type: 'boolean'
}, {
  name: 'eventsDeleteGrant',
  type: 'boolean'
}], {
  appName: 'Calendar',
  modelName: 'ResourceGrants',
  idProperty: 'id',
  titleProperty: 'account_name',
  // ngettext('Resource Grant', 'Resource Grants', n); gettext('Resource Grant');
  recordName: 'Resource Grant',
  recordsName: 'Resource Grants'
}); // register grants for calendar containers

Tine.widgets.container.GrantsManager.register('Calendar_Model_Event', function (container) {
  var _ = window.lodash,
      me = this,
      grantsModelName = _.get(container, 'xprops.Tinebase.Container.GrantsModel', 'Tinebase_Model_Grants');

  if (grantsModelName == 'Calendar_Model_ResourceGrants') {
    // resource events container
    return ['resourceInvite', 'resourceRead', 'resourceEdit', // 'resourceExport', // should be resource-admin?
    // 'resourceSync',   // no sync targets - let's save space
    'resourceAdmin', // not yet used? - let's save space
    'eventsAdd', 'eventsRead', 'eventsExport', 'eventsSync', 'eventsFreebusy', 'eventsEdit', 'eventsDelete'];
  } else {
    var grants = Tine.widgets.container.GrantsManager.defaultGrants(container); // normal events container

    if (container.type == 'personal') {
      grants.push('freebusy');
    }

    if (container.type == 'personal' && container.capabilites_private) {
      grants.push('private');
    }

    return grants;
  }
});
Ext.override(Tine.widgets.container.GrantsGrid, {
  resourceInviteGrantTitle: 'Invite Resource',
  // i18n._('Invite Resource')
  resourceInviteGrantDescription: 'The grant to invite the resource to an event',
  // i18n._('The grant to invite the resource to an event')
  resourceReadGrantTitle: 'Read Resource',
  // i18n._('Read Resource')
  resourceReadGrantDescription: 'The grant to read the resource itself',
  // i18n._('The grant to read the resource itself')
  resourceEditGrantTitle: 'Edit Resource',
  // i18n._('Edit Resource')
  resourceEditGrantDescription: 'The grant to edit the resource itself',
  // i18n._('The grant to edit the resource itself')
  resourceExportGrantTitle: 'Export Resource',
  // i18n._('Export Resource')
  resourceExportGrantDescription: 'The grant to export the resource itself',
  // i18n._('The grant to export the resource itself')
  resourceSyncGrantTitle: 'Sync Resource',
  // i18n._('Sync Resource')
  resourceSyncGrantDescription: 'The grant to synchronise the resource itself',
  // i18n._('The grant to synchronise the resource itself')
  resourceAdminGrantTitle: 'Resource Admin',
  // i18n._('Resource Admin')
  resourceAdminGrantDescription: 'The grant to administrate the resource itself',
  // i18n._('The grant to administrate the resource itself')
  eventsAddGrantTitle: 'Add Events',
  // i18n._('Add Events')
  eventsAddGrantDescription: 'The grant to directly add events into this resource calendar',
  // i18n._('The grant to directly add events into this resource calendar')
  eventsReadGrantTitle: 'Read Events',
  // i18n._('Read Events')
  eventsReadGrantDescription: 'The grant to read events from this resource calendar',
  // i18n._('The grant to read events from this resource calendar')
  eventsExportGrantTitle: 'Export Events',
  // i18n._('Export Events')
  eventsExportGrantDescription: 'The grant to export events from this resource calendar',
  // i18n._('The grant to export events from this resource calendar')
  eventsSyncGrantTitle: 'Sync Events',
  // i18n._('Sync Events')
  eventsSyncGrantDescription: 'The grant to synchronise events from this resource calendar. Needs the grant read events',
  // i18n._('The grant to synchronise events from this resource calendar. Need Read Events Grant')
  eventsFreebusyGrantTitle: 'Events Free Busy',
  // i18n._('Events Free Busy')
  eventsFreebusyGrantDescription: 'The grant to get free/busy information of events from this resource calendar',
  // i18n._('The grant to get free/busy information of events from this resource calendar')
  eventsEditGrantTitle: 'Edit Events',
  // i18n._('Edit Events')
  eventsEditGrantDescription: 'The grant to respond to event invitations of this resource and to edit events directly saved in this resource calendar',
  // i18n._('The grant to respond to event invitations of this resource and to edit events directly saved in this resource calendar')
  eventsDeleteGrantTitle: 'Delete Events',
  // i18n._('Delete Events')
  eventsDeleteGrantDescription: 'The grant to delete events directly stored in this resource calendar',
  // i18n._('The grant to delete events directly stored in this resource calendar')
  freebusyGrantTitle: 'Free Busy',
  // i18n._('Free Busy')
  freebusyGrantDescription: 'The grant to get free/busy information of events in this calendar',
  // i18n._('The grant to get free/busy information of events in this calendar')
  privateGrantTitle: 'Private',
  // i18n._('Private')
  privateGrantDescription: 'The grant to access events marked as private in this calendar' // i18n._('The grant to access events marked as private in this calendar')

});

/***/ }),

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

/*
 * Tine 2.0
 * 
 * @package     Calendar
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Philipp Schuele <p.schuele@metaways.de>
 * @copyright   Copyright (c) 2009 Metaways Infosystems GmbH (http://www.metaways.de)
 *
 */
Ext.namespace('Tine.Calendar');
/**
 * admin settings panel
 * 
 * @namespace   Tine.Calendar
 * @class       Tine.Calendar.AdminPanel
 * @extends     Ext.TabPanel
 * 
 * <p>Calendar Admin Panel</p>
 * <p><pre>
 * </pre></p>
 * 
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Philipp Schuele <p.schuele@metaways.de>
 * @copyright   Copyright (c) 2009 Metaways Infosystems GmbH (http://www.metaways.de)
 * 
 * @param       {Object} config
 * @constructor
 * Create a new Tine.Calendar.AdminPanel
 */

Tine.Calendar.AdminPanel = Ext.extend(Ext.TabPanel, {
  border: false,
  activeTab: 0,

  /**
   * @private
   */
  initComponent: function initComponent() {
    this.app = Tine.Tinebase.appMgr.get('Calendar');
    this.items = [new Tine.Calendar.ResourceGridPanel({
      title: this.app.i18n._('Manage Resources'),
      disabled: !Tine.Tinebase.common.hasRight('manage_resources', 'Calendar')
    }), new Tine.Admin.config.GridPanel({
      configApp: this.app
    })];
    Tine.Calendar.AdminPanel.superclass.initComponent.call(this);
  }
});
/**
 * Calendar Admin Panel Popup
 * 
 * @param   {Object} config
 * @return  {Ext.ux.Window}
 */

Tine.Calendar.AdminPanel.openWindow = function (config) {
  var window = Tine.WindowFactory.getWindow({
    width: 600,
    height: 470,
    name: 'cal-mange-resources',
    contentPanelConstructor: 'Tine.Calendar.AdminPanel',
    contentPanelConstructorConfig: config
  });
};

/***/ }),

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

/* 
 * Tine 2.0
 * 
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2009 Metaways Infosystems GmbH (http://www.metaways.de)
 */
Date.msSECOND = 1000;
Date.msMINUTE = 60 * Date.msSECOND;
Date.msHOUR = 60 * Date.msMINUTE;
Date.msDAY = 24 * Date.msHOUR;
Date.msWEEK = 7 * Date.msDAY;
Ext.ns('Tine.Calendar');
/**
 * @class Tine.Calendar.CalendarPanel
 * @namespace Tine.Calendar
 * @extends Ext.Panel
 * @author Cornelius Weiss <c.weiss@metaways.de>
 */

Tine.Calendar.CalendarPanel = Ext.extend(Ext.Panel, {
  /**
   * @cfg {Tine.Calendar.someView} view
   */
  view: null,
  border: false,
  layout: 'fit',
  autoScroll: false,
  autoWidth: false,

  /**
   * @private
   */
  initComponent: function initComponent() {
    this.items = this.view; // init plugins

    this.plugins = Ext.isString(this.plugins) ? Ext.decode(this.plugins) : Ext.isArray(this.plugins) ? this.plugins.concat(Ext.decode(this.initialConfig.plugins)) : [];
    Tine.Calendar.CalendarPanel.superclass.initComponent.call(this);
    this.relayEvents(this.view, ['changeView', 'changePeriod', 'click', 'dblclick', 'contextmenu', 'keydown']);
  },

  /**
   * Returns selection model
   * 
   * @deprecated
   * @return {Tine.Calendar.EventSelectionModel}
   */
  getSelectionModel: function getSelectionModel() {
    return this.getView().getSelectionModel();
  },

  /**
   * Returns data store
   * 
   * @deprecated
   * @return {Ext.data.Store}
   */
  getStore: function getStore() {
    return this.getView().store;
  },

  /**
   * Retruns calendar View
   * 
   * @return {Tine.Calendar.View}
   */
  getView: function getView() {
    return this.view;
  }
});

/***/ }),

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

/*
 * Tine 2.0
 *
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2017 Metaways Infosystems GmbH (http://www.metaways.de)
 */
Ext.ns('Tine.Calendar');
/**
 * @namespace   Tine.Calendar
 * @class       Tine.Calendar.AbstractView
 * @extends     Ext.Container
 *
 * Calendar abstract view
 *
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @constructor
 * @param {Object} config
 */

Tine.Calendar.AbstractView = Ext.extend(Ext.Container, {
  /**
   * @cfg {String} eventCls
   * css class of event ui
   */
  eventCls: '-evnet',
  initComponent: function initComponent() {
    this.initTemplates();
    this.initData(this.store);

    if (!this.selModel) {
      this.selModel = new Tine.Calendar.EventSelectionModel();
    }

    if (Ext.isFunction(this.unbufferedOnLayout)) {
      this.onLayout = Function.createBuffered(this.unbufferedOnLayout, 100, this);
    }

    Tine.Calendar.AbstractView.superclass.initComponent.apply(this, arguments);
  },

  /**
   * @private
   * @param {Ext.data.Store} ds
   */
  initData: function initData(ds) {
    if (this.store) {
      this.store.un("load", this.onLoad, this);
      this.store.un("beforeload", this.onBeforeLoad, this);
      this.store.un("add", this.onAdd, this);
      this.store.un("remove", this.onRemove, this);
      this.store.un("update", this.onUpdate, this);
    }

    if (ds) {
      ds.on("load", this.onLoad, this);
      ds.on("beforeload", this.onBeforeLoad, this);
      ds.on("add", this.onAdd, this);
      ds.on("remove", this.onRemove, this);
      ds.on("update", this.onUpdate, this);
    }

    this.store = ds;
  },

  /**
   * fill the events into the view
   */
  afterRender: function afterRender() {
    Tine.Calendar.AbstractView.superclass.afterRender.apply(this, arguments);
    this.mon(this.el, 'click', this.onClick, this);
    this.mon(this.el, 'dblclick', this.onDblClick, this);
    this.mon(this.el, 'contextmenu', this.onContextMenu, this);
    this.mon(this.el, 'keydown', this.onKeyDown, this);
    this.getSelectionModel().init(this);
  },
  onBeforeLoad: function onBeforeLoad(store, options) {
    if (options.autoRefresh && this.editing) {
      return false;
    }

    if (!options.refresh) {
      this.removeAllEvents();
    }
  },

  /**
   * @private
   */
  onLoad: function onLoad() {
    if (!this.rendered) {
      return;
    } // remove old events


    this.clearAll();
    this.initParallelEventRegistry();
    this.store.fields = Tine.Calendar.Model.Event.prototype.fields;
    this.store.sortInfo = {
      field: 'dtstart',
      direction: 'ASC'
    };
    this.store.applySort();
    this.store.each(function (event) {
      this.getParallelEventRegistry(event).register(event);
    }, this); // put the events in

    this.store.each(this.insertEvent, this);
    this.onLayout();
  },

  /**
   * @private
   */
  onAdd: function onAdd(ds, records, index) {
    for (var i = 0; i < records.length; i++) {
      var event = records[i];
      this.getParallelEventRegistry(event).register(event);
      var parallelEvents = this.getParallelEventRegistry(event).getEvents(event.get('dtstart'), event.get('dtend'));

      for (var j = 0; j < parallelEvents.length; j++) {
        this.removeEvent(parallelEvents[j]);
        this.insertEvent(parallelEvents[j]);
      }
    }

    this.onLayout();
  },

  /**
   * @private
   */
  onUpdate: function onUpdate(ds, event) {
    // don't update events while being created
    if (event.get('id').match(/new/)) {
      return;
    }

    var originalRegistry = this.getParallelEventRegistry(event, true);
    var originalDtstart = event.modified.hasOwnProperty('dtstart') ? event.modified.dtstart : event.get('dtstart');
    var originalDtend = event.modified.hasOwnProperty('dtend') ? event.modified.dtend : event.get('dtend');
    var originalParallels = originalRegistry.getEvents(originalDtstart, originalDtend);

    for (var j = 0; j < originalParallels.length; j++) {
      this.removeEvent(originalParallels[j]);
    }

    originalRegistry.unregister(event);
    var originalParallels = originalRegistry.getEvents(originalDtstart, originalDtend);

    for (var j = 0; j < originalParallels.length; j++) {
      this.insertEvent(originalParallels[j]);
    } // relayout actual context


    var registry = this.getParallelEventRegistry(event);
    var parallelEvents = registry.getEvents(event.get('dtstart'), event.get('dtend'));

    for (var j = 0; j < parallelEvents.length; j++) {
      this.removeEvent(parallelEvents[j]);
    }

    registry.register(event);
    var parallelEvents = registry.getEvents(event.get('dtstart'), event.get('dtend'));

    for (var j = 0; j < parallelEvents.length; j++) {
      this.insertEvent(parallelEvents[j]);
    }

    this.onLayout();
  },

  /**
   * @private
   */
  onRemove: function onRemove(ds, event, index, isUpdate) {
    if (!event || index == -1) {
      return;
    }

    this.removeEvent(event);
    var registry = this.getParallelEventRegistry(event);
    var parallelEvents = registry.getEvents(event.get('dtstart'), event.get('dtend'));

    for (var j = 0; j < parallelEvents.length; j++) {
      this.removeEvent(parallelEvents[j]);
    }

    this.getParallelEventRegistry(event).unregister(event);
    var parallelEvents = registry.getEvents(event.get('dtstart'), event.get('dtend'));

    for (var j = 0; j < parallelEvents.length; j++) {
      this.insertEvent(parallelEvents[j]);
    }

    this.onLayout();
  },
  getParallelEventRegistry: function getParallelEventRegistry(event, original) {
    return this.parallelEventRegistry;
  },
  initParallelEventRegistry: function initParallelEventRegistry(event) {
    this.parallelEventRegistry = new Tine.Calendar.ParallelEventsRegistry({
      dtStart: this.period.from,
      dtEnd: this.period.until
    });
  },

  /**
   * removes all events from store
   */
  removeAllEvents: function removeAllEvents() {
    this.store.each(function (event) {
      if (event.ui) {
        event.ui.remove();
      }
    });
  },

  /**
   * remove all events from dom
   */
  clearAll: function clearAll() {
    var els = this.el.query('.' + this.eventCls);
    Ext.each(els, function (el) {
      el.remove();
    });
  },

  /**
   * removes a event from the dom
   * @param {Tine.Calendar.Model.Event} event
   */
  removeEvent: function removeEvent(event) {
    if (this.editing == event) {
      this.abortCreateEvent(event);
    }

    if (event.ui) {
      event.ui.remove();
    }

    this.onLayout();
  },
  replaceEvent: function replaceEvent(event) {
    this.removeEvent(event);
    this.insertEvent(event);
  },
  onClick: function onClick(e) {
    var event = this.getTargetEvent(e);

    if (event) {
      this.fireEvent('click', event, e);
    }
  },
  onDblClick: function onDblClick(e, target) {
    e.stopEvent();
    var event = this.getTargetEvent(e);

    if (event) {
      this.fireEvent('dblclick', event, e);
    }
  },
  onContextMenu: function onContextMenu(e) {
    this.fireEvent('contextmenu', e);
  },
  onKeyDown: function onKeyDown(e) {
    this.fireEvent("keydown", e);
  },

  /**
   * gets event el of target
   *
   * @param {Ext.EventObject} e
   * @return {Tine.Calendar.Model.Event}
   */
  getTargetEvent: function getTargetEvent(e) {
    var target = e.getTarget();
    var el = Ext.fly(target);

    if (el.hasClass(this.eventCls) || (el = el.up('[id*=event:]', 10))) {
      var parts = el.dom.id.split(':');
      parts.shift();
      return this.store.getById(parts.join(':'));
    }
  },

  /**
   * returns the selectionModel of the active panel
   * @return {}
   */
  getSelectionModel: function getSelectionModel() {
    return this.selModel;
  },
  hex2dec: function hex2dec(hex) {
    var dec = 0;
    hex = hex.toString();
    var length = hex.length,
        multiplier,
        digit;

    for (var i = 0; i < length; i++) {
      multiplier = Math.pow(16, Math.abs(i - hex.length) - 1);
      digit = parseInt(hex.toString().charAt([i]), 10);

      if (isNaN(digit)) {
        switch (hex.toString().charAt([i]).toUpperCase()) {
          case 'A':
            digit = 10;
            break;

          case 'B':
            digit = 11;
            break;

          case 'C':
            digit = 12;
            break;

          case 'D':
            digit = 13;
            break;

          case 'E':
            digit = 14;
            break;

          case 'F':
            digit = 15;
            break;

          default:
            return NaN;
        }
      }

      dec = dec + multiplier * digit;
    }

    return dec;
  },
  beforeDestroy: function beforeDestroy() {
    this.removeAllEvents();
    this.initData(false);
    this.purgeListeners();
    Tine.Calendar.AbstractView.superclass.beforeDestroy.apply(this, arguments);
  }
});

/***/ }),

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

/*
 * Tine 2.0
 * 
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2007-2016 Metaways Infosystems GmbH (http://www.metaways.de)
 * 
 */
Ext.ns('Tine.Calendar');

Tine.Calendar.EventUI = function (event) {
  this.event = event;
  this.domIds = [];
  this.app = Tine.Tinebase.appMgr.get('Calendar');
  this.init();
};

Tine.Calendar.EventUI.prototype = {
  zIndex: 100,
  addClass: function addClass(cls) {
    Ext.each(this.getEls(), function (el) {
      el.addClass(cls);
    });
  },
  removeClass: function removeClass(cls) {
    Ext.each(this.getEls(), function (el) {
      el.removeClass(cls);
    });
  },
  focus: function focus() {
    Ext.each(this.getEls(), function (el) {
      el.focus();
    });
  },
  blur: function blur() {
    Ext.each(this.getEls(), function (el) {
      el.blur();
    });
  },
  clearDirty: function clearDirty() {
    this.setOpacity(1, 1);
  },
  setStyle: function setStyle(style) {
    Ext.each(this.getEls(), function (el) {
      el.setStyle(style);
    });
  },
  getStyle: function getStyle(property) {
    var value;
    Ext.each(this.getEls(), function (el) {
      value = el.getStyle(property);
      return false;
    });
    return value;
  },
  setOpacity: function setOpacity(v, a) {
    Ext.each(this.getEls(), function (el) {
      el.setOpacity(v, a);
    });
  },

  /**
   * returns events dom
   * @return {Array} of Ext.Element
   */
  getEls: function getEls() {
    var domEls = [];

    for (var i = 0; i < this.domIds.length; i++) {
      var el = Ext.get(this.domIds[i]);

      if (el) {
        domEls.push(el);
      }
    }

    return domEls;
  },
  init: function init() {// shortcut
    //this.colMgr = Tine.Calendar.colorMgr;
  },
  markDirty: function markDirty() {
    this.setOpacity(0.5, 1);
  },
  markOutOfFilter: function markOutOfFilter() {
    Ext.each(this.getEls(), function (el) {
      el.setOpacity(0.5, 0);
      el.setStyle({
        'background-color': '#aaa',
        'border-color': '#888'
      });
      Ext.DomHelper.applyStyles(el.dom.firstChild, {
        'background-color': '#888'
      });

      if (el.dom.firstChild.firstChild) {
        Ext.DomHelper.applyStyles(el.dom.firstChild.firstChild, {
          'background-color': '#888'
        });
      }

      if (_.get(el, 'dom.firstChild.children[1]')) {
        Ext.DomHelper.applyStyles(_.get(el, 'dom.firstChild.children[1]'), {
          'background-color': '#888'
        });
      }
    });
  },
  onSelectedChange: function onSelectedChange(state) {
    if (state) {
      //this.focus();
      this.addClass('cal-event-active');
      this.setStyle({
        'z-index': 1000
      });
    } else {
      //this.blur();
      this.removeClass('cal-event-active');
      this.setStyle({
        'z-index': this.zIndex
      });
    }
  },

  /**
   * removes a event from the dom
   */
  remove: function remove() {
    var eventEls = this.getEls();

    for (var i = 0; i < eventEls.length; i++) {
      if (eventEls[i] && typeof eventEls[i].remove == 'function') {
        eventEls[i].remove();
      }
    }

    if (this.resizeable) {
      this.resizeable.destroy();
      this.resizeable = null;
    }

    this.domIds = [];
  },
  render: function render(view) {
    this.event.view = view;
    this.attendeeRecord = view.ownerCt && view.ownerCt.attendee ? Tine.Calendar.Model.Attender.getAttendeeStore.getAttenderRecord(this.event.getAttendeeStore(), view.ownerCt.attendee) : this.event.getMyAttenderRecord();
    this.colorSet = Tine.Calendar.colorMgr.getColor(this.event, this.attendeeRecord);
    this.event.colorSet = this.colorSet;
    this.infoBarColors = Tine.Calendar.colorMgr.getInfoBarStrategy().getColors(this.event);
    this.dtStart = this.event.get('dtstart');
    this.dtEnd = this.event.get('dtend'); // 00:00 in users timezone is a spechial case where the user expects
    // something like 24:00 and not 00:00

    if (this.dtEnd.format('H:i') == '00:00') {
      this.dtEnd = this.dtEnd.add(Date.MINUTE, -1);
    }

    if (this.event.get('editGrant')) {
      this.extraCls = 'cal-daysviewpanel-event-editgrant';
    }

    this.extraCls += ' cal-status-' + this.event.get('status');

    if (this.event.hasPoll()) {
      this.extraCls += ' cal-poll-event';
    } // compute status icons


    this.statusIcons = Tine.Calendar.EventUI.getStatusInfo(this.event, this.attendeeRecord);
  }
};

Tine.Calendar.EventUI.getStatusInfo = function (event, attendeeRecord) {
  var _ = window.lodash,
      app = Tine.Tinebase.appMgr.get('Calendar'),
      statusInfo = [];

  if (event.get('class') === 'PRIVATE') {
    statusInfo.push({
      status: 'private',
      text: app.i18n._('private classification')
    });
  }

  if (event.get('rrule')) {
    statusInfo.push({
      status: 'recur',
      text: app.i18n._('recurring event')
    });
  } else if (event.isRecurException()) {
    statusInfo.push({
      status: 'recurex',
      text: app.i18n._('recurring event exception')
    });
  }

  if (!Ext.isEmpty(event.get('alarms'))) {
    statusInfo.push({
      status: 'alarm',
      text: app.i18n._('has alarm')
    });
  }

  if (!Ext.isEmpty(event.get('attachments'))) {
    statusInfo.push({
      status: 'attachment',
      text: app.i18n._('has attachments')
    });
  }

  if (event.hasPoll()) {
    statusInfo.push({
      status: 'poll',
      text: app.i18n._('is part of an open poll')
    });
  }

  var attenderStatusRecord = attendeeRecord ? Tine.Tinebase.widgets.keyfield.StoreMgr.get('Calendar', 'attendeeStatus').getById(attendeeRecord.get('status')) : null;

  if (attenderStatusRecord && attenderStatusRecord.get('system')) {
    statusInfo.push({
      status: attendeeRecord.get('status'),
      text: attenderStatusRecord.get('i18nValue')
    });
  }

  return statusInfo;
};

/***/ }),

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

/*
 * Tine 2.0
 *
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2007-2016 Metaways Infosystems GmbH (http://www.metaways.de)
 */
Ext.ns('Tine.Calendar');
Tine.Calendar.DaysViewEventUI = Ext.extend(Tine.Calendar.EventUI, {
  clearDirty: function clearDirty() {
    Tine.Calendar.DaysViewEventUI.superclass.clearDirty.call(this);
    Ext.each(this.getEls(), function (el) {
      el.setStyle({
        'border-left-style': 'solid'
      });
    });
  },

  /**
   * get diff of resizeable
   *
   * @param {Ext.Resizeable} rz
   */
  getRzInfo: function getRzInfo(rz, width, height) {
    var rzInfo = {};
    var event = rz.event;
    var view = event.view; // NOTE proxy might be gone after resize

    var box = rz.proxy.getBox();
    var width = width ? width : box.width;
    var height = height ? height : box.height;
    var originalDuration = (event.get('dtend').getTime() - event.get('dtstart').getTime()) / Date.msMINUTE;

    if (event.get('is_all_day_event')) {
      var dayWidth = Ext.fly(view.wholeDayArea).getWidth() / view.numOfDays;
      rzInfo.diff = Math.round((width - rz.originalWidth) / dayWidth);
    } else {
      rzInfo.diff = view.getHeightMinutes(height - rz.originalHeight); // neglegt diffs due to borders etc.

      rzInfo.diff = Math.ceil(rzInfo.diff / view.timeIncrement) * view.timeIncrement;
    }

    rzInfo.duration = originalDuration + rzInfo.diff;

    if (event.get('is_all_day_event')) {
      rzInfo.dtend = event.get('dtend').add(Date.DAY, rzInfo.diff);
    } else {
      rzInfo.dtend = event.get('dtstart').add(Date.MINUTE, rzInfo.duration);
    }

    return rzInfo;
  },
  markDirty: function markDirty() {
    Tine.Calendar.DaysViewEventUI.superclass.markDirty.call(this);
    Ext.each(this.getEls(), function (el) {
      el.setStyle({
        'border-left-style': 'dashed'
      });
    });
  },
  render: function render(view) {
    Tine.Calendar.DaysViewEventUI.superclass.render.call(this, view);
    this.startColNum = view.getColumnNumber(this.dtStart);
    this.endColNum = view.getColumnNumber(this.dtEnd); // skip dates not in our diplay range

    if (this.endColNum < 0 || this.startColNum > view.numOfDays - 1) {
      return;
    }

    var registry = this.event.get('is_all_day_event') ? view.parallelWholeDayEventsRegistry : view.parallelScrollerEventsRegistry;
    var position = registry.getPosition(this.event);
    var maxParallels = registry.getMaxParalles(this.dtStart, this.dtEnd);

    if (this.event.get('is_all_day_event')) {
      this.renderAllDayEvent(view, maxParallels, position);
    } else {
      this.renderScrollerEvent(view, maxParallels, position);
    }

    var ids = Tine.Tinebase.data.Clipboard.getIds('Calendar', 'Event');

    if (ids.indexOf(this.event.get('id')) > -1) {
      this.markDirty(true);
    } else if (this.event.dirty) {
      // the event was selected before
      this.onSelectedChange(true);
    }

    this.rendered = true;
  },
  renderAllDayEvent: function renderAllDayEvent(view, parallels, pos) {
    // lcocal COPY!
    var extraCls = this.extraCls;
    var offsetWidth = Ext.fly(view.wholeDayArea).getWidth(); //var width = Math.round(offsetWidth * (this.dtEnd.getTime() - this.dtStart.getTime()) / (view.numOfDays * Date.msDAY)) -5;
    //var left = Math.round(offsetWidth * (this.dtStart.getTime() - view.startDate.getTime()) / (view.numOfDays * Date.msDAY));

    var width = Math.floor(1000 * (this.dtEnd.getTime() - this.dtStart.getTime()) / (view.numOfDays * Date.msDAY) - 5) / 10;
    var left = 100 * (this.dtStart.getTime() - view.startDate.getTime()) / (view.numOfDays * Date.msDAY);

    if (left < 0) {
      width = width + left;
      left = 0;
      extraCls = extraCls + ' cal-daysviewpanel-event-cropleft';
    }

    if (left + width > offsetWidth) {
      width = offsetWidth - left;
      extraCls = extraCls + ' cal-daysviewpanel-event-cropright';
    }

    var domId = Ext.id() + '-event:' + this.event.get('id');
    this.domIds.push(domId);
    var eventEl = view.templates.wholeDayEvent.insertFirst(view.wholeDayArea, {
      id: domId,
      tagsHtml: Tine.Tinebase.common.tagsRenderer(this.event.get('tags')),
      summary: this.event.getTitle(),
      startTime: this.dtStart.format('H:i'),
      extraCls: extraCls,
      color: this.colorSet.color,
      bgColor: this.colorSet.light,
      textColor: this.colorSet.text,
      zIndex: 100,
      width: width + '%',
      height: '15px',
      left: left + '%',
      top: pos * 18 + 'px',
      //'1px'
      statusIcons: this.statusIcons
    }, true);

    if (this.event.dirty) {
      eventEl.setStyle({
        'border-left-style': 'dashed'
      });
      eventEl.setOpacity(0.5);
    }

    if (!(this.endColNum > view.numOfDays) && this.event.get('editGrant') && !view.readOnly) {
      this.resizeable = new Ext.Resizable(eventEl, {
        handles: 'e',
        disableTrackOver: true,
        dynamic: true,
        //dynamic: !!this.event.isRangeAdd,
        widthIncrement: Math.round(offsetWidth / view.numOfDays),
        minWidth: Math.round(offsetWidth / view.numOfDays),
        listeners: {
          scope: view,
          resize: view.onEventResize,
          beforeresize: view.onBeforeEventResize
        }
      });
    } //console.log([eventEl.dom, parallels, pos])

  },
  renderScrollerEvent: function renderScrollerEvent(view, parallels, pos) {
    var mainBodyHeight = view.getMainBodyHeight();

    for (var currColNum = this.startColNum; currColNum <= this.endColNum; currColNum++) {
      if (currColNum < 0 || currColNum >= view.numOfDays) {
        continue;
      }

      var domId = Ext.id() + '-event:' + this.event.get('id'),
          extraCls = this.extraCls,
          top = view.getTimeOffsetPct(this.dtStart),
          height = this.startColNum == this.endColNum ? view.getTimeHeightPct(this.dtStart, this.dtEnd) : view.getTimeOffsetPct(this.dtEnd),
          isShortEvent = height * mainBodyHeight / 100 < 24;
      this.domIds.push(domId);

      if (currColNum != this.startColNum) {
        top = 0;
        extraCls = extraCls + ' cal-daysviewpanel-event-croptop';
      }

      if (this.endColNum != currColNum) {
        height = view.getTimeHeightPct(this.dtStart, this.dtStart.add(Date.DAY, 1));
        extraCls = extraCls + ' cal-daysviewpanel-event-cropbottom';
      }

      var eventEl = view.templates.event.append(view.getDateColumnEl(currColNum), {
        id: domId,
        summary: isShortEvent ? '' : this.event.getTitle(),
        tagsHtml: isShortEvent ? '' : Tine.Tinebase.common.tagsRenderer(this.event.get('tags')),
        startTime: isShortEvent ? this.dtStart.format('H:i') + ' ' + this.event.getTitle() : this.dtStart.format('H:i'),
        extraCls: extraCls,
        color: this.colorSet.color,
        bgColor: this.colorSet.light,
        textColor: this.colorSet.text,
        infoColors: this.createBorderColors(this.infoBarColors),
        zIndex: 100,
        height: height + '%',
        left: Math.round(pos * 90 * 1 / parallels) + '%',
        width: Math.round(90 * 1 / parallels) + '%',
        top: top + '%',
        statusIcons: this.statusIcons
      }, true);

      if (this.event.dirty) {
        eventEl.setStyle({
          'border-left-style': 'dashed'
        });
        eventEl.setOpacity(0.5);
      }

      if (currColNum == this.endColNum && this.event.get('editGrant') && !view.readOnly) {
        this.resizeable = new Ext.Resizable(eventEl, {
          handles: 's',
          disableTrackOver: true,
          dynamic: true,
          minHeight: view.getTimeOffset(view.timeGranularity),
          heightIncrement: view.getTimeOffset(view.timeGranularity),
          resizeElement: function resizeElement() {
            return this.proxy.getBox();
          },
          listeners: {
            scope: view,
            resize: view.onEventResize,
            beforeresize: view.onBeforeEventResize
          }
        });
      }
    }
  },
  createBorderColors: function createBorderColors(colors) {
    if (colors.length === 0) {
      return 'linear-gradient(to bottom, rgb(210, 210, 210) 0%, rgb(210, 210, 210) 100%) 0 0 0 3';
    }

    let out = 'linear-gradient(to bottom';
    let pct = 100 / colors.length;
    let c = 0;

    _.forEach(colors, function (color) {
      color = color.replace('#', '');
      let r = parseInt(color.substr(0, 2), 16),
          g = parseInt(color.substr(2, 2), 16),
          b = parseInt(color.substr(4, 2), 16),
          rgb = 'rgb(' + r + ', ' + g + ', ' + b + ')';
      out += ', ' + rgb + ' ' + c * pct + '%';
      c++;
      out += ', ' + rgb + ' ' + c * pct + '%';
    });

    return out + ') 0 0 0 3 stretch';
  },
  onSelectedChange: function onSelectedChange(state) {
    Tine.Calendar.MonthViewEventUI.superclass.onSelectedChange.call(this, state);
    var style = {
      'background-color': state ? this.colorSet.color : this.colorSet.light,
      'color': state ? this.colorSet.text : '#000000'
    };
    Ext.each(this.getEls(), function (el) {
      el.setStyle(style);
      el.select('div[class^=cal-daysviewpanel-event-header]').setStyle(style);
      el.select('.cal-status-icon').each(img => {
        let status = img.dom.className.match(/([-a-zA-Z]+)-(?:black|white)/)[1];
        img.removeClass([status + '-black', status + '-white']);
        img.addClass(status + (style.color === '#FFFFFF' ? '-white' : '-black'));
      });
    }, this);
  }
});

/***/ }),

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

/*
 * Tine 2.0
 *
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2007-2016 Metaways Infosystems GmbH (http://www.metaways.de)
 */
Ext.ns('Tine.Calendar');
Tine.Calendar.MonthViewEventUI = Ext.extend(Tine.Calendar.EventUI, {
  onSelectedChange: function onSelectedChange(state) {
    Tine.Calendar.MonthViewEventUI.superclass.onSelectedChange.call(this, state);

    if (state) {
      this.addClass('cal-monthview-active');
      this.setStyle({
        'background-color': this.color,
        'color': this.colorSet ? this.colorSet.text : '#000000'
      });
    } else {
      this.removeClass('cal-monthview-active');
      this.setStyle({
        'background-color': this.is_all_day_event ? this.bgColor : '',
        'color': this.is_all_day_event ? '#000000' : this.color
      });
    }
  }
});
Tine.Calendar.YearViewEventUI = Ext.extend(Tine.Calendar.EventUI, {
  onSelectedChange: function onSelectedChange(state) {
    Tine.Calendar.YearViewEventUI.superclass.onSelectedChange.call(this, state);

    if (state) {
      this.addClass('cal-yearview-active');
      this.setStyle({
        'background-color': this.color,
        'color': this.colorSet ? this.colorSet.text : '#000000'
      });
    } else {
      this.removeClass('cal-yearview-active');
      this.setStyle({
        'background-color': this.is_all_day_event ? this.bgColor : '',
        'color': this.is_all_day_event ? '#000000' : this.color
      });
    }
  }
});

/***/ }),

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

/* 
 * Tine 2.0
 * 
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2007-2008 Metaways Infosystems GmbH (http://www.metaways.de)
 */
Ext.ns('Tine.Calendar');
/**
 * @namespace Tine.Calendar
 * @class Tine.Calendar.EventSelectionModel
 * @extends Ext.tree.MultiSelectionModel
 * Selection model for a calendar views.
 */

Tine.Calendar.EventSelectionModel = Ext.extend(Ext.tree.MultiSelectionModel, {
  init: function init(view) {
    view.getTreeEl = function () {
      return view.el;
    };

    view.el.on("keydown", this.onKeyDown, this);
    view.on("click", this.onNodeClick, this); // since 3.1 it requires a mon fn
    //Tine.Calendar.EventSelectionModel.superclass.init.call(this, view);
  },

  /**
   * Gets the number of selected events.
   * @return {Number}
   */
  getCount: function getCount() {
    return this.getSelectedNodes().length;
  },

  /**
   * Returns the first selected event.
   * @return {Record}
   */
  getSelected: function getSelected() {
    var selection = this.getSelectedEvents();
    return selection.length > 0 ? selection[0] : null;
  },

  /**
   * Returns an array of the selected events
   * @return {Array}
   */
  getSelectedEvents: function getSelectedEvents() {
    return this.getSelectedNodes();
  },
  //    getSelections: function() {
  //        return this.getSelectedEvents();
  //    },

  /**
   * Select an event.
   * 
   * @param {Tine.Calendar.Model.Event} event The event to select
   * @param {EventObject} e (optional) An event associated with the selection
   * @param {Boolean} keepExisting True to retain existing selections
   * @return {Tine.Calendar.Model.Event} The selected event
   */
  select: function select(event, e, keepExisting) {
    if (!event || !event.ui) {
      return event;
    }

    Tine.Calendar.EventSelectionModel.superclass.select.apply(this, arguments);
  },
  selectRecords: function selectRecords(records) {
    this.clearSelections();

    _.each(records, record => {
      this.select(record, Ext.EventObject, true);
    });
  },
  onKeyDown: Ext.emptyFn
});

/***/ }),

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

/* 
 * Tine 2.0
 * 
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2009-2015 Metaways Infosystems GmbH (http://www.metaways.de)
 */
Ext.ns('Tine.Calendar');

__webpack_require__(1776);

__webpack_require__(1781);
/**
 * @namespace   Tine.Calendar
 * @class       Tine.Calendar.DaysView
 * @extends     Tine.Calendar.AbstractView
 * Calendar view representing each day in a column
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @constructor
 * @param {Object} config
 */


Tine.Calendar.DaysView = function (config) {
  Ext.apply(this, config);
  Tine.Calendar.DaysView.superclass.constructor.call(this);
  this.printRenderer = Tine.Calendar.Printer.DaysViewRenderer;
  this.addEvents(
  /**
   * @event click
   * fired if an event got clicked
   * @param {Tine.Calendar.Model.Event} event
   * @param {Ext.EventObject} e
   */
  'click',
  /**
   * @event contextmenu
   * fired if an event got contextmenu 
   * @param {Ext.EventObject} e
   */
  'contextmenu',
  /**
   * @event dblclick
   * fired if an event got dblclicked
   * @param {Tine.Calendar.Model.Event} event
   * @param {Ext.EventObject} e
   */
  'dblclick',
  /**
   * @event changeView
   * fired if user wants to change view
   * @param {String} requested view name
   * @param {mixed} start param of requested view
   */
  'changeView',
  /**
   * @event changePeriod
   * fired when period changed
   * @param {Object} period
   */
  'changePeriod',
  /**
   * @event addEvent
   * fired when a new event got inserted
   * 
   * @param {Tine.Calendar.Model.Event} event
   */
  'addEvent',
  /**
   * @event updateEvent
   * fired when an event go resised/moved
   * 
   * @param {Tine.Calendar.Model.Event} event
   */
  'updateEvent',
  /**
   * @event onBeforeAllDayScrollerResize
   * fired when an the allDayArea gets resized
   *
   * @param {Tine.Calendar.Model.DaysView} this
   * @param {number} heigt
   */
  'onBeforeAllDayScrollerResize');
};

Ext.extend(Tine.Calendar.DaysView, Tine.Calendar.AbstractView, {
  /**
   * @cfg {Date} startDate
   * start date
   */
  startDate: new Date(),

  /**
   * @cfg {Number} numOfDays
   * number of days to display
   */
  numOfDays: 4,

  /**
   * @cfg {String} (H:i) defaultStart
   * generic scroll start of the (work) day
   */
  defaultStart: '08:00',

  /**
   * @cfg {String} (H:i) dayStart
   * generic start of the (work) day
   */
  dayStart: '08:00',

  /**
   * @cfg {String} (H:i) dayEnd
   * generic end of the (work) day
   */
  dayEnd: '18:00',

  /**
   * @cfg {Bool} cropDayTime
   * crop times before and after dayStart and dayEnd
   */
  cropDayTime: false,

  /**
   *  @cfg {Integer} wheelIncrement
   *  the number of pixels to increment on mouse wheel scrolling (defaults to 50)
   */
  wheelIncrement: 50,

  /**
   * @cfg {String} newEventSummary
   * i18n._('New Event')
   */
  newEventSummary: 'New Event',

  /**
   * @cfg {String} dayFormatString
   * i18n._('{0}, the {1}. of {2}')
   */
  dayFormatString: '{0}, the {1}. of {2}',

  /**
   * @cfg {Number} timeGranularity
   * granularity of timegrid in minutes
   */
  timeGranularity: 30,

  /**
   * @cfg {Number} timeIncrement
   * time increment for range adds/edits (minutes)
   */
  timeIncrement: 15,

  /**
   * @cfg {Number} timeVisible
   * time visible in scrolling area (minutes)
   */
  timeVisible: '10:00',

  /**
   * @cfg {Boolean} denyDragOnMissingEditGrant
   * deny drag action if edit grant for event is missing
   */
  denyDragOnMissingEditGrant: true,

  /**
   * @cfg {Boolean} readOnly
   * no dd acionts if read only
   */
  readOnly: false,

  /**
   * store holding timescale
   * @property {Ext.data.Store}
   * @private
   */
  timeScale: null,

  /**
   * The amount of space to reserve for the scrollbar (defaults to 19 pixels)
   * @property {Number}
   * @private
   */
  scrollOffset: 19,

  /**
   * The time in milliseconds, a scroll should be delayed after using the mousewheel
   * @property Number
   * @private
   */
  scrollBuffer: 200,

  /**
   * The minmum all day height in px
   * @property Number
   * @private
   */
  minAllDayScrollerHight: 10,

  /**
   * record currently being edited or false
   * @property {Record} editing
   * @private
   */
  editing: false,

  /**
   * @property {Ext.data.Store}
   * @private
   */
  ds: null,
  eventCls: 'cal-daysviewpanel-event',

  /**
   * updates period to display
   * @param {Array} period
   */
  updatePeriod: function updatePeriod(period) {
    this.startDate = period.from.clearTime(true);
    var tbar = this.findParentBy(function (c) {
      return c.getTopToolbar();
    }).getTopToolbar();

    if (tbar && tbar.periodPicker) {
      tbar.periodPicker.update(this.startDate);
      this.startDate = tbar.periodPicker.getPeriod().from.clearTime(true);
    }

    this.endDate = this.startDate.add(Date.DAY, this.numOfDays + 1); //this.parallelScrollerEventsRegistry = new Tine.Calendar.ParallelEventsRegistry({dtStart: this.startDate, dtEnd: this.endDate});
    //this.parallelWholeDayEventsRegistry = new Tine.Calendar.ParallelEventsRegistry({dtStart: this.startDate, dtEnd: this.endDate});
    //this.store.each(this.removeEvent, this);

    this.updateDayHeaders();
    this.onBeforeScroll();
    this.fireEvent('changePeriod', period);
  },

  /**
   * init this view
   */
  initComponent: function initComponent() {
    this.app = Tine.Tinebase.appMgr.get('Calendar');
    this.newEventSummary = this.app.i18n._hidden(this.newEventSummary);
    this.dayFormatString = this.app.i18n._hidden(this.dayFormatString);
    this.startDate.clearTime();
    this.endDate = this.startDate.add(Date.DAY, this.numOfDays + 1);
    this.boxMinWidth = 60 * this.numOfDays;
    this.parallelScrollerEventsRegistry = new Tine.Calendar.ParallelEventsRegistry({
      dtStart: this.startDate,
      dtEnd: this.endDate
    });
    this.parallelWholeDayEventsRegistry = new Tine.Calendar.ParallelEventsRegistry({
      dtStart: this.startDate,
      dtEnd: this.endDate
    });
    this.timeIncrement = parseInt(this.app.getRegistry().get('preferences').get('timeIncrement')) || this.timeIncrement;
    this.initTimeScale();

    if (Tine.Tinebase.MainScreen) {
      this.mon(Tine.Tinebase.MainScreen, 'appactivate', this.onAppActivate, this);
    } // apply preferences


    var prefs = this.app.getRegistry().get('preferences'),
        defaultStartTime = Date.parseDate(prefs.get('daysviewdefaultstarttime'), 'H:i'),
        startTime = Date.parseDate(prefs.get('daysviewstarttime'), 'H:i'),
        endTime = Date.parseDate(prefs.get('daysviewendtime'), 'H:i'),
        timeVisible = Date.parseTimePart(prefs.get('daysviewtimevisible'), 'H:i');
    this.dayStart = Ext.isDate(startTime) ? startTime : Date.parseDate(this.dayStart, 'H:i');
    this.dayEnd = Ext.isDate(endTime) ? endTime : Date.parseDate(this.dayEnd, 'H:i'); // 00:00 in users timezone is a spechial case where the user expects
    // something like 24:00 and not 00:00

    if (this.dayEnd.format('H:i') == '00:00') {
      this.dayEnd = this.dayEnd.add(Date.MINUTE, -1);
    }

    this.timeVisible = Ext.isDate(timeVisible) ? timeVisible : Date.parseTimePart(this.timeVisible, 'H:i');
    this.cropDayTime = !!Tine.Tinebase.configManager.get('daysviewcroptime', 'Calendar');

    if (this.cropDayTime) {
      this.defaultStart = Ext.isDate(defaultStartTime) ? defaultStartTime : Date.parseDate(this.defaultStart, 'H:i');
    } else {
      this.defaultStart = this.dayStart;
    }

    this.wheelIncrement = Tine.Tinebase.configManager.get('daysviewwheelincrement', 'Calendar') || this.wheelIncrement;
    Tine.Calendar.DaysView.superclass.initComponent.apply(this, arguments);
  },

  /**
   * inits time scale
   * @private
   */
  initTimeScale: function initTimeScale() {
    var data = [];
    var scaleSize = Date.msDAY / (this.timeGranularity * Date.msMINUTE);
    var baseDate = this.startDate.clone();
    var minutes;

    for (var i = 0; i < scaleSize; i++) {
      minutes = i * this.timeGranularity;
      data.push([i, minutes, minutes * Date.msMINUTE, baseDate.add(Date.MINUTE, minutes).format('H:i')]);
    }

    this.timeScale = new Ext.data.SimpleStore({
      fields: ['index', 'minutes', 'milliseconds', 'time'],
      data: data,
      id: 'index'
    });
  },
  initDropZone: function initDropZone() {
    this.dd = new Ext.dd.DropZone(this.mainWrap.dom, {
      ddGroup: 'cal-event',
      view: this,
      notifyOver: function notifyOver(dd, e, data) {
        var sourceEl = Ext.fly(data.sourceEl),
            sourceView = data.scope,
            colorIcon = _.get(data, 'event.colorSet.text') === '#FFFFFF' ? '-WHITE' : '';
        sourceEl.setStyle({
          'border-left-style': 'dashed'
        });
        sourceEl.setOpacity(0.5);
        data.denyDrop = true;

        if (data.event) {
          var event = data.event;
          var targetDateTime = Tine.Calendar.DaysView.prototype.getTargetDateTime.call(data.scope, e);

          if (targetDateTime) {
            var dtString = targetDateTime.format(targetDateTime.is_all_day_event ? Ext.form.DateField.prototype.format : 'H:i');

            if (!event.data.is_all_day_event) {
              Ext.fly(dd.proxy.el.query('div[class=cal-daysviewpanel-event-header-inner]')[0]).update(dtString);
            }

            if (event.get('editGrant')) {
              data.denyDrop = this.view == sourceView && Math.abs(targetDateTime.getTime() - event.get('dtstart').getTime()) < Date.msMINUTE;

              if (data.dtstartLimit && targetDateTime.getTimePart() > data.dtstartLimit) {
                data.denyDrop = true;
              }

              var eventDrop = data.denyDrop ? 'cal-daysviewpanel-event-drop-nodrop' : 'cal-daysviewpanel-event-drop-ok';
              return eventDrop + colorIcon;
            }
          }
        }

        return 'cal-daysviewpanel-event-drop-nodrop' + colorIcon;
      },
      notifyOut: function notifyOut() {//delete this.grid;
      },
      notifyDrop: function notifyDrop(dd, e, data) {
        var v = data.scope,
            targetDate = v.getTargetDateTime(e);

        if (targetDate) {
          var event = data.event,
              originalDuration = (event.get('dtend').getTime() - event.get('dtstart').getTime()) / Date.msMINUTE;

          if (data.denyDrop) {
            return false;
          }

          event.beginEdit();
          event.set('dtstart', targetDate);

          if (!event.get('is_all_day_event') && targetDate.is_all_day_event && event.duration < Date.msDAY) {
            // draged from scroller -> dropped to allDay and duration less than a day
            event.set('dtend', targetDate.add(Date.DAY, 1).add(Date.SECOND, -1));
          } else if (event.get('is_all_day_event') && !targetDate.is_all_day_event) {
            // draged from allDay -> droped to scroller will be resetted to hone hour
            event.set('dtend', targetDate.add(Date.MINUTE, Tine.Calendar.Model.Event.getMeta('defaultEventDuration')));
          } else {
            event.set('dtend', targetDate.add(Date.MINUTE, originalDuration));
          }

          event.set('is_all_day_event', targetDate.is_all_day_event); // change attendee in split view

          if (this.view.ownerCt.attendee) {
            var attendeeStore = Tine.Calendar.Model.Attender.getAttendeeStore(event.get('attendee')),
                sourceAttendee = Tine.Calendar.Model.Attender.getAttendeeStore.getAttenderRecord(attendeeStore, event.view.ownerCt.attendee),
                destinationAttendee = Tine.Calendar.Model.Attender.getAttendeeStore.getAttenderRecord(attendeeStore, this.view.ownerCt.attendee);

            if (!destinationAttendee) {
              destinationAttendee = new Tine.Calendar.Model.Attender(this.view.ownerCt.attendee.data);
              attendeeStore.remove(sourceAttendee);
              attendeeStore.add(destinationAttendee);
              Tine.Calendar.Model.Attender.getAttendeeStore.getData(attendeeStore, event);
            }
          }

          event.endEdit();
          v.fireEvent('updateEvent', event);
        }

        return !!targetDate;
      }
    });
  },

  /**
   * @private
   */
  initDragZone: function initDragZone() {
    this.scroller.ddScrollConfig = {
      hthresh: -1,
      frequency: 500
    };
    Ext.dd.ScrollManager.register(this.scroller); // init dragables

    this.dragZone = new Ext.dd.DragZone(this.el, {
      ddGroup: 'cal-event',
      view: this,
      scroll: false,
      containerScroll: true,
      getDragData: function getDragData(e) {
        // adjust scrollConfig
        var scrollUnit = this.view.getTimeOffset(this.view.timeIncrement);
        this.view.scroller.ddScrollConfig.vthresh = scrollUnit * 2;
        this.view.scroller.ddScrollConfig.increment = scrollUnit * 4;
        var selected = this.view.getSelectionModel().getSelectedEvents();
        var eventEl = e.getTarget('div.cal-daysviewpanel-event', 10);

        if (eventEl) {
          var parts = eventEl.id.split(':');
          var event = this.view.store.getById(parts[1]); // don't allow dragging of dirty events
          // don't allow dragging with missing edit grant

          if (!event || event.dirty || this.readOnly || this.view.denyDragOnMissingEditGrant && !event.get('editGrant')) {
            return;
          } // we need to clone an event with summary in


          var eventEl = Ext.get(event.ui.domIds[0]),
              eventBox = eventEl.getBox(),
              d = eventEl.dom.cloneNode(true);
          d.id = Ext.id();

          if (event.get('is_all_day_event')) {
            Ext.fly(d).setTop(-2);
            Ext.fly(d).setLeft(0);
            Ext.fly(d).setWidth(eventBox.width);
          } else {
            var width = Ext.fly(this.view.dayCols[0]).getWidth() * 0.9;
            Ext.fly(d).setTop(0);
            Ext.fly(d).setWidth(width);
            Ext.fly(d).setHeight(eventBox.height);
          }

          return {
            scope: this.view,
            sourceEl: eventEl,
            event: event,
            ddel: d,
            selections: this.view.getSelectionModel().getSelectedEvents(),
            dtstartLimit: this.view.cropDayTime ? this.view.dayEnd.getTimePart() - event.duration : false
          };
        }
      },
      getRepairXY: function getRepairXY(e, dd) {
        Ext.fly(this.dragData.sourceEl).setStyle({
          'border-left-style': 'solid'
        });
        Ext.fly(this.dragData.sourceEl).setOpacity(1, 1);
        return Ext.fly(this.dragData.sourceEl).getXY();
      }
    });
  },

  /**
   * renders the view
   */
  onRender: function onRender(container, position) {
    Tine.Calendar.DaysView.superclass.onRender.apply(this, arguments);
    this.templates.master.append(this.el.dom, {
      header: this.templates.header.applyTemplate({
        daysHeader: this.getDayHeaders(),
        wholeDayCols: this.getWholeDayCols()
      }),
      body: this.templates.body.applyTemplate({
        timeRows: this.getTimeRows(),
        dayColumns: this.getDayColumns()
      })
    });
    this.initElements();
  },

  /**
   * fill the events into the view
   */
  afterRender: function afterRender() {
    Tine.Calendar.DaysView.superclass.afterRender.apply(this, arguments);
    this.mon(this.el, 'mousedown', this.onMouseDown, this);
    this.mon(this.el, 'mouseup', this.onMouseUp, this);
    this.initDropZone();
    this.initDragZone();
    this.updatePeriod({
      from: this.startDate
    }); // apply os specific scrolling space

    Ext.fly(this.innerHd.firstChild.firstChild).setStyle('margin-right', Ext.getScrollBarWidth() + 'px'); // crop daytime

    if (this.cropDayTime) {
      this.cropper.setStyle('overflow', 'hidden');
      this.scroller.addClass('cal-daysviewpanel-body-cropDayTime');
    }

    if (this.store.getCount()) {
      this.onLoad.defer(100, this);
    }

    this.rendered = true;
  },
  scrollTo: function scrollTo(time) {
    time = Ext.isDate(time) ? time : new Date();
    var scrollTop = this.getTimeOffset(time);

    if (this.cropDayTime) {
      scrollTop = scrollTop - this.getTimeOffset(this.dayStart);
    }

    this.scroller.dom.scrollTop = scrollTop;
  },
  onMouseWheel: function onMouseWheel(e) {
    var d = e.getWheelDelta() * this.wheelIncrement * -1;
    e.stopEvent();
    var scrollTop = this.scroller.dom.scrollTop,
        newTop = scrollTop + d,
        sh = this.scroller.dom.scrollHeight - this.scroller.dom.clientHeight;
    var s = Math.max(0, Math.min(sh, newTop));

    if (s != scrollTop) {
      this.scroller.scrollTo('top', s);
    }
  },
  onBeforeScroll: function onBeforeScroll() {
    if (!this.isScrolling) {
      this.isScrolling = true; // walk all cols an hide hints

      Ext.each(this.dayCols, function (dayCol, idx) {
        this.aboveHints.item(idx).setDisplayed(false);
        this.belowHints.item(idx).setDisplayed(false);
      }, this);
    }
  },

  /**
   * add hint if events are outside visible area
   * 
   * @param {} e
   * @param {} t
   * @param {} o
   */
  onScroll: function onScroll(e, t, o) {
    // no arguments means programatic scroll (show/hide/...)
    if (!arguments.length) {
      var topTime = this.lastScrollTime || this.defaultStart;

      if (topTime) {
        this.scrollTo(topTime);
      }
    }

    var visibleHeight = this.scroller.dom.clientHeight,
        visibleStart = this.scroller.dom.scrollTop - this.mainBody.dom.offsetTop,
        visibleEnd = visibleStart + visibleHeight,
        vStartMinutes = this.getHeightMinutes(visibleStart),
        vEndMinutes = this.getHeightMinutes(visibleEnd);
    Ext.each(this.dayCols, function (dayCol, idx) {
      var dayColEl = Ext.get(dayCol),
          dayStart = this.startDate.add(Date.DAY, idx),
          aboveEvents = this.parallelScrollerEventsRegistry.getEvents(dayStart, dayStart.add(Date.MINUTE, vStartMinutes)),
          belowEvents = this.parallelScrollerEventsRegistry.getEvents(dayStart.add(Date.MINUTE, vEndMinutes), dayStart.add(Date.DAY, 1));

      if (aboveEvents.length) {
        var aboveHint = this.aboveHints.item(idx);
        aboveHint.setTop(visibleStart + 5);

        if (!aboveHint.isVisible()) {
          aboveHint.fadeIn({
            duration: 1.6
          });
        }
      }

      if (belowEvents.length) {
        var belowHint = this.belowHints.item(idx);
        belowHint.setTop(visibleEnd - 14);

        if (!belowHint.isVisible()) {
          belowHint.fadeIn({
            duration: 1.6
          });
        }
      }
    }, this);
    var topOffset = this.scroller ? this.getHeightMinutes(this.scroller.dom.scrollTop) : null;

    if (topOffset !== null) {
      if (this.cropDayTime) {
        topOffset = topOffset + this.dayStart.getHours() * 60 + this.dayStart.getMinutes();
      }

      this.lastScrollTime = this.dayStart.clearTime(true).add(Date.MINUTE, topOffset);
    }

    this.isScrolling = false;
  },

  /**
   * renders a single event into this daysview
   * @param {Tine.Calendar.Model.Event} event
   * 
   * @todo Add support vor Events spanning over a day boundary
   */
  insertEvent: function insertEvent(event) {
    if (!this.mainBody) {
      // maybe another app is active and mainBody has not been rendered yet
      return;
    }

    event.ui = new Tine.Calendar.DaysViewEventUI(event);
    event.ui.render(this);
  },

  /**
   * creates a new event directly from this view
   * @param {} event
   */
  createEvent: function createEvent(e, event) {
    // only add range events if mouse is down long enough
    if (this.editing || event.isRangeAdd && !this.mouseDown || !event.isValid()) {
      return;
    } // insert event silently into store


    this.editing = event;
    this.store.suspendEvents();
    this.store.add(event);
    this.store.resumeEvents(); // draw event

    var registry = event.get('is_all_day_event') ? this.parallelWholeDayEventsRegistry : this.parallelScrollerEventsRegistry;
    registry.register(event);
    this.insertEvent(event);
    this.onLayout(); //var eventEls = event.ui.getEls();
    //eventEls[0].setStyle({'border-left-style': 'dashed'});
    //eventEls[0].setOpacity(0.5);
    // start sizing for range adds

    if (event.isRangeAdd) {
      // don't create events with very small duration
      event.ui.resizeable.on('resize', function () {
        if (event.get('is_all_day_event')) {
          var keep = true;
        } else {
          var keep = (event.get('dtend').getTime() - event.get('dtstart').getTime()) / Date.msMINUTE >= this.timeIncrement;
        }

        if (keep) {
          this.startEditSummary(event);
        } else {
          this.abortCreateEvent(event);
        }
      }, this); // snap correction for rangeadds

      var box = event.ui.resizeable.el.getBox(),
          mouseXY = Ext.EventObject.getXY(),
          startX = mouseXY[0],
          startY = mouseXY[1],
          handleX = box.x + box.width,
          handleY = box.y + box.height;
      event.ui.resizeable.correctionX = handleX - startX;
      event.ui.resizeable.correctionY = handleY - startY;

      event.ui.resizeable.snap = function (value, inc, min) {
        var pos = this.activeHandle.position;

        if (pos === 'south' && inc === this.heightIncrement) {
          value = value - this.correctionY;
        } else if (pos === 'east' && inc === this.widthIncrement) {
          value = value - this.correctionX;
        }

        return Ext.Resizable.prototype.snap.call(this, value, inc, min);
      };

      var rzPos = event.get('is_all_day_event') ? 'east' : 'south';
      event.ui.resizeable[rzPos].onMouseDown.call(event.ui.resizeable[rzPos], e); // adjust initial size to avoid flickering when start resizing

      event.ui.resizeable.onMouseMove(Ext.EventObject);
    } else {
      this.startEditSummary(event);
    }
  },
  abortCreateEvent: function abortCreateEvent(event) {
    this.store.remove(event);
    this.editing = false;
  },
  startEditSummary: function startEditSummary(event) {
    if (event.summaryEditor) {
      return false;
    }

    var eventEls = event.ui.getEls();
    var bodyCls = event.get('is_all_day_event') ? 'cal-daysviewpanel-wholedayevent-body' : 'cal-daysviewpanel-event-body';
    event.summaryEditor = new Ext.form.TextArea({
      event: event,
      renderTo: eventEls[0].down('div[class=' + bodyCls + ']'),
      width: event.ui.getEls()[0].getWidth() - 12,
      height: Math.max(12, event.ui.getEls()[0].getHeight() - 18),
      style: 'background-color: transparent; background: 0: border: 0; position: absolute; top: 0px; font-weight: bold; color: ' + event.ui.colorSet.text + ';',
      value: this.newEventSummary,
      maxLength: 255,
      maxLengthText: this.app.i18n._('The summary must not be longer than 255 characters.'),
      minLength: 1,
      minLengthText: this.app.i18n._('The summary must have at least 1 character.'),
      enableKeyEvents: true,
      listeners: {
        scope: this,
        render: function render(field) {
          field.focus(true, 100);
        },
        blur: this.endEditSummary,
        specialkey: this.endEditSummary,
        keydown: this.endEditSummary
      }
    });
  },
  endEditSummary: function endEditSummary(f, e) {
    if (!this.editing || this.validateMsg) {
      return;
    }

    var field = this.editing.summaryEditor;
    var event = field.event;
    var summary = field.getValue(); // abort edit on ESC key

    if (e && e.getKey() == e.ESC) {
      this.abortCreateEvent(event);
      return;
    } // only commit edit on Enter & blur


    if (e && e.getKey() != e.ENTER) {
      return;
    } // Validate Summary maxLength


    if (summary.length > field.maxLength) {
      field.markInvalid();
      this.validateMsg = Ext.Msg.alert(this.app.i18n._('Summary too Long'), field.maxLengthText, function () {
        field.focus();
        this.validateMsg = false;
      }, this);
      return;
    } // Validate Summary minLength


    if (!summary || summary.match(/^\s{1,}$/) || summary.length < field.minLength) {
      field.markInvalid();
      this.validateMsg = Ext.Msg.alert(this.app.i18n._('Summary too Short'), field.minLengthText, function () {
        field.focus();
        this.validateMsg = false;
      }, this);
      return;
    }

    this.editing = false;
    event.summaryEditor = false;
    event.set('summary', summary);
    this.store.suspendEvents();
    this.store.remove(event);
    this.store.resumeEvents();
    var registry = event.get('is_all_day_event') ? this.parallelWholeDayEventsRegistry : this.parallelScrollerEventsRegistry;
    registry.unregister(event);
    this.removeEvent(event);
    event.dirty = true;
    this.store.add(event);
    this.fireEvent('addEvent', event);
  },
  onAppActivate: function onAppActivate(app) {
    if (app === this.app) {
      this.redrawWholeDayEvents();
    }
  },
  onResize: function onResize() {
    Tine.Calendar.DaysView.superclass.onResize.apply(this, arguments);
    this.updateDayHeaders();
    this.redrawWholeDayEvents.defer(50, this);
    this.unbufferedOnLayout();
  },
  redrawWholeDayEvents: function redrawWholeDayEvents() {
    this.store.each(function (event) {
      // check if event is currently visible by looking into ui.domIds
      if (event.ui && event.ui.domIds.length > 0 && event.get('is_all_day_event')) {
        this.removeEvent(event);
        this.insertEvent(event);
      }
    }, this);
  },
  onClick: function onClick(e) {
    // check for hint clicks first
    var hint = e.getTarget('img[class^=cal-daysviewpanel-body-daycolumn-hint-]', 10, true);

    if (hint) {
      this.scroller.scroll(hint.hasClass('cal-daysviewpanel-body-daycolumn-hint-above') ? 't' : 'b', 10000, true);
      return;
    }

    return Tine.Calendar.DaysView.superclass.onClick.call(this, e);
  },

  /**
   * @private
   */
  onDblClick: function onDblClick(e, target) {
    e.stopEvent();
    var event = this.getTargetEvent(e);
    var dtStart = this.getTargetDateTime(e);

    if (event) {
      if (event.dirty && this.editing) {
        event.set('summary', this.editing.summaryEditor.getValue());
        event.summaryEditor = false;
        this.editing = false;
        this.abortCreateEvent.defer(500, this, [event]);
      }

      this.fireEvent('dblclick', event, e);
    } else if (dtStart && !this.editing) {
      var newId = 'cal-daysviewpanel-new-' + Ext.id();
      var dtend = dtStart.add(Date.MINUTE, Tine.Calendar.Model.Event.getMeta('defaultEventDuration'));

      if (dtStart.is_all_day_event) {
        dtend = dtend.add(Date.HOUR, 23).add(Date.SECOND, -1);
      } // do not create an event exceeding the crop day time limit
      else if (this.cropDayTime) {
          var format = 'Hms';

          if (dtStart.format(format) >= this.dayEnd.format(format)) {
            return false;
          }

          if (dtend.format(format) >= this.dayEnd.format(format)) {
            dtend.setHours(this.dayEnd.getHours());
            dtend.setMinutes(this.dayEnd.getMinutes());
            dtend.setSeconds(this.dayEnd.getSeconds());
          }
        }

      var event = new Tine.Calendar.Model.Event(Ext.apply(Tine.Calendar.Model.Event.getDefaultData(), {
        id: newId,
        dtstart: dtStart,
        dtend: dtend,
        is_all_day_event: dtStart.is_all_day_event
      }), newId);
      this.createEvent(e, event);
      event.dirty = true;
    } else if (target.className == 'cal-daysviewpanel-dayheader-day') {
      var dayHeaders = Ext.DomQuery.select('div[class=cal-daysviewpanel-dayheader-day]', this.innerHd);
      var date = this.startDate.add(Date.DAY, dayHeaders.indexOf(target));
      this.fireEvent('changeView', 'day', date);
    }
  },

  /**
   * @private
   */
  onMouseDown: function onMouseDown(e) {
    // don't care for right btn
    if (e.button > 0) {
      return;
    }

    if (!this.editing) {
      this.focusEl.focus();
    }

    this.mouseDown = true;
    var targetEvent = this.getTargetEvent(e);

    if (this.editing && this.editing.summaryEditor && targetEvent != this.editing) {
      this.editing.summaryEditor.fireEvent('blur', this.editing.summaryEditor, null);
      return;
    }

    var sm = this.getSelectionModel();
    sm.select(targetEvent);
    var dtStart = this.getTargetDateTime(e),
        dtEnd = this.getTargetDateTime(e, this.timeIncrement, 's');

    if (dtStart && !this.readOnly) {
      var newId = 'cal-daysviewpanel-new-' + Ext.id();
      var event = new Tine.Calendar.Model.Event(Ext.apply(Tine.Calendar.Model.Event.getDefaultData(), {
        id: newId,
        dtstart: dtStart,
        dtend: dtStart.is_all_day_event ? dtStart.add(Date.HOUR, 24).add(Date.SECOND, -1) : dtEnd,
        is_all_day_event: dtStart.is_all_day_event
      }), newId);
      event.isRangeAdd = true;
      event.dirty = true;
      e.stopEvent();
      e.preventDefault();
      this.createEvent.defer(100, this, [e, event]);
    }
  },

  /**
   * @private
   */
  onMouseUp: function onMouseUp() {
    this.mouseDown = false;
  },

  /**
   * @private
   */
  onBeforeEventResize: function onBeforeEventResize(rz, e) {
    var me = this;
    var parts = rz.el.id.split(':');
    var event = this.store.getById(parts[1]);
    this.getSelectionModel().select(event); // @TODO compute max minutes also

    var maxHeight = 10000;

    if (this.cropDayTime) {
      var maxMinutes = (this.dayEnd.getTimePart() - event.get('dtstart').getTimePart()) / Date.msMINUTE;
      maxHeight = this.getTimeOffset(maxMinutes);
    }

    rz.heightIncrement = this.getTimeOffset(this.timeIncrement);
    rz.maxHeight = maxHeight;
    rz.event = event;
    rz.originalHeight = rz.el.getHeight();
    rz.originalWidth = rz.el.getWidth(); // NOTE: ext dosn't support move events via api

    rz.onMouseMove = rz.onMouseMove.createSequence(function (e) {
      var event = this.event;

      if (!event) {
        //event already gone -> late event / busy brower?
        return;
      }

      var ui = event.ui;
      var rzInfo = ui.getRzInfo(this);

      if (e.type === 'mousemove') {
        if (!event.get('is_all_day_event')) {
          // getRzInfo calcs wrong values???
          let shouldHeight = me.getTimeOffset(rzInfo.dtend) - me.getTimeOffset(event.get('dtstart'));
          this.el.setHeight(shouldHeight);
        }

        if (this.durationEl) {
          this.durationEl.update(rzInfo.dtend.format(event.get('is_all_day_event') ? Ext.form.DateField.prototype.format : 'H:i'));
        }
      }
    }, rz); // adjust initial size to avoid flickering when start resizing

    if (e.getTarget('.x-resizable-handle-south')) {
      event.ui.resizeable.onMouseMove(e);
    }

    event.ui.markDirty(); // NOTE: Ext keeps proxy if element is not destroyed (diff !=0)

    if (!rz.durationEl) {
      rz.durationEl = rz.el.insertFirst({
        'class': 'cal-daysviewpanel-event-rzduration',
        'style': 'position: absolute; bottom: 3px; right: 2px; z-index: 1000;'
      });
    }

    rz.durationEl.update(event.get('dtend').format(event.get('is_all_day_event') ? Ext.form.DateField.prototype.format : 'H:i'));
  },

  /**
   * @private
   */
  onEventResize: function onEventResize(rz, width, height) {
    var event = rz.event;

    if (!event) {
      //event already gone -> late event / busy brower?
      return;
    }

    var rzInfo = event.ui.getRzInfo(rz, width, height);

    if (rzInfo.diff != 0) {
      if (rzInfo.duration > 0) {
        event.set('dtend', rzInfo.dtend);
      } else {
        // force event length to at least 1 minute
        var date = new Date(event.get('dtstart').getTime());
        date.setMinutes(date.getMinutes() + 1);
        event.set('dtend', date);
      }
    }

    if (event.summaryEditor) {
      event.summaryEditor.setHeight(event.ui.getEls()[0].getHeight() - 18);
    } // don't fire update events on rangeAdd


    if (rzInfo.diff != 0 && event != this.editing && !event.isRangeAdd) {
      this.fireEvent('updateEvent', event);
    } else if (event.isRangeAdd) {
      event.ui.clearDirty();
    } else {
      // NOTE: we need to redraw event as resizer is broken after one attempt
      this.removeEvent(event);
      this.insertEvent(event);
      this.getSelectionModel().select(event);
    }
  },
  getParallelEventRegistry: function getParallelEventRegistry(event, original) {
    var isAllDayEvent = original && event.modified.hasOwnProperty('is_all_day_event') ? event.modified.is_all_day_event : event.get('is_all_day_event');
    return isAllDayEvent ? this.parallelWholeDayEventsRegistry : this.parallelScrollerEventsRegistry;
  },
  initParallelEventRegistry: function initParallelEventRegistry(event) {
    this.parallelScrollerEventsRegistry = new Tine.Calendar.ParallelEventsRegistry({
      dtStart: this.startDate,
      dtEnd: this.endDate
    });
    this.parallelWholeDayEventsRegistry = new Tine.Calendar.ParallelEventsRegistry({
      dtStart: this.startDate,
      dtEnd: this.endDate
    });
  },

  /**
   * print wrapper
   */
  print: function print(printMode) {
    var renderer = new this.printRenderer({
      printMode: printMode
    });
    renderer.print(this);
  },
  getPeriod: function getPeriod() {
    var tbar = this.findParentBy(function (c) {
      return c.getTopToolbar();
    }).getTopToolbar();
    return tbar && tbar.periodPicker ? tbar.periodPicker.getPeriod() : {
      from: this.startDate,
      until: this.startDate.add(Date.DAY, this.numOfDays)
    };
  },

  /**
   * get date of a (event) target
   * 
   * @param {Ext.EventObject} e
   * @param {number} graticule
   * @param {char} graticuleEdge one of n (north) s, (south)
   * @return {Date}
   */
  getTargetDateTime: function getTargetDateTime(e, graticule, graticuleHandle) {
    var target = e.getTarget('div[class^=cal-daysviewpanel-datetime]');

    if (target && target.id.match(/^ext-gen\d+:\d+/)) {
      var parts = target.id.split(':');
      var date = this.startDate.add(Date.DAY, parseInt(parts[1], 10));
      date.is_all_day_event = true;

      if (parts[2]) {
        var timePart = this.timeScale.getAt(parts[2]),
            eventXY = e.getXY(),
            mainBodyXY = this.mainBody.getXY(),
            offsetPx = eventXY[1] - mainBodyXY[1],
            offsetMinutes = this.getHeightMinutes(offsetPx),
            graticule = graticule ? graticule : this.timeGranularity,
            graticuleHandle = graticuleHandle ? graticuleHandle : 'n',
            graticuleFn = graticuleHandle == 'n' ? Math.floor : Math.ceil; // constraint to graticule

        offsetMinutes = graticuleFn(offsetMinutes / graticule) * graticule;
        date = date.add(Date.MINUTE, offsetMinutes);
        date.is_all_day_event = false;
      }

      return date;
    }
  },

  /**
   * get offset in px for the time part of given date (with current scaling)
   *
   * @param {date} date
   * @returns {number}
   */
  getTimeOffset: function getTimeOffset(date) {
    if (this.mainBody) {
      var minutes = Ext.isDate(date) ? date.getTimePart() / Date.msMINUTE : date,
          d = this.getMainBodyHeight() / (24 * 60);
      return Math.round(d * minutes);
    }
  },

  /**
   * get offset in % for the time part of given date
   *
   * @param {date|number} date
   * @returns {number}
   */
  getTimeOffsetPct: function getTimeOffsetPct(date) {
    var minutes = Ext.isDate(date) ? date.getTimePart() / Date.msMINUTE : date;
    return 100 * (Date.msMINUTE * minutes / Date.msDAY);
  },

  /**
   * get height in px of the diff for the given dates (with current scaling)
   *
   * @param {date} dtStart
   * @param {date} dtEnd
   * @returns {number}
   */
  getTimeHeight: function getTimeHeight(dtStart, dtEnd) {
    if (this.mainBody) {
      var d = this.getMainBodyHeight() / (24 * 60);
      return Math.round(d * ((dtEnd.getTime() - dtStart.getTime()) / Date.msMINUTE));
    }
  },

  /**
   * get height in % of the diff for the given dates
   *
   * @param {date} dtStart
   * @param {date} dtEnd
   * @returns {number}
   */
  getTimeHeightPct: function getTimeHeightPct(dtStart, dtEnd) {
    return 100 * ((dtEnd.getTime() - dtStart.getTime()) / Date.msDAY);
  },

  /**
   * get number of minutes represented by height in px (current scaleing)
   *
   * @param {number} height
   * @returns {number}
   */
  getHeightMinutes: function getHeightMinutes(height) {
    var d = 24 * 60 / this.getMainBodyHeight();
    return Math.round(d * height);
  },
  getMainBodyHeight: function getMainBodyHeight() {
    if (!this.mainBody) {
      // maybe another app is active
      return 0;
    }

    var height = this.mainBody.getHeight(); // hidden atm.

    if (!height) {
      height = parseInt(this.mainBody.dom.style.height, 10);
    }

    return height;
  },

  /**
   * fetches elements from our generated dom
   */
  initElements: function initElements() {
    var E = Ext.Element;
    var cs = this.el.dom.firstChild.childNodes;
    this.mainWrap = new E(cs[0]);
    this.mainHd = new E(this.mainWrap.dom.firstChild);
    this.innerHd = this.mainHd.dom.firstChild;
    this.wholeDayScroller = new E(this.innerHd.firstChild.childNodes[1]);
    this.wholeDayArea = this.wholeDayScroller.dom.firstChild;
    this.scroller = new E(this.mainWrap.dom.childNodes[1]);
    this.scroller.setStyle('overflow-x', 'hidden');
    this.mon(this.scroller, 'mousewheel', this.onMouseWheel, this);
    this.mon(this.scroller, 'scroll', this.onBeforeScroll, this);
    this.mon(this.scroller, 'scroll', this.onScroll, this, {
      buffer: 200
    });
    this.cropper = new E(this.scroller.dom.firstChild);
    this.mainBody = new E(this.cropper.dom.firstChild);
    this.dayCols = this.mainBody.dom.lastChild.childNodes;
    this.focusEl = new E(this.el.dom.lastChild.lastChild);
    this.focusEl.swallowEvent("click", true);
    this.focusEl.swallowEvent("dblclick", true);
    this.focusEl.swallowEvent("contextmenu", true);
    this.aboveHints = this.mainBody.select('img[class=cal-daysviewpanel-body-daycolumn-hint-above]');
    this.belowHints = this.mainBody.select('img[class=cal-daysviewpanel-body-daycolumn-hint-below]');
  },

  /**
   * @TODO this returns wrong cols on DST boundaries:
   *  e.g. on DST switch form +2 to +1 an all day event is 25 hrs. long
   * 
   * @param {} date
   * @return {}
   */
  getColumnNumber: function getColumnNumber(date) {
    return Math.floor((date.add(Date.SECOND, 1).getTime() - this.startDate.getTime()) / Date.msDAY);
  },
  getDateColumnEl: function getDateColumnEl(pos) {
    return this.dayCols[pos];
  },
  checkWholeDayEls: function checkWholeDayEls() {
    var freeIdxs = [];

    for (var i = 0; i < this.wholeDayArea.childNodes.length - 1; i++) {
      if (this.wholeDayArea.childNodes[i].childNodes.length === 1) {
        freeIdxs.push(i);
      }
    }

    for (var i = 1; i < freeIdxs.length; i++) {
      Ext.fly(this.wholeDayArea.childNodes[freeIdxs[i]]).remove();
    }
  },

  /**
   * buffered version of this.unbufferedOnLayout
   * @see this.initComponent
   */
  onLayout: Ext.emptyFn,

  /**
   * layouts the view
   */
  unbufferedOnLayout: function unbufferedOnLayout() {
    Tine.Calendar.DaysView.superclass.onLayout.apply(this, arguments);

    if (!this.mainBody) {
      return; // not rendered
    }

    var csize = this.container.getSize(true),
        vw = csize.width;

    if (!vw) {
      return; // hidden
    }

    this.el.setSize(csize.width, csize.height); // layout whole day area -> take one third of the available height maximum

    var wholeDayAreaEl = Ext.get(this.wholeDayArea),
        wholeDayAreaHeight = this.computeAllDayAreaHeight(),
        wholeDayScrollerHeight = wholeDayAreaHeight,
        maxAllowedHeight = Math.round(csize.height / 4),
        resizeEvent = {
      wholeDayAreaHeight: wholeDayAreaHeight,
      wholeDayScrollerHeight: Math.min(wholeDayAreaHeight, maxAllowedHeight),
      maxAllowedHeight: maxAllowedHeight
    };
    wholeDayAreaEl.setHeight(wholeDayAreaHeight);
    this.fireEvent('onBeforeAllDayScrollerResize', this, resizeEvent);
    this.wholeDayScroller.setHeight(resizeEvent.wholeDayScrollerHeight);
    var hdHeight = this.mainHd.getHeight();
    var vh = csize.height - hdHeight;
    this.scroller.setSize(vw, vh); // resize mainBody for visibleMinutes to fit

    var timeToDisplay = this.timeVisible.getTime() / Date.msMINUTE,
        scrollerHeight = this.scroller.getHeight(),
        height = scrollerHeight * (24 * 60) / timeToDisplay;
    this.mainBody.setHeight(height);

    if (this.cropDayTime) {
      var cropHeightPx = this.getTimeHeight(this.dayStart, this.dayEnd),
          cropStartPx = this.getTimeOffset(this.dayStart);
      this.cropper.setStyle('height', cropHeightPx + 'px');
      this.cropper.dom.scrollTop = cropStartPx;
    }

    if (!this.initialScrolled) {
      // scrollTo initial position
      this.isScrolling = true;
      this.scrollTo(this.defaultStart);
      this.initialScrolled = true;
    } // force positioning on scroll hints


    this.onBeforeScroll.defer(50, this);
    this.onScroll.defer(100, this);
  },
  computeAllDayAreaHeight: function computeAllDayAreaHeight() {
    var wholeDayAreaEl = Ext.get(this.wholeDayArea);

    for (var i = 0, bottom = wholeDayAreaEl.getTop(); i < this.wholeDayArea.childNodes.length - 1; i++) {
      bottom = Math.max(parseInt(Ext.get(this.wholeDayArea.childNodes[i]).getBottom(), 10), bottom);
    } // take one third of the available height maximum


    return bottom - wholeDayAreaEl.getTop() + this.minAllDayScrollerHight;
  },

  /**
   * returns HTML frament of the day headers
   */
  getDayHeaders: function getDayHeaders() {
    var html = '';
    var width = 100 / this.numOfDays;

    for (var i = 0, date; i < this.numOfDays; i++) {
      var day = this.startDate.add(Date.DAY, i);
      html += this.templates.dayHeader.applyTemplate({
        day: String.format(this.dayFormatString, day.format('l'), day.format('j'), day.format('F')),
        height: '20px',
        width: width + '%',
        left: i * width + '%'
      });
    }

    return html;
  },

  /**
   * updates HTML of day headers
   */
  updateDayHeaders: function updateDayHeaders() {
    if (!this.rendered) return;
    var dayHeaders = Ext.DomQuery.select('div[class=cal-daysviewpanel-dayheader-day]', this.innerHd),
        dayWidth = dayHeaders ? Ext.get(dayHeaders[0]).getWidth() : [],
        headerString;

    for (var i = 0, date, isToDay, headerEl, dayColEl; i < dayHeaders.length; i++) {
      date = this.startDate.add(Date.DAY, i);
      isToDay = date.getTime() == new Date().clearTime().getTime();
      headerEl = Ext.get(dayHeaders[i]);

      if (dayWidth > 150) {
        headerString = String.format(this.dayFormatString, date.format('l'), date.format('j'), date.format('F'));
      } else if (dayWidth > 60) {
        headerString = date.format('D') + ', ' + date.format('j') + '.' + date.format('n');
      } else {
        headerString = date.format('j') + '.' + date.format('n');
      }

      headerEl.update(headerString);
      headerEl.parent()[(isToDay ? 'add' : 'remove') + 'Class']('cal-daysviewpanel-dayheader-today');
      Ext.get(this.dayCols[i])[(isToDay ? 'add' : 'remove') + 'Class']('cal-daysviewpanel-body-daycolumn-today');
    }
  },

  /**
   * returns HTML fragment of the whole day cols
   */
  getWholeDayCols: function getWholeDayCols() {
    var html = '';
    var width = 100 / this.numOfDays;
    var baseId = Ext.id();

    for (var i = 0; i < this.numOfDays; i++) {
      html += this.templates.wholeDayCol.applyTemplate({
        //day: date.get('dateString'),
        id: baseId + ':' + i,
        width: width + '%',
        left: i * width + '%'
      });
    }

    ;
    return html;
  },

  /**
   * gets HTML fragment of the horizontal time rows
   */
  getTimeRows: function getTimeRows() {
    var html = '';
    this.timeScale.each(function (time) {
      var index = time.get('index');
      html += this.templates.timeRow.applyTemplate({
        cls: time.get('minutes') % 60 ? 'cal-daysviewpanel-timeRow-off' : 'cal-daysviewpanel-timeRow-on',
        height: 100 / (24 * 60 / this.timeGranularity) + '%',
        time: time.get('minutes') % 60 ? '' : time.get('time')
      });
    }, this);
    return html;
  },

  /**
   * gets HTML fragment of the day columns
   */
  getDayColumns: function getDayColumns() {
    var html = '';
    var width = 100 / this.numOfDays;

    for (var i = 0; i < this.numOfDays; i++) {
      html += this.templates.dayColumn.applyTemplate({
        width: width + '%',
        left: i * width + '%',
        overRows: this.getOverRows(i)
      });
    }

    return html;
  },

  /**
   * gets HTML fragment of the time over rows
   */
  getOverRows: function getOverRows(dayIndex) {
    var html = '',
        baseId = Ext.id();
    this.timeScale.each(function (time, index, totalCount) {
      var cls = 'cal-daysviewpanel-daycolumn-row-' + (time.get('minutes') % 60 ? 'off' : 'on');

      if (index + 1 == totalCount) {
        cls += ' cal-daysviewpanel-daycolumn-row-last';
      }

      html += this.templates.overRow.applyTemplate({
        id: baseId + ':' + dayIndex + ':' + index,
        cls: cls,
        height: 100 / (24 * 60 / this.timeGranularity) + '%',
        time: time.get('time')
      });
    }, this);
    return html;
  },

  /**
   * inits all tempaltes of this view
   */
  initTemplates: function initTemplates() {
    var ts = this.templates || {};
    ts.master = new Ext.XTemplate('<div class="cal-daysviewpanel" hidefocus="true">', '<div class="cal-daysviewpanel-viewport">', '<div class="cal-daysviewpanel-header">', '<div class="cal-daysviewpanel-header-inner">', '<div class="cal-daysviewpanel-header-offset">{header}</div>', '</div>', '<div class="x-clear"></div>', '</div>', '<div class="cal-daysviewpanel-scroller">', '<div class="cal-daysviewpanel-cropper">{body}</div>', '</div>', '</div>', '<a href="#" class="cal-daysviewpanel-focus" tabIndex="-1"></a>');
    ts.header = new Ext.XTemplate('<div class="cal-daysviewpanel-daysheader">{daysHeader}</div>', '<div class="cal-daysviewpanel-wholedayheader-scroller">', '<div class="cal-daysviewpanel-wholedayheader">', '<div class="cal-daysviewpanel-wholedayheader-daycols">{wholeDayCols}</div>', '</div>', '</div>');
    ts.dayHeader = new Ext.XTemplate('<div class="cal-daysviewpanel-dayheader" style="height: {height}; width: {width}; left: {left};">' + '<div class="cal-daysviewpanel-dayheader-day-wrap">' + '<div class="cal-daysviewpanel-dayheader-day">{day}</div>' + '</div>', '</div>');
    ts.wholeDayCol = new Ext.XTemplate('<div class="cal-daysviewpanel-body-wholedaycolumn" style="left: {left}; width: {width};">' + '<div id="{id}" class="cal-daysviewpanel-datetime cal-daysviewpanel-body-wholedaycolumn-over">&#160;</div>' + '</div>');
    ts.body = new Ext.XTemplate('<div class="cal-daysviewpanel-body">', '<div class="cal-daysviewpanel-body-timecolumn">{timeRows}</div>', '<div class="cal-daysviewpanel-body-daycolumns">{dayColumns}</div>', '</div>');
    ts.timeRow = new Ext.XTemplate('<div class="{cls}" style="height: {height}; top: {top};">', '<div class="cal-daysviewpanel-timeRow-time">{time}</div>', '</div>');
    ts.dayColumn = new Ext.XTemplate('<div class="cal-daysviewpanel-body-daycolumn" style="left: {left}; width: {width}; height: 100%">', '<div class="cal-daysviewpanel-body-daycolumn-inner">&#160;</div>', '{overRows}', '<img src="', Ext.BLANK_IMAGE_URL, '" class="cal-daysviewpanel-body-daycolumn-hint-above" />', '<img src="', Ext.BLANK_IMAGE_URL, '" class="cal-daysviewpanel-body-daycolumn-hint-below" />', '</div>');
    ts.overRow = new Ext.XTemplate('<div id="{id}" class="cal-daysviewpanel-datetime cal-daysviewpanel-daycolumn-row" style="height: {height};">' + '<div class="{cls}" >{time}</div>' + '</div>');
    ts.event = new Ext.XTemplate('<div id="{id}" class="cal-daysviewpanel-event {extraCls}" style="width: {width}; height: {height}; left: {left}; top: {top}; z-index: {zIndex}; background-color: {bgColor}; border-image: {infoColors};">', '<div class="cal-daysviewpanel-event-header" style="background-color: {bgColor};">', '<div class="cal-daysviewpanel-event-header-inner" style="color: {textColor}; background-color: {bgColor}; z-index: {zIndex};">{startTime}</div>', '<div class="cal-daysviewpanel-event-header-icons">', '<tpl for="statusIcons">', '<img src="', Ext.BLANK_IMAGE_URL, '" class="cal-status-icon {status}-{[parent.textColor == \'#FFFFFF\' ? \'white\' : \'black\']}" ext:qtip="{[this.encode(values.text)]}" />', '</tpl>', '</div>', '</div>', '<div class="cal-daysviewpanel-event-body">{[Ext.util.Format.nl2br(Ext.util.Format.htmlEncode(values.summary))]}</div>', '<div class="cal-daysviewpanel-event-tags">{tagsHtml}</div>', '</div>', {
      encode: function encode(v) {
        return Tine.Tinebase.common.doubleEncode(v);
      }
    });
    ts.wholeDayEvent = new Ext.XTemplate('<div id="{id}" class="cal-daysviewpanel-event {extraCls}" style="width: {width}; height: {height}; left: {left}; top: {top}; z-index: {zIndex}; background-color: {bgColor}; border-color: {color};">' + '<div class="cal-daysviewpanel-wholedayevent-tags">{tagsHtml}</div>' + '<div class="cal-daysviewpanel-wholedayevent-body">{[Ext.util.Format.nl2br(Ext.util.Format.htmlEncode(values.summary))]}</div>' + '<div class="cal-daysviewpanel-event-header-icons" style="background-color: {bgColor};" >' + '<tpl for="statusIcons">' + '<img src="', Ext.BLANK_IMAGE_URL, '" class="cal-status-icon {status}-black" ext:qtip="{[this.encode(values.text)]}" />', '</tpl>' + '</div>' + '</div>', {
      encode: function encode(v) {
        return Tine.Tinebase.common.doubleEncode(v);
      }
    });

    for (var k in ts) {
      var t = ts[k];

      if (t && typeof t.compile == 'function' && !t.compiled) {
        t.disableFormats = true;
        t.compile();
      }
    }

    this.templates = ts;
  }
});
Ext.reg('Tine.Calendar.DaysView', Tine.Calendar.DaysView);

/***/ }),

/***/ 1776:
/***/ (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__(1777);
if(typeof content === 'string') content = [[module.i, content, '']];
// Prepare cssTransformation
var transform;

var options = {"hmr":true}
options.transform = transform
// add the styles to the DOM
var update = __webpack_require__(17)(content, options);
if(content.locals) module.exports = content.locals;
// Hot Module Replacement
if(false) {}

/***/ }),

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

var escape = __webpack_require__(103);
exports = module.exports = __webpack_require__(16)(false);
// imports


// module
exports.push([module.i, ".cal-print-marker { /* NOTE: this has to be the first line here. @see js/Printer/DaysView.js */\n    top:0;\n}\n\n/********************************* Header *********************************/\n.cal-daysviewpanel-header {\n    position: relative;\n    border-bottom: 1px solid #F0F0F0;\n    z-index: 5000;\n}\n\n.cal-daysviewpanel-header-inner {\n    position: relative;\n    /*background:#F9F9F9 url(../../library/ExtJS/resources/images/default/grid/grid3-hrow.gif) repeat-x scroll 0 top;*/\n}\n\n.cal-daysviewpanel-dayheader-today, .cal-daysviewpanel-dayheader-day-wrap:hover {\n    background:#EBF3FD;\n    /*url(../../library/ExtJS/resources/images/default/grid/grid3-hrow-over.gif) repeat-x scroll 0 bottom;*/\n    /*cursor: pointer; see ticket #1484*/\n}\n\n.cal-daysviewpanel-header-offset {\n    position: relative;\n    /*right:0;*/\n    top:0;\n}\n\n.cal-daysviewpanel-daysheader {\n    height: 21px;\n    margin-left:45px;\n    margin-right:15px;\n    cursor:default;\n    padding:1px 0 0;\n    margin-bottom: 2px;\n}\n\n.cal-daysviewpanel-dayheader {\n    float: left;\n}\n\n.cal-daysviewpanel-dayheader-day {\n    padding-top: 3px;\n    text-align: center;\n    color:black;\n    font-family:arial,tahoma,helvetica,sans-serif;\n    font-size:11px;\n    font-size-adjust:none;\n    font-style:normal;\n    font-variant:normal;\n    font-weight:normal;\n    line-height:normal;\n    white-space:nowrap;\n    overflow: hidden;\n}\n\n.cal-daysviewpanel-dayheader-day-wrap {\n    border-left: 3px double #E1E1E1;\n    height: 23px;\n}\n\n.cal-daysviewpanel-wholedayheader-scroller {\n    overflow-y: scroll;\n    overflow-x: hidden;\n}\n\n.cal-daysviewpanel-wholedayheader {\n    position: relative;\n    margin-left:45px;\n}\n/********************************* Body *********************************/\n.cal-daysviewpanel {\n    overflow: hidden;\n}\n\n.cal-daysviewpanel-body {\n    position: relative;\n    top: 0px;\n    left: 0px;\n    margin-bottom: 10px;\n    margin-top: 10px;\n}\n\n.cal-daysviewpanel-scroller {\n    border-top: 1px solid #D0D0D0;\n    overflow-y: scroll;\n    overflow-x: hidden;\n    position:relative;\n}\n\n.cal-daysviewpanel-body-daycolumns {\n    position:absolute;\n    left:45px;\n    right:0;\n    top:0;\n    height: 100%;\n    border-bottom: 1px solid #EDEDED;\n}\n\n.cal-daysviewpanel-body-daycolumn {\n    float: left;\n    position: absolute;\n    overflow: hidden;\n}\n\n.cal-daysviewpanel-body-daycolumn-hint-above {\n    width: 9px;\n    height: 9px;\n    background-image: url(" + escape(__webpack_require__(545)) + ");\n    position: absolute;\n    right: 5px;\n    z-index: 1000;\n    cursor: pointer;\n    display: none;\n}\n\n.cal-daysviewpanel-body-daycolumn-hint-below {\n    width: 9px;\n    height: 9px;\n    background-image: url(" + escape(__webpack_require__(219)) + ");\n    position: absolute;\n    right: 5px;\n    z-index: 1000;\n    cursor: pointer;\n    display: none;\n}\n\n.cal-daysviewpanel-body-cropDayTime .cal-daysviewpanel-body-daycolumn-hint-above,\n.cal-daysviewpanel-body-cropDayTime .cal-daysviewpanel-body-daycolumn-hint-below {\n    display: none !important;\n}\n\n.cal-daysviewpanel-body-daycolumn-today {\n    background-color: #EBF3FD;\n}\n\n.cal-daysviewpanel-body-daycolumn-inner {\n    border-left: 3px double #EDEDED;\n    height:100%;\n    position:absolute;\n    top:0;\n}\n\n.cal-daysviewpanel-daycolumn-row {\n    margin-left: 3px;\n    text-align: right;\n    font-family:arial,tahoma,helvetica,sans-serif;\n    font-size:10px;\n    font-size-adjust:none;\n    font-style:normal;\n    font-variant:normal;\n    font-weight:normal;\n    line-height:normal;\n    white-space:nowrap;\n    color: #FFFFFF;\n}\n\n.cal-daysviewpanel-body-daycolumn-today .cal-daysviewpanel-daycolumn-row {\n    color: #EBF3FD;\n}\n\n.cal-daysviewpanel-daycolumn-row:hover {\n    background-color:#DFE8F6;\n    color: #999999;\n    /*cursor: pointer; see ticket #1484*/\n}\n\n.cal-daysviewpanel-body-timecolumn {\n    position: absolute;\n    left: 0px;\n    top: 0px;\n    float: left;\n    width: 45px;\n    height: 100%;\n    margin-top: -8px;\n}\n\n.cal-daysviewpanel-timeRow-time {\n    height:100%;\n    width: 40px;\n    padding-top: 2px;\n    text-align: right;\n    color:black;\n    font-family:arial,tahoma,helvetica,sans-serif;\n    font-size:11px;\n    font-size-adjust:none;\n    font-style:normal;\n    font-variant:normal;\n    font-weight:normal;\n    line-height:normal;\n    white-space:nowrap;\n}\n\n.cal-daysviewpanel-timeRow-on .cal-daysviewpanel-timeRow-time{\n    border-top: 1px solid transparent;\n}\n.cal-daysviewpanel-timeRow-off .cal-daysviewpanel-timeRow-time{\n    border-top: 1px dotted transparent;\n}\n\n.cal-daysviewpanel-daycolumn-row-on,\n.cal-daysviewpanel-daycolumn-row-off {\n    height: 100%;\n}\n\n.cal-daysviewpanel-daycolumn-row-off {\n    border-top: 1px dotted #EDEDED;\n}\n\n.cal-daysviewpanel-daycolumn-row-on {\n    border-top: 1px solid #EDEDED;\n}\n\n/********************************* Events *********************************/\n.cal-daysviewpanel-event {\n    min-height: 16px;\n    margin-left: 3px;\n    /*background: #EDEDED url(../../images/white-gradiend.png) repeat-y right;*/\n    /*border-radius: 8px;*/\n    position: absolute;\n    border: 3px solid #808080;\n    overflow: hidden;\n\n    text-align: left;\n    color:black;\n    font-family:arial,tahoma,helvetica,sans-serif;\n    font-size:11px;\n    font-size-adjust:none;\n    font-style:normal;\n    font-variant:normal;\n    font-weight:normal;\n    line-height:normal;\n    white-space:nowrap;\n    border-top: none;\n    border-bottom: none;\n    border-right: none;\n}\n\n.cal-daysviewpanel-scroller .cal-daysviewpanel-event {\n    box-sizing: border-box;\n    border-top: 1px solid white !important;\n}\n.cal-daysviewpanel-scroller .cal-daysviewpanel-body-daycolumn-today .cal-daysviewpanel-event {\n    border-top: 1px solid #EBF3FD !important;\n}\n/*.ext-gecko .cal-daysviewpanel-event {*/\n/*    -moz-border-radius: 8px;*/\n/*}*/\n\n/*.ext-safari .cal-daysviewpanel-event {*/\n/*    -webkit-border-radius: 8px;*/\n/*}*/\n\n/*!** todo: add khtml switch **!*/\n/*.cal-daysviewpanel-event {*/\n/*    -khtml-border-radius: 8px;*/\n/*}*/\n\n.cal-daysviewpanel-event-croptop {\n    border-top-style: none;\n    /*border-top-left-radius: 0px;*/\n    /*border-top-right-radius: 0px;*/\n}\n\n/*.ext-gecko .cal-daysviewpanel-event-croptop {*/\n/*    -moz-border-radius-topleft: 0px;*/\n/*    -moz-border-radius-topright: 0px;*/\n/*}*/\n\n/*.ext-safari .cal-daysviewpanel-event-croptop {*/\n/*    -webkit-border-top-left-radius: 0px;*/\n/*    -webkit-border-top-right-radius: 0px;*/\n/*}*/\n\n/*!** todo: add khtml switch **!*/\n/*.cal-daysviewpanel-event-croptop {*/\n/*    -khtml-border-top-left-radius: 0px;*/\n/*    -khtml-border-top-right-radius: 0px;*/\n/*}*/\n\n.cal-daysviewpanel-event-cropbottom {\n    border-bottom-style: none;\n    /*border-bottom-left-radius: 0px;*/\n    /*border-bottom-right-radius: 0px;*/\n}\n\n/*.ext-gecko .cal-daysviewpanel-event-cropbottom {*/\n/*    -moz-border-radius-bottomleft: 0px;*/\n/*    -moz-border-radius-bottomright: 0px;*/\n/*}*/\n\n/*.ext-safari .cal-daysviewpanel-event-cropbottom {*/\n/*    -webkit-border-bottom-left-radius: 0px;*/\n/*    -webkit-border-bottom-right-radius: 0px;*/\n/*}*/\n\n/*!** todo: add khtml switch **!*/\n/*.cal-daysviewpanel-event-cropbottom {*/\n/*    -khtml-border-bottom-left-radius: 0px;*/\n/*    -khtml-border-bottom-right-radius: 0px;*/\n/*}*/\n\n.cal-daysviewpanel-event-drop-nodrop .x-dd-drop-icon {\n    left: 3px;\n    top: 0px;\n    background-color: transparent;\n    background-image:url(" + escape(__webpack_require__(526)) + ");\n}\n\n.cal-daysviewpanel-event-drop-ok .x-dd-drop-icon {\n    left: 3px;\n    top: 0px;\n    background-image:url(" + escape(__webpack_require__(1778)) + ");\n}\n\n.cal-daysviewpanel-event-drop-nodrop-WHITE .x-dd-drop-icon{\n    left: 3px;\n    top: 0px;\n    background-image:url(" + escape(__webpack_require__(1779)) + ") !important;\n}\n\n.cal-daysviewpanel-event-drop-ok-WHITE .x-dd-drop-icon{\n    left: 3px;\n    top: 0px;\n    background-image:url(" + escape(__webpack_require__(1780)) + ") !important;\n}\n\n.cal-daysviewpanel-event-header {\n    width: 100%;\n    position: absolute;\n    top: -1px;\n    height: 14px;\n    background-color: #808080;\n    /*border-top-left-radius: 8px;*/\n    /*border-top-right-radius: 8px;*/\n    overflow: hidden;\n}\n\n.cal-daysviewpanel-event-editgrant .cal-daysviewpanel-event-header {\n    cursor: move;\n}\n\n/*.ext-gecko .cal-daysviewpanel-event-header {*/\n/*    -moz-border-radius-topleft: 8px;*/\n/*    -moz-border-radius-topright: 8px;*/\n/*}*/\n\n/*.ext-safari .cal-daysviewpanel-event-header {*/\n/*    -webkit-border-top-left-radius: 8px;*/\n/*    -webkit-border-top-right-radius: 8px;*/\n/*}*/\n\n/*!** todo: add khtml switch **!*/\n/*.cal-daysviewpanel-event-header {*/\n/*    -khtml-border-top-left-radius: 8px;*/\n/*    -khtml-border-top-right-radius: 8px;*/\n/*}*/\n\n.cal-daysviewpanel-event-croptop .cal-daysviewpanel-event-header {\n    display: none;\n    border-top-style: none;\n    /*border-top-left-radius: 0px;*/\n    /*border-top-right-radius: 0px;*/\n}\n\n/*.ext-gecko .cal-daysviewpanel-event-croptop .cal-daysviewpanel-event-header {*/\n/*    -moz-border-radius-topleft: 0px;*/\n/*    -moz-border-radius-topright: 0px;*/\n/*}*/\n\n/*.ext-safari .cal-daysviewpanel-event-croptop .cal-daysviewpanel-event-header {*/\n/*    -webkit-border-top-left-radius: 0px;*/\n/*    -webkit-border-top-right-radius: 0px;*/\n/*}*/\n\n/*!** todo: add khtml switch **!*/\n/*.cal-daysviewpanel-event-croptop .cal-daysviewpanel-event-header {*/\n/*    -khtml-border-top-left-radius: 0px;*/\n/*    -khtml-border-top-right-radius: 0px;*/\n/*}*/\n\n.cal-daysviewpanel-event-header-inner {\n    color: white;\n    position: absolute;\n    top: 2px;\n    left: 2px;\n}\n\n.cal-daysviewpanel-event-header-icons {\n    position: absolute;\n    right: 4px;\n    top: 2px;\n}\n\n.cal-daysviewpanel-wholedayheader .cal-daysviewpanel-event-header-icons {\n    /*background: #EDEDED url(../../images/white-gradiend.png) repeat-y right;*/\n    padding-left: 2px;\n    top: 3px;\n}\n\n.cal-daysviewpanel-wholedayheader .cal-daysviewpanel-event-cropright  .cal-daysviewpanel-event-header-icons {\n    background: transparent;\n}\n\n.cal-daysviewpanel-event-drop-ok .cal-daysviewpanel-event-header-inner,\n.cal-daysviewpanel-event-drop-nodrop .cal-daysviewpanel-event-header-inner,\n.cal-daysviewpanel-event-drop-ok-WHITE .cal-daysviewpanel-event-header-inner,\n.cal-daysviewpanel-event-drop-nodrop-WHITE .cal-daysviewpanel-event-header-inner {\n    left: 17px;\n}\n\n.cal-daysviewpanel-event-body {\n    position: absolute;\n    top: 13px;\n    padding: 2px 2px 0px 2px;\n    white-space: normal;\n}\n\n.cal-daysviewpanel-event-tags {\n    position: absolute;\n    right: 1px;\n    bottom: 4px;\n}\n\n.cal-event-active,\n.cal-daysviewpanel-event-active {\n    font-weight: bold;\n}\n\n.cal-daysviewpanel-event-onedit {\n    border-style: dashed;\n}\n\n/****************************** Whole Day Events ******************************/\n.cal-daysviewpanel-wholedayheader-daycols {\n    position: absolute;\n    top: 0px;\n    width: 100%;\n    height: 100%;\n}\n\n.cal-daysviewpanel-body-wholedaycolumn {\n    position: absolute;\n    height: 100%;\n}\n\n.cal-daysviewpanel-body-wholedaycolumn-over {\n    width: 100%;\n    height: 100%;\n    /*margin-left: 3px;*/\n}\n\n.cal-daysviewpanel-body-wholedaycolumn-over:hover {\n    background-color:#DFE8F6;\n    /*cursor: pointer; see ticket #1484*/\n}\n\n.cal-daysviewpanel-wholedayevent-body {\n    margin-top: 1px;\n    margin-left: 1px;\n    cursor: move;\n    padding: 0px 4px;\n    white-space: normal;\n    height: 13px;\n    word-break: break-all;\n    overflow: hidden;\n}\n\n.cal-daysviewpanel-wholedayevent-tags {\n    padding: 1px 2px 0 3px;\n}\n\n.cal-daysviewpanel-event-cropleft {\n    border-left-style: none;\n    border-top-left-radius: 0px;\n    border-bottom-left-radius: 0px;\n}\n\n/*.ext-gecko .cal-daysviewpanel-event-cropleft {*/\n/*    -moz-border-radius-topleft: 0px;*/\n/*    -moz-border-radius-bottomleft: 0px;*/\n/*}*/\n\n/*.ext-safari .cal-daysviewpanel-event-cropleft {*/\n/*    -webkit-border-top-left-radius: 0px;*/\n/*    -webkit-border-bottom-left-radius: 0px;*/\n/*}*/\n\n/*!** todo: add khtml switch **!*/\n/*.cal-daysviewpanel-event-cropleft {*/\n/*    -khtml-border-top-left-radius: 0px;*/\n/*    -khtml-border-bottom-left-radius: 0px;*/\n/*}*/\n\n.cal-daysviewpanel-event-cropright {\n    background-image: none;\n    border-right-style: hidden;\n    /*border-top-right-radius: 0px;*/\n    /*border-bottom-right-radius: 0px;*/\n}\n\n/*.ext-gecko .cal-daysviewpanel-event-cropright {*/\n/*    -moz-border-radius-topright: 0px;*/\n/*    -moz-border-radius-bottomright: 0px;*/\n/*}*/\n\n/*.ext-safari .cal-daysviewpanel-event-cropright {*/\n/*    -webkit-border-top-right-radius: 0px;*/\n/*    -webkit-border-bottom-right-radius: 0px;*/\n/*}*/\n\n/*!** todo: add khtml switch **!*/\n/*.cal-daysviewpanel-event-cropright {*/\n/*    -khtml-border-top-right-radius: 0px;*/\n/*    -khtml-border-bottom-right-radius: 0px;*/\n/*}*/\n\n.cal-daysviewpanel-wholedayevent-body .x-form-text {\n    position: absolute;\n    top: 0px;\n    /*padding-top: 0px;*/\n    /*padding-left: 0px;*/\n}\n.cal-daysviewpanel-wholedayevent-body .x-form-field {\n    height: 11px;\n    font-size: 10.5px;\n    margin-top: 1px;\n}\n\n.cal-daysviewpanel-wholedayheader .cal-daysviewpanel-event-rzduration {\n    display: none;\n}\n\n.x-dd-drag-ghost .cal-daysviewpanel-wholedayevent-body {\n    margin-left: 15px;\n}", ""]);

// exports


/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='UTF-8' standalone='no'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg xmlns:dc='http://purl.org/dc/elements/1.1/' xmlns:cc='http://creativecommons.org/ns%23' xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns%23' xmlns:svg='http://www.w3.org/2000/svg' xmlns='http://www.w3.org/2000/svg' xmlns:sodipodi='http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd' xmlns:inkscape='http://www.inkscape.org/namespaces/inkscape' version='1.1' id='Ebene_1' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' sodipodi:docname='icon_ok_3.svg' inkscape:version='0.92.4 (5da689c313, 2019-01-14)' width='42.5' height='42.5'%3E%3Cmetadata id='metadata3798'%3E%3Crdf:RDF%3E%3Ccc:Work rdf:about=''%3E%3Cdc:format%3Eimage/svg+xml%3C/dc:format%3E%3Cdc:type rdf:resource='http://purl.org/dc/dcmitype/StillImage'/%3E%3Cdc:title/%3E%3C/cc:Work%3E%3C/rdf:RDF%3E%3C/metadata%3E%3Cdefs id='defs3796'/%3E%3Csodipodi:namedview pagecolor='%23ffffff' bordercolor='%23666666' borderopacity='1' objecttolerance='10' gridtolerance='10' guidetolerance='10' inkscape:pageopacity='0' inkscape:pageshadow='2' inkscape:window-width='1680' inkscape:window-height='1013' id='namedview3794' showgrid='false' inkscape:zoom='34.872843' inkscape:cx='12.965945' inkscape:cy='20.160004' inkscape:window-x='1366' inkscape:window-y='0' inkscape:window-maximized='1' inkscape:current-layer='Ebene_1' inkscape:snap-grids='true' inkscape:snap-to-guides='true'/%3E %3Cpath stroke='white' fill='white' id='Icon_Zeiterfassung_7_' d='M32.7,21.2c0-2.1-0.5-4-1.6-5.8c-1-1.8-2.4-3.2-4.2-4.2c-1.8-1-3.7-1.6-5.8-1.6s-4,0.5-5.8,1.6 s-3.2,2.4-4.2,4.2s-1.6,3.7-1.6,5.8s0.5,4,1.6,5.8c1,1.8,2.4,3.2,4.2,4.2c1.8,1,3.7,1.6,5.8,1.6s4-0.5,5.8-1.6 c1.8-1,3.2-2.4,4.2-4.2C32.2,25.2,32.7,23.3,32.7,21.2z M35.3,21.2c0,2.6-0.6,4.9-1.9,7.1c-1.3,2.2-3,3.9-5.2,5.2 c-2.2,1.3-4.5,1.9-7.1,1.9s-4.9-0.6-7.1-1.9c-2.2-1.3-3.9-3-5.2-5.2S7,23.7,7,21.2s0.6-4.9,1.9-7.1s3-3.9,5.2-5.2S18.6,7,21.2,7 s4.9,0.6,7.1,1.9s3.9,3,5.2,5.2C34.7,16.2,35.3,18.6,35.3,21.2z' style='fill:%23000000;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none'/%3E %3Cpath d='M 29.5,17.5 18.6,28.4 c -0.2,0.2 -0.5,0.3 -0.8,0.3 -0.3,0 -0.6,-0.1 -0.8,-0.3 L 11.6,23 c -0.2,-0.2 -0.3,-0.5 -0.3,-0.8 0,-0.3 0.1,-0.6 0.3,-0.8 l 0.8,-0.8 c 0.2,-0.2 0.5,-0.3 0.8,-0.3 0.3,0 0.6,0.1 0.8,0.3 l 3.8,3.8 9.3,-9.3 c 0.2,-0.2 0.5,-0.3 0.8,-0.3 0.3,0 0.6,0.1 0.8,0.3 l 0.8,0.8 c 0.2,0.2 0.3,0.5 0.3,0.8 0,0.3 -0.1,0.6 -0.3,0.8 z' id='path3791' style='fill:%23000000;stroke:%23ffffff;opacity:1;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none' inkscape:connector-curvature='0' sodipodi:nodetypes='sssssssssscssssss'/%3E %3Cpath style='fill:%23000000;stroke-width:0.08110687' d='M 19.125,34.733024 C 15.316601,34.18476 11.924515,32.011554 9.7059841,28.698547 8.4848936,26.875052 7.8407638,25.030565 7.6098132,22.696094 7.1840093,18.392025 8.6563191,14.342595 11.713612,11.409035 15.007376,8.2485739 19.153341,6.98796 23.707538,7.7621855 c 2.619158,0.4452637 5.027722,1.7358137 7.10399,3.8064395 2.427171,2.420574 3.604583,4.987584 3.90241,8.50808 0.207931,2.457885 -0.258394,4.963279 -1.315663,7.068583 -1.961814,3.906492 -5.488072,6.640368 -9.633298,7.468607 -1.115102,0.222803 -3.495327,0.283914 -4.639977,0.119129 z m 3.924005,-1.552773 c 2.372256,-0.373317 4.848036,-1.656839 6.624563,-3.434379 1.698713,-1.699683 2.902817,-3.972643 3.375602,-6.372053 0.21831,-1.107934 0.19753,-3.450887 -0.04042,-4.557266 -0.653054,-3.036458 -2.549417,-5.925514 -4.92955,-7.510033 -1.457887,-0.970554 -3.022302,-1.6348773 -4.753614,-2.0186043 -1.187564,-0.2632106 -3.367194,-0.2620368 -4.596974,0.00248 -2.06698,0.4445854 -3.84698,1.3396983 -5.600806,2.8164913 -1.914217,1.611848 -3.3462315,4.098369 -3.9516633,6.861586 -0.212173,0.968368 -0.21091,3.63023 0.00218,4.603854 0.3370293,1.539881 0.9835263,3.038215 1.9266063,4.465142 0.630211,0.95354 1.887059,2.260007 2.796514,2.906917 1.165616,0.829122 2.914224,1.651039 4.268902,2.006562 1.417766,0.372079 3.384113,0.464502 4.878657,0.229308 z' id='path3804' inkscape:connector-curvature='0'/%3E%3Cpath style='fill:%23000000' d='M 19.294546,34.75972 C 15.727207,34.34612 12.201281,32.208974 9.9959125,29.123599 8.4181908,26.916321 7.6907838,24.755857 7.5581338,21.883181 7.3818079,18.064656 8.7003397,14.54371 11.33874,11.787624 c 2.155447,-2.2515892 4.781914,-3.6341086 7.826813,-4.1198775 1.031492,-0.1645593 3.384363,-0.1239307 4.501432,0.077729 2.720139,0.4910561 5.06028,1.7431397 7.144543,3.8226615 2.42075,2.415243 3.595862,4.96585 3.900869,8.466925 0.163938,1.881785 -0.106405,4.072335 -0.707332,5.73141 -0.52113,1.438765 -1.604137,3.243159 -2.696997,4.493457 -1.823464,2.08615 -4.653569,3.765023 -7.242317,4.296279 -1.417312,0.290858 -3.318423,0.371948 -4.771205,0.203512 z m 4.210225,-1.653273 c 2.530773,-0.553938 5.12212,-2.069676 6.701727,-3.919994 1.381694,-1.618487 2.362962,-3.591831 2.802138,-5.635139 0.257367,-1.197421 0.254081,-3.534487 -0.0067,-4.76001 -0.60807,-2.857698 -2.44092,-5.715419 -4.702459,-7.331937 C 26.934719,10.483856 24.83187,9.583219 23.13979,9.2495051 22.052157,9.0350009 19.853166,9.0552712 18.744738,9.2900185 c -2.548584,0.5397494 -4.995441,1.9741505 -6.761764,3.9638955 -1.421602,1.601419 -2.5591074,4.07651 -2.8803477,6.267329 -0.1596566,1.088838 -0.1187353,3.047237 0.084696,4.053332 0.4738759,2.343614 1.8531797,4.789198 3.6484027,6.468824 1.775474,1.661148 4.29206,2.834642 6.897577,3.216367 0.562805,0.08246 3.180463,-0.02396 3.771469,-0.153319 z' id='path3806' inkscape:connector-curvature='0'/%3E%3C/svg%3E\""

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='UTF-8' standalone='no'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg xmlns:dc='http://purl.org/dc/elements/1.1/' xmlns:cc='http://creativecommons.org/ns%23' xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns%23' xmlns:svg='http://www.w3.org/2000/svg' xmlns='http://www.w3.org/2000/svg' xmlns:sodipodi='http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd' xmlns:inkscape='http://www.inkscape.org/namespaces/inkscape' version='1.1' id='Ebene_1' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' sodipodi:docname='icon_stop_white.svg' inkscape:version='0.92.4 (5da689c313, 2019-01-14)' width='42.5' height='42.5'%3E%3Cmetadata id='metadata9'%3E%3Crdf:RDF%3E%3Ccc:Work rdf:about=''%3E%3Cdc:format%3Eimage/svg+xml%3C/dc:format%3E%3Cdc:type rdf:resource='http://purl.org/dc/dcmitype/StillImage'/%3E%3Cdc:title/%3E%3C/cc:Work%3E%3C/rdf:RDF%3E%3C/metadata%3E%3Cdefs id='defs7'/%3E%3Csodipodi:namedview pagecolor='%23ffffff' bordercolor='%23666666' borderopacity='1' objecttolerance='10' gridtolerance='10' guidetolerance='10' inkscape:pageopacity='0' inkscape:pageshadow='2' inkscape:window-width='1680' inkscape:window-height='1013' id='namedview5' showgrid='false' inkscape:zoom='11.105882' inkscape:cx='25.387333' inkscape:cy='21.628503' inkscape:window-x='1366' inkscape:window-y='0' inkscape:window-maximized='1' inkscape:current-layer='Ebene_1'/%3E %3Cpath d='M32.8,21.3c0-2.1-0.5-4-1.6-5.8c-1-1.8-2.4-3.2-4.2-4.2c-1.8-1-3.7-1.6-5.8-1.6s-4,0.5-5.8,1.6s-3.2,2.4-4.2,4.2 s-1.6,3.7-1.6,5.8s0.5,4,1.6,5.8c1,1.8,2.4,3.2,4.2,4.2c1.8,1,3.7,1.6,5.8,1.6s4-0.5,5.8-1.6c1.8-1,3.2-2.4,4.2-4.2 C32.3,25.3,32.8,23.4,32.8,21.3z M35.4,21.3c0,2.6-0.6,4.9-1.9,7.1c-1.3,2.2-3,3.9-5.2,5.2c-2.2,1.3-4.5,1.9-7.1,1.9 s-4.9-0.6-7.1-1.9c-2.2-1.3-3.9-3-5.2-5.2s-1.9-4.5-1.9-7.1s0.6-4.9,1.9-7.1s3-3.9,5.2-5.2s4.5-1.9,7.1-1.9s4.9,0.6,7.1,1.9 s3.9,3,5.2,5.2C34.8,16.3,35.4,18.7,35.4,21.3z M30.4,29.1l-1.2,1.2c-0.2,0.2-0.4,0.2-0.6,0.2c-0.2,0-0.4-0.1-0.6-0.2l-6.7-6.7l-7,7 c-0.2,0.2-0.4,0.2-0.6,0.2c-0.2,0-0.4-0.1-0.6-0.2l-1.2-1.2c-0.2-0.2-0.2-0.4-0.2-0.6c0-0.2,0.1-0.4,0.2-0.6l7-7l-7.1-7 c-0.2-0.2-0.2-0.4-0.2-0.6s0.1-0.4,0.2-0.6l1.2-1.2c0.2-0.2,0.4-0.2,0.6-0.2s0.4,0.1,0.6,0.2l7,7l8.2-8.2c0.2-0.2,0.4-0.2,0.6-0.2 s0.4,0.1,0.6,0.2l1.2,1.2c0.2,0.2,0.2,0.4,0.2,0.6s-0.1,0.4-0.2,0.6l-8.2,8.2l6.7,6.7c0.2,0.2,0.2,0.4,0.2,0.6 C30.6,28.8,30.5,29,30.4,29.1z' id='path2' style='fill:%23ffffff'/%3E %3C/svg%3E\""

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cpath stroke='white' fill='white' id='Icon_Zeiterfassung_7_' d='M32.7,21.2c0-2.1-0.5-4-1.6-5.8c-1-1.8-2.4-3.2-4.2-4.2c-1.8-1-3.7-1.6-5.8-1.6s-4,0.5-5.8,1.6 s-3.2,2.4-4.2,4.2s-1.6,3.7-1.6,5.8s0.5,4,1.6,5.8c1,1.8,2.4,3.2,4.2,4.2c1.8,1,3.7,1.6,5.8,1.6s4-0.5,5.8-1.6 c1.8-1,3.2-2.4,4.2-4.2C32.2,25.2,32.7,23.3,32.7,21.2z M35.3,21.2c0,2.6-0.6,4.9-1.9,7.1c-1.3,2.2-3,3.9-5.2,5.2 c-2.2,1.3-4.5,1.9-7.1,1.9s-4.9-0.6-7.1-1.9c-2.2-1.3-3.9-3-5.2-5.2S7,23.7,7,21.2s0.6-4.9,1.9-7.1s3-3.9,5.2-5.2S18.6,7,21.2,7 s4.9,0.6,7.1,1.9s3.9,3,5.2,5.2C34.7,16.2,35.3,18.6,35.3,21.2z'/%3E %3Cpath stroke='white' fill='white' d='M29.5,17.5L18.6,28.4c-0.2,0.2-0.5,0.3-0.8,0.3c-0.3,0-0.6-0.1-0.8-0.3l-5.4-5.4c-0.2-0.2-0.3-0.5-0.3-0.8 c0-0.3,0.1-0.6,0.3-0.8l0.8-0.8c0.2-0.2,0.5-0.3,0.8-0.3s0.6,0.1,0.8,0.3l3.8,3.8l9.3-9.3c0.2-0.2,0.5-0.3,0.8-0.3 c0.3,0,0.6,0.1,0.8,0.3l0.8,0.8c0.2,0.2,0.3,0.5,0.3,0.8C29.8,17,29.7,17.3,29.5,17.5z'/%3E %3C/svg%3E\""

/***/ }),

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

Tine.Calendar.Printer.DaysViewRenderer = Ext.extend(Tine.Calendar.Printer.BaseRenderer, {
  paperHeight: 200,
  printMode: 'sheet',
  generateBody: function generateBody(view) {
    var mode = Ext.util.Format.capitalize(this.printMode),
        method = 'generate' + mode + 'HTML',
        me = this;
    return new Promise(function (fulfill, reject) {
      fulfill(me[method](view));
    });
  },

  /**
   * Returns the HTML that will be placed into the <head> element of th print window.
   * @param {Ext.Component} component The component to render
   * @return {String} The HTML fragment to place inside the print window's <head> element
   */
  getAdditionalHeaders: function getAdditionalHeaders(component) {
    var head = '<style type="text/css" title="text/css" media="screen,print">' + '@import url(library/ExtJS/resources/css/ext-all.css);' + '</style>';
    Ext.each(Ext.getDoc().query('style'), function (style) {
      if (style.innerText.match(/^\.cal-print-marker/)) {
        head += style.outerHTML;
      }
    });
    return head;
  },
  onBeforePrint: function onBeforePrint(document, view) {
    if (this.printMode == 'sheet') {
      this.useHtml2Canvas = true;

      if (view.cropDayTime) {
        var node = document.getElementById(this.panelId),
            cropper = node.getElementsByClassName('cal-daysviewpanel-cropper')[0],
            dayStartPx = view.getTimeOffset(view.dayStart);
        cropper.scrollTop = dayStartPx;
      }
    }
  },
  generateSheetHTML: function generateSheetHTML(view) {
    var node = view.el.dom.cloneNode(true),
        daysViewPanel = node.firstChild,
        header = node.getElementsByClassName('cal-daysviewpanel-wholedayheader-scroller')[0],
        scroller = node.getElementsByClassName('cal-daysviewpanel-scroller')[0],
        cropper = node.getElementsByClassName('cal-daysviewpanel-cropper')[0],
        body = node.getElementsByClassName('cal-daysviewpanel-body')[0],
        dayStartPx = view.getTimeOffset(view.dayStart),
        dayEndPx = view.getTimeOffset(view.dayEnd),
        fullHeight = view.getTimeOffset(view.startDate.add(Date.DAY, 1).add(Date.MINUTE, -1)),
        cropHeight = dayEndPx - dayStartPx + 20,
        scrollerHeight = view.cropDayTime ? cropHeight : fullHeight;
    daysViewPanel.id = this.panelId = Ext.id(); // resize header/scroller to fullsize
    // @TODO: if you have a lot of allDayEvents, your scroller gets smaller,
    //        this might be confusing in print

    header.style.height = Math.max(header.firstChild.style.height, header.style.height);
    scroller.style.height = scrollerHeight + 'px';
    scroller.style.width = null;
    return this.generateTitle(view) + node.innerHTML;
  },
  generateGridHTML: function generateGridHTML(view) {
    var daysHtml = this.splitDays(view.store, view.startDate, view.numOfDays),
        body = [];
    body.push(this.generateTitle(view));

    if (view.numOfDays === 1) {
      body.push(String.format('<div class="cal-print-day-singleday">{0}</div>', daysHtml[0]));
    } else if (view.numOfDays < 9) {
      if (view.numOfDays == 7 && view.startDate.format('w') == 1) {
        // iso week
        body.push(this.generateIsoWeek(daysHtml));
      } else {
        body.push(String.format('<table>{0}</table>', this.generateCalRows(daysHtml, 2)));
      }
    } else {
      body.push(String.format('<table>{0}</table>', this.generateCalRows(daysHtml, 2, true)));
    }

    return body.join("\n");
  },
  getTitle: function getTitle(view) {
    if (view.numOfDays == 1) {
      return String.format(view.dayFormatString + ' {3}', view.startDate.format('l'), view.startDate.format('j'), view.startDate.format('F'), view.startDate.format('Y'));
    } else {
      var endDate = view.startDate.add(Date.DAY, view.numOfDays - 1),
          startDayOfMonth = view.startDate.format('j. '),
          startMonth = view.startDate.format('F '),
          startYear = view.startDate.format('Y '),
          endDayOfMonth = endDate.format('j. '),
          endMonth = endDate.format('F '),
          endYear = endDate.format('Y '),
          week = view.numOfDays == 7 ? String.format(view.app.i18n._('Week {0} :'), view.startDate.add(Date.DAY, 1).getWeekOfYear()) + ' ' : '';
      if (startYear === endYear) startYear = '';
      if (startMonth === endMonth) startMonth = '';
      return week + startDayOfMonth + startMonth + startYear + ' - ' + endDayOfMonth + endMonth + endYear;
    }
  },
  generateIsoWeek: function generateIsoWeek(daysHtml) {
    var height = this.paperHeight / 4;
    return ['<table>', '<tr style="height: ' + height + 'mm;">', '<td class="cal-print-daycell" width="50%">', daysHtml[0], '</td>', '<td class="cal-print-daycell" width="50%">', daysHtml[3], '</td>', '</tr>', '<tr style="height: ' + height + 'mm;">', '<td class="cal-print-daycell" width="50%">', daysHtml[1], '</td>', '<td class="cal-print-daycell" width="50%">', daysHtml[4], '</td>', '</tr>', '<tr style="height: ' + height + 'mm;">', '<td class="cal-print-daycell" width="50%">', daysHtml[2], '</td>', '<td class="cal-print-daycell" width="50%">', '<table style="padding: 0;">', '<tr style="height: ' + height / 2 + 'mm;">', '<td class="cal-print-daycell" width="100%" style="padding: 0;">', daysHtml[5], '</td>', '</tr>', '<tr style="height: ' + height / 2 + 'mm;">', '<td class="cal-print-daycell" width="100%" style="padding: 0;">', daysHtml[6], '</td>', '</tr>', '</table>', '</tr>', '</table>'].join("\n");
  }
});

/***/ }),

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

/* 
 * Tine 2.0
 * 
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2007-2008 Metaways Infosystems GmbH (http://www.metaways.de)
 */
Ext.ns('Tine.Calendar');

__webpack_require__(1783);

__webpack_require__(1785);
/**
 * @namespace Tine.Calendar
 * @class Tine.Calendar.MonthView
 * @extends Ext.util.Observable
 * @constructor
 * @param {Object} config
 */


Tine.Calendar.MonthView = function (config) {
  Ext.apply(this, config);
  Tine.Calendar.MonthView.superclass.constructor.call(this);
  this.printRenderer = Tine.Calendar.Printer.MonthViewRenderer;
  this.addEvents(
  /**
   * @event click
   * fired if an event got clicked
   * @param {Tine.Calendar.Model.Event} event
   * @param {Ext.EventObject} e
   */
  'click',
  /**
   * @event contextmenu
   * fired if an event got contextmenu 
   * @param {Ext.EventObject} e
   */
  'contextmenu',
  /**
   * @event dblclick
   * fired if an event got dblclicked
   * @param {Tine.Calendar.Model.Event} event
   * @param {Ext.EventObject} e
   */
  'dblclick',
  /**
   * @event changeView
   * fired if user wants to change view
   * @param {String} requested view name
   * @param {mixed} start param of requested view
   */
  'changeView',
  /**
   * @event changePeriod
   * fired when period changed
   * @param {Object} period
   */
  'changePeriod',
  /**
   * @event addEvent
   * fired when a new event got inserted
   * 
   * @param {Tine.Calendar.Model.Event} event
   */
  'addEvent',
  /**
   * @event updateEvent
   * fired when an event go resised/moved
   * 
   * @param {Tine.Calendar.Model.Event} event
   */
  'updateEvent');
};

Ext.extend(Tine.Calendar.MonthView, Ext.Container, {
  /**
   * @cfg {Date} startDate
   * start date
   */
  startDate: new Date().clearTime(),

  /**
   * @cfg {String} newEventSummary
   * i18n._('New Event')
   */
  newEventSummary: 'New Event',

  /**
   * @cfg {String} calWeekString
   * i18n._('WK')
   */
  calWeekString: 'WK',

  /**
   * @cfg String moreString
   * i18n._('{0} more...')
   */
  moreString: '{0} more...',

  /**
   * @cfg {Array} monthNames
   * An array of textual month names which can be overriden for localization support (defaults to Date.monthNames)
   */
  monthNames: Date.monthNames,

  /**
   * @cfg {Array} dayNames
   * An array of textual day names which can be overriden for localization support (defaults to Date.dayNames)
   */
  dayNames: Date.dayNames,

  /**
   * @cfg {Number} startDay
   * Day index at which the week should begin, 0-based
   */
  startDay: Ext.DatePicker.prototype.startDay,

  /**
   * @cfg {Boolean} denyDragOnMissingEditGrant
   * deny drag action if edit grant for event is missing
   */
  denyDragOnMissingEditGrant: true,

  /**
   * @private {Date} toDay
   */
  toDay: null,

  /**
   * @private {Array} dateMesh
   */
  dateMesh: null,

  /**
   * @private {Tine.Calendar.ParallelEventsRegistry} parallelEventsRegistry
   */
  parallelEventsRegistry: null,
  cls: "cal-monthview",
  boxMinWidth: 550,

  /**
   * @private
   */
  afterRender: function afterRender() {
    Tine.Calendar.MonthView.superclass.afterRender.apply(this, arguments);
    this.initElements();
    this.getSelectionModel().init(this);
    this.mon(this.el, 'mousedown', this.onMouseDown, this);
    this.mon(this.el, 'dblclick', this.onDblClick, this);
    this.mon(this.el, 'click', this.onClick, this);
    this.mon(this.el, 'contextmenu', this.onContextMenu, this);
    this.mon(this.el, 'keydown', this.onKeyDown, this);
    this.initDragZone();
    this.initDropZone();
    this.updatePeriod({
      from: this.period.from
    }); // NOTE: store.getCount == 0 is no indicator for an unloaded store
    //       as the view just might be empty. If an unloded store is
    //       a problem here we have to find a smart solution

    this.onLoad.apply(this);
    this.rendered = true;
  },

  /**
   * @private calculates mesh of dates for month this.startDate is in
   */
  calcDateMesh: function calcDateMesh() {
    var mesh = [];
    var d = Date.parseDate(this.startDate.format('Y-m') + '-01 00:00:00', Date.patterns.ISO8601Long);

    while (d.getDay() != this.startDay) {
      d = d.add(Date.DAY, -1);
    }

    while (d.getMonth() != this.startDate.add(Date.MONTH, 1).getMonth()) {
      for (var i = 0; i < 7; i++) {
        mesh.push(d.add(Date.DAY, i).clone());
      }

      d = d.add(Date.DAY, 7);
    }

    this.dateMesh = mesh;
  },

  /**
   * returns index of dateCell given date is in
   * @param {Date} date
   */
  getDayCellIndex: function getDayCellIndex(date) {
    return Math.round((date.clearTime(true).getTime() - this.dateMesh[0].getTime()) / Date.msDAY);
  },

  /**
   * @private returns a child div in requested position
   * 
   * @param {dom} dayCell
   * @param {Number} pos
   * @return {dom}
   */
  getEventSlice: function getEventSlice(dayCell, pos) {
    pos = Math.abs(pos);

    for (var i = dayCell.childNodes.length; i <= pos; i++) {
      Ext.DomHelper.insertAfter(dayCell.lastChild, '<div class="cal-monthview-eventslice"/>');
    } // make sure cell is empty


    while (dayCell.childNodes[pos].innerHTML) {
      pos++;

      if (pos > dayCell.childNodes.length - 1) {
        Ext.DomHelper.insertAfter(dayCell.lastChild, '<div class="cal-monthview-eventslice"/>');
      }
    }

    return dayCell.childNodes[pos];
  },

  /**
   * returns period of currently displayed month
   * @return {Object}
   */
  getPeriod: function getPeriod() {
    // happens if month view is rendered first
    if (!this.dateMesh) {
      this.calcDateMesh();
    }

    return {
      from: this.dateMesh[0],
      until: this.dateMesh[this.dateMesh.length - 1].add(Date.DAY, 1)
    };
  },
  getSelectionModel: function getSelectionModel() {
    return this.selModel;
  },
  getTargetDateTime: function getTargetDateTime(e) {
    var target = e.getTarget('td.cal-monthview-daycell', 3);

    if (target) {
      var dateIdx = this.dayCells.indexOf(target),
          date = this.dateMesh[this.dayCells.indexOf(target)]; // date has no time part

      date.date_only = true;
      return date;
    }
  },
  getTargetEvent: function getTargetEvent(e) {
    var target = e.getTarget('div.cal-monthview-alldayevent', 10) || e.getTarget('div.cal-monthview-event', 10);

    if (target) {
      var parts = target.id.split(':');
      var event = this.store.getById(parts[1]);
    }

    return event;
  },

  /**
   * init month view
   */
  initComponent: function initComponent() {
    this.app = Tine.Tinebase.appMgr.get('Calendar');
    this.newEventSummary = this.app.i18n._hidden(this.newEventSummary);
    this.calWeekString = this.app.i18n._hidden(this.calWeekString);
    this.moreString = this.app.i18n._hidden(this.moreString); // redefine this props in case ext translations got included after this component

    this.monthNames = Date.monthNames;
    this.dayNames = Date.dayNames;
    this.startDay = Ext.DatePicker.prototype.startDay;
    this.initData(this.store);
    this.initTemplates();

    if (!this.selModel) {
      this.selModel = this.selModel || new Tine.Calendar.EventSelectionModel();
    }

    Tine.Calendar.MonthView.superclass.initComponent.apply(this, arguments);
  },

  /**
   * @private
   * @param {Ext.data.Store} ds
   */
  initData: function initData(ds) {
    if (this.store) {
      this.store.un("load", this.onLoad, this);
      this.store.un("beforeload", this.onBeforeLoad, this);
      this.store.un("add", this.onAdd, this);
      this.store.un("remove", this.onRemove, this);
      this.store.un("update", this.onUpdate, this);
    }

    if (ds) {
      ds.on("load", this.onLoad, this);
      ds.on("beforeload", this.onBeforeLoad, this);
      ds.on("add", this.onAdd, this);
      ds.on("remove", this.onRemove, this);
      ds.on("update", this.onUpdate, this);
    }

    this.store = ds;
  },

  /**
   * @private
   */
  initDragZone: function initDragZone() {
    this.dragZone = new Ext.dd.DragZone(this.el, {
      ddGroup: 'cal-event',
      view: this,
      scroll: false,
      getDragData: function getDragData(e) {
        var eventEl = e.getTarget('div.cal-monthview-alldayevent', 10) || e.getTarget('div.cal-monthview-event', 10);

        if (eventEl) {
          var parts = eventEl.id.split(':');
          var event = this.view.store.getById(parts[1]); // don't allow dragging with missing edit grant

          if (this.view.denyDragOnMissingEditGrant && !event.get('editGrant')) {
            return false;
          } // we need to clone an event with summary in


          var d = Ext.get(event.ui.domIds[0]).dom.cloneNode(true);
          var width = Ext.fly(eventEl).getWidth() * event.ui.domIds.length;
          Ext.fly(d).removeClass(['cal-monthview-alldayevent-cropleft', 'cal-monthview-alldayevent-cropright']);
          Ext.fly(d).setWidth(width);
          Ext.fly(d).setOpacity(0.5);
          d.id = Ext.id();
          return {
            scope: this.view,
            sourceEl: eventEl,
            event: event,
            ddel: d,
            selections: this.view.getSelectionModel().getSelectedEvents()
          };
        }
      },
      getRepairXY: function getRepairXY(e, dd) {
        Ext.fly(this.dragData.sourceEl).setOpacity(1, 1);
        return Ext.fly(this.dragData.sourceEl).getXY();
      }
    });
  },
  initDropZone: function initDropZone() {
    this.dd = new Ext.dd.DropZone(this.el.dom, {
      ddGroup: 'cal-event',
      notifyOver: function notifyOver(dd, e, data) {
        var target = e.getTarget('td.cal-monthview-daycell', 3);
        var event = data.event; // we dont support multiple dropping yet

        if (event) {
          data.scope.getSelectionModel().select(event);
        }

        return target && event && event.get('editGrant') ? 'cal-daysviewpanel-event-drop-ok' : 'cal-daysviewpanel-event-drop-nodrop';
      },
      notifyDrop: function notifyDrop(dd, e, data) {
        var v = data.scope;
        var target = e.getTarget('td.cal-monthview-daycell', 3);
        var targetDate = v.dateMesh[v.dayCells.indexOf(target)];

        if (targetDate) {
          var event = data.event;
          var diff = (targetDate.getTime() - event.get('dtstart').clearTime(true).getTime()) / Date.msDAY;

          if (!diff || !event.get('editGrant')) {
            return false;
          }

          event.beginEdit();
          event.set('dtstart', event.get('dtstart').add(Date.DAY, diff));
          event.set('dtend', event.get('dtend').add(Date.DAY, diff));
          event.endEdit();
          v.fireEvent('updateEvent', event);
        }

        return !!targetDate;
      }
    });
  },

  /**
   * @private
   */
  initElements: function initElements() {
    var E = Ext.Element;
    this.focusEl = new E(this.el.dom.firstChild);
    this.mainHd = new E(this.el.dom.lastChild.firstChild);
    this.mainBody = new E(this.el.dom.lastChild.lastChild);
    this.dayCells = Ext.DomQuery.select('td[class=cal-monthview-daycell]', this.mainBody.dom);
  },

  /**
   * inits all tempaltes of this view
   */
  initTemplates: function initTemplates() {
    var ts = this.templates || {};
    ts.allDayEvent = new Ext.XTemplate('<div id="{id}" class="cal-monthview-event cal-monthview-alldayevent {extraCls}" style="background-color: {bgColor};">' + '<div class="cal-event-icon {iconCls} cal-monthview-event-info-{[values.showInfo ? "show" : "hide"]}">' + '<div class="cal-monthview-alldayevent-summary" style="width: {width};">{[Ext.util.Format.htmlEncode(values.summary)]}</div>' + '</div>' + '</div>');
    ts.event = new Ext.XTemplate('<div id="{id}" class="cal-monthview-event {extraCls}" style="color: {color};">' + '<div class="cal-event-icon {iconCls}">' + '<div class="cal-monthview-event-summary">{startTime} {[Ext.util.Format.htmlEncode(values.summary)]}</div>' + '</div>' + '</div>');

    for (var k in ts) {
      var t = ts[k];

      if (t && typeof t.compile == 'function' && !t.compiled) {
        t.disableFormats = true;
        t.compile();
      }
    }

    this.templates = ts;
  },

  /**
   * @private
   * @param {Tine.Calendar.Model.Event} event
   */
  insertEvent: function insertEvent(event) {
    event.ui = new Tine.Calendar.MonthViewEventUI(event); //event.ui.render(this);

    var dtStart = event.get('dtstart');
    var startCellNumber = this.getDayCellIndex(dtStart);
    var dtEnd = event.get('dtend'); // 00:00 in users timezone is a spechial case where the user expects
    // something like 24:00 and not 00:00

    if (dtEnd.format('H:i') == '00:00') {
      dtEnd = dtEnd.add(Date.MINUTE, -1);
    }

    var endCellNumber = this.getDayCellIndex(dtEnd); // skip out of range events

    if (endCellNumber < 0 || startCellNumber >= this.dateMesh.length) {
      return;
    }

    var pos = this.parallelEventsRegistry.getPosition(event),
        attendeeRecord = this.ownerCt && this.ownerCt.attendee ? Tine.Calendar.Model.Attender.getAttendeeStore.getAttenderRecord(event.getAttendeeStore(), this.ownerCt.attendee) : event.getMyAttenderRecord(); // save some layout info

    event.ui.is_all_day_event = event.get('is_all_day_event') || startCellNumber != endCellNumber;
    event.ui.colorSet = event.colorSet = Tine.Calendar.colorMgr.getColor(event, attendeeRecord);
    event.ui.color = event.ui.colorSet.color;
    event.ui.bgColor = event.ui.colorSet.light;
    var data = {
      startTime: dtStart.format('H:i'),
      summary: event.getTitle(),
      color: event.ui.color,
      bgColor: event.ui.bgColor,
      width: '100%'
    };

    for (var i = Math.max(startCellNumber, 0); i <= Math.min(endCellNumber, this.dayCells.length - 1); i++) {
      var col = i % 7,
          row = Math.floor(i / 7);
      data.id = Ext.id() + '-event:' + event.get('id');
      event.ui.domIds.push(data.id);
      var tmpl = this.templates.event;
      data.extraCls = event.get('editGrant') ? 'cal-monthview-event-editgrant' : '';
      data.extraCls += ' cal-status-' + event.get('status');

      if (event.ui.is_all_day_event) {
        tmpl = this.templates.allDayEvent;
        data.color = 'black';

        if (i > startCellNumber) {
          data.extraCls += ' cal-monthview-alldayevent-cropleft';
        }

        if (i < endCellNumber) {
          data.extraCls += ' cal-monthview-alldayevent-cropright';
        } // show icon on startCell and leftCells


        data.showInfo = i == startCellNumber || i % 7 == 0; // adopt summary width NOTE: we need width in row

        if (data.showInfo && startCellNumber != endCellNumber) {
          var cols = (row == Math.floor(endCellNumber / 7) ? endCellNumber % 7 : 6) - col + 1;
          data.width = 100 * cols + '%';
        }
      }

      if (event.hasPoll()) {
        data.extraCls += ' cal-poll-event';
      }

      var posEl = this.getEventSlice(this.dayCells[i].lastChild, pos);
      var eventEl = tmpl.overwrite(posEl, data, true);

      if (event.dirty) {
        eventEl.setOpacity(0.5); // the event was selected before

        event.ui.onSelectedChange(true);
      }
    }
  },
  onLayout: function onLayout() {
    Tine.Calendar.MonthView.superclass.onLayout.apply(this, arguments);

    if (!this.mainBody) {
      return; // not rendered
    }

    var csize = this.container.getSize(true);
    var vw = csize.width; //this.el.setSize(csize.width, csize.height);

    var hsize = this.mainHd.getSize(true);
    var hdCels = this.mainHd.dom.firstChild.childNodes;
    Ext.fly(hdCels[0]).setWidth(50);

    for (var i = 1; i < hdCels.length; i++) {
      Ext.get(hdCels[i]).setWidth((vw - 50) / 7);
    }

    var rowHeight = (csize.height - hsize.height - 2) / Math.ceil(this.dateMesh.length / 7);
    var calRows = this.mainBody.dom.childNodes;

    for (var i = 0; i < calRows.length; i++) {
      Ext.get(calRows[i]).setHeight(rowHeight);
    }

    var dhsize = Ext.get(this.dayCells[0].firstChild).getSize();
    this.dayCellsHeight = rowHeight - dhsize.height;

    for (var i = 0; i < this.dayCells.length; i++) {
      Ext.get(this.dayCells[i].lastChild).setSize((vw - 50) / 7, this.dayCellsHeight);
    }

    this.layoutDayCells();
  },
  onDestroy: function onDestroy() {
    this.removeAllEvents();
    this.initData(false);
    this.purgeListeners();
    Tine.Calendar.MonthView.superclass.onDestroy.apply(this, arguments);
  },

  /**
   * layouts the contents (sets 'more items marker')
   */
  layoutDayCells: function layoutDayCells() {
    for (var i = 0; i < this.dayCells.length; i++) {
      if (this.dayCells[i].lastChild.childNodes.length > 1) {
        this.layoutDayCell(this.dayCells[i], true, true);
      }
    }
  },

  /**
   * layouts a single day cell
   * 
   * @param {dom} cell
   * @param {Bool} hideOverflow
   * @param {Bool} updateHeader
   */
  layoutDayCell: function layoutDayCell(cell, hideOverflow, updateHeader) {
    // clean empty slices
    while (cell.lastChild.childNodes.length > 1 && cell.lastChild.lastChild.innerHTML == '') {
      Ext.fly(cell.lastChild.lastChild).remove();
    }

    Tine.log.debug('Tine.Calendar.MonthView::layoutDayCell() - cell:');
    Tine.log.debug(cell);

    for (var j = 0, height = 0, hideCount = 0; j < cell.lastChild.childNodes.length; j++) {
      var eventEl = Ext.get(cell.lastChild.childNodes[j]);
      height += eventEl.getHeight();
      eventEl[height > this.dayCellsHeight && hideOverflow ? 'hide' : 'show']();

      if (height > this.dayCellsHeight && hideOverflow && cell.lastChild.childNodes[j].innerHTML !== '') {
        hideCount++;
      }
    }

    Tine.log.debug('Tine.Calendar.MonthView::layoutDayCell() - hideCount:' + hideCount);

    if (updateHeader) {
      cell.firstChild.firstChild.innerHTML = hideCount > 0 ? String.format(this.moreString, hideCount) : '';
    }

    return height;
  },

  /**
   * @private
   */
  onAdd: function onAdd(ds, records, index) {
    for (var i = 0; i < records.length; i++) {
      var event = records[i];
      this.parallelEventsRegistry.register(event);
      var parallelEvents = this.parallelEventsRegistry.getEvents(event.get('dtstart'), event.get('dtend'));

      for (var j = 0; j < parallelEvents.length; j++) {
        this.removeEvent(parallelEvents[j]);
        this.insertEvent(parallelEvents[j]);
      }
    }

    this.layoutDayCells();
  },
  onClick: function onClick(e, target) {
    // send click event anyway
    var event = this.getTargetEvent(e);

    if (event) {
      this.fireEvent('click', event, e);
      return;
    }
    /** distinct click from dblClick **/


    var now = new Date().getTime();

    if (now - parseInt(this.lastClickTime, 10) < 300) {
      this.lastClickTime = now; //e.stopEvent();

      return;
    }

    var dateTime = this.getTargetDateTime(e);

    if (Math.abs(dateTime - now) < 100) {
      this.lastClickTime = now;
      return this.onClick.defer(400, this, [e, target]);
    }

    this.lastClickTime = now;
    /** end distinct click from dblClick **/

    switch (target.className) {
      case 'cal-monthview-dayheader-date':
      case 'cal-monthview-dayheader-more':
        var moreText = target.parentNode.firstChild.innerHTML;

        if (!moreText) {
          return;
        } //e.stopEvent();


        this.zoomDayCell(target.parentNode.parentNode);
        break;
    }
  },
  onContextMenu: function onContextMenu(e) {
    this.fireEvent('contextmenu', e);
  },
  onKeyDown: function onKeyDown(e) {
    this.fireEvent("keydown", e);
  },
  onDblClick: function onDblClick(e, target) {
    this.lastClickTime = new Date().getTime();
    e.stopEvent();
    var event = this.getTargetEvent(e);

    if (event) {
      this.fireEvent('dblclick', event, e);
      return;
    }

    switch (target.className) {
      case 'cal-monthview-wkcell':
        var wkIndex = Ext.DomQuery.select('td[class=cal-monthview-wkcell]', this.mainBody.dom).indexOf(target);
        var startDate = this.dateMesh[7 * wkIndex];
        this.fireEvent('changeView', 'week', startDate);
        break;

      case 'cal-monthview-dayheader-date':
      case 'cal-monthview-dayheader-more':
        var dateIndex = this.dayCells.indexOf(target.parentNode.parentNode);
        var date = this.dateMesh[dateIndex];
        this.fireEvent('changeView', 'day', date);
        break;

      case 'cal-monthview-daycell':
        var dateIndex = this.dayCells.indexOf(target);
        var date = this.dateMesh[dateIndex]; //console.log("Create event at: " + date.format('Y-m-d'));

        break;
    } //console.log(Ext.get(target));

  },
  onBeforeLoad: function onBeforeLoad(store, options) {
    if (!options.refresh) {
      this.store.each(this.removeEvent, this);
    }
  },

  /**
   * @private
   */
  onLoad: function onLoad() {
    if (!this.rendered) {
      return;
    }

    this.removeAllEvents(); // create parallels registry

    this.parallelEventsRegistry = new Tine.Calendar.ParallelEventsRegistry({
      dtStart: this.dateMesh[0],
      dtEnd: this.dateMesh[this.dateMesh.length - 1].add(Date.DAY, 1)
      /*.add(Date.SECOND, -1)*/
      ,
      granularity: 60 * 24
    }); // todo: sort generic?

    this.store.fields = Tine.Calendar.Model.Event.prototype.fields;
    this.store.sortInfo = {
      field: 'dtstart',
      direction: 'ASC'
    };
    this.store.applySort(); // calculate duration and parallels

    this.store.each(function (event) {
      this.parallelEventsRegistry.register(event);
    }, this);
    this.store.each(this.insertEvent, this);
    this.layoutDayCells();
  },

  /**
   * @private
   */
  onMouseDown: function onMouseDown(e, target) {
    this.focusEl.focus();
    this.mainBody.focus(); // only unzoom if click is not in the area of the daypreviewbox

    if (!e.getTarget('div.cal-monthview-daypreviewbox')) {
      this.unZoom();
    }
  },

  /**
   * @private
   */
  onRemove: function onRemove(ds, event, index, isUpdate) {
    this.parallelEventsRegistry.unregister(event);
    this.removeEvent(event);
    this.getSelectionModel().unselect(event);
  },

  /**
   * @private
   */
  onUpdate: function onUpdate(ds, event) {
    // relayout original context
    var originalDtstart = event.modified.hasOwnProperty('dtstart') ? event.modified.dtstart : event.get('dtstart');
    var originalDtend = event.modified.hasOwnProperty('dtend') ? event.modified.dtend : event.get('dtend');
    var originalParallels = this.parallelEventsRegistry.getEvents(originalDtstart, originalDtend);

    for (var j = 0; j < originalParallels.length; j++) {
      this.removeEvent(originalParallels[j]);
    }

    this.parallelEventsRegistry.unregister(event);
    var originalParallels = this.parallelEventsRegistry.getEvents(originalDtstart, originalDtend);

    for (var j = 0; j < originalParallels.length; j++) {
      this.insertEvent(originalParallels[j]);
    } // relayout actual context


    var parallelEvents = this.parallelEventsRegistry.getEvents(event.get('dtstart'), event.get('dtend'));

    for (var j = 0; j < parallelEvents.length; j++) {
      this.removeEvent(parallelEvents[j]);
    }

    this.parallelEventsRegistry.register(event);
    var parallelEvents = this.parallelEventsRegistry.getEvents(event.get('dtstart'), event.get('dtend'));

    for (var j = 0; j < parallelEvents.length; j++) {
      this.insertEvent(parallelEvents[j]);
    }

    event.commit(true);
    this.layoutDayCells();
  },

  /**
   * print wrapper
   */
  print: function print() {
    var renderer = new this.printRenderer();
    renderer.print(this);
  },

  /**
   * removes all events from dom
   */
  removeAllEvents: function removeAllEvents() {
    var els = Ext.DomQuery.filter(Ext.DomQuery.select('div[class^=cal-monthview-event]', this.mainBody.dom), 'div[class=cal-monthview-eventslice]', true);

    for (var i = 0; i < els.length; i++) {
      Ext.fly(els[i]).remove();
    }

    this.store.each(function (event) {
      if (event.ui) {
        event.ui.domIds = [];
      }
    });
    this.layoutDayCells();
  },

  /**
   * removes a event from the dom
   * @param {Tine.Calendar.Model.Event} event
   */
  removeEvent: function removeEvent(event) {
    if (!event) {
      return;
    }

    if (event.ui) {
      event.ui.remove();
    }
  },

  /**
   * renders the view
   */
  onRender: function onRender(container, position) {
    Tine.Calendar.MonthView.superclass.onRender.apply(this, arguments);
    var m = ['<a href="#" class="cal-monthviewpanel-focus" tabIndex="-1"></a>', '<table class="cal-monthview-inner" cellspacing="0"><thead><tr class="cal-monthview-inner-header" height="23px">', "<th class='cal-monthview-wkcell-header'><span >", this.calWeekString, "</span></th>"];

    for (var i = 0; i < 7; i++) {
      var d = this.startDay + i;

      if (d > 6) {
        d = d - 7;
      }

      m.push("<th class='cal-monthview-daycell'><span>", this.dayNames[d], "</span></th>");
    }

    m[m.length] = "</tr></thead><tbody><tr><td class='cal-monthview-wkcell'></td>";

    for (var i = 0; i < 42; i++) {
      if (i % 7 == 0 && i != 0) {
        m[m.length] = "</tr><tr><td class='cal-monthview-wkcell'></td>";
      }

      m[m.length] = '<td class="cal-monthview-daycell">' + '<div class="cal-monthview-dayheader">' + '<div class="cal-monthview-dayheader-more"></div>' + '<div class="cal-monthview-dayheader-date"></div>' + '</div>' + '<div class="cal-monthview-daybody"><div class="cal-monthview-eventslice" /></div>' + '</td>';
    }

    m.push('</tr></tbody></table>');
    this.el.update(m.join(""));
  },
  updatePeriod: function updatePeriod(period) {
    this.toDay = new Date().clearTime();
    this.startDate = period.from;
    this.calcDateMesh();
    var tbar = this.findParentBy(function (c) {
      return c.getTopToolbar();
    }).getTopToolbar();

    if (tbar) {
      tbar.periodPicker.update(this.startDate);
      this.startDate = tbar.periodPicker.getPeriod().from;
    }

    if (!this.rendered) return; // update dates and bg colors

    var dayHeaders = Ext.DomQuery.select('div[class=cal-monthview-dayheader-date]', this.mainBody.dom);

    for (var i = 0; i < this.dateMesh.length; i++) {
      clsToAdd = this.dateMesh[i].getMonth() == this.startDate.getMonth() ? ' cal-monthview-daycell-valid' : ' cal-monthview-daycell-invalid';

      if (this.dateMesh[i].getTime() == this.toDay.getTime()) {
        clsToAdd = ' cal-monthview-daycell-today';
      }

      this.dayCells[i].setAttribute('class', 'cal-monthview-daycell ' + clsToAdd);
      dayHeaders[i].innerHTML = this.dateMesh[i].format('j');
    } // update weeks


    var wkCells = Ext.DomQuery.select('td[class=cal-monthview-wkcell]', this.mainBody.dom);

    for (var i = 0; i < wkCells.length; i++) {
      if (this.dateMesh.length > i * 7 + 1) {
        // NOTE: '+1' is to ensure we display the ISO8601 based week where weeks always start on monday!
        wkCells[i].innerHTML = this.dateMesh[i * 7 + 1].getWeekOfYear(); //Ext.fly(wkCells[i]).unselectable(); // this supresses events ;-(
      }
    }

    this.onLayout();
    this.fireEvent('changePeriod', period);
  },
  unZoom: function unZoom() {
    if (this.zoomCell) {
      // this prevents reopen of cell on header clicks
      this.lastClickTime = new Date().getTime();
      var cell = Ext.get(this.zoomCell);
      var dayBodyEl = cell.last();
      var height = cell.getHeight() - cell.first().getHeight();
      dayBodyEl.scrollTo('top');
      dayBodyEl.removeClass('cal-monthview-daypreviewbox');
      dayBodyEl.setStyle('background-color', cell.getStyle('background-color'));
      dayBodyEl.setStyle('border-top', 'none');
      dayBodyEl.setHeight(height); // NOTE: we need both setWidht statements, otherwise safari keeps scroller space

      for (var i = 0; i < dayBodyEl.dom.childNodes.length; i++) {
        Ext.get(dayBodyEl.dom.childNodes[i]).setWidth(dayBodyEl.getWidth());
        Ext.get(dayBodyEl.dom.childNodes[i]).setWidth(dayBodyEl.first().getWidth());
      }

      this.layoutDayCell(this.zoomCell, true, true);
      this.zoomCell = false;
    }
  },
  zoomDayCell: function zoomDayCell(cell) {
    this.zoomCell = cell;
    var dayBodyEl = Ext.get(cell.lastChild);
    var box = dayBodyEl.getBox();
    var bgColor = Ext.fly(cell).getStyle('background-color');
    bgColor == 'transparent' ? '#FFFFFF' : bgColor;
    dayBodyEl.addClass('cal-monthview-daypreviewbox');
    dayBodyEl.setBox(box);
    dayBodyEl.setStyle('background-color', bgColor);
    dayBodyEl.setStyle('border-top', '1px solid ' + bgColor);
    var requiredHeight = this.layoutDayCell(cell, false, true) + 10;
    var availHeight = this.el.getBottom() - box.y;
    dayBodyEl.setHeight(Math.min(requiredHeight, availHeight));
  }
});
Ext.reg('Tine.Calendar.MonthView', Tine.Calendar.MonthView);

/***/ }),

/***/ 1783:
/***/ (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__(1784);
if(typeof content === 'string') content = [[module.i, content, '']];
// Prepare cssTransformation
var transform;

var options = {"hmr":true}
options.transform = transform
// add the styles to the DOM
var update = __webpack_require__(17)(content, options);
if(content.locals) module.exports = content.locals;
// Hot Module Replacement
if(false) {}

/***/ }),

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

var escape = __webpack_require__(103);
exports = module.exports = __webpack_require__(16)(false);
// imports


// module
exports.push([module.i, ".cal-monthview {\n    color:black;\n    font-family:arial,tahoma,helvetica,sans-serif;\n    font-size:11px;\n    font-size-adjust:none;\n    font-style:normal;\n    font-variant:normal;\n    font-weight:normal;\n    line-height:normal;\n    white-space:nowrap;\n}\n\n.cal-monthview-inner th {\n    border-top: none;\n    text-align: center;\n    vertical-align: middle;\n}\n\n.cal-monthview-wkcell {\n    border-right: 3px double #E1E1E1;\n    text-align: center;\n    vertical-align: middle;\n    /*background:#F0F0F0 url(../../library/ExtJS/resources/images/default/toolbar/bg.gif) repeat-x scroll left top;*/\n    background-color: #F0F0F0;\n    border-color:#D0D0D0;\n}\n\n.cal-monthview-wkcell:hover{\n    background: #CDDCEF url(" + escape(__webpack_require__(211)) + ") repeat-x scroll left top;\n    /*cursor: pointer; see ticket #1484*/\n}\n\n.cal-monthview-wkcell-header {\n    border-right: 3px double #E1E1E1;\n}\n\n.cal-monthview-daycell {\n    vertical-align: top;\n    border-right: 1px solid #E1E1E1;\n    border-top: 1px solid #E1E1E1;\n}\n\n.cal-monthview-dayheader:hover {\n    background: #CDDCEF url(" + escape(__webpack_require__(211)) + ") repeat-x scroll left top;\n    /*cursor: pointer; see ticket #1484*/\n}\n\n.cal-monthview-inner-header {\n    position: relative;\n    /*background:#F9F9F9 url(../../library/ExtJS/resources/images/default/grid/grid3-hrow.gif) repeat-x scroll 0 top;*/\n    height: 23px;\n}\n\n.cal-monthview-dayheader {\n    position: relative;\n    width: 100%;\n}\n\n.cal-monthview-dayheader-more {\n    position: absolute;\n    padding: 2px 5px;\n    border-collapse: separate;\n    color: #233D6D;\n    cursor: pointer;\n    text-align: left !important;\n}\n\n.cal-monthview-dayheader-date {\n    padding: 2px 5px;\n    border-collapse: separate;\n    color: #233D6D;\n    /*cursor: pointer; see ticket #1484*/\n    text-align: right !important;\n}\n\n.cal-monthview-daybody {\n    /*overflow: visible;*/\n}\n\n/*********************************** Events ***********************************/\n.cal-monthview-eventslice {\n    height: 18px;\n    overflow: visible;\n}\n\n.cal-monthview-event-icon,\n.cal-monthview-alldayevent-icon {\n    width: 16px;\n    height: 16px;\n}\n\n.cal-monthview-event {\n    margin: 0px 0px;\n    width: 100%;\n    cursor: pointer;\n    /*overflow: hidden;*/\n}\n\n.cal-monthview-eventslice .cal-monthview-event-editgrant {\n    cursor: move;\n}\n\n.cal-monthview-event-summary {\n    white-space: nowrap;\n    overflow: hidden;\n}\n\n.cal-monthview-alldayevent {\n    /*border-radius: 8px;*/\n    margin: 0px 0px 1px 0px;\n    background-color: red;\n    height: 17px;\n    width: 100%;\n    /*overflow: visible;*/\n}\n\n/*.ext-gecko .cal-monthview-alldayevent {*/\n/*    -moz-border-radius: 8px;*/\n/*}*/\n\n/*.ext-safari .cal-monthview-alldayevent {*/\n/*    -webkit-border-radius: 8px;*/\n/*}*/\n\n/*!** todo: add khtml switch **!*/\n/*.cal-monthview-alldayevent {*/\n/*    -khtml-border-radius: 8px;*/\n/*}*/\n\n.cal-monthview-alldayevent-cropleft {\n    margin-left: 0px;\n    border-left-style: none;\n    /*border-top-left-radius: 0px;*/\n    /*border-bottom-left-radius: 0px;*/\n}\n\n/*.ext-gecko .cal-monthview-alldayevent-cropleft {*/\n/*    -moz-border-radius-topleft: 0px;*/\n/*    -moz-border-radius-bottomleft: 0px;*/\n/*}*/\n\n/*.ext-safari .cal-monthview-alldayevent-cropleft {*/\n/*    -webkit-border-top-left-radius: 0px;*/\n/*    -webkit-border-bottom-left-radius: 0px;*/\n/*}*/\n\n/*!** todo: add khtml switch **!*/\n/*.cal-monthview-alldayevent-cropleft {*/\n/*    -khtml-border-top-left-radius: 0px;*/\n/*    -khtml-border-bottom-left-radius: 0px;*/\n/*}*/\n\n.cal-monthview-alldayevent-cropright {\n    margin-right: 0px;\n    background-image: none;\n    border-right-style: hidden;\n    /*border-top-right-radius: 0px;*/\n    /*border-bottom-right-radius: 0px;*/\n}\n\n/*.ext-gecko .cal-monthview-alldayevent-cropright {*/\n/*    -moz-border-radius-topright: 0px;*/\n/*    -moz-border-radius-bottomright: 0px;*/\n/*}*/\n\n/*.ext-safari .cal-monthview-alldayevent-cropright {*/\n/*    -webkit-border-top-right-radius: 0px;*/\n/*    -webkit-border-bottom-right-radius: 0px;*/\n/*}*/\n\n/*!** todo: add khtml switch **!*/\n/*.cal-monthview-alldayevent-cropright {*/\n/*    -khtml-border-top-right-radius: 0px;*/\n/*    -khtml-border-bottom-right-radius: 0px;*/\n/*}*/\n\n.cal-monthview-alldayevent-summary {\n    white-space: nowrap;\n    overflow: hidden;\n    min-height: 12px;\n    /*overflow: visible; */\n}\n\n.cal-monthview-event-info-hide {\n    display: none;\n}\n\n.cal-monthview-daypreviewbox .cal-monthview-event-info-hide {\n    display: block;\n}\n\n/******************************* daypreviewbox ********************************/\n.cal-monthview-daypreviewbox {\n    position: absolute;\n    border-bottom: 1px solid #E1E1E1;\n    overflow-y: auto;\n    overflow-x: hidden;\n    z-index: 5000;\n}\n\n/* Calendar */\n.cal-monthview-daycell-valid {\n    background: #FFF;\n}\n.cal-monthview-daycell-invalid {\n    background: #F9F9F9;\n}\n.cal-monthview-daycell-today {\n    background: #EBF3FD;\n}", ""]);

// exports


/***/ }),

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

Tine.Calendar.Printer.MonthViewRenderer = Ext.extend(Tine.Calendar.Printer.BaseRenderer, {
  paperHeight: 155,
  generateBody: function generateBody(view) {
    var daysHtml = this.splitDays(view.store, view.dateMesh[0], view.dateMesh.length),
        body = [],
        me = this;
    return new Promise(function (fulfill, reject) {
      // try to force landscape -> opera only atm...
      body.push('<style type="text/css">', '@page {', 'size:landscape', '}', '@media print {thead {display: table-header-group;}}', '</style>'); // day headers

      var dayNames = [];

      for (var i = 0; i < 7; i++) {
        var d = view.startDay + i;

        if (d > 6) {
          d = d - 7;
        }

        dayNames.push("<th class='cal-print-monthview-daycell'><span>", view.dayNames[d], "</span></th>");
      }

      body.push('<table class="cal-print-monthview">', '<thead>', '<tr><th colspan="7" class="cal-print-title">', me.getTitle(view), '</th></tr>', '<tr>', dayNames.join("\n"), '</tr>', '</thead>', '<tbody>', me.generateCalRows(daysHtml, 7, true), '</tbody>');
      fulfill(body.join("\n"));
    });
  },
  getTitle: function getTitle(view) {
    return view.dateMesh[10].format('F Y');
  },
  dayHeadersTpl: new Ext.XTemplate('<tr>', '<tpl for=".">', '<th>\{{dataIndex}\}</th>', '</tpl>', '</tr>')
});

/***/ }),

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

/* 
 * Tine 2.0
 * 
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Nico Hessler <tine20@nico-hessler.de>
 * @copyright   Copyright (c) 2007-2008 Metaways Infosystems GmbH (http://www.metaways.de)
 */
Ext.ns('Tine.Calendar');

__webpack_require__(1787);

__webpack_require__(1789);
/**
 * @namespace Tine.Calendar
 * @class Tine.Calendar.YearView
 * @extends Ext.util.Observable
 * @constructor
 * @param {Object} config
 */


Tine.Calendar.YearView = function (config) {
  Ext.apply(this, config);
  Tine.Calendar.YearView.superclass.constructor.call(this);
  this.printRenderer = Tine.Calendar.Printer.YearViewRenderer;
  this.addEvents(
  /**
   * @event click
   * fired if an event got clicked
   * @param {Tine.Calendar.Model.Event} event
   * @param {Ext.EventObject} e
   */
  'click',
  /**
   * @event contextmenu
   * fired if an event got contextmenu 
   * @param {Ext.EventObject} e
   */
  'contextmenu',
  /**
   * @event dblclick
   * fired if an event got dblclicked
   * @param {Tine.Calendar.Model.Event} event
   * @param {Ext.EventObject} e
   */
  'dblclick',
  /**
   * @event changeView
   * fired if user wants to change view
   * @param {String} requested view name
   * @param {mixed} start param of requested view
   */
  'changeView',
  /**
   * @event changePeriod
   * fired when period changed
   * @param {Object} period
   */
  'changePeriod',
  /**
   * @event addEvent
   * fired when a new event got inserted
   * 
   * @param {Tine.Calendar.Model.Event} event
   */
  'addEvent',
  /**
   * @event updateEvent
   * fired when an event go resised/moved
   * 
   * @param {Tine.Calendar.Model.Event} event
   */
  'updateEvent');
};

Ext.extend(Tine.Calendar.YearView, Ext.Container, {
  /**
   * @cfg {Date} startDate
   * start date
   */
  startDate: new Date().clearTime(),

  /**
   * @cfg {String} newEventSummary
   * i18n._('New Event')
   */
  newEventSummary: 'New Event',

  /**
   * @cfg String moreString
   * i18n._('{0} more...')
   */
  moreString: '{0} more...',

  /**
   * @cfg {Array} monthNames
   * An array of textual month names which can be overriden for localization support (defaults to Date.monthNames)
   */
  monthNames: Date.monthNames,

  /**
   * @cfg {Boolean} denyDragOnMissingEditGrant
   * deny drag action if edit grant for event is missing
   */
  denyDragOnMissingEditGrant: true,

  /**
   * @private {Date} toDay
   */
  toDay: null,

  /**
   * @private {Array} dateMesh
   */
  dateMesh: null,

  /**
   * @private {Tine.Calendar.ParallelEventsRegistry} parallelEventsRegistry
   */
  parallelEventsRegistry: null,
  cls: "cal-yearview",

  /**
   * @private
   */
  afterRender: function afterRender() {
    Tine.Calendar.YearView.superclass.afterRender.apply(this, arguments);
    this.initElements();
    this.getSelectionModel().init(this);
    this.mon(this.el, 'mousedown', this.onMouseDown, this);
    this.mon(this.el, 'click', this.onClick, this);
    this.mon(this.el, 'contextmenu', this.onContextMenu, this);
    this.mon(this.el, 'keydown', this.onKeyDown, this);
    this.initDragZone();
    this.initDropZone();
    this.updatePeriod({
      from: this.period.from
    });

    if (this.store.getCount()) {
      this.onLoad.apply(this);
    }

    this.rendered = true;
  },

  /**
   * @private calculates mesh of dates for month this.startDate is in
   */
  calcDateMesh: function calcDateMesh() {
    var mesh = [];
    var d = Date.parseDate(this.startDate.format('Y') + '-01-01 00:00:00', Date.patterns.ISO8601Long);

    for (var day = 0; day < 31; day++) {
      for (var month = 0; month < 12; month++) {
        var cell = d.add(Date.MONTH, month).add(Date.DAY, day);

        if (cell.getMonth() == month) {
          mesh.push(cell.clone());
        } else {
          mesh.push(null);
        }
      }
    }

    this.dateMesh = mesh;
  },

  /**
   * returns index of dateCell given date is in
   * @param {Date} date
   */
  getDayCellIndex: function getDayCellIndex(date) {
    return date.getMonth() + (date.getDate() - 1) * 12;
  },

  /**
   * @private returns a child div in requested position
   * 
   * @param {dom} dayCell
   * @param {Number} pos
   * @return {dom}
   */
  getEventSlice: function getEventSlice(dayCell, pos) {
    pos = Math.abs(pos);

    for (var i = dayCell.childNodes.length; i <= pos; i++) {
      Ext.DomHelper.insertAfter(dayCell.lastChild, '<div class="cal-yearview-eventslice"/>');
    } // make sure cell is empty


    while (dayCell.childNodes[pos].innerHTML) {
      pos++;

      if (pos > dayCell.childNodes.length - 1) {
        Ext.DomHelper.insertAfter(dayCell.lastChild, '<div class="cal-yearview-eventslice"/>');
      }
    }

    return dayCell.childNodes[pos];
  },

  /**
   * returns period of currently displayed month
   * @return {Object}
   */
  getPeriod: function getPeriod() {
    // happens if month view is rendered first
    if (!this.dateMesh) {
      this.calcDateMesh();
    }

    return {
      from: this.dateMesh[0],
      until: this.dateMesh[this.dateMesh.length - 1].add(Date.DAY, 1)
    };
  },
  getSelectionModel: function getSelectionModel() {
    return this.selModel;
  },
  getTargetDateTime: function getTargetDateTime(e) {
    var target = e.getTarget('td.cal-yearview-daycell', 3);

    if (target) {
      var dateIdx = this.dayCells.indexOf(target);
      var date = this.dateMesh[this.dayCells.indexOf(target)]; // set some default time:

      date.add(Date.HOUR, 10);
      return date;
    }
  },
  getTargetEvent: function getTargetEvent(e) {
    var target = e.getTarget('div.cal-yearview-event', 10);

    if (target) {
      var parts = target.id.split(':');
      var event = this.store.getById(parts[1]);
    }

    return event;
  },

  /**
   * init month view
   */
  initComponent: function initComponent() {
    this.app = Tine.Tinebase.appMgr.get('Calendar');
    this.newEventSummary = this.app.i18n._hidden(this.newEventSummary);
    this.calWeekString = this.app.i18n._hidden(this.calWeekString);
    this.moreString = this.app.i18n._hidden(this.moreString); // redefine this props in case ext translations got included after this component

    this.monthNames = Date.monthNames;
    this.dayNames = Date.dayNames;
    this.initData(this.store);
    this.initTemplates();

    if (!this.selModel) {
      this.selModel = this.selModel || new Tine.Calendar.EventSelectionModel();
    }

    Tine.Calendar.YearView.superclass.initComponent.apply(this, arguments);
  },

  /**
   * @private
   * @param {Ext.data.Store} ds
   */
  initData: function initData(ds) {
    if (this.store) {
      this.store.un("load", this.onLoad, this);
      this.store.un("beforeload", this.onBeforeLoad, this);
      this.store.un("add", this.onAdd, this);
      this.store.un("remove", this.onRemove, this);
      this.store.un("update", this.onUpdate, this);
    }

    if (ds) {
      ds.on("load", this.onLoad, this);
      ds.on("beforeload", this.onBeforeLoad, this);
      ds.on("add", this.onAdd, this);
      ds.on("remove", this.onRemove, this);
      ds.on("update", this.onUpdate, this);
    }

    this.store = ds;
  },

  /**
   * @private
   */
  initDragZone: function initDragZone() {
    this.dragZone = new Ext.dd.DragZone(this.el, {
      ddGroup: 'cal-event',
      view: this,
      scroll: false,
      getDragData: function getDragData(e) {
        var eventEl = e.getTarget('div.cal-yearview-event', 10);

        if (eventEl) {
          var parts = eventEl.id.split(':');
          var event = this.view.store.getById(parts[1]); // don't allow dragging with missing edit grant

          if (this.view.denyDragOnMissingEditGrant && !event.get('editGrant')) {
            return false;
          } // we need to clone an event with summary in


          var d = Ext.get(event.ui.domIds[0]).dom.cloneNode(true);
          var width = Ext.fly(eventEl).getWidth() * event.ui.domIds.length;
          Ext.fly(d).setWidth(width);
          Ext.fly(d).setOpacity(0.5);
          d.id = Ext.id();
          return {
            scope: this.view,
            sourceEl: eventEl,
            event: event,
            ddel: d,
            selections: this.view.getSelectionModel().getSelectedEvents()
          };
        }
      },
      getRepairXY: function getRepairXY(e, dd) {
        Ext.fly(this.dragData.sourceEl).setOpacity(1, 1);
        return Ext.fly(this.dragData.sourceEl).getXY();
      }
    });
  },
  initDropZone: function initDropZone() {
    this.dd = new Ext.dd.DropZone(this.el.dom, {
      ddGroup: 'cal-event',
      notifyOver: function notifyOver(dd, e, data) {
        var target = e.getTarget('td.cal-yearview-daycell', 3);
        var event = data.event; // we dont support multiple dropping yet

        if (event) {
          data.scope.getSelectionModel().select(event);
        }

        return target && event && event.get('editGrant') ? 'cal-daysviewpanel-event-drop-ok' : 'cal-daysviewpanel-event-drop-nodrop';
      },
      notifyDrop: function notifyDrop(dd, e, data) {
        var v = data.scope;
        var target = e.getTarget('td.cal-yearview-daycell', 3);
        var targetDate = v.dateMesh[v.dayCells.indexOf(target)];

        if (targetDate) {
          var event = data.event;
          var diff = (targetDate.getTime() - event.get('dtstart').clearTime(true).getTime()) / Date.msDAY;

          if (!diff || !event.get('editGrant')) {
            return false;
          }

          event.beginEdit();
          event.set('dtstart', event.get('dtstart').add(Date.DAY, diff));
          event.set('dtend', event.get('dtend').add(Date.DAY, diff));
          event.endEdit();
          v.fireEvent('updateEvent', event);
        }

        return !!targetDate;
      }
    });
  },

  /**
   * @private
   */
  initElements: function initElements() {
    var E = Ext.Element;
    this.focusEl = new E(this.el.dom.firstChild);
    this.mainHd = new E(this.el.dom.lastChild.firstChild);
    this.mainBody = new E(this.el.dom.lastChild.lastChild);
    this.dayCells = Ext.DomQuery.select('td[class=cal-yearview-daycell]', this.mainBody.dom);
  },

  /**
   * inits all tempaltes of this view
   */
  initTemplates: function initTemplates() {
    var ts = this.templates || {};
    ts.event = new Ext.XTemplate('<div id="{id}" class="cal-yearview-event {extraCls}" style="background-color: {bgColor};"">' + //'<div class="cal-yearview-event-summary"> {[Ext.util.Format.htmlEncode(values.summary)]}</div>' +
    '{[Ext.util.Format.htmlEncode(values.summary)]}' + '</div>');

    for (var k in ts) {
      var t = ts[k];

      if (t && typeof t.compile == 'function' && !t.compiled) {
        t.disableFormats = true;
        t.compile();
      }
    }

    this.templates = ts;
  },

  /**
   * @private
   * @param {Tine.Calendar.Model.Event} event
   */
  insertEvent: function insertEvent(event) {
    event.ui = new Tine.Calendar.YearViewEventUI(event); //event.ui.render(this);

    var dtStart = event.get('dtstart');
    var startCellNumber = this.getDayCellIndex(dtStart);
    var dtEnd = event.get('dtend'); // 00:00 in users timezone is a spechial case where the user expects
    // something like 24:00 and not 00:00

    if (dtEnd.format('H:i') == '00:00') {
      dtEnd = dtEnd.add(Date.MINUTE, -1);
    }

    var endCellNumber = this.getDayCellIndex(dtEnd); // skip out of range events

    if (endCellNumber < 0 || startCellNumber >= this.dateMesh.length) {
      return;
    }

    var pos = this.parallelEventsRegistry.getPosition(event); // save some layout info

    event.ui.colorSet = event.colorSet = Tine.Calendar.colorMgr.getColor(event);
    event.ui.color = event.ui.colorSet.color;
    event.ui.bgColor = event.ui.colorSet.light;
    var data = {
      startTime: dtStart.format('H:i'),
      summary: event.get('summary'),
      color: event.ui.color,
      bgColor: event.ui.bgColor,
      width: '100%'
    };

    for (var i = Math.max(startCellNumber, 0); i <= Math.min(endCellNumber, this.dayCells.length - 1); i = i + 12) {
      var col = i % 12,
          row = Math.floor(i / 12); //var row = i%12, col = Math.floor(i/12);

      data.id = Ext.id() + '-event:' + event.get('id');
      event.ui.domIds.push(data.id);
      var tmpl = this.templates.event;
      data.extraCls = event.get('editGrant') ? 'cal-yearview-event-editgrant' : '';
      data.extraCls += ' cal-status-' + event.get('status');

      if (data.showInfo && startCellNumber != endCellNumber) {
        var cols = (row == Math.floor(endCellNumber / 12) ? endCellNumber % 12 : 11) - col + 1;
        data.width = 100 * cols + '%';
      }

      if (i > startCellNumber) {
        data.extraCls += ' cal-yearview-event-croptop';
      }

      if (i < endCellNumber) {
        data.extraCls += ' cal-yearview-event-cropbottom';
      }

      var posEl = this.getEventSlice(this.dayCells[i].lastChild, pos);
      var eventEl = tmpl.overwrite(posEl, data, true);

      if (event.dirty) {
        eventEl.setOpacity(0.5); // the event was selected before

        event.ui.onSelectedChange(true);
      }
    }
  },
  onLayout: function onLayout() {
    Tine.Calendar.YearView.superclass.onLayout.apply(this, arguments);

    if (!this.mainBody) {
      return; // not rendered
    }

    var csize = this.container.getSize(true);
    var vw = csize.width;
    var vh = csize.height;
    var hsize = this.mainHd.getSize(true);
    this.dayCellsHeight = vh / 31 - 2;
    this.dayCellsWidth = vw / 12 - 25;
    var hdCels = this.mainHd.dom.firstChild.childNodes;

    for (var i = 0; i < hdCels.length; i++) {
      Ext.get(hdCels[i]).setWidth(vw / 12);
    }

    for (var i = 0; i < this.dayCells.length; i++) {
      Ext.get(this.dayCells[i].lastChild).setSize(this.dayCellsWidth, Math.max(this.dayCellsHeight, 17));
    }

    this.layoutDayCells();
  },
  onDestroy: function onDestroy() {
    this.removeAllEvents();
    this.initData(false);
    this.purgeListeners();
    Tine.Calendar.YearView.superclass.onDestroy.apply(this, arguments);
  },

  /**
   * layouts the contents (sets 'more items marker')
   */
  layoutDayCells: function layoutDayCells() {
    for (var i = 0; i < this.dayCells.length; i++) {
      if (this.dayCells[i].lastChild.childNodes.length > 1) {
        this.layoutDayCell(this.dayCells[i], true, true);
      }
    }
  },

  /**
   * layouts a single day cell
   * 
   * @param {dom} cell
   * @param {Bool} hideOverflow
   * @param {Bool} updateHeader
   */
  layoutDayCell: function layoutDayCell(cell, hideOverflow, updateHeader) {
    // clean empty slices
    while (cell.lastChild.childNodes.length > 1 && cell.lastChild.lastChild.innerHTML == '') {
      Ext.fly(cell.lastChild.lastChild).remove();
    }

    Tine.log.debug('Tine.Calendar.YearView::layoutDayCell() - cell:');
    Tine.log.debug(cell);
    var items = cell.lastChild.childNodes.length;

    for (var j = 0; j < items; j++) {
      var eventEl = Ext.get(cell.lastChild.childNodes[j]); //eventEl[height > this.dayCellsHeight && hideOverflow ? 'hide' : 'show']();

      eventEl.dom.style.width = this.dayCellsWidth / items;
      cell.lastChild.childNodes[j].style.width = this.dayCellsWidth / items;
    } //return height;

  },

  /**
   * @private
   */
  onAdd: function onAdd(ds, records, index) {
    for (var i = 0; i < records.length; i++) {
      var event = records[i];
      this.parallelEventsRegistry.register(event);
      var parallelEvents = this.parallelEventsRegistry.getEvents(event.get('dtstart'), event.get('dtend'));

      for (var j = 0; j < parallelEvents.length; j++) {
        this.removeEvent(parallelEvents[j]);
        this.insertEvent(parallelEvents[j]);
      }
    }

    this.layoutDayCells();
  },
  onClick: function onClick(e, target) {
    // send click event anyway
    var event = this.getTargetEvent(e);

    if (event) {
      this.fireEvent('click', event, e);
      return;
    }
    /** distinct click from dblClick **/


    var now = new Date().getTime();

    if (now - parseInt(this.lastClickTime, 10) < 300) {
      this.lastClickTime = now; //e.stopEvent();

      return;
    }

    var dateTime = this.getTargetDateTime(e);

    if (Math.abs(dateTime - now) < 100) {
      this.lastClickTime = now;
      return this.onClick.defer(400, this, [e, target]);
    }

    this.lastClickTime = now;
    /** end distinct click from dblClick **/

    switch (target.className) {
      case 'cal-yearview-monthheader-date':
      case 'cal-yearview-monthheader-more':
        var moreText = target.parentNode.firstChild.innerHTML;

        if (!moreText) {
          return;
        } //e.stopEvent();


        this.zoomDayCell(target.parentNode.parentNode);
        break;
    }
  },
  onContextMenu: function onContextMenu(e) {//TODO reenable
    //this.fireEvent('contextmenu', e);
  },
  onKeyDown: function onKeyDown(e) {
    this.fireEvent("keydown", e);
  },
  onBeforeLoad: function onBeforeLoad(store, options) {
    if (!options.refresh) {
      this.store.each(this.removeEvent, this);
    }
  },

  /**
   * @private
   */
  onLoad: function onLoad() {
    if (!this.rendered) {
      return;
    }

    this.removeAllEvents(); // create parallels registry

    this.parallelEventsRegistry = new Tine.Calendar.ParallelEventsRegistry({
      dtStart: this.dateMesh[0],
      dtEnd: this.dateMesh[this.dateMesh.length - 1].add(Date.DAY, 1)
      /*.add(Date.SECOND, -1)*/
      ,
      granularity: 60 * 24
    }); // todo: sort generic?

    this.store.fields = Tine.Calendar.Model.Event.prototype.fields;
    this.store.sortInfo = {
      field: 'dtstart',
      direction: 'ASC'
    };
    this.store.applySort(); // calculate duration and parallels

    this.store.each(function (event) {
      this.parallelEventsRegistry.register(event);
    }, this);
    this.store.each(this.insertEvent, this);
    this.layoutDayCells();
  },

  /**
   * @private
   */
  onMouseDown: function onMouseDown(e, target) {
    this.focusEl.focus();
    this.mainBody.focus(); // only unzoom if click is not in the area of the daypreviewbox

    if (!e.getTarget('div.cal-yearview-daypreviewbox')) {
      this.unZoom();
    }
  },

  /**
   * @private
   */
  onRemove: function onRemove(ds, event, index, isUpdate) {
    this.parallelEventsRegistry.unregister(event);
    this.removeEvent(event);
    this.getSelectionModel().unselect(event);
  },

  /**
   * @private
   */
  onUpdate: function onUpdate(ds, event) {
    // relayout original context
    var originalDtstart = event.modified.hasOwnProperty('dtstart') ? event.modified.dtstart : event.get('dtstart');
    var originalDtend = event.modified.hasOwnProperty('dtend') ? event.modified.dtend : event.get('dtend');
    var originalParallels = this.parallelEventsRegistry.getEvents(originalDtstart, originalDtend);

    for (var j = 0; j < originalParallels.length; j++) {
      this.removeEvent(originalParallels[j]);
    }

    this.parallelEventsRegistry.unregister(event);
    var originalParallels = this.parallelEventsRegistry.getEvents(originalDtstart, originalDtend);

    for (var j = 0; j < originalParallels.length; j++) {
      this.insertEvent(originalParallels[j]);
    } // relayout actual context


    var parallelEvents = this.parallelEventsRegistry.getEvents(event.get('dtstart'), event.get('dtend'));

    for (var j = 0; j < parallelEvents.length; j++) {
      this.removeEvent(parallelEvents[j]);
    }

    this.parallelEventsRegistry.register(event);
    var parallelEvents = this.parallelEventsRegistry.getEvents(event.get('dtstart'), event.get('dtend'));

    for (var j = 0; j < parallelEvents.length; j++) {
      this.insertEvent(parallelEvents[j]);
    }

    event.commit(true);
    this.layoutDayCells();
  },

  /**
   * print wrapper
   */
  print: function print() {
    var renderer = new this.printRenderer();
    renderer.print(this);
  },

  /**
   * removes all events from dom
   */
  removeAllEvents: function removeAllEvents() {
    var els = Ext.DomQuery.filter(Ext.DomQuery.select('div[class^=cal-yearview-event]', this.mainBody.dom), 'div[class=cal-yearview-eventslice]', true);

    for (var i = 0; i < els.length; i++) {
      Ext.fly(els[i]).remove();
    }

    this.store.each(function (event) {
      if (event.ui) {
        event.ui.domIds = [];
      }
    });
    this.layoutDayCells();
  },

  /**
   * removes a event from the dom
   * @param {Tine.Calendar.Model.Event} event
   */
  removeEvent: function removeEvent(event) {
    if (!event) {
      return;
    }

    if (event.ui) {
      event.ui.remove();
    }
  },

  /**
   * renders the view
   */
  onRender: function onRender(container, position) {
    Tine.Calendar.YearView.superclass.onRender.apply(this, arguments);
    var m = ['<a href="#" class="cal-yearviewpanel-focus" tabIndex="-1"></a>', '<table class="cal-yearview-inner" cellspacing="0"><thead><tr class="cal-yearview-inner-header" height="23px">'];

    for (var i = 0; i < 12; i++) {
      m.push("<th class='cal-yearview-monthcell'><span>", this.monthNames[i], "</span></th>");
    }

    m[m.length] = "</tr></thead><tbody><tr>";

    for (var i = 0; i < 372; i++) {
      if (i % 12 == 0 && i != 0) {
        m[m.length] = "</tr><tr>";
      }

      m[m.length] = '<td class="cal-yearview-daycell">' + //                    '<div class="cal-yearview-dayheader">' +
      //                        '<div class="cal-yearview-dayheader-more"></div>' +
      '<div class="cal-yearview-daycell-date"></div>' + //                    '</div>' +
      //'<div class="cal-yearview-daybody"><div class="cal-yearview-eventslice" /></div>' +
      '<div class="cal-yearview-daybody"><div class="cal-yearview-eventslice" /></div>' + '</td>';
    }

    m.push('</tr></tbody></table>');
    this.el.update(m.join(""));
  },
  updatePeriod: function updatePeriod(period) {
    this.toDay = new Date().clearTime();
    this.startDate = period.from;
    this.calcDateMesh();
    var tbar = this.findParentBy(function (c) {
      return c.getTopToolbar();
    }).getTopToolbar();

    if (tbar) {
      tbar.periodPicker.update(this.startDate);
      this.startDate = tbar.periodPicker.getPeriod().from;
    }

    if (!this.rendered) return; // update dates and bg colors

    var monthHeaders = Ext.DomQuery.select('div[class=cal-yearview-daycell-date]', this.mainBody.dom);

    for (var i = 0; i < this.dateMesh.length; i++) {
      if (this.dateMesh[i] != null && monthHeaders[i]) {
        //clsToAdd = ((this.dateMesh[i].getMonth() == this.startDate.getMonth()) ? ' cal-yearview-daycell-valid' : ' cal-yearview-daycell-invalid');
        clsToAdd = "";
        clsToAdd = clsToAdd + (this.dateMesh[i].getDay() == 0 ? ' cal-yearview-daycell-sunday' : '');
        clsToAdd = clsToAdd + (this.dateMesh[i].getDay() == 6 ? ' cal-yearview-daycell-saturday' : '');

        if (this.dateMesh[i].getTime() == this.toDay.getTime()) {
          clsToAdd = clsToAdd + ' cal-yearview-daycell-today';
        }

        this.dayCells[i].setAttribute('class', 'cal-yearview-daycell ' + clsToAdd);
        monthHeaders[i].innerHTML = this.dateMesh[i].format('j');
      }
    }

    this.onLayout();
    this.fireEvent('changePeriod', period);
  },
  unZoom: function unZoom() {
    if (this.zoomCell) {
      // this prevents reopen of cell on header clicks
      this.lastClickTime = new Date().getTime();
      var cell = Ext.get(this.zoomCell);
      var dayBodyEl = cell.last();
      var height = cell.getHeight() - cell.first().getHeight();
      dayBodyEl.scrollTo('top');
      dayBodyEl.removeClass('cal-yearview-daypreviewbox');
      dayBodyEl.setStyle('background-color', cell.getStyle('background-color'));
      dayBodyEl.setStyle('border-top', 'none');
      dayBodyEl.setHeight(height); // NOTE: we need both setWidht statements, otherwise safari keeps scroller space

      for (var i = 0; i < dayBodyEl.dom.childNodes.length; i++) {
        Ext.get(dayBodyEl.dom.childNodes[i]).setWidth(dayBodyEl.getWidth());
        Ext.get(dayBodyEl.dom.childNodes[i]).setWidth(dayBodyEl.first().getWidth());
      }

      this.layoutDayCell(this.zoomCell, true, true);
      this.zoomCell = false;
    }
  },
  zoomDayCell: function zoomDayCell(cell) {
    this.zoomCell = cell;
    var dayBodyEl = Ext.get(cell.lastChild);
    var box = dayBodyEl.getBox();
    var bgColor = Ext.fly(cell).getStyle('background-color');
    bgColor == 'transparent' ? '#FFFFFF' : bgColor;
    dayBodyEl.addClass('cal-yearview-daypreviewbox');
    dayBodyEl.setBox(box);
    dayBodyEl.setStyle('background-color', bgColor);
    dayBodyEl.setStyle('border-top', '1px solid ' + bgColor);
    var requiredHeight = this.layoutDayCell(cell, false, true) + 10;
    var availHeight = this.el.getBottom() - box.y;
    dayBodyEl.setHeight(Math.min(requiredHeight, availHeight));
  }
});
Ext.reg('Tine.Calendar.YearView', Tine.Calendar.YearView);

/***/ }),

/***/ 1787:
/***/ (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__(1788);
if(typeof content === 'string') content = [[module.i, content, '']];
// Prepare cssTransformation
var transform;

var options = {"hmr":true}
options.transform = transform
// add the styles to the DOM
var update = __webpack_require__(17)(content, options);
if(content.locals) module.exports = content.locals;
// Hot Module Replacement
if(false) {}

/***/ }),

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

var escape = __webpack_require__(103);
exports = module.exports = __webpack_require__(16)(false);
// imports


// module
exports.push([module.i, ".cal-yearview {\n    color:black;\n    font-family:arial,tahoma,helvetica,sans-serif;\n    font-size:11px;\n    font-size-adjust:none;\n    font-style:normal;\n    font-variant:normal;\n    font-weight:normal;\n    line-height:normal;\n    white-space:nowrap;\n}\n\n.cal-yearview-inner th {\n    border-top: none;\n    text-align: center;\n    vertical-align: middle;\n}\n.cal-yearview-daycell {\n    vertical-align: top;\n    border-right: 1px solid #E1E1E1;\n    border-top: 1px solid #E1E1E1;\n    overflow: hidden;\n}\n\n.cal-yearview-daycell:hover {\n    background: #CDDCEF url(" + escape(__webpack_require__(211)) + ") repeat-x scroll left top;\n    /*cursor: pointer; see ticket #1484*/\n}\n\n.cal-yearview-inner-header,\n.cal-yearview-wkcell-header {\n    position: relative;\n    background:#F9F9F9 url(" + escape(__webpack_require__(225)) + ") repeat-x scroll 0 top;\n    height: 23px;\n}\n\n.cal-yearview-daycell {\n    position: relative;\n/*    width: 100%;*/\n}\n\n.cal-yearview-daycell-saturday {\n    background-color:#dddddd; \n}\n\n.cal-yearview-daycell-sunday {\n    background-color:#bbbbbb; \n}\n\n.cal-yearview-daycell-date {\n    padding: 2px 5px;\n    border-collapse: separate;\n    color: #233D6D;\n    /*cursor: pointer; see ticket #1484*/\n    float: left;\n    text-align: left;\n}\n\n.cal-yearview-daybody {\n    overflow: hidden;\n    float: left;\n    height: 100%;\n}\n\n/*********************************** Events ***********************************/\n.cal-yearview-eventslice {\n/*    height: 18px;*/\n    overflow: hidden;\n    float: left;\n    height: 100%;\n}\n\n.cal-yearview-event {\n    cursor: pointer;\n    border-radius: 8px;\n    margin: 0px 1px 0px 1px;\n    height: 100%;\n    line-height: 100%;\n}\n\n.cal-yearview-eventslice .cal-yearview-event-editgrant {\n    cursor: move;\n}\n\n.cal-yearview-event-summary {\n    white-space: nowrap;\n    overflow: hidden;\n}\n\n.ext-gecko .cal-yearview-alldayevent {\n    -moz-border-radius: 8px;\n}\n\n.ext-safari .cal-yearview-alldayevent {\n    -webkit-border-radius: 8px;\n}\n\n/** todo: add khtml switch **/\n.cal-yearview-alldayevent {\n    -khtml-border-radius: 8px;\n}\n\n.cal-yearview-event-croptop {\n/*    margin-left: 0px;\n    border-left-style: none;*/\n    border-top-left-radius: 0px;\n    border-top-right-radius: 0px;\n}\n\n.cal-yearview-event-cropbottom {\n    border-bottom-left-radius: 0px;\n    border-bottom-right-radius: 0px;\n}\n\n.cal-yearview-alldayevent-summary {\n    white-space: nowrap;\n    overflow: hidden;\n    min-height: 12px;\n    /*overflow: visible; */\n}\n\n.cal-yearview-event-info-hide {\n    display: none;\n}\n\n.cal-yearview-daypreviewbox .cal-yearview-event-info-hide {\n    display: block;\n}\n\n/******************************* daypreviewbox ********************************/\n.cal-yearview-daypreviewbox {\n    position: absolute;\n    border-bottom: 1px solid #E1E1E1;\n    overflow-y: auto;\n    overflow-x: hidden;\n    z-index: 5000;\n}\n", ""]);

// exports


/***/ }),

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

Tine.Calendar.Printer.YearViewRenderer = Ext.extend(Tine.Calendar.Printer.BaseRenderer, {
  paperHeight: 155,
  generateBody: function generateBody(view) {
    var body = [],
        me = this;
    return new Promise(function (fulfill, reject) {
      // try to force landscape -> opera only atm...
      body.push('<style type="text/css">', '@page {', 'size:landscape', '}', '@media print {thead {display: table-header-group;}}', '</style>');
      var monthNames = [];
      monthNames.push("<th class='cal-print-yearview-daycell'><span></span></th>");

      for (var i = 0; i < 12; i++) {
        monthNames.push("<th class='cal-print-yearview-daycell'><span>", view.monthNames[i], "</span></th>");
      }

      var daysHtml = [];

      for (i = 0; i < view.dayCells.length; i++) {
        if (i % 12 == 0) daysHtml.push(i / 12 + 1);
        celltext = view.dayCells[i].innerText;
        if (celltext.length > 3) daysHtml.push(celltext.substring(celltext.indexOf("\n")));else daysHtml.push("");
      }

      body.push('<table class="cal-print-yearview">', '<thead>', '<tr><th colspan="13" class="cal-print-title">', me.getTitle(view), '</th></tr>', '<tr>', monthNames.join("\n"), '</tr>', '</thead>', '<tbody>', me.generateCalRows(daysHtml, 13, true, true), '</tbody>');
      fulfill(body.join("\n"));
    });
  },
  getTitle: function getTitle(view) {
    return view.dateMesh[10].format('Y');
  },
  dayHeadersTpl: new Ext.XTemplate('<tr>', '<tpl for=".">', '<th>\{{dataIndex}\}</th>', '</tpl>', '</tr>')
});

/***/ }),

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

/* 
 * Tine 2.0
 * 
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2011 Metaways Infosystems GmbH (http://www.metaways.de)
 */
Ext.ns('Tine.Calendar');
/**
 * @namespace   Tine.Calendar
 * @class       Tine.Calendar.GridView
 * @extends     Ext.grid.GridPanel
 * 
 * Calendar grid view representing
 * 
 * @TODO generalize renderers and role out to displaypanel/printing etc.
 * @TODO add organiser and own status
 * 
 * 
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @constructor
 * @param {Object} config
 */

Tine.Calendar.GridView = Ext.extend(Ext.grid.GridPanel, {
  /**
   * record class
   * @cfg {Tine.Addressbook.Model.Contact} recordClass
   */
  recordClass: Tine.Calendar.Model.Event,

  /**
   * @cfg {Ext.data.DataProxy} recordProxy
   */
  recordProxy: Tine.Calendar.backend,

  /**
   * grid specific
   * @private
   */
  defaultSortInfo: {
    field: 'dtstart',
    direction: 'ASC'
  },
  layout: 'fit',
  border: false,
  stateful: true,
  stateId: 'Calendar-Event-GridPanel-Grid',
  enableDragDrop: true,
  ddGroup: 'cal-event',
  initComponent: function initComponent() {
    this.app = Tine.Tinebase.appMgr.get('Calendar');
    this.store.sort(this.defaultSortInfo.field, this.defaultSortInfo.direction);
    this.cm = Tine.Calendar.GridView.initCM(this.app);
    this.selModel = this.initSM();
    this.view = this.initVIEW();
    this.on('rowcontextmenu', function (grid, row, e) {
      var selModel = grid.getSelectionModel();

      if (!selModel.isSelected(row)) {
        selModel.selectRow(row);
      }
    }, this);
    this.on('rowclick', Tine.widgets.grid.GridPanel.prototype.onRowClick, this); // activate grid header menu for column selection

    this.plugins = this.plugins ? this.plugins : [];
    this.plugins.push(new Ext.ux.grid.GridViewMenuPlugin({}));
    this.enableHdMenu = false;
    Tine.Calendar.GridView.superclass.initComponent.call(this);
  },
  initSM: function initSM() {
    return new Ext.grid.RowSelectionModel({
      allowMultiple: true,
      getSelectedEvents: function getSelectedEvents() {
        return this.getSelections();
      },

      /**
       * Select an event.
       * 
       * @param {Tine.Calendar.Model.Event} event The event to select
       * @param {EventObject} e (optional) An event associated with the selection
       * @param {Boolean} keepExisting True to retain existing selections
       * @return {Tine.Calendar.Model.Event} The selected event
       */
      select: function select(event, e, keepExisting) {
        if (!event || !event.ui) {
          return event;
        }

        var idx = this.grid.getStore.indexOf(event);
        this.selectRow(idx, keepExisting);
        return event;
      }
    });
  },
  initVIEW: function initVIEW() {
    return new Ext.grid.GridView(Ext.apply({}, this.viewConfig, {
      grid: this,
      forceFit: true,
      store: this.store,
      getPeriod: function getPeriod() {
        return this.grid.getTopToolbar().periodPicker.getPeriod();
      },
      updatePeriod: function updatePeriod(period) {
        this.startDate = period.from;
        var tbar = this.grid.getTopToolbar();

        if (tbar) {
          tbar.periodPicker.update(period);
          this.startDate = tbar.periodPicker.getPeriod().from;
        }
      },
      getTargetEvent: function getTargetEvent(e) {
        var idx = this.findRowIndex(e.getTarget());
        return this.grid.getStore().getAt(idx);
      },
      getTargetDateTime: Ext.emptyFn,
      getSelectionModel: function getSelectionModel() {
        return this.grid.getSelectionModel();
      },
      print: function print() {
        Ext.ux.Printer.print(this.grid);
      },
      getRowClass: this.getViewRowClass
    }));
  },
  attendeeStatusRenderer: function attendeeStatusRenderer(attendee) {
    var store = new Tine.Calendar.Model.Attender.getAttendeeStore(attendee),
        attender = null;
    store.each(function (a) {
      if (a.getUserId() == this.record.id && a.get('user_type') == 'user') {
        attender = a;
        return false;
      }
    }, this);

    if (attender) {
      return Tine.Tinebase.widgets.keyfield.Renderer.render('Calendar', 'attendeeStatus', attender.get('status'));
    }
  },

  /**
   * Return CSS class to apply to rows depending upon due status
   * 
   * @param {Tine.Tasks.Task} record
   * @param {Integer} index
   * @return {String}
   */
  getViewRowClass: function getViewRowClass(record, index) {
    var cls = 'cal-status-' + record.get('status');

    if (record.hasPoll()) {
      cls = cls + ' cal-poll-event';
    }

    return cls;
  }
});
/**
 * returns cm
 *
 * @return Ext.grid.ColumnModel
 */

Tine.Calendar.GridView.initCM = function (app, additionalColumns) {
  if (!additionalColumns) {
    additionalColumns = [];
  }

  return new Ext.grid.ColumnModel({
    defaults: {
      sortable: true,
      resizable: true
    },
    columns: additionalColumns.concat([{
      id: 'attachments',
      header: window.i18n._('Attachments'),
      tooltip: window.i18n._('Attachments'),
      dataIndex: 'attachments',
      width: 20,
      sortable: false,
      resizable: false,
      renderer: Tine.widgets.grid.attachmentRenderer,
      hidden: false
    }, {
      id: 'container_id',
      header: Tine.Calendar.Model.Event.getContainerName(),
      width: 150,
      dataIndex: 'container_id',
      renderer: Tine.widgets.grid.RendererManager.get('Calendar', 'Event', 'container_id')
    }, {
      id: 'class',
      header: app.i18n._("Private"),
      width: 50,
      dataIndex: 'class',
      renderer: function renderer(transp) {
        return Tine.Tinebase.common.booleanRenderer(transp == 'PRIVATE');
      }
    }, {
      id: 'tags',
      header: app.i18n._("Tags"),
      width: 50,
      dataIndex: 'tags',
      renderer: Tine.Tinebase.common.tagsRenderer
    }, {
      id: 'dtstart',
      header: app.i18n._("Start Time"),
      width: 120,
      dataIndex: 'dtstart',
      renderer: Tine.Tinebase.common.dateTimeRenderer
    }, {
      id: 'dtend',
      header: app.i18n._("End Time"),
      width: 120,
      dataIndex: 'dtend',
      renderer: Tine.Tinebase.common.dateTimeRenderer
    }, {
      id: 'is_all_day_event',
      header: app.i18n._("whole day"),
      width: 50,
      dataIndex: 'is_all_day_event',
      renderer: Tine.Tinebase.common.booleanRenderer
    }, {
      id: 'transp',
      header: app.i18n._("Blocking"),
      width: 50,
      dataIndex: 'transp',
      renderer: function renderer(transp) {
        return Tine.Tinebase.common.booleanRenderer(transp == 'OPAQUE');
      }
    }, {
      id: 'status',
      header: app.i18n._("Tentative"),
      width: 50,
      dataIndex: 'status',
      renderer: function renderer(transp) {
        return Tine.Tinebase.common.booleanRenderer(transp == 'TENTATIVE');
      }
    }, {
      id: 'summary',
      header: app.i18n._("Summary"),
      width: 200,
      dataIndex: 'summary',
      renderer: function renderer(summary, metadata, event) {
        return event.getTitle();
      }
    }, {
      id: 'location',
      header: app.i18n._("Location"),
      width: 200,
      hidden: true,
      dataIndex: 'location'
    }, {
      id: 'organizer',
      header: app.i18n._("Organizer"),
      width: 200,
      hidden: true,
      dataIndex: 'organizer',
      renderer: Tine.Calendar.AttendeeGridPanel.prototype.renderAttenderUserName
    }, {
      id: 'description',
      header: app.i18n._("Description"),
      width: 200,
      hidden: true,
      dataIndex: 'description',
      renderer: function renderer(description, metaData, record) {
        if (metaData) {
          metaData.attr = 'ext:qtip="' + Ext.util.Format.nl2br(Ext.util.Format.htmlEncode(Ext.util.Format.htmlEncode(description))) + '"';
        }

        return Ext.util.Format.htmlEncode(description);
      }
    }])
  });
};

/***/ }),

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

/*
 * Tine 2.0
 *
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2017 Metaways Infosystems GmbH (http://www.metaways.de)
 */
Ext.ns('Tine.Calendar');
/**
 * @namespace   Tine.Calendar
 * @class       Tine.Calendar.TimelineLabel
 * @extends     Ext.Component
 *
 * Calendar timeline view
 *
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @constructor
 * @param {Object} config
 */

Tine.Calendar.TimelineLabel = Ext.extend(Ext.Component, {
  /**
   * @cfg {String} label
   * Note: must be escaped properly
   */
  label: '',
  iconCls: 'cal-timelinelabel-noicon',
  initialHeight: 25,
  collapsed: true,
  collapsedCls: 'cal-timelinelabel-collapsed',
  cls: 'cal-timelinelabel',
  initComponent: function initComponent() {
    if (this.collapsed) {
      this.cls = this.cls + ' ' + this.collapsedCls;
    }

    this.style = 'height: ' + this.initialHeight + 'px;';
    this.tpl = ['<div class="cal-timelinelabel-collapsetool"></div>', '<div class="cal-timelinelabel-icon {iconCls}"></div>', '{label}'];
    this.data = {
      label: this.label,
      iconCls: this.iconCls
    };
    Tine.Calendar.TimelineLabel.superclass.initComponent.call(this);
  },
  afterRender: function afterRender() {
    Tine.Calendar.TimelineLabel.superclass.afterRender.call(this);
    this.getEl().on('click', this.toggleCollapsed, this);
  },
  toggleCollapsed: function toggleCollapsed() {
    return this.collapsed ? this.expand() : this.collapse();
  },
  collapse: function collapse() {
    if (!this.collapsed) {
      this.getEl().addClass(this.collapsedCls);
      this.collapsed = true;
      this.getEl().dom.style.height = this.initialHeight + 'px';
      this.fireEvent('collapse', this, this.initialHeight);
    }
  },
  expand: function expand() {
    var o = {
      expandedHeight: this.initialHeight
    };
    this.collapsed = false;
    this.getEl().removeClass(this.collapsedCls);
    this.fireEvent('beforeexpand', this, o);
    this.getEl().dom.style.height = o.expandedHeight + 'px';
  }
});

/***/ }),

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

/*
 * Tine 2.0
 *
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2017 Metaways Infosystems GmbH (http://www.metaways.de)
 */
Ext.ns('Tine.Calendar');
Tine.Calendar.TimelineViewEventUI = Ext.extend(Tine.Calendar.EventUI, {
  render: function render(view) {
    Tine.Calendar.TimelineViewEventUI.superclass.render.call(this, view);
    var from = view.period.from.getTime(),
        until = view.period.until.getTime(),
        start = Math.max(from, this.dtStart.getTime()),
        end = Math.min(until, this.dtEnd.getTime()),
        length = end - start,
        f = view.scalingFactor,
        pos = this.event.parallelEventRegistry.position;
    this.zIndex = pos * 100;
    var data = {
      id: view.id + '-event:' + this.event.get('id'),
      width: f * length + '%',
      height: 15 + 'px',
      left: f * (start - from) + '%',
      top: 3 + (view.collapsed ? 0 : pos * 23) + 'px',
      tagsHtml: Tine.Tinebase.common.tagsRenderer(this.event.get('tags')),
      summary: this.event.get('summary'),
      startTime: this.dtStart.format('H:i'),
      extraCls: this.extraCls,
      color: this.colorSet.color,
      bgColor: this.colorSet.light,
      textColor: this.colorSet.text,
      zIndex: this.zIndex,
      statusIcons: this.statusIcons
    };
    view.templates.event.insertFirst(view.getEl(), data, true);
    this.domIds.push(data.id);
  }
});

/***/ }),

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

/*
 * Tine 2.0
 *
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2017 Metaways Infosystems GmbH (http://www.metaways.de)
 */
Ext.ns('Tine.Calendar');

__webpack_require__(1794);
/**
 * @namespace   Tine.Calendar
 * @class       Tine.Calendar.TimelineView
 * @extends     Tine.Calendar.AbstractView
 *
 * Calendar timeline view
 *
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @constructor
 * @param {Object} config
 */


Tine.Calendar.TimelineView = Ext.extend(Tine.Calendar.AbstractView, {
  /**
   * @cfg {Ext.data.Store} store
   */
  store: null,

  /**
   * @cfg {Object} period
   * period to display
   */
  period: null,

  /**
   * @cfg {Tine.Calendar.TimelineLabel} label
   */
  label: null,
  initialHeight: 25,
  collapsed: true,
  cls: 'cal-timeline-view',
  collapsedCls: 'cal-timeline-view-collapsed',
  eventCls: 'cal-daysviewpanel-event',
  initComponent: function initComponent() {
    if (this.collapsed) {
      this.cls = this.cls + ' ' + this.collapsedCls;
    }

    this.style = 'height: ' + this.initialHeight + 'px;';

    if (this.label) {
      this.label.on('beforeexpand', function (label, o) {
        this.expand();
        o.expandedHeight = this.getExpandedHeight();
      }, this);
      this.label.on('collapse', function (o) {
        this.collapse();
      }, this);
    }

    this.initParallelEventRegistry();
    this.updatePeriod(this.period);
    Tine.Calendar.TimelineView.superclass.initComponent.call(this);
  },
  unbufferedOnLayout: function unbufferedOnLayout(shallow, forceLayout) {
    var currHeight = this.el.getHeight(),
        height = this.collapsed ? this.initialHeight : this.getExpandedHeight();

    if (currHeight != height) {
      this.getEl().dom.style.height = height + 'px';

      if (this.label) {
        this.label.getEl().dom.style.height = height + 'px';
      }
    }
  },
  updatePeriod: function updatePeriod(period) {
    this.period = period;
    var msTotal = this.period.until.getTime() - this.period.from.getTime();
    this.scalingFactor = 100 / msTotal;
  },
  insertEvent: function insertEvent(event) {
    event.ui = new Tine.Calendar.TimelineViewEventUI(event);
    event.ui.render(this);
    this.onLayout();
  },
  getExpandedHeight: function getExpandedHeight() {
    return Math.max(this.initialHeight, this.getParallelEventRegistry().map.length * this.initialHeight);
  },
  toggleCollapsed: function toggleCollapsed() {
    return this.collapsed ? this.expand() : this.collapse();
  },
  collapse: function collapse() {
    if (!this.collapsed) {
      this.getEl().addClass(this.collapsedCls);
      this.collapsed = true;
      this.getEl().dom.style.height = this.initialHeight + 'px';
      this.store.each(this.replaceEvent, this);
      this.fireEvent('collapse', this, this.initialHeight);
    }
  },
  expand: function expand() {
    var expandedHeight = this.getExpandedHeight();
    this.collapsed = false;
    this.getEl().removeClass(this.collapsedCls);
    this.getEl().dom.style.height = expandedHeight + 'px';
    this.store.each(this.replaceEvent, this);
    this.fireEvent('expand', this, expandedHeight);
  },

  /**
   * inits all tempaltes of this view
   */
  initTemplates: function initTemplates() {
    var ts = this.templates || {};
    ts.event = new Ext.XTemplate('<div id="{id}" class="cal-daysviewpanel-event {extraCls}" style="width: {width}; height: {height}; left: {left}; top: {top}; z-index: {zIndex}; background-color: {bgColor}; border-color: {color};">' + '<div class="cal-daysviewpanel-wholedayevent-tags">{tagsHtml}</div>' + '<div class="cal-daysviewpanel-wholedayevent-body">{[Ext.util.Format.nl2br(Ext.util.Format.htmlEncode(values.summary))]}</div>' + '<div class="cal-daysviewpanel-event-header-icons" style="background-color: {bgColor};" >' + '<tpl for="statusIcons">' + '<img src="', Ext.BLANK_IMAGE_URL, '" class="cal-status-icon {status}-black" ext:qtip="{[this.encode(values.text)]}" />', '</tpl>' + '</div>' + '</div>', {
      encode: function encode(v) {
        return Tine.Tinebase.common.doubleEncode(v);
      }
    });

    for (var k in ts) {
      var t = ts[k];

      if (t && typeof t.compile == 'function' && !t.compiled) {
        t.disableFormats = true;
        t.compile();
      }
    }

    this.templates = ts;
  }
});

/***/ }),

/***/ 1794:
/***/ (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__(1795);
if(typeof content === 'string') content = [[module.i, content, '']];
// Prepare cssTransformation
var transform;

var options = {"hmr":true}
options.transform = transform
// add the styles to the DOM
var update = __webpack_require__(17)(content, options);
if(content.locals) module.exports = content.locals;
// Hot Module Replacement
if(false) {}

/***/ }),

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

var escape = __webpack_require__(103);
exports = module.exports = __webpack_require__(16)(false);
// imports


// module
exports.push([module.i, ".cal-timelinepanel-header {\n    height: 100%;\n    /*background:#F9F9F9 url(../../library/ExtJS/resources/images/default/grid/grid3-hrow.gif) repeat-x scroll 0 top;*/\n    overflow-y: scroll;\n}\n\n.cal-timelinepanel-header-label {\n    /*background:#F9F9F9 url(../../library/ExtJS/resources/images/default/grid/grid3-hrow.gif) repeat-x scroll 0 top;*/\n    box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    -webkit-box-sizing: border-box;\n    border-right: 3px double #E1E1E1;\n}\n\n.cal-timelinepanel-yscroller-labels {\n    box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    -webkit-box-sizing: border-box;\n    border-right: 3px double #E1E1E1;\n}\n\n.cal-timelinepanel-headeritem {\n    height: 100%;\n    float: left;\n    padding-top: 5px;\n    padding-left: 3px;\n     box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    -webkit-box-sizing: border-box;\n    border-right: 1px dotted #E1E1E1;\n    text-align: left;\n    color:black;\n    font-family:arial,tahoma,helvetica,sans-serif;\n    font-size:11px;\n    font-size-adjust:none;\n    font-style:normal;\n    font-variant:normal;\n    font-weight:normal;\n    line-height:normal;\n    white-space:nowrap;\n    overflow: hidden;\n}\n\n.cal-timelinepanel-headeritem:hover, .cal-timelinepanel-headeritem-today{\n    background:#EBF3FD url(" + escape(__webpack_require__(226)) + ") repeat-x scroll 0 bottom;\n}\n\n.cal-timelinepanel-headeritem-long {\n    display: none;\n}\n\n.cal-timelinepanel-header-long .cal-timelinepanel-headeritem-long {\n    display: inline;\n}\n\n.cal-timelinepanel-header-long .cal-timelinepanel-headeritem-short {\n    display: none;\n}\n\n.cal-timelinepanel-vscroller .x-box-inner {\n    overflow-y: scroll;\n}\n\n\n/*.cal-timelinepanel-yscroller-labels,*/\n/*.cal-timelinepanel-yscroller-timelines {*/\n    /*box-sizing: border-box;*/\n    /*-moz-box-sizing: border-box;*/\n    /*-webkit-box-sizing: border-box;*/\n/*}*/\n\n.cal-timelinelabel {\n    background-color: #F9F9F9;\n    box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    -webkit-box-sizing: border-box;\n    border-bottom: 1px solid #E1E1E1;\n    color:black;\n    font-family:arial,tahoma,helvetica,sans-serif;\n    font-size:11px;\n    font-size-adjust:none;\n    font-style:normal;\n    font-variant:normal;\n    font-weight:normal;\n    line-height:normal;\n    white-space:nowrap;\n    text-overflow: ellipsis;\n    padding-top: 5px;\n    overflow: hidden;\n}\n\n.cal-timelinelabel div {\n    height: 100%;\n    float: left;\n}\n\n.cal-timelinelabel-collapsetool {\n    width: 16px;\n    background:#F9F9F9 url(" + escape(__webpack_require__(158)) + ") no-repeat -18px 0;\n    position: relative;\n    margin-top: -4px;\n}\n\n.cal-timelinelabel-collapsetool:hover {\n    background-position: -48px 0;\n}\n\n.cal-timelinelabel-collapsed .cal-timelinelabel-collapsetool {\n    background-position: 0 0;\n}\n\n.cal-timelinelabel-collapsed .cal-timelinelabel-collapsetool:hover {\n    background-position: -32px 0;\n}\n\n.cal-timelinelabel-icon {\n    width: 20px;\n    margin-right: 2px;\n    margin-top: -3px;\n}\n\n.cal-timelinelabel-icon . .cal-timelinelabel-noicon {\n    width: 0px;\n    margin: 0;\n}\n\n.cal-timeline-view {\n    background-color: #FFFFFF;\n    position: relative;\n    padding-top: 2px;\n    box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    -webkit-box-sizing: border-box;\n    border-bottom: 1px solid #E1E1E1;\n}\n\n/* reuse daysview allday css */\n.cal-timeline-view .cal-daysviewpanel-event {\n    margin-left: 0px;\n}\n\n.cal-timeline-view .cal-daysviewpanel-event .cal-daysviewpanel-wholedayevent-body,\n.cal-timeline-view .cal-daysviewpanel-event-editgrant .cal-daysviewpanel-event-header {\n    cursor: pointer !important;\n}\n\n.cal-timeline-view .cal-daysviewpanel-event-header-icons {\n    /*background: #EDEDED url(../../images/white-gradiend.png) repeat-y right;*/\n    padding-left: 2px;\n    top: 3px;\n}\n", ""]);

// exports


/***/ }),

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

/*
 * Tine 2.0
 *
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2017 Metaways Infosystems GmbH (http://www.metaways.de)
 */
Ext.ns('Tine.Calendar');
/**
 * @namespace   Tine.Calendar
 * @class       Tine.Calendar.TimelinePanel
 * @extends     Ext.Panel
 *
 * Calendar timeline view
 *
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @constructor
 * @param {Object} config
 */

Tine.Calendar.TimelinePanel = Ext.extend(Ext.Panel, {
  /**
   * @cfg {Object} period
   * period to display
   */
  period: null,

  /**
   * @cfg {Ext.data.Store} store
   */
  store: null,

  /**
   * @cfg {String} viewType
   */
  viewType: 'month',

  /**
   * @cfg {Number} labelWidth
   * width of left label column
   */
  labelWidth: 150,

  /**
   * @cfg {String} dayFormatString
   * i18n._('{0}, the {1}. of {2}')
   */
  dayFormatString: '{0}, the {1}. of {2}',

  /**
   * @property {Number} scalingFactor
   * percentage per millisecond
   */
  scalingFactor: null,
  groupingMetadataCache: null,
  layout: 'vbox',
  border: false,
  layoutConfig: {
    align: 'stretch',
    pack: 'start'
  },
  initComponent: function initComponent() {
    this.app = Tine.Tinebase.appMgr.get('Calendar');
    this.dayFormatString = this.app.i18n._hidden(this.dayFormatString);
    this.groupingMetadataCache = {};
    this.labels = [];
    this.items = [{
      ref: 'headerRow',
      height: 24,
      layout: 'hbox',
      border: false,
      xtype: 'container',
      layoutConfig: {
        align: 'stretch',
        pack: 'start'
      },
      items: [{
        ref: '../periodLabel',
        cls: 'cal-timelinepanel-header-label',
        width: this.labelWidth,
        border: false,
        xtype: 'container'
      }, {
        ref: '../timelineHeading',
        flex: 1,
        layout: 'fit',
        border: false,
        xtype: 'container'
      }]
    }, {
      ref: 'vScroller',
      cls: 'cal-timelinepanel-vscroller',
      flex: 1,
      layout: 'hbox',
      border: false,
      xtype: 'container',
      layoutConfig: {
        align: 'stretch',
        pack: 'start'
      },
      items: [{
        ref: '../timelineLabels',
        cls: 'cal-timelinepanel-yscroller-labels',
        width: this.labelWidth,
        border: false,
        xtype: 'container',
        autoHeight: true
      }, {
        ref: '../timelines',
        cls: 'cal-timelinepanel-yscroller-timelines',
        flex: 1,
        border: false,
        xtype: 'container',
        autoHeight: true
      }]
    }];
    this.groupCollection = new Tine.Tinebase.data.GroupedStoreCollection({
      store: this.store,
      group: this.groupingFn.createDelegate(this),
      groupOnLoad: false,
      listeners: {
        scope: this,
        add: this.onGroupAdd,
        remove: this.onGroupRemove
      }
    });
    this.store.on('beforeload', this.onStoreBeforeLoad, this);
    this.store.on('load', this.onStoreLoad, this);
    this.initTemplates();

    if (!this.selModel) {
      this.selModel = this.selModel || new Tine.Calendar.EventSelectionModel();
    }

    Tine.Calendar.TimelinePanel.superclass.initComponent.apply(this, arguments);
  },
  onStoreBeforeLoad: function onStoreBeforeLoad(store, options) {
    this.resolveGroupingItemsPromise = Promise.resolve(); // resolve members for memberOf filters

    const attendeeFilter = Tine.Calendar.AttendeeFilterGrid.prototype.extractFilterValue(options.params.filter);

    const memberIds = _.reduce(attendeeFilter, (memberIds, attendee) => {
      return memberIds.concat(memberIds, _.get(attendee, 'user_type') === 'memberOf' ? _.get(attendee, 'user_id.members', []) : []);
    }, []);

    if (memberIds.length) {
      this.resolveGroupingItemsPromise = Tine.Addressbook.searchContacts([{
        field: 'id',
        operator: 'in',
        value: _.compact(_.uniq(memberIds))
      }]);
    }
  },
  onStoreLoad: async function onStoreLoad(store, records, options) {
    this.groupingMetadataCache = {};
    var fixedGroups = [],
        attendeeFilterValue = Tine.Calendar.AttendeeFilterGrid.prototype.extractFilterValue(options.params.filter),
        attendeeStore = attendeeFilterValue ? Tine.Calendar.Model.Attender.getAttendeeStore(attendeeFilterValue) : null;
    options.keepLoadMask = true;
    const members = await this.resolveGroupingItemsPromise;

    if (attendeeStore) {
      attendeeStore.each(async attendee => {
        if (attendee.get('user_type') === 'memberOf') {
          // add each list member to fixedGroups
          const Attender = Tine.Calendar.Model.Attender;

          _.each(_.get(attendee, 'data.user_id.members', []), memberId => {
            const memberContact = _.find(_.get(members, 'results', {}), {
              id: memberId
            });

            if (memberContact) {
              const memberAttendee = new Attender(Attender.getDefaultData({
                user_type: 'user',
                user_id: memberContact
              }));
              const groupName = memberAttendee.getCompoundId();
              fixedGroups.push(groupName);
              this.groupingMetadataCache[groupName] = memberAttendee;
            }
          });
        } else {
          var groupName = attendee.getCompoundId();
          fixedGroups.push(groupName);
          this.groupingMetadataCache[groupName] = attendee;
        }
      });
    }

    this.groupCollection.setFixedGroups(_.uniq(fixedGroups));
    this.mainScreen.loadMask.hide();
  },
  groupingFn: function groupingFn(event) {
    var groups = [],
        attendeeStore = Tine.Calendar.Model.Attender.getAttendeeStore(event.get('attendee'));
    attendeeStore.each(function (attendee) {
      var groupName = this.getAttendeeType(attendee) + '-' + attendee.getUserId();

      if (!this.groupingMetadataCache.hasOwnProperty(groupName)) {
        this.groupingMetadataCache[groupName] = attendee;
      }

      groups.push(groupName);
    }, this);
    return groups;
  },
  getAttendeeType: function getAttendeeType(attendee) {
    var attendeeType = attendee.get('user_type');
    return attendeeType === 'groupmember' ? 'user' : attendeeType;
  },
  onGroupAdd: function onGroupAdd(idx, groupStore, groupName) {
    var _ = window.lodash,
        attendee = this.groupingMetadataCache[groupName],
        name = Tine.Calendar.AttendeeGridPanel.prototype.renderAttenderName.call(Tine.Calendar.AttendeeGridPanel.prototype, attendee.get('user_id'), false, attendee),
        type = this.getAttendeeType(attendee);
    var label = new Tine.Calendar.TimelineLabel({
      groupName: groupName,
      label: name,
      iconCls: type === 'user' ? 'tine-grid-row-action-icon renderer_typeAccountIcon' : attendee.getIconCls(),
      groupSortOrder: Tine.Calendar.Model.Attender.getSortOrder(type)
    });
    this.labels.push(label);
    this.labels = _.sortBy(this.labels, ['groupSortOrder', 'label']);
    var idx = this.labels.indexOf(label);
    this.timelineLabels.insert(idx, label);
    this.timelineLabels.doLayout();
    var view = new Tine.Calendar.TimelineView({
      groupName: groupName,
      store: groupStore,
      period: this.period,
      label: label
    });
    this.timelines.insert(idx, view);
    this.timelines.doLayout();
    this.relayEvents(view, ['click', 'dblclick', 'contextmenu']);
    view.getSelectionModel().on('selectionchange', this.onSelectionChange.createDelegate(this, [view]));
  },
  onGroupRemove: function onGroupRemove(groupStore, groupName) {
    this.timelineLabels.remove(this.timelineLabels.find('groupName', groupName)[0]);
    this.timelines.remove(this.timelines.find('groupName', groupName)[0]);
  },
  getSelectionModel: function getSelectionModel() {
    return this.selModel;
  },
  onSelectionChange: function onSelectionChange(view) {
    if (this.selectionChangeLocked) return;
    this.selectionChangeLocked = true;
    view = Ext.isString(view) ? this.timelines.items.get(view) : view;
    this.activeView = view; // clear selections from other views

    this.timelines.items.each(function (v) {
      if (v !== view) {
        v.getSelectionModel().clearSelections(true);
      }
    }, this);
    var selections = view.getSelectionModel().getSelectedEvents();
    this.getSelectionModel().clearSelections();
    Ext.each(selections, function (viewEvent) {
      var event = this.store.getById(viewEvent.id); // @TODO: have own (grouping) ui

      if (event) {
        event.ui = viewEvent.ui;
      }

      this.getSelectionModel().select(event, true);
    }, this);
    this.selectionChangeLocked = false;
  },
  getPeriod: function getPeriod() {
    return this.period;
  },
  updatePeriod: function updatePeriod(period) {
    this.period = period;
    var tbar = this.getTopToolbar();

    if (tbar) {
      tbar.periodPicker.update(period.from);
      this.period = tbar.periodPicker.getPeriod();
      this.viewType = tbar.view;
    } // @TODO do this on period change only


    this.timelines.items.each(function (view) {
      view.updatePeriod(this.period);
    }, this);
    this.onLayout();
  },
  onLayout: function onLayout() {
    Tine.Calendar.TimelinePanel.superclass.onLayout.apply(this, arguments); // update header & scaling

    var msTotal = this.period.until.getTime() - this.period.from.getTime();
    this.scalingFactor = 100 / msTotal; // this.periodLabel.update(this.period.from.format())

    this.setHeaders();
  },
  setHeaders: function setHeaders() {
    var items = [],
        item = null,
        itemStart = this.period.from,
        periodEndTs = this.period.until.getTime(),
        unit = this.viewType == 'day' ? Date.HOUR : Date.DAY,
        formatString = this.viewType == 'day' ? 'G' : 'd',
        itemEnd = itemStart.add(unit, 1);

    if (this.viewType != 'day') {
      itemEnd.setHours(0);
    }

    itemEnd.setMinutes(0);
    itemEnd.setSeconds(0);
    itemEnd.setMilliseconds(0);

    while (itemEnd <= this.period.until) {
      item = {
        header: itemStart.format(formatString),
        width: this.scalingFactor * (Math.min(periodEndTs, itemEnd.getTime()) - itemStart.getTime())
      };
      item.headerLong = this.viewType == 'day' ? item.header : String.format(this.dayFormatString, itemStart.format('l'), itemStart.format('j'), itemStart.format('F'));
      items.push(item);
      itemStart = itemEnd;
      itemEnd = itemStart.add(unit, 1);
    }

    this.timelineHeading.update(this.templates.header.apply(items));
  },
  onResize: function onResize(w, h) {
    Tine.Calendar.TimelinePanel.superclass.onResize.apply(this, arguments);
  },
  getTargetEvent: function getTargetEvent(e) {
    var viewEl = e.getTarget('.cal-timeline-view'),
        id = viewEl ? viewEl.id : undefined,
        view = this.timelines.items.get(id);
    return view.getTargetEvent(e);
  },
  getTargetDateTime: Ext.emptyFn,
  print: function print() {
    Ext.ux.Printer.print(this.grid);
  },
  getView: function getView() {
    return this;
  },
  getStore: function getStore() {
    return this.store;
  },
  initTemplates: function initTemplates() {
    var ts = this.templates || {};
    ts.header = new Ext.XTemplate('<div class="cal-timelinepanel-header">', '<tpl for=".">', '<div class="cal-timelinepanel-headeritem<tpl if="width &gt; 10"> cal-timelinepanel-header-long</tpl>" style="width: {width}%;">', '<span class="cal-timelinepanel-headeritem-short">{header}</span>', '<span class="cal-timelinepanel-headeritem-long">{headerLong}</span>', '</div>', '</tpl>', '</div>');

    for (var k in ts) {
      var t = ts[k];

      if (t && typeof t.compile == 'function' && !t.compiled) {
        t.disableFormats = true;
        t.compile();
      }
    }

    this.templates = ts;
  }
});

/***/ }),

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

/*
 * Tine 2.0
 * 
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Alexander Stintzing <a.stintzing@metaways.de>
 * @copyright   Copyright (c) 2014 Metaways Infosystems GmbH (http://www.metaways.de)
 */
Ext.ns('Tine.Calendar');
/**
 * @namespace   Tine.Calendar
 * @class       Tine.Calendar.ExceptionHandler
 * 
 * <p>Exception Handler for Calendar</p>
 * 
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Alexander Stintzing <a.stintzing@metaways.de>
 */

Tine.Calendar.handleRequestException = function (exception, callback, callbackScope) {
  if (!exception.code && exception.responseText) {
    // we need to decode the exception first
    var response = Ext.util.JSON.decode(exception.responseText);
    exception = response.data;
  }

  var app = Tine.Tinebase.appMgr.get('Calendar');
  var defaults = {
    buttons: Ext.Msg.OK,
    icon: Ext.MessageBox.ERROR,
    fn: callback,
    scope: callbackScope,
    title: app.i18n._(exception.title),
    msg: app.i18n._(exception.message)
  };
  Tine.log.warn('Request exception :');
  Tine.log.warn(exception);

  switch (exception.code) {
    case 911:
      // Calendar_Exception_InvalidUrl
      Ext.MessageBox.show(defaults);
      break;
    // return false will the generic exceptionhandler handle the caught exception

    default:
      return false;
  }

  return true;
};

Tine.Tinebase.ExceptionHandlerRegistry.register('Calendar', Tine.Calendar.handleRequestException);

/***/ }),

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

/* 
 * Tine 2.0
 * 
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2007-2008 Metaways Infosystems GmbH (http://www.metaways.de)
 */
Ext.ns('Tine.Calendar');
Tine.Calendar.PagingToolbar = Ext.extend(Ext.Toolbar, {
  /**
   * @cfg {Date} dtstart
   */
  dtStart: null,

  /**
   * @cfg {String} view
   */
  view: 'day',

  /**
   * @private periodPicker
   */
  periodPicker: null,

  /**
   * @cfg {Boolean} showReloadBtn
   */
  showReloadBtn: true,

  /**
   * @cfg {Boolean} showTodayBtn
   */
  showTodayBtn: true,

  /**
   * shows if the periodpicker is active
   * @type boolean
   */
  periodPickerActive: null,

  /**
   * @private
   */
  initComponent: function initComponent() {
    this.addEvents(
    /**
     * @event change
     * Fired whenever a viewstate changes
     * @param {Tine.Calendar.PagingToolbar} this
     * @param {String} activeView
     * @param {Array} period
     */
    'change',
    /**
     * @event refresh
     * Fired when user request view freshresh
     * @param {Tine.Calendar.PagingToolbar} this
     * @param {String} activeView
     * @param {Array} period
     */
    'refresh');

    if (!Ext.isDate(this.dtStart)) {
      this.dtStart = new Date().clearTime();
    }

    this.periodPicker = new Tine.Calendar.PagingToolbar[Ext.util.Format.capitalize(this.view) + 'PeriodPicker']({
      tb: this,
      listeners: {
        scope: this,
        change: function change(picker, view, period) {
          this.dtStart = period.from.clearTime(true);
          this.fireEvent('change', this, view, period);
        },
        menushow: function menushow() {
          this.periodPickerActive = true;
        },
        menuhide: function menuhide() {
          this.periodPickerActive = false;
        }
      }
    });
    Tine.Calendar.PagingToolbar.superclass.initComponent.call(this);
    this.bind(this.store);
  },

  /**
   * @private
   */
  onRender: function onRender(ct, position) {
    Tine.Calendar.PagingToolbar.superclass.onRender.call(this, ct, position);
    this.prevBtn = this.addButton({
      tooltip: Ext.PagingToolbar.prototype.prevText,
      iconCls: "x-tbar-page-prev",
      handler: this.onClick.createDelegate(this, ["prev"])
    });
    this.addSeparator();
    this.periodPicker.render();
    this.addSeparator();
    this.nextBtn = this.addButton({
      tooltip: Ext.PagingToolbar.prototype.nextText,
      iconCls: "x-tbar-page-next",
      handler: this.onClick.createDelegate(this, ["next"])
    });
    if (this.showTodayBtn || this.showReloadBtn) this.addSeparator();

    if (this.showTodayBtn) {
      this.todayBtn = this.addButton({
        text: Ext.DatePicker.prototype.todayText,
        iconCls: 'cal-today-action',
        handler: this.onClick.createDelegate(this, ["today"])
      });
    }

    if (this.showReloadBtn) {
      this.loading = this.addButton({
        tooltip: Ext.PagingToolbar.prototype.refreshText,
        iconCls: "x-tbar-loading",
        handler: this.onClick.createDelegate(this, ["refresh"])
      });
    }

    this.addFill();

    if (this.additionalItems) {
      this.addButton(this.additionalItems);
    }

    if (this.isLoading) {
      this.loading.disable();
    }
  },

  /**
   * @private
   * @param {String} which
   */
  onClick: function onClick(which) {
    switch (which) {
      case 'today':
      case 'next':
      case 'prev':
        this.periodPicker[which]();
        this.fireEvent('change', this, this.activeView, this.periodPicker.getPeriod());
        break;

      case 'refresh':
        this.fireEvent('refresh', this, this.activeView, this.periodPicker.getPeriod());
        break;
    }
  },

  /**
   * returns requested period
   * @return {Array}
   */
  getPeriod: function getPeriod() {
    return this.periodPicker.getPeriod();
  },
  // private
  beforeLoad: function beforeLoad() {
    this.isLoading = true;

    if (this.rendered && this.loading) {
      this.loading.disable();
    }
  },
  // private
  onLoad: function onLoad(store, r, o) {
    this.isLoading = false;

    if (this.rendered && this.loading) {
      this.loading.enable();
    }
  },

  /**
   * Unbinds the paging toolbar from the specified {@link Ext.data.Store}
   * @param {Ext.data.Store} store The data store to unbind
   */
  unbind: function unbind(store) {
    store = Ext.StoreMgr.lookup(store);
    store.un("beforeload", this.beforeLoad, this);
    store.un("load", this.onLoad, this); //store.un("loadexception", this.onLoadError, this);

    this.store = undefined;
  },

  /**
   * Binds the paging toolbar to the specified {@link Ext.data.Store}
   * @param {Ext.data.Store} store The data store to bind
   */
  bind: function bind(store) {
    store = Ext.StoreMgr.lookup(store);
    store.on("beforeload", this.beforeLoad, this);
    store.on("load", this.onLoad, this); //store.on("loadexception", this.onLoadError, this);

    this.store = store;
  },

  /**
   * just needed when inserted in an eventpickercombobox
   */
  bindStore: function bindStore() {},
  // private
  onDestroy: function onDestroy() {
    if (this.store) {
      this.unbind(this.store);
    }

    Tine.Calendar.PagingToolbar.superclass.onDestroy.call(this);
  }
});
/**
 * @class Tine.Calendar.PagingToolbar.AbstractPeriodPicker
 * @extends Ext.util.Observable
 * @constructor
 * @param {Object} config
 */

Tine.Calendar.PagingToolbar.AbstractPeriodPicker = function (config) {
  Ext.apply(this, config);
  this.addEvents(
  /**
   * @event change
   * Fired whenever a period changes
   * @param {Tine.Calendar.PagingToolbar.AbstractPeriodPicker} this
   * @param {String} corresponding view
   * @param {Array} period
   */
  'change');
  Tine.Calendar.PagingToolbar.AbstractPeriodPicker.superclass.constructor.call(this);
  this.update(this.tb.dtStart);
  this.init();
};

Ext.extend(Tine.Calendar.PagingToolbar.AbstractPeriodPicker, Ext.util.Observable, {
  /**
   * period NOTE: might not fit to current range on view changes!
   */
  period: null,
  init: function init() {},
  hide: function hide() {
    this.button.hide();
  },
  show: function show() {
    this.button.show();
  },
  update: function update(period) {},
  render: function render() {},
  prev: function prev() {},
  next: function next() {},
  today: function today() {
    this.update(new Date().clearTime());
  },
  getPeriod: function getPeriod() {}
});
/**
 * @class Tine.Calendar.PagingToolbar.DayPeriodPicker
 * @extends Tine.Calendar.PagingToolbar.AbstractPeriodPicker
 * @constructor
 */

Tine.Calendar.PagingToolbar.DayPeriodPicker = Ext.extend(Tine.Calendar.PagingToolbar.AbstractPeriodPicker, {
  init: function init() {
    this.button = new Ext.Button({
      text: this.tb.dtStart.format(Ext.DatePicker.prototype.format),
      //hidden: this.tb.activeView != 'day',
      menu: new Ext.menu.DateMenu({
        listeners: {
          scope: this,
          select: function select(field) {
            if (typeof field.getValue == 'function') {
              this.update(field.getValue());
              this.fireEvent('change', this, 'day', this.getPeriod());
            }
          }
        }
      })
    });
  },
  update: function update(period) {
    this.dtStart = _.get(period, 'from', period).clearTime(true);

    if (this.button && this.button.rendered) {
      this.button.setText(this.dtStart.format(Ext.DatePicker.prototype.format));
    }
  },
  render: function render() {
    this.button = this.tb.addButton(this.button);
  },
  next: function next() {
    this.dtStart = this.dtStart.add(Date.DAY, 1);
    this.update(this.dtStart);
  },
  prev: function prev() {
    this.dtStart = this.dtStart.add(Date.DAY, -1);
    this.update(this.dtStart);
  },
  getPeriod: function getPeriod() {
    var from = Date.parseDate(this.dtStart.format('Y-m-d') + ' 00:00:00', Date.patterns.ISO8601Long);
    return {
      from: from,
      until: from.add(Date.DAY, 1)
      /*.add(Date.SECOND, -1)*/

    };
  }
});
/**
 * @class Tine.Calendar.PagingToolbar.WeekPeriodPicker
 * @extends Tine.Calendar.PagingToolbar.AbstractPeriodPicker
 * @constructor
 */

Tine.Calendar.PagingToolbar.WeekPeriodPicker = Ext.extend(Tine.Calendar.PagingToolbar.AbstractPeriodPicker, {
  datepickerMenu: null,
  datepickerButton: null,
  wkField: null,
  init: function init() {
    this.label = new Ext.form.Label({
      text: Tine.Tinebase.appMgr.get('Calendar').i18n._('Week'),
      style: 'padding-right: 3px'
    });
    this.wkField = new Ext.form.TextField({
      value: this.tb.dtStart.getWeekOfYear(),
      width: 22,
      cls: "x-tbar-page-number",
      listeners: {
        scope: this,
        specialkey: this.onSelect,
        blur: this.onSelect
      }
    });
    this.yearField = new Ext.form.Label({
      text: this.tb.dtStart.format('o'),
      style: 'padding-left: 3px'
    });
    this.datepickerMenu = new Ext.menu.DateMenu({
      value: this.tb.dtStart,
      hideOnClick: true,
      focusOnSelect: true,
      plugins: [new Ext.ux.DatePickerWeekPlugin({
        weekHeaderString: Tine.Tinebase.appMgr.get('Calendar').i18n._('WK')
      })],
      listeners: {
        scope: this,
        'select': function select(picker, date) {
          var oldPeriod = this.getPeriod();
          this.update(date);

          if (this.getPeriod().from.getElapsed(oldPeriod.from)) {
            this.fireEvent('change', this, 'week', this.getPeriod());
          }
        }
      }
    });
    this.datepickerButton = new Ext.Button({
      iconCls: 'cal-sheet-view-type'
    });
    this.datepickerButton.on('click', function () {
      this.datepickerMenu.show(this.datepickerButton.el);
    }.createDelegate(this));
  },
  onSelect: function onSelect(field, e) {
    if (e && e.getKey() == e.ENTER) {
      return field.blur();
    }

    var diff = field.getValue() - this.dtStart.getWeekOfYear() - parseInt(this.dtStart.getDay() < 1 ? 1 : 0, 10);

    if (diff !== 0) {
      this.update(this.dtStart.add(Date.DAY, diff * 7));
      this.fireEvent('change', this, 'week', this.getPeriod());
    }
  },
  update: function update(period) {
    let dtStart = _.get(period, 'from', period).clearTime(true); // const state = Ext.state.Manager.get('cal-pgtb-pp-wkbtn');


    const state = this.tb.periodBtn.getState();
    const wkStartDiff = state.startIdx - Tine.Calendar.PagingToolbar.WeekPeriodPicker.Button.prototype.beforeDays;
    const startDay = Ext.DatePicker.prototype.startDay; // recalculate dtstart according to WeekPeriodPicker.Button

    this.dtStart = dtStart.add(Date.DAY, -1 * (7 + dtStart.getDay() - startDay - wkStartDiff) % 7);

    if (this.getPeriod().until < dtStart) {
      this.dtStart = this.dtStart.add(Date.DAY, 7);
    }

    if (this.wkField && this.wkField.rendered) {
      // NOTE: '+1' is to ensure we display the ISO8601 based week where weeks always start on monday!
      var wkStart = this.dtStart.add(Date.DAY, dtStart.getDay() < 1 ? 1 : 0).add(Date.DAY, -1 * wkStartDiff);
      this.wkField.setValue(parseInt(wkStart.getWeekOfYear(), 10));
      this.yearField.setText(this.dtStart.format('o'));
    }
  },
  render: function render() {
    this.tb.addField(this.label);
    this.tb.addField(this.wkField);
    this.tb.addField(this.yearField);
    this.tb.addField(this.datepickerButton);
  },
  hide: function hide() {
    this.label.hide();
    this.wkField.hide();
    this.yearField.hide();
    this.datepickerButton.hide();
  },
  show: function show() {
    this.label.show();
    this.wkField.show();
    this.yearField.show();
    this.datepickerButton.show();
  },
  next: function next() {
    this.dtStart = this.dtStart.add(Date.DAY, 7);
    this.update(this.dtStart);
  },
  prev: function prev() {
    this.dtStart = this.dtStart.add(Date.DAY, -7);
    this.update(this.dtStart);
  },
  getPeriod: function getPeriod() {
    const state = this.tb.periodBtn.getState(); // const state = Ext.state.Manager.get('cal-pgtb-pp-wkbtn');

    return {
      from: this.dtStart.clone(),
      until: this.dtStart.add(Date.DAY, state.endIdx - state.startIdx + 1)
    };
  }
});
Tine.Calendar.PagingToolbar.WeekPeriodPicker.Button = Ext.extend(Ext.SplitButton, {
  // override via prototype or config
  beforeDays: 1,
  numDays: 10,
  stateful: true,
  stateId: 'cal-pgtb-pp-wkbtn',
  initComponent: function initComponent() {
    this.app = Tine.Tinebase.appMgr.get('Calendar');
    const state = Ext.state.Manager.get(this.stateId);

    const wkStartDay = _.get(state, 'wkStart', Ext.DatePicker.prototype.startDay);

    const selectionStartIdx = _.get(state, 'startIdx', this.beforeDays + wkStartDay - 1);

    const selectionEndIdx = _.get(state, 'endIdx', selectionStartIdx + 6);

    this.startDay = (wkStartDay + 7 - this.beforeDays) % 7;
    this.dayBtns = []; // @TODO: if week is not standard, have a marker in btn?

    for (let i = 0, dayNum = this.startDay; i < this.numDays; i++, dayNum++) {
      this.dayBtns.push(new Ext.Button({
        pressed: i >= selectionStartIdx && i <= selectionEndIdx,
        dayIdx: i,
        dayNum: dayNum,
        text: Date.dayNames[dayNum % 7].substr(0, 2),
        enableToggle: true,
        scope: this,
        handler: this.onDayBtnPress
      }));
    }

    this.menu = new Ext.menu.Menu({
      items: [new Ext.Toolbar({
        cls: 'cal-wkperiod-config-menu',
        items: [].concat(this.dayBtns, {
          xtype: 'tbtext',
          width: 40
        }, {
          text: i18n._hidden('OK'),
          handler: () => {
            this.menu.hide();
          }
        })
      })]
    });
    this.menu.on('hide', this.onMenuHide, this);
    this.supr().initComponent.call(this);
  },
  onMenuHide: function onMenuHide() {
    const state = Ext.state.Manager.get(this.stateId);

    if (JSON.stringify(state) !== JSON.stringify(this.getState())) {
      this.saveState();
      this.fireEvent('change', this, state);
    }
  },
  onDayBtnPress: function onDayBtnPress(btn) {
    const selected = _.filter(this.dayBtns, {
      pressed: true
    });

    if (!btn.pressed) {
      // deselect/reduce
      const bellow = _.filter(selected, cmp => {
        return cmp.dayIdx < btn.dayIdx;
      });

      const above = _.filter(selected, cmp => {
        return cmp.dayIdx > btn.dayIdx;
      });

      const toReduce = bellow.length < above.length ? bellow : above;

      _.each(toReduce, btn => {
        btn.toggle(false, false);
      });

      if (bellow.length + above.length < 3) {
        btn.toggle(true, false);
      }
    } else {
      // select/expand
      let lastIdx = selected[0].dayIdx;

      _.each(selected, btn => {
        for (let idx = lastIdx + 1; idx < btn.dayIdx; idx++) {
          this.dayBtns[idx].toggle(true, false);
        }

        lastIdx = btn.dayIdx;
      });
    }
  },
  getState: function getState() {
    const state = {
      startIdx: _.find(this.dayBtns, {
        pressed: true
      }).dayIdx,
      endIdx: _.findLast(this.dayBtns, {
        pressed: true
      }).dayIdx
    }; // normalise

    if (state.startIdx - 7 >= 0) {
      state.startIdx = state.startIdx - 7;
      state.endIdx = state.endIdx - 7;
    }

    return state;
  },
  onRender: function onRender() {
    Tine.Calendar.PagingToolbar.WeekPeriodPicker.Button.superclass.onRender.apply(this, arguments); // have less optical focus

    this.btnEl.setStyle({
      border: "none"
    });
  }
});
/**
 * @class Tine.Calendar.PagingToolbar.MonthPeriodPicker
 * @extends Tine.Calendar.PagingToolbar.AbstractPeriodPicker
 * @constructor
 */

Tine.Calendar.PagingToolbar.MonthPeriodPicker = Ext.extend(Tine.Calendar.PagingToolbar.AbstractPeriodPicker, {
  init: function init() {
    this.dateMenu = new Ext.menu.DateMenu({
      hideMonthPicker: Ext.DatePicker.prototype.hideMonthPicker.createSequence(function () {
        if (this.monthPickerActive) {
          this.monthPickerActive = false;
          this.value = this.activeDate;
          this.fireEvent('select', this, this.value);
        }
      }),
      listeners: {
        scope: this,
        select: function select(field) {
          if (typeof field.getValue == 'function') {
            this.update(field.getValue());
            this.fireEvent('change', this, 'month', this.getPeriod());
          }
        }
      }
    });
    this.button = new Ext.Button({
      minWidth: 130,
      text: Ext.DatePicker.prototype.monthNames[this.tb.dtStart.getMonth()] + this.tb.dtStart.format(' Y'),
      //hidden: this.tb.activeView != 'month',
      menu: this.dateMenu,
      listeners: {
        scope: this,
        menushow: function menushow(btn, menu) {
          menu.picker.showMonthPicker();
          menu.picker.monthPickerActive = true;
          this.fireEvent('menushow');
        },
        menuhide: function menuhide(btn, menu) {
          menu.picker.monthPickerActive = false;
          this.fireEvent('menuhide');
        }
      }
    });
  },
  update: function update(period) {
    this.dtStart = _.get(period, 'from', period).clearTime(true);

    if (this.button && this.button.rendered) {
      var monthName = Ext.DatePicker.prototype.monthNames[this.dtStart.getMonth()];
      this.button.setText(monthName + this.dtStart.format(' Y'));
      this.dateMenu.picker.setValue(this.dtStart.clone());
    }
  },
  render: function render() {
    this.button = this.tb.addButton(this.button);
  },
  next: function next() {
    this.dtStart = this.dtStart.add(Date.MONTH, 1);
    this.update(this.dtStart);
  },
  prev: function prev() {
    this.dtStart = this.dtStart.add(Date.MONTH, -1);
    this.update(this.dtStart);
  },
  getPeriod: function getPeriod() {
    var from = Date.parseDate(this.dtStart.format('Y-m') + '-01 00:00:00', Date.patterns.ISO8601Long);
    return {
      from: from,
      until: from.add(Date.MONTH, 1)
      /*.add(Date.SECOND, -1)*/

    };
  }
});
/**
 * @class Tine.Calendar.PagingToolbar.YearPeriodPicker
 * @extends Tine.Calendar.PagingToolbar.AbstractPeriodPicker
 * @constructor
 */

Tine.Calendar.PagingToolbar.YearPeriodPicker = Ext.extend(Tine.Calendar.PagingToolbar.AbstractPeriodPicker, {
  init: function init() {
    this.label = new Ext.form.Label({
      text: Tine.Tinebase.appMgr.get('Calendar').i18n._('Year'),
      style: 'padding-right: 3px'
    });
    this.field = new Ext.form.TextField({
      value: this.tb.dtStart.format('Y'),
      width: 40,
      cls: "x-tbar-page-number",
      listeners: {
        scope: this,
        specialkey: this.onSelect,
        blur: this.onSelect
      }
    });
  },
  onSelect: function onSelect(field, e) {
    if (e && e.getKey() == e.ENTER) {
      return field.blur();
    }

    var diff = field.getValue() - this.dtStart.format('Y');

    if (diff !== 0) {
      this.update(this.dtStart.add(Date.YEAR, diff));
      this.fireEvent('change', this, 'year', this.getPeriod());
    }
  },
  update: function update(period) {
    this.dtStart = _.get(period, 'from', period).clearTime(true);

    if (this.field && this.field.rendered) {
      this.field.setValue(this.dtStart.format('Y'));
    }
  },
  render: function render() {
    this.tb.addField(this.label);
    this.tb.addField(this.field);
  },
  hide: function hide() {
    this.label.hide();
    this.field.hide();
  },
  show: function show() {
    this.label.show();
    this.field.show();
  },
  next: function next() {
    this.dtStart = this.dtStart.add(Date.YEAR, 1);
    this.update(this.dtStart);
  },
  prev: function prev() {
    this.dtStart = this.dtStart.add(Date.YEAR, -1);
    this.update(this.dtStart);
  },
  getPeriod: function getPeriod() {
    var from = Date.parseDate(this.dtStart.format('Y') + '-01-01 00:00:00', Date.patterns.ISO8601Long);
    return {
      from: from,
      until: from.add(Date.YEAR, 1)
    };
  }
});
/**
 * @class Tine.Calendar.PagingToolbar.CustomPeriodPicker
 * @extends Tine.Calendar.PagingToolbar.AbstractPeriodPicker
 * @constructor
 */

Tine.Calendar.PagingToolbar.CustomPeriodPicker = Ext.extend(Tine.Calendar.PagingToolbar.AbstractPeriodPicker, {
  init: function init() {
    this.tb.showTodayBtn = false;
    this.fromLabel = new Ext.form.Label({
      text: Tine.Tinebase.appMgr.get('Calendar').i18n._('From'),
      style: 'padding-right: 3px'
    });
    this.fromPicker = new Ext.ux.form.DateTimeField({
      style: 'margin-top: 2px',
      value: _.get(this, 'tb.period.from', this.tb.startDate) || new Date().clearTime(),
      listeners: {
        scope: this,
        specialkey: this.onSelect,
        blur: this.onSelect
      }
    });
    this.untilLabel = new Ext.form.Label({
      text: Tine.Tinebase.appMgr.get('Calendar').i18n._('until'),
      style: 'padding-left: 10px; padding-right: 3px'
    });
    this.untilPicker = new Ext.ux.form.DateTimeField({
      style: 'margin-top: 2px',
      value: _.get(this, 'tb.period.until', this.tb.startDate) || new Date().clearTime().add(Date.DAY, 5),
      listeners: {
        scope: this,
        specialkey: this.onSelect,
        blur: this.onSelect
      }
    });
    this.period = this.getPeriod();
  },
  onSelect: function onSelect(field, e) {
    if (e && e.getKey() === e.ENTER) {
      return field.blur();
    }

    let currentPeriod = this.period;
    Tine.Tinebase.common.assertComparable(currentPeriod);
    let period = this.getPeriod();
    Tine.Tinebase.common.assertComparable(period);

    if (String(currentPeriod) !== String(period)) {
      this.fireEvent('change', this, 'custom', period);
    }
  },
  update: function update(periodStart, period) {
    let boundaries = ['from', 'until'];

    _.each(boundaries, boundary => {
      if (_.get(this, "".concat(boundary, "Picker")) && _.isDate(_.get(period, boundary))) {
        let date = period[boundary].clone(); // constrain to other boundary

        let boundaryIdx = boundaries.indexOf(boundary);
        let otherBoundary = boundaries[(boundaryIdx + 1) % 2];
        let otherDate = _.isDate(_.get(period, otherBoundary)) ? _.get(period, otherBoundary) : new Date().clearTime();
        this["".concat(boundary, "Picker")].setValue(new Date(Math[boundaryIdx ? 'max' : 'min'](date, otherDate))); // save state

        _.set(this, "period.".concat(boundary), _.get(period, boundary).clone());
      }
    });
  },
  render: function render() {
    this.tb.addField(this.fromLabel);
    this.tb.addField(this.fromPicker);
    this.tb.addField(this.untilLabel);
    this.tb.addField(this.untilPicker);
  },
  hide: function hide() {
    this.fromLabel.hide();
    this.fromPicker.hide();
    this.untilLabel.hide();
    this.untilPicker.hide();
  },
  show: function show() {
    this.fromLabel.show();
    this.fromPicker.show();
    this.untilLabel.show();
    this.untilPicker.show();
  },
  next: function next() {
    let period = this.getPeriod();
    this.update({
      from: period.until,
      until: period.until.add(Date.MILLI, period.until.getTime() - period.from.getTime()).add(Date.SECOND, period.until.format('Z') - period.from.format('Z'))
    });
  },
  prev: function prev() {
    let period = this.getPeriod();
    this.update({
      from: period.until.add(Date.MILLI, period.from.getTime() - period.until.getTime()).add(Date.SECOND, period.from.format('Z') - period.until.format('Z')),
      until: period.from
    });
  },
  getPeriod: function getPeriod() {
    // let from = this.fromPicker.getValue() || new Date
    return {
      from: this.fromPicker.getValue().clone(),
      until: this.untilPicker.getValue().clone()
    };
  }
});

/***/ }),

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

/* 
 * Tine 2.0
 * 
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2009 Metaways Infosystems GmbH (http://www.metaways.de)
 */
Ext.ns('Tine.Calendar');
/**
 * @class Tine.Calendar.EventDetailsPanel
 * @namespace Tine.Calendar
 * @extends Tine.widgets.grid.DetailsPanel
 * @author Cornelius Weiss <c.weiss@metaways.de>
 */

Tine.Calendar.EventDetailsPanel = Ext.extend(Tine.widgets.grid.DetailsPanel, {
  border: false,
  defaultHeight: 135,

  /**
   * renders attendee names
   * 
   * @param {Array} attendeeData
   * @return {String}
   */
  attendeeRenderer: function attendeeRenderer(attendeeData) {
    if (!attendeeData) {
      return i18n._('No Information');
    }

    var attendeeStore = Tine.Calendar.Model.Attender.getAttendeeStore(attendeeData);
    var a = [];
    attendeeStore.each(function (attender) {
      var name = Tine.Calendar.AttendeeGridPanel.prototype.renderAttenderName.call(Tine.Calendar.AttendeeGridPanel.prototype, attender.get('user_id'), false, attender),
          status = Tine.Tinebase.widgets.keyfield.Renderer.render('Calendar', 'attendeeStatus', attender.get('status')),
          role = Tine.Tinebase.widgets.keyfield.Renderer.render('Calendar', 'attendeeRoles', attender.get('role'));
      a.push(name + ' (' + role + ', ' + status + ')');
    });
    return a.join("<br />");
  },

  /**
   * renders datetime
   * 
   * @param {Date} dt
   * @return {String}
   */
  datetimeRenderer: function datetimeRenderer(dt) {
    return Tine.Calendar.Model.Event.datetimeRenderer(dt);
  },
  transpRenderer: function transpRenderer(transp) {
    return Tine.Tinebase.common.booleanRenderer(transp == 'OPAQUE');
  },
  statusRenderer: function statusRenderer(transp) {
    return Tine.Tinebase.common.booleanRenderer(transp == 'TENTATIVE');
  },
  summaryRenderer: function summaryRenderer(summary) {
    if (!this.record) {
      // no record, no summary
      return '';
    }

    var myAttenderRecord = this.record.getMyAttenderRecord(),
        ret = Tine.Tinebase.common.tagsRenderer(this.record.get('tags')),
        status = null,
        recur = null;
    ret += Ext.util.Format.htmlEncode(this.record.getTitle());

    if (myAttenderRecord) {
      status = Tine.Tinebase.widgets.keyfield.Renderer.render('Calendar', 'attendeeStatus', myAttenderRecord.get('status'));
    }

    if (this.record.isRecurBase() || this.record.isRecurInstance()) {
      recur = '<img class="cal-recurring" unselectable="on" src="' + Ext.BLANK_IMAGE_URL + '">' + this.app.i18n._('recurring event');
    } else if (this.record.isRecurException()) {
      recur = '<img class="cal-recurring exception" unselectable="on" src="' + Ext.BLANK_IMAGE_URL + '">' + this.app.i18n._('recurring event exception');
    }

    if (status || recur) {
      ret += '&nbsp;&nbsp;&nbsp;(&nbsp;';
      if (status) ret += status;
      if (status && recur) ret += '&nbsp;&nbsp;';
      if (recur) ret += recur;
      ret += '&nbsp;)';
    }

    return ret;
  },

  /**
   * inits this component
   */
  initComponent: function initComponent() {
    this.app = Tine.Tinebase.appMgr.get('Calendar');
    Tine.Calendar.EventDetailsPanel.superclass.initComponent.call(this);
  },

  /**
   * default panel w.o. data
   * 
   * @return {Ext.ux.display.DisplayPanel}
   */
  getDefaultInfosPanel: function getDefaultInfosPanel() {
    if (!this.defaultInfosPanel) {
      this.defaultInfosPanel = new Ext.ux.display.DisplayPanel({
        layout: 'fit',
        border: false,
        items: [{
          layout: 'hbox',
          border: false,
          defaults: {
            margins: '0 5 0 0'
          },
          layoutConfig: {
            padding: '5',
            align: 'stretch'
          },
          items: [{
            flex: 1,
            border: false,
            layout: 'ux.display',
            layoutConfig: {
              background: 'solid',
              declaration: this.app.i18n.n_('Event', 'Events', 50)
            }
          }, {
            flex: 1,
            border: false,
            layout: 'ux.display',
            layoutConfig: {
              background: 'border'
            }
          }]
        }]
      });
    }

    return this.defaultInfosPanel;
  },

  /**
   * main event details panel
   * 
   * @return {Ext.ux.display.DisplayPanel}
   */
  getSingleRecordPanel: function getSingleRecordPanel() {
    var me = this;

    if (!this.singleRecordPanel) {
      this.singleRecordPanel = new Tine.widgets.display.RecordDisplayPanel({
        recordClass: Tine.Calendar.Model.Event,
        titleRenderer: this.summaryRenderer.createDelegate(this),
        getBodyItems: function getBodyItems() {
          return [{
            layout: 'hbox',
            flex: 1,
            border: false,
            layoutConfig: {
              padding: '0',
              align: 'stretch'
            },
            defaults: {
              margins: '0 5 0 0'
            },
            items: [{
              flex: 2,
              layout: 'ux.display',
              labelWidth: 60,
              autoScroll: true,
              layoutConfig: {
                background: 'solid'
              },
              items: [{
                xtype: 'ux.displayfield',
                name: 'dtstart',
                fieldLabel: this.app.i18n._('Start Time'),
                renderer: me.datetimeRenderer.createDelegate(me)
              }, {
                xtype: 'ux.displayfield',
                name: 'dtend',
                fieldLabel: this.app.i18n._('End Time'),
                renderer: me.datetimeRenderer.createDelegate(me)
              }, {
                xtype: 'ux.displayfield',
                name: 'transp',
                fieldLabel: this.app.i18n._('Blocking'),
                renderer: me.transpRenderer.createDelegate(me)
              }, {
                xtype: 'ux.displayfield',
                name: 'status',
                fieldLabel: this.app.i18n._('Tentative'),
                renderer: me.statusRenderer.createDelegate(me)
              }, {
                xtype: 'ux.displayfield',
                name: 'location',
                linkify: true,
                fieldLabel: this.app.i18n._('Event Location')
              }, {
                xtype: 'ux.displayfield',
                name: 'organizer',
                fieldLabel: this.app.i18n._('Organizer'),
                renderer: function renderer(organizer) {
                  return organizer && organizer.n_fileas ? organizer.n_fileas : '';
                }
              }]
            }, {
              flex: 3,
              layout: 'ux.display',
              labelAlign: 'top',
              autoScroll: true,
              layoutConfig: {
                background: 'solid'
              },
              items: [{
                xtype: 'ux.displayfield',
                name: 'attendee',
                nl2br: true,
                htmlEncode: false,
                fieldLabel: this.app.i18n._('Attendee'),
                renderer: me.attendeeRenderer
              }]
            }, {
              flex: 3,
              layout: 'ux.display',
              hideLabels: true,
              border: false,
              items: [{
                xtype: 'ux.displayfield',
                name: 'url',
                ctCls: 'x-ux-dislplay-no-label',
                itemCls: 'x-ux-dislplay-no-label',
                fieldLabel: this.app.i18n._('URL'),
                linkify: true
              }, {
                cls: 'x-ux-display-background-border',
                xtype: 'ux.displaytextarea',
                name: 'description'
              }]
            }]
          }];
        }
      });
    }

    return this.singleRecordPanel;
  },

  /**
   * update event details panel
   * 
   * @param {Tine.Tinebase.data.Record} record
   * @param {Mixed} body
   */
  updateDetails: function updateDetails(record, body) {
    //this.cardPanel.layout.setActiveItem(this.cardPanel.items.getKey(this.eventDetailsPanel));
    this.getSingleRecordPanel().loadRecord.defer(100, this.getSingleRecordPanel(), [record]); //return this.supr().updateDetails.apply(this, arguments);
  } //    /**
  //     * show default panel
  //     * 
  //     * @param {Mixed} body
  //     */
  //    showDefault: function(body) {
  //        this.cardPanel.layout.setActiveItem(this.cardPanel.items.getKey(this.defaultPanel));
  //    },
  //    
  //    /**
  //     * show template for multiple rows
  //     * 
  //     * @param {Ext.grid.RowSelectionModel} sm
  //     * @param {Mixed} body
  //     */
  //    showMulti: function(sm, body) {
  //        //if (this.multiTpl) {
  //        //    this.multiTpl.overwrite(body);
  //        //}
  //    }

});

/***/ }),

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

/* 
 * Tine 2.0
 * 
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2007-2013 Metaways Infosystems GmbH (http://www.metaways.de)
 */

/* global Ext, Tine */
Ext.ns('Tine.Calendar');
Tine.Calendar.MainScreenCenterPanel = Ext.extend(Ext.Panel, {
  /**
   * @cfg {String} activeView
   */
  activeView: 'weekSheet',
  startDate: new Date().clearTime(),

  /**
   * $property Object view -> startdate
   */
  startDates: null,

  /**
   * @cfg {String} loadMaskText
   * i18n._('Loading events, please wait...')
   */
  loadMaskText: 'Loading events, please wait...',

  /**
   * @cfg {Number} autoRefreshInterval (seconds)
   */
  autoRefreshInterval: 300,

  /**
   * @cfg {Boolean} initialLoadAfterRender
   */
  initialLoadAfterRender: true,

  /**
   * @property autoRefreshTask
   * @type Ext.util.DelayedTask
   */
  autoRefreshTask: null,

  /**
   * add records from other applications using the split add button
   * - activated by default
   * 
   * @type Bool
   * @property splitAddButton
   */
  splitAddButton: true,

  /**
   * default print mode
   * 
   * @type String {sheet|grid}
   * @property defaultPrintMode
   */
  defaultPrintMode: 'sheet',
  periodRe: /^(day|week|month|year|custom)/i,
  presentationRe: /(sheet|grid|timeline)$/i,
  calendarPanels: {},
  border: false,
  layout: 'border',
  stateful: true,
  stateId: 'cal-mainscreen',
  stateEvents: ['changeview'],
  getState: function getState() {
    return Ext.copyTo({}, this, 'activeView');
  },
  applyState: Ext.emptyFn,
  initComponent: function initComponent() {
    var me = this;
    this.addEvents(
    /**
     * @event changeview
     * fired if an event got clicked
     * @param {Tine.Calendar.MainScreenCenterPanel} mspanel
     * @param {String} view
     */
    'changeview');
    this.recordClass = Tine.Calendar.Model.Event;
    this.app = Tine.Tinebase.appMgr.get('Calendar'); // init some translations

    this.i18nRecordName = this.app.i18n.n_hidden(this.recordClass.getMeta('recordName'), this.recordClass.getMeta('recordsName'), 1);
    this.i18nRecordsName = this.app.i18n._hidden(this.recordClass.getMeta('recordsName'));
    this.i18nContainerName = this.app.i18n.n_hidden(this.recordClass.getMeta('containerName'), this.recordClass.getMeta('containersName'), 1);
    this.i18nContainersName = this.app.i18n._hidden(this.recordClass.getMeta('containersName'));
    this.loadMaskText = this.app.i18n._hidden(this.loadMaskText);
    var state = Ext.state.Manager.get(this.stateId, {});
    Ext.apply(this, state);
    this.defaultFilters = [{
      field: 'attender',
      operator: 'in',
      value: [Ext.apply(Tine.Calendar.Model.Attender.getDefaultData(), {
        user_id: Tine.Tinebase.registry.get('currentAccount')
      })]
    }, {
      field: 'attender_status',
      operator: 'notin',
      value: ['DECLINED']
    }];
    this.filterToolbar = this.getFilterToolbar({
      onFilterChange: this.refresh.createDelegate(this, [false]),
      getAllFilterData: this.getAllFilterData.createDelegate(this)
    });
    this.filterToolbar.getQuickFilterPlugin().criteriaIgnores.push({
      field: 'period'
    }, {
      field: 'grants'
    });
    this.startDates = [];
    this.initActions();
    this.initLayout(); // init autoRefresh

    this.autoRefreshTask = new Ext.util.DelayedTask(this.refresh, this, [{
      refresh: true,
      autoRefresh: true
    }]);
    Tine.Calendar.MainScreenCenterPanel.superclass.initComponent.call(this);
  },
  initActions: function initActions() {
    this.action_editInNewWindow = new Ext.Action({
      requiredGrant: 'readGrant',
      text: this.i18nEditActionText ? this.app.i18n._hidden(this.i18nEditActionText) : String.format(i18n._hidden('Edit {0}'), this.i18nRecordName),
      disabled: true,
      handler: this.onEditInNewWindow.createDelegate(this, ["edit"], 0),
      iconCls: 'action_edit'
    });
    this.action_addInNewWindow = new Ext.Action({
      requiredGrant: 'addGrant',
      text: this.i18nAddActionText ? this.app.i18n._hidden(this.i18nAddActionText) : String.format(i18n._hidden('Add {0}'), this.i18nRecordName),
      handler: this.onEditInNewWindow.createDelegate(this, ["add"], 0),
      iconCls: 'action_add'
    });
    this.action_cut = new Ext.Action({
      requiredGrant: 'deleteGrant',
      text: this.app.i18n._('Cut event'),
      handler: this.onCutEvent.createDelegate(this),
      iconCls: 'action_cut'
    });
    this.action_copy_to = new Ext.Action({
      requiredGrant: 'deleteGrant',
      text: this.app.i18n._('Copy Event to clipboard'),
      handler: this.onCopyToEvent.createDelegate(this),
      iconCls: 'action_copy'
    });
    this.action_cancelPasting = new Ext.Action({
      requiredGrant: 'deleteGrant',
      text: this.app.i18n._('Stop cut / copy & paste'),
      handler: this.onCutCancelEvent.createDelegate(this),
      iconCls: 'action_cut_break'
    }); // note: unprecise plural form here, but this is hard to change

    this.action_deleteRecord = new Ext.Action({
      requiredGrant: 'deleteGrant',
      allowMultiple: true,
      singularText: this.i18nDeleteActionText ? i18nDeleteActionText[0] : String.format(i18n.n_hidden('Delete {0}', 'Delete {0}', 1), this.i18nRecordName),
      pluralText: this.i18nDeleteActionText ? i18nDeleteActionText[1] : String.format(i18n.n_hidden('Delete {0}', 'Delete {0}', 1), this.i18nRecordsName),
      translationObject: this.i18nDeleteActionText ? this.app.i18n : i18n,
      text: this.i18nDeleteActionText ? this.i18nDeleteActionText[0] : String.format(i18n.n_hidden('Delete {0}', 'Delete {0}', 1), this.i18nRecordName),
      handler: this.onDeleteRecords,
      disabled: true,
      iconCls: 'action_delete',
      scope: this
    });
    this.actions_print = new Ext.Action({
      requiredGrant: 'readGrant',
      text: this.app.i18n._('Print Page'),
      handler: this.onPrint.createDelegate(this, []),
      iconCls: 'action_print',
      scope: this,
      listeners: {
        arrowclick: this.onPrintMenuClick.createDelegate(this)
      },
      menu: {
        items: [{
          text: this.app.i18n._('Loose-Leaf'),
          iconCls: 'cal-print-loose-leaf',
          handler: this.onPrint.createDelegate(this, ['grid'])
        }, {
          text: this.app.i18n._('Sheet'),
          iconCls: 'cal-week-view',
          handler: this.onPrint.createDelegate(this, ['sheet']),
          disabled: Ext.isNewIE
        }]
      }
    });
    this.showSheetView = new Ext.Button({
      pressed: this.isActiveView('Sheet'),
      scale: 'medium',
      minWidth: 60,
      rowspan: 2,
      iconAlign: 'top',
      requiredGrant: 'readGrant',
      text: this.app.i18n._('Sheet'),
      handler: this.changeView.createDelegate(this, ["sheet"]),
      iconCls: 'cal-sheet-view-type',
      xtype: 'tbbtnlockedtoggle',
      toggleGroup: 'Calendar_Toolbar_tgViewTypes',
      scope: this
    });
    this.showGridView = new Ext.Button({
      pressed: this.isActiveView('Grid'),
      scale: 'medium',
      minWidth: 60,
      rowspan: 2,
      iconAlign: 'top',
      requiredGrant: 'readGrant',
      text: this.app.i18n._('Grid'),
      handler: this.changeView.createDelegate(this, ["grid"]),
      iconCls: 'cal-grid-view-type',
      xtype: 'tbbtnlockedtoggle',
      toggleGroup: 'Calendar_Toolbar_tgViewTypes',
      scope: this
    });
    this.showTimelineView = new Ext.Button({
      pressed: this.isActiveView('Timeline'),
      scale: 'medium',
      minWidth: 60,
      rowspan: 2,
      iconAlign: 'top',
      requiredGrant: 'readGrant',
      text: this.app.i18n._('Timeline'),
      handler: this.changeView.createDelegate(this, ["timeline"]),
      iconCls: 'cal-timeline-view-type',
      xtype: 'tbbtnlockedtoggle',
      toggleGroup: 'Calendar_Toolbar_tgViewTypes',
      scope: this
    });
    this.showDayView = new Ext.Toolbar.Button({
      pressed: this.isActiveView('Day'),
      text: this.app.i18n._('Day'),
      iconCls: 'cal-day-view',
      xtype: 'tbbtnlockedtoggle',
      handler: this.changeView.createDelegate(this, ["day"]),
      enableToggle: true,
      toggleGroup: 'Calendar_Toolbar_tgViews'
    });
    this.showWeekView = new Tine.Calendar.PagingToolbar.WeekPeriodPicker.Button({
      pressed: this.isActiveView('Week'),
      text: this.app.i18n._('Week'),
      iconCls: 'cal-week-view',
      xtype: 'tbbtnlockedtoggle',
      handler: this.changeView.createDelegate(this, ["week"]),
      enableToggle: true,
      toggleGroup: 'Calendar_Toolbar_tgViews',
      listeners: {
        change: this.recreatePanel.createDelegate(this, ['weekSheet'])
      }
    });
    this.showMonthView = new Ext.Toolbar.Button({
      pressed: this.isActiveView('Month'),
      text: this.app.i18n._('Month'),
      iconCls: 'cal-month-view',
      xtype: 'tbbtnlockedtoggle',
      handler: this.changeView.createDelegate(this, ["month"]),
      enableToggle: true,
      toggleGroup: 'Calendar_Toolbar_tgViews'
    });
    this.showYearView = new Ext.Toolbar.Button({
      pressed: String(this.activeView).match(/^year/i),
      hidden: !this.app.featureEnabled('featureYearView'),
      text: this.app.i18n._('Year'),
      iconCls: 'cal-year-view',
      xtype: 'tbbtnlockedtoggle',
      handler: this.changeView.createDelegate(this, ["year"]),
      enableToggle: true,
      toggleGroup: 'Calendar_Toolbar_tgViews',
      checkState: (mainScreen, btn) => {
        _.defer(() => {
          btn.setVisible(this.app.featureEnabled('featureYearView'));
        });
      }
    });
    this.showCustomView = new Ext.Toolbar.Button({
      pressed: String(this.activeView).match(/^custom/i),
      tooltip: this.app.i18n._('Custom Selection'),
      text: '&nbsp;',
      iconCls: 'cal-customperiod-view',
      xtype: 'tbbtnlockedtoggle',
      handler: this.changeView.createDelegate(this, ["custom"]),
      enableToggle: true,
      toggleGroup: 'Calendar_Toolbar_tgViews',
      hidden: !this.activeView.match(/grid/i),
      checkState: (mainScreen, btn) => {
        let isGridView = mainScreen.activeView.match(/grid/i);
        btn.setVisible(isGridView);
      }
    });
    this.toggleFullScreen = new Ext.Toolbar.Button({
      text: '\u2197',
      scope: this,
      handler: function handler() {
        if (this.ownerCt.ref == 'tineViewportMaincardpanel') {
          Tine.Tinebase.viewport.tineViewportMaincardpanel.remove(this, false);
          Tine.Tinebase.viewport.tineViewportMaincardpanel.layout.setActiveItem(Tine.Tinebase.viewport.tineViewportMaincardpanel.layout.lastActiveItem);
          this.originalOwner.add(this);
          this.originalOwner.layout.setActiveItem(this);
          this.toggleFullScreen.setText('\u2197');
          this.southPanel.expand();
        } else {
          this.originalOwner = this.ownerCt;
          this.originalOwner.remove(this, false);
          Tine.Tinebase.viewport.tineViewportMaincardpanel.layout.lastActiveItem = Tine.Tinebase.viewport.tineViewportMaincardpanel.layout.activeItem;
          Tine.Tinebase.viewport.tineViewportMaincardpanel.add(this);
          Tine.Tinebase.viewport.tineViewportMaincardpanel.layout.setActiveItem(this);
          this.toggleFullScreen.setText('\u2199');
          this.southPanel.collapse();
        }
      }
    });
    this.action_import = new Ext.Action({
      requiredGrant: 'addGrant',
      text: this.app.i18n._('Import Events'),
      disabled: false,
      handler: this.onImport,
      minWidth: 60,
      iconCls: 'action_import',
      scope: this,
      allowMultiple: true
    });
    this.action_export = Tine.widgets.exportAction.getExportButton(Tine.Calendar.Model.Event, {
      getExportOptions: function () {
        return {
          filter: this.getAllFilterData({
            noPeriodFilter: false
          })
        };
      }.createDelegate(this)
    }, Tine.widgets.exportAction.SCOPE_MULTI); // FIXME: how can this be null? is it ok??

    if (this.action_export) {
      this.action_export.setDisabled(false);
      this.action_export.setText(this.action_export.initialConfig.pluralText);
    }

    this.changeViewActions = [this.showDayView, this.showWeekView, this.showMonthView, this.showYearView, this.showCustomView];
    this.changeViewActions.push(this.toggleFullScreen);
    this.recordActions = [this.action_editInNewWindow, this.action_deleteRecord];
    this.actionUpdater = new Tine.widgets.ActionUpdater({
      actions: this.recordActions
    });
  },

  /**
   * get current view type (Grid/Day/Week/...)
   *
   * @param {String} view
   * @returns {Boolean}
   */
  isActiveView: function isActiveView(view) {
    var re = new RegExp(String(view).toLowerCase(), 'i');
    return String(this.activeView).match(re);
  },

  /**
   * returns the paste action
   * 
   * @param {Date} datetime
   * @param {Tine.Calendar.Model.Event} event
   */
  getPasteAction: function getPasteAction(datetime, event) {
    var shortSummary = Ext.util.Format.ellipsis(event.get('summary'), 15);
    return new Ext.Action({
      requiredGrant: 'addGrant',
      text: String.format(this.app.i18n._('Paste event "{0}"'), shortSummary),
      handler: this.onPasteEvent.createDelegate(this, [datetime]),
      iconCls: 'action_paste'
    });
  },
  getActionToolbar: Tine.widgets.grid.GridPanel.prototype.getActionToolbar,
  onActionToolbarResize: Tine.widgets.grid.GridPanel.prototype.onActionToolbarResize,
  getActionToolbarItems: function getActionToolbarItems() {
    var items = [this.action_import];

    if (this.action_export) {
      items = items.concat(this.action_export);
    }

    return [{
      xtype: 'buttongroup',
      columns: 1,
      rows: 2,
      frame: false,
      items: items
    }, {
      xtype: 'tbseparator'
    }, {
      xtype: 'buttongroup',
      frame: false,
      plugins: [{
        ptype: 'ux.itemregistry',
        key: 'Calendar-MainScreenPanel-ViewBtnGrp'
      }],
      items: [this.showSheetView, this.showTimelineView, this.showGridView]
    }];
  },

  /**
   * @private
   * 
   * NOTE: Order of items matters! Ext.Layout.Border.SplitRegion.layout() does not
   *       fence the rendering correctly, as such it's impotant, so have the ftb
   *       defined after all other layout items
   */
  initLayout: function initLayout() {
    this.items = [{
      region: 'center',
      layout: 'card',
      activeItem: 0,
      border: false,
      items: [this.getCalendarPanel(this.activeView)]
    }]; // add detail panel

    if (this.detailsPanel) {
      this.items.push({
        region: 'south',
        ref: 'southPanel',
        border: false,
        collapsible: true,
        collapseMode: 'mini',
        header: false,
        split: true,
        layout: 'fit',
        height: this.detailsPanel.defaultHeight ? this.detailsPanel.defaultHeight : 125,
        items: this.detailsPanel
      });
    } // add filter toolbar


    if (this.filterToolbar) {
      this.items.push({
        region: 'north',
        border: false,
        items: this.filterToolbar,
        listeners: {
          scope: this,
          afterlayout: function afterlayout(ct) {
            ct.suspendEvents();
            ct.setHeight(this.filterToolbar.getHeight());
            ct.ownerCt.layout.layout();
            ct.resumeEvents();
          }
        }
      });
    }
  },

  /**
   * import events
   * 
   * @param {Button} btn 
   */
  onImport: function onImport(btn) {
    var popupWindow = Tine.Calendar.ImportDialog.openWindow({
      appName: 'Calendar',
      modelName: 'Event',
      defaultImportContainer: this.app.getMainScreen().getWestPanel().getContainerTreePanel().getDefaultContainer('defaultContainer'),
      ignoreConflicts: true,
      doTryRun: false,
      // update grid after import
      listeners: {
        scope: this,
        'finish': function finish() {
          this.refresh();
        }
      }
    });
  },

  /**
   * @private
   */
  onRender: function onRender(ct, position) {
    Tine.Calendar.MainScreenCenterPanel.superclass.onRender.apply(this, arguments);
    this.loadMask = new Ext.LoadMask(this.body, {
      msg: this.loadMaskText,
      msgCls: 'x-mask-loading cal-ms-panel-mask'
    });
    var defaultFavorite = Tine.widgets.persistentfilter.model.PersistentFilter.getDefaultFavorite(this.app.appName, this.recordClass.prototype.modelName);

    if (this.initialLoadAfterRender) {
      if (defaultFavorite) {
        this.selectFavorite(defaultFavorite);
      } else {
        this.refresh();
      }
    }
  },
  selectFavorite: function selectFavorite(favorite) {
    var favorite = favorite || Tine.widgets.persistentfilter.model.PersistentFilter.getDefaultFavorite(this.app.appName, this.recordClass.prototype.modelName),
        favoritesPanel = this.app.getMainScreen().getWestPanel().getFavoritesPanel();
    favoritesPanel.selectFilter(favorite);
  },
  getViewParts: function getViewParts(view) {
    view = String(view);
    var activeView = String(this.activeView),
        periodMatch = view.match(this.periodRe),
        period = Ext.isArray(periodMatch) ? periodMatch[0] : null,
        activePeriodMatch = activeView.match(this.periodRe),
        activePeriod = Ext.isArray(activePeriodMatch) ? activePeriodMatch[0] : 'week',
        presentationMatch = view.match(this.presentationRe),
        presentation = Ext.isArray(presentationMatch) ? presentationMatch[0] : null,
        activePresentationMatch = activeView.match(this.presentationRe),
        activePresentation = Ext.isArray(activePresentationMatch) ? activePresentationMatch[0] : 'sheet';
    return {
      period: period ? period : activePeriod,
      presentation: presentation ? presentation : activePresentation,
      toString: function toString() {
        return this.period + Ext.util.Format.capitalize(this.presentation);
      }
    };
  },
  changeView: function changeView(view, startDate) {
    // autocomplete view
    var viewParts = this.getViewParts(view);

    if (viewParts.period === 'custom' && viewParts.presentation !== 'Grid') {
      // transition customGrid -> sheetView
      let range = Ext.ux.form.PeriodPicker.getRange(this.getCalendarPanel(this.activeView).getView().getPeriod());
      if (['month', 'week', 'day'].indexOf(range) < 0) range = 'week';
      viewParts.period = range;
      ;
    }

    view = viewParts.toString();
    Tine.log.debug('Tine.Calendar.MainScreenCenterPanel::changeView(' + view + ',' + startDate + ')'); // save current startDate

    this.startDates[this.activeView] = this.startDate.clone();

    if (startDate && Ext.isDate(startDate)) {
      this.startDate = startDate.clone();
    } else {
      // see if a recent startDate of that view fits
      var lastStartDate = this.startDates[view],
          currentPeriod = this.getCalendarPanel(this.activeView).getView().getPeriod();

      if (Ext.isDate(lastStartDate) && lastStartDate.between(currentPeriod.from, currentPeriod.until)) {
        this.startDate = this.startDates[view].clone();
      }
    }

    var panel = this.getCalendarPanel(view);
    var cardPanel = this.items.first();

    if (panel.rendered) {
      cardPanel.layout.setActiveItem(panel.id);
    } else {
      cardPanel.add(panel);
      cardPanel.layout.setActiveItem(panel.id);
      cardPanel.doLayout();
    }

    this.activeView = view;
    this.movePeriodBtns(panel.tbar);
    this['show' + Ext.util.Format.capitalize(viewParts.period) + 'View'].toggle(true);
    this['show' + Ext.util.Format.capitalize(viewParts.presentation) + 'View'].toggle(true); // update actions

    this.updateEventActions(); // update data
    // NOTE: monthView periods differ for views.
    //  - sheetView begins with end of last month and ends with beginning of next month
    //  - timelineView starts with the first and ends with the last
    //    BUT startDate sticks to first of month!
    // monthSheet is a bitch!

    panel.getView().updatePeriod({
      from: this.startDate
    }, currentPeriod);
    panel.getStore().load({});
    this.fireEvent('changeview', this, view);
  },
  movePeriodBtns: function movePeriodBtns(tgt) {
    // NOTE: we need to dereference btn's in source view, oterwise btn's get destroyed on cmp destroy
    var rightRow = Ext.get(Ext.DomQuery.selectNode('tr[class=x-toolbar-right-row]', tgt.dom));

    for (var i = this.changeViewActions.length - 1; i >= 0; i--) {
      if (_.isFunction(this.changeViewActions[i].checkState)) {
        this.changeViewActions[i].checkState(this, this.changeViewActions[i]);
      }

      rightRow.insertFirst(this.changeViewActions[i].getEl().parent().dom);
    }
  },

  /**
   * returns all filter data for current view
   */
  getAllFilterData: function getAllFilterData(options) {
    var store = this.getCalendarPanel(this.activeView).getStore();
    options = Ext.apply({
      refresh: true,
      // ommit loadMask
      noPeriodFilter: true
    }, options || {});
    this.onStoreBeforeload(store, options);
    return options.params.filter;
  },
  getCustomfieldFilters: Tine.widgets.grid.GridPanel.prototype.getCustomfieldFilters,
  getFilterToolbar: Tine.widgets.grid.GridPanel.prototype.getFilterToolbar,

  /**
   * returns store of currently active view
   */
  getStore: function getStore() {
    return this.getCalendarPanel(this.activeView).getStore();
  },

  /**
   * onContextMenu
   * 
   * @param {Event} e
   */
  onContextMenu: function onContextMenu(e) {
    e.stopEvent();
    var view = this.getCalendarPanel(this.activeView).getView();
    var event = view.getTargetEvent(e);
    var datetime = view.getTargetDateTime(e);

    if (event && event.id.match(/new-ext-gen/)) {
      // new event, no ctx menu possible atm
      // @see 0008948: deactivate context menu on new events
      return;
    }

    var addAction, responseAction, copyAction, eventStatusAction;

    if (datetime || event) {
      var dtStart = datetime || event.get('dtstart').clone();

      if (dtStart.format('H:i') === '00:00') {
        dtStart = dtStart.add(Date.HOUR, 9);
      }

      addAction = {
        text: this.i18nAddActionText ? this.app.i18n._hidden(this.i18nAddActionText) : String.format(i18n._hidden('Add {0}'), this.i18nRecordName),
        handler: this.onEditInNewWindow.createDelegate(this, ["add", null, null, {
          dtStart: dtStart,
          is_all_day_event: datetime && datetime.is_all_day_event
        }]),
        iconCls: 'action_add'
      }; // assemble event actions

      if (event) {
        responseAction = this.getResponseAction(event);
        copyAction = this.getCopyAction(event);
        eventStatusAction = this.getEventStatusAction(event);
      }
    } else {
      addAction = this.action_addInNewWindow;
    }

    if (event) {
      view.getSelectionModel().select(event, e, e.ctrlKey);
    } else {
      view.getSelectionModel().clearSelections();
    }

    var menuitems = this.recordActions.concat(addAction, copyAction || [], eventStatusAction || [], '-', responseAction || []);

    if (event && event.get('poll_id') && event.get('editGrant')) {
      __webpack_require__(646);

      menuitems = menuitems.concat(['-', {
        text: this.app.i18n._('Set as definite event'),
        iconCls: 'cal-polls-set-definite-action',
        scope: this,
        handler: function handler() {
          var me = this,
              ns = Tine.Calendar.eventActions.setDefiniteEventAction;
          ns.confirm().then(function () {
            me.loadMask.show();
            return Tine.Calendar.setDefinitePollEvent(event.data);
          }).then(function () {
            me.getStore().load({
              refresh: true
            });
          }).catch(function (error) {
            me.loadMask.hide();
          });
        }
      }]);
    }

    if (event) {
      this.action_copy_to.setDisabled(event.isRecurInstance() || event.isRecurException() || event.isRecurBase());
      menuitems = menuitems.concat(['-', this.action_cut, this.action_copy_to, '-']);
    } else if (Tine.Tinebase.data.Clipboard.has('Calendar', 'Event')) {
      menuitems = menuitems.concat(['-', this.getPasteAction(datetime, Tine.Tinebase.data.Clipboard.pull('Calendar', 'Event', true)), this.action_cancelPasting, '-']);
    }

    var ctxMenu = new Ext.menu.Menu({
      plugins: [{
        ptype: 'ux.itemregistry',
        key: 'Calendar-MainScreenPanel-ContextMenu',
        config: {
          event: event,
          datetime: datetime
        }
      }, // to allow gridpanel hooks (like email compose)
      {
        ptype: 'ux.itemregistry',
        key: 'Calendar-Event-GridPanel-ContextMenu'
      }, {
        ptype: 'ux.itemregistry',
        key: 'Tinebase-MainContextMenu'
      }],
      items: menuitems
    }); // run action updater

    ctxMenu.showAt(e.getXY());
  },

  /**
   * get response action
   * 
   * @param {Tine.Calendar.Model.Event} event
   * @return {Object}
   */
  getResponseAction: function getResponseAction(event) {
    var statusStore = Tine.Tinebase.widgets.keyfield.StoreMgr.get('Calendar', 'attendeeStatus'),
        myAttenderRecord = event.getMyAttenderRecord(),
        myAttenderStatus = myAttenderRecord ? myAttenderRecord.get('status') : null,
        myAttenderStatusRecord = statusStore.getById(myAttenderStatus),
        responseAction = null;

    if (myAttenderRecord) {
      responseAction = {
        text: this.app.i18n._('Set my response'),
        icon: myAttenderStatusRecord ? myAttenderStatusRecord.get('icon') : false,
        menu: []
      };
      statusStore.each(function (status) {
        var isCurrent = myAttenderRecord.get('status') === status.id; // NOTE: we can't use checked items here as we use icons already

        responseAction.menu.push({
          text: status.get('i18nValue'),
          handler: this.setResponseStatus.createDelegate(this, [event, status.id]),
          icon: status.get('icon'),
          disabled: myAttenderRecord.get('status') === status.id
        });
      }, this);
    }

    return responseAction;
  },

  /**
   * get copy action
   * 
   * @param {Tine.Calendar.Model.Event} event
   * @return {Object}
   */
  getCopyAction: function getCopyAction(event) {
    var copyAction = {
      text: String.format(this.app.i18n._('Copy {0}'), this.i18nRecordName),
      handler: this.onEditInNewWindow.createDelegate(this, ["copy", event]),
      iconCls: 'action_editcopy',
      // TODO allow to copy recurring events / exceptions
      disabled: event.isRecurInstance() || event.isRecurException() || event.isRecurBase()
    };
    return copyAction;
  },

  /**
   * get eventStatusAction action
   *
   * @param {Tine.Calendar.Model.Event} event
   * @return {Object}
   */
  getEventStatusAction: function getEventStatusAction(event) {
    const statusField = new Tine.Tinebase.widgets.keyfield.ComboBox({
      app: 'Calendar',
      keyFieldName: 'eventStatus'
    });
    const statusRecord = statusField.store.getById(event.get('status'));
    const constraintsProvider = Tine.Calendar.EventEditDialog.getCheckStateProviders('status');
    const editDialogMock = {
      getForm() {
        return {
          findField() {
            return statusField;
          }

        };
      }

    };

    _.each(constraintsProvider, cp => {
      cp(editDialogMock, event);
    });

    let eventStatusAction = {
      text: this.app.i18n._('Set event status'),
      icon: statusRecord ? statusRecord.get('icon') : false,
      menu: []
    };
    statusField.store.each(function (status) {
      // NOTE: we can't use checked items here as we use icons already
      eventStatusAction.menu.push({
        text: status.get('i18nValue'),
        handler: this.setEventStatus.createDelegate(this, [event, status.id]),
        icon: status.get('icon'),
        disabled: status.id === event.get('status')
      });
    }, this);
    return eventStatusAction;
  },
  checkPastEvent: function checkPastEvent(event, checkBusyConflicts, actionType, oldEvent) {
    var start = event.get('dtstart').getTime();
    var morning = new Date().clearTime().getTime();

    switch (actionType) {
      case 'update':
        var title = this.app.i18n._('Updating event in the past'),
            optionYes = this.app.i18n._('Update this event'),
            optionNo = this.app.i18n._('Do not update this event');

        break;

      case 'add':
      default:
        var title = this.app.i18n._('Creating event in the past'),
            optionYes = this.app.i18n._('Create this event'),
            optionNo = this.app.i18n._('Do not create this event');

    }

    if (start < morning) {
      Tine.widgets.dialog.MultiOptionsDialog.openWindow({
        title: title,
        height: 170,
        scope: this,
        options: [{
          text: optionYes,
          name: 'yes'
        }, {
          text: optionNo,
          name: 'no'
        }],
        handler: function handler(option) {
          try {
            switch (option) {
              case 'yes':
                if (actionType == 'update') this.onUpdateEvent(event, true, oldEvent);else this.onAddEvent(event, checkBusyConflicts, true);
                break;

              case 'no':
              default:
                try {
                  var panel = this.getCalendarPanel(this.activeView);

                  if (panel) {
                    var store = this.getStore(),
                        view = panel.getView();
                  }
                } catch (e) {
                  var panel = null,
                      store = null,
                      view = null;
                }

                if (actionType == 'add') {
                  if (store) store.remove(event);
                } else {
                  if (view && view.rendered) {
                    this.loadMask.show();
                    store.reload(); //                                        TODO: restore original event so no reload is needed
                    //                                        var updatedEvent = event;
                    //                                        updatedEvent.dirty = false;
                    //                                        updatedEvent.editing = false;
                    //                                        updatedEvent.modified = null;
                    //                                        
                    //                                        store.replaceRecord(event, updatedEvent);
                    //                                        view.getSelectionModel().select(event);
                  }

                  this.setLoading(false);
                }

            }
          } catch (e) {
            Tine.log.error('Tine.Calendar.MainScreenCenterPanel::checkPastEvent::handler');
            Tine.log.error(e);
          }
        }
      });
    } else {
      if (actionType == 'update') this.onUpdateEvent(event, true, oldEvent);else this.onAddEvent(event, checkBusyConflicts, true);
    }
  },
  onAddEvent: function onAddEvent(event, checkBusyConflicts, pastChecked) {
    if (!pastChecked) {
      this.checkPastEvent(event, checkBusyConflicts, 'add');
      return;
    }

    this.setLoading(true); // remove temporary id

    if (event.get('id').match(/new/)) {
      event.set('id', '');
    }

    if (event.isRecurBase()) {
      if (this.loadMask) {
        this.loadMask.show();
      }
    }

    var panel = this.getCalendarPanel(this.activeView),
        store = this.getStore();
    Tine.Calendar.backend.saveRecord(event, {
      scope: this,
      success: function success(createdEvent) {
        this.congruenceFilterCheck(event, createdEvent);
      },
      failure: this.onProxyFail.createDelegate(this, [event], true)
    }, {
      checkBusyConflicts: checkBusyConflicts === false ? 0 : 1
    });
  },
  onUpdateEvent: function onUpdateEvent(event, pastChecked, oldEvent) {
    this.setLoading(true);

    if (!pastChecked) {
      this.checkPastEvent(event, null, 'update', oldEvent);
      return;
    }

    if (event.isRecurBase() && this.loadMask) {
      this.loadMask.show();
    }

    if (event.id && (event.isRecurInstance() || event.isRecurException() || event.isRecurBase() && !event.get('rrule').newrule)) {
      var options = [];
      options.push({
        text: this.app.i18n._('Update this event only'),
        name: 'this'
      }); // if

      options.push({
        text: this.app.i18n._('Update this and all future events'),
        name: event.isRecurBase() && !event.get('rrule').newrule ? 'series' : 'future'
      });
      options.push({
        text: this.app.i18n._('Update whole series'),
        name: 'series'
      }); // endif

      options.push({
        text: this.app.i18n._('Update nothing'),
        name: 'cancel'
      });
      Tine.widgets.dialog.MultiOptionsDialog.openWindow({
        title: this.app.i18n._('Update Event'),
        height: 170,
        scope: this,
        options: options,
        handler: function handler(option) {
          var store = this.getStore();

          switch (option) {
            case 'series':
              if (this.loadMask) {
                this.loadMask.show();
              }

              var options = {
                scope: this,
                success: function success(updatedEvent) {
                  this.congruenceFilterCheck(event, updatedEvent);
                }
              };
              options.failure = this.onProxyFail.createDelegate(this, [event, Tine.Calendar.backend.updateRecurSeries.createDelegate(Tine.Calendar.backend, [event, false, options])], true);

              if (event.isRecurException()) {
                Tine.Calendar.backend.saveRecord(event, options, {
                  range: 'ALL',
                  checkBusyConflicts: true
                });
              } else {
                Tine.Calendar.backend.updateRecurSeries(event, true, options);
              }

              break;

            case 'this':
            case 'future':
              var options = {
                scope: this,
                success: function success(updatedEvent) {
                  this.congruenceFilterCheck(event, updatedEvent);
                },
                failure: this.onProxyFail.createDelegate(this, [event], true)
              };

              if (event.isRecurException()) {
                var range = option === 'this' ? 'THIS' : 'THISANDFUTURE';
                options.failure = this.onProxyFail.createDelegate(this, [event, Tine.Calendar.backend.saveRecord.createDelegate(Tine.Calendar.backend, [event, options, {
                  range: range,
                  checkBusyConflicts: false
                }])], true);
                Tine.Calendar.backend.saveRecord(event, options, {
                  range: range,
                  checkBusyConflicts: true
                });
              } else {
                options.failure = this.onProxyFail.createDelegate(this, [event, Tine.Calendar.backend.createRecurException.createDelegate(Tine.Calendar.backend, [event, false, option == 'future', false, options])], true);
                Tine.Calendar.backend.createRecurException(event, false, option === 'future', true, options);
              }

              break;

            default:
              if (this.loadMask) {
                //no loadMask called from another app
                this.loadMask.show();
                store.load({
                  refresh: true
                });
              }

              break;
          }
        }
      });
    } else {
      this.onUpdateEventAction(event);
    }
  },
  onUpdateEventAction: function onUpdateEventAction(event) {
    var panel = this.getCalendarPanel(this.activeView),
        store = this.getStore(),
        view = panel.getView();
    Tine.Calendar.backend.saveRecord(event, {
      scope: this,
      success: function success(updatedEvent) {
        this.congruenceFilterCheck(event, updatedEvent);
      },
      failure: this.onProxyFail.createDelegate(this, [event], true)
    }, {
      checkBusyConflicts: 1
    });
  },

  /**
   * checks, if the last filter still matches after update
   * 
   * @param {Tine.Calendar.Model.Event} event
   * @param {Tine.Calendar.Model.Event} updatedEvent
   */
  congruenceFilterCheck: function congruenceFilterCheck(event, updatedEvent) {
    var filterData = this.getAllFilterData(),
        panel = this.getCalendarPanel(this.activeView),
        store = this.getStore(),
        view = panel.getView(),
        isSelected = panel.getSelectionModel().isSelected(event),
        me = this,
        promise = Promise.resolve();

    if (updatedEvent.ui) {
      updatedEvent.ui.markDirty();
    }

    store.replaceRecord(event, updatedEvent);

    if (isSelected) {
      panel.getSelectionModel().select(updatedEvent);
    }

    if (!event.inPeriod(view.getPeriod())) {
      view.updatePeriod({
        from: event.get('dtstart')
      });
      promise = store.promiseLoad({});
    } else if (event.isRecurBase() || updatedEvent.isRecurBase() || updatedEvent.isRecurException() // NOTE: we also need to refresh for 'this' as otherwise baseevent is not refreshed -> concurrency failures
    || event.hasPoll() || updatedEvent.hasPoll()) {
      promise = store.promiseLoad({
        refresh: true
      });
    }

    promise.then(function () {
      me.setLoading(true);
      filterData[0].filters[0].filters.push({
        field: 'id',
        operator: 'in',
        value: [updatedEvent.get('id')]
      });
      filterData.push({
        field: 'period',
        operator: 'within',
        value: me.getCalendarPanel(me.activeView).getView().getPeriod()
      });
      Tine.Calendar.searchEvents(filterData, {},
      /* fixed calendars */
      true, function (r) {
        if (updatedEvent.ui) {
          updatedEvent.ui.clearDirty();
        }

        if (r.totalcount == 0) {
          var renderedEvent = me.getStore().getById(updatedEvent.id);

          if (!renderedEvent) {
            me.getStore().add(updatedEvent);
            renderedEvent = updatedEvent;
          }

          if (renderedEvent.ui) {
            renderedEvent.ui.markOutOfFilter();
            renderedEvent.ui.clearDirty();
          }
        }

        me.setLoading(false);
      }, me);
    });
  },
  onDeleteRecords: function onDeleteRecords() {
    var panel = this.getCalendarPanel(this.activeView);
    var selection = panel.getSelectionModel().getSelectedEvents();
    var containsRecurBase = false,
        containsRecurInstance = false,
        containsRecurException = false;
    Ext.each(selection, function (event) {
      if (event.ui) event.ui.markDirty();

      if (event.isRecurInstance()) {
        containsRecurInstance = true;
      }

      if (event.isRecurBase()) {
        containsRecurBase = true;
      }

      if (event.isRecurException()) {
        containsRecurException = true;
      }
    });

    if (selection.length > 1 && (containsRecurBase || containsRecurInstance)) {
      Ext.Msg.show({
        title: this.app.i18n._('Please Change Selection'),
        msg: this.app.i18n._('Your selection contains recurring events. Recuring events must be deleted seperatly!'),
        icon: Ext.MessageBox.INFO,
        buttons: Ext.Msg.OK,
        scope: this,
        fn: function fn() {
          this.onDeleteRecordsConfirmFail(panel, selection);
        }
      });
      return;
    }

    if (selection.length === 1 && (containsRecurBase || containsRecurInstance || containsRecurException)) {
      this.deleteMethodWin = Tine.widgets.dialog.MultiOptionsDialog.openWindow({
        title: this.app.i18n._('Delete Event'),
        scope: this,
        height: 170,
        options: [{
          text: this.app.i18n._('Delete this event only'),
          name: 'this'
        }, {
          text: this.app.i18n._('Delete this and all future events'),
          name: containsRecurBase ? 'all' : 'future'
        }, {
          text: this.app.i18n._('Delete whole series'),
          name: 'all'
        }, {
          text: this.app.i18n._('Delete nothing'),
          name: 'nothing'
        }],
        handler: function handler(option) {
          try {
            switch (option) {
              case 'all':
              case 'this':
              case 'future':
                panel.getTopToolbar().beforeLoad();

                if (option !== 'this') {
                  this.loadMask.show();
                }

                var options = {
                  scope: this,
                  success: function success() {
                    if (option === 'this') {
                      Ext.each(selection, function (event) {
                        panel.getStore().remove(event);
                      });
                    }

                    this.refresh(true);
                  }
                };

                if (containsRecurException) {
                  var range = option === 'future' ? 'THISANDFUTURE' : Ext.util.Format.uppercase(option);
                  Tine.Calendar.backend.deleteRecords([selection[0]], options, {
                    range: range
                  });
                } else {
                  if (option === 'all') {
                    Tine.Calendar.backend.deleteRecurSeries(selection[0], options);
                  } else {
                    Tine.Calendar.backend.createRecurException(selection[0], true, option === 'future', false, options);
                  }
                }

                break;

              default:
                this.onDeleteRecordsConfirmFail(panel, selection);
                break;
            }
          } catch (e) {
            Tine.log.error('Tine.Calendar.MainScreenCenterPanel::onDeleteRecords::handle');
            Tine.log.error(e);
          }
        }
      });
      return;
    } // else


    var i18nQuestion = String.format(this.app.i18n.ngettext('Do you really want to delete this event?', 'Do you really want to delete the {0} selected events?', selection.length), selection.length);
    Ext.MessageBox.confirm(i18n._hidden('Confirm'), i18nQuestion, function (btn) {
      if (btn === 'yes') {
        this.onDeleteRecordsConfirmNonRecur(panel, selection);
      } else {
        this.onDeleteRecordsConfirmFail(panel, selection);
      }
    }, this);
  },
  onDeleteRecordsConfirmNonRecur: function onDeleteRecordsConfirmNonRecur(panel, selection) {
    panel.getTopToolbar().beforeLoad(); // create a copy of selection so selection changes don't affect this

    var sel = Ext.unique(selection);
    var options = {
      scope: this,
      success: function success() {
        panel.getTopToolbar().onLoad();
        Ext.each(sel, function (event) {
          panel.getStore().remove(event);
        });
      },
      failure: function failure() {
        panel.getTopToolbar().onLoad();
        Ext.MessageBox.alert(i18n._hidden('Failed'), String.format(this.app.i18n.n_('Failed to delete event', 'Failed to delete the {0} events', selection.length), selection.length));
      }
    };
    Tine.Calendar.backend.deleteRecords(selection, options);
  },
  onDeleteRecordsConfirmFail: function onDeleteRecordsConfirmFail(panel, selection) {
    Ext.each(selection, function (event) {
      event.ui.clearDirty();
    });
  },

  /**
   * is called on action cut
   * 
   * @param {} action
   * @param {} event
   */
  onCutEvent: function onCutEvent(action, event) {
    var panel = this.getCalendarPanel(this.activeView);
    var selection = panel.getSelectionModel().getSelectedEvents();

    if (Ext.isArray(selection) && selection.length === 1) {
      event = selection[0];
    }

    if (event.ui) {
      event.ui.markDirty();
    }

    event.view = event.view ? event.view : panel.view;
    Tine.Tinebase.data.Clipboard.push(event);
  },

  /**
   * Is called on copy to clipboard
   *
   * @param action
   * @param event
   */
  onCopyToEvent: function onCopyToEvent(action, event) {
    var panel = this.getCalendarPanel(this.activeView);
    var selection = panel.getSelectionModel().getSelectedEvents();

    if (Ext.isArray(selection) && selection.length === 1) {
      event = selection[0];
    }

    event.isCopy = true;
    event.view = event.view ? event.view : panel.view;
    Tine.Tinebase.data.Clipboard.push(event);
  },

  /**
   * is called on cancelling cut & paste
   */
  onCutCancelEvent: function onCutCancelEvent() {
    var store = this.getStore();
    var ids = Tine.Tinebase.data.Clipboard.getIds('Calendar', 'Event');

    for (var index = 0; index < ids.length; index++) {
      var record = store.getAt(store.findExact('id', ids[index]));

      if (record && record.ui) {
        record.ui.clearDirty();
      }
    }

    Tine.Tinebase.data.Clipboard.clear('Calendar', 'Event');
  },

  /**
   * is called on action paste
   * 
   * @param {Date} datetime
   */
  onPasteEvent: function onPasteEvent(datetime) {
    var record = Tine.Tinebase.data.Clipboard.pull('Calendar', 'Event'),
        isCopy = record.isCopy,
        sourceView = record.view,
        sourceRecord = record,
        sourceViewAttendee = sourceView.ownerCt.attendee,
        destinationView = this.getCalendarPanel(this.activeView).getView(),
        destinationViewAttendee = destinationView.ownerCt.attendee;

    if (!record) {
      return;
    }

    var dtend = record.get('dtend'),
        dtstart = record.get('dtstart'),
        eventLength = dtend - dtstart,
        store = this.getStore();
    record.beginEdit();

    if (isCopy !== true) {
      // remove from ui before update
      var oldRecord = store.getAt(store.findExact('id', record.getId()));

      if (oldRecord && oldRecord.hasOwnProperty('ui')) {
        oldRecord.ui.remove();
      }
    } else {
      this.omitCopyTitle = record.hasPoll();
      record = Tine.Calendar.EventEditDialog.prototype.doCopyRecordToReturn(record);
      record.set('editGrant', true);
      record.set('id', '');
      record.view = sourceView; // remove attender ids

      Ext.each(record.data.attendee, function (attender) {
        delete attender.id;
      }, this);
    } // @TODO move to common function with daysView::notifyDrop parts
    // change attendee in split view


    if (sourceViewAttendee || destinationViewAttendee) {
      var attendeeStore = Tine.Calendar.Model.Attender.getAttendeeStore(sourceRecord.get('attendee')),
          sourceAttendee = sourceViewAttendee ? Tine.Calendar.Model.Attender.getAttendeeStore.getAttenderRecord(attendeeStore, sourceViewAttendee) : false,
          destinationAttendee = destinationViewAttendee ? Tine.Calendar.Model.Attender.getAttendeeStore.getAttenderRecord(attendeeStore, destinationViewAttendee) : false;

      if (destinationViewAttendee && !destinationAttendee) {
        destinationAttendee = new Tine.Calendar.Model.Attender(destinationViewAttendee.data);
        attendeeStore.remove(sourceAttendee);
        attendeeStore.add(destinationAttendee);
        record.view = destinationView;
        Tine.Calendar.Model.Attender.getAttendeeStore.getData(attendeeStore, record);
      }
    }

    if (datetime.is_all_day_event) {
      record.set('dtstart', datetime);
      record.set('dtend', datetime.clone().add(Date.DAY, 1).add(Date.SECOND, -1));
      record.set('is_all_day_event', true);
    } else if (datetime.date_only) {
      var adoptedDtStart = datetime.clone();
      adoptedDtStart.setHours(dtstart.getHours());
      adoptedDtStart.setMinutes(dtstart.getMinutes());
      adoptedDtStart.setSeconds(dtstart.getSeconds());
      record.set('dtstart', adoptedDtStart);
      record.set('dtend', new Date(adoptedDtStart.getTime() + eventLength));
    } else {
      record.set('dtstart', datetime);
      record.set('dtend', new Date(datetime.getTime() + eventLength));
    }

    record.endEdit();

    if (isCopy === true) {
      record.isCopy = true;
      Tine.Tinebase.data.Clipboard.push(record);

      if (record.ui) {
        record.ui.clearDirty();
      }

      this.onAddEvent(record);
    } else {
      this.onUpdateEvent(record);
    }
  },

  /**
   * open event in new window
   * 
   * @param {String} action  add|edit|copy
   * @param {String} event   edit given event instead of selected event
   * @param {Object} plugins event dlg plugins
   * @param {Object} default properties for new items
   */
  onEditInNewWindow: function onEditInNewWindow(action, event, plugins, defaults) {
    if (!(event && Ext.isFunction(event.beginEdit))) {
      event = null;
    } // needed for addToEventPanel


    if (Ext.isObject(action)) {
      action = action.actionType;
    }

    if (action === 'edit' && !event) {
      var panel = this.getCalendarPanel(this.activeView);
      var selection = panel.getSelectionModel().getSelectedEvents();

      if (Ext.isArray(selection) && selection.length === 1) {
        event = selection[0];
      }
    }

    if (action === 'edit' && !event) {
      return;
    }

    if (!event) {
      event = new Tine.Calendar.Model.Event(Ext.apply(Tine.Calendar.Model.Event.getDefaultData(), defaults), 0);

      if (defaults && Ext.isDate(defaults.dtStart)) {
        event.set('dtstart', defaults.dtStart);
        event.set('dtend', defaults.dtStart.add(Date.MINUTE, Tine.Calendar.Model.Event.getMeta('defaultEventDuration')));
      }
    }

    Tine.log.debug('Tine.Calendar.MainScreenCenterPanel::onEditInNewWindow() - Opening event edit dialog with action: ' + action);
    Tine.Calendar.EventEditDialog.openWindow({
      plugins: Ext.isArray(plugins) ? Ext.encode(plugins) : null,
      record: Ext.encode(event.data),
      recordId: event.data.id,
      copyRecord: action == 'copy',
      listeners: {
        scope: this,
        update: function update(eventJson) {
          var updatedEvent = Tine.Calendar.backend.recordReader({
            responseText: eventJson
          });
          updatedEvent.dirty = true;
          updatedEvent.modified = {};
          event.phantom = action === 'edit';
          var panel = this.getCalendarPanel(this.activeView);
          var store = panel.getStore();
          event = store.getById(event.id);

          if (event && action !== 'copy') {
            store.replaceRecord(event, updatedEvent);
          } else {
            store.add(updatedEvent);
          }

          this.onUpdateEvent(updatedEvent, false, event);
        }
      }
    });
  },
  onKeyDown: function onKeyDown(e) {
    // no keys for quickadds etc.
    if (e.getTarget('input') || e.getTarget('textarea')) return;

    switch (e.getKey()) {
      case e.A:
        // select only current page
        //this.grid.getSelectionModel().selectAll(true);
        e.preventDefault();
        break;

      case e.E:
        if (!this.action_editInNewWindow.isDisabled()) {
          this.onEditInNewWindow('edit');
        }

        e.preventDefault();
        break;

      case e.N:
        if (!this.action_addInNewWindow.isDisabled()) {
          this.onEditInNewWindow('add');
        }

        e.preventDefault();
        break;

      case e.DELETE:
        e.stopEvent();

        if (!this.action_deleteRecord.isDisabled()) {
          this.onDeleteRecords.call(this);
        }

        break;
    }
  },
  onPrintMenuClick: function onPrintMenuClick(splitBtn, e) {
    if (!String(this.activeView).match(/(day|week)sheet$/i)) {
      splitBtn.menu.hide();
    }
  },
  onPrint: function onPrint(printMode) {
    var printMode = printMode ? printMode : this.defaultPrintMode,
        panel = this.getCalendarPanel(this.activeView),
        view = panel ? panel.getView() : null;

    if (view && Ext.isFunction(view.print)) {
      view.print(printMode);
    } else {
      Ext.Msg.alert(this.app.i18n._('Could not Print'), this.app.i18n._('Sorry, your current view does not support printing.'));
    }
  },

  /**
   * called before store queries for data
   */
  onStoreBeforeload: function onStoreBeforeload(store, options) {
    options.params = options.params || {}; // define a transaction

    this.lastStoreTransactionId = options.transactionId = Ext.id(); // allways start with an empty filter set!
    // this is important for paging and sort header!

    options.params.filter = [];

    if (!options.refresh && this.rendered) {
      // defer to have the loadMask centered in case of rendering actions
      this.loadMask.show.defer(50, this.loadMask);
    } // note, we can't use the 'normal' plugin approach here, cause we have to deal with n stores
    //var calendarSelectionPlugin = this.app.getMainScreen().getWestPanel().getContainerTreePanel().getFilterPlugin();
    //calendarSelectionPlugin.onBeforeLoad.call(calendarSelectionPlugin, store, options);


    this.filterToolbar.onBeforeLoad.call(this.filterToolbar, store, options); // add period filter as last filter to not conflict with first OR filter

    if (!options.noPeriodFilter) {
      options.params.filter.push({
        field: 'period',
        operator: 'within',
        value: this.getCalendarPanel(this.activeView).getView().getPeriod()
      });
    }
  },

  /**
   * fence against loading of wrong data set
   */
  onStoreBeforeLoadRecords: function onStoreBeforeLoadRecords(o, options, success) {
    return this.lastStoreTransactionId === options.transactionId;
  },

  /**
   * called when store loaded data
   */
  onStoreLoad: function onStoreLoad(store, options) {
    if (this.rendered && _.get(options, 'keepLoadMask') !== true) {
      this.loadMask.hide();
    } // reset autoRefresh


    if (window.isMainWindow && this.autoRefreshInterval) {
      this.autoRefreshTask.delay(this.autoRefreshInterval * 1000);
    } // check if store is current store


    if (store !== this.getCalendarPanel(this.activeView).getStore()) {
      Tine.log.debug('Tine.Calendar.MainScreenCenterPanel::onStoreLoad view is not active anymore');
      return;
    }

    if (this.rendered) {
      // update filtertoolbar
      if (this.filterToolbar) {
        this.filterToolbar.setValue(store.proxy.jsonReader.jsonData.filter);
      } // update container tree


      Tine.Tinebase.appMgr.get('Calendar').getMainScreen().getWestPanel().getContainerTreePanel().getFilterPlugin().setValue(store.proxy.jsonReader.jsonData.filter); // update attendee filter grid

      Tine.Tinebase.appMgr.get('Calendar').getMainScreen().getWestPanel().getAttendeeFilter().setFilterValue(store.proxy.jsonReader.jsonData.filter);
    }
  },

  /**
   * on store load exception
   * 
   * @param {Tine.Tinebase.data.RecordProxy} proxy
   * @param {String} type
   * @param {Object} error
   * @param {Object} options
   */
  onStoreLoadException: function onStoreLoadException(proxy, type, error, options) {
    // reset autoRefresh
    if (window.isMainWindow && this.autoRefreshInterval) {
      this.autoRefreshTask.delay(this.autoRefreshInterval * 5000);
    }

    this.setLoading(false);
    this.loadMask.hide();

    if (!options.autoRefresh) {
      this.onProxyFail(error);
    }
  },
  onConflict: function onConflict(error, event, ignoreFn) {
    var attendeeStore = Tine.Calendar.Model.Attender.getAttendeeStore(error.event.attendee),
        fbInfo = new Tine.Calendar.FreeBusyInfo(error.freebusyinfo),
        denyIgnore = fbInfo.getStateOfAllAttendees() == Tine.Calendar.FreeBusyInfo.states.BUSY_UNAVAILABLE;
    this.conflictConfirmWin = Tine.widgets.dialog.MultiOptionsDialog.openWindow({
      modal: true,
      allowCancel: false,
      width: 550,
      height: 180 + fbInfo.attendeeCount * 14 + 12 * error.freebusyinfo.length,
      title: this.app.i18n._('Scheduling Conflict'),
      questionText: '<div class = "cal-conflict-heading">' + this.app.i18n._('The following attendee are busy at the requested time:') + '</div>' + fbInfo.getInfoByAttendee(attendeeStore, event),
      options: [{
        text: this.app.i18n._('Ignore Conflict'),
        name: 'ignore',
        disabled: denyIgnore
      }, {
        text: this.app.i18n._('Edit Event'),
        name: 'edit',
        checked: true
      }, {
        text: this.app.i18n._('Cancel this action'),
        name: 'cancel'
      }],
      scope: this,
      handler: function handler(option) {
        var panel = this.getCalendarPanel(this.activeView),
            store = this.getStore();

        switch (option) {
          case 'ignore':
            if (Ext.isFunction(ignoreFn)) {
              ignoreFn();
            } else {
              this.onAddEvent(event, false, true);
            }

            this.conflictConfirmWin.close();
            break;

          case 'edit':
            var presentationMatch = this.activeView.match(this.presentationRe),
                presentation = Ext.isArray(presentationMatch) ? presentationMatch[0] : null;

            if (presentation != 'Grid') {
              var view = panel.getView();
              view.getSelectionModel().select(event); // mark event as not dirty to allow edit dlg

              event.dirty = false;
              view.fireEvent('dblclick', view, event);
            } else {
              // add or edit?
              this.onEditInNewWindow(null, event);
            }

            this.conflictConfirmWin.close();
            break;

          case 'cancel':
          default:
            this.conflictConfirmWin.close();
            this.loadMask.show();
            store.load({
              refresh: true
            });
            break;
        }
      }
    });
  },
  onProxyFail: function onProxyFail(error, event, ignoreFn) {
    this.setLoading(false);
    if (this.loadMask) this.loadMask.hide();

    if (error.code === 901) {
      this.onConflict(error, event, ignoreFn);
    } else {
      error.clientProps = ['component', 'proxyEvent'];
      error.component = this;
      error.proxyEvent = event;
      Tine.Tinebase.ExceptionHandler.handleRequestException(error);
    }
  },
  refresh: function refresh(options) {
    // convert old boolean argument
    options = Ext.isObject(options) ? options : {
      refresh: !!options
    };
    Tine.log.debug('Tine.Calendar.MainScreenCenterPanel::refresh(' + options.refresh + ')'); // reset autoRefresh it might get lost if request fails

    if (window.isMainWindow && this.autoRefreshInterval) {
      this.autoRefreshTask.delay(this.autoRefreshInterval * 2000);
    }

    var panel = this.getCalendarPanel(this.activeView);
    panel.getStore().load(options); // clear favorites

    Tine.Tinebase.appMgr.get('Calendar').getMainScreen().getWestPanel().getFavoritesPanel().getSelectionModel().clearSelections();
  },
  setLoading: function setLoading(bool) {
    if (this.rendered) {
      var panel = this.getCalendarPanel(this.activeView),
          tbar = panel.getTopToolbar();

      if (tbar && tbar.loading) {
        tbar.loading[bool ? 'disable' : 'enable']();
      }
    }
  },
  setResponseStatus: function setResponseStatus(event, status) {
    var myAttenderRecord = event.getMyAttenderRecord();

    if (myAttenderRecord) {
      myAttenderRecord.set('status', status);
      this.updateEvent(event);
    }
  },
  setEventStatus: function setEventStatus(event, status) {
    Ext.MessageBox.confirm(this.app.i18n._('Update Status for all Attendee?'), this.app.i18n._('You are about to change the status of the event itself and not just your own status. Do you really want to change the event status for all attendee?'), function (btn) {
      if (btn === 'yes') {
        event.set('status', status);
        this.updateEvent(event);
      }
    }, this).setIcon(Ext.MessageBox.QUESTION);
  },
  updateEvent: function updateEvent(event) {
    event.dirty = true;
    event.modified = {};
    var panel = this.getCalendarPanel(this.activeView);
    var store = this.getStore();
    store.replaceRecord(event, event);
    this.onUpdateEvent(event);
  },
  updateEventActions: function updateEventActions() {
    var panel = this.getCalendarPanel(this.activeView);
    var selection = panel.getSelectionModel().getSelectedEvents();
    this.actionUpdater.updateActions(selection);

    if (this.detailsPanel) {
      this.detailsPanel.onDetailsUpdate(panel.getSelectionModel());
    }
  },
  updateView: function updateView(which) {
    Tine.log.debug('Tine.Calendar.MainScreenCenterPanel::updateView(' + which + ')');
    var panel = this.getCalendarPanel(which);
    var period = panel.getTopToolbar().getPeriod();
    panel.getView().updatePeriod(period);
    panel.getStore().load({}); //this.updateMiniCal();
  },

  /**
   * returns requested CalendarPanel
   * 
   * @param {String} which
   * @return {Tine.Calendar.CalendarPanel}
   */
  getCalendarPanel: function getCalendarPanel(which) {
    var whichParts = this.getViewParts(which);
    which = whichParts.toString();

    let currentCalendarPanel = _.get(this, "calendarPanels.".concat(this.activeView));

    let currentPeriod = _.isFunction(_.get(currentCalendarPanel, 'getView')) && _.isFunction(_.get(currentCalendarPanel.getView(), 'getPeriod')) ? currentCalendarPanel.getView().getPeriod() : null;

    if (!this.calendarPanels[which]) {
      Tine.log.debug('Tine.Calendar.MainScreenCenterPanel::getCalendarPanel creating new calender panel for view ' + which);
      var store = new Ext.data.JsonStore({
        //autoLoad: true,
        id: 'id',
        fields: Tine.Calendar.Model.Event,
        proxy: Tine.Calendar.backend,
        reader: new Ext.data.JsonReader({}),
        //Tine.Calendar.backend.getReader(),
        listeners: {
          scope: this,
          'beforeload': this.onStoreBeforeload,
          'beforeloadrecords': this.onStoreBeforeLoadRecords,
          'load': this.onStoreLoad,
          'loadexception': this.onStoreLoadException
        },
        replaceRecord: function replaceRecord(o, n) {
          var idx = this.indexOf(o);
          this.remove(o);
          this.insert(idx, n);
        }
      });
      var tbar = new Tine.Calendar.PagingToolbar({
        view: whichParts.period,
        store: store,
        dtStart: this.startDate,
        period: _.cloneDeep(currentPeriod),
        periodBtn: _.get(this, 'show' + _.upperFirst(whichParts.period) + 'View'),
        listeners: {
          scope: this,
          // NOTE: only render the button once for the toolbars
          //       the buttons will be moved on chageView later
          render: function render(tbar) {
            for (var i = 0; i < this.changeViewActions.length; i += 1) {
              if (!this.changeViewActions[i].rendered) {
                tbar.addButton(this.changeViewActions[i]);
              }
            }
          }
        }
      });
      tbar.on('change', this.updateView.createDelegate(this, [which]), this, {
        buffer: 200
      });
      tbar.on('refresh', this.refresh.createDelegate(this, [true]), this, {
        buffer: 200
      });

      if (whichParts.presentation.match(/sheet/i)) {
        var view;

        switch (which) {
          case 'daySheet':
            view = new Tine.Calendar.DaysView({
              store: store,
              startDate: tbar.getPeriod().from,
              numOfDays: 1
            });
            break;

          case 'monthSheet':
            view = new Tine.Calendar.MonthView({
              store: store,
              period: tbar.getPeriod()
            });
            break;

          case 'yearSheet':
            view = new Tine.Calendar.YearView({
              store: store,
              period: tbar.getPeriod()
            });
            break;

          default:
          case 'weekSheet':
            const from = tbar.getPeriod().from;
            const numOfDays = Math.round((tbar.getPeriod().until.getTime() - from.getTime()) / (3600 * 24000));
            view = new Tine.Calendar.DaysView({
              store: store,
              startDate: from,
              numOfDays: numOfDays
            });
            break;
        }

        view.on('changeView', this.changeView, this);
        view.on('changePeriod', function (period) {
          this.startDate = period.from;
          this.startDates[which] = this.startDate.clone();
          this.updateMiniCal();
        }, this); // quick add/update actions

        view.on('addEvent', this.onAddEvent, this);
        view.on('updateEvent', this.onUpdateEvent, this);
        this.calendarPanels[which] = new Tine.Calendar.CalendarPanel({
          tbar: tbar,
          view: view,
          mainScreen: this,
          canonicalName: ['Event', 'Sheet']
        });
      } else if (whichParts.presentation.match(/grid/i)) {
        this.calendarPanels[which] = new Tine.Calendar.GridView({
          tbar: tbar,
          store: store,
          mainScreen: this,
          canonicalName: ['Event', 'Grid']
        });
      } else if (whichParts.presentation.match(/timeline/i)) {
        this.calendarPanels[which] = new Tine.Calendar.TimelinePanel({
          tbar: tbar,
          period: tbar.periodPicker.getPeriod(),
          viewType: whichParts.period,
          store: store,
          canonicalName: ['Event', 'Timeline'],
          mainScreen: this
        });
      }

      this.calendarPanels[which]['canonicalName'].push(Ext.util.Format.capitalize(which.match(/[a-z]+/)[0]));
      this.calendarPanels[which]['canonicalName'] = this.calendarPanels[which]['canonicalName'].join(Tine.Tinebase.CanonicalPath.separator);
      this.calendarPanels[which].on('dblclick', this.onEditInNewWindow.createDelegate(this, ["edit"], 0));
      this.calendarPanels[which].on('contextmenu', this.onContextMenu, this);
      this.calendarPanels[which].getSelectionModel().on('selectionchange', this.updateEventActions, this);
      this.calendarPanels[which].on('keydown', this.onKeyDown, this);
      this.calendarPanels[which].relayEvents(this, ['show', 'beforehide']);
      this.calendarPanels[which].cls = 'cal-ms-panel'; // rebind store so it's event listeners get called at last.
      // -> otherwise loading spinner would be active event if the view beforeload cancels the request

      tbar.unbind(store);
      tbar.bind(store);
    }

    return this.calendarPanels[which];
  },
  recreatePanel: function recreatePanel(which) {
    if (this.calendarPanels[which]) {
      let panel = this.getCalendarPanel(which);
      this.calendarPanels[which] = null;

      _.delay(() => {
        const cardPanel = this.items.first();
        panel.tbar = null; //  yes, this is a mem leak - but it's ok as recreate is a rare action

        panel.toolbars = []; // and the button handling is complicated

        cardPanel.remove(panel);
      }, 2000);

      if (this.activeView === which) {
        this.changeView(which, panel.getView().getPeriod().from);
      }
    }
  },
  updateMiniCal: function updateMiniCal() {
    var miniCal = Ext.getCmp('cal-mainscreen-minical');
    var weekNumbers = null;
    var period = this.getCalendarPanel(this.activeView).getView().getPeriod();

    switch (this.activeView) {
      case 'week':
        weekNumbers = [period.from.add(Date.DAY, 1).getWeekOfYear()];
        break;

      case 'month':
        weekNumbers = [];
        var startWeek = period.from.add(Date.DAY, 1).getWeekOfYear();
        var numWeeks = Math.round((period.until.getTime() - period.from.getTime()) / Date.msWEEK);

        for (var i = 0; i < numWeeks; i += 1) {
          weekNumbers.push(startWeek + i);
        }

        break;
    }

    miniCal.update(this.startDate, true, weekNumbers);
  }
});

/***/ }),

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

/*
 * Tine 2.0
 *
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2015 Metaways Infosystems GmbH (http://www.metaways.de)
 */
Tine.Calendar.EventContextTagsItem = Ext.extend(Ext.menu.Item, {
  text: 'Tags',
  event: null,
  datetime: null,
  initComponent: function initComponent() {
    this.app = Tine.Tinebase.appMgr.get('Calendar');
    this.hidden = this.app.getMainScreen().getCenterPanel().isActiveView('Grid') || !(this.event && this.event.get('editGrant') && Tine.Tinebase.appMgr.get('Calendar').featureEnabled('featureExtendedEventContextActions'));
    this.recentsManager = new Tine.Tinebase.RecentsManager({
      recordClass: Tine.Tinebase.Model.Tag,
      domain: this.app.appName,
      maxRecents: 20
    });
    this.menu = [];
    this.view = this.app.getMainScreen().getCenterPanel().getCalendarPanel(this.app.getMainScreen().getCenterPanel().activeView).getView();
    this.attachedTagIds = [];
    var attachedTags = this.event ? this.event.get('tags') : [],
        recents = this.recentsManager.getRecentRecords(),
        tagRenderer = Tine.Tinebase.common.tagRenderer;
    Ext.each(attachedTags, function (r) {
      r = Ext.isFunction(r.beginEdit) ? r : new Tine.Tinebase.Model.Tag(r);
      this.attachedTagIds.push(r.getId());
      this.menu.push({
        value: r.getId(),
        record: r,
        text: tagRenderer(r),
        checked: true,
        handleClick: this.handleClick
      });
    }, this);
    Ext.each(recents, function (r) {
      if (this.attachedTagIds.indexOf(r.getId()) < 0) {
        this.menu.push({
          value: r.getId(),
          record: r,
          text: tagRenderer(r),
          checked: false,
          handleClick: this.handleClick
        });
      }
    }, this);
    var other = new Tine.widgets.tags.TagsMassAttachAction({
      app: this.app,
      text: this.app.i18n._('Additional Tags ...')
    });
    other.initialConfig.handler = other.initialConfig.handler.createSequence(this.onOtherClick, this);
    this.menu.push(other);
    Tine.Calendar.EventContextTagsItem.superclass.initComponent.call(this);
    this.menu.on('hide', this.onMenuHide, this);
  },

  /**
   * prevent menu hide
   */
  handleClick: function handleClick(e) {
    if (this.setChecked && !this.disabled && !(this.checked && this.group)) {
      // disable unselect on radio item
      this.setChecked(!this.checked);
    }

    e.stopEvent();
  },

  /**
   * show extra window & prevent autosave
   */
  onOtherClick: function onOtherClick() {
    this.menu.un('hide', this.onMenuHide, this);
    var massAttach = this.menu.items.last().baseAction;
    massAttach.store.add(this.getSelectedRecords());

    massAttach.win.okButton.handler = function () {
      var tags = [];
      massAttach.store.each(function (r) {
        tags.push(r);
      }, this);
      massAttach.win.close();
      this.updateRecord(tags);
    }.createDelegate(this);

    massAttach.manageOkBtn = function () {
      if (this.win && this.win.okButton) this.win.okButton.setDisabled(false);
    };
  },

  /**
   * autosave
   */
  onMenuHide: function onMenuHide() {
    if (this.updateRecord(this.getSelectedRecords())) {
      this.menu.un('hide', this.onMenuHide, this);
    }
  },
  updateRecord: function updateRecord(selectedRecords) {
    var tagDatas = [],
        tagIds = [];
    Ext.each(selectedRecords, function (tag) {
      tagDatas.push(tag.data);
      tagIds.push(tag.getId());
    }, this);
    var migration = this.attachedTagIds.getMigration(tagIds);

    if (migration.toDelete.length || migration.toCreate.length) {
      this.event.set('tags', '');
      this.event.set('tags', tagDatas);
      this.view.editing = this.event;
      this.app.getMainScreen().getCenterPanel().onUpdateEvent(this.event, false, 'update');
      this.ownerCt.destroy.defer(100, this.ownerCt);
      return true;
    }
  },
  getSelectedRecords: function getSelectedRecords() {
    var records = [];
    this.menu.items.each(function (item) {
      if (item.checked) {
        records.push(item.record);
      }
    }, this);
    return records;
  }
});
Ext.ux.ItemRegistry.registerItem('Calendar-MainScreenPanel-ContextMenu', Tine.Calendar.EventContextTagsItem, 130);

/***/ }),

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

/*
 * Tine 2.0
 *
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2015 Metaways Infosystems GmbH (http://www.metaways.de)
 */
Tine.Calendar.EventContextAttendeesItem = Ext.extend(Ext.menu.Item, {
  event: null,
  datetime: null,
  initComponent: function initComponent() {
    this.app = Tine.Tinebase.appMgr.get('Calendar');
    this.text = this.app.i18n._('Attendee/Resources');
    this.hidden = this.app.getMainScreen().getCenterPanel().isActiveView('Grid') || !(this.event && this.event.get('editGrant') && Tine.Tinebase.appMgr.get('Calendar').featureEnabled('featureExtendedEventContextActions'));
    this.menu = [];
    this.view = this.app.getMainScreen().getCenterPanel().getCalendarPanel(this.app.getMainScreen().getCenterPanel().activeView).getView();

    var attendeeFilter = Ext.state.Manager.get('calendar-attendee-filter-grid'),
        explicitAttendee = attendeeFilter && Ext.isArray(attendeeFilter.explicitAttendee) ? attendeeFilter.explicitAttendee : [],
        currentAttendee = Tine.Calendar.Model.Attender.getAttendeeStore(this.event ? this.event.get('attendee') : []),
        attendeeRenderer = function attendeeRenderer(attender) {
      var name = Tine.Calendar.AttendeeGridPanel.prototype.renderAttenderName.call(Tine.Calendar.AttendeeGridPanel.prototype, attender.get('user_id'), false, attender),
          type = Tine.Calendar.AttendeeGridPanel.prototype.renderAttenderType.call(Tine.Calendar.AttendeeGridPanel.prototype, attender.get('user_type'), false, attender);
      type = type.replace('<div', '<div style="float: left; padding-left: 20px;"');
      return type + name;
    };

    currentAttendee.each(function (r) {
      this.menu.push({
        record: r,
        text: attendeeRenderer(r),
        checked: true,
        handleClick: this.handleClick
      });
    }, this);
    Ext.each(explicitAttendee, function (attendeeData) {
      var r = new Tine.Calendar.Model.Attender(attendeeData, 'new-' + Ext.id()),
          isCurrent = Tine.Calendar.Model.Attender.getAttendeeStore.getAttenderRecord(currentAttendee, r);

      if (!isCurrent) {
        this.menu.push({
          record: r,
          text: attendeeRenderer(r),
          checked: false,
          handleClick: this.handleClick
        });
      }
    }, this);
    var other = new Ext.Action({
      text: this.app.i18n._('Additional Attendees ...'),
      handler: this.onOtherClick,
      scope: this
    });
    this.menu.push(other);
    Tine.Calendar.EventContextAttendeesItem.superclass.initComponent.call(this);
    this.menu.on('hide', this.onMenuHide, this);
  },

  /**
   * prevent menu hide
   */
  handleClick: function handleClick(e) {
    if (this.setChecked && !this.disabled && !(this.checked && this.group)) {
      // disable unselect on radio item
      this.setChecked(!this.checked);
      this.parentMenu.dirty = true;
    }

    e.stopEvent();
  },

  /**
   * show extra window & prevent autosave
   */
  onOtherClick: function onOtherClick() {
    this.menu.un('hide', this.onMenuHide, this);
    var data = [],
        fakeRecord = this.event.copy();
    Ext.each(this.getSelectedRecords(), function (r) {
      data.push(r.data);
    }, this);
    fakeRecord.set('attendee', '');
    fakeRecord.set('attendee', data);
    this.attendeeGridPanel = new Tine.Calendar.AttendeeGridPanel({
      header: false,
      border: false
    });
    this.attendeeGridPanel.onRecordLoad(fakeRecord);
    var win = Tine.WindowFactory.getWindow({
      layout: 'fit',
      width: 500,
      height: 300,
      modal: true,
      title: this.app.i18n._('Attendee'),
      items: [{
        xtype: 'form',
        buttonAlign: 'right',
        border: false,
        layout: 'fit',
        items: this.attendeeGridPanel,
        buttons: [{
          text: i18n._('Cancel'),
          minWidth: 70,
          scope: this,
          handler: function handler(btn) {
            win.close();
          },
          iconCls: 'action_cancel'
        }, {
          text: i18n._('Ok'),
          minWidth: 70,
          scope: this,
          handler: function handler(btn) {
            this.attendeeGridPanel.onRecordUpdate(this.event);
            this.view.editing = this.event;
            this.app.getMainScreen().getCenterPanel().onUpdateEvent(this.event, false, 'update');
            win.close();
          },
          iconCls: 'action_saveAndClose'
        }]
      }]
    });
    win.show();
  },

  /**
   * autosave
   */
  onMenuHide: function onMenuHide() {
    if (this.updateRecord(this.getSelectedRecords())) {
      this.menu.un('hide', this.onMenuHide, this);
    }
  },
  updateRecord: function updateRecord(selectedRecords) {
    var data = [];
    Ext.each(selectedRecords, function (r) {
      data.push(r.data);
    }, this);

    if (this.menu.dirty) {
      this.event.set('attendee', '');
      this.event.set('attendee', data);
      this.view.editing = this.event;
      this.app.getMainScreen().getCenterPanel().onUpdateEvent(this.event, false, 'update');
      this.ownerCt.destroy.defer(100, this.ownerCt);
      return true;
    }
  },
  getSelectedRecords: function getSelectedRecords() {
    var records = [];
    this.menu.items.each(function (item) {
      if (item.checked) {
        records.push(item.record);
      }
    }, this);
    return records;
  }
});
Ext.ux.ItemRegistry.registerItem('Calendar-MainScreenPanel-ContextMenu', Tine.Calendar.EventContextAttendeesItem, 140);

/***/ }),

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

/* 
 * Tine 2.0
 * 
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2009-2010 Metaways Infosystems GmbH (http://www.metaways.de)
 */
Ext.ns('Tine.Calendar');
/**
 * Calendar west panel
 * 
 * @namespace   Tine.Calendar
 * @class       Tine.Calendar.WestPanel
 * @extends     Tine.widgets.mainscreen.WestPanel
 * 
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * 
 * @constructor
 * @xtype       tine.calendar.mainscreenwestpanel
 */

Tine.Calendar.WestPanel = Ext.extend(Tine.widgets.mainscreen.WestPanel, {
  cls: 'cal-tree',
  canonicalName: 'Event',
  defaultCollapseContainerTree: true,
  getAdditionalItems: function getAdditionalItems() {
    return [Ext.apply(this.getAttendeeFilter(), this.defaults), Ext.apply({
      title: this.app.i18n._('Mini Calendar'),
      canonicalName: 'MiniDatePicker',
      forceLayout: true,
      border: false,
      layout: 'hbox',
      layoutConfig: {
        align: 'middle'
      },
      defaults: {
        border: false
      },
      items: [{
        flex: 1
      }, this.getDatePicker(), {
        flex: 1
      }]
    }, this.defaults)];
  },
  getDatePicker: function getDatePicker() {
    if (!this.datePicker) {
      this.datePicker = new Ext.DatePicker({
        width: 200,
        id: 'cal-mainscreen-minical',
        plugins: [new Ext.ux.DatePickerWeekPlugin({
          weekHeaderString: Tine.Tinebase.appMgr.get('Calendar').i18n._('WK'),
          inspectMonthPickerClick: function inspectMonthPickerClick(btn, e) {
            if (e.getTarget('button')) {
              var contentPanel = Tine.Tinebase.appMgr.get('Calendar').getMainScreen().getCenterPanel();
              contentPanel.changeView('month', this.activeDate);
              return false;
            }
          }
        })],
        selectToday: function selectToday() {
          var contentPanel = Tine.Tinebase.appMgr.get('Calendar').getMainScreen().getCenterPanel(),
              pagingBar = contentPanel.getCalendarPanel(contentPanel.activeView).getTopToolbar();
          pagingBar.onClick('today');
          this.update(new Date().clearTime());
        },
        listeners: {
          scope: this,
          select: function select(picker, value, weekNumber) {
            var contentPanel = Tine.Tinebase.appMgr.get('Calendar').getMainScreen().getCenterPanel();
            contentPanel.changeView(weekNumber ? 'week' : 'day', value);
          }
        }
      });
    }

    return this.datePicker;
  },
  getAttendeeFilter: function getAttendeeFilter() {
    if (!this.attendeeFilter) {
      this.attendeeFilter = new Tine.Calendar.AttendeeFilterGrid({
        canonicalName: 'AttendeeFilter',
        autoHeight: true,
        title: this.app.i18n._('Attendee')
      });
    }

    return this.attendeeFilter;
  }
});

/***/ }),

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

/*
 * Tine 2.0
 * 
 * @package     Calendar
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2009-2012 Metaways Infosystems GmbH (http://www.metaways.de)
 *
 */
Ext.ns('Tine.Calendar');

__webpack_require__(1805);

__webpack_require__(1806);

__webpack_require__(1807);
/**
 * @namespace Tine.Calendar
 * @class Tine.Calendar.EventEditDialog
 * @extends Tine.widgets.dialog.EditDialog
 * Calendar Edit Dialog <br>
 * 
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 */


Tine.Calendar.EventEditDialog = Ext.extend(Tine.widgets.dialog.EditDialog, {
  labelAlign: 'side',
  windowNamePrefix: 'CalEventEditWindow_',
  appName: 'Calendar',
  recordClass: Tine.Calendar.Model.Event,
  showContainerSelector: false,
  displayNotes: true,
  requiredSaveGrant: 'readGrant',
  mode: 'local',
  saveEvent: function saveEvent(record, options, additionalArguments) {
    // NOTE: only mainscreen can handle busyConflicts
    additionalArguments.checkBusyConflicts = 0;
    return Tine.Calendar.Model.EventJsonBackend.prototype.saveRecord.apply(this.recordProxy, arguments); //
    // var cp = this.app.getMainScreen().getCenterPanel(),
    //     activePanel = cp.getCalendarPanel(cp.activeView),
    //     activeView = activePanel.getView();
    //
    // activeView.showEvent(record)
    //     .then(function() {
    //         // save via mainscreen to show fbExceptions and recurring decistions
    //         // but we would need to foreground the window and this is not possible for the browser
    //     });
  },
  onResize: function onResize() {
    Tine.Calendar.EventEditDialog.superclass.onResize.apply(this, arguments);
    this.setTabHeight.defer(100, this);
  },

  /**
   * returns dialog
   * 
   * NOTE: when this method gets called, all initalisation is done.
   * @return {Object} components this.itmes definition
   */
  getFormItems: function getFormItems() {
    var timeIncrement = parseInt(this.app.getRegistry().get('preferences').get('timeIncrement'));
    return {
      xtype: 'tabpanel',
      plugins: [{
        ptype: 'ux.tabpanelkeyplugin'
      }],
      defaults: {
        hideMode: 'offsets'
      },
      plain: true,
      activeTab: 0,
      border: false,
      items: [{
        title: this.app.i18n.n_('Event', 'Events', 1),
        border: false,
        frame: true,
        layout: 'border',
        items: [{
          region: 'center',
          layout: 'hfit',
          border: false,
          items: [{
            layout: 'hbox',
            items: [{
              margins: '5',
              width: 100,
              xtype: 'label',
              text: this.app.i18n._('Summary')
            }, {
              flex: 1,
              xtype: 'textfield',
              name: 'summary',
              listeners: {
                render: function render(field) {
                  field.focus(false, 250);
                }
              },
              allowBlank: false,
              requiredGrant: 'editGrant',
              maxLength: 1024
            }]
          }, {
            layout: 'hbox',
            items: [{
              margins: '5',
              width: 100,
              xtype: 'label',
              text: this.app.i18n._('View')
            }, Ext.apply(this.perspectiveCombo, {
              flex: 1
            })]
          }, {
            layout: 'hbox',
            height: 115,
            layoutConfig: {
              align: 'stretch',
              pack: 'start'
            },
            items: [{
              flex: 1,
              xtype: 'fieldset',
              layout: 'hfit',
              margins: '0 5 0 0',
              title: this.app.i18n._('Details'),
              items: [{
                xtype: 'columnform',
                labelAlign: 'side',
                labelWidth: 100,
                formDefaults: {
                  xtype: 'textfield',
                  anchor: '100%',
                  labelSeparator: '',
                  columnWidth: .7
                },
                items: [[{
                  columnWidth: 1,
                  fieldLabel: this.app.i18n._('Location'),
                  name: 'location',
                  requiredGrant: 'editGrant',
                  maxLength: 255
                }], [{
                  xtype: 'datetimefield',
                  fieldLabel: this.app.i18n._('Start Time'),
                  listeners: {
                    scope: this,
                    change: this.onDtStartChange
                  },
                  name: 'dtstart',
                  allowBlank: false,
                  increment: timeIncrement,
                  requiredGrant: 'editGrant'
                }, {
                  columnWidth: .19,
                  xtype: 'checkbox',
                  hideLabel: true,
                  boxLabel: this.app.i18n._('whole day'),
                  listeners: {
                    scope: this,
                    check: this.onAllDayChange
                  },
                  name: 'is_all_day_event',
                  requiredGrant: 'editGrant'
                }], [{
                  xtype: 'datetimefield',
                  fieldLabel: this.app.i18n._('End Time'),
                  listeners: {
                    scope: this,
                    change: this.onDtEndChange
                  },
                  name: 'dtend',
                  allowBlank: false,
                  increment: timeIncrement,
                  requiredGrant: 'editGrant'
                }, {
                  columnWidth: .3,
                  xtype: 'combo',
                  hideLabel: true,
                  readOnly: true,
                  hideTrigger: true,
                  disabled: true,
                  name: 'originator_tz',
                  requiredGrant: 'editGrant'
                }], [this.containerSelectCombo = new Tine.widgets.container.SelectionComboBox({
                  columnWidth: 1,
                  id: this.app.appName + 'EditDialogContainerSelector' + Ext.id(),
                  fieldLabel: i18n._('Saved in'),
                  ref: '../../../../../../../../containerSelect',
                  //width: 300,
                  //listWidth: 300,
                  name: this.recordClass.getMeta('containerProperty'),
                  treePanelClass: Tine.Calendar.TreePanel,
                  recordClass: this.recordClass,
                  containerName: this.app.i18n.n_hidden(this.recordClass.getMeta('containerName'), this.recordClass.getMeta('containersName'), 1),
                  containersName: this.app.i18n._hidden(this.recordClass.getMeta('containersName')),
                  appName: this.app.appName,
                  requiredGrant: 'readGrant',
                  requiredGrants: ['addGrant'],
                  disabled: true
                }), Ext.apply(this.perspectiveCombo.getAttendeeContainerField(), {
                  columnWidth: 1
                })]]
              }]
            }, {
              width: 130,
              xtype: 'fieldset',
              title: this.app.i18n._('Status'),
              items: [{
                xtype: 'widget-keyfieldcombo',
                app: 'Calendar',
                keyFieldName: 'eventStatus',
                width: 120,
                hideLabel: true,
                value: 'CONFIRMED',
                name: 'status',
                requiredGrant: 'editGrant',
                listeners: {
                  beforeselect: (combo, status, index) => {
                    Ext.MessageBox.confirm(this.app.i18n._('Update Status for all Attendee?'), this.app.i18n._('You are about to change the status of the event itself and not just your own status. Do you really want to change the event status for all attendee?'), function (btn) {
                      if (btn === 'yes') {
                        combo.setValue(status.id);
                      }
                    }, this).setIcon(Ext.MessageBox.QUESTION);
                    return false;
                  }
                }
              }, {
                xtype: 'checkbox',
                hideLabel: true,
                boxLabel: this.app.i18n._('non-blocking'),
                name: 'transp',
                requiredGrant: 'editGrant',
                getValue: function getValue() {
                  var bool = Ext.form.Checkbox.prototype.getValue.call(this);
                  return bool ? 'TRANSPARENT' : 'OPAQUE';
                },
                setValue: function setValue(value) {
                  var bool = value == 'TRANSPARENT' || value === true;
                  return Ext.form.Checkbox.prototype.setValue.call(this, bool);
                }
              }, Ext.apply(this.perspectiveCombo.getAttendeeTranspField(), {
                hideLabel: true
              }), {
                xtype: 'checkbox',
                hideLabel: true,
                boxLabel: this.app.i18n._('Private'),
                name: 'class',
                requiredGrant: 'editGrant',
                getValue: function getValue() {
                  var bool = Ext.form.Checkbox.prototype.getValue.call(this);
                  return bool ? 'PRIVATE' : 'PUBLIC';
                },
                setValue: function setValue(value) {
                  var bool = value == 'PRIVATE' || value === true;
                  return Ext.form.Checkbox.prototype.setValue.call(this, bool);
                }
              }, Ext.apply(this.perspectiveCombo.getAttendeeStatusField(), {
                width: 115,
                hideLabel: true
              })]
            }]
          }, {
            xtype: 'tabpanel',
            deferredRender: false,
            activeTab: 0,
            border: false,
            height: 235,
            form: true,
            items: [this.attendeeGridPanel, this.rrulePanel, this.alarmPanel].concat(Tine.Tinebase.appMgr.get('Calendar').featureEnabled('featurePolls') ? this.pollPanel : [])
          }]
        }, {
          // activities and tags
          region: 'east',
          layout: 'ux.multiaccordion',
          animate: true,
          width: 200,
          split: true,
          collapsible: true,
          collapseMode: 'mini',
          header: false,
          margins: '0 5 0 5',
          border: true,
          items: [new Ext.Panel({
            // @todo generalise!
            title: this.app.i18n._('Description'),
            iconCls: 'descriptionIcon',
            layout: 'form',
            labelAlign: 'top',
            border: false,
            items: [{
              hideLabel: true,
              xtype: 'textfield',
              width: '100%',
              itemCls: 'cal-urlfield',
              name: 'url',
              emptyText: this.app.i18n._('URL'),
              requiredGrant: 'editGrant'
            }, {
              style: 'margin-top: -4px; border 0px;',
              labelSeparator: '',
              xtype: 'textarea',
              name: 'description',
              hideLabel: true,
              grow: false,
              preventScrollbars: false,
              anchor: '100% 100%',
              emptyText: this.app.i18n._('Enter description'),
              requiredGrant: 'editGrant'
            }]
          }), new Tine.widgets.tags.TagPanel({
            app: 'Calendar',
            border: false,
            bodyStyle: 'border:1px solid #B5B8C8;'
          })]
        }]
      }, new Tine.widgets.activities.ActivitiesTabPanel({
        app: this.appName,
        record_id: this.record ? this.record.id : '',
        record_model: this.appName + '_Model_' + this.recordClass.getMeta('modelName'),
        getRecordId: function () {
          return this.record.isRecurInstance() ? this.record.get('base_event_id') : this.record.get('id');
        }.createDelegate(this)
      })]
    };
  },
  onFreeTimeSearch: function onFreeTimeSearch() {
    this.onRecordUpdate();
    Tine.Calendar.FreeTimeSearchDialog.openWindow({
      record: this.record,
      listeners: {
        scope: this,
        apply: this.onFreeTimeSearchApply
      }
    });
  },
  onFreeTimeSearchApply: function onFreeTimeSearchApply(dialog, recordData) {
    this.record = this.recordProxy.recordReader({
      responseText: recordData
    });
    this.onRecordLoad();
  },

  /**
   * mute first alert
   * 
   * @param {} button
   * @param {} e
   */
  onMuteNotificationOnce: function onMuteNotificationOnce(button, e) {
    this.record.set('mute', button.pressed);
    button.setText(Tine.Tinebase.appMgr.get('Calendar').i18n._(button.pressed ? 'Notifications are disabled' : 'Notifications are enabled'));
  },
  onPrint: function onPrint(printMode) {
    this.onRecordUpdate();
    var renderer = new Tine.Calendar.Printer.EventRenderer();
    renderer.print(this);
  },
  initComponent: function initComponent() {
    this.addEvents(
    /**
     * @event dtStartChange
     * @desc  Fired when dtstart chages in UI
     * @param {Json String} oldValue, newValue
     */
    'dtStartChange');
    this.recordProxy = new Tine.Calendar.Model.EventJsonBackend({
      saveRecord: this.saveEvent.createDelegate(this)
    });
    this.action_freeTimeSearch = new Ext.Action({
      text: Tine.Tinebase.appMgr.get('Calendar').i18n._('Free Time Search'),
      handler: this.onFreeTimeSearch,
      iconCls: 'cal-action_fretimesearch',
      disabled: false,
      scope: this
    });
    this.button_muteNotification = new Ext.Button(new Ext.Action({
      text: Tine.Tinebase.appMgr.get('Calendar').i18n._('Notifications are enabled'),
      handler: this.onMuteNotificationOnce,
      iconCls: 'action_mute_noteification',
      disabled: false,
      scope: this,
      enableToggle: true
    }));
    this.tbarItems = [new Ext.Button(this.action_freeTimeSearch), this.button_muteNotification, new Ext.Button(new Ext.Action({
      text: Tine.Tinebase.appMgr.get('Calendar').i18n._('Print Event'),
      handler: this.onPrint,
      iconCls: 'action_print',
      disabled: false,
      scope: this
    }))];
    var organizerCombo;
    this.attendeeGridPanel = new Tine.Calendar.AttendeeGridPanel({
      editDialog: this,
      bbar: [{
        xtype: 'label',
        html: Tine.Tinebase.appMgr.get('Calendar').i18n._('Organizer') + "&nbsp;"
      }, organizerCombo = Tine.widgets.form.RecordPickerManager.get('Addressbook', 'Contact', {
        width: 300,
        name: 'organizer',
        userOnly: true,
        getValue: function getValue() {
          var id = Tine.Addressbook.SearchCombo.prototype.getValue.apply(this, arguments),
              record = this.store.getById(id);
          return record ? record.data : id;
        }
      })]
    }); // auto location

    this.attendeeGridPanel.on('afteredit', function (o) {
      if (o.field == 'user_id' && o.record.get('user_type') == 'resource') {
        var typeId = _.get(o.record, 'data.user_id.type'),
            type = Tine.Tinebase.widgets.keyfield.StoreMgr.get('Calendar', 'resourceTypes').getById(typeId);

        if (type === null || type === void 0 ? void 0 : type.get('is_location')) {
          const locationField = this.getForm().findField('location');

          if (!locationField.getValue()) {
            locationField.setValue(this.attendeeGridPanel.renderAttenderResourceName(o.record.get('user_id'), {
              noIcon: true
            }));
          }

          var relations = _.get(o.record, 'data.user_id.relations'),
              locationId = relations ? _.findIndex(relations, function (k) {
            return k.type == 'LOCATION';
          }) : -1,
              locationContact = locationId >= 0 ? relations[locationId].related_record : null;

          if (locationContact) {
            if (locationContact.preferred_address == 0) {
              this.record.set('adr_lon', locationContact.adr_one_lon);
              this.record.set('adr_lat', locationContact.adr_one_lat);
            } else {
              this.record.set('adr_lon', locationContact.adr_two_lon);
              this.record.set('adr_lat', locationContact.adr_two_lat);
            }
          }
        }
      }

      this.checkStates();
    }, this);
    this.attendeeGridPanel.store.on('remove', function (store, record, idx) {
      //remove location if location is location from deleted ressource
      var typeId = _.get(record, 'data.user_id.type'),
          type = Tine.Tinebase.widgets.keyfield.StoreMgr.get('Calendar', 'resourceTypes').getById(typeId),
          locationName = this.attendeeGridPanel.renderAttenderResourceName(record.get('user_id'), {
        noIcon: true
      }),
          locationField = this.getForm().findField('location');

      if ((type === null || type === void 0 ? void 0 : type.get('is_location')) && locationName === locationField.getValue()) {
        locationField.setValue('');
      }
    }, this);
    this.on('render', function () {
      this.getForm().add(organizerCombo);
    }, this);
    this.pollPanel = new Tine.Calendar.PollPanel({
      editDialog: this
    });
    this.rrulePanel = new Tine.Calendar.RrulePanel({
      eventEditDialog: this
    });
    this.alarmPanel = new Tine.widgets.dialog.AlarmPanel({});
    this.attendeeStore = this.attendeeGridPanel.getStore();
    this.attendeeStore.on('add', this.onAttendeeStoreChange, this);
    this.attendeeStore.on('clear', this.onAttendeeStoreChange, this);
    this.attendeeStore.on('load', this.onAttendeeStoreChange, this);
    this.attendeeStore.on('datachanged', this.onAttendeeStoreChange, this);
    this.attendeeStore.on('remove', this.onAttendeeStoreChange, this); // a combo with all attendee + origin/organizer

    this.perspectiveCombo = new Tine.Calendar.PerspectiveCombo({
      editDialog: this
    });
    Tine.Calendar.EventEditDialog.superclass.initComponent.call(this);
    this.addAttendee();
  },

  /**
   * if this addRelations is set, iterate and create attendee
   */
  addAttendee: function addAttendee() {
    var attendee = this.record.get('attendee');
    var attendee = Ext.isArray(attendee) ? attendee : [];

    if (Ext.isArray(this.plugins)) {
      for (var index = 0; index < this.plugins.length; index++) {
        if (this.plugins[index].hasOwnProperty('addRelations')) {
          var config = this.plugins[index].hasOwnProperty('relationConfig') ? this.plugins[index].relationConfig : {};

          for (var index2 = 0; index2 < this.plugins[index].addRelations.length; index2++) {
            var item = this.plugins[index].addRelations[index2];
            var attender = Ext.apply({
              user_type: 'user',
              role: 'REQ',
              quantity: 1,
              status: 'NEEDS-ACTION',
              user_id: item
            }, config);
            attendee.push(attender);
          }
        }
      }
    }

    this.record.set('attendee', attendee);
  },

  /**
   * checks if form data is valid
   * 
   * @return {Boolean}
   */
  isValid: function isValid() {
    var isValid = this.validateDtStart() && this.validateDtEnd();

    if (!this.rrulePanel.isValid()) {
      isValid = false;
      this.rrulePanel.ownerCt.setActiveTab(this.rrulePanel);
    }

    return isValid && Tine.Calendar.EventEditDialog.superclass.isValid.apply(this, arguments);
  },
  onAllDayChange: function onAllDayChange(checkbox, isChecked) {
    var dtStartField = this.getForm().findField('dtstart');
    var dtEndField = this.getForm().findField('dtend');
    dtStartField.setDisabled(isChecked, 'time');
    dtEndField.setDisabled(isChecked, 'time');

    if (isChecked) {
      dtStartField.clearTime();
      var dtend = dtEndField.getValue();

      if (Ext.isDate(dtend) && dtend.format('H:i:s') != '23:59:59') {
        dtEndField.setValue(dtend.clearTime(true).add(Date.HOUR, 24).add(Date.SECOND, -1));
      }
    } else {
      dtStartField.undo();
      dtEndField.undo();
    }
  },
  onDtEndChange: function onDtEndChange(dtEndField, newValue, oldValue) {
    this.validateDtEnd();
  },

  /**
   * on dt start change
   * 
   * @param {} dtStartField
   * @param {} newValue
   * @param {} oldValue
   */
  onDtStartChange: function onDtStartChange(dtStartField, newValue, oldValue) {
    if (this.validateDtStart() == false) {
      return false;
    }

    if (Ext.isDate(newValue) && Ext.isDate(oldValue)) {
      var dtEndField = this.getForm().findField('dtend'),
          dtEnd = dtEndField.getValue();

      if (Ext.isDate(dtEnd) && dtEnd.format('H:i') != '23:59') {
        var duration = dtEnd.getTime() - oldValue.getTime(),
            newDtEnd = newValue.add(Date.MILLI, duration);
        dtEndField.setValue(newDtEnd);
        this.validateDtEnd();
      }
    }

    this.fireEvent('dtStartChange', Ext.util.JSON.encode({
      newValue: newValue,
      oldValue: oldValue || newValue
    }));
  },

  /**
   * copy record
   * 
   * TODO change attender status?
   */
  doCopyRecord: function doCopyRecord() {
    var _ = window.lodash; // Calendar is the only app with record based grants -> user gets edit grant for all fields when copying

    this.record.set('editGrant', true); // BUT: add Grant is container based!

    this.record.set('addGrant', _.get(this.record, 'data.container_id.account_grants.addGrant', false));
    Tine.Calendar.EventEditDialog.superclass.doCopyRecord.call(this); // remove attender ids

    Ext.each(this.record.data.attendee, function (attender) {
      delete attender.id;
    }, this);
    Tine.log.debug('Tine.Calendar.EventEditDialog::doCopyRecord() -> record:');
    Tine.log.debug(this.record);
  },

  /**
   * executed after record got updated from proxy
   */
  onRecordLoad: function onRecordLoad() {
    if (String(this.record.id).match(/new-ext-gen/)) {
      this.record.set('id', '');
    }

    this.omitCopyTitle = this.record.hasPoll();
    Tine.Calendar.EventEditDialog.superclass.onRecordLoad.call(this);
  },

  /**
   * is called after all subpanels have been loaded
   */
  onAfterRecordLoad: function onAfterRecordLoad() {
    Tine.Calendar.EventEditDialog.superclass.onAfterRecordLoad.call(this); // disable relations panel for non persistent exceptions till we have the baseEventId

    if (this.record.isRecurInstance()) {
      this.relationsPanel.setDisabled(true);
    }

    this.attendeeGridPanel.onRecordLoad(this.record);
    this.rrulePanel.onRecordLoad(this.record);
    this.alarmPanel.onRecordLoad(this.record);
    this.perspectiveCombo.loadPerspective(); // disable container selection combo if user has no right to edit

    this.containerSelect.setDisabled.defer(20, this.containerSelect, [!this.record.get('editGrant')]); // disable time selectors if this is a whole day event

    if (this.record.get('is_all_day_event')) {
      this.onAllDayChange(null, true);
    }

    this.button_muteNotification.pressed = !!+this.record.get('mute');
    this.button_muteNotification.setText(!!+this.record.get('mute') ? Tine.Tinebase.appMgr.get('Calendar').i18n._('Notifications are disabled') : Tine.Tinebase.appMgr.get('Calendar').i18n._('Notifications are enabled'));
  },

  /**
   * generic apply changes handler
   * @param {Boolean} closeWindow
   */
  onApplyChanges: function onApplyChanges(closeWindow) {
    if (this.app.featureEnabled('featureEventNotificationConfirmation') && !+this.record.get('mute')) {
      Ext.MessageBox.confirm(this.app.i18n._('Send Notification?'), this.app.i18n._('Changes to this event might send notifications. Press the button "Notifcation are enabled" to switch to "Notification are disabled"'), function (button) {
        if (button === 'yes') {
          Tine.Calendar.EventEditDialog.superclass.onApplyChanges.call(this, closeWindow);
        }
      }, this);
      return;
    } else {
      Tine.Calendar.EventEditDialog.superclass.onApplyChanges.call(this, closeWindow);
    }
  },
  onRecordUpdate: function onRecordUpdate() {
    Tine.Calendar.EventEditDialog.superclass.onRecordUpdate.apply(this, arguments);
    this.attendeeGridPanel.onRecordUpdate(this.record);
    this.rrulePanel.onRecordUpdate(this.record);
    this.alarmPanel.onRecordUpdate(this.record);
    this.perspectiveCombo.updatePerspective();
  },
  onAttendeeStoreChange: function onAttendeeStoreChange() {
    // NOTE: mind the add new attendee row!
    this.action_freeTimeSearch.setDisabled(this.attendeeStore.getCount() < 2);
  },
  setTabHeight: function setTabHeight() {
    var eventTab = this.items.first().items.first();
    var centerPanel = eventTab.items.first();
    var tabPanel = centerPanel.items.last();
    tabPanel.setHeight(centerPanel.getEl().getBottom() - tabPanel.getEl().getTop());
  },
  validateDtEnd: function validateDtEnd() {
    var dtStart = this.getForm().findField('dtstart').getValue(),
        dtEndField = this.getForm().findField('dtend'),
        dtEnd = dtEndField.getValue(),
        endTime = this.adjustTimeToUserPreference(dtEndField.getValue(), 'daysviewendtime');

    if (!Ext.isDate(dtEnd)) {
      dtEndField.markInvalid(this.app.i18n._('End date is not valid'));
      return false;
    } else if (Ext.isDate(dtStart) && dtEnd.getTime() - dtStart.getTime() <= 0) {
      dtEndField.markInvalid(this.app.i18n._('End date must be after start date'));
      return false;
    } else if (!Tine.Tinebase.configManager.get('daysviewallowallevents', 'Calendar') && this.getForm().findField('is_all_day_event').checked === false && !!Tine.Tinebase.configManager.get('daysviewcroptime', 'Calendar') && dtEnd > endTime) {
      dtEndField.markInvalid(this.app.i18n._('End time is not allowed to be after the configured time.'));
      return false;
    } else {
      dtEndField.clearInvalid();
      return true;
    }
  },

  /**
   * adjusts given date (end/start) to user preference (hours)
   * 
   * @param {Date} dateValue
   * @param {String} prefKey
   * @return {Date}
   */
  adjustTimeToUserPreference: function adjustTimeToUserPreference(dateValue, prefKey) {
    var userPreferenceDate = dateValue;
    prefs = this.app.getRegistry().get('preferences'), hour = prefs.get(prefKey).split(':')[0]; // adjust date to user preference

    userPreferenceDate.setHours(hour);
    userPreferenceDate.setMinutes(0);

    if (prefKey == 'daysviewendtime' && userPreferenceDate.format('H:i') == '00:00') {
      userPreferenceDate = userPreferenceDate.add(Date.MINUTE, -1);
    }

    return userPreferenceDate;
  },
  validateDtStart: function validateDtStart() {
    var dtStartField = this.getForm().findField('dtstart'),
        dtStart = dtStartField.getValue(),
        startTime = this.adjustTimeToUserPreference(dtStartField.getValue(), 'daysviewstarttime');

    if (!Ext.isDate(dtStart)) {
      dtStartField.markInvalid(this.app.i18n._('Start date is not valid'));
      return false;
    } else if (!Tine.Tinebase.configManager.get('daysviewallowallevents', 'Calendar') && this.getForm().findField('is_all_day_event').checked === false && !!Tine.Tinebase.configManager.get('daysviewcroptime', 'Calendar') && dtStart < startTime) {
      dtStartField.markInvalid(this.app.i18n._('Start date is not allowed to be before the configured time.'));
      return false;
    } else {
      dtStartField.clearInvalid();
      return true;
    }
  }
});
/**
 * Opens a new event edit dialog window
 * 
 * @return {Ext.ux.Window}
 */

Tine.Calendar.EventEditDialog.openWindow = function (config) {
  // record is JSON encoded here...
  var id = config.recordId ? config.recordId : 0;
  var window = Tine.WindowFactory.getWindow({
    width: 800,
    height: 505,
    name: Tine.Calendar.EventEditDialog.prototype.windowNamePrefix + id,
    contentPanelConstructor: 'Tine.Calendar.EventEditDialog',
    contentPanelConstructorConfig: config
  });
  return window;
};

/***/ }),

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

Tine.Calendar.Printer.EventRenderer = Ext.extend(Ext.ux.Printer.EditDialogRenderer, {
  stylesheetPath: 'Calendar/css/print.css',
  generateBody: function generateBody(component, data) {
    var i18n = Tine.Tinebase.appMgr.get('Calendar').i18n;
    return new Promise(function (fulfill, reject) {
      var bodyTpl = new Ext.XTemplate('<div class="cal-print-single">', '<div class="cal-print-single-logo">', '<img src="' + Tine.installLogo + '">', '</div>', '<div class="cal-print-single-summary">', '<span class="cal-print-single-label">', i18n._('Summary'), '</span>', '<span class="cal-print-single-value">{summary}</span>', '</div>', '<div class="cal-print-single-organizer">', '<span class="cal-print-single-label">', i18n._('Organizer'), '</span>', '<span class="cal-print-single-value">{values.organizer}</span>', '</div>', '<div class="cal-print-single-block-heading">', i18n._('Description'), '</div>', '<div class="cal-print-single-block">', '<div class="cal-print-single-description">{description}</div>', '</div>', // @TODO sort out css
      // new Ext.ux.Printer.TagsRenderer().generateBody(component.getForm().findField('tags').tagsPanel),
      '<div class="cal-print-single-block-heading">', i18n._('Details'), '</div>', '<div class="cal-print-single-block">', '<div class="print-single-details-row">', '<span class="cal-print-single-label">', i18n._('Location'), '</span>', '<span class="cal-print-single-value">{location}</span>', '</div>', '<div class="print-single-details-row">', '<span class="cal-print-single-label">', i18n._('Start Time'), '</span>', '<span class="cal-print-single-value">{values.dtstart}</span>', '</div>', '<div class="print-single-details-row">', '<span class="cal-print-single-label">', i18n._('End Time'), '</span>', '<span class="cal-print-single-value">{values.dtend}</span>', '</div>', // @TODO print rrule
      '{[this.customFieldRenderer(values.customfields)]}', '</div>', '<div class="cal-print-single-block-heading">', i18n._('Attendee'), '</div>', '<div class="cal-print-single-block">', '{[this.attendeeRenderer(values.attendee)]}', '</div>', '</div>', {
        attendeeRenderer: Tine.Calendar.EventDetailsPanel.prototype.attendeeRenderer,
        customFieldRenderer: function customFieldRenderer(values) {
          return Tine.widgets.customfields.Renderer.renderAll('Calendar', Tine.Calendar.Model.Event, values);
        }
      });
      fulfill(bodyTpl.apply(data));
    });
  }
});

/***/ }),

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

/*
 * Tine 2.0
 *
 * @package     Calendar
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2017 Metaways Infosystems GmbH (http://www.metaways.de)
 */
Ext.ns('Tine.Calendar');
/**
 * @namespace Tine.Calendar
 * @class Tine.Calendar.FreeTimeSearchDialog
 * @extends Ext.Panel
 */

Tine.Calendar.FreeTimeSearchDialog = Ext.extend(Ext.Panel, {
  cls: 'tw-editdialog',
  layout: 'fit',
  windowNamePrefix: 'CalFreeTimeSearchWindow_',
  optionsStateId: 'FreeTimeSearchOptions',
  canonicalName: ['', 'Calendar', 'FreeTimeSearchDialog'].join(Tine.Tinebase.CanonicalPath.separator),
  initComponent: function initComponent() {
    var _ = window.lodash;
    this.app = Tine.Tinebase.appMgr.get('Calendar');
    this.recordClass = Tine.Calendar.Model.Event;
    this.recordProxy = Tine.Calendar.backend;

    if (Ext.isString(this.record)) {
      this.record = this.recordProxy.recordReader({
        responseText: this.record
      });
    }

    var prefs = this.app.getRegistry().get('preferences');
    Ext.DatePicker.prototype.startDay = parseInt(prefs ? prefs.get('firstdayofweek') : 1, 10);
    this.store = new Ext.data.JsonStore({
      fields: Tine.Calendar.Model.Event,
      proxy: Tine.Calendar.backend,
      reader: new Ext.data.JsonReader({})
    });
    this.calendarView = new Tine.Calendar.DaysView({
      store: this.store,
      startDate: new Date(),
      numOfDays: 7,
      readOnly: true
    });
    this.calendarView.getSelectionModel().on('selectionchange', this.onViewSelectionChange, this);
    this.store.on('beforeload', this.onStoreBeforeload, this);
    this.store.on('load', this.onStoreLoad, this);
    this.detailsPanel = new Tine.Calendar.EventDetailsPanel();
    this.freeTimeSlots = [];
    this.tbar = [{
      text: this.app.i18n._('Back'),
      minWidth: 70,
      ref: '../buttonBack',
      iconCls: 'action_previous',
      scope: this,
      disabled: true,
      handler: this.onButtonBack
    }, {
      text: this.app.i18n._('Next'),
      minWidth: 70,
      ref: '../buttonNext',
      iconCls: 'action_next',
      scope: this,
      handler: this.onButtonNext
    }, '-', {
      text: this.app.i18n._('Options'),
      minWidth: 70,
      ref: '../buttonOptions',
      iconCls: 'action_options',
      scope: this,
      handler: this.onButtonOptions
    }];
    this.fbar = ['->', {
      text: i18n._('Cancel'),
      minWidth: 70,
      ref: '../buttonCancel',
      scope: this,
      handler: this.onButtonCancel,
      iconCls: 'action_cancel'
    }, {
      text: i18n._('Ok'),
      minWidth: 70,
      ref: '../buttonApply',
      scope: this,
      handler: this.onButtonApply,
      iconCls: 'action_saveAndClose'
    }];
    this.items = [{
      layout: 'border',
      border: false,
      items: [{
        region: 'center',
        layout: 'fit',
        border: false,
        items: this.calendarView
      }, {
        region: 'south',
        border: false,
        collapsible: true,
        collapseMode: 'mini',
        header: false,
        split: true,
        layout: 'fit',
        height: this.detailsPanel.defaultHeight ? this.detailsPanel.defaultHeight : 125,
        items: this.detailsPanel
      }]
    }];
    Tine.Calendar.FreeTimeSearchDialog.superclass.initComponent.call(this);
    this.constraints = Ext.state.Manager.get(this.optionsStateId, Tine.Calendar.EventFinderOptionsDialog.prototype.defaultOptions);
    this.doFreeTimeSearch();
  },
  afterRender: function afterRender() {
    Tine.Calendar.FreeTimeSearchDialog.superclass.afterRender.call(this);
    this.window.setTitle(this.app.i18n._('Free Time Search'));
    this.loadMask = new Ext.LoadMask(this.getEl(), {
      msg: this.app.i18n._("Searching for Free Time...")
    });
    this.loadMask.show.defer(100, this.loadMask);
  },
  applyOptions: function applyOptions(constraints) {
    // nothing to do
    if (Ext.encode(this.constraints) == Ext.encode(constraints)) return;
    this.constraints = constraints;
    this.doFreeTimeSearch();
  },
  doFreeTimeSearch: function doFreeTimeSearch(from) {
    if (this.loadMask) {
      this.loadMask.show();
    }

    var _ = window.lodash,
        datePart = this.record.get('dtstart').add(Date.DAY, -7).format('Y-m-d '),
        groupedConstraints = _.groupBy(_.filter(this.constraints, {
      active: true
    }), function (constraint) {
      return constraint.period.from + '-' + constraint.period.until;
    }),
        constraints = _.reduce(groupedConstraints, function (result, constraintsGroup) {
      return result.concat({
        dtstart: datePart + constraintsGroup[0].period.from,
        dtend: datePart + constraintsGroup[0].period.until,
        rrule: 'FREQ=WEEKLY;INTERVAL=1;BYDAY=' + _.map(constraintsGroup, 'id').join(',')
      });
    }, []),
        options = {
      from: from ? from : this.record.get('dtstart'),
      constraints: constraints
    };

    Tine.Calendar.searchFreeTime(this.record.data, options, this.onFreeTimeData, this);
  },
  onFreeTimeData: function onFreeTimeData(result) {
    if (result.timeSearchStopped) {
      return this.onFreeTimeSearchTimeout(result);
    }

    var _ = window.lodash,
        timing = _.get(result, 'results[0]'),
        dtStart = Date.parseDate(timing.dtstart, Date.patterns.ISO8601Long),
        from = dtStart.clearTime(true).add(Date.DAY, -1 * dtStart.getDay()).add(Date.DAY, Ext.DatePicker.prototype.startDay - (dtStart.getDay() == 0 ? 7 : 0)),
        dtEnd = Date.parseDate(timing.dtend, Date.patterns.ISO8601Long),
        until = from.add(Date.DAY, 7),
        period = {
      from: from,
      until: until
    },
        filterHash = Ext.encode(this.store.baseParams.filter);

    this.store.remove(this.record);
    this.record.set('dtstart', dtStart);
    this.record.set('dtend', dtEnd);
    this.freeTimeSlot = result; // calculate period start

    if (Ext.DatePicker.prototype.startDay) {
      from = from.add(Date.DAY, Ext.DatePicker.prototype.startDay - (dtStart.getDay() == 0 ? 7 : 0));
    }

    this.store.baseParams.filter = [{
      field: 'period',
      operator: 'within',
      value: period
    }, {
      field: 'attender',
      operator: 'in',
      value: this.record.get('attendee')
    }, {
      field: 'attender_status',
      operator: 'notin',
      value: 'DECLINED'
    }];

    if (this.record.get('id')) {
      this.store.baseParams.filter.push({
        field: 'id',
        operator: 'not',
        value: this.record.get('id')
      });
    }

    if (filterHash == Ext.encode(this.store.baseParams.filter)) {
      this.onStoreLoad();
    } else {
      this.calendarView.updatePeriod(period);
      this.store.load();
    }
  },
  onFreeTimeSearchTimeout: function onFreeTimeSearchTimeout(result) {
    var _ = window.lodash,
        dtStopped = Date.parseDate(_.get(result, 'timeSearchStopped'), Date.patterns.ISO8601Long),
        stoppedString = Tine.Tinebase.common.dateRenderer(dtStopped);
    Tine.widgets.dialog.MultiOptionsDialog.openWindow({
      title: this.app.i18n._('No Free Time found'),
      questionText: String.format(this.app.i18n._('No free timeslot could be found Until {0}. Do you want to continue?'), '<b>' + stoppedString + '</b>') + '<br><br>',
      height: 170,
      scope: this,
      options: [{
        text: this.app.i18n._('Continue'),
        name: 'continue'
      }, {
        text: this.app.i18n._('Give up'),
        name: 'giveUp'
      }],
      handler: function handler(option) {
        switch (option) {
          case 'giveUp':
            this.onButtonCancel();
            break;

          case 'continue':
            this.doFreeTimeSearch(Date.parseDate(dtStopped, Date.patterns.ISO8601Long));
            break;
        }
      }
    });
  },
  onStoreBeforeload: function onStoreBeforeload() {
    if (this.loadMask) {
      this.loadMask.show();
    }
  },
  onStoreLoad: function onStoreLoad() {
    this.store.each(function (event) {
      if (event.ui) {
        event.ui.setOpacity(0.5, 0);
      }
    }, this);
    this.store.add([this.record]);
    this.record.ui.setOpacity(1, 0); // @TODO check if event is visible and skip scrolling -> defered scrolling looks ugly
    // this.calendarView.scrollTo.defer(500, this.calendarView, [this.record.get('dtstart')]);

    this.loadMask.hide();
  },
  onViewSelectionChange: function onViewSelectionChange(sm, selections) {
    this.detailsPanel.onDetailsUpdate(sm);
  },
  onButtonBack: function onButtonBack() {
    this.onFreeTimeData(this.freeTimeSlots.pop());
    this.buttonBack.setDisabled(!this.freeTimeSlots.length);
  },
  onButtonNext: function onButtonNext() {
    this.freeTimeSlots.push(this.freeTimeSlot);
    this.doFreeTimeSearch(this.record.get('dtend'));
    this.buttonBack.enable();
  },
  onButtonOptions: function onButtonOptions() {
    Tine.Calendar.EventFinderOptionsDialog.openWindow({
      titleText: this.app.i18n._('Free Time Search Options'),
      stateId: this.optionsStateId,
      recordId: this.record.id,
      listeners: {
        scope: this,
        apply: this.onOptionsApply
      }
    });
  },
  onOptionsApply: function onOptionsApply(dialog, options) {
    this.applyOptions(Ext.decode(options));
  },
  onButtonCancel: function onButtonCancel() {
    this.fireEvent('cancel');
    this.purgeListeners();
    this.window.close();
  },
  onButtonApply: function onButtonApply() {
    this.fireEvent('apply', this, Ext.encode(this.record.data));
    this.purgeListeners();
    this.window.close();
  }
});
/**
 * Opens a new free time serach dialog window
 *
 * @return {Ext.ux.Window}
 */

Tine.Calendar.FreeTimeSearchDialog.openWindow = function (config) {
  var _ = window.lodash;

  if (!_.isString(config.record)) {
    config.record = Ext.encode(config.record.data);
  }

  return Tine.WindowFactory.getWindow({
    width: 1024,
    height: 768,
    name: Tine.Calendar.FreeTimeSearchDialog.prototype.windowNamePrefix + _.get(config, 'record.id', 0),
    contentPanelConstructor: 'Tine.Calendar.FreeTimeSearchDialog',
    contentPanelConstructorConfig: config
  });
};

/***/ }),

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

/*
 * Tine 2.0
 *
 * @package     Calendar
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2017 Metaways Infosystems GmbH (http://www.metaways.de)
 *
 */
Ext.ns('Tine.Calendar');

__webpack_require__(1808);

Tine.Calendar.PollPanel = Ext.extend(Ext.Panel, {
  /**
   * @cfg {Tine.widgets.dialog.EditDialog}
   */
  editDialog: null,
  requiredGrant: 'editGrant',

  /**
   * @property {Tine.Calendar.Model.Poll} poll
   */
  poll: null,
  canonicalName: 'PollPanel',
  xtype: 'form',
  frame: true,
  layout: 'vbox',
  layoutConfig: {
    align: 'stretch',
    pack: 'start'
  },
  statusWeightMap: ["DECLINED", "NEEDS-ACTION", "TENTATIVE", "ACCEPTED"],
  initComponent: function initComponent() {
    var _ = window.lodash,
        me = this;
    this.app = Tine.Tinebase.appMgr.get('Calendar');
    this.title = this.app.i18n._('Poll');
    this.on('activate', this.onPanelActivate, this);
    this.editDialog.on('load', this.onRecordLoad, this);
    this.editDialog.on('recordUpdate', this.onRecordUpdate, this);
    this.editDialog.on('dtStartChange', this.onMainTabDtStartChange, this);
    this.tbar = [{
      xtype: 'buttongroup',
      frame: false,
      items: [{
        xtype: 'tbbtnlockedtoggle',
        toggleGroup: 'cal-poll-panel',
        pressed: true,
        text: this.app.i18n._('Options'),
        handler: this.changeCardPanel.createDelegate(this, [0]),
        enableToggle: true
      }, {
        xtype: 'tbbtnlockedtoggle',
        toggleGroup: 'cal-poll-panel',
        ref: '../../alternativeDatesButton',
        disabled: true,
        pressed: false,
        text: this.app.i18n._('Alternative Dates'),
        handler: this.changeCardPanel.createDelegate(this, [1]),
        enableToggle: true
      }]
    }];
    this.action_setDefiniteEvent = new Ext.Action({
      text: this.app.i18n._('Set as definite event'),
      iconCls: 'cal-polls-set-definite-action',
      scope: this,
      handler: this.onSetDefiniteEvent
    });
    this.items = [{
      layout: 'card',
      ref: 'cardPanel',
      activeItem: 0,
      layoutConfig: {
        layoutOnCardChange: true,
        deferredRender: true
      },
      flex: 1,
      items: [{
        // layout: 'form',
        // frame: true,
        xtype: 'columnform',
        border: false,
        labelAlign: 'top',
        width: '100%',
        items: [[{
          xtype: 'checkbox',
          columnWidth: 0.40,
          ref: '../../../../createPollCheckbox',
          disabled: true,
          hideLabel: true,
          boxLabel: this.app.i18n._('Create Poll for this Event'),
          listeners: {
            scope: this,
            check: this.onCreatePollCheck
          }
        }, {
          xtype: 'textfield',
          columnWidth: 0.60,
          ref: '../../../../pollNameField',
          disabled: true,
          hideLabel: true,
          emptyText: this.app.i18n._('Name for poll')
        }], [{
          xtype: 'displayfield',
          columnWidth: 1,
          hideLabel: true,
          value: [this.app.i18n._("Create scheduling suggestions and pick the best alternative based on user feedback."), this.app.i18n._("Share the link below to poll for attendee status feedback.")].join(' ')
        }], [{
          // @TODO implement clipbord field (trigger field)
          xtype: 'field',
          columnWidth: 1,
          ref: '../../../../urlField',
          fieldLabel: this.app.i18n._('Public URL'),
          readOnly: true,
          anchor: '100%'
        }], [{
          xtype: 'checkbox',
          columnWidth: 0.40,
          ref: '../../../../isPasswordProtectedCheckbox',
          disabled: true,
          hideLabel: true,
          boxLabel: this.app.i18n._('Protect poll with a password'),
          listeners: {
            scope: this,
            check: this.onIsPasswordProtectedCheck
          }
        }, {
          xtype: 'textfield',
          columnWidth: 0.30,
          ref: '../../../../pollPasswordField',
          disabled: true,
          hideLabel: true
        }], [{
          xtype: 'checkbox',
          columnWidth: 1,
          ref: '../../../../isLockedPollCheckbox',
          disabled: true,
          hideLabel: true,
          boxLabel: this.app.i18n._('Only invited attendee can reply')
        }]]
      }, new Tine.widgets.grid.QuickaddGridPanel({
        ref: '../alternativeEventsGrid',
        layout: 'fit',
        border: false,
        frame: false,
        autoExpandColumn: 'info',
        quickaddMandatory: 'dtstart',
        recordClass: Tine.Calendar.Model.Event,
        store: new Tine.Tinebase.data.RecordStore({
          readOnly: true,
          autoLoad: false,
          recordClass: Tine.Calendar.Model.Event,
          proxy: Tine.Calendar.backend,
          pruneModifiedRecords: true,
          getModifiedRecords: function getModifiedRecords() {
            return window.lodash.filter(this.modified, {
              dirty: true
            });
          },
          sort: this.sortEventStore,
          sortInfo: {
            field: 'dtstart',
            direction: 'ASC'
          }
        }),
        resetAllOnNew: false,
        getContextMenuItems: function getContextMenuItems() {
          return [me.action_setDefiniteEvent];
        },
        listeners: {
          scope: this,
          afteredit: this.onAfterEventEdit,
          activate: this.onEventsGridActivate
        },
        cm: new Ext.grid.ColumnModel([{
          id: 'dtstart',
          header: this.app.i18n._('Start Date'),
          width: 200,
          dataIndex: 'dtstart',
          hideable: false,
          sortable: true,
          renderer: this.dateRenderer.createDelegate(this),
          quickaddField: new Ext.ux.form.DateTimeField({
            resetOnNew: false
          }),
          editor: new Ext.ux.form.DateTimeField({
            allowBlank: false
          })
        }, {
          id: 'info',
          header: this.app.i18n._('Info'),
          dataIndex: 'info',
          hideable: false,
          sortable: true,
          renderer: this.infoRenderer.createDelegate(this)
        }])
      })]
    }];
    this.supr().initComponent.apply(this, arguments);
  },
  dateRenderer: function dateRenderer(value, metaData, record, rowIndex, colIndex, store) {
    if (this.editDialog.record.get('id') == record.get('id')) {
      metaData.css = 'cal-pollpanel-alternativeevents-currentevent';
    }

    return value.format('l') + ', ' + Tine.Tinebase.common.dateTimeRenderer(value);
  },
  infoRenderer: function infoRenderer(value, metaData, record, rowIndex, colIndex, store) {
    var _ = window.lodash,
        attendeeStatus = _.groupBy(_.get(record, 'data.attendee', {}), 'status'),
        statusStore = store = Tine.Tinebase.widgets.keyfield.StoreMgr.get(this.app, 'attendeeStatus'),
        renderer = Tine.Tinebase.widgets.keyfield.Renderer.get(this.app, 'attendeeStatus');

    return _.map(_.reverse([].concat(Tine.Calendar.PollPanel.prototype.statusWeightMap)), function (statusId) {
      var count = _.get(attendeeStatus, statusId, []).length;

      return '<span class="cal-pollpanel-alternativeevents-statustoken">' + renderer(statusId) + '<span class="cal-pollpanel-alternativeevents-statuscount">' + count + '</span>' + '</span>';
    }).join('');
  },
  infoSortValueFn: function infoSortValueFn(event) {
    var _ = window.lodash,
        attendeeStatus = _.groupBy(_.get(event, 'data.attendee', {}), 'status');

    return _.reduce(attendeeStatus, function (result, attendee, id) {
      return result + attendee.length * Math.max(0, _.indexOf(Tine.Calendar.PollPanel.prototype.statusWeightMap, id));
    }, 0);
  },
  sortEventStore: function sortEventStore(fieldName, dir) {
    if (fieldName != 'info') {
      return Ext.data.JsonStore.prototype.sort.apply(this, arguments);
    }

    dir = this.sortToggle['info'] = (this.sortToggle['info'] || 'ASC').toggle('ASC', 'DESC');
    this.data.sort(dir, function (a, b) {
      return Tine.Calendar.PollPanel.prototype.infoSortValueFn(a) - Tine.Calendar.PollPanel.prototype.infoSortValueFn(b);
    });
    this.sortInfo = {
      field: 'info',
      direction: dir
    };
    this.fireEvent('datachanged', this);
  },
  onPanelActivate: function onPanelActivate() {
    this.editDialog.rrulePanel.onRecordUpdate(this.editDialog.record);
    this.setReadOnly(this.readOnly);
  },
  onCreatePollCheck: function onCreatePollCheck(cb, checked) {
    var pollData = null; // initialize new poll

    if (checked && !this.poll) {
      var pollId = Tine.Tinebase.data.Record.generateUID(40),
          event = this.editDialog.record;
      this.alternativeEventsGrid.store.add([new Tine.Calendar.Model.Event({
        // id: event.get('id'),
        dtstart: event.get('dtstart'),
        dtend: event.get('dtdend')
      }, event.id)]);
      this.alternativeEventsGrid.pollId = pollId;
      pollData = {
        id: pollId
      };
    }

    this.onPollLoad(pollData);
  },
  onIsPasswordProtectedCheck: function onIsPasswordProtectedCheck(cb, checked) {
    this.pollPasswordField.setDisabled(!checked);
  },
  onRecordLoad: function onRecordLoad() {
    var _ = window.lodash,
        me = this; // load poll

    me.onPollLoad(this.editDialog.record.get('poll_id'));
    this.alternativeEventsGrid.afterIsRendered().then(function () {
      // preset quickadd
      me.alternativeEventsGrid.getCols(true)[0].quickaddField.setValue(me.editDialog.record.get('dtstart'));
    });
  },
  onPollLoad: function onPollLoad(pollData) {
    var _ = window.lodash,
        me = this,
        record = me.editDialog.record,
        evalGrants = me.editDialog.evalGrants,
        isClosed = !!+_.get(pollData, 'closed', false),
        hasRequiredGrant = !evalGrants || _.get(record, record.constructor.getMeta('grantsPath') + '.' + this.requiredGrant);

    if (pollData) {
      this.poll = new Tine.Calendar.Model.Poll(pollData);
      Tine.Tinebase.common.assertComparable(this.poll.data);
    } else {
      this.poll = null;
    } // click vs. setValue!


    this.createPollCheckbox.suspendEvents();
    this.createPollCheckbox.setValue(!!this.poll);
    this.createPollCheckbox.resumeEvents();
    this.urlField.setValue(this.poll ? record.getPollUrl(this.poll.id) : '');
    this.pollNameField.setValue(this.poll ? this.poll.get('name') : '');
    this.isPasswordProtectedCheckbox.setValue(this.poll ? !!this.poll.get('password') : false);
    this.pollPasswordField.setValue(this.poll && this.poll.get('password') ? this.poll.get('password') : '');
    this.isLockedPollCheckbox.setValue(this.poll ? !!+this.poll.get('locked') : false);

    if (this.poll) {
      this.editDialog.rrulePanel.setDisabled(true);
    }

    this.setReadOnly(!hasRequiredGrant || isClosed);
  },
  setReadOnly: function setReadOnly(readOnly) {
    var hasPoll = this.createPollCheckbox.getValue(),
        isRecur = this.editDialog.record.get('rrule') || this.editDialog.record.isRecurException(),
        hasPassword = this.isPasswordProtectedCheckbox.getValue(); // NOTE: it's not possible to remove a persistent poll here
    //       -> use choose definite event

    this.createPollCheckbox.setDisabled(readOnly || this.poll || isRecur);
    this.pollNameField.setDisabled(!hasPoll || readOnly);
    this.isPasswordProtectedCheckbox.setDisabled(!hasPoll || readOnly);
    this.pollPasswordField.setDisabled(!hasPoll || !hasPassword || readOnly);
    this.isLockedPollCheckbox.setDisabled(!hasPoll || readOnly);
    this.alternativeEventsGrid.setReadOnly(!hasPoll || readOnly);
    this.alternativeDatesButton.setDisabled(!hasPoll);
    this.readOnly = readOnly;
  },
  onEventsGridActivate: function onEventsGridActivate() {
    var me = this,
        pollId = this.poll.get('id'),
        event = this.editDialog.record;

    if (!this.alternativeEventsGrid.loadMask) {
      this.alternativeEventsGrid.loadMask = new Ext.LoadMask(this.alternativeEventsGrid.getEl(), {
        msg: this.app.i18n._('loading alternative dates')
      });
    }

    if (pollId != this.alternativeEventsGrid.pollId) {
      this.alternativeEventsGrid.loadMask.show();
      Tine.Calendar.getPollEvents(this.poll.get('id')).then(function (response) {
        me.alternativeEventsGrid.store.loadData(response); // event copy

        if (!event.get('id')) {
          me.alternativeEventsGrid.store.add([new Tine.Calendar.Model.Event({
            // id: event.get('id'),
            dtstart: event.get('dtstart'),
            dtend: event.get('dtdend')
          }, event.id)]);
        }

        me.alternativeEventsGrid.pollId = pollId;
        me.alternativeEventsGrid.loadMask.hide();
      });
    }

    this.alternativeEventsGrid.setReadOnly(this.readOnly);
    this.action_setDefiniteEvent.setDisabled(this.readOnly);
  },
  onRecordUpdate: function onRecordUpdate(editDialog, record) {
    if (this.poll) {
      this.poll.set('name', this.pollNameField.getValue());
      this.poll.set('password', this.isPasswordProtectedCheckbox.getValue() ? this.pollPasswordField.getValue() : null);
      this.poll.set('locked', this.isLockedPollCheckbox.getValue());
      this.poll.set('alternative_dates', null);

      if (this.poll.get('id') == this.alternativeEventsGrid.pollId) {
        this.poll.set('alternative_dates', this.alternativeEventsGrid.getFromStoreAsArray(true));
      }

      record.set('poll_id', this.poll.data);
    }
  },
  onMainTabDtStartChange: function onMainTabDtStartChange(data) {
    var scheduling = Ext.decode(data),
        newValue = new Date(scheduling.newValue),
        oldValue = new Date(scheduling.oldValue),
        event = this.alternativeEventsGrid.store.getById(this.editDialog.record.id);

    if (event) {
      event.set('dtstart', newValue);
    }
  },
  onAfterEventEdit: function onAfterEventEdit(o) {
    if (o.field == 'dtstart' && o.record.get('id') == this.editDialog.record.get('id')) {
      var dtStartField = this.editDialog.getForm().findField('dtstart'),
          newValue = o.record.get('dtstart'),
          oldValue = o.record.modified['dtstart'];
      dtStartField.setValue(newValue);
      this.editDialog.onDtStartChange(dtStartField, newValue, oldValue);
    }
  },
  onSetDefiniteEvent: function onSetDefiniteEvent() {
    __webpack_require__(646);

    var me = this,
        ns = Tine.Calendar.eventActions.setDefiniteEventAction,
        selected = this.alternativeEventsGrid.getSelectionModel().getSelections(),
        event = selected[0],
        dlg = this.editDialog;

    if (selected.length > 1) {
      Ext.Msg.alert(this.app.i18n._('Select one Event Only'), this.app.i18n._('You need to select exactly one event as the definite event.'));
      return;
    }

    ns.confirm().then(function () {
      me.setDefiniteEventMask = new Ext.LoadMask(dlg.getEl(), {
        msg: me.app.i18n._('Setting definite event')
      });
      me.setDefiniteEventMask.show();
      return Tine.Calendar.setDefinitePollEvent(event.data);
    }).then(function (response) {
      window.postal.publish({
        channel: "thirdparty",
        topic: "data.changed"
      });
      dlg.onCancel.defer(1000, dlg);
    }).catch(function (error) {
      me.setDefiniteEventMask.hide();
    });
  },
  changeCardPanel: function changeCardPanel(idx) {
    this.cardPanel.layout.setActiveItem(idx);
  }
});

/***/ }),

/***/ 1808:
/***/ (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__(1809);
if(typeof content === 'string') content = [[module.i, content, '']];
// Prepare cssTransformation
var transform;

var options = {"hmr":true}
options.transform = transform
// add the styles to the DOM
var update = __webpack_require__(17)(content, options);
if(content.locals) module.exports = content.locals;
// Hot Module Replacement
if(false) {}

/***/ }),

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

var escape = __webpack_require__(103);
exports = module.exports = __webpack_require__(16)(false);
// imports


// module
exports.push([module.i, ".cal-polls-set-definite-action {\n    background-image:url(" + escape(__webpack_require__(641)) + ") !important;\n}\n.cal-pollpanel-alternativeevents-currentevent .x-grid3-cell-inner {\n    font-weight: bold;\n}\n\n.cal-pollpanel-alternativeevents-statustoken {\n    padding: 2px;\n    border-radius: 3px;\n    background-color: #dfe8f6;\n    margin-right: 2px;\n}\n\n.cal-pollpanel-alternativeevents-statuscount {\n    margin-left: 4px;\n    padding-left: 2px;\n    padding-right: 2px;\n    font-weight: bolder;\n    border-radius: 3px;\n    /*background-color: white;*/\n}", ""]);

// exports


/***/ }),

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

/*
 * Tine 2.0
 * 
 * @package     Calendar
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2009-2013 Metaways Infosystems GmbH (http://www.metaways.de)
 *
 */
Ext.ns('Tine.Calendar');

__webpack_require__(1811);

__webpack_require__(647);
/**
 * @namespace   Tine.Calendar
 * @class       Tine.Calendar.AttendeeGridPanel
 * @extends     Ext.grid.EditorGridPanel
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 */


Tine.Calendar.AttendeeGridPanel = Ext.extend(Ext.grid.EditorGridPanel, {
  autoExpandColumn: 'user_id',
  clicksToEdit: 1,
  enableHdMenu: false,
  canonicalName: 'AttendeeGrid',

  /**
   * @cfg defaut text for new attendee combo
   * i18n._('Click here to invite another attender...')
   */
  addNewAttendeeText: 'Click here to invite another attender...',

  /**
   * @cfg {Boolean} showGroupMemberType
   * show user_type groupmember in type selection
   */
  showMemberOfType: false,

  /**
   * @cfg {Boolean} showNamesOnly
   * true to only show types and names in the list
   */
  showNamesOnly: false,

  /**
   * @cfg {Boolean} showAttendeeRole
   * true to show roles in the list
   */
  showAttendeeRole: false,

  /**
   * @cfg {String} defaultAttendeeRole
   * attendee role for new attendee row
   */
  defaultAttendeeRole: 'REQ',

  /**
   * @cfg {Bool} requireFreeBusyGrantOnly
   *  freebusy grant is sufficient to find ressource (instead of inviteGrant)
   */
  requireFreeBusyGrantOnly: null,

  /**
   * The record currently being edited
   * 
   * @type Tine.Calendar.Model.Event
   * @property record
   */
  record: null,

  /**
   * id of current account
   * 
   * @type Number
   * @property currentAccountId
   */
  currentAccountId: null,

  /**
   * ctx menu
   * 
   * @type Ext.menu.Menu
   * @property ctxMenu
   */
  ctxMenu: null,

  /**
   * store to hold all attendee
   * 
   * @type Ext.data.Store
   * @property attendeeStore
   */
  attendeeStore: null,
  attendeeTypeCombo: null,

  /**
   * grid panel phone hook for calling attendee
   * 
   * @type Tine.Phone.AddressbookGridPanelHook
   */
  phoneHook: null,
  stateful: true,
  stateId: 'cal-attendeegridpanel',
  initComponent: function initComponent() {
    this.app = this.app ? this.app : Tine.Tinebase.appMgr.get('Calendar');
    this.currentAccountId = Tine.Tinebase.registry.get('currentAccount').accountId;
    this.title = this.hasOwnProperty('title') ? this.title : this.app.i18n._('Attendee');
    this.plugins = this.plugins || [];

    if (!this.showNamesOnly) {
      this.plugins.push(new Ext.ux.grid.GridViewMenuPlugin({}));
    }

    this.store = new Ext.data.SimpleStore({
      fields: Tine.Calendar.Model.Attender.getFieldDefinitions().concat('sort'),
      sortInfo: {
        field: 'user_id',
        direction: 'ASC'
      },
      sortData: function sortData(f, direction) {
        direction = direction || 'ASC';
        var st = this.fields.get(f).sortType;

        var fn = function fn(r1, r2) {
          // make sure new-attendee line is on the bottom
          if (!r1.data.user_id) return direction == 'ASC';
          if (!r2.data.user_id) return direction != 'ASC';
          var v1 = st(r1.data[f]),
              v2 = st(r2.data[f]);
          return v1 > v2 ? 1 : v1 < v2 ? -1 : 0;
        };

        this.data.sort(direction, fn);

        if (this.snapshot && this.snapshot != this.data) {
          this.snapshot.sort(direction, fn);
        }
      }
    });
    this.on('beforeedit', this.onBeforeAttenderEdit, this);
    this.on('afteredit', this.onAfterAttenderEdit, this);
    this.on('rowcontextmenu', this.onRowContextMenu, this);
    this.addEvents('beforenewattendee');
    this.initColumns();
    this.mon(Ext.getBody(), 'click', this.stopEditingIf, this);
    this.viewConfig = _.assign(this.viewConfig || {}, {
      getRowClass: this.getRowClass
    });
    Tine.Calendar.AttendeeGridPanel.superclass.initComponent.call(this);
    this.initPhoneGridPanelHook();
  },
  initColumns: function initColumns() {
    var attendeeTypes = new Ext.data.ArrayStore({
      fields: ['name', 'value'],
      idIndex: 0 // id for each record will be the first element

    });
    attendeeTypes.loadData([['any', '...'], ['user', this.app.i18n._('User')], ['group', this.app.i18n._('Group')], ['resource', this.app.i18n._('Resource')]].concat(this.showMemberOfType ? [['memberOf', this.app.i18n._('Member of group')]] : []));
    this.attendeeTypeCombo = new Ext.form.ComboBox({
      blurOnSelect: true,
      expandOnFocus: true,
      listWidth: 100,
      mode: 'local',
      valueField: 'name',
      displayField: 'value',
      store: attendeeTypes
    });
    this.columns = [{
      id: 'role',
      dataIndex: 'role',
      width: 70,
      sortable: true,
      hidden: !this.showAttendeeRole || this.showNamesOnly,
      header: this.app.i18n._('Role'),
      renderer: this.renderAttenderRole.createDelegate(this),
      editor: {
        xtype: 'widget-keyfieldcombo',
        app: 'Calendar',
        keyFieldName: 'attendeeRoles'
      }
    }, {
      id: 'displaycontainer_id',
      dataIndex: 'displaycontainer_id',
      width: 200,
      sortable: false,
      hidden: this.showNamesOnly || true,
      header: i18n._hidden('Saved in'),
      tooltip: this.app.i18n._('This is the calendar where the attender has saved this event in'),
      renderer: this.renderAttenderDispContainer.createDelegate(this),
      // disable for the moment, as updating calendarSelectWidget is not working in both directions
      editor2: new Tine.widgets.container.SelectionComboBox({
        blurOnSelect: true,
        selectOnFocus: true,
        appName: 'Calendar',
        getValue: function getValue() {
          if (this.selectedContainer) {
            // NOTE: the store checks if data changed. If we don't overwrite to string, 
            //  the check only sees [Object Object] wich of course never changes...
            var container_id = this.selectedContainer.id;

            this.selectedContainer.toString = function () {
              return container_id;
            };
          }

          return this.selectedContainer;
        },
        listeners: {
          scope: this,
          select: function select(field, newValue) {
            // the field is already blured, due to the extra chooser window. We need to change the value per hand
            var selection = this.getSelectionModel().getSelectedCell();

            if (selection) {
              var row = selection[0];
              this.store.getAt(row).set('displaycontainer_id', newValue);
            }
          }
        }
      })
    }, {
      id: 'user_type',
      dataIndex: 'user_type',
      width: 50,
      sortable: true,
      header: this.app.i18n._('Type'),
      tooltip: this.app.i18n._('Click icon to change'),
      renderer: this.renderAttenderType.createDelegate(this),
      editor: this.attendeeTypeCombo
    }, {
      id: 'user_id',
      dataIndex: 'user_id',
      width: 300,
      sortable: true,
      header: this.app.i18n._('Name'),
      renderer: this.renderAttenderName.createDelegate(this),
      editor: true
    }, {
      id: 'fbInfo',
      dataIndex: 'fbInfo',
      width: 20,
      hidden: this.showNamesOnly,
      header: '&nbsp',
      tooltip: this.app.i18n._('Availability of Attendee'),
      fixed: true,
      sortable: false,
      renderer: function renderer(v, m, r) {
        // NOTE: already encoded
        return r.get('user_id') ? v : '';
      }
    }, {
      id: 'status',
      dataIndex: 'status',
      width: 100,
      sortable: true,
      header: this.app.i18n._('Status'),
      hidden: this.showNamesOnly,
      renderer: this.renderAttenderStatus.createDelegate(this),
      editor: {
        xtype: 'widget-keyfieldcombo',
        app: 'Calendar',
        keyFieldName: 'attendeeStatus'
      }
    }];
  },
  onEditComplete: function onEditComplete(ed, value, startValue) {
    var _ = window.lodash,
        attendeeData = _.get(ed, 'field.selectedRecord.data.user_id'),
        type = _.get(ed, 'field.selectedRecord.data.user_type'),
        fbInfo = _.get(ed, 'field.selectedRecord.data.fbInfo'); // attendeePickerCombo


    if (attendeeData && type) {
      if (this.showMemberOfType && 'group' == type) {
        var row = ed.row,
            col = ed.col,
            selectedRecord = _.get(ed, 'field.selectedRecord');

        Tine.widgets.dialog.MultiOptionsDialog.openWindow({
          title: this.app.i18n._('Whole Group or each Member of Group'),
          questionText: this.app.i18n._('Choose "Group" to filter for the whole group itself. Choose "Member of Group" to filter for each member of the group'),
          height: 170,
          scope: this,
          options: [{
            text: this.app.i18n._('Group'),
            name: 'sel_group'
          }, {
            text: this.app.i18n._('Member of Group'),
            name: 'sel_memberOf'
          }],
          handler: function handler(option) {
            this.startEditing(row, col);
            selectedRecord.set('user_type', option);
            selectedRecord.groupType = option;
            this.activeEditor.field.selectedRecord = selectedRecord;
            this.stopEditing();
          }
        }); // abort normal flow

        value = startValue;
      } else {
        value = attendeeData;
        ed.record.set('user_type', type.replace(/^sel_/, ''));
        ed.record.set('fbInfo', fbInfo);
        ed.record.commit();
      }
    }

    Tine.Calendar.AttendeeGridPanel.superclass.onEditComplete.call(this, ed, value, startValue);
  },
  onAfterAttenderEdit: function onAfterAttenderEdit(o) {
    switch (o.field) {
      case 'user_id':
        // detect duplicate entry
        // TODO detect duplicate emails, too 
        var isDuplicate = false;
        this.store.each(function (attender) {
          if (o.record.getUserId() == attender.getUserId() && o.record.get('user_type') == attender.get('user_type') && o.record != attender) {
            attender.set('checked', true);
            var row = this.getView().getRow(this.store.indexOf(attender));
            Ext.fly(row).highlight();
            isDuplicate = true;
            return false;
          }
        }, this);

        if (isDuplicate) {
          o.record.reject();
          this.startEditing(o.row, o.column);
        } else if (o.value) {
          // set status authkey for contacts and recources so user can edit status directly
          // NOTE: we can't compute if the user has editgrant to the displaycontainer of an account here!
          //       WELL we could add the info to search attendee somehow
          if (o.record.get('user_type') == 'user' && !o.value.account_id || o.record.get('user_type') == 'resource' && o.record.get('user_id') && o.record.get('user_id').container_id && o.record.get('user_id').container_id.account_grants && o.record.get('user_id').container_id.account_grants.editGrant) {
            o.record.set('status_authkey', Tine.Tinebase.data.Record.generateUID());
          }

          o.record.explicitlyAdded = true;
          o.record.set('checked', true); // Set status if the resource has a specific default status

          if (o.record.get('user_type') == 'resource' && o.record.get('user_id') && o.record.get('user_id').status) {
            o.record.set('status', o.record.get('user_id').status);
          } // resolve groupmembers


          if (o.record.get('user_type') == 'group' && !this.showMemberOfType) {
            this.resolveListMembers(o.record.get('user_id'));
          } else {
            this.addNewAttendeeRow();
            this.startEditing(o.row + 1, o.column);
          }
        }

        break;

      case 'user_type':
        this.startEditing(o.row, this.getColumnModel().getIndexById('user_id'));
        break;

      case 'role':
        if (o.row == this.store.getCount() - 1) {
          this.setDefaultAttendeeRole(o.record.get('role'));
          this.startEditing(o.row, this.getColumnModel().getIndexById('user_id'));
        }

        break;

      case 'container_id':
        // check if displaycontainer of owner got changed
        if (o.record == this.eventOriginator) {
          this.record.set('container_id', '');
          this.record.set('container_id', o.record.get('displaycontainer_id'));
        }

        break;
    }
  },
  resolveListMembers: function resolveListMembers() {
    if (this.showMemberOfType) return;
    var _ = window.lodash,
        members = Tine.Calendar.Model.Attender.getAttendeeStore.getData(this.store),
        fbInfoUpdate = [];
    var mask = new Ext.LoadMask(this.getEl(), {
      msg: this.app.i18n._("Loading Groupmembers...")
    });
    mask.show();
    Tine.Calendar.resolveGroupMembers(members, function (attendeesData) {
      var attendees = Tine.Calendar.Model.Attender.getAttendeeStore(attendeesData); // remove not longer existing attendee

      this.store.each(function (attendee) {
        if (!Tine.Calendar.Model.Attender.getAttendeeStore.getAttenderRecord(attendees, attendee)) {
          this.store.remove(attendee);
        }
      }); // add new attendee

      attendees.each(function (attendee) {
        if (!Tine.Calendar.Model.Attender.getAttendeeStore.getAttenderRecord(this.store, attendee)) {
          attendee.set('role', this.defaultAttendeeRole);
          this.fireEvent('beforenewattendee', this, attendee, this.record);
          this.store.add([attendee]);
          fbInfoUpdate.push(attendee.id);
        }
      }, this);
      this.updateFreeBusyInfo(fbInfoUpdate);
      mask.hide();
      this.addNewAttendeeRow();
    }, this);
  },
  onBeforeAttenderEdit: function onBeforeAttenderEdit(o) {
    if (o.field == 'status') {
      // allow status setting if status authkey is present
      o.cancel = !o.record.get('status_authkey');
      return;
    }

    if (o.field == 'displaycontainer_id') {
      if (!o.value || !o.value.account_grants || !o.value.account_grants.deleteGrant) {
        o.cancel = true;
      }

      return;
    } // for all other fields user need editGrant


    if (!this.record.get('editGrant')) {
      o.cancel = true;
      return;
    } // don't allow to set anything besides quantity and role for already set attendee


    if (o.record.get('user_id')) {
      o.cancel = true;

      if (o.field == 'quantity' && o.record.get('user_type') == 'resource') {
        o.cancel = false;
      }

      if (o.field == 'role') {
        o.cancel = false;
      }

      return;
    }

    if (o.field == 'user_id') {
      // switch editor
      var colModel = o.grid.getColumnModel(),
          type = o.record.get('user_type');
      type = type == 'memberOf' ? 'group' : type;
      var attendeePickerCombo = new Tine.Calendar.AttendeePickerCombo({
        minListWidth: 370,
        blurOnSelect: true,
        eventRecord: this.record,
        requireFreeBusyGrantOnly: this.requireFreeBusyGrantOnly,
        additionalFilters: type != 'any' ? [{
          field: 'type',
          operator: 'oneof',
          value: [type]
        }] : null
      });
      this.fireEvent('beforenewattendeepickercombo', this, attendeePickerCombo, o);
      colModel.config[o.column].setEditor(attendeePickerCombo);
      colModel.config[o.column].editor.selectedRecord = null;
    }
  },

  /**
   * give new attendee an extra cls
   */
  getRowClass: function getRowClass(record, index) {
    if (!record.get('user_id')) {
      return 'x-cal-add-attendee-row';
    }
  },

  /**
   * stop editing if user clicks else where
   * 
   * FIXME this breaks the paging in search combos, maybe we should check if search combo paging buttons are clicked, too
   */
  stopEditingIf: function stopEditingIf(e) {
    if (!e.within(this.getGridEl())) {//this.stopEditing();
    }
  },
  onBeforeRemoveAttendee: function onBeforeRemoveAttendee() {
    return true;
  },
  onRowContextMenu: function onRowContextMenu(grid, row, e) {
    e.stopEvent();
    var me = this,
        attender = this.store.getAt(row),
        type = attender.get('user_type');

    if (attender && !this.disabled) {
      // don't delete 'add' row
      var attender = this.store.getAt(row);

      if (!attender.get('user_id')) {
        return;
      } // select name cell


      if (Ext.isFunction(this.getSelectionModel().select)) {
        this.getSelectionModel().select(row, 3);
      } else {
        // west panel attendee filter grid
        this.getSelectionModel().selectRow(row);
      }

      Tine.log.debug('onContextMenu - attender:');
      Tine.log.debug(attender);
      var items = [{
        text: this.app.i18n._('Remove Attender'),
        iconCls: 'action_delete',
        scope: this,
        disabled: !this.record.get('editGrant') || type == 'groupmember',
        handler: function handler() {
          if (this.onBeforeRemoveAttendee(attender, type) === false) {
            return false;
          }

          this.store.remove(attender);

          if (type == 'group' && !this.showMemberOfType) {
            this.resolveListMembers();
          }
        }
      }, {
        text: this.app.i18n._('Use as event location'),
        iconCls: 'action_export',
        scope: this,
        disabled: !this.record.get('editGrant'),
        handler: function handler() {
          var _attender, _attender$data;

          const locationField = this.editDialog.getForm().findField('location');
          const attendeeName = this.renderAttenderName((_attender = attender) === null || _attender === void 0 ? void 0 : (_attender$data = _attender.data) === null || _attender$data === void 0 ? void 0 : _attender$data.user_id, {
            noIcon: true
          }, attender);
          locationField.setValue(attendeeName);
        }
      }, '-'];
      var felamimailApp = Tine.Tinebase.appMgr.get('Felamimail');

      if (felamimailApp && attender.get('user_type') == 'user') {
        Tine.log.debug('Adding email compose hook for attender');
        items = items.concat(new Ext.Action({
          text: felamimailApp.i18n._('Compose email'),
          iconCls: felamimailApp.getIconCls(),
          disabled: false,
          scope: this,
          handler: function handler() {
            var _ = window.lodash;
            var email = Tine.Felamimail.getEmailStringFromContact(new Tine.Addressbook.Model.Contact(attender.get('user_id')));
            var record = new Tine.Felamimail.Model.Message({
              subject: _.get(this.record, 'data.poll.name', _.get(this.record, 'data.summary', ''), ''),
              body: this.record.hasPoll() ? String.format(this.app.i18n._('Poll URL: {0}'), this.record.getPollUrl()) : '',
              massMailingFlag: this.record.hasPoll(),
              to: [email]
            }, 0);
            var popupWindow = Tine.Felamimail.MessageEditDialog.openWindow({
              record: record
            });
          }
        }));
      }

      if (attender.get('user_type') == 'resource') {
        Tine.log.debug('Adding resource hook for attender');
        var resourceId = attender.get('user_id').id,
            resource = new Tine.Calendar.Model.Resource(attender.get('user_id'), resourceId),
            grants = lodash.get(resource, 'data.container_id.account_grants', {});
        items = items.concat(new Ext.Action({
          text: grants.resourceEditGrant || Tine.Tinebase.common.hasRight('manage', 'Calendar', 'resources') ? this.app.i18n._('Edit Resource') : this.app.i18n._('View Resource'),
          iconCls: 'cal-resource',
          scope: this,
          handler: function handler() {
            Tine.Calendar.ResourceEditDialog.openWindow({
              record: resource
            });
          }
        }));
        var exportAction = Tine.widgets.exportAction.getExportButton(Tine.Calendar.Model.Resource, {
          getExportOptions: function getExportOptions() {
            var options = {
              recordData: attender.get('user_id')
            }; // do we have a 'real' event?

            if (me.record.data.dtstart) {
              options.additionalRecords = {
                Event: {
                  model: 'Calendar_Model_Event',
                  recordData: me.record.data
                }
              };
            }

            return options;
          }
        }, Tine.widgets.exportAction.SCOPE_SINGLE);
        items = items.concat(exportAction);
      }

      var plugins = [{
        ptype: 'ux.itemregistry',
        key: 'Attendee-GridPanel-ContextMenu'
      }, {
        ptype: 'ux.itemregistry',
        key: 'Tinebase-MainContextMenu'
      }]; // add phone call action via item registry

      if (this.phoneHook && attender.get('user_type') == 'user') {
        var contact = new Tine.Addressbook.Model.Contact(attender.get('user_id'));
        this.phoneHook.setContactAndUpdateAction(contact);
      }

      Tine.log.debug(items);
      this.ctxMenu = new Ext.menu.Menu({
        items: items,
        plugins: plugins,
        listeners: {
          scope: this,
          hide: function hide() {
            this.getSelectionModel().clearSelections();
          }
        }
      });
      var actionUpdater = new Tine.widgets.ActionUpdater({
        evalGrants: false
      });
      actionUpdater.addAction(exportAction);
      actionUpdater.updateActions([resource]);
      this.ctxMenu.showAt(e.getXY());
    }
  },

  /**
   * init phone grid panel hook if Phone app is available
   */
  initPhoneGridPanelHook: function initPhoneGridPanelHook() {
    var phoneApp = Tine.Tinebase.appMgr.get('Phone');

    if (phoneApp) {
      Tine.log.debug('Adding Phone call hook');
      this.phoneHook = new Tine.Phone.AddressbookGridPanelHook({
        app: phoneApp,
        keyPrefix: 'Attendee',
        useActionUpdater: false
      });
    }
  },

  /**
   * loads this panel with data from given record
   * called by edit dialog when record is loaded
   * 
   * @param {Tine.Calendar.Model.Event} record
   * @param Array addAttendee
   */
  onRecordLoad: function onRecordLoad(record) {
    this.record = record;
    this.store.removeAll();
    var attendee = record.get('attendee'),
        resolveListMembers = false;
    Ext.each(attendee, function (attender) {
      var record = new Tine.Calendar.Model.Attender(attender, attender.id);
      this.store.addSorted(record);

      if (attender.displaycontainer_id && this.record.get('container_id') && attender.displaycontainer_id.id == this.record.get('container_id').id) {
        this.eventOriginator = record;
      }

      if (String(record.get('user_type')).match(/^group/)) {
        resolveListMembers = true;
      }
    }, this);
    this.updateFreeBusyInfo();

    if (resolveListMembers) {
      this.resolveListMembers();
    } else if (record.get('editGrant')) {
      this.addNewAttendeeRow();
    }
  },
  updateFreeBusyInfo: function updateFreeBusyInfo(force) {
    if (this.showMemberOfType) return;
    var _ = window.lodash,
        schedulingInfo = this.record.getSchedulingData(),
        encodedSchedulingInfo = Ext.encode(schedulingInfo);

    if (encodedSchedulingInfo == this.encodedSchedulingInfo && !force) {
      return;
    }

    if (!schedulingInfo.dtend || !schedulingInfo.dtstart) {
      // dtend & dtstart are required
      return;
    } // @TODO have load spinner?


    this.encodedSchedulingInfo = encodedSchedulingInfo; // clear state

    this.store.each(function (attendee) {
      if (Ext.isArray(force) && force.indexOf(attendee.id) < 0) {
        return;
      }

      attendee.set('fbInfo', '...');
      attendee.commit();
    }, this);
    Tine.Calendar.getFreeBusyInfo(Tine.Calendar.Model.Attender.getAttendeeStore.getData(this.store), [schedulingInfo], [this.record.get('uid')], function (freeBusyData) {
      // outdated data
      if (encodedSchedulingInfo != this.encodedSchedulingInfo) return;
      var fbInfo = new Tine.Calendar.FreeBusyInfo(_.values(freeBusyData)[0]);
      this.store.each(function (attendee) {
        attendee.set('fbInfo', fbInfo.getStateOfAttendee(attendee, this.record));
        attendee.commit();
      }, this);
    }, this);
  },
  // Add new attendee
  addNewAttendeeRow: function addNewAttendeeRow() {
    this.newAttendee = new Tine.Calendar.Model.Attender(Tine.Calendar.Model.Attender.getDefaultData(), 'new-' + Ext.id());
    this.newAttendee.set('role', this.defaultAttendeeRole);
    this.fireEvent('beforenewattendee', this, this.newAttendee, this.record);
    this.store.add([this.newAttendee]);
  },
  setDefaultAttendeeRole: function setDefaultAttendeeRole(role) {
    this.defaultAttendeeRole = role;

    if (this.newAttendee) {
      this.newAttendee.set('role', role);
    }
  },

  /**
   * Updates given record with data from this panel
   * called by edit dialog to get data
   * 
   * @param {Tine.Calendar.Model.Event} record
   */
  onRecordUpdate: function onRecordUpdate(record) {
    this.stopEditing(false);
    this.updateFreeBusyInfo();
    Tine.Calendar.Model.Attender.getAttendeeStore.getData(this.store, record);
  },
  onKeyDown: function onKeyDown(e) {
    switch (e.getKey()) {
      case e.DELETE:
        if (this.record.get('editGrant')) {
          var selection = this.getSelectionModel().getSelectedCell();

          if (selection) {
            var row = selection[0]; // don't delete 'add' row

            var attender = this.store.getAt(row);

            if (!attender.get('user_id')) {
              return;
            }

            this.store.removeAt(row);
          }
        }

        break;
    }
  },
  renderAttenderName: function renderAttenderName(name, metaData, record) {
    if (name) {
      var type = record ? record.get('user_type') : 'user',
          fn = this['renderAttender' + Ext.util.Format.capitalize(type) + 'Name'];
      return fn ? fn.apply(this, arguments) : '';
    } // add new user:


    if (arguments[1]) {
      arguments[1].css = 'x-form-empty-field';
      return this.app.i18n._(this.addNewAttendeeText);
    }
  },

  /**
   * render attender user name
   *
   * @param name
   * @returns {*}
   */
  renderAttenderUserName: function renderAttenderUserName(name) {
    name = name || "";
    var result = "",
        email = "";

    if (typeof name.get == 'function' && name.get('n_fileas')) {
      result = name.get('n_fileas');
    } else if (name.n_fileas) {
      result = name.n_fileas;
    } else if (name.accountDisplayName) {
      result = name.accountDisplayName;
    } else if (Ext.isString(name) && !name.match('^[0-9a-f-]{40,}$') && !parseInt(name, 10)) {
      // how to detect hash/string ids
      result = name;
    } // add email address if available
    // need to create a "dummy" app to call featureEnabled()
    // TODO: should be improved


    var tinebaseApp = new Tine.Tinebase.Application({
      appName: 'Tinebase'
    });

    if (tinebaseApp.featureEnabled('featureShowAccountEmail')) {
      if (typeof name.getPreferredEmail == 'function') {
        email = name.getPreferredEmail();
      } else if (name.email) {
        email = name.email;
      } else if (name.accountEmailAddress) {
        email = name.accountEmailAddress;
      }

      if (email !== '') {
        result += ' (' + email + ')';
      }
    }

    if (result === '') {
      result = Tine.Tinebase.appMgr.get('Calendar').i18n._('No Information');
    } else {
      result = Ext.util.Format.htmlEncode(result);
    } // NOTE: this fn gets also called from other scopes


    return result;
  },
  renderAttenderGroupmemberName: function renderAttenderGroupmemberName(name) {
    var name = Tine.Calendar.AttendeeGridPanel.prototype.renderAttenderUserName.apply(this, arguments);
    return name + ' ' + Tine.Tinebase.appMgr.get('Calendar').i18n._('(as a group member)');
  },
  renderAttenderGroupName: function renderAttenderGroupName(name) {
    if (typeof name.getTitle == 'function') {
      return Ext.util.Format.htmlEncode(name.getTitle());
    }

    if (name.name) {
      return Ext.util.Format.htmlEncode(name.name);
    }

    if (Ext.isString(name)) {
      return Ext.util.Format.htmlEncode(name);
    }

    return Tine.Tinebase.appMgr.get('Calendar').i18n._('No Information');
  },
  renderAttenderMemberofName: function renderAttenderMemberofName(name) {
    return Tine.Calendar.AttendeeGridPanel.prototype.renderAttenderGroupName.apply(this, arguments);
  },
  renderAttenderResourceName: function renderAttenderResourceName(name, metadata) {
    var icon = metadata && metadata.noIcon ? '' : this.renderAttenderResourceIcon(name),
        displayName = Ext.isString(name) ? name : Ext.isFunction(name.getTitle) ? name.getTitle() : name.name ? name.name : Tine.Tinebase.appMgr.get('Calendar').i18n._('No Information');
    return icon + Ext.util.Format.htmlEncode(displayName);
  },
  renderAttenderResourceIcon: function renderAttenderResourceIcon(name) {
    try {
      var ResourceId = name.type,
          icon = Tine.Tinebase.widgets.keyfield.StoreMgr.get('Calendar', 'resourceTypes').getById(ResourceId).get('icon');
      return '<img class="tine-keyfield-icon" src="' + icon + '"/>';
    } catch (e) {}

    return '';
  },
  renderAttenderDispContainer: function renderAttenderDispContainer(displaycontainer_id, metadata, attender) {
    metadata.attr = 'style = "overflow: none;"';

    if (displaycontainer_id) {
      if (displaycontainer_id.name) {
        return Ext.util.Format.htmlEncode(displaycontainer_id.name).replace(/ /g, "&nbsp;");
      } else {
        metadata.css = 'x-form-empty-field';
        return this.app.i18n._('No Information');
      }
    }
  },
  renderAttenderQuantity: function renderAttenderQuantity(quantity, metadata, attender) {
    return quantity > 1 ? quantity : '';
  },
  renderAttenderRole: function renderAttenderRole(role, metadata, attender) {
    var i18n = Tine.Tinebase.appMgr.get('Calendar').i18n,
        renderer = Tine.widgets.grid.RendererManager.get('Calendar', 'Attender', 'role', Tine.widgets.grid.RendererManager.CATEGORY_GRIDPANEL);

    if (this.record && this.record.get('editGrant')) {
      metadata.attr = 'style = "cursor:pointer;"';
    } else {
      metadata.css = 'x-form-empty-field';
    }

    return renderer(role);
  },
  renderAttenderStatus: function renderAttenderStatus(status, metadata, attender) {
    var i18n = Tine.Tinebase.appMgr.get('Calendar').i18n,
        renderer = Tine.widgets.grid.RendererManager.get('Calendar', 'Attender', 'status', Tine.widgets.grid.RendererManager.CATEGORY_GRIDPANEL);

    if (!attender.get('user_id')) {
      return '';
    }

    if (attender.get('status_authkey')) {
      metadata.attr = 'style = "cursor:pointer;"';
    } else {
      metadata.css = 'x-form-empty-field';
    }

    return renderer(status);
  },
  renderAttenderType: function renderAttenderType(type, metadata, attender) {
    metadata.css = 'tine-grid-cell-no-dirty';
    var cssClass = 'tine-grid-row-action-icon ',
        qtipText = '',
        userId = attender.get('user_id'),
        hasAccount = userId && (userId.get && userId.get('account_id') || userId.account_id);

    switch (type) {
      case 'user':
        cssClass += hasAccount || !userId ? 'renderer_typeAccountIcon' : 'renderer_typeContactIcon';
        qtipText = hasAccount || !userId ? '' : Tine.Tinebase.appMgr.get('Calendar').i18n._('External Attendee');
        break;

      case 'group':
        cssClass += 'renderer_accountGroupIcon';
        break;

      default:
        cssClass += 'cal-attendee-type-' + type;
        break;
    }

    var qtip = qtipText ? 'ext:qtip="' + Tine.Tinebase.common.doubleEncode(qtipText) + '" ' : '';
    var result = '<div ' + qtip + 'style="background-position:0px;" class="' + cssClass + '">&#160</div>';

    if (!attender.get('user_id')) {
      result = Tine.Tinebase.common.cellEditorHintRenderer(result);
    }

    return result;
  },

  /**
   * disable contents not panel
   */
  setDisabled: function setDisabled(v) {
    if (v) {
      // remove "add new attender" row
      this.store.filterBy(function (r) {
        return !(r.id && r.id.match(/^new-/));
      });
    } else {
      this.store.clearFilter();
    }
  }
});

/***/ }),

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

/*
 * Tine 2.0
 *
 * @package     Calendar
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2017 Metaways Infosystems GmbH (http://www.metaways.de)
 *
 */
Ext.ns('Tine.Calendar');

__webpack_require__(647);

__webpack_require__(1812);
/**
 * @namespace   Tine.Calendar
 * @class       Tine.Calendar.AttendeePickerCombo
 * @extends     Tine.Tinebase.widgets.form.RecordPickerComboBox
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 */


Tine.Calendar.AttendeePickerCombo = Ext.extend(Tine.Tinebase.widgets.form.RecordPickerComboBox, {
  /**
   * @cfg {} eventRecord
   * reference to event record. If set scheduling info for freebusy info will be taken from it
   */
  eventRecord: null,

  /**
   * @cfg {Bool} requireFreeBusyGrantOnly
   * freebusy grant is sufficient to find ressource (instead of inviteGrant)
   */
  requireFreeBusyGrantOnly: false,

  /**
   * @property {Tine.Calendar.Model.AttenderProxy} recordProxy
   */
  recordProxy: null,
  recordClass: Tine.Calendar.Model.Attender,
  itemSelector: '.cal-attendee-picker-combo-list-item',
  initComponent: function initComponent() {
    _ = window.lodash;
    this.typeTemplates = {};
    this.recordProxy = new Tine.Calendar.Model.AttenderProxy({
      freeBusyEventsProvider: _.bind(function () {
        return [this.eventRecord];
      }, this)
    });
    Tine.Calendar.AttendeePickerCombo.superclass.initComponent.call(this);
  },

  /**
   * prepare paging and sort
   *
   * @param {Ext.data.Store} store
   * @param {Object} options
   */
  onBeforeLoad: function onBeforeLoad(store, options) {
    Tine.Calendar.AttendeePickerCombo.superclass.onBeforeLoad.call(this, store, options);

    if (this.requireFreeBusyGrantOnly) {
      this.store.baseParams.filter.push({
        field: 'resourceFilter',
        value: [{
          field: 'requireFreeBusyGrant',
          value: 1
        }]
      });
    }
  },

  /**
   * create bogus attendee record for directly entered email-addresses
   */
  getValue: function getValue() {
    if (this.el.dom) {
      var raw = _.get(this, 'el.dom') ? this.getRawValue() : Ext.value(this.value, '');

      if (Ext.form.VTypes.email(raw)) {
        this.value = raw;
        this.selectedRecord = new Tine.Calendar.Model.Attender(Ext.apply(Tine.Calendar.Model.Attender.getDefaultData(), {
          'user_type': 'user',
          'user_id': this.value
        }));
      }
    }

    return Tine.Calendar.AttendeePickerCombo.superclass.getValue.apply(this, arguments);
  },

  /**
   * respect record.getTitle method
   */
  initTemplate: function initTemplate() {
    if (!this.tpl) {
      this.tpl = new Ext.XTemplate('<tpl for=".">', '<div class="cal-attendee-picker-combo-list-item">', '<table>', '<tr>', '<td width="100%">{[this.getAttendeeItem(values.' + this.recordClass.getMeta('idProperty') + ')]}</td>', '<td style="min-width: 20px;" class="cal-attendee-picker-combo-list-item-fbinfo">{values.fbInfo}</td>', '</tr>', '</table>', '</div>', '</tpl>', this);
    }
  },
  getAttendeeItem: function getAttendeeItem(id) {
    var record = this.getStore().getById(id),
        type = record.get('user_type'),
        template = this.getTemplate(type);
    return template.apply([record.get('user_id')]);
  },
  getTemplate: function getTemplate(type) {
    if (!this.typeTemplates[type]) {
      var p,
          o = {
        getLastQuery: this.getLastQuery.createDelegate(this)
      };

      switch (type) {
        case 'user':
          p = Tine.Addressbook.ContactSearchCombo.prototype;
          break;

        case 'group':
          p = Tine.Addressbook.ListSearchCombo.prototype;
          break;

        case 'resource':
          p = Tine.Calendar.ResourcePickerCombo.prototype;
          break;
      }

      p.initTemplate.call(o);
      this.typeTemplates[type] = o.tpl;
    }

    return this.typeTemplates[type];
  }
});

/***/ }),

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

/*
 * Tine 2.0
 *
 * @package     Calendar
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2017 Metaways Infosystems GmbH (http://www.metaways.de)
 *
 */
Ext.ns('Tine.Calendar');
/**
 *
 * @param freeBusyInfo
 * @constructor
 */

Tine.Calendar.FreeBusyInfo = function (freeBusyInfo) {
  this.app = Tine.Tinebase.appMgr.get('Calendar');
  this.freeBusyInfo = freeBusyInfo;
  var _ = window.lodash;
  this.byAttendee = _.groupBy(this.freeBusyInfo, function (fbInfo) {
    var type = fbInfo.user_type == 'groupmember' ? 'user' : fbInfo.user_type;
    return [type, '-', fbInfo.user_id].join('');
  });
  this.statusMap = _.mapValues(this.byAttendee, function (fbInfos) {
    var state = 0;

    _.each(fbInfos, function (fbInfo) {
      state = Math.max(state, Tine.Calendar.FreeBusyInfo.states[fbInfo.type]);
    });

    return state;
  });
  this.attendeeCount = _.keys(this.statusMap).length;
};

Tine.Calendar.FreeBusyInfo.states = {
  'FREE': 0,
  'BUSY_TENTATIVE': 1,
  'BUSY': 2,
  'BUSY_UNAVAILABLE': 3
};
Tine.Calendar.FreeBusyInfo.prototype = {
  /**
   * @property {Object} byAttendee
   * fbInfo grouped by attendee
   */
  byAttendee: null,

  /**
   * @property {Object} statusMap
   * status per attendee
   */
  statusMap: null,

  /**
   * get detailed info (HTML) grouped by attendee
   *
   * @param {Store} attendees
   */
  getInfoByAttendee: function getInfoByAttendee(attendees, event) {
    var _ = window.lodash,
        html = '<div class="cal-conflict-eventinfos">';

    _.each(_.get(attendees, 'data.items', []), _.bind(function (attendee) {
      if (!this.byAttendee[attendee.getCompoundId(true)]) return;
      html += ['<div class="cal-conflict-attendername ', attendee.getIconCls(), '">', attendee.getTitle(), '</div>'].join('');
      html += this.getInfoForAttendee(attendee, event);
    }, this));

    return html + '</div>';
  },

  /**
   * get detailed info (HTML) for a single attendee
   *
   * @param {Record} attendee
   */
  getInfoForAttendee: function getInfoForAttendee(attendee, event) {
    var _ = window.lodash,
        eventInfos = [];

    _.each(_.get(this.byAttendee, attendee.getCompoundId(true), []), _.bind(function (fbInfo) {
      var format = 'H:i';
      var eventInfo;
      var dateFormat = Ext.form.DateField.prototype.format;

      if (event.get('dtstart').format(dateFormat) != event.get('dtend').format(dateFormat) || Date.parseDate(fbInfo.dtstart, Date.patterns.ISO8601Long).format(dateFormat) != Date.parseDate(fbInfo.dtend, Date.patterns.ISO8601Long).format(dateFormat)) {
        eventInfo = Date.parseDate(fbInfo.dtstart, Date.patterns.ISO8601Long).format(dateFormat + ' ' + format) + ' - ' + Date.parseDate(fbInfo.dtend, Date.patterns.ISO8601Long).format(dateFormat + ' ' + format);
      } else {
        eventInfo = Date.parseDate(fbInfo.dtstart, Date.patterns.ISO8601Long).format(dateFormat + ' ' + format) + ' - ' + Date.parseDate(fbInfo.dtend, Date.patterns.ISO8601Long).format(format);
      }

      if (fbInfo.event && fbInfo.event.summary) {
        eventInfo += ' : ' + Ext.util.Format.htmlEncode(fbInfo.event.summary);
      }

      if (fbInfo.type == 'BUSY_UNAVAILABLE') {
        eventInfo += '<span class="cal-conflict-eventinfos-unavailable">' + this.app.i18n._('Unavailable') + '</span>';
      }

      eventInfos.push(eventInfo);
    }, this));

    return '<div class="cal-conflict-eventinfos">' + eventInfos.join(', <br />') + '</div>';
  },

  /**
   * get short info (HTML with hover) for a single attendee
   *
   * @param {Record} attendee
   * @param {Record} event
   * @return {Number} one of Tine.Calendar.FreeBusyInfo.states
   */
  getStateOfAttendee: function getStateOfAttendee(attendee, event) {
    var _ = window.lodash,
        id = attendee.getCompoundId(true),
        stateId = _.get(this.statusMap, id, 0),
        state = _.invert(Tine.Calendar.FreeBusyInfo.states)[stateId],
        cls = _.lowerCase(_.replace(state, /^BUSY_/, '')),
        info = Ext.util.Format.htmlEncode(this.getInfoForAttendee(attendee, event)),
        qtip = stateId ? 'ext:qtip="' + info + '" ' : '';

    return ['<div class="cal-fbinfo-state cal-fbinfo-state-', cls, '"', ' tine:calendar-event-id="', event.get('id'), '" ', ' tine:calendar-freebusy-state-id="', stateId, '" ', qtip, ' ></div>'].join('');
  },

  /**
   * get max state of all attendee
   *
   * @return {Number} one of Tine.Calendar.FreeBusyInfo.states
   */
  getStateOfAllAttendees: function getStateOfAllAttendees() {
    var _ = window.lodash;
    return _.reduce(this.statusMap, function (result, value, key) {
      return Math.max(result, value);
    }, 0);
  }
};

/***/ }),

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

/*
 * Tine 2.0
 * 
 * @package     Calendar
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2009-2012 Metaways Infosystems GmbH (http://www.metaways.de)
 *
 */
Ext.ns('Tine.Calendar');
/**
 * attendee filter gird widget
 * 
 * @TODO: remove attendee deleted on server?
 * 
 * @namespace   Tine.Calendar
 * @class       Tine.Calendar.AttendeeFilterGrid
 * @extends     Tine.Calendar.AttendeeGridPanel
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 */

Tine.Calendar.AttendeeFilterGrid = Ext.extend(Tine.Calendar.AttendeeGridPanel, {
  showNamesOnly: true,
  showMemberOfType: true,
  stateId: 'calendar-attendee-filter-grid',
  cls: 'x-cal-attendee-filter-grid',
  addNewAttendeeText: 'Add attendee',
  // i18n._('Add attendee')
  requireFreeBusyGrantOnly: true,
  enableDragDrop: true,
  ddGroup: 'Tine.Calendar.AttendeeFilterGrid.Sort',
  initComponent: function initComponent() {
    this.record = new Tine.Calendar.Model.Event({
      editGrant: true
    });
    this.viewConfig = {
      scrollOffset: 0
    };
    this.selModel = new Ext.grid.RowSelectionModel({
      singleSelect: true
    });
    this.selModel.on('beforerowselect', this.onBeforeRowSelect, this);
    Tine.Calendar.AttendeeFilterGrid.superclass.initComponent.call(this);
    this.store.on('add', this.onStoreAdd, this);
    this.store.on('remove', this.onStoreRemove, this);
    this.store.on('update', this.onStoreUpdate, this);
    this.ddText = this.app.i18n._('Sort Attendee');
  },
  initColumns: function initColumns() {
    Tine.Calendar.AttendeeFilterGrid.superclass.initColumns.call(this);
    this.columns.unshift(new Ext.ux.grid.CheckColumn({
      id: 'checked',
      dataIndex: 'checked',
      width: 30,
      sortable: true,
      resizable: false,
      header: '&#160;',
      tooltip: this.app.i18n._('Check to filter for this attendee'),
      listeners: {
        scope: this,
        beforecheckchange: this.onBeforeCheckChange
      }
    }));
    this.plugins = Ext.isArray(this.plugins) ? this.plugins : [];
    this.plugins.push(this.columns[0]);
  },
  afterRender: function afterRender() {
    Tine.Calendar.AttendeeFilterGrid.superclass.afterRender.apply(this, arguments);
    this.dropZone = new Ext.ux.grid.GridDropZone(this, {
      ddGroup: this.ddGroup,
      isValidDropPoint: function isValidDropPoint(target, pt, dd, e, data) {
        var addIdx = this.grid.store.getCount() - 1;
        return this.view.findRowIndex(target) != addIdx && data.rowIndex != addIdx;
      },
      onNodeDrop: function onNodeDrop(target, dd, e, data) {
        var pt = this.getDropPoint(e, target, dd),
            targetRowIndex = this.view.findRowIndex(target),
            targetPos = pt == 'above' ? targetRowIndex : targetRowIndex + 1;

        if (this.isValidDropPoint(target, pt, dd, e, data)) {
          var store = this.grid.getStore();
          store.suspendEvents();
          Ext.each(data.selections, function (r) {
            var currentIdx = store.indexOf(r);

            if (currentIdx >= 0) {
              targetPos = targetPos > currentIdx ? targetPos - 1 : targetPos;
              store.remove(r);
            }

            store.insert(targetPos, data.selections);
          }, this);
          store.each(function (r, idx) {
            r.set('sort', idx);
          });
          store.sort('sort', 'ASC');
          store.resumeEvents();
          this.grid.getView().refresh();
          this.grid.getView().updateSortIcon('sort', 'ASC');
          this.grid.fireEvent('sortchange', this.grid, this.grid.getState());
        }
      }
    });
  },
  onBeforeCheckChange: function onBeforeCheckChange(col, newValue, oldValue, record) {
    var _ = window.lodash,
        chkCount = _.countBy(_.map(this.store.data.items, 'data.checked')).true,
        filterPanel = this.app.getMainScreen().getCenterPanel().filterToolbar.activeFilterPanel,
        calFilter = filterPanel.filterStore.getAt(filterPanel.filterStore.findExact('field', 'container_id'));

    if (!newValue && chkCount == 1 && !calFilter) {
      return false;
    }
  },
  onBeforeRowSelect: function onBeforeRowSelect(sm, idx, keep, attendee) {
    if (!attendee.get('user_id')) {
      return false;
    }
  },
  onStoreAdd: function onStoreAdd() {
    // don't save initial 'add attendee' record
    if (this.store.getCount() > 1) {
      this.saveState();
    }
  },
  onStoreRemove: function onStoreRemove() {
    this.saveState();
    this.onStoreChange();
  },
  onStoreUpdate: function onStoreUpdate(store, attendee) {
    // skip updates from new attendee row
    if (store.indexOf(attendee) + 1 != store.getCount() || attendee.explicitlyAdded) {
      this.onStoreChange();
    }
  },

  /**
   * sync to filter panel
   */
  onStoreChange: function onStoreChange() {
    try {
      var filterPanel = this.app.getMainScreen().getCenterPanel().filterToolbar.activeFilterPanel,
          attendeeFilter = filterPanel.filterStore.getAt(filterPanel.filterStore.findExact('field', 'attender'));

      if (attendeeFilter) {
        //                attendeeFilter.formFields.operator.setValue('in');
        attendeeFilter.formFields.value.setValue(this.getValue());
      } else {
        attendeeFilter = {
          field: 'attender',
          operator: 'oneof',
          value: this.getValue()
        };
        filterPanel.addFilter(new filterPanel.record(attendeeFilter));
      }

      filterPanel.onFilterChange();
    } catch (e) {}
  },
  applyState: function applyState(state) {
    this.stateful = false;
    var explicitAttendee = !state || Ext.isArray(state) ? state : state.explicitAttendee;
    var rs = [];
    Ext.each(explicitAttendee, function (attendeeData) {
      var attendee = new Tine.Calendar.Model.Attender(attendeeData, 'new-' + Ext.id());
      attendee.explicitlyAdded = true;
      rs.push(attendee);
    }, this);
    this.store.removeAll();
    this.store.add(rs);

    if (state && state.sort) {
      if (state.sort.field == 'sort') {
        this.store.each(function (attendee) {
          var idx = state.sort.order.indexOf(attendee.get('user_type') + '-' + attendee.getUserId());
          attendee.data.sort = idx >= 0 ? idx : 1000;
        }, this);
      }

      this.store.sort(state.sort.field, state.sort.direction);
      this.getView().sortState = state.sort;
    }

    this.stateful = true;
  },
  getState: function getState() {
    var explicitAttendee = [],
        sort = this.store.getSortState(),
        order = [];
    this.store.each(function (attendee) {
      if (attendee.get('user_id')) {
        order.push(attendee.get('user_type') + '-' + attendee.getUserId());

        if (attendee.explicitlyAdded) {
          explicitAttendee.push(attendee.data);
        }
      }
    }, this);

    if (sort.field == 'sort') {
      sort.order = order;
    }

    return {
      explicitAttendee: explicitAttendee,
      sort: sort
    };
  },

  /**
   * get checked attendee
   */
  getValue: function getValue() {
    var attendeeData = [];
    this.store.each(function (attendee) {
      if (attendee.get('checked') && attendee.get('user_id')) {
        attendeeData.push(attendee.data);
      }
    }, this);
    return attendeeData;
  },

  /**
   * set filter value (done by MainScreenCenterPanel::onStoreLoad)
   * 
   * @param {Array} filter
   */
  setFilterValue: function setFilterValue(filters) {
    var value = this.extractFilterValue(filters) || []; // save west panel scrolling position so we can restore it after selecting nodes

    if (this.app.getMainScreen().getWestPanel().body) {
      this.leftPanelScrollTop = this.app.getMainScreen().getWestPanel().body.getScroll().top;
    }

    this.setValue(value);
  },

  /**
   * extract attendee filter from filters
   *
   * @param {Array} filters
   */
  extractFilter: function extractFilter(filters) {
    let attendeeFilters = null; // use first OR panel in case of filterPanel

    Ext.each(filters, function (filterData) {
      if (filterData.condition && filterData.condition == 'OR') {
        attendeeFilters = filterData.filters[0].filters;
        return false;
      }
    }, this); // use first attedee filter

    let attendeeFilter = null;
    Ext.each(attendeeFilters, function (filter) {
      if (filter.field === 'attender') {
        attendeeFilter = filter;
        return false;
      }
    }, this);
    return attendeeFilter;
  },

  /**
   * extract attendee filter values from filters
   *
   * @param {Array} filters
   */
  extractFilterValue: function extractFilterValue(filters) {
    let attendeeFilter = this.extractFilter(filters);
    return _.get(attendeeFilter, 'value');
  },

  /**
   * set attendee value
   * 
   * @param {Array} value
   */
  setValue: function setValue(value) {
    var attendeeStore = Tine.Calendar.Model.Attender.getAttendeeStore(value),
        selections = this.getSelectionModel().getSelections(),
        activeEditor = this.activeEditor,
        state = Ext.state.Manager.get(this.stateId);
    this.store.suspendEvents();
    this.applyState(state);
    this.store.each(function (attendee) {
      attendee.set('checked', false);
    }, this);
    attendeeStore.each(function (attendee) {
      var currentAttendee = Tine.Calendar.Model.Attender.getAttendeeStore.getAttenderRecord(this.store, attendee);

      if (!currentAttendee) {
        if (state && state.sort && state.sort.order) {
          var idx = state.sort.order.indexOf(attendee.get('user_type') + '-' + attendee.getUserId());
          attendee.data.sort = idx >= 0 ? idx : 1000;
        }

        this.store.add(attendee);
        attendee.set('checked', true);
      } else {
        currentAttendee.set('checked', true);
      }
    }, this);
    this.store.add([new Tine.Calendar.Model.Attender(Tine.Calendar.Model.Attender.getDefaultData(), 'new-' + Ext.id())]);
    this.store.applySort();
    this.store.resumeEvents();

    try {
      this.getView().refresh();
    } catch (e) {// grid could not be refreshed at the moment, maybe a row has been deleted
    }

    if (activeEditor) {
      this.startEditing(activeEditor.row, activeEditor.col);
    }

    Ext.each(selections, function (attendee) {
      var toSelect = Tine.Calendar.Model.Attender.getAttendeeStore.getAttenderRecord(this.store, attendee);

      if (toSelect) {
        this.getSelectionModel().selectRecords([toSelect], true);
      }
    }, this);
  }
});

/***/ }),

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

/*
 * Tine 2.0
 * 
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2010 Metaways Infosystems GmbH (http://www.metaways.de)
 */
Ext.ns('Tine.Calendar');
/**
 * @namespace   Tine.Calendar
 * @class       Tine.Calendar.AttendeeFilterModel
 * @extends     Tine.widgets.grid.FilterModel
 * 
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 */

Tine.Calendar.AttendeeFilterModel = Ext.extend(Tine.widgets.grid.FilterModel, {
  /**
   * @property Tine.Tinebase.Application app
   */
  app: null,
  field: 'attender',
  defaultOperator: 'in',

  /**
   * @private
   */
  initComponent: function initComponent() {
    Tine.Calendar.AttendeeFilterModel.superclass.initComponent.call(this);
    this.app = Tine.Tinebase.appMgr.get('Calendar');
    this.operators = ['in'
    /*, 'notin'*/
    ];
    this.label = this.app.i18n._('Attendee');
    this.gender = this.app.i18n._('GENDER_Attendee');
    this.defaultValue = Ext.apply(Tine.Calendar.Model.Attender.getDefaultData(), {
      user_type: 'user',
      user_id: Tine.Tinebase.registry.get('userContact')
    });
  },

  /**
   * value renderer
   * 
   * @param {Ext.data.Record} filter line
   * @param {Ext.Element} element to render to 
   */
  valueRenderer: function valueRenderer(filter, el) {
    var value = new Tine.Calendar.AttendeeFilterModelValueField({
      app: this.app,
      filter: filter,
      value: filter.data.value ? filter.data.value : this.defaultValue,
      renderTo: el
    });
    value.on('select', this.onFiltertrigger, this);
    return value;
  }
});
Tine.widgets.grid.FilterToolbar.FILTERS['calendar.attendee'] = Tine.Calendar.AttendeeFilterModel;
/**
 * @namespace   Tine.Calendar
 * @class       Tine.Calendar.AttendeeFilterModelValueField
 * @extends     Ext.ux.form.LayerCombo
 * 
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 */

Tine.Calendar.AttendeeFilterModelValueField = Ext.extend(Ext.ux.form.LayerCombo, {
  hideButtons: false,
  layerAlign: 'tr-br?',
  minLayerWidth: 400,
  layerHeight: 300,
  lazyInit: true,
  formConfig: {
    labelAlign: 'left',
    labelWidth: 30
  },
  attendeeData: null,
  initComponent: function initComponent() {
    this.on('beforecollapse', this.onBeforeCollapse, this);
    this.supr().initComponent.call(this);
  },
  getFormValue: function getFormValue() {
    return this.attendeeFilterGrid.getValue();
  },
  getItems: function getItems() {
    this.attendeeFilterGrid = new Tine.Calendar.AttendeeFilterGrid({
      title: this.app.i18n._('Select Attendee'),
      height: this.layerHeight - 40 || 'auto',
      showNamesOnly: true,
      showMemberOfType: true,
      onStoreChange: Ext.emptyFn
    });
    this.attendeeFilterGrid.store.on({
      'add': function add(store) {
        this.action_ok.setDisabled(this.attendeeFilterGrid.store.getCount() === 1);
      },
      'remove': function remove(store) {
        this.action_ok.setDisabled(this.attendeeFilterGrid.store.getCount() === 1);
      },
      scope: this
    });
    var items = [this.attendeeFilterGrid];
    return items;
  },

  /**
   * cancel collapse if ctx menu is shown
   */
  onBeforeCollapse: function onBeforeCollapse() {
    return (!this.attendeeFilterGrid.ctxMenu || this.attendeeFilterGrid.ctxMenu.hidden) && !this.attendeeFilterGrid.editing;
  },

  /**
   * @param {String} value
   * @return {Ext.form.Field} this
   */
  setValue: function setValue(value) {
    value = Ext.isArray(value) ? value : [value];
    this.attendeeData = value;
    this.currentValue = [];
    var attendeeStore = Tine.Calendar.Model.Attender.getAttendeeStore(value);
    var a = [];
    attendeeStore.each(function (attender) {
      this.currentValue.push(attender.data);
      var name = Tine.Calendar.AttendeeGridPanel.prototype.renderAttenderName.call(Tine.Calendar.AttendeeGridPanel.prototype, attender.get('user_id'), {
        noIcon: true
      }, attender); //var status = Tine.Calendar.AttendeeGridPanel.prototype.renderAttenderStatus.call(Tine.Calendar.AttendeeGridPanel.prototype, attender.get('status'), {}, attender);

      a.push(name
      /* + ' (' + status + ')'*/
      );
    }, this);
    this.setRawValue(a.join(', '));
    return this;
  },

  /**
   * sets values to innerForm
   */
  setFormValue: function setFormValue(value) {
    this.attendeeFilterGrid.setValue(this.attendeeData);
  }
});

/***/ }),

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

/* 
 * Tine 2.0
 * 
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2009-2011 Metaways Infosystems GmbH (http://www.metaways.de)
 */
Ext.ns('Tine.Calendar');
/**
 * @namespace   Tine.Calendar
 * @class       Tine.Calendar.FilterPanel
 * @extends     Tine.widgets.persistentfilter.PickerPanel
 * 
 * <p>Calendar Favorites Panel</p>
 * 
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * 
 * @param       {Object} config
 * @constructor
 * Create a new Tine.Calendar.FilterPanel
 */

Tine.Calendar.FilterPanel = Ext.extend(Tine.widgets.persistentfilter.PickerPanel, {
  filter: [{
    field: 'model',
    operator: 'equals',
    value: 'Calendar_Model_EventFilter'
  }],
  initComponent: function initComponent() {
    // TODO this is set to null somewhere in the Calendar, find a better place to fix this
    this.contentType = 'Event';
    Tine.Calendar.FilterPanel.superclass.initComponent.call(this);
  },

  /**
   * returns filter toolbar of mainscreen center panel of app this picker panel belongs to
   */
  getFilterToolbar: function getFilterToolbar() {
    return this.app.getMainScreen().getCenterPanel().filterToolbar;
  },
  storeOnBeforeload: function storeOnBeforeload(store, options) {
    store.un('beforeload', this.storeOnBeforeload, this);
    options.params.filter = options.persistentFilter.get('filters'); // take a full clone to not taint the original filter

    options.params.filter = Ext.decode(Ext.encode(options.params.filter));
    var cp = Tine.Tinebase.appMgr.get('Calendar').getMainScreen().getCenterPanel();
    var period = cp.getCalendarPanel(cp.activeView).getView().getPeriod(); // remove all existing period filters

    Ext.each(options.params.filter, function (filter) {
      if (filter.field === 'period') {
        options.params.filter.remove(filter);
        return false;
      }
    }, this);
    options.params.filter.push({
      field: 'period',
      operator: 'within',
      value: period
    });
  }
});
/**
 * @namespace Tine.Calendar
 * @class     Tine.Calendar.CalendarSelectTreePanel
 * @extends   Tine.widgets.container.TreePanel
 * 
 * Main Calendar Select Panel
 * 
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2009 Metaways Infosystems GmbH (http://www.metaways.de)
 */

Tine.Calendar.TreePanel = Ext.extend(Tine.widgets.container.TreePanel, {
  recordClass: Tine.Calendar.Model.Event,
  ddGroup: 'cal-event',
  filterMode: 'filterToolbar',
  useContainerColor: true,
  useProperties: true,
  initComponent: function initComponent() {
    var _ = window.lodash,
        me = this; //@TODO improve detection or pipe as config

    this.isMainScreenFilterTree = this.hasContextMenu; // only apply filter plugin when used as mainscreen leftpanel

    if (this.isMainScreenFilterTree) {
      this.filterPlugin = new Tine.widgets.tree.FilterPlugin({
        treePanel: this,

        /**
         * overwritten to deal with calendars special filter approach
         *
         * @return {Ext.Panel}
         */
        getGridPanel: function getGridPanel() {
          return Tine.Tinebase.appMgr.get('Calendar').getMainScreen().getCenterPanel();
        }
      });
    }

    this.on('beforeclick', this.onBeforeClick, this);
    this.on('containercolorset', function () {
      Tine.Tinebase.appMgr.get('Calendar').getMainScreen().getCenterPanel().refresh(true);
    });
    this.supr().initComponent.call(this); // remove resource calendars user has appropriate grants for

    this.loader.processResponse = _.wrap(this.loader.processResponse, function (orig, response, node, callback, scope) {
      var o = response.responseData || Ext.decode(response.responseText);
      response.responseData = o.hasOwnProperty('totalcount') ? o.results : o;
      response.responseData = _.reduce(response.responseData, function (newResponse, nodeData) {
        var grantsModelName = _.get(nodeData, 'xprops.Tinebase.Container.GrantsModel', 'Tinebase_Model_Grants'),
            accountGrants = _.get(nodeData, 'account_grants', {}),
            hasRequiredGrants = grantsModelName != 'Calendar_Model_ResourceGrants' ? true : (_.get(accountGrants, 'resourceInviteGrant', false) || _.get(accountGrants, 'resourceReadGrant', false)) && (_.get(accountGrants, 'eventsFreebusyGrant', false) || _.get(accountGrants, 'eventsReadGrant', false));

        if (grantsModelName == 'Calendar_Model_ResourceGrants') {
          // transform grants for event container selection
          accountGrants.addGrant = accountGrants.eventsAddGrant;
          accountGrants.editGrant = accountGrants.eventsEditGrant;
          accountGrants.deleteGrant = accountGrants.eventsDeleteGrant;
        }

        return hasRequiredGrants ? newResponse.concat([nodeData]) : newResponse;
      }, []);
      return orig.apply(me.loader, _.drop(arguments));
    });
  },
  initContextMenu: function initContextMenu() {
    this.supr().initContextMenu.call(this);
    this.contextModel = 'Event';
    this.action_editResource = new Ext.Action({
      iconCls: 'cal-resource',
      hidden: true,
      text: this.app.i18n._('Edit Resource'),
      handler: function handler() {
        var resource = new Tine.Calendar.Model.Resource({
          id: this.action_editResource.resourceId
        }, this.action_editResource.resourceId);
        Tine.Calendar.ResourceEditDialog.openWindow({
          record: resource
        });
      },
      scope: this
    });
    this.contextMenuSingleContainer.add(this.action_editResource);
    this.contextMenuSingleContainerProperties.add(this.action_editResource);
  },
  onContextMenu: function onContextMenu(node, event) {
    var grants = lodash.get(node, 'attributes.container.account_grants'),
        xprops = lodash.get(node, 'attributes.container.xprops'),
        resourceId;

    if (Ext.isString(xprops)) {
      xprops = Ext.decode(xprops);
    }

    resourceId = lodash.get(xprops, 'Calendar.Resource.resource_id');

    if (resourceId) {
      this.action_editResource.setText(grants.resourceEditGrant || Tine.Tinebase.common.hasRight('manage', 'Calendar', 'resources') ? this.app.i18n._('Edit Resource') : this.app.i18n._('View Resource'));
    }

    if (grants) {
      this.action_editResource.setHidden(!grants.resourceReadGrant || !resourceId);
    }

    this.action_editResource.resourceId = resourceId;
    this.supr().onContextMenu.apply(this, arguments);
  },

  /**
   * dissalow loading of all and otherUsers node
   * 
   * @param {Ext.tree.TreeNode} node
   * @param {Ext.EventObject} e
   * @return {Boolean}
   */
  onBeforeClick: function onBeforeClick(node, e) {
    if (!node.disabled && node.attributes.path && node.attributes.path.match(/^\/$|^\/personal$/)) {
      this.onClick(node, e);
      return false;
    }
  },

  /**
   * adopt attr
   * 
   * @param {Object} attr
   */
  onBeforeCreateNode: function onBeforeCreateNode(attr) {
    var xprops = lodash.get(attr, 'xprops'),
        resourceIcon,
        typeId;
    this.supr().onBeforeCreateNode.apply(this, arguments);

    if (attr.container) {
      attr.container.capabilites_private = true;
    }

    if (Ext.isString(xprops)) {
      xprops = Ext.decode(xprops);
    }

    typeId = lodash.get(xprops, 'Calendar.Resource.resource_type');
    resourceIcon = Tine.Tinebase.widgets.keyfield.StoreMgr.get('Calendar', 'resourceTypes').getById(typeId);

    if (resourceIcon) {
      attr.icon = resourceIcon.get('icon');
      attr.cls = attr.cls || '';
      attr.cls += ' cal-calendartree-resource-icon';
    }
  },

  /**
   * called when events are droped on a calendar node
   * 
   * NOTE: atm. event panels only allow d&d for single events
   * 
   * @private
   * @param  {Ext.Event} dropEvent
   * @return {Boolean}
   */
  onBeforeNodeDrop: function onBeforeNodeDrop(dropEvent) {
    var containerData = dropEvent.target.attributes,
        selection = dropEvent.data.selections,
        mainScreenPanel = Tine.Tinebase.appMgr.get('Calendar').getMainScreen().getCenterPanel(),
        abort = false; // @todo move this to dragOver

    if (!containerData.account_grants.addGrant) {
      abort = true;
    }

    Ext.each(selection, function (event) {
      if (Tine.Tinebase.container.pathIsMyPersonalContainer(event.get('container_id').path)) {
        // origin container will only be moved for personal events with their origin in
        // a personal container of the current user
        event.set('container_id', containerData.id);
        mainScreenPanel.onUpdateEvent(event);
        dropEvent.cancel = false;
        dropEvent.dropStatus = true;
      } else {
        // @todo move displaycal if curruser is attender
        abort = true;
      }
    }, this);

    if (abort) {
      return false;
    }
  },
  getSelectedContainer: function getSelectedContainer(requiredGrants, defaultContainer, onlySingle) {
    var prefs = this.app.getRegistry().get('preferences');

    if ('none' === prefs.get('defaultCalendarStrategy')) {
      var sm = this.getSelectionModel(),
          selection = typeof sm.getSelectedNodes == 'function' ? sm.getSelectedNodes() : [sm.getSelectedNode()];

      if (selection.length > 1 || selection.length === 0) {
        return null;
      }
    }

    return this.supr().getSelectedContainer.call(this, requiredGrants, defaultContainer, onlySingle);
  }
});

/***/ }),

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

/*
 * Tine 2.0
 * 
 * @package     Calendar
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2012 Metaways Infosystems GmbH (http://www.metaways.de)
 *
 */
Ext.ns('Tine.Calendar');
/**
 * @namespace   Tine.Calendar
 * @class       Tine.Calendar.PerspectiveCombo
 * @extends     Ext.form.ComboBox
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * 
 * @TODO make displaycontainer setting work
 */

Tine.Calendar.PerspectiveCombo = Ext.extend(Ext.form.ComboBox, {
  /**
   * @cfg {Tine.Calendar.EventEditDialog}
   */
  editDialog: null,
  defaultValue: 'origin',
  typeAhead: true,
  triggerAction: 'all',
  lazyRender: true,
  mode: 'local',
  valueField: 'id',
  displayField: 'displayText',
  initComponent: function initComponent() {
    this.app = Tine.Tinebase.appMgr.get('Calendar');
    this.initStore();
    this.on('beforeselect', function (field, record, index) {
      var oldValue = this.getValue(),
          newValue = this.store.getAt(index).id;
      this.onPerspectiveChange.defer(50, this, [field, newValue, oldValue]);
    }, this);
    this.editDialog.alarmPanel.alarmGrid.deleteAction.setHandler(this.onAlarmDelete, this);
    this.editDialog.alarmPanel.onRecordUpdate = this.onAlarmRecordUpdate.createDelegate(this);
    this.editDialog.alarmPanel.alarmGrid.store.on('add', this.onAlarmAdd, this);
    Tine.Calendar.PerspectiveCombo.superclass.initComponent.call(this);
  },
  getAttendeeStatusField: function getAttendeeStatusField() {
    if (!this.attendeeStatusField) {
      this.attendeeStatusField = Ext.ComponentMgr.create({
        xtype: 'widget-keyfieldcombo',
        width: 115,
        hideLabel: true,
        app: 'Calendar',
        name: 'attendeeStatus',
        keyFieldName: 'attendeeStatus'
      });
      this.attendeeStatusField.on('change', function (field) {
        var perspective = this.getValue(),
            attendeeRecord = this.editDialog.attendeeStore.getById(perspective);
        attendeeRecord.set('status', field.getValue());
      }, this);
    }

    return this.attendeeStatusField;
  },
  getAttendeeTranspField: function getAttendeeTranspField() {
    if (!this.attendeeTranspField) {
      this.attendeeTranspField = Ext.ComponentMgr.create({
        xtype: 'checkbox',
        boxLabel: this.app.i18n._('non-blocking'),
        name: 'attendeeTransp',
        getValue: function getValue() {
          var bool = Ext.form.Checkbox.prototype.getValue.call(this);
          return bool ? 'TRANSPARENT' : 'OPAQUE';
        },
        setValue: function setValue(value) {
          var bool = value == 'TRANSPARENT' || value === true;
          return Ext.form.Checkbox.prototype.setValue.call(this, bool);
        }
      });
      this.attendeeTranspField.on('change', function (field) {
        var perspective = this.getValue(),
            attendeeRecord = this.editDialog.attendeeStore.getById(perspective);
        attendeeRecord.set('transp', field.getValue());
      }, this);
    }

    return this.attendeeTranspField;
  },
  getAttendeeContainerField: function getAttendeeContainerField() {
    if (!this.attendeeContainerField) {
      this.attendeeContainerField = new Tine.widgets.container.SelectionComboBox({
        fieldLabel: this.app.i18n._('Displayed in'),
        name: 'attendeeContainer',
        recordClass: this.editDialog.recordClass,
        appName: this.app.appName,
        requiredGrant: this.editDialog.record.data.id ? ['editGrant'] : ['addGrant'],
        disabled: true
      });
    }

    return this.attendeeContainerField;
  },
  initStore: function initStore() {
    this.store = new Ext.data.Store({
      fields: Tine.Calendar.Model.Attender.getFieldDefinitions().concat([{
        name: 'displayText'
      }])
    });
    this.originRecord = new Tine.Calendar.Model.Attender({
      id: 'origin',
      displayText: this.app.i18n._('Organizer')
    }, 'origin');
    this.editDialog.attendeeStore.on('add', this.syncStores, this);
    this.editDialog.attendeeStore.on('update', this.syncStores, this);
    this.editDialog.attendeeStore.on('remove', this.syncStores, this);
  },
  syncStores: function syncStores() {
    this.store.removeAll();
    this.store.add(this.originRecord);
    this.editDialog.attendeeStore.each(function (attendee) {
      if (attendee.get('user_id')) {
        var attendee = attendee.copy(),
            displayName = Tine.Calendar.AttendeeGridPanel.prototype.renderAttenderName.call(Tine.Calendar.AttendeeGridPanel.prototype, attendee.get('user_id'), false, attendee);
        attendee.set('displayText', displayName + ' (' + Tine.Calendar.Model.Attender.getRecordName() + ')');
        attendee.set('id', attendee.id);
        this.store.add(attendee);
      }
    }, this); // reset if perspective attendee is gone

    if (!this.store.getById(this.getValue())) {
      this.setValue(this.originRecord.id);
    } // sync attendee status


    if (this.getValue() != 'origin') {
      var attendeeStatusField = this.editDialog.getForm().findField('attendeeStatus'),
          attendeeStatus = this.editDialog.attendeeStore.getById(this.getValue()).get('status');
      attendeeStatusField.setValue(attendeeStatus);
    }
  },
  applyAlarmFilter: function applyAlarmFilter() {
    var alarmGrid = this.editDialog.alarmPanel.alarmGrid,
        perspective = this.getValue(),
        perspectiveRecord = this.store.getById(perspective),
        isOriginPerspective = perspective == 'origin';

    if (isOriginPerspective) {
      alarmGrid.store.filterBy(function (alarm) {
        // all but option attendee
        return !alarm.getOption('attendee');
      }, this);
    } else {
      alarmGrid.store.filterBy(function (alarm) {
        var skip = alarm.getOption('skip') || [],
            isSkipped = Tine.Calendar.Model.Attender.getAttendeeStore.getAttenderRecord(Tine.Calendar.Model.Attender.getAttendeeStore(skip), perspectiveRecord),
            attendee = alarm.getOption('attendee'),
            isAttendee = Tine.Calendar.Model.Attender.getAttendeeStore.getAttenderRecord(Tine.Calendar.Model.Attender.getAttendeeStore([attendee]), perspectiveRecord); // origin w.o. skip of this perspective + specials for this perspective

        return !(isSkipped || attendee && !isAttendee);
      }, this);
    }
  },
  onAlarmAdd: function onAlarmAdd(store, records, index) {
    var alarm = records[0],
        perspective = this.getValue(),
        perspectiveRecord = this.store.getById(perspective),
        isOriginPerspective = perspective == 'origin';

    if (!alarm.get('id') && !isOriginPerspective) {
      store.suspendEvents();
      alarm.setOption('attendee', {
        'user_type': perspectiveRecord.get('user_type'),
        'user_id': perspectiveRecord.getUserId()
      });
      store.resumeEvents();
    }
  },
  onAlarmDelete: function onAlarmDelete() {
    var alarmGrid = this.editDialog.alarmPanel.alarmGrid,
        perspective = this.getValue(),
        perspectiveRecord = this.store.getById(perspective),
        isOriginPerspective = perspective == 'origin';
    Ext.each(alarmGrid.getSelectionModel().getSelections(), function (alarm) {
      if (!isOriginPerspective && !alarm.getOption('user_id')) {
        var skip = alarm.getOption('skip') || [];
        skip.push({
          'user_type': perspectiveRecord.get('user_type'),
          'user_id': perspectiveRecord.getUserId()
        });
        alarm.setOption('skip', skip);
        this.applyAlarmFilter();
      } else {
        alarmGrid.store.remove(alarm);
      }
    }, this);
  },
  onAlarmRecordUpdate: function onAlarmRecordUpdate(record) {
    var alarmGrid = this.editDialog.alarmPanel.alarmGrid,
        alarmStore = alarmGrid.store;
    alarmStore.suspendEvents();
    alarmStore.clearFilter();
    Tine.widgets.dialog.AlarmPanel.prototype.onRecordUpdate.call(this.editDialog.alarmPanel, record);
    this.applyAlarmFilter();
    alarmStore.resumeEvents();
  },
  onPerspectiveChange: function onPerspectiveChange(field, newValue, oldValue) {
    if (newValue != oldValue) {
      this.updatePerspective(oldValue);
      this.loadPerspective(newValue);
    }
  },

  /**
   * load perspective into dialog
   */
  loadPerspective: function loadPerspective(perspective) {
    if (!this.perspectiveIsInitialized) {
      this.syncStores();
      var myAttendee = Tine.Calendar.Model.Attender.getAttendeeStore.getMyAttenderRecord(this.store),
          imOrganizer = this.editDialog.record.get('organizer').id == Tine.Tinebase.registry.get('currentAccount').contact_id,
          eventView = Tine.Tinebase.configManager.get('eventView', 'Calendar');

      if (eventView == 'organizer') {
        perspective = 'origin';
      } else {
        perspective = imOrganizer || !myAttendee ? 'origin' : myAttendee.id;
      }

      this.perspectiveIsInitialized = true;
      this.setValue(perspective);
    }

    var perspective = perspective || this.getValue(),
        perspectiveRecord = this.store.getById(perspective),
        isOriginPerspective = perspective == 'origin',
        attendeeStatusField = this.getAttendeeStatusField(),
        attendeeTranspField = this.getAttendeeTranspField(),
        attendeeContainerField = this.getAttendeeContainerField(),
        transpField = this.editDialog.getForm().findField('transp'),
        containerField = this.editDialog.getForm().findField('container_id');
    attendeeTranspField.setValue(isOriginPerspective ? '' : perspectiveRecord.get('transp'));
    attendeeStatusField.setValue(isOriginPerspective ? '' : perspectiveRecord.get('status'));
    attendeeContainerField.setValue(isOriginPerspective ? this.editDialog.record.get('container_id') : perspectiveRecord.get('displaycontainer_id'));
    attendeeContainerField.startPath = isOriginPerspective ? '/' : '/personal/' + perspectiveRecord.getUserAccountId();
    attendeeStatusField.setVisible(!isOriginPerspective);
    attendeeTranspField.setVisible(!isOriginPerspective);
    attendeeContainerField.setVisible(!isOriginPerspective);
    transpField.setVisible(isOriginPerspective);
    containerField.setVisible(isOriginPerspective); // (de)activate fields 

    var fs = this.editDialog.record.fields;
    fs.each(function (f) {
      var field = this.editDialog.getForm().findField(f.name);

      if (field) {
        field.setDisabled(!isOriginPerspective || field.requiredGrant && !this.editDialog.record.get(field.requiredGrant));
      }
    }, this);
    attendeeStatusField.setDisabled(isOriginPerspective || !perspectiveRecord.get('status_authkey'));
    attendeeTranspField.setDisabled(isOriginPerspective || !perspectiveRecord.get('status_authkey'));
    attendeeContainerField.setDisabled(isOriginPerspective || !perspectiveRecord.get('displaycontainer_id').account_grants[containerField.requiredGrant]);
    this.editDialog.alarmPanel.setDisabled((!isOriginPerspective || !this.editDialog.record.get('editGrant')) && !perspectiveRecord.get('status_authkey'));
    this.editDialog.attendeeGridPanel.setDisabled(!isOriginPerspective || !this.editDialog.record.get('editGrant'));
    this.editDialog.rrulePanel.setDisabled(!isOriginPerspective || !this.editDialog.record.get('editGrant') || this.editDialog.record.isRecurException());
    this.applyAlarmFilter();
  },

  /**
   * update perspective from dialog
   */
  updatePerspective: function updatePerspective(perspective) {
    var perspective = perspective || this.getValue(),
        perspectiveRecord = this.editDialog.attendeeStore.getById(perspective),
        isOriginPerspective = perspective == 'origin',
        attendeeStatusField = this.getAttendeeStatusField(),
        attendeeTranspField = this.getAttendeeTranspField(),
        attendeeContainerField = this.getAttendeeContainerField(),
        containerField = this.editDialog.getForm().findField('container_id');

    if (perspectiveRecord && !isOriginPerspective) {
      perspectiveRecord.set('transp', attendeeTranspField.getValue());
      perspectiveRecord.set('status', attendeeStatusField.getValue());
      perspectiveRecord.set('displaycontainer_id', attendeeContainerField.selectedContainer);
    }
  }
});

/***/ }),

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

/* 
 * Tine 2.0
 * 
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2009 Metaways Infosystems GmbH (http://www.metaways.de)
 */
Ext.ns('Tine.Calendar');
/**
 * @namespace Tine.Calendar
 * @class Tine.Calendar.ColorManager
 * Colormanager for Coloring Calendar Events <br>
 * 
 * @constructor
 * Creates a new color manager
 * @param {Object} config
 * 
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2007-2008 Metaways Infosystems GmbH (http://www.metaways.de)
 */

Tine.Calendar.ColorManager = function (config) {
  Ext.apply(this, config);
  this.customColorSchemataCache = {};
};

Ext.apply(Tine.Calendar.ColorManager.prototype, {
  /**
   * gray color set
   * 
   * @type Object 
   * @property gray
   */
  gray: {
    color: '#808080',
    light: '#EDEDED',
    text: '#FFFFFF',
    lightText: '#FFFFFF'
  },

  /**
   * color sets for colors from colorPalette
   * 
   * @type Array 
   * @property colorSchemata
   */
  colorSchemata: {
    "000000": {
      color: '#000000',
      light: '#8F8F8F',
      text: '#FFFFFF',
      lightText: '#FFFFFF'
    },
    "993300": {
      color: '#993300',
      light: '#CEA590',
      text: '#FFFFFF',
      lightText: '#FFFFFF'
    },
    "333300": {
      color: '#333300',
      light: '#A6A691',
      text: '#FFFFFF',
      lightText: '#FFFFFF'
    },
    "003300": {
      color: '#003300',
      light: '#8FA48F',
      text: '#FFFFFF',
      lightText: '#FFFFFF'
    },
    "003366": {
      color: '#003366',
      light: '#90A5B9',
      text: '#FFFFFF',
      lightText: '#FFFFFF'
    },
    "000080": {
      color: '#000080',
      light: '#9090C4',
      text: '#FFFFFF',
      lightText: '#FFFFFF'
    },
    "333399": {
      color: '#333399',
      light: '#A5A5CE',
      text: '#FFFFFF',
      lightText: '#FFFFFF'
    },
    "333333": {
      color: '#333333',
      light: '#A6A6A6',
      text: '#FFFFFF',
      lightText: '#FFFFFF'
    },
    "800000": {
      color: '#800000',
      light: '#C79393',
      text: '#FFFFFF',
      lightText: '#FFFFFF'
    },
    "FF6600": {
      color: '#FF6600',
      light: '#F8BB92',
      text: '#FFFFFF',
      lightText: '#FFFFFF'
    },
    // orange
    "808000": {
      color: '#808000',
      light: '#C6C692',
      text: '#FFFFFF',
      lightText: '#FFFFFF'
    },
    "008000": {
      color: '#008000',
      light: '#92C692',
      text: '#FFFFFF',
      lightText: '#FFFFFF'
    },
    "008080": {
      color: '#008080',
      light: '#91C5C5',
      text: '#FFFFFF',
      lightText: '#FFFFFF'
    },
    "0000FF": {
      color: '#0000FF',
      light: '#9292F8',
      text: '#FFFFFF',
      lightText: '#FFFFFF'
    },
    "666699": {
      color: '#666699',
      light: '#BBBBD0',
      text: '#FFFFFF',
      lightText: '#FFFFFF'
    },
    "808080": {
      color: '#808080',
      light: '#C6C6C6',
      text: '#FFFFFF',
      lightText: '#FFFFFF'
    },
    "FF0000": {
      color: '#FF0000',
      light: '#F89292',
      text: '#FFFFFF',
      lightText: '#FFFFFF'
    },
    // red
    "FF9900": {
      color: '#FF9900',
      light: '#F8D092',
      text: '#FFFFFF',
      lightText: '#FFFFFF'
    },
    "99CC00": {
      color: '#99CC00',
      light: '#D0E492',
      text: '#FFFFFF',
      lightText: '#FFFFFF'
    },
    "339966": {
      color: '#339966',
      light: '#A7D0BB',
      text: '#FFFFFF',
      lightText: '#FFFFFF'
    },
    "33CCCC": {
      color: '#33CCCC',
      light: '#A8E5E5',
      text: '#FFFFFF',
      lightText: '#FFFFFF'
    },
    "3366FF": {
      color: '#3366FF',
      light: '#A7BBF8',
      text: '#FFFFFF',
      lightText: '#FFFFFF'
    },
    // blue
    "800080": {
      color: '#800080',
      light: '#C692C6',
      text: '#FFFFFF',
      lightText: '#FFFFFF'
    },
    "969696": {
      color: '#969696',
      light: '#CECECE',
      text: '#FFFFFF',
      lightText: '#FFFFFF'
    },
    "FF00FF": {
      color: '#FF00FF',
      light: '#F690F6',
      text: '#FFFFFF',
      lightText: '#FFFFFF'
    },
    // purple
    "FFCC00": {
      color: '#FFCC00',
      light: '#F7E391',
      text: '#FFFFFF',
      lightText: '#FFFFFF'
    },
    "FFFF00": {
      color: '#FFFF00',
      light: '#F7F791',
      text: '#000000',
      lightText: '#000000'
    },
    "00FF00": {
      color: '#00FF00',
      light: '#93F993',
      text: '#000000',
      lightText: '#000000'
    },
    // green
    "00FFFF": {
      color: '#00FFFF',
      light: '#93F9F9',
      text: '#000000',
      lightText: '#000000'
    },
    "00CCFF": {
      color: '#00CCFF',
      light: '#93E5F9',
      text: '#FFFFFF',
      lightText: '#FFFFFF'
    },
    "993366": {
      color: '#993366',
      light: '#D1A8BC',
      text: '#FFFFFF',
      lightText: '#FFFFFF'
    },
    // violet
    "C0C0C0": {
      color: '#C0C0C0',
      light: '#DFDFDF',
      text: '#FFFFFF',
      lightText: '#FFFFFF'
    },
    "FF99CC": {
      color: '#FF99CC',
      light: '#F8F0E4',
      text: '#FFFFFF',
      lightText: '#FFFFFF'
    },
    "FFCC99": {
      color: '#FFCC99',
      light: '#F8E4D0',
      text: '#000000',
      lightText: '#000000'
    },
    "FFFF99": {
      color: '#FFFF99',
      light: '#F9F9D1',
      text: '#000000',
      lightText: '#000000'
    },
    "CCFFCC": {
      color: '#CCFFCC',
      light: '#E5F9E5',
      text: '#000000',
      lightText: '#000000'
    },
    "CCFFFF": {
      color: '#CCFFFF',
      light: '#E5F9F9',
      text: '#000000',
      lightText: '#000000'
    },
    "99CCFF": {
      color: '#99CCFF',
      light: '#D0E4F8',
      text: '#000000',
      lightText: '#000000'
    },
    "CC99FF": {
      color: '#CC99FF',
      light: '#E5D1F9',
      text: '#000000',
      lightText: '#000000'
    },
    "FFFFFF": {
      color: '#DFDFDF',
      light: '#F8F8F8',
      text: '#000000',
      lightText: '#000000'
    },
    "996633": {
      color: '#996633',
      light: '#d9b38c',
      text: '#FFFFFF',
      lightText: '#FFFFFF'
    },
    // brown
    "604020": {
      color: '#604020',
      light: '#996633',
      text: '#FFFFFF',
      lightText: '#FFFFFF'
    },
    // more brown
    "b37700": {
      color: '#b37700',
      light: '#ffd480',
      text: '#FFFFFF',
      lightText: '#FFFFFF'
    } // even more brown

  },
  getStrategy: function getStrategy() {
    let p = Tine.Calendar.ColorManager.colorStrategyBtn.prototype;
    let name = Ext.state.Manager.get(p.stateId, p).colorStrategy;
    return Tine.Calendar.colorStrategies[name];
  },
  getInfoBarStrategy: function getInfoBarStrategy() {
    let p = Tine.Calendar.ColorManager.colorStrategyBtn.prototype;
    let name = Ext.state.Manager.get(p.stateId, p).infoBarColorStrategy;

    if (!Tine.Calendar.infoBarColorStrategies[name]) {
      // fallback to default value
      name = 'response';
    }

    return Tine.Calendar.infoBarColorStrategies[name];
  },

  /**
   * hack for container only support
   * 
   * @param {Tine.Calendar.Model.Evnet} event
   * @return {Object} colorset
   */
  getColor: function getColor(event, attendeeRecord) {
    var color = this.getStrategy().getColor(event, attendeeRecord);
    color = String(color).replace('#', '');

    if (!color.match(/[0-9a-fA-F]{6}/)) {
      return this.gray;
    }

    let schema = this.colorSchemata[color];
    return schema ? schema : this.getCustomSchema(color);
  },
  getCustomSchema: function getCustomSchema(color) {
    if (!this.customColorSchemataCache[color]) {
      const solid = "#" + color;
      const light = this.shadeColor(0.4, solid);
      this.customColorSchemataCache[color] = {
        color: solid,
        text: this.getTextColor(solid),
        light: light,
        lighttext: this.getTextColor(light)
      };
    }

    return this.customColorSchemataCache[color];
  },
  shadeColor: function shadeColor(shade, color) {
    // TODO: Move copied pSBC code out of here!
    // pSBC - Shade Blend Convert - Version 4.0 - 02/18/2019
    // https://github.com/PimpTrizkit/PJs/edit/master/pSBC.js
    const pSBC = (p, c0, c1, l) => {
      let r,
          g,
          b,
          P,
          f,
          t,
          h,
          m = Math.round,
          a = typeof c1 == "string";
      if (typeof p != "number" || p < -1 || p > 1 || typeof c0 != "string" || c0[0] != 'r' && c0[0] != '#' || c1 && !a) return null;
      h = c0.length > 9, h = a ? c1.length > 9 ? true : c1 == "c" ? !h : false : h, f = pSBC.pSBCr(c0), P = p < 0, t = c1 && c1 != "c" ? pSBC.pSBCr(c1) : P ? {
        r: 0,
        g: 0,
        b: 0,
        a: -1
      } : {
        r: 255,
        g: 255,
        b: 255,
        a: -1
      }, p = P ? p * -1 : p, P = 1 - p;
      if (!f || !t) return null;
      if (l) r = m(P * f.r + p * t.r), g = m(P * f.g + p * t.g), b = m(P * f.b + p * t.b);else r = m((P * f.r ** 2 + p * t.r ** 2) ** 0.5), g = m((P * f.g ** 2 + p * t.g ** 2) ** 0.5), b = m((P * f.b ** 2 + p * t.b ** 2) ** 0.5);
      a = f.a, t = t.a, f = a >= 0 || t >= 0, a = f ? a < 0 ? t : t < 0 ? a : a * P + t * p : 0;
      if (h) return "rgb" + (f ? "a(" : "(") + r + "," + g + "," + b + (f ? "," + m(a * 1000) / 1000 : "") + ")";else return "#" + (4294967296 + r * 16777216 + g * 65536 + b * 256 + (f ? m(a * 255) : 0)).toString(16).slice(1, f ? undefined : -2);
    };

    pSBC.pSBCr = d => {
      const i = parseInt,
            m = Math.round;
      let n = d.length,
          x = {};

      if (n > 9) {
        const [r, g, b, a] = d = d.split(',');
        n = d.length;
        if (n < 3 || n > 4) return null;
        x.r = i(r[3] == "a" ? r.slice(5) : r.slice(4)), x.g = i(g), x.b = i(b), x.a = a ? parseFloat(a) : -1;
      } else {
        if (n == 8 || n == 6 || n < 4) return null;
        if (n < 6) d = "#" + d[1] + d[1] + d[2] + d[2] + d[3] + d[3] + (n > 4 ? d[4] + d[4] : "");
        d = i(d.slice(1), 16);
        if (n == 9 || n == 5) x.r = d >> 24 & 255, x.g = d >> 16 & 255, x.b = d >> 8 & 255, x.a = m((d & 255) / 0.255) / 1000;else x.r = d >> 16, x.g = d >> 8 & 255, x.b = d & 255, x.a = -1;
      }

      return x;
    }; // end of pSBC


    return pSBC(shade, color);
  },
  getTextColor: function getTextColor(colorString) {
    let values = Tine.Calendar.ColorManager.str2dec(colorString); // weights of color values see: https://stackoverflow.com/questions/596216/formula-to-determine-brightness-of-rgb-color

    let Y = 0.299 * values[0] + 0.587 * values[1] + 0.114 * values[2];
    return Y > 128 ? '#000000' : '#FFFFFF';
  }
});
Tine.Calendar.colorMgr = new Tine.Calendar.ColorManager({});

Tine.Calendar.ColorManager.str2dec = function (string) {
  var s = String(string).replace('#', ''),
      parts = s.match(/([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})/);
  if (!parts || parts.length != 4) return;
  return [parseInt('0x' + parts[1]), parseInt('0x' + parts[2]), parseInt('0x' + parts[3])];
};

Tine.Calendar.ColorManager.compare = function (color1, color2, abs) {
  var c1 = Ext.isArray(color1) ? color1 : Tine.Calendar.ColorManager.str2dec(color1),
      c2 = Ext.isArray(color2) ? color2 : Tine.Calendar.ColorManager.str2dec(color2);
  if (!c1 || !c2) return;
  var diff = [c1[0] - c2[0], c1[1] - c2[1], c1[2] - c2[2]];
  return abs ? Math.abs(diff[0]) + Math.abs(diff[1]) + Math.abs(diff[2]) : diff;
};

Tine.Calendar.ColorManager.colorStrategyBtn = Ext.extend(Ext.Button, {
  scale: 'medium',
  minWidth: 60,
  rowspan: 2,
  iconAlign: 'top',
  requiredGrant: 'readGrant',
  iconCls: 'action_changecolor',
  colorStrategy: 'container',
  infoBarColorStrategy: 'response',
  stateful: true,
  stateId: 'cal-calpanel-color-strategy-btn',
  stateEvents: [],
  initComponent: function initComponent() {
    var _ = window.lodash,
        me = this;
    this.app = Tine.Tinebase.appMgr.get('Calendar');

    if (!this.app.featureEnabled('featureColorBy')) {
      // hide button and make sure it isn't pressed
      Tine.log.info('ColorStrategy feature is deactivated');
      this.hidden = true;
      this.stateful = false;
    } // init state now to render menu with state applied


    this.initState();
    this.text = this.app.i18n._('Colors');
    this.menu = {
      items: _.reduce(Tine.Calendar.colorStrategies, function (items, strategy, key) {
        return items.concat({
          text: strategy.getName(),
          checked: me.colorStrategy == key,
          group: 'colorStrategy',
          checkHandler: me.changeColorStrategy.createDelegate(me, [key])
        });
      }, [])
    };

    let sidebarItems = _.reduce(Tine.Calendar.infoBarColorStrategies, function (items, strategy, key) {
      return items.concat({
        text: strategy.getName(),
        checked: me.infoBarColorStrategy == key,
        group: 'infoBarColorStrategy',
        checkHandler: me.changeInfoBarColorStrategy.createDelegate(me, [key])
      });
    }, []);

    this.menu.items.push({
      text: this.app.i18n._('Side bar color'),
      menu: sidebarItems
    });
    Tine.Calendar.ColorManager.colorStrategyBtn.superclass.initComponent.apply(this, arguments);
  },
  changeColorStrategy: function changeColorStrategy(strategy) {
    this.colorStrategy = strategy;
    this.saveState();
    this.app.getMainScreen().getCenterPanel().refresh();
  },
  getState: function getState() {
    return {
      colorStrategy: this.colorStrategy,
      infoBarColorStrategy: this.infoBarColorStrategy
    };
  },
  changeInfoBarColorStrategy: function changeInfoBarColorStrategy(strategy) {
    this.infoBarColorStrategy = strategy;
    this.saveState();
    this.app.getMainScreen().getCenterPanel().refresh();
  }
});
Ext.ux.ItemRegistry.registerItem('Calendar-MainScreenPanel-ViewBtnGrp', Tine.Calendar.ColorManager.colorStrategyBtn, 30);
/**
 * Color Strategies Registry
 * 
 * @type Object
 */

Tine.Calendar.colorStrategies = {};
Tine.Calendar.colorStrategies['container'] = {
  getName: function getName() {
    return Tine.Tinebase.appMgr.get('Calendar').i18n._('Color by Calendar');
  },
  getColor: function getColor(event, attendeeRecord) {
    var container = null,
        color = null,
        schema = null;

    if (!Ext.isFunction(event.get)) {
      // tree comes with containers only
      container = event;
    } else {
      container = event.get('container_id'); // take displayContainer if user has no access to origin

      if (Ext.isPrimitive(container)) {
        container = event.getDisplayContainer();
      }
    }

    if (null === container) {
      return;
    }

    return String(container.color).replace('#', '');
  }
};
Tine.Calendar.colorStrategies['displayContainer'] = {
  getName: function getName() {
    return Tine.Tinebase.appMgr.get('Calendar').i18n._('Color by Attendee Calendar');
  },
  getColor: function getColor(event, attendeeRecord) {
    var container = null,
        color = null;

    if (attendeeRecord) {
      container = attendeeRecord.get('displaycontainer_id');
      color = container ? String(container.color).replace('#', '') : 'C0C0C0';
    } else {
      color = 'C0C0C0'; // light gray
    }

    return color;
  }
};
Tine.Calendar.colorStrategies['tag'] = {
  getName: function getName() {
    return Tine.Tinebase.appMgr.get('Calendar').i18n._('Color by Tags');
  },
  getColor: function getColor(event, attendeeRecord) {
    var color = 'C0C0C0',
        tags = event.get('tags'),
        tag = Ext.isArray(tags) ? tags[0] : null;

    if (tag) {
      color = tag.color;
    }

    return color;
  }
};
Tine.Calendar.colorStrategies['requiredAttendee'] = {
  getName: function getName() {
    return Tine.Tinebase.appMgr.get('Calendar').i18n._('Color by Attendee Role');
  },
  getColor: function getColor(event, attendeeRecord) {
    var color, role;

    if (attendeeRecord) {
      role = attendeeRecord.get('role');
      const roleStore = Tine.Tinebase.widgets.keyfield.StoreMgr.get('Calendar', 'attendeeRoles');
      const roleRecord = roleStore.getById(role);
      color = roleRecord ? roleRecord.get('color') : role === 'REQ' ? 'FF0000' : '00FF00';
    } else {
      color = 'C0C0C0'; // light gray
    }

    return color;
  }
};
/**
 * Info Color Bar Strategies Registry
 *
 * @type Object
 */

Tine.Calendar.infoBarColorStrategies = {};
Tine.Calendar.infoBarColorStrategies['response'] = {
  getName: function getName() {
    return Tine.Tinebase.appMgr.get('Calendar').i18n._('Colors by response');
  },
  getColors: function getColors(event, attendeeRecord) {
    let attendees = event.get('attendee');
    let colorMapping = {
      'ACCEPTED': '00CC00',
      'DECLINED': 'FF0000',
      'TENTATIVE': 'FFDD00'
    };
    let colors = [];

    _.forEach(attendees, function (att) {
      var _colorMapping$att$sta;

      colors.push((_colorMapping$att$sta = colorMapping[att.status]) !== null && _colorMapping$att$sta !== void 0 ? _colorMapping$att$sta : 'C0C0C0');
    });

    return colors;
  }
};
Tine.Calendar.infoBarColorStrategies['tag'] = {
  getName: function getName() {
    return Tine.Tinebase.appMgr.get('Calendar').i18n._('Colors by tags');
  },
  getColors: function getColors(event, attendeeRecord) {
    let tags = event.get('tags');
    let colors = [];

    _.forEach(tags, function (tag) {
      if (tag.color) {
        colors.push(tag.color);
      }
    });

    return colors;
  }
};
Tine.Calendar.infoBarColorStrategies['attendees'] = {
  getName: function getName() {
    return Tine.Tinebase.appMgr.get('Calendar').i18n._('Colors by attendee');
  },
  getColors: function getColors(event, attendeeRecord) {
    let attendees = event.get('attendee');
    let colors = [];

    _.forEach(attendees, function (att) {
      if (att.user_type !== 'user' && att.user_type !== 'groupmember') {
        return;
      }

      let container = att.displaycontainer_id;
      let color = container ? String(container.color).replace('#', '') : 'C0C0C0';
      colors.push(color);
    });

    return colors;
  }
};
Tine.Calendar.infoBarColorStrategies['resource'] = {
  getName: function getName() {
    return Tine.Tinebase.appMgr.get('Calendar').i18n._('Colors by resource');
  },
  getColors: function getColors(event, attendeeRecord) {
    let attendees = event.get('attendee');
    let colors = [];

    _.forEach(attendees, function (att) {
      if (att.user_type !== 'resource') {
        return;
      }

      let user = att.user_id;
      let color = user ? String(user.color).replace('#', '') : 'C0C0C0';
      colors.push(color);
    });

    return colors;
  }
};

/***/ }),

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

/* 
 * Tine 2.0
 * 
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2007-2015 Metaways Infosystems GmbH (http://www.metaways.de)
 */
Ext.ns('Tine.Calendar');
Tine.Calendar.RrulePanel = Ext.extend(Ext.Panel, {
  /**
   * @static
   */
  wkdays: ['SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA'],

  /**
   * @property
   */
  activeRuleCard: null,

  /**
   * the event edit dialog (parent)
   * @type Tine.Calendar.EventEditDialog
   */
  eventEditDialog: null,
  layout: 'form',
  frame: true,
  canonicalName: 'RecurrenceConfig',
  initComponent: function initComponent() {
    this.app = Tine.Tinebase.appMgr.get('Calendar');
    this.title = this.app.i18n._('Recurrances');
    this.defaults = {
      border: false
    };
    this.NONEcard = new Ext.Panel({
      freq: 'NONE',
      html: this.app.i18n._('No recurring rule defined')
    });
    this.NONEcard.setRule = Ext.emptyFn;
    this.NONEcard.fillDefaults = Ext.emptyFn;

    this.NONEcard.getRule = function () {
      return null;
    };

    this.NONEcard.isValid = function () {
      return true;
    };

    this.DAILYcard = new Tine.Calendar.RrulePanel.DAILYcard({
      rrulePanel: this
    });
    this.WEEKLYcard = new Tine.Calendar.RrulePanel.WEEKLYcard({
      rrulePanel: this
    });
    this.MONTHLYcard = new Tine.Calendar.RrulePanel.MONTHLYcard({
      rrulePanel: this
    });
    this.YEARLYcard = new Tine.Calendar.RrulePanel.YEARLYcard({
      rrulePanel: this
    });
    this.ruleCards = new Ext.Panel({
      layout: 'card',
      baseCls: 'ux-arrowcollapse',
      cls: 'ux-arrowcollapse-plain',
      collapsible: true,
      collapsed: false,
      activeItem: 0,
      listeners: {
        scope: this,
        collapse: this.doLayout,
        expand: this.doLayout
      },
      //style: 'padding: 10px 0 0 20px;',
      title: this.app.i18n._('Details'),
      items: [this.NONEcard, this.DAILYcard, this.WEEKLYcard, this.MONTHLYcard, this.YEARLYcard]
    });
    this.idPrefix = Ext.id();
    this.tbar = [{
      id: this.idPrefix + 'tglbtn' + 'NONE',
      xtype: 'tbbtnlockedtoggle',
      enableToggle: true,
      text: this.app.i18n._('None'),
      handler: this.onFreqChange.createDelegate(this, ['NONE']),
      toggleGroup: this.idPrefix + 'freqtglgroup'
    }, {
      id: this.idPrefix + 'tglbtn' + 'DAILY',
      xtype: 'tbbtnlockedtoggle',
      enableToggle: true,
      text: this.app.i18n._('Daily'),
      handler: this.onFreqChange.createDelegate(this, ['DAILY']),
      toggleGroup: this.idPrefix + 'freqtglgroup'
    }, {
      id: this.idPrefix + 'tglbtn' + 'WEEKLY',
      xtype: 'tbbtnlockedtoggle',
      enableToggle: true,
      text: this.app.i18n._('Weekly'),
      handler: this.onFreqChange.createDelegate(this, ['WEEKLY']),
      toggleGroup: this.idPrefix + 'freqtglgroup'
    }, {
      id: this.idPrefix + 'tglbtn' + 'MONTHLY',
      xtype: 'tbbtnlockedtoggle',
      enableToggle: true,
      text: this.app.i18n._('Monthly'),
      handler: this.onFreqChange.createDelegate(this, ['MONTHLY']),
      toggleGroup: this.idPrefix + 'freqtglgroup'
    }, {
      id: this.idPrefix + 'tglbtn' + 'YEARLY',
      xtype: 'tbbtnlockedtoggle',
      enableToggle: true,
      text: this.app.i18n._('Yearly'),
      handler: this.onFreqChange.createDelegate(this, ['YEARLY']),
      toggleGroup: this.idPrefix + 'freqtglgroup'
    }];
    this.items = [this.ruleCards];
    this.eventEditDialog.on('dtStartChange', function (jsonData) {
      var data = Ext.decode(jsonData),
          dtstart = Date.parseDate(data.newValue, Date.patterns.ISO8601Long);
      this.initRrule(dtstart);
    }, this);
    Tine.Calendar.RrulePanel.superclass.initComponent.call(this);
  },
  initRrule: function initRrule(dtstart) {
    if (Ext.isDate(dtstart)) {
      var byday = Tine.Calendar.RrulePanel.prototype.wkdays[dtstart.format('w')];
      var bymonthday = dtstart.format('j');
      var bymonth = dtstart.format('n');
      this.WEEKLYcard.setRule({
        interval: 1,
        byday: byday
      });
      this.MONTHLYcard.setRule({
        interval: 1,
        byday: '1' + byday,
        bymonthday: bymonthday
      });
      this.YEARLYcard.setRule({
        byday: '1' + byday,
        bymonthday: bymonthday,
        bymonth: bymonth
      });
    }
  },
  isValid: function isValid() {
    return this.activeRuleCard.isValid(this.record);
  },
  onFreqChange: function onFreqChange(freq) {
    this.ruleCards.layout.setActiveItem(this[freq + 'card']);
    this.ruleCards.layout.layout();
    this.activeRuleCard = this[freq + 'card'];
  },

  /**
   * disable contents not panel
   */
  setDisabled: function setDisabled(v) {
    this.getTopToolbar().items.each(function (item) {
      item.setDisabled(v);
    }, this);
  },
  onRecordLoad: function onRecordLoad(record) {
    this.record = record;

    if (!this.record.get('editGrant') || this.record.isRecurException() || this.record.hasPoll()) {
      this.setDisabled(true);
    }

    this.rrule = this.record.get('rrule');
    this.initRrule(this.record.get('dtstart'));
    var freq = this.rrule && this.rrule.freq ? this.rrule.freq : 'NONE';
    var freqBtn = Ext.getCmp(this.idPrefix + 'tglbtn' + freq);
    freqBtn.toggle(true);
    this.activeRuleCard = this[freq + 'card'];
    this.ruleCards.activeItem = this.activeRuleCard;
    this.activeRuleCard.setRule(this.rrule);
    this.constrains = this.record.get('rrule_constraints');

    if (this.constrains) {
      var constrainsValue = this.constrains[0].value;

      if (constrainsValue && this.activeRuleCard.constrains) {
        this.activeRuleCard.constrains.setValue(constrainsValue);
      }
    }

    if (this.record.isRecurException()) {
      this.activeRuleCard = this.NONEcard;
      this.items.each(function (item) {
        item.setDisabled(true);
      }, this);
      this.ruleCards.collapsed = false;
      this.NONEcard.html = this.app.i18n._("Exceptions of reccuring events can't have recurrences themselves.");
    }
  },
  onRecordUpdate: function onRecordUpdate(record) {
    var _ = window.lodash,
        rendered = _.get(this, 'activeRuleCard.rendered', false),
        rrule = rendered ? this.activeRuleCard.getRule() : this.rrule;

    if (rrule && (!this.rrule || !this.record.data.creation_time)) {
      // mark as new rule to avoid series confirm dlg
      rrule.newrule = true;
    }

    record.set('rrule', '');
    record.set('rrule', rrule);
    record.set('rrule_constraints', '');

    if (!rendered) {
      record.set('rrule_constraints', this.constrains);
    } else if (this.activeRuleCard.constrains) {
      var constrainsValue = this.activeRuleCard.constrains.getValue();

      if (constrainsValue && constrainsValue.length) {
        record.set('rrule_constraints', [{
          field: 'container_id',
          operator: 'in',
          value: constrainsValue
        }]);
      }
    }
  }
});
Tine.Calendar.RrulePanel.AbstractCard = Ext.extend(Ext.Panel, {
  border: false,
  layout: 'form',
  labelAlign: 'side',
  autoHeight: true,
  getRule: function getRule() {
    var rrule = {
      freq: this.freq,
      interval: this.interval.getValue()
    };

    if (this.untilRadio.checked) {
      rrule.until = this.until.getRawValue();
      rrule.until = rrule.until ? Date.parseDate(rrule.until, this.until.format) : null;

      if (Ext.isDate(rrule.until)) {
        // make sure, last reccurance is included
        rrule.until = rrule.until.clearTime(true).add(Date.HOUR, 24).add(Date.SECOND, -1).format(Date.patterns.ISO8601Long);
      }
    } else {
      rrule.count = this.count.getValue() || 1;
    }

    return rrule;
  },
  onAfterUnitTriggerClick: function onAfterUnitTriggerClick() {
    if (!this.until.getValue()) {
      var dtstart = this.rrulePanel.record.get('dtstart');
      this.until.menu.picker.setValue(dtstart);
    }
  },
  initComponent: function initComponent() {
    this.app = Tine.Tinebase.appMgr.get('Calendar');
    this.limitId = Ext.id();
    this.untilRadio = new Ext.form.Radio({
      requiredGrant: 'editGrant',
      hideLabel: true,
      boxLabel: this.app.i18n._('at'),
      name: this.limitId + 'LimitRadioGroup',
      inputValue: 'UNTIL',
      checked: true,
      listeners: {
        check: this.onLimitRadioCheck.createDelegate(this)
      }
    });
    this.until = new Ext.form.DateField({
      requiredGrant: 'editGrant',
      width: 100,
      emptyText: this.app.i18n._('never'),
      onTriggerClick: Ext.form.DateField.prototype.onTriggerClick.createSequence(this.onAfterUnitTriggerClick, this),
      listeners: {
        scope: this,
        // so dumb!
        render: function render(f) {
          f.wrap.setWidth.defer(100, f.wrap, [f.initialConfig.width]);
        }
      }
    });

    var countStringParts = this.app.i18n._('after {0} occurrences').split('{0}'),
        countBeforeString = countStringParts[0],
        countAfterString = countStringParts[1];

    this.countRadio = new Ext.form.Radio({
      requiredGrant: 'editGrant',
      hideLabel: true,
      boxLabel: countBeforeString,
      name: this.limitId + 'LimitRadioGroup',
      inputValue: 'COUNT',
      listeners: {
        check: this.onLimitRadioCheck.createDelegate(this)
      }
    });
    this.count = new Ext.form.NumberField({
      requiredGrant: 'editGrant',
      style: 'text-align:right;',
      width: 40,
      minValue: 1,
      disabled: true,
      allowDecimals: false,
      allowBlank: false
    });
    var intervalPars = this.intervalString.split('{0}');
    var intervalBeforeString = intervalPars[0];
    var intervalAfterString = intervalPars[1];
    this.interval = new Ext.form.NumberField({
      requiredGrant: 'editGrant',
      style: 'text-align:right;',
      //fieldLabel    : this.intervalBeforeString,
      minValue: 1,
      allowBlank: false,
      value: 1,
      width: 40
    });

    if (!this.items) {
      this.items = [];
    }

    if (this.freq != 'YEARLY') {
      this.items = [{
        layout: 'column',
        items: [{
          width: 70,
          html: intervalBeforeString
        }, this.interval, {
          style: 'padding-top: 2px;',
          html: intervalAfterString
        }]
      }].concat(this.items);
    }

    this.constrains = new Tine.widgets.container.FilterModelMultipleValueField({
      //this.constrains = new Tine.widgets.container.SelectionComboBox({
      app: this.app,
      allowBlank: true,
      width: 260,
      listWidth: 200,
      allowNodeSelect: true,
      recordClass: Tine.Calendar.Model.Event
    });

    if (this.app.featureEnabled('featureRecurExcept')) {
      this.items = this.items.concat([{
        layout: 'hbox',
        //style: 'padding-top: 2px;',
        items: [{
          xtype: 'label',
          style: 'padding-top: 2px;',
          width: 70,
          text: this.app.i18n._('Except')
        }, {
          // @IDEA: this could be a combo later
          // - if one attendee is busy
          // - if organizer is busy
          // - resources are busy
          // - ...
          xtype: 'label',
          style: 'padding-top: 2px;',
          width: 200,
          text: this.app.i18n._('during events in the calendars')
        }, {
          xtype: 'label',
          width: 260,
          id: this.limitId + 'constraints'
        }]
      }]);
    }

    ;
    this.items = this.items.concat({
      layout: 'form',
      html: '<div style="padding-top: 5px;">' + this.app.i18n._('End') + '</div>' + '<div style="position: relative;">' + '<div style="position: relative;">' + '<table><tr>' + '<td width="65" id="' + this.limitId + 'untilRadio"></td>' + '<td width="100" id="' + this.limitId + 'until"></td>' + '</tr></table>' + '</div>' + '<div style="position: relative;">' + '<table><tr>' + '<td width="65" id="' + this.limitId + 'countRadio"></td>' + '<td width="40" id="' + this.limitId + 'count"></td>' + '<td width="40" style="padding-left: 5px" >' + countAfterString + '</td>' + '</tr></table>' + '</div>' + '</div>',
      listeners: {
        scope: this,
        render: this.onLimitRender
      }
    });
    Tine.Calendar.RrulePanel.AbstractCard.superclass.initComponent.call(this);
  },
  onLimitRender: function onLimitRender() {
    var untilradioel = Ext.get(this.limitId + 'untilRadio');
    var untilel = Ext.get(this.limitId + 'until');
    var countradioel = Ext.get(this.limitId + 'countRadio');
    var countel = Ext.get(this.limitId + 'count');

    if (!(untilradioel && countradioel)) {
      return this.onLimitRender.defer(100, this, arguments);
    }

    this.untilRadio.render(untilradioel);
    this.until.render(untilel);
    this.until.wrap.setWidth(80);
    this.countRadio.render(countradioel);
    this.count.render(countel);

    if (this.app.featureEnabled('featureRecurExcept')) {
      this.constrains.render(Ext.get(this.limitId + 'constraints'));
      this.constrains.wrap.setWidth(260);
    }
  },
  onLimitRadioCheck: function onLimitRadioCheck(radio, checked) {
    switch (radio.inputValue) {
      case 'UNTIL':
        this.count.setDisabled(checked);
        break;

      case 'COUNT':
        this.until.setDisabled(checked);
        break;
    }
  },
  isValid: function isValid(record) {
    var until = this.until.getValue(),
        freq = this.freq;

    if (Ext.isDate(until) && Ext.isDate(record.get('dtstart'))) {
      if (until.getTime() < record.get('dtstart').getTime()) {
        this.until.markInvalid(this.app.i18n._('Until has to be after event start'));
        return false;
      }
    }

    if (Ext.isDate(record.get('dtend')) && Ext.isDate(record.get('dtstart'))) {
      var dayDifference = (record.get('dtend').getTime() - record.get('dtstart').getTime()) / 1000 / 60 / 60 / 24,
          dtendField = this.rrulePanel.eventEditDialog.getForm().findField('dtend');

      if (freq == 'DAILY' && dayDifference >= 1) {
        dtendField.markInvalid(this.app.i18n._('The event is longer than the recurring interval'));
        return false;
      } else if (freq == 'WEEKLY' && dayDifference >= 7) {
        dtendField.markInvalid(this.app.i18n._('The event is longer than the recurring interval'));
        return false;
      } else if (freq == 'MONTHLY' && dayDifference >= 28) {
        dtendField.markInvalid(this.app.i18n._('The event is longer than the recurring interval'));
        return false;
      } else if (freq == 'YEARLY' && dayDifference >= 365) {
        dtendField.markInvalid(this.app.i18n._('The event is longer than the recurring interval'));
        return false;
      }
    }

    return true;
  },
  setRule: function setRule(rrule) {
    this.interval.setValue(rrule.interval || 1);
    var date = Date.parseDate(rrule.until, Date.patterns.ISO8601Long);
    this.until.value = date;

    if (rrule.count) {
      this.count.value = rrule.count;
      this.untilRadio.setValue(false);
      this.countRadio.setValue(true);
      this.onLimitRadioCheck(this.untilRadio, false);
      this.onLimitRadioCheck(this.countRadio, true);
    }
  }
});
Tine.Calendar.RrulePanel.DAILYcard = Ext.extend(Tine.Calendar.RrulePanel.AbstractCard, {
  freq: 'DAILY',
  initComponent: function initComponent() {
    this.app = Tine.Tinebase.appMgr.get('Calendar');
    this.intervalString = this.app.i18n._('Every {0}. Day');
    Tine.Calendar.RrulePanel.DAILYcard.superclass.initComponent.call(this);
  }
});
Tine.Calendar.RrulePanel.WEEKLYcard = Ext.extend(Tine.Calendar.RrulePanel.AbstractCard, {
  freq: 'WEEKLY',
  getRule: function getRule() {
    var rrule = Tine.Calendar.RrulePanel.WEEKLYcard.superclass.getRule.call(this);
    var bydayArray = [];
    this.byday.items.each(function (cb) {
      if (cb.checked) {
        bydayArray.push(cb.name);
      }
    }, this);
    rrule.byday = bydayArray.join();

    if (!rrule.byday) {
      rrule.byday = this.byDayValue;
    }

    rrule.wkst = this.wkst || Tine.Calendar.RrulePanel.prototype.wkdays[Ext.DatePicker.prototype.startDay];
    return rrule;
  },
  initComponent: function initComponent() {
    this.app = Tine.Tinebase.appMgr.get('Calendar');
    this.intervalString = this.app.i18n._('Every {0}. Week at');
    var bydayItems = [];

    for (var i = 0, d; i < 7; i++) {
      d = (i + Ext.DatePicker.prototype.startDay) % 7;
      bydayItems.push({
        boxLabel: Date.dayNames[d],
        name: Tine.Calendar.RrulePanel.prototype.wkdays[d]
      });
    }

    this.byday = new Ext.form.CheckboxGroup({
      requiredGrant: 'editGrant',
      style: 'padding-top: 5px;',
      hideLabel: true,
      items: bydayItems
    });
    this.items = [this.byday];
    Tine.Calendar.RrulePanel.WEEKLYcard.superclass.initComponent.call(this);
  },
  setRule: function setRule(rrule) {
    Tine.Calendar.RrulePanel.WEEKLYcard.superclass.setRule.call(this, rrule);
    this.wkst = rrule.wkst;

    if (rrule.byday) {
      this.byDayValue = rrule.byday;
      var bydayArray = rrule.byday.split(',');

      if (Ext.isArray(this.byday.items)) {
        // on initialisation items are not renderd
        Ext.each(this.byday.items, function (cb) {
          cb.checked = bydayArray.indexOf(cb.name) != -1;
        }, this);
      } else {
        // after items are rendered
        this.byday.items.each(function (cb) {
          cb.setValue(bydayArray.indexOf(cb.name) != -1);
        }, this);
      }
    }
  }
});
Tine.Calendar.RrulePanel.MONTHLYcard = Ext.extend(Tine.Calendar.RrulePanel.AbstractCard, {
  freq: 'MONTHLY',
  getRule: function getRule() {
    var rrule = Tine.Calendar.RrulePanel.MONTHLYcard.superclass.getRule.call(this);

    if (this.bydayRadio.checked) {
      rrule.byday = this.wkNumber.getValue() + this.wkDay.getValue();
    } else {
      rrule.bymonthday = this.bymonthdayday.getValue();
    }

    return rrule;
  },
  initComponent: function initComponent() {
    this.app = Tine.Tinebase.appMgr.get('Calendar');
    this.intervalString = this.app.i18n._('Every {0}. Month');
    this.idPrefix = Ext.id();
    this.bydayRadio = new Ext.form.Radio({
      hideLabel: true,
      boxLabel: this.app.i18n._('at the'),
      name: this.idPrefix + 'byRadioGroup',
      inputValue: 'BYDAY',
      checked: true,
      listeners: {
        check: this.onByRadioCheck.createDelegate(this)
      }
    });
    this.wkNumber = new Ext.form.ComboBox({
      requiredGrant: 'editGrant',
      width: 80,
      listWidth: 80,
      triggerAction: 'all',
      hideLabel: true,
      value: 1,
      editable: false,
      mode: 'local',
      store: [[1, this.app.i18n._('first')], [2, this.app.i18n._('second')], [3, this.app.i18n._('third')], [4, this.app.i18n._('fourth')], [-1, this.app.i18n._('last')]]
    });
    var wkdayItems = [];

    for (var i = 0, d; i < 7; i++) {
      d = (i + Ext.DatePicker.prototype.startDay) % 7;
      Tine.Calendar.RrulePanel.prototype.wkdays[d];
      wkdayItems.push([Tine.Calendar.RrulePanel.prototype.wkdays[d], Date.dayNames[d]]);
    }

    this.wkDay = new Ext.form.ComboBox({
      requiredGrant: 'editGrant',
      width: 100,
      listWidth: 100,
      triggerAction: 'all',
      hideLabel: true,
      value: Tine.Calendar.RrulePanel.prototype.wkdays[Ext.DatePicker.prototype.startDay],
      editable: false,
      mode: 'local',
      store: wkdayItems
    });
    this.bymonthdayRadio = new Ext.form.Radio({
      requiredGrant: 'editGrant',
      hideLabel: true,
      boxLabel: this.app.i18n._('at the'),
      name: this.idPrefix + 'byRadioGroup',
      inputValue: 'BYMONTHDAY',
      listeners: {
        check: this.onByRadioCheck.createDelegate(this)
      }
    });
    this.bymonthdayday = new Ext.form.NumberField({
      requiredGrant: 'editGrant',
      style: 'text-align:right;',
      hideLabel: true,
      width: 40,
      value: 1,
      disabled: true
    });
    this.items = [{
      html: '<div style="padding-top: 5px;">' + '<div style="position: relative;">' + '<table><tr>' + '<td style="position: relative;" width="65" id="' + this.idPrefix + 'bydayradio"></td>' + '<td width="100" id="' + this.idPrefix + 'bydaywknumber"></td>' + '<td width="110" id="' + this.idPrefix + 'bydaywkday"></td>' + '</tr></table>' + '</div>' + '<div style="position: relative;">' + '<table><tr>' + '<td width="65" id="' + this.idPrefix + 'bymonthdayradio"></td>' + '<td width="40" id="' + this.idPrefix + 'bymonthdayday"></td>' + '<td>.</td>' + '</tr></table>' + '</div>' + '</div>',
      listeners: {
        scope: this,
        render: this.onByRender
      }
    }];
    Tine.Calendar.RrulePanel.MONTHLYcard.superclass.initComponent.call(this);
  },
  onByRadioCheck: function onByRadioCheck(radio, checked) {
    switch (radio.inputValue) {
      case 'BYDAY':
        this.bymonthdayday.setDisabled(checked);
        break;

      case 'BYMONTHDAY':
        this.wkNumber.setDisabled(checked);
        this.wkDay.setDisabled(checked);
        break;
    }
  },
  onByRender: function onByRender() {
    var bybayradioel = Ext.get(this.idPrefix + 'bydayradio');
    var bybaywknumberel = Ext.get(this.idPrefix + 'bydaywknumber');
    var bybaywkdayel = Ext.get(this.idPrefix + 'bydaywkday');
    var bymonthdayradioel = Ext.get(this.idPrefix + 'bymonthdayradio');
    var bymonthdaydayel = Ext.get(this.idPrefix + 'bymonthdayday');

    if (!(bybayradioel && bymonthdayradioel)) {
      return this.onByRender.defer(100, this, arguments);
    }

    this.bydayRadio.render(bybayradioel);
    this.wkNumber.render(bybaywknumberel);
    this.wkNumber.wrap.setWidth(80);
    this.wkDay.render(bybaywkdayel);
    this.wkDay.wrap.setWidth(100);
    this.bymonthdayRadio.render(bymonthdayradioel);
    this.bymonthdayday.render(bymonthdaydayel);
  },
  setRule: function setRule(rrule) {
    Tine.Calendar.RrulePanel.MONTHLYcard.superclass.setRule.call(this, rrule);

    if (rrule.byday) {
      this.bydayRadio.setValue(true);
      this.bymonthdayRadio.setValue(false);
      this.onByRadioCheck(this.bydayRadio, true);
      this.onByRadioCheck(this.bymonthdayRadio, false);
      var parts = rrule.byday.match(/([\-\d]{1,2})([A-Z]{2})/);
      this.wkNumber.setValue(parts[1]);
      this.wkDay.setValue(parts[2]);
    }

    if (rrule.bymonthday) {
      this.bydayRadio.setValue(false);
      this.bymonthdayRadio.setValue(true);
      this.onByRadioCheck(this.bydayRadio, false);
      this.onByRadioCheck(this.bymonthdayRadio, true);
      this.bymonthdayday.setValue(rrule.bymonthday);
    }
  }
});
Tine.Calendar.RrulePanel.YEARLYcard = Ext.extend(Tine.Calendar.RrulePanel.AbstractCard, {
  freq: 'YEARLY',
  getRule: function getRule() {
    var rrule = Tine.Calendar.RrulePanel.MONTHLYcard.superclass.getRule.call(this);

    if (this.bydayRadio.checked) {
      rrule.byday = this.wkNumber.getValue() + this.wkDay.getValue();
    } else {
      rrule.bymonthday = this.bymonthdayday.getValue();
    }

    rrule.bymonth = this.bymonth.getValue();
    return rrule;
  },
  initComponent: function initComponent() {
    this.app = Tine.Tinebase.appMgr.get('Calendar');
    this.intervalString = this.app.i18n._('Every {0}. Year');
    this.idPrefix = Ext.id();
    this.bydayRadio = new Ext.form.Radio({
      requiredGrant: 'editGrant',
      hideLabel: true,
      boxLabel: this.app.i18n._('at the'),
      name: this.idPrefix + 'byRadioGroup',
      inputValue: 'BYDAY',
      listeners: {
        check: this.onByRadioCheck.createDelegate(this)
      }
    });
    this.wkNumber = new Ext.form.ComboBox({
      requiredGrant: 'editGrant',
      width: 80,
      listWidth: 80,
      triggerAction: 'all',
      hideLabel: true,
      value: 1,
      editable: false,
      mode: 'local',
      disabled: true,
      store: [[1, this.app.i18n._('first')], [2, this.app.i18n._('second')], [3, this.app.i18n._('third')], [4, this.app.i18n._('fourth')], [-1, this.app.i18n._('last')]]
    });
    var wkdayItems = [];

    for (var i = 0, d; i < 7; i++) {
      d = (i + Ext.DatePicker.prototype.startDay) % 7;
      Tine.Calendar.RrulePanel.prototype.wkdays[d];
      wkdayItems.push([Tine.Calendar.RrulePanel.prototype.wkdays[d], Date.dayNames[d]]);
    }

    this.wkDay = new Ext.form.ComboBox({
      requiredGrant: 'editGrant',
      width: 100,
      listWidth: 100,
      triggerAction: 'all',
      hideLabel: true,
      value: Tine.Calendar.RrulePanel.prototype.wkdays[Ext.DatePicker.prototype.startDay],
      editable: false,
      mode: 'local',
      store: wkdayItems,
      disabled: true
    });
    this.bymonthdayRadio = new Ext.form.Radio({
      requiredGrant: 'editGrant',
      hideLabel: true,
      boxLabel: this.app.i18n._('at the'),
      name: this.idPrefix + 'byRadioGroup',
      inputValue: 'BYMONTHDAY',
      checked: true,
      listeners: {
        check: this.onByRadioCheck.createDelegate(this)
      }
    });
    this.bymonthdayday = new Ext.form.NumberField({
      requiredGrant: 'editGrant',
      style: 'text-align:right;',
      hideLabel: true,
      width: 40,
      value: 1
    });
    var monthItems = [];

    for (var i = 0; i < Date.monthNames.length; i++) {
      monthItems.push([i + 1, Date.monthNames[i]]);
    }

    this.bymonth = new Ext.form.ComboBox({
      requiredGrant: 'editGrant',
      width: 100,
      listWidth: 100,
      triggerAction: 'all',
      hideLabel: true,
      value: 1,
      editable: false,
      mode: 'local',
      store: monthItems
    });
    this.items = [{
      html: '<div style="padding-top: 5px;">' + '<div style="position: relative;">' + '<table><tr>' + '<td style="position: relative;" width="65" id="' + this.idPrefix + 'bydayradio"></td>' + '<td width="100" id="' + this.idPrefix + 'bydaywknumber"></td>' + '<td width="110" id="' + this.idPrefix + 'bydaywkday"></td>' + //'<td style="padding-left: 10px">' + this.app.i18n._('of') + '</td>' +
      '</tr></table>' + '</div>' + '<div style="position: relative;">' + '<table><tr>' + '<td width="65" id="' + this.idPrefix + 'bymonthdayradio"></td>' + '<td width="40" id="' + this.idPrefix + 'bymonthdayday"></td>' + '<td>.</td>' + '<td width="15" style="padding-left: 37px">' + this.app.i18n._('of') + '</td>' + '<td width="100" id="' + this.idPrefix + 'bymonth"></td>' + '</tr></table>' + '</div>' + '</div>',
      listeners: {
        scope: this,
        render: this.onByRender
      }
    }];
    Tine.Calendar.RrulePanel.YEARLYcard.superclass.initComponent.call(this);
  },
  onByRadioCheck: function onByRadioCheck(radio, checked) {
    switch (radio.inputValue) {
      case 'BYDAY':
        this.bymonthdayday.setDisabled(checked);
        break;

      case 'BYMONTHDAY':
        this.wkNumber.setDisabled(checked);
        this.wkDay.setDisabled(checked);
        break;
    }
  },
  onByRender: function onByRender() {
    var bybayradioel = Ext.get(this.idPrefix + 'bydayradio');
    var bybaywknumberel = Ext.get(this.idPrefix + 'bydaywknumber');
    var bybaywkdayel = Ext.get(this.idPrefix + 'bydaywkday');
    var bymonthdayradioel = Ext.get(this.idPrefix + 'bymonthdayradio');
    var bymonthdaydayel = Ext.get(this.idPrefix + 'bymonthdayday');
    var bymonthel = Ext.get(this.idPrefix + 'bymonth');

    if (!(bybayradioel && bymonthdayradioel)) {
      return this.onByRender.defer(100, this, arguments);
    }

    this.bydayRadio.render(bybayradioel);
    this.wkNumber.render(bybaywknumberel);
    this.wkNumber.wrap.setWidth(80);
    this.wkDay.render(bybaywkdayel);
    this.wkDay.wrap.setWidth(100);
    this.bymonthdayRadio.render(bymonthdayradioel);
    this.bymonthdayday.render(bymonthdaydayel);
    this.bymonth.render(bymonthel);
    this.bymonth.wrap.setWidth(100);
  },
  setRule: function setRule(rrule) {
    Tine.Calendar.RrulePanel.MONTHLYcard.superclass.setRule.call(this, rrule);

    if (rrule.byday) {
      this.bydayRadio.setValue(true);
      this.bymonthdayRadio.setValue(false);
      this.onByRadioCheck(this.bydayRadio, true);
      this.onByRadioCheck(this.bymonthdayRadio, false);
      var parts = rrule.byday.match(/([\-\d]{1,2})([A-Z]{2})/);
      this.wkNumber.setValue(parts[1]);
      this.wkDay.setValue(parts[2]);
    }

    if (rrule.bymonthday) {
      this.bydayRadio.setValue(false);
      this.bymonthdayRadio.setValue(true);
      this.onByRadioCheck(this.bydayRadio, false);
      this.onByRadioCheck(this.bymonthdayRadio, true);
      this.bymonthdayday.setValue(rrule.bymonthday);
    }

    this.bymonth.setValue(rrule.bymonth);
  }
});

/***/ }),

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

/*
 * Tine 2.0
 * 
 * @package     Calendar
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2009 Metaways Infosystems GmbH (http://www.metaways.de)
 *
 */
Ext.ns('Tine.Calendar');
/**
 * @namespace Tine.Calendar
 * @class     Tine.Calendar.ResourceGridPanel
 * @extends   Tine.widgets.grid.GridPanel
 * Resources Grid Panel <br>
 * 
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 */

Tine.Calendar.ResourceGridPanel = Ext.extend(Tine.widgets.grid.GridPanel, {
  // model generics
  recordClass: Tine.Calendar.Model.Resource,
  // grid specific
  defaultSortInfo: {
    field: 'name',
    dir: 'ASC'
  },
  // not yet
  evalGrants: false,
  newRecordIcon: 'cal-resource',
  ownActionToolbar: true,
  initComponent: function initComponent() {
    this.app = Tine.Tinebase.appMgr.get('Calendar');
    this.gridConfig = {
      autoExpandColumn: 'name'
    };
    this.gridConfig.columns = [{
      id: 'name',
      header: this.app.i18n._("Name"),
      width: 150,
      sortable: true,
      dataIndex: 'name'
    }, {
      id: 'hierarchy',
      header: this.app.i18n._("Calendar Hierarchy/Name"),
      width: 150,
      sortable: true,
      dataIndex: 'hierarchy'
    }, {
      id: 'email',
      header: this.app.i18n._("Email"),
      width: 150,
      sortable: true,
      dataIndex: 'email'
    }, {
      id: 'type',
      header: this.app.i18n._("Type"),
      width: 150,
      sortable: true,
      dataIndex: 'type',
      renderer: Tine.Tinebase.widgets.keyfield.Renderer.get('Calendar', 'resourceTypes')
    }, {
      id: 'max_number_of_people',
      header: this.app.i18n._("Maximum number of attendee"),
      width: 150,
      sortable: true,
      dataIndex: 'max_number_of_people'
    }, {
      id: 'status',
      dataIndex: 'status',
      width: 140,
      header: this.app.i18n._('Default Status'),
      renderer: Tine.Tinebase.widgets.keyfield.Renderer.get('Calendar', 'attendeeStatus')
    }, {
      id: 'busy_type',
      dataIndex: 'busy_type',
      width: 140,
      header: this.app.i18n._('Busy Type'),
      renderer: Tine.Tinebase.widgets.keyfield.Renderer.get('Calendar', 'freebusyTypes')
    }, {
      id: 'site',
      header: this.app.i18n._('Site'),
      width: 150,
      dataIndex: 'relations',
      renderer: Tine.Calendar.ResourceGridPanel.siteRenderer,
      sortable: false
    }, {
      id: 'location',
      header: this.app.i18n._('Location'),
      width: 150,
      dataIndex: 'relations',
      renderer: Tine.Calendar.ResourceGridPanel.locationRenderer,
      sortable: false
    }, {
      id: 'color',
      header: this.app.i18n._('Color'),
      width: 30,
      sortable: false,
      renderer: Tine.Tinebase.common.colorRenderer,
      dataIndex: 'color'
    }];
    Tine.Calendar.ResourceGridPanel.superclass.initComponent.call(this);
  },

  /**
   * preform the initial load of grid data
   */
  initialLoad: function initialLoad() {
    this.store.load.defer(10, this.store, [typeof this.autoLoad == 'object' ? this.autoLoad : undefined]);
  }
});
Ext.reg('calendar.resourcegridpanel', Tine.Calendar.ResourceGridPanel);
/**
 * render site relation
 *
 * @param data
 * @param cell
 * @param record
 * @returns {*|String}
 */

Tine.Calendar.ResourceGridPanel.siteRenderer = function (data, cell, record) {
  var _ = window.lodash;

  if (Ext.isArray(data) && data.length > 0) {
    var index = 0;

    while (index < data.length && data[index].type != 'SITE') {
      index++;
    }

    if (data[index]) {
      return Ext.util.Format.htmlEncode(_.get(data[index], 'related_record.n_fileas', i18n._('No Access')));
    }
  }
};
/**
 * render location relation
 *
 * @param data
 * @param cell
 * @param record
 * @returns {*|String}
 */


Tine.Calendar.ResourceGridPanel.locationRenderer = function (data, cell, record) {
  var _ = window.lodash;

  if (Ext.isArray(data) && data.length > 0) {
    var index = 0;

    while (index < data.length && data[index].type != 'LOCATION') {
      index++;
    }

    if (data[index]) {
      return Ext.util.Format.htmlEncode(_.get(data[index], 'related_record.n_fileas', i18n._('No Access')));
    }
  }
};

/***/ }),

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

/*
 * Tine 2.0
 * 
 * @package     Calendar
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2009-2017 Metaways Infosystems GmbH (http://www.metaways.de)
 *
 */
Ext.ns('Tine.Calendar');
/**
 * @namespace Tine.Calendar
 * @class     Tine.Calendar.ResourceEditDialog
 * @extends   Tine.widgets.dialog.EditDialog
 * Resources Grid Panel <br>
 * 
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 */

Tine.Calendar.ResourceEditDialog = Ext.extend(Tine.widgets.dialog.EditDialog, {
  recordClass: Tine.Calendar.Model.Resource,
  windowNamePrefix: 'ResourceEditWindow_',
  evalGrants: true,
  showContainerSelector: false,
  tbarItems: [],
  requiredSaveGrant: 'resourceEditGrant',

  /**
   *
   * @returns {{xtype: string, border: boolean, plain: boolean, activeTab: number, border: boolean, items: [null,null,null]}}
   */
  getFormItems: function getFormItems() {
    this.grantsGridPanel = new Tine.widgets.container.GrantsGrid({
      recordClass: Tine.Calendar.Model.ResourceGrants,
      grantContainer: {
        application_id: this.app.id,
        type: Tine.Tinebase.container.TYPE_SHARED,
        model: 'Calendar_Model_Event',
        xprops: {
          Tinebase: {
            Container: {
              GrantsModel: 'Calendar_Model_ResourceGrants'
            }
          }
        }
      }
    });
    return {
      xtype: 'tabpanel',
      plain: true,
      activeTab: 0,
      border: false,
      items: [{
        title: this.app.i18n.n_('Resource', 'Resources', 1),
        autoScroll: true,
        border: false,
        frame: true,
        layout: 'border',
        items: [{
          region: 'center',
          xtype: 'columnform',
          labelAlign: 'top',
          formDefaults: {
            xtype: 'textfield',
            anchor: '100%',
            labelSeparator: '',
            columnWidth: .333
          },
          items: [[{
            xtype: 'textfield',
            fieldLabel: this.app.i18n._('Name'),
            allowBlank: false,
            name: 'name'
          }, {
            xtype: 'textfield',
            fieldLabel: this.app.i18n._('Email'),
            allowBlank: false,
            name: 'email',
            vtype: 'email'
          }, new Tine.Tinebase.widgets.keyfield.ComboBox({
            app: 'Calendar',
            keyFieldName: 'resourceTypes',
            fieldLabel: this.app.i18n._('Type'),
            name: 'type'
          })], [{
            xtype: 'textfield',
            fieldLabel: this.app.i18n._('Calendar Hierarchy/Name'),
            allowBlank: true,
            columnWidth: 1,
            name: 'hierarchy'
          }], [new Tine.Tinebase.widgets.keyfield.ComboBox({
            app: 'Calendar',
            keyFieldName: 'attendeeStatus',
            fieldLabel: this.app.i18n._('Default attendee status'),
            name: 'status',
            value: 'NEEDS-ACTION'
          }), new Tine.Tinebase.widgets.keyfield.ComboBox({
            app: 'Calendar',
            keyFieldName: 'freebusyTypes',
            fieldLabel: this.app.i18n._('Busy Type'),
            name: 'busy_type'
          }), {
            xtype: 'numberfield',
            fieldLabel: this.app.i18n._('Maximum number of attendee'),
            allowNegative: false,
            allowBlank: true,
            name: 'max_number_of_people'
          }], [{
            xtype: 'tinerelationpickercombo',
            fieldLabel: this.app.i18n._('Site'),
            editDialog: this,
            allowBlank: true,
            app: 'Addressbook',
            recordClass: Tine.Addressbook.Model.Contact,
            relationType: 'SITE',
            relationDegree: 'child',
            ref: '../../../../../site',
            listeners: {
              scope: this,
              select: this.onSiteSelect
            }
          }, {
            xtype: 'tinerelationpickercombo',
            fieldLabel: this.app.i18n._('Location'),
            editDialog: this,
            allowBlank: true,
            app: 'Addressbook',
            recordClass: Tine.Addressbook.Model.Contact,
            relationType: 'LOCATION',
            relationDegree: 'child',
            ref: '../../../../../location'
          }, {
            xtype: 'checkbox',
            fieldLabel: this.app.i18n._('Suppress notification'),
            name: 'suppress_notification'
          }, {
            xtype: 'colorfield',
            allowBlank: true,
            fieldLabel: this.app.i18n._('Color'),
            name: 'color'
          }], [{
            columnWidth: 1,
            fieldLabel: this.app.i18n._('Description'),
            emptyText: this.app.i18n._('Enter description...'),
            name: 'description',
            xtype: 'textarea',
            height: 200
          }]]
        }, {
          // activities and tags
          layout: 'ux.multiaccordion',
          animate: true,
          region: 'east',
          width: 210,
          split: true,
          collapsible: true,
          collapseMode: 'mini',
          header: false,
          margins: '0 5 0 5',
          border: true,
          items: [new Tine.widgets.tags.TagPanel({
            app: 'Calendar',
            border: false,
            bodyStyle: 'border:1px solid #B5B8C8;'
          })]
        }]
      }, {
        title: this.app.i18n._('Grants'),
        layout: 'fit',
        items: this.grantsGridPanel
      }, new Tine.widgets.activities.ActivitiesTabPanel({
        app: this.appName,
        record_id: this.record.id,
        record_model: this.appName + '_Model_' + this.recordClass.getMeta('modelName')
      })]
    };
  },
  onAfterRecordLoad: function onAfterRecordLoad() {
    Tine.Calendar.ResourceEditDialog.superclass.onAfterRecordLoad.apply(this, arguments);

    if (this.record.data && this.record.data.grants) {
      this.grantsGridPanel.getStore().loadData({
        results: this.record.data.grants
      });
    }

    this.getForm().items.each(function (f) {
      if (f.isFormField && f.requiredGrant !== undefined) {
        var hasRequiredGrant = _.get(this.record, this.recordClass.getMeta('grantsPath') + '.resourceEditGrant');

        f.setDisabled(!hasRequiredGrant);
      }
    }, this);
  },
  onRecordUpdate: function onRecordUpdate() {
    var grantsData = [];
    this.grantsGridPanel.getStore().each(function (r) {
      grantsData.push(r.data);
    }, this);
    this.record.set('grants', '');
    this.record.set('grants', grantsData);
    Tine.Calendar.ResourceEditDialog.superclass.onRecordUpdate.apply(this, arguments);
  },
  onSiteSelect: function onSiteSelect(field, newValue) {
    if (!this.location.getValue()) {
      this.location.setValue(newValue);
    }
  }
});
/**
 * Opens a new resource edit dialog window
 * 
 * @return {Ext.ux.Window}
 */

Tine.Calendar.ResourceEditDialog.openWindow = function (config) {
  var id = config.record && config.record.id ? config.record.id : 0;
  var window = Tine.WindowFactory.getWindow({
    width: 1024,
    height: 430,
    name: Tine.Calendar.ResourceEditDialog.prototype.windowNamePrefix + id,
    contentPanelConstructor: 'Tine.Calendar.ResourceEditDialog',
    contentPanelConstructorConfig: config
  });
  return window;
};

/***/ }),

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

/* 
 * Tine 2.0
 * 
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2009-2011 Metaways Infosystems GmbH (http://www.metaways.de)
 */
Ext.ns('Tine.Calendar');
/**
 * show all events, given contact record is attender of
 * 
 * NOTE: This Grid does not show recuings yet!
 *       If we want to display recurings we need to add a period filter.
 *       We might be able to do so after we have a generic calendar list widget
 *       with a generic period paging tbar
 *       
 * @namespace   Tine.Calendar
 * @class       Tine.Calendar.ContactEventsGridPanel
 * @extends     Tine.widgets.grid.GridPanel
 */

Tine.Calendar.ContactEventsGridPanel = Ext.extend(Tine.widgets.grid.GridPanel, {
  /**
   * record class
   * @cfg {Tine.Addressbook.Model.Contact} recordClass
   */
  recordClass: Tine.Calendar.Model.Event,

  /**
   * @cfg {Ext.data.DataProxy} recordProxy
   */
  recordProxy: Tine.Calendar.backend,

  /**
   * grid specific
   * @private
   */
  stateful: false,
  defaultSortInfo: {
    field: 'dtstart',
    direction: 'ASC'
  },
  gridConfig: {
    autoExpandColumn: 'summary'
  },

  /**
   * @cfg {Bool} hasDetailsPanel 
   */
  hasDetailsPanel: true,
  initComponent: function initComponent() {
    this.app = Tine.Tinebase.appMgr.get('Calendar');
    this.title = this.app.i18n._('Events');
    this.record = this.editDialog.record;
    this.gridConfig.cm = this.getColumnModel();
    this.initFilterToolbar();
    this.plugins = this.plugins || [];
    this.plugins.push(this.filterToolbar);
    Tine.Calendar.ContactEventsGridPanel.superclass.initComponent.call(this);
  },

  /**
   * perform the initial load of grid data
   */
  initialLoad: function initialLoad() {
    this.store.load.defer(10, this.store, [typeof this.autoLoad == 'object' ? this.autoLoad : undefined]);
  },

  /**
   * called before store queries for data
   */
  onStoreBeforeload: function onStoreBeforeload(store, options) {
    Tine.Calendar.ContactEventsGridPanel.superclass.onStoreBeforeload.apply(this, arguments); // prevent adding of fixed calendars

    options.params.addFixedCalendars = false;
  },

  /**
   * initialises filter toolbar
   *  @private
   */
  initFilterToolbar: function initFilterToolbar() {
    this.filterToolbar = new Tine.widgets.grid.FilterToolbar({
      recordClass: this.recordClass,
      neverAllowSaving: true,
      filterModels: Tine.Calendar.Model.Event.getFilterModel(),
      defaultFilter: 'query',
      filters: [{
        field: 'query',
        operator: 'contains',
        value: ''
      }, {
        field: 'attender',
        operator: 'in',
        value: [{
          user_type: 'user',
          user_id: this.record.id ? this.record.data : ''
        }]
      }]
    });
  },

  /**
   * returns cm
   * 
   * @return Ext.grid.ColumnModel
   * @private
   */
  getColumnModel: function getColumnModel() {
    return new Ext.grid.ColumnModel({
      defaults: {
        sortable: true,
        resizable: true
      },
      columns: [{
        id: 'summary',
        header: this.app.i18n._("Summary"),
        width: 350,
        sortable: true,
        dataIndex: 'summary'
      }, {
        id: 'dtstart',
        header: this.app.i18n._("Start Time"),
        width: 150,
        sortable: true,
        dataIndex: 'dtstart',
        renderer: Tine.Tinebase.common.dateTimeRenderer
      }, {
        id: 'attendee_status',
        header: this.app.i18n._("Status"),
        width: 100,
        sortable: true,
        dataIndex: 'attendee',
        renderer: this.attendeeStatusRenderer.createDelegate(this)
      }]
    });
  },
  attendeeStatusRenderer: function attendeeStatusRenderer(attendee) {
    var store = new Tine.Calendar.Model.Attender.getAttendeeStore(attendee),
        attender = null;
    store.each(function (a) {
      if (a.getUserId() == this.record.id && a.get('user_type') == 'user') {
        attender = a;
        return false;
      }
    }, this);

    if (attender) {
      return Tine.Tinebase.widgets.keyfield.Renderer.render('Calendar', 'attendeeStatus', attender.get('status'));
    }
  }
});

/***/ }),

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

/*
 * Tine 2.0
 * 
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2011-2012 Metaways Infosystems GmbH (http://www.metaways.de)
 */
Ext.ns('Tine.Calendar');
/**
 * display panel for MIME type text/calendar
 * 
 * NOTE: this panel is registered on Tine.Calendar::init
 * 
 * @namespace   Tine.Calendar
 * @class       Tine.Calendar.iMIPDetailsPanel
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @constructor
 */

Tine.Calendar.iMIPDetailsPanel = Ext.extend(Tine.Calendar.EventDetailsPanel, {
  /**
   * @cfg {Object} preparedPart
   * server prepared text/calendar iMIP part 
   */
  preparedPart: null,

  /**
   * @property actionToolbar
   * @type Ext.Toolbar
   */
  actionToolbar: null,

  /**
   * @property iMIPrecord
   * @type Tine.Calendar.Model.iMIP
   */
  iMIPrecord: null,

  /**
   * @property statusActions
   * @type Array
   */
  statusActions: [],

  /**
   * init this component
   */
  initComponent: function initComponent() {
    this.app = Tine.Tinebase.appMgr.get('Calendar');
    this.iMIPrecord = new Tine.Calendar.Model.iMIP(this.preparedPart.preparedData);

    if (!this.iMIPrecord.get('event') || !Ext.isFunction(this.iMIPrecord.get('event').beginEdit)) {
      this.iMIPrecord.set('event', Tine.Calendar.backend.recordReader({
        responseText: Ext.util.JSON.encode(this.preparedPart.preparedData.event)
      }));
    }

    this.initIMIPToolbar();
    this.on('afterrender', this.showIMIP, this);
    Tine.Calendar.iMIPDetailsPanel.superclass.initComponent.call(this);
  },

  /**
   * (re) prepare IMIP
   */
  prepareIMIP: function prepareIMIP() {
    this.iMIPclause.setText(this.app.i18n._('Checking Calendar Data...'));
    Tine.Calendar.iMIPPrepare(this.iMIPrecord.data, function (result, response) {
      this.preparedPart.preparedData = result;

      if (response.error) {
        // give up!
        this.iMIPrecord.set('preconditions', {
          'GENERIC': 'generic problem'
        });
      } else {
        this.iMIPrecord = new Tine.Calendar.Model.iMIP(result);
        this.iMIPrecord.set('event', Tine.Calendar.backend.recordReader({
          responseText: Ext.util.JSON.encode(result.event)
        }));
      }

      this.showIMIP();
    }, this);
  },

  /**
   * process IMIP
   * 
   * @param {String} status
   */
  processIMIP: function processIMIP(status, range) {
    if (this.iMIPrecord.get('event').isRecurBase() && status != 'ACCEPTED' && !range) {
      Tine.widgets.dialog.MultiOptionsDialog.openWindow({
        title: this.app.i18n._('Reply to Recurring Event'),
        questionText: this.app.i18n._('You are responding to an recurring event. What would you like to do?'),
        height: 170,
        scope: this,
        options: [{
          text: this.app.i18n._('Respond to whole series'),
          name: 'series'
        }, {
          text: this.app.i18n._('Do not respond'),
          name: 'cancel'
        }],
        handler: function handler(option) {
          if (option != 'cancel') {
            this.processIMIP(status, option);
          }
        }
      });
      return;
    }

    Tine.log.debug('Tine.Calendar.iMIPDetailsPanel::processIMIP status: ' + status);
    this.getLoadMask().show();
    Tine.Calendar.iMIPProcess(this.iMIPrecord.data, status, function (result, response) {
      this.preparedPart.preparedData = result;

      if (response.error) {
        // precondition changed?  
        return this.prepareIMIP();
      } // load result


      this.iMIPrecord = new Tine.Calendar.Model.iMIP(result);
      this.iMIPrecord.set('event', Tine.Calendar.backend.recordReader({
        responseText: Ext.util.JSON.encode(result.event)
      }));
      this.showIMIP();
    }, this);
  },

  /**
   * iMIP action toolbar
   */
  initIMIPToolbar: function initIMIPToolbar() {
    var singleRecordPanel = this.getSingleRecordPanel();
    this.actions = [];
    this.statusActions = [];
    Tine.Tinebase.widgets.keyfield.StoreMgr.get('Calendar', 'attendeeStatus').each(function (status) {
      // NEEDS-ACTION is not appropriate in iMIP context
      if (status.id == 'NEEDS-ACTION') return;
      this.statusActions.push(new Ext.Action({
        text: status.get('i18nValue'),
        handler: this.processIMIP.createDelegate(this, [status.id]),
        icon: status.get('icon')
      }));
    }, this);
    this.actions = this.actions.concat(this.statusActions); // add more actions here (no spam / apply / crush / send event / ...)

    this.iMIPclause = new Ext.Toolbar.TextItem({
      text: ''
    });
    this.tbar = this.actionToolbar = new Ext.Toolbar({
      items: [{
        xtype: 'tbitem',
        cls: 'CalendarIconCls',
        width: 16,
        height: 16,
        style: 'margin: 3px 5px 2px 5px;'
      }, this.iMIPclause, '->'].concat(this.actions)
    });
  },

  /**
   * show/layout iMIP panel
   */
  showIMIP: function showIMIP() {
    var singleRecordPanel = this.getSingleRecordPanel(),
        preconditions = this.iMIPrecord.get('preconditions'),
        method = this.iMIPrecord.get('method'),
        event = this.iMIPrecord.get('event'),
        existingEvent = this.iMIPrecord.get('existing_event') ? Tine.Calendar.backend.recordReader({
      responseText: Ext.util.JSON.encode(this.iMIPrecord.get('existing_event'))
    }) : null,
        myAttenderRecord = existingEvent ? existingEvent.getMyAttenderRecord() : event.getMyAttenderRecord(),
        myAttenderstatus = myAttenderRecord ? myAttenderRecord.get('status') : null; // show container from existing event if exists

    if (existingEvent && existingEvent.container_id) {
      event.set('container_id', existingEvent.container_id);
    } // reset actions


    Ext.each(this.actions, function (action) {
      action.setHidden(true);
    }); // check preconditions

    if (preconditions) {
      if (preconditions.hasOwnProperty('EVENTEXISTS')) {
        this.iMIPclause.setText(this.app.i18n._("The event of this message does not exist"));
      } else if (preconditions.hasOwnProperty('ORIGINATOR')) {
        // display spam box -> might be accepted by user?
        this.iMIPclause.setText(this.app.i18n._("The sender is not authorised to update the event"));
      } else if (preconditions.hasOwnProperty('RECENT')) {
        //            else if (preconditions.hasOwnProperty('TOPROCESS')) {
        this.iMIPclause.setText(this.app.i18n._("This message is already processed"));
      } else if (preconditions.hasOwnProperty('ATTENDEE')) {
        // party crush button?
        this.iMIPclause.setText(this.app.i18n._("You are not an attendee of this event"));
      } else if (preconditions.hasOwnProperty('NOTDELETED')) {
        this.iMIPclause.setText(this.app.i18n._("This event has been deleted by the organizer"));
      } else if (preconditions.hasOwnProperty('NOTCANCELLED')) {
        this.iMIPclause.setText(this.app.i18n._("This event has been canceled."));
      } else {
        this.iMIPclause.setText(this.app.i18n._("Unsupported message"));
      }
    } // method specific text / actions
    else {
        switch (method) {
          case 'REQUEST':
            if (!myAttenderRecord) {
              // might happen in shared folders -> we might want to become a party crusher?
              this.iMIPclause.setText(this.app.i18n._("This is an event invitation for someone else."));
              break;
            } else if (existingEvent && myAttenderstatus !== 'NEEDS-ACTION' && (event.get('external_seq') <= existingEvent.get('external_seq') || event.get('seq') <= existingEvent.get('seq'))) {
              this.iMIPclause.setText(this.app.i18n._("You have already replied to this event invitation."));
            } else if (existingEvent && existingEvent.isRescheduled(event)) {
              this.iMIPclause.setText(this.app.i18n._('The event got rescheduled. Set your response to:'));
            } else {
              this.iMIPclause.setText(this.app.i18n._('You received an event invitation. Set your response to:'));
            }

            Ext.each(this.statusActions, function (action) {
              action.setHidden(false);
            });
            break;

          case 'REPLY':
            // Someone replied => autoprocessing atm.
            this.iMIPclause.setText(this.app.i18n._('An invited attendee responded to the invitation.'));
            break;

          case 'CANCEL':
            this.iMIPclause.setText(this.app.i18n._('This event has been canceled.'));
            break;

          default:
            this.iMIPclause.setText(this.app.i18n._("Unsupported method"));
            break;
        }
      }

    this.getLoadMask().hide();
    singleRecordPanel.setVisible(true);
    singleRecordPanel.setHeight(150);
    this.record = existingEvent && !preconditions ? existingEvent : event;
    singleRecordPanel.loadRecord(this.record);
  }
});

/***/ }),

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

/*
 * Tine 2.0
 * 
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2011-2014 Metaways Infosystems GmbH (http://www.metaways.de)
 */
Ext.ns('Tine.Calendar');
/**
 * render the CalDAV Url into property panel of containers
 * 
 * @class   Tine.Calendar.CalDAVContainerPropertiesHookField
 * @extends Tine.widgets.container.CalDAVContainerPropertiesHookField
 */

Tine.Calendar.CalDAVContainerPropertiesHookField = Ext.extend(Tine.widgets.container.CalDAVContainerPropertiesHookField, {
  appName: 'Calendar'
});
Ext.ux.ItemRegistry.registerItem('Tine.widgets.container.PropertiesDialog.FormItems.Properties', Tine.Calendar.CalDAVContainerPropertiesHookField, 100);

/***/ }),

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

/*
 * Tine 2.0
 * 
 * @package     Calendar
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Alexander Stintzing <alex@stintzing.net>
 * @copyright   Copyright (c) 2009-2012 Metaways Infosystems GmbH (http://www.metaways.de)
 *
 */
Ext.ns('Tine.Calendar');
/**
 * @namespace   Tine.Calendar
 * @class       Tine.Calendar.AddToEventPanel
 * @extends     Tine.widgets.dialog.AddToRecordPanel
 * @author      Alexander Stintzing <alex@stintzing.net>
 */

Tine.Calendar.AddToEventPanel = Ext.extend(Tine.widgets.dialog.AddToRecordPanel, {
  // private
  appName: 'Calendar',
  recordClass: Tine.Calendar.Model.Event,
  callingApp: 'Addressbook',
  callingModel: 'Contact',

  /**
   * @see Tine.widgets.dialog.AddToRecordPanel::isValid()
   */
  isValid: function isValid() {
    var valid = true;

    if (this.searchBox.getValue() == '') {
      this.searchBox.markInvalid(this.app.i18n._('Please choose the Event to add the contacts to'));
      valid = false;
    }

    return valid;
  },

  /**
   * @see Tine.widgets.dialog.AddToRecordPanel::getRelationConfig()
   */
  getRelationConfig: function getRelationConfig() {
    var config = {
      role: this.chooseRoleBox.getValue(),
      status: this.chooseStatusBox.getValue()
    };
    return config;
  },

  /**
   * @see Tine.widgets.dialog.AddToRecordPanel::getFormItems()
   */
  getFormItems: function getFormItems() {
    return {
      border: false,
      frame: false,
      layout: 'border',
      items: [{
        region: 'center',
        border: false,
        frame: false,
        layout: {
          align: 'stretch',
          type: 'vbox'
        },
        items: [{
          layout: 'form',
          margins: '10px 10px',
          border: false,
          frame: false,
          items: [Tine.widgets.form.RecordPickerManager.get('Calendar', 'Event', {
            ref: '../../../searchBox',
            onStoreLoad: function onStoreLoad(store, records) {
              store.each(function (record) {
                // Only show records with edit grant
                if (!record.data.editGrant) {
                  store.remove(record);
                }
              });
            }
          }), {
            fieldLabel: this.app.i18n._('Role'),
            emptyText: this.app.i18n._('Select Role'),
            xtype: 'widget-keyfieldcombo',
            app: 'Calendar',
            value: 'REQ',
            anchor: '100% 100%',
            margins: '10px 10px',
            keyFieldName: 'attendeeRoles',
            ref: '../../../chooseRoleBox'
          }, {
            fieldLabel: this.app.i18n._('Status'),
            emptyText: this.app.i18n._('Select Status'),
            xtype: 'widget-keyfieldcombo',
            app: 'Calendar',
            value: 'NEEDS-ACTION',
            anchor: '100% 100%',
            margins: '10px 10px',
            keyFieldName: 'attendeeStatus',
            ref: '../../../chooseStatusBox'
          }]
        }]
      }]
    };
  }
});

Tine.Calendar.AddToEventPanel.openWindow = function (config) {
  var window = Tine.WindowFactory.getWindow({
    modal: true,
    title: String.format(Tine.Tinebase.appMgr.get('Calendar').i18n._('Adding {0} Attendee to event'), config.count),
    width: 240,
    height: 250,
    contentPanelConstructor: 'Tine.Calendar.AddToEventPanel',
    contentPanelConstructorConfig: config
  });
  return window;
};

/***/ }),

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

/*
 * Tine 2.0
 * 
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2007-2011 Metaways Infosystems GmbH (http://www.metaways.de)
 */
Ext.ns('Tine.Calendar');
/**
 * render event container_id
 */

Tine.Calendar.calendarRenderer = function (value, metaData, record, rowIndex, colIndex, store) {
  var app = Tine.Tinebase.appMgr.get('Calendar');

  if (record) {
    // no record after delete
    var originContainer = record.get('container_id'),
        displayContainer = record.getDisplayContainer(),
        containerHtml = '',
        tip = ''; // show origin (if available)

    if (!Ext.isPrimitive(originContainer)) {
      containerHtml = Tine.Tinebase.common.containerRenderer(originContainer);
    } else {
      containerHtml = Tine.Tinebase.common.containerRenderer(displayContainer);
    }

    tip += Ext.isPrimitive(originContainer) ? Ext.util.Format.htmlEncode(app.i18n._("This event is originally stored in a calendar you don't have access to.")) : String.format(Ext.util.Format.htmlEncode(app.i18n._("This event is originally stored in {0}")), Ext.util.Format.htmlEncode(Tine.Tinebase.common.containerRenderer(originContainer)));
    tip += displayContainer && !Tine.Tinebase.container.pathIsMyPersonalContainer(originContainer.path) ? String.format(Ext.util.Format.htmlEncode(app.i18n._("This event is additionally displayed in your personal calendar {0}")), Ext.util.Format.htmlEncode(Tine.Tinebase.common.containerRenderer(displayContainer))) : '';
    return containerHtml.replace('<div ', '<div ext:qtip="' + tip + '" ');
  } else {
    return Tine.Tinebase.common.containerRenderer(value);
  }
};

Tine.widgets.grid.RendererManager.register('Calendar', 'Event', 'container_id', Tine.Calendar.calendarRenderer);

/***/ }),

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

/*
 * Tine 2.0
 * 
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Michael Spahn <m.spahn@metaways.de>
 * @copyright   Copyright (c) 2014 Metaways Infosystems GmbH (http://www.metaways.de)
 */
Ext.ns('Tine.Calendar');
/**
 * Simple Import Dialog
 *
 * @namespace   Tine.widgets.dialog
 * @class       Tine.widgets.dialog.ImportDialog
 * @extends     Tine.widgets.dialog.EditDialog
 * @constructor
 * @param       {Object} config The configuration options.
 * 
 * TODO add app grid to show results when dry run is selected
 */

Tine.Calendar.ImportDialog = Ext.extend(Tine.widgets.dialog.ImportDialog, {
  appName: 'Calendar',
  modelName: 'Event',

  /**
   * init import wizard
   */
  initComponent: function initComponent() {
    Tine.log.debug('Tine.Calendar.ImportDialog::initComponent');
    Tine.log.debug(this);
    Tine.Calendar.ImportDialog.superclass.initComponent.call(this);
  },
  getItems: function getItems() {
    return [this.getPanel()];
  },

  /**
   * do import request
   * 
   * @param {Function} callback
   * @param {Object}   importOptions
   */
  doImport: function doImport(callback, importOptions, clientRecordData) {
    var targetContainer = this.containerCombo.getValue();
    var type = this.typeCombo.getValue();
    var params = {
      importOptions: Ext.apply({
        container_id: targetContainer,
        sourceType: this.typeCombo.getValue(),
        importFileByScheduler: this.typeCombo.getValue() == 'remote_caldav' ? true : false
      }, importOptions || {})
    };

    if (this.typeCombo.getValue() == 'remote_caldav') {
      params.importOptions = Ext.apply({
        password: this.remotePassword.getValue(),
        username: this.remoteUsername.getValue()
      }, params.importOptions);
    }

    if (type == 'upload') {
      params = Ext.apply(params, {
        clientRecordData: clientRecordData,
        method: this.appName + '.import' + this.recordClass.getMeta('modelName') + 's',
        tempFileId: this.uploadButton.getTempFileId(),
        definitionId: this.definitionCombo.getValue()
      });
    } else {
      params = Ext.apply(params, {
        method: this.appName + '.importRemote' + this.recordClass.getMeta('modelName') + 's',
        remoteUrl: this.remoteLocation.getValue(),
        interval: this.ttlCombo.getValue()
      });
    }

    Ext.Ajax.request({
      scope: this,
      timeout: 1800000,
      // 30 minutes
      callback: this.onImportResponse.createDelegate(this, [callback], true),
      params: params
    });
  },

  /**
   * called when import request sends response
   * 
   * @param {Object}   request
   * @param {Boolean}  success
   * @param {Object}   response
   * @param {Function} callback
   */
  onImportResponse: function onImportResponse(request, success, response, callback) {
    var decoded = Ext.util.JSON.decode(response.responseText);
    Tine.log.debug('Tine.widgets.dialog.SimpleImportDialog::onImportResponse server response');
    Tine.log.debug(decoded);
    this.lastImportResponse = decoded;
    var that = this;

    if (success) {
      Ext.MessageBox.show({
        buttons: Ext.Msg.OK,
        icon: Ext.MessageBox.INFO,
        fn: callback,
        scope: that,
        title: that.app.i18n._('Import Definition Success!'),
        msg: that.app.i18n._('The Ical Import definition has been created successfully! Please wait some minutes to get the events synced by the cronjob.')
      });
      var wp = this.app.mainScreen.getWestPanel(),
          tp = wp.getContainerTreePanel(),
          state = wp.getState();
      tp.getLoader().load(tp.getRootNode());
      wp.applyState(state);
    } else {
      Tine.Tinebase.ExceptionHandler.handleRequestException(response, callback, that);
    }
  },

  /**
   * Returns a panel with a upload field and descriptions
   * 
   * @returns {Object}
   */
  getUploadPanel: function getUploadPanel() {
    return {
      xtype: 'panel',
      baseCls: 'ux-subformpanel',
      id: 'uploadPanel',
      hidden: true,
      title: i18n._('Choose Import File'),
      height: 100,
      items: [{
        xtype: 'label',
        html: '<p>' + i18n._('Please choose the file that contains the records you want to add to Tine 2.0') + '</p><br />'
      }, {
        xtype: 'tw.uploadbutton',
        ref: '../../uploadButton',
        text: String.format(i18n._('Select file containing your {0}'), this.recordClass.getRecordsName()),
        handler: this.onFileReady,
        allowedTypes: this.allowedFileExtensions,
        scope: this
      }]
    };
  },

  /**
   * Returns a panel with a text field for a remote location and a description
   * 
   * @returns {Object}
   */
  getRemotePanel: function getRemotePanel() {
    var ttl = [['once', this.app.i18n._('once')], ['hourly', this.app.i18n._('hourly')], ['daily', this.app.i18n._('daily')], ['weekly', this.app.i18n._('weekly')]];
    var ttlStore = new Ext.data.ArrayStore({
      fields: ['ttl_id', 'ttl'],
      data: ttl
    });
    return {
      xtype: 'form',
      labelAlign: 'top',
      baseCls: 'ux-subformpanel',
      id: 'remotePanel',
      hidden: false,
      title: this.app.i18n._('Choose Remote Location'),
      //height: 230,
      items: [{
        xtype: 'label',
        html: '<p>' + this.app.i18n._('Please choose a remote location you want to add to Tine 2.0') + '</p><br />'
      }, {
        ref: '../../remoteLocation',
        xtype: 'textfield',
        scope: this,
        enableKeyEvents: true,
        width: 400,
        listeners: {
          scope: this,
          keyup: function keyup() {
            this.manageButtons();
          }
        }
      }, {
        xtype: 'label',
        ref: '../../remoteUsernameLabel',
        html: '<p><br />' + this.app.i18n._('Username') + '</p><br />'
      }, {
        ref: '../../remoteUsername',
        xtype: 'textfield',
        scope: this,
        disabled: true,
        enableKeyEvents: true,
        width: 400,
        listeners: {
          scope: this,
          keyup: function keyup() {
            this.manageButtons();
          }
        }
      }, {
        xtype: 'label',
        ref: '../../remotePasswordLabel',
        html: '<p><br />' + this.app.i18n._('Password') + '</p><br />'
      }, {
        ref: '../../remotePassword',
        xtype: 'tw-passwordTriggerField',
        clipboard: false,
        scope: this,
        disabled: true,
        enableKeyEvents: true,
        width: 400,
        listeners: {
          scope: this,
          keyup: function keyup() {
            this.manageButtons();
          }
        }
      }, {
        xtype: 'label',
        html: '<p><br />' + this.app.i18n._('Refresh time') + '</p><br />'
      }, {
        xtype: 'combo',
        mode: 'local',
        ref: '../../ttlCombo',
        value: 'once',
        scope: this,
        width: 400,
        listeners: {
          scope: this,
          'select': function select() {
            this.manageButtons();
          }
        },
        editable: false,
        allowblank: false,
        valueField: 'ttl_id',
        displayField: 'ttl',
        store: ttlStore
      }]
    };
  },
  getImportOptionsPanel: function getImportOptionsPanel() {
    if (this.importOptionsPanel) {
      return this.importOptionsPanel;
    }

    return {
      xtype: 'panel',
      ref: '../../importOptionsPanel',
      baseCls: 'ux-subformpanel',
      title: this.app.i18n._('General Settings'),
      height: 100,
      width: 400,
      items: [{
        xtype: 'label',
        html: '<p>' + this.app.i18n._('Calendar name (you need permissions to add events)') + '<br /><br /></p>'
      }, {
        xtype: 'panel',
        heigth: 150,
        layout: 'hbox',
        items: [{
          xtype: 'panel',
          flex: 1,
          height: 20,
          items: [new Tine.widgets.container.SelectionComboBox({
            id: this.app.appName + 'EditDialogContainerSelector',
            ref: '../../../../containerCombo',
            stateful: false,
            containerName: this.recordClass.getContainerName(),
            containersName: this.recordClass.getContainersName(),
            appName: this.appName,
            value: this.defaultImportContainer,
            requiredGrant: false,
            recordClass: this.recordClass,
            width: 400
          })]
        }]
      }]
    };
  },
  getDefinitionPanel: function getDefinitionPanel() {
    if (this.definitionPanel) {
      return this.definitionPanel;
    }

    var def = this.selectedDefinition,
        description = def ? def.get('description') : '',
        options = def ? def.get('plugin_options_json') : null,
        example = options && options.example ? options.example : '';
    return {
      xtype: 'panel',
      ref: '../../definitionPanel',
      id: 'definitionPanel',
      hidden: true,
      baseCls: 'ux-subformpanel',
      title: this.app.i18n._('What should the file you upload look like?'),
      flex: 1,
      items: [{
        xtype: 'label',
        html: '<p>' + this.app.i18n._('Tine 2.0 does not understand all kind of files you might want to upload. You will have to manually adjust your file so Tine 2.0 can handle it.') + '</p><br />'
      }, {
        //                xtype: 'label',
        //                html: '<p>' + this.app.i18n._('Following you find a list of all supported import formats and a sample file, how Tine 2.0 expects your file to look like.') + '</p><br />'
        //            }, {
        xtype: 'label',
        html: '<p>' + this.app.i18n._('Please select the import format of the file you want to upload') + '<br /><br /></p>'
      }, {
        xtype: 'combo',
        ref: '../../definitionCombo',
        store: this.definitionsStore,
        displayField: 'label',
        valueField: 'id',
        mode: 'local',
        triggerAction: 'all',
        editable: false,
        allowBlank: false,
        forceSelection: true,
        width: 400,
        value: this.selectedDefinition ? this.selectedDefinition.id : null,
        listeners: {
          scope: this,
          'select': this.onDefinitionSelect
        }
      }, {
        xtype: 'label',
        ref: '../../exampleLink',
        html: example ? '<p><a href="' + example + '">' + this.app.i18n._('Download example file') + '</a></p>' : '<p>&nbsp;</p>'
      }, {
        xtype: 'displayfield',
        ref: '../../definitionDescription',
        height: 70,
        value: description,
        cls: 'x-ux-display-background-border',
        style: 'padding-left: 5px;'
      }]
    };
  },

  /**
   * returns the file panel of this wizard (step 1)
   */
  getPanel: function getPanel() {
    var def = this.selectedDefinition,
        description = def ? def.get('description') : '',
        options = def ? def.get('plugin_options_json') : null,
        example = options && options.example ? options.example : '';
    var types = [['remote_ics', this.app.i18n._('Remote / ICS')], ['remote_caldav', i18n._('Remote / CalDAV (BETA)')], ['upload', this.app.i18n._('Upload')]];
    var typeStore = new Ext.data.ArrayStore({
      fields: ['type_id', 'type_value'],
      data: types,
      disabled: false
    });
    return {
      title: this.app.i18n._('Choose File and Format'),
      layout: 'vbox',
      border: false,
      xtype: 'ux.displaypanel',
      frame: true,
      ref: '../filePanel',
      items: [{
        xtype: 'panel',
        baseCls: 'ux-subformpanel',
        title: this.app.i18n._('Select type of source'),
        height: 100,
        items: [{
          xtype: 'label',
          html: '<p>' + this.app.i18n._('Please select the type of source you want to add to Tine 2.0') + '</p><br />'
        }, {
          xtype: 'combo',
          mode: 'local',
          ref: '../../typeCombo',
          width: 400,
          listeners: {
            scope: this,
            'select': function select(combo) {
              if (combo.getValue() == 'upload') {
                Ext.getCmp('uploadPanel').show();
                Ext.getCmp('definitionPanel').show();
                Ext.getCmp('remotePanel').hide();
              } else if (combo.getValue() == 'remote_ics' || combo.getValue() == 'remote_caldav') {
                Ext.getCmp('uploadPanel').hide();
                Ext.getCmp('definitionPanel').hide();
                Ext.getCmp('remotePanel').show();

                if (combo.getValue() == 'remote_caldav') {
                  this.remoteLocation.emptyText = 'http://example/calendars';
                  this.remoteUsername.enable();
                  this.remotePassword.enable();
                  this.remoteUsername.show();
                  this.remotePassword.show();
                  this.remoteUsernameLabel.show();
                  this.remotePasswordLabel.show();
                } else {
                  this.remoteLocation.emptyText = 'http://example.ics';
                  this.remoteUsername.disable();
                  this.remotePassword.disable();
                  this.remoteUsername.hide();
                  this.remotePassword.hide();
                  this.remoteUsernameLabel.hide();
                  this.remotePasswordLabel.hide();
                }

                this.remoteLocation.applyEmptyText();
                this.remoteLocation.reset();
              }

              this.doLayout();
              this.manageButtons();
            },
            'render': function render(combo) {
              combo.setValue('upload');
              Ext.getCmp('uploadPanel').show();
              Ext.getCmp('definitionPanel').show();
              Ext.getCmp('remotePanel').hide();
            }
          },
          scope: this,
          valueField: 'type_id',
          displayField: 'type_value',
          store: typeStore
        }]
      }, this.getUploadPanel(), this.getRemotePanel(), this.getImportOptionsPanel(), this.getDefinitionPanel()],

      /**
      * finish button handler for this panel
      */
      onFinishButton: function () {
        if (!this.importMask) {
          this.importMask = new Ext.LoadMask(this.getEl(), {
            msg: String.format(i18n._('Importing {0}'), this.recordClass.getRecordsName())
          });
        }

        this.importMask.show(); // collect client data

        var clientRecordData = [];
        var importOptions = {};
        this.doImport(function (request, success, response) {
          this.importMask.hide();
          this.fireEvent('finish', this, this.layout.activeItem);

          if (Ext.isArray(response.exceptions) && response.exceptions.length > 0) {
            this.backButton.setDisabled(true);
            this.finishButton.setHandler(function () {
              this.window.close();
            }, this);
          } else {
            this.window.close();
          }
        }, importOptions, clientRecordData);
      }.createDelegate(this),
      finishIsAllowed: function () {
        var credentialsCheck = false;

        if (this.typeCombo.getValue() == 'remote_caldav') {
          if (this.remoteUsername.getValue() != '' && this.remotePassword.getValue() != '') {
            credentialsCheck = true;
          }
        } else if (this.typeCombo.getValue() == 'remote_ics') {
          credentialsCheck = true;
        }

        return this.typeCombo && (this.typeCombo.getValue() == 'remote_ics' || this.typeCombo.getValue() == 'remote_caldav') && this.remoteLocation && this.remoteLocation.getValue() && this.ttlCombo && (this.ttlCombo.getValue() || this.ttlCombo.getValue() === 0) && credentialsCheck || this.typeCombo && this.typeCombo.getValue() == 'upload' && this.definitionCombo && this.definitionCombo.getValue() && this.uploadButton && this.uploadButton.upload && this.containerCombo && this.containerCombo.getValue();
      }.createDelegate(this)
    };
  }
});
/**
 * Create new import window
 */

Tine.Calendar.ImportDialog.openWindow = function (config) {
  var window = Tine.WindowFactory.getWindow({
    width: 800,
    height: 600,
    name: Tine.Calendar.ImportDialog.windowNamePrefix + Ext.id(),
    contentPanelConstructor: 'Tine.Calendar.ImportDialog',
    contentPanelConstructorConfig: config
  });
  return window;
};

/***/ }),

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

Tine.Calendar.CalendarPanelSplitPlugin = function () {};
/**
 * @TODO ui for active view?
 * @TODO we could also create views beforeload for better performace
 * 
 */


Tine.Calendar.CalendarPanelSplitPlugin.prototype = {
  /**
   * @property app
   * @type Tine.Calendar.Application
   */
  app: null,

  /**
   * @property attendeeViews
   * @type Ext.util.MixedCollection
   */
  attendeeViews: null,

  /**
   * @property mainStore store of main view
   * @type Ext.Store
   */
  mainStore: null,
  init: function init(calPanel) {
    if (!Tine.Tinebase.appMgr.get('Calendar').featureEnabled('featureSplitView')) {
      return;
    }

    this.calPanel = calPanel;
    this.app = Tine.Tinebase.appMgr.get('Calendar');
    this.attendeeViews = new Ext.util.MixedCollection(); // NOTE: we can't use a normal hbox layout as it can't deal with minWidth and overflow.
    //       As ext has no suiteable layout for this, we do a little hack

    this.calPanel.layout = new Ext.layout.HBoxLayout({
      align: 'stretch',
      pack: 'start'
    });
    this.calPanel.layout.onLayout = this.calPanel.layout.onLayout.createInterceptor(function () {
      var viewCount = this.attendeeViews.getCount(),
          availableWidth = this.calPanel.getWidth(),
          minViewWidth = this.calPanel.view.boxMinWidth;
      var width = availableWidth / viewCount < minViewWidth ? minViewWidth * viewCount : availableWidth;
      this.calPanel.body.setWidth(width);
      this.calPanel.body.setStyle('overflow-x', width > availableWidth ? 'scroll' : 'hidden');
    }, this);
    this.calPanel.on('afterlayout', function () {
      this.calPanel.body.setWidth(this.calPanel.getWidth());
    }, this);
    this.mainStore = this.calPanel.view.store;
    this.mainStore.on('load', this.onMainStoreLoad, this);
    this.mainStore.on('beforeload', this.onMainStoreBeforeLoad, this); // NOTE: we remove from items to avoid autoDestroy

    this.calPanel.items.remove(this.calPanel.view);
    this.calPanel.getView = this.getActiveView.createDelegate(this);
    this.calPanel.on('show', this.onCalPanelShow, this);
    this.calPanel.on('hide', this.onCalPanelHide, this);
    this.calPanel.on('afterrender', function () {
      this.attendeeFilterGrid = this.app.getMainScreen().getWestPanel().getAttendeeFilter();
      this.attendeeFilterGrid.on('sortchange', this.onAttendeeFilterSortChange, this);
    }, this); // hook into getDefaultData 

    this.originalGetDefaultData = Tine.Calendar.Model.Event.getDefaultData;
    Tine.Calendar.Model.Event.getDefaultData = this.getDefaultData.createDelegate(this);
  },
  getDefaultData: function getDefaultData() {
    var defaultData = this.originalGetDefaultData(),
        useSplit = Tine.Calendar.CalendarPanelSplitPlugin.splitBtn && Tine.Calendar.CalendarPanelSplitPlugin.splitBtn.pressed,
        centerPanel = this.app.getMainScreen().getCenterPanel(),
        activeCalPanel = centerPanel.getCalendarPanel(centerPanel.activeView),
        activeView = this.getActiveView(),
        attendee = activeView && activeView.ownerCt ? activeView.ownerCt.attendee : null;

    if (useSplit && attendee && this.calPanel == activeCalPanel) {
      Ext.apply(attendee.data, {
        status: 'ACCEPTED'
      });
      defaultData.attendee = [attendee.data];
    }

    return defaultData;
  },
  onCalPanelShow: function onCalPanelShow() {
    if (Tine.Calendar.CalendarPanelSplitPlugin.splitBtn) {
      Tine.Calendar.CalendarPanelSplitPlugin.splitBtn.enable();
    } else {
      Tine.Calendar.CalendarPanelSplitPlugin.SplitBtn.prototype.disabled = false;
    }
  },
  onCalPanelHide: function onCalPanelHide() {
    if (Tine.Calendar.CalendarPanelSplitPlugin.splitBtn) {
      Tine.Calendar.CalendarPanelSplitPlugin.splitBtn.disable();
    }
  },
  onMainStoreBeforeLoad: function onMainStoreBeforeLoad(store, options) {
    var ret = true;
    this.attendeeViews.each(function (attendeeView) {
      ret = ret && attendeeView.store.fireEvent('beforeload', store, options);
    }, this);
    return ret;
  },
  onMainStoreLoad: function onMainStoreLoad(store, options) {
    var cp = this.app.getMainScreen().getCenterPanel();

    if (store !== cp.getCalendarPanel(cp.activeView).getStore()) {
      Tine.log.debug('Tine.Calendar.CalendarPanelSplitPlugin::onMainStoreLoad try again with active subview');
      cp.onStoreLoad(this.getActiveView().store, options);
    }

    if (!this.attendeeFilterGrid) {
      return;
    } // create view for each attendee


    var filteredAttendee = this.attendeeFilterGrid.getValue(),
        attendeeStore = Tine.Calendar.Model.Attender.getAttendeeStore(filteredAttendee),
        useSplit = Tine.Calendar.CalendarPanelSplitPlugin.splitBtn && Tine.Calendar.CalendarPanelSplitPlugin.splitBtn.pressed; // remove views not longer in filter

    this.calPanel.items.each(function (view) {
      if (view.attendee && (!useSplit || !Tine.Calendar.Model.Attender.getAttendeeStore.getAttenderRecord(attendeeStore, view.attendee))) {
        this.removeAttendeeView(view.attendee);
      }
    }, this);
    this.manageSplitViews(filteredAttendee); // manage main (main is shown if no split criteria is present)

    if (!filteredAttendee.length || !useSplit) {
      if (!this.attendeeViews.get('main')) {
        var view = this.createView({
          store: this.cloneStore(false)
        });
        this.attendeeViews.add('main', view);
        this.calPanel.add({
          layout: 'fit',
          border: false,
          flex: 1,
          height: this.calPanel.getHeight(),
          // <- initialHeight
          items: view
        });
      } else {
        this.attendeeViews.get('main').initData(this.cloneStore(false));
        this.attendeeViews.get('main').onLoad();
      }
    } else {
      var main = this.attendeeViews.get('main');

      if (main && main.ownerCt) {
        this.calPanel.remove(main.ownerCt);
      }

      this.attendeeViews.removeKey('main');
    }

    this.calPanel.doLayout();
  },
  addAttendeeView: function addAttendeeView(attendee, pos) {
    var attendeeName = Tine.Calendar.AttendeeGridPanel.prototype.renderAttenderName.call(Tine.Calendar.AttendeeGridPanel.prototype, attendee.get('user_id'), false, attendee),
        attendeeViewId = this.getAttendeeViewId(attendee);

    var filter = function filter(r) {
      var attendeeStore = Tine.Calendar.Model.Attender.getAttendeeStore(r.get('attendee'));
      return Tine.Calendar.Model.Attender.getAttendeeStore.getAttenderRecord(attendeeStore, attendee);
    };

    var store = this.cloneStore(filter);
    var view = this.createView({
      title: attendeeName,
      store: store,
      print: this.onPrint.createDelegate(this)
    }); // manage active views

    view.on('render', function (v) {
      v.mon(v.getEl(), 'mousedown', this.setActiveAttendeeView.createDelegate(this, [attendeeViewId]), this);
    }, this);
    this.attendeeViews.add(attendeeViewId, view);
    this.calPanel.insert(pos, {
      xtype: 'tabpanel',
      style: 'padding: 5px;',
      id: attendeeViewId,
      attendee: attendee,
      plain: true,
      flex: 1,
      height: this.calPanel.getHeight(),
      // <- initialHeight
      activeItem: 0,
      items: view
    });
  },
  onAttendeeFilterSortChange: function onAttendeeFilterSortChange() {
    var filteredAttendee = this.attendeeFilterGrid.getValue();
    this.manageSplitViews(filteredAttendee);
    this.calPanel.doLayout();
  },
  manageSplitViews: function manageSplitViews(filteredAttendee) {
    // create view for each attendee
    var useSplit = Tine.Calendar.CalendarPanelSplitPlugin.splitBtn && Tine.Calendar.CalendarPanelSplitPlugin.splitBtn.pressed;

    if (useSplit) {
      // add subviews new to filter
      // NOTE: we don't iterate the attendeeStore as we would loose attendee order than
      Ext.each(filteredAttendee, function (attendeeData, idx) {
        var attendee = new Tine.Calendar.Model.Attender(attendeeData, attendeeData.id);
        var attendeeView = this.attendeeViews.get(this.getAttendeeViewId(attendee));

        if (!attendeeView) {
          this.addAttendeeView(attendee, idx);
        } else {
          //assert position
          this.calPanel.items.remove(attendeeView.ownerCt);
          this.calPanel.items.insert(idx, attendeeView.ownerCt);
          var filterFn = attendeeView.store.filterFn;
          attendeeView.initData(this.cloneStore(filterFn));
          attendeeView.onLoad();
        }
      }, this);
    }
  },
  getAttendeeViewId: function getAttendeeViewId(attendee) {
    return this.calPanel.id + '-' + attendee.get('user_type') + '-' + attendee.getUserId();
  },
  removeAttendeeView: function removeAttendeeView(attendee) {
    var attendeeViewId = this.getAttendeeViewId(attendee); //@TODO remove relayed events?

    this.attendeeViews.removeKey(attendeeViewId);
    this.calPanel.remove(attendeeViewId);
  },
  createView: function createView(config) {
    var view = Ext.create(Ext.apply({
      xtype: this.calPanel.view.getXType(),
      startDate: this.calPanel.getTopToolbar().periodPicker.getPeriod().from,
      numOfDays: this.calPanel.view.numOfDays,
      period: this.calPanel.getTopToolbar().periodPicker.getPeriod(),
      updatePeriod: this.updatePeriod.createDelegate(this)
    }, config)); // NOTE: this is already done by the view itself - don't have dublicate events in mainscreen!
    // this.calPanel.relayEvents(view, ['changeView', 'changePeriod', 'addEvent', 'updateEvent', 'click', 'dblclick', 'contextmenu', 'keydown']);

    this.calPanel.view.relayEvents(view, ['changeView', 'changePeriod', 'addEvent', 'updateEvent', 'click', 'dblclick', 'contextmenu', 'keydown']);
    this.calPanel.view.getSelectionModel().relayEvents(view.getSelectionModel(), 'selectionchange');
    view.getSelectionModel().on('selectionchange', this.onSelectionChange.createDelegate(this, [view]));

    if (view.onBeforeScroll) {
      view.onBeforeScroll = view.onBeforeScroll.createSequence(this.onScroll.createDelegate(this, [view], 0));
    }

    view.on('onBeforeAllDayScrollerResize', this.onAllDayAreaResize, this);
    return view;
  },

  /**
   * is called on scroll of a grid, scrolls the other grids
   * 
   * @param {Object} activeView
   * @param {Object} e Event
   */
  onScroll: function onScroll(activeView, e) {
    if (!(activeView && activeView.scroller && activeView.scroller.dom && activeView.getHeight() > 100)) {
      return;
    }

    var scrollTop = activeView.scroller.dom.scrollTop;
    this.attendeeViews.each(function (view) {
      if (activeView.id != view.id && view.scroller) {
        view.scroller.dom.scrollTop = scrollTop;
      }
    }, this);
  },
  getActiveView: function getActiveView() {
    if (!this.attendeeViews.getCount()) {
      return this.calPanel.view;
    }

    if (!this.activeAttendeeView || this.attendeeViews.indexOf(this.activeAttendeeView) < 0) {
      this.activeAttendeeView = this.attendeeViews.itemAt(0);
    }

    return this.activeAttendeeView;
  },
  onPrint: function onPrint(printMode) {
    var renderer = new Tine.Calendar.Printer.SplitViewRenderer({
      printMode: printMode
    });
    renderer.print(this);
  },
  onSelectionChange: function onSelectionChange(view) {
    view = Ext.isString(view) ? this.attendeeViews.get(view) : view;
    this.setActiveAttendeeView(view);
    this.attendeeViews.each(function (v) {
      if (v !== view) {
        v.getSelectionModel().clearSelections(true);
      }
    }, this);

    if (this.calPanel.mainScreen) {
      this.calPanel.mainScreen.updateEventActions.call(this.calPanel.mainScreen);
    }
  },
  setActiveAttendeeView: function setActiveAttendeeView(view) {
    view = Ext.isString(view) ? this.attendeeViews.get(view) : view;

    if (view != this.activeAttendeeView && this.activeAttendeeView.endEditSummary && this.activeAttendeeView.editing) {
      this.activeAttendeeView.endEditSummary();
    }

    this.activeAttendeeView = view;
  },
  updatePeriod: function updatePeriod() {
    var origArgs = arguments;
    this.attendeeViews.each(function (view) {
      view.constructor.prototype.updatePeriod.apply(view, origArgs);
    }, this);
  },
  onAllDayAreaResize: function onAllDayAreaResize(originView, rzEvent) {
    if (this.attendeeViews.items.length > 1) {
      var maxWholeDayAreaSize = 10;
      this.attendeeViews.each(function (view) {
        if (view.wholeDayArea) {
          var allDayAreaHeight = view.computeAllDayAreaHeight();

          if (allDayAreaHeight > maxWholeDayAreaSize) {
            maxWholeDayAreaSize = allDayAreaHeight;
          }
        }
      }, this);
      rzEvent.wholeDayScrollerHeight = Math.min(maxWholeDayAreaSize, rzEvent.maxAllowedHeight);
      this.attendeeViews.each(function (view) {
        if (view.wholeDayArea) {
          var allDayAreaEl = Ext.get(view.wholeDayArea),
              allDayAreaHeight = allDayAreaEl.getHeight();
          view.wholeDayScroller.setHeight(rzEvent.wholeDayScrollerHeight);
          allDayAreaEl.setHeight(Math.max(allDayAreaHeight, maxWholeDayAreaSize));
        }
      }, this);
    }
  },
  cloneStore: function cloneStore(filterFn) {
    var clone = new Ext.data.Store({
      fields: Tine.Calendar.Model.Event,
      load: this.mainStore.load.createDelegate(this.mainStore),
      proxy: this.mainStore.proxy,
      filterFn: filterFn,
      replaceRecord: function replaceRecord(o, n) {
        var idx = this.indexOf(o);
        this.remove(o);
        this.insert(idx, n);
      }
    });
    var rs = [];
    this.mainStore.each(function (r) {
      if (!filterFn || filterFn(r)) {
        rs.push(r.copy());
      }
    }, this);
    clone.add(rs);
    clone.on('add', this.onCloneStoreAdd, this);
    clone.on('update', this.onCloneStoreUpdate, this);
    clone.on('remove', this.onCloneStoreRemove, this);
    return clone;
  },
  onCloneStoreAdd: function onCloneStoreAdd(store, rs) {
    Ext.each(rs, function (r) {
      this.attendeeViews.each(function (view) {
        if (view.store != store) {
          if (!view.store.filterFn || view.store.filterFn(r)) {
            view.store.un('add', this.onCloneStoreAdd, this);
            view.store.add([r.copy()]);
            view.store.on('add', this.onCloneStoreAdd, this);
          }
        }
      }, this); // check if events fits into view @see Tine.Calendar.MainScreenCenterPanel::congruenceFilterCheck

      if (store.filterFn && !store.filterFn(r)) {
        (function () {
          if (this.ui && this.ui.rendered) {
            this.ui.markOutOfFilter();
          }
        }).defer(25, r);
      }
    }, this);
  },
  onCloneStoreUpdate: function onCloneStoreUpdate(store, r) {
    this.attendeeViews.each(function (view) {
      if (view.store != store) {
        view.store.un('add', this.onCloneStoreAdd, this);
        view.store.un('remove', this.onCloneStoreRemove, this);
        var cr = view.store.getById(r.id);

        if (cr) {
          view.store.remove(cr);
          view.store.add([r.copy()]);
        }

        view.store.on('add', this.onCloneStoreAdd, this);
        view.store.on('remove', this.onCloneStoreRemove, this);
      }
    }, this);
  },
  onCloneStoreRemove: function onCloneStoreRemove(store, r) {
    this.attendeeViews.each(function (view) {
      if (view.store != store) {
        view.store.un('remove', this.onCloneStoreRemove, this);
        view.store.remove(view.store.getById(r.id));
        view.store.on('remove', this.onCloneStoreRemove, this);
      }
    }, this);
  }
};
Ext.preg('Calendar.CalendarPanelSplitPlugin', Tine.Calendar.CalendarPanelSplitPlugin);
Tine.Calendar.CalendarPanelSplitPlugin.SplitBtn = Ext.extend(Ext.Button, {
  enableToggle: true,
  pressed: false,
  disabled: true,
  scale: 'medium',
  rowspan: 2,
  iconCls: 'cal-split-view',
  iconAlign: 'top',
  text: 'Split',
  stateful: true,
  stateId: 'cal-calpanel-split-btn',
  stateEvents: ['toggle'],
  initComponent: function initComponent() {
    if (!Tine.Tinebase.appMgr.get('Calendar').featureEnabled('featureSplitView')) {
      // hide button and make sure it isn't pressed
      Tine.log.info('Split view feature is deactivated');
      this.hidden = true;
      this.pressed = false;
    }

    Tine.Calendar.CalendarPanelSplitPlugin.SplitBtn.superclass.initComponent.apply(this, arguments);
    Tine.Calendar.CalendarPanelSplitPlugin.splitBtn = this;
  },
  handler: function handler() {
    Tine.Tinebase.appMgr.get('Calendar').getMainScreen().getCenterPanel().refresh();
  },
  getState: function getState() {
    return {
      pressed: this.pressed
    };
  }
});
Tine.Calendar.Printer.SplitViewRenderer = Ext.extend(Tine.Calendar.Printer.BaseRenderer, {
  getAdditionalHeaders: Tine.Calendar.Printer.DaysViewRenderer.prototype.getAdditionalHeaders,
  generateBody: function generateBody(splitView) {
    var viewRenderer = splitView.calPanel.view.printRenderer,
        htmlArray = [],
        me = this,
        _ = window.lodash;
    me.rendererArray = [];
    me.viewArray = [];
    me.paperHeight = viewRenderer.paperHeight;
    me.useHtml2Canvas = me.printMode == 'sheet' && splitView.calPanel.view.cls != "cal-monthview";
    return _.reduce(splitView.attendeeViews.items, function (promise, view, i) {
      return promise.then(function () {
        var renderer = new view.printRenderer({
          printMode: me.printMode
        });
        me.rendererArray.push(renderer);
        me.viewArray.push(view);
        renderer.extraTitle = view.title + ' // ';
        renderer.titleStyle = i > 0 ? 'page-break-before:always' : '';
        return renderer.generateBody(view);
      }).then(function (html) {
        htmlArray.push('<div class="page">' + html + '</div>');
      });
    }, Promise.resolve('')).then(function () {
      return htmlArray.join('');
    });
  },
  onBeforePrint: function onBeforePrint(doc, view) {
    Ext.each(this.rendererArray, function (renderer, i) {
      renderer.onBeforePrint(doc, this.viewArray[i]);
    }, this);
  }
}); // self register

Tine.Calendar.CalendarPanel.prototype.plugins = '[{"ptype": "Calendar.CalendarPanelSplitPlugin"}]';
Ext.ux.ItemRegistry.registerItem('Calendar-MainScreenPanel-ViewBtnGrp', Tine.Calendar.CalendarPanelSplitPlugin.SplitBtn, -10);

/***/ }),

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

/*
 * Tine 2.0
 * 
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Michael Spahn <m.spahn@metaways.de>
 * @copyright   Copyright (c) 2017 Metaways Infosystems GmbH (http://www.metaways.de)
 */
Ext.ns('Tine.Calendar');
/**
 * @namespace   Tine.Calendar
 * @class       Tine.Calendar.RruleFilter
 * @extends     Tine.widgets.grid.FilterModel
 *
 * @author      Michael Spahn <m.spahn@metaways.de>
 */

Tine.Calendar.RruleFilter = Ext.extend(Tine.widgets.grid.FilterModel, {
  app: null,
  field: 'rrule',
  defaultOperator: 'in',
  operators: ['in', 'notin'],
  initComponent: function initComponent() {
    Tine.Calendar.AttendeeFilterModel.superclass.initComponent.call(this);
    this.app = this.app || Tine.Tinebase.appMgr.get('Calendar');
    this.label = this.app.i18n._('Rrule');
    this.defaultValue = [{
      'daily': true,
      'weekly': true,
      'monthly': true,
      'yearly': true
    }];
  },
  valueRenderer: function valueRenderer(filter, el) {
    var value = new Tine.Calendar.RruleFilterValueField({
      app: this.app,
      filter: filter,
      value: filter.data.value ? filter.data.value : this.defaultValue,
      renderTo: el
    });
    value.on('select', this.onFiltertrigger, this);
    value.onCheckboxSelect(null, null);
    return value;
  }
});
Tine.widgets.grid.FilterToolbar.FILTERS['calendar.rrule'] = Tine.Calendar.RruleFilter;
/**
 * @namespace   Tine.Calendar
 * @class       Tine.Calendar.RruleFilterValueField
 * @extends     Ext.ux.form.LayerCombo
 *
 * @author      Michael Spahn <m.spahn@metaways.de>
 */

Tine.Calendar.RruleFilterValueField = Ext.extend(Ext.ux.form.LayerCombo, {
  hideButtons: false,
  lazyInit: false,
  formConfig: {
    labelAlign: 'left',
    labelWidth: 30
  },
  dailyCheckbox: null,
  weeklyCheckbox: null,
  monthlyCheckbox: null,
  yearlyCheckbox: null,
  initComponent: function initComponent() {
    this.supr().initComponent.apply(this, arguments);
  },
  getFormValue: function getFormValue() {
    return [{
      'daily': this.dailyCheckbox.getValue(),
      'weekly': this.weeklyCheckbox.getValue(),
      'monthly': this.monthlyCheckbox.getValue(),
      'yearly': this.yearlyCheckbox.getValue()
    }];
  },
  getItems: function getItems() {
    this.dailyCheckbox = new Ext.form.Checkbox({
      boxLabel: this.app.i18n._('Daily'),
      name: 'daily',
      columnWidth: 1,
      readOnly: false,
      disabled: false,
      checked: true,
      listeners: {
        scope: this,
        check: this.onCheckboxSelect
      }
    });
    this.weeklyCheckbox = new Ext.form.Checkbox({
      xtype: 'checkbox',
      boxLabel: this.app.i18n._('Weekly'),
      name: 'weekly',
      columnWidth: 1,
      readOnly: false,
      disabled: false,
      checked: true,
      listeners: {
        scope: this,
        check: this.onCheckboxSelect
      }
    });
    this.monthlyCheckbox = new Ext.form.Checkbox({
      boxLabel: this.app.i18n._('Monthly'),
      name: 'monthly',
      columnWidth: 1,
      readOnly: false,
      disabled: false,
      checked: true,
      listeners: {
        scope: this,
        check: this.onCheckboxSelect
      }
    });
    this.yearlyCheckbox = new Ext.form.Checkbox({
      boxLabel: this.app.i18n._('Yearly'),
      name: 'yearly',
      columnWidth: 1,
      readOnly: false,
      disabled: false,
      checked: true,
      listeners: {
        scope: this,
        check: this.onCheckboxSelect
      }
    });
    return [this.dailyCheckbox, this.weeklyCheckbox, this.monthlyCheckbox, this.yearlyCheckbox];
  },
  onCheckboxSelect: function onCheckboxSelect(cb, checked) {
    var selection = [];

    if (this.dailyCheckbox.getValue()) {
      selection.push(this.dailyCheckbox.boxLabel);
    }

    if (this.weeklyCheckbox.getValue()) {
      selection.push(this.weeklyCheckbox.boxLabel);
    }

    if (this.monthlyCheckbox.getValue()) {
      selection.push(this.monthlyCheckbox.boxLabel);
    }

    if (this.yearlyCheckbox.getValue()) {
      selection.push(this.yearlyCheckbox.boxLabel);
    }

    this.setRawValue(selection.join(', '));
    this.setValue(this.getFormValue());
  },
  setValue: function setValue(value) {
    value = Ext.isArray(value) ? value : [value];
    this.setFormValue(value);
    return this.supr().setValue.apply(this, [value]);
  },
  setFormValue: function setFormValue(value) {
    this.dailyCheckbox.setValue(value[0].daily || false);
    this.weeklyCheckbox.setValue(value[0].weekly || false);
    this.monthlyCheckbox.setValue(value[0].monthly || false);
    this.yearlyCheckbox.setValue(value[0].yearly || false);
  }
});

/***/ }),

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

/*
 * Tine 2.0
 *
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Michael Spahn <m.spahn@metaways.de>
 * @copyright   Copyright (c) 2017 Metaways Infosystems GmbH (http://www.metaways.de)
 */
Ext.ns('Tine.Calendar');
/**
 * File picker dialog
 *
 * @namespace   Tine.Calendar
 * @class       Tine.Calendar.EventFinderOptionsDialog
 * @extends     Ext.FormPanel
 * @constructor
 * @param       {Object} config The configuration options.
 */

Tine.Calendar.EventFinderOptionsDialog = Ext.extend(Ext.Panel, {
  defaultOptions: [{
    id: 'MO',
    active: true,
    config: [8, 18.00],
    period: {
      from: '08:00:00',
      until: '18:00:00'
    }
  }, {
    id: 'TU',
    active: true,
    config: [8, 18.00],
    period: {
      from: '08:00:00',
      until: '18:00:00'
    }
  }, {
    id: 'WE',
    active: true,
    config: [8, 18.00],
    period: {
      from: '08:00:00',
      until: '18:00:00'
    }
  }, {
    id: 'TH',
    active: true,
    config: [8, 18.00],
    period: {
      from: '08:00:00',
      until: '18:00:00'
    }
  }, {
    id: 'FR',
    active: true,
    config: [8, 18.00],
    period: {
      from: '08:00:00',
      until: '18:00:00'
    }
  }, {
    id: 'SA',
    active: false,
    config: [8, 18.00],
    period: {
      from: '08:00:00',
      until: '18:00:00'
    }
  }, {
    id: 'SU',
    active: false,
    config: [8, 18.00],
    period: {
      from: '08:00:00',
      until: '18:00:00'
    }
  }],
  windowNamePrefix: 'eventfinderoptionsdialog_',
  app: null,
  cls: 'tw-editdialog',
  header: false,
  border: false,
  layout: 'fit',
  wkdays: ['SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA'],
  MOSlider: null,
  TUSlider: null,
  WESlider: null,
  THSlider: null,
  FRSlider: null,
  SASlider: null,
  SUSlider: null,
  MOCheckbox: null,
  TUCheckbox: null,
  WECheckbox: null,
  THCheckbox: null,
  FRCheckbox: null,
  SACheckbox: null,
  SUCheckbox: null,
  stateId: 'eventFinderOptions',
  stateConfig: [],
  initComponent: function initComponent() {
    if (null === this.app) {
      this.app = Tine.Tinebase.appMgr.get('Calendar');
    }

    this.title = this.titleText ? this.titleText : this.app.i18n._('Event finder options');
    this.window.setTitle(this.title);
    this.initActions();
    this.initButtons();
    this.stateConfig = Ext.state.Manager.get(this.stateId, this.defaultOptions);
    this.items = this.getFormItems();
    this.supr().initComponent.apply(this, arguments);
  },
  initButtons: function initButtons() {
    this.fbar = ['->'];
    this.fbar.push(this.action_cancel, this.action_saveAndClose);
  },
  initActions: function initActions() {
    this.action_saveAndClose = new Ext.Action({
      text: this.app.i18n._('Ok'),
      minWidth: 70,
      ref: '../btnSaveAndClose',
      scope: this,
      handler: function handler() {
        this.onSaveAndClose();
      },
      iconCls: 'action_saveAndClose'
    });
    this.action_cancel = new Ext.Action({
      text: this.app.i18n._('Cancel'),
      minWidth: 70,
      scope: this,
      handler: this.onCancel,
      iconCls: 'action_cancel'
    });
    this.actionUpdater = new Tine.widgets.ActionUpdater({
      evalGrants: false
    });
    this.actionUpdater.addActions([this.action_saveAndClose, this.action_cancel]);
  },
  onCancel: function onCancel() {
    this.window.close();
  },

  /**
   * Get a time period of a given slider range
   *
   *    0:0:0 - 23:59:59
   *
   * @param range
   * @return {{from: *, until: *}}
   */
  getPeriodFromSliderRange: function getPeriodFromSliderRange(range) {
    var hoursStart = Tine.Tinebase.common.trunc(range[0]);
    var minStart = Tine.Tinebase.common.trunc(Math.round(range[0] % 1 * 100) * 0.60);
    var hoursEnd = Tine.Tinebase.common.trunc(range[1]);
    var minEnd = Tine.Tinebase.common.trunc(range[1] % 1 * 100 * 0.60);
    var startDate = new Date();
    startDate.setHours(hoursStart);
    startDate.setMinutes(minStart);
    startDate.setSeconds(0);
    var endDate = new Date();
    endDate.setHours(hoursEnd);
    endDate.setMinutes(minEnd);
    endDate.setSeconds(hoursEnd === 23 && minEnd === 59 ? 59 : 0);
    var pattern = 'H:i:s';
    return {
      from: startDate.format(pattern),
      until: endDate.format(pattern)
    };
  },
  onSaveAndClose: function onSaveAndClose() {
    var data = [{
      id: 'MO',
      active: this.MOCheckbox.getValue(),
      config: this.MOSlider.getRange(),
      period: this.getPeriodFromSliderRange(this.MOSlider.getRange())
    }, {
      id: 'TU',
      active: this.TUCheckbox.getValue(),
      config: this.TUSlider.getRange(),
      period: this.getPeriodFromSliderRange(this.TUSlider.getRange())
    }, {
      id: 'WE',
      active: this.WECheckbox.getValue(),
      config: this.WESlider.getRange(),
      period: this.getPeriodFromSliderRange(this.WESlider.getRange())
    }, {
      id: 'TH',
      active: this.THCheckbox.getValue(),
      config: this.THSlider.getRange(),
      period: this.getPeriodFromSliderRange(this.THSlider.getRange())
    }, {
      id: 'FR',
      active: this.FRCheckbox.getValue(),
      config: this.FRSlider.getRange(),
      period: this.getPeriodFromSliderRange(this.FRSlider.getRange())
    }, {
      id: 'SA',
      active: this.SACheckbox.getValue(),
      config: this.SASlider.getRange(),
      period: this.getPeriodFromSliderRange(this.SASlider.getRange())
    }, {
      id: 'SU',
      active: this.SUCheckbox.getValue(),
      config: this.SUSlider.getRange(),
      period: this.getPeriodFromSliderRange(this.SUSlider.getRange())
    }];
    Ext.state.Manager.set(this.stateId, data);
    this.fireEvent('apply', this, Ext.encode(data));
    this.window.close();
  },
  onCheckSlider: function onCheckSlider(cb, checked) {
    this[cb.name + 'Slider'].setDisabled(!checked);
  },
  getCheckboxSliderRowFor: function getCheckboxSliderRowFor(id) {
    var _ = window.lodash;

    var config = _.find(this.stateConfig, function (o) {
      return o.id === id;
    });

    return {
      layout: 'hbox',
      layoutConfig: {
        align: 'stretch',
        pack: 'start'
      },
      height: 30,
      items: [{
        xtype: 'checkbox',
        checked: !!config && config.active,
        boxLabel: Date.dayNames[this.wkdays.indexOf(id)],
        name: id,
        anchor: '95%',
        flex: 1,
        ref: '../../../../../' + id + 'Checkbox',
        listeners: {
          scope: this,
          check: this.onCheckSlider
        }
      }, this.getSliderFor(id, config)]
    };
  },
  getSliderFor: function getSliderFor(id, config) {
    var _ = window.lodash;
    var sliderId = id + 'Slider';
    var sliderStart = 0;
    var sliderEnd = 23.9999;

    if (config) {
      sliderStart = config.config[0];
      sliderEnd = config.config[1];
    }

    return new Tine.Tinebase.RangeSliderComponent({
      width: 500,
      ref: '../../../../../' + sliderId,
      currentStart: sliderStart,
      currentEnd: sliderEnd,
      disabled: !config || !config.active
    });
  },

  /**
   * @todo: improve layout, rangeslidercomponent can't deal with resizing! Techically it can but it's extremely slow atm!
   */
  getFormItems: function getFormItems() {
    var wkdayItems = [];

    for (var i = 0, d; i < 7; i++) {
      d = (i + Ext.DatePicker.prototype.startDay) % 7;
      wkdayItems.push(this.getCheckboxSliderRowFor(this.wkdays[d]));
    }

    var sliderElements = [{
      layout: 'vbox',
      border: false,
      layoutConfig: {
        align: 'stretch',
        pack: 'start'
      },
      items: wkdayItems
    }];
    return {
      xtype: 'tabpanel',
      border: false,
      plain: true,
      defaults: {
        hideMode: 'offsets'
      },
      plugins: [{
        ptype: 'ux.tabpanelkeyplugin'
      }],
      activeTab: 0,
      items: [{
        title: this.title,
        autoScroll: true,
        border: false,
        frame: true,
        layout: 'border',
        items: [{
          region: 'center',
          layout: 'fit',
          border: false,
          items: sliderElements
        }]
      }]
    };
  }
});
/**
 * Create new EventFinderOptionsDialog window
 */

Tine.Calendar.EventFinderOptionsDialog.openWindow = function (config) {
  var window = Tine.WindowFactory.getWindow({
    width: 800,
    height: 300,
    name: Tine.Calendar.EventFinderOptionsDialog.prototype.windowNamePrefix + config.recordId,
    contentPanelConstructor: 'Tine.Calendar.EventFinderOptionsDialog',
    contentPanelConstructorConfig: config
  });
  return window;
};

/***/ }),

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

module.exports = "data:image/gif;base64,R0lGODlhAgA4AIcAAMnZ7cra7cra7svb7szb7s3c7s3c787d7s7d787e7s7e78/e78/f8NDe8NDf8NHf8NDg8NDh8NHh8NLg8NLg8dLh8NPh8dTh8tXi8tbj8tbj89fk89jk89nl89nl9Nrm9PD1+gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAAAAP8ALAAAAAACADgAAAhlAEGA+EDwgwcPHTpw4LCh4QYNGjJIzIChIoYLFyxotEChI4UJEx6IfNCgZIMFCxCoRGCgpYECBQjIJDBggAABAQIA2AkAps8CBw4kGJpAgQKUDJIycOAAAoQIUCNIkFChqtWrAQEAOw=="

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cpath d='M19.9,28.4L7.5,16C7.2,15.7,7,15.3,7,14.8c0-0.5,0.2-0.9,0.5-1.2C7.9,13.2,8.3,13,8.8,13h24.8c0.5,0,0.9,0.2,1.2,0.5 c0.4,0.4,0.5,0.8,0.5,1.2c0,0.5-0.2,0.9-0.5,1.2L22.4,28.4c-0.4,0.4-0.8,0.5-1.2,0.5C20.7,28.9,20.3,28.8,19.9,28.4z'/%3E %3C/svg%3E\""

/***/ }),

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

module.exports = "data:image/gif;base64,R0lGODlhAgAYAIcAANDQ0Ovs7uzt7+3u8O7v8e/w8vDx8/Hy9Pn5+QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAAAAP8ALAAAAAACABgAAAghABEIHEiwYMEDCA8YWMiwgMMCBAgMmDhAgIAAGAMAABAQADs="

/***/ }),

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

module.exports = "data:image/gif;base64,R0lGODlhAgAWAIcAAKrM9tno++vz/QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAAAAP8ALAAAAAACABYAAAgUAAUIHEiwoIAACBMqXMhwIQAAAQEAOw=="

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cstyle type='text/css'%3E .st0%7Bfill:%23FFFFFF;%7D .st1%7Bfill:%2304BAEE;%7D %3C/style%3E %3Cpath class='st0' d='M34.2,14.5h-27v21.3h27V14.5z'/%3E %3Cpath class='st1' d='M27.5,22.8h-6.1v6.1h6.1V22.8z'/%3E %3Cpath d='M7.4,35.6h5.5v-5.5H7.4V35.6z M14.1,35.6h6.1v-5.5h-6.1V35.6z M7.4,28.9h5.5v-6.1H7.4V28.9z M14.1,28.9h6.1v-6.1h-6.1V28.9z M7.4,21.6h5.5v-5.5H7.4V21.6z M21.4,35.6h6.1v-5.5h-6.1V35.6z M14.1,21.6h6.1v-5.5h-6.1V21.6z M28.7,35.6h5.5v-5.5h-5.5V35.6z M21.4,28.9h6.1v-6.1h-6.1V28.9z M14.7,12.5V7c0-0.2-0.1-0.3-0.2-0.4s-0.3-0.2-0.4-0.2h-1.2c-0.2,0-0.3,0.1-0.4,0.2 c-0.1,0.1-0.2,0.3-0.2,0.4v5.5c0,0.2,0.1,0.3,0.2,0.4c0.1,0.1,0.3,0.2,0.4,0.2h1.2c0.2,0,0.3-0.1,0.4-0.2 C14.7,12.8,14.7,12.7,14.7,12.5z M28.7,28.9h5.5v-6.1h-5.5V28.9z M21.4,21.6h6.1v-5.5h-6.1V21.6z M28.7,21.6h5.5v-5.5h-5.5V21.6z M29.3,12.5V7c0-0.2-0.1-0.3-0.2-0.4s-0.3-0.2-0.4-0.2h-1.2c-0.2,0-0.3,0.1-0.4,0.2S26.9,6.9,26.9,7v5.5c0,0.2,0.1,0.3,0.2,0.4 c0.1,0.1,0.3,0.2,0.4,0.2h1.2c0.2,0,0.3-0.1,0.4-0.2C29.2,12.8,29.3,12.7,29.3,12.5z M36.6,11.3v24.3c0,0.7-0.2,1.2-0.7,1.7 c-0.5,0.5-1.1,0.7-1.7,0.7H7.4c-0.7,0-1.2-0.2-1.7-0.7C5.2,36.8,5,36.2,5,35.6V11.3c0-0.7,0.2-1.2,0.7-1.7c0.5-0.5,1.1-0.7,1.7-0.7 h2.4V7c0-0.8,0.3-1.6,0.9-2.1S12.1,4,12.9,4h1.2c0.8,0,1.6,0.3,2.1,0.9c0.6,0.6,0.9,1.3,0.9,2.1v1.8h7.3V7c0-0.8,0.3-1.6,0.9-2.1 C25.9,4.3,26.6,4,27.5,4h1.2c0.8,0,1.6,0.3,2.1,0.9s0.9,1.3,0.9,2.1v1.8h2.4c0.7,0,1.2,0.2,1.7,0.7C36.3,10.1,36.6,10.6,36.6,11.3z'/%3E %3C/svg%3E\""

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cpath d='M28.3,9.8C27.8,6.5,24.7,4,21,4c-4.1,0-7.4,3-7.4,6.8c0,1,0.9,1.9,2,1.9c1.1,0,2-0.8,2-1.9c0-1.7,1.5-3.1,3.4-3.1 c1.9,0,3.4,1.4,3.4,3.1c0,2.6-7,3.6-7,3.6l0,0c-2,0.3-3.5,2-3.5,3.9V34c0,2.2,1.9,4,4.3,4h6c2.2,0,4-1.6,4.2-3.5l0,0v-0.1 c0-0.1,0-0.2,0-0.4V18.3c0-0.1,0-0.2,0-0.4v-6.8c0-0.1,0-0.2,0-0.4c0-0.2,0-0.5,0-0.7L28.3,9.8C28.4,9.8,28.4,9.8,28.3,9.8L28.3,9.8 z M27.7,27.5'/%3E %3C/svg%3E\""

/***/ }),

/***/ 40:
/***/ (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;
};


/***/ }),

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

/*
 * Tine 2.0
 *
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiß <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2009-2017 Metaways Infosystems GmbH (http://www.metaways.de)
 */
__webpack_require__(1728);

__webpack_require__(1760);

__webpack_require__(1761);

__webpack_require__(1762);

__webpack_require__(1763);

__webpack_require__(1764);

__webpack_require__(1765);

__webpack_require__(1766);

__webpack_require__(1767);

__webpack_require__(1768);

__webpack_require__(1769);

__webpack_require__(1770);

__webpack_require__(1771);

__webpack_require__(1772);

__webpack_require__(1773);

__webpack_require__(1774);

__webpack_require__(1775);

__webpack_require__(1782);

__webpack_require__(1786);

__webpack_require__(1790);

__webpack_require__(1791);

__webpack_require__(1792);

__webpack_require__(1793);

__webpack_require__(1796);

__webpack_require__(1797);

__webpack_require__(1798);

__webpack_require__(1799);

__webpack_require__(1800);

__webpack_require__(1801);

__webpack_require__(1802);

__webpack_require__(1803);

__webpack_require__(43);

__webpack_require__(1804);

__webpack_require__(1810);

__webpack_require__(1813);

__webpack_require__(1814);

__webpack_require__(1815);

__webpack_require__(1816);

__webpack_require__(1817);

__webpack_require__(1818);

__webpack_require__(1819);

__webpack_require__(1820);

__webpack_require__(1821);

__webpack_require__(1822);

__webpack_require__(1823);

__webpack_require__(1824);

__webpack_require__(1825);

__webpack_require__(1826);

__webpack_require__(1827);

__webpack_require__(1828);

__webpack_require__(1829);

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cg%3E %3Cg%3E %3Cpath d='M34,13.4c-0.2-1.7-1-3.3-2.4-4.4l-0.8-0.6C29.7,7.5,28.3,7,26.8,7c-2,0-3.8,0.9-5,2.4L9.9,24.1c-1.1,1.3-1.6,3-1.4,4.8 c0.2,1.7,1,3.3,2.4,4.4l0.8,0.6c1.1,0.9,2.6,1.4,4.1,1.4c0.2,0,0.5,0,0.7,0c1.7-0.2,3.3-1,4.3-2.3c0,0,0,0,8-9.9 c1.4-1.8,1.2-4.4-0.6-5.8l-0.4-0.3C27,16.3,26.1,16,25.1,16c-1.3,0-2.4,0.6-3.2,1.5l-8,9.9c-0.5,0.6-0.4,1.6,0.2,2.1 c0.3,0.2,0.6,0.3,0.9,0.3c0.5,0,0.9-0.2,1.2-0.6l8-9.9c0.2-0.3,0.5-0.4,0.9-0.4c0.3,0,0.5,0.1,0.7,0.2l0.4,0.3 c0.2,0.2,0.4,0.4,0.4,0.7c0,0.3-0.1,0.6-0.2,0.8l-8,9.9c-0.7,0.8-1.6,1.3-2.7,1.3c-0.8,0-1.6-0.3-2.2-0.8l-0.8-0.6 c-0.7-0.6-1.2-1.4-1.3-2.3c-0.1-0.9,0.2-1.8,0.8-2.5l11.9-14.7c0.7-0.8,1.6-1.3,2.7-1.3c0.8,0,1.6,0.3,2.2,0.8l0.8,0.6 c1.5,1.2,1.7,3.4,0.5,4.9C30,16.6,29.9,17,30,17.4c0,0.4,0.2,0.8,0.6,1c0.3,0.2,0.6,0.3,0.9,0.3c0.5,0,0.9-0.2,1.2-0.6 C33.7,16.8,34.2,15.1,34,13.4L34,13.4z M34,13.4'/%3E %3C/g%3E %3C/g%3E %3C/svg%3E\""

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cpath d='M32.8,21.3c0-2.1-0.5-4-1.6-5.8c-1-1.8-2.4-3.2-4.2-4.2c-1.8-1-3.7-1.6-5.8-1.6s-4,0.5-5.8,1.6s-3.2,2.4-4.2,4.2 s-1.6,3.7-1.6,5.8s0.5,4,1.6,5.8c1,1.8,2.4,3.2,4.2,4.2c1.8,1,3.7,1.6,5.8,1.6s4-0.5,5.8-1.6c1.8-1,3.2-2.4,4.2-4.2 C32.3,25.3,32.8,23.4,32.8,21.3z M35.4,21.3c0,2.6-0.6,4.9-1.9,7.1c-1.3,2.2-3,3.9-5.2,5.2c-2.2,1.3-4.5,1.9-7.1,1.9 s-4.9-0.6-7.1-1.9c-2.2-1.3-3.9-3-5.2-5.2s-1.9-4.5-1.9-7.1s0.6-4.9,1.9-7.1s3-3.9,5.2-5.2s4.5-1.9,7.1-1.9s4.9,0.6,7.1,1.9 s3.9,3,5.2,5.2C34.8,16.3,35.4,18.7,35.4,21.3z M30.4,29.1l-1.2,1.2c-0.2,0.2-0.4,0.2-0.6,0.2c-0.2,0-0.4-0.1-0.6-0.2l-6.7-6.7l-7,7 c-0.2,0.2-0.4,0.2-0.6,0.2c-0.2,0-0.4-0.1-0.6-0.2l-1.2-1.2c-0.2-0.2-0.2-0.4-0.2-0.6c0-0.2,0.1-0.4,0.2-0.6l7-7l-7.1-7 c-0.2-0.2-0.2-0.4-0.2-0.6s0.1-0.4,0.2-0.6l1.2-1.2c0.2-0.2,0.4-0.2,0.6-0.2s0.4,0.1,0.6,0.2l7,7l8.2-8.2c0.2-0.2,0.4-0.2,0.6-0.2 s0.4,0.1,0.6,0.2l1.2,1.2c0.2,0.2,0.2,0.4,0.2,0.6s-0.1,0.4-0.2,0.6l-8.2,8.2l6.7,6.7c0.2,0.2,0.2,0.4,0.2,0.6 C30.6,28.8,30.5,29,30.4,29.1z'/%3E %3C/svg%3E\""

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cpath d='M29.5,13.6c1.3,0,2.5-0.5,3.4-1.4s1.4-2.1,1.4-3.4c0-1.3-0.5-2.4-1.4-3.4c-1-0.9-2.1-1.4-3.4-1.4c-1.4,0-2.5,0.5-3.4,1.4 s-1.4,2.1-1.4,3.4c0,1.3,0.5,2.5,1.4,3.4S28.2,13.6,29.5,13.6z M27.3,6.6c0.6-0.6,1.3-0.9,2.2-0.9c0.9,0,1.6,0.3,2.2,0.9 c0.6,0.7,0.9,1.4,0.9,2.2c0,0.9-0.3,1.6-0.9,2.2c-0.6,0.6-1.4,0.9-2.2,0.9c-0.9,0-1.6-0.3-2.2-0.9c-0.6-0.6-0.9-1.4-0.9-2.2 C26.4,8,26.7,7.2,27.3,6.6z M31.5,31.1c0.1,0.7,0.1,1.4,0.1,2c0,1.5-0.5,2.7-1.4,3.6S28.1,38,26.5,38H10.1c-1.5,0-2.7-0.4-3.7-1.3 C5.5,35.8,5,34.6,5,33.1c0-0.7,0-1.3,0.1-2c0.1-0.7,0.1-1.3,0.3-2.1c0.1-0.7,0.3-1.4,0.5-2s0.5-1.2,0.8-1.8s0.7-1.1,1.2-1.5 c0.4-0.4,1-0.8,1.6-1c0.6-0.2,1.3-0.4,2.1-0.4c0.1,0,0.4,0.1,0.8,0.4s0.9,0.6,1.4,0.9c0.5,0.3,1.2,0.6,2,0.9 c0.8,0.3,1.7,0.4,2.5,0.4s1.7-0.1,2.5-0.4c0.8-0.3,1.5-0.6,2-0.9s1-0.6,1.4-0.9c0.4-0.3,0.7-0.4,0.8-0.4c0.8,0,1.5,0.1,2.1,0.4 s1.2,0.6,1.6,1c0.4,0.4,0.8,0.9,1.2,1.5c0.3,0.6,0.6,1.2,0.8,1.8c0.2,0.6,0.4,1.3,0.5,2C31.3,29.7,31.4,30.4,31.5,31.1z M13.8,20.6 c-1.3-1.3-1.9-2.8-1.9-4.5s0.6-3.3,1.9-4.5c1.3-1.2,2.8-1.9,4.5-1.9c1.8,0,3.3,0.6,4.5,1.9c1.3,1.2,1.9,2.7,1.9,4.5 s-0.6,3.3-1.9,4.5c-1.3,1.3-2.8,1.9-4.5,1.9C16.5,22.5,15,21.9,13.8,20.6z M34.2,13.7c-0.1,0-0.3,0.1-0.8,0.4 c-0.4,0.3-1,0.5-1.8,0.8c-0.7,0.3-1.5,0.4-2.2,0.4c-0.8,0-1.7-0.1-2.5-0.4c0.1,0.4,0.1,0.8,0.1,1.2c0,1.7-0.5,3.3-1.5,4.8 c2,0,3.7,0.9,5,2.4H33c1,0,1.9-0.3,2.6-0.8c0.7-0.5,1.1-1.2,1.1-2.2C36.7,15.9,35.9,13.7,34.2,13.7z M34.4,21.3 c-0.5,0.3-1.1,0.5-1.7,0.5H31c-0.9-1-2-1.6-3.3-1.6c0.7-1,1-2,1-3.2c0-0.3,0-0.5-0.1-0.8c0.5,0.2,1.1,0.3,1.6,0.3 c0.5,0,1-0.1,1.5-0.3c0.5-0.2,0.9-0.3,1.2-0.5c0.3-0.2,0.5-0.3,0.5-0.3c1.1,0,1.6,1.5,1.6,4.4C35.1,20.5,34.9,21,34.4,21.3z'/%3E %3C/svg%3E\""

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cg%3E %3Cpath d='M35.8,7.9C35.2,7.3,34.5,7,33.7,7H9C8.1,7,7.4,7.3,6.9,7.9C6.3,8.4,6,9.1,6,10v22.4c0,0.8,0.3,1.5,0.9,2.1 C7.4,35,8.1,35.3,9,35.3h24.8c0.8,0,1.5-0.3,2.1-0.9c0.6-0.6,0.9-1.3,0.9-2.1V10C36.7,9.1,36.4,8.4,35.8,7.9L35.8,7.9z M20.2,33H9 c-0.2,0-0.3-0.1-0.4-0.2c-0.1-0.1-0.2-0.3-0.2-0.4V11.7h11.8V33z M34.3,32.4c0,0.2-0.1,0.3-0.2,0.4C34,32.9,33.9,33,33.7,33H22.5 V11.7h11.8V32.4z M34.3,32.4'/%3E %3C/g%3E %3C/svg%3E\""

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cstyle type='text/css'%3E .st0%7Bfill:%2304BAEE;%7D %3C/style%3E %3Cpath class='st0' d='M34.2,35.7H7.4V16.1h26.7V35.7z'/%3E %3Cpath d='M7.4,35.6h5.5v-5.5H7.4V35.6z M14.1,35.6h6.1v-5.5h-6.1V35.6z M7.4,28.9h5.5v-6.1H7.4V28.9z M14.1,28.9h6.1v-6.1h-6.1V28.9z M7.4,21.6h5.5v-5.5H7.4V21.6z M21.4,35.6h6.1v-5.5h-6.1V35.6z M14.1,21.6h6.1v-5.5h-6.1V21.6z M28.7,35.6h5.5v-5.5h-5.5V35.6z M21.4,28.9h6.1v-6.1h-6.1V28.9z M14.7,12.5V7c0-0.2-0.1-0.3-0.2-0.4s-0.3-0.2-0.4-0.2h-1.2c-0.2,0-0.3,0.1-0.4,0.2 c-0.1,0.1-0.2,0.3-0.2,0.4v5.5c0,0.2,0.1,0.3,0.2,0.4c0.1,0.1,0.3,0.2,0.4,0.2h1.2c0.2,0,0.3-0.1,0.4-0.2 C14.7,12.8,14.7,12.7,14.7,12.5z M28.7,28.9h5.5v-6.1h-5.5V28.9z M21.4,21.6h6.1v-5.5h-6.1V21.6z M28.7,21.6h5.5v-5.5h-5.5V21.6z M29.3,12.5V7c0-0.2-0.1-0.3-0.2-0.4s-0.3-0.2-0.4-0.2h-1.2c-0.2,0-0.3,0.1-0.4,0.2S26.9,6.9,26.9,7v5.5c0,0.2,0.1,0.3,0.2,0.4 c0.1,0.1,0.3,0.2,0.4,0.2h1.2c0.2,0,0.3-0.1,0.4-0.2C29.2,12.8,29.3,12.7,29.3,12.5z M36.6,11.3v24.3c0,0.7-0.2,1.2-0.7,1.7 c-0.5,0.5-1.1,0.7-1.7,0.7H7.4c-0.7,0-1.2-0.2-1.7-0.7C5.2,36.8,5,36.2,5,35.6V11.3c0-0.7,0.2-1.2,0.7-1.7c0.5-0.5,1.1-0.7,1.7-0.7 h2.4V7c0-0.8,0.3-1.6,0.9-2.1S12.1,4,12.9,4h1.2c0.8,0,1.6,0.3,2.1,0.9c0.6,0.6,0.9,1.3,0.9,2.1v1.8h7.3V7c0-0.8,0.3-1.6,0.9-2.1 C25.9,4.3,26.6,4,27.5,4h1.2c0.8,0,1.6,0.3,2.1,0.9s0.9,1.3,0.9,2.1v1.8h2.4c0.7,0,1.2,0.2,1.7,0.7C36.3,10.1,36.6,10.6,36.6,11.3z'/%3E %3C/svg%3E\""

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cpath d='M36.6,30.7c0,0.7-0.2,1.2-0.7,1.7c-0.5,0.5-1,0.7-1.7,0.7h-8.5c0,1.3-0.5,2.5-1.4,3.4c-0.9,0.9-2.1,1.4-3.4,1.4 c-1.3,0-2.5-0.5-3.4-1.4c-0.9-0.9-1.4-2.1-1.4-3.4H7.4c-0.7,0-1.2-0.2-1.7-0.7c-0.5-0.5-0.7-1-0.7-1.7c0.6-0.5,1.2-1.1,1.7-1.7 c0.5-0.6,1.1-1.3,1.6-2.3c0.6-0.9,1-1.9,1.4-3s0.7-2.4,0.9-3.9c0.2-1.5,0.4-3.2,0.4-4.9c0-1.9,0.7-3.7,2.2-5.4s3.4-2.7,5.8-3 C19,6.3,19,6.1,19,5.8c0-0.5,0.2-0.9,0.5-1.3C19.8,4.2,20.3,4,20.8,4s0.9,0.2,1.3,0.5s0.5,0.8,0.5,1.3c0,0.3-0.1,0.5-0.2,0.7 c2.4,0.4,4.3,1.4,5.8,3s2.2,3.4,2.2,5.4c0,1.8,0.1,3.4,0.4,4.9c0.2,1.5,0.6,2.8,0.9,3.9c0.4,1.1,0.9,2.1,1.4,3 c0.6,0.9,1.1,1.7,1.6,2.3C35.4,29.6,35.9,30.2,36.6,30.7z'/%3E %3C/svg%3E\""

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cpath d='M32.1,7H10.2C8.5,7,7,8.5,7,10.2v21.9c0,1.8,1.5,3.2,3.2,3.2h21.9c1.8,0,3.2-1.5,3.2-3.2V10.2C35.4,8.5,33.9,7,32.1,7z M32.5,31.1c0,0.8-0.6,1.4-1.4,1.4H11.3c-0.8,0-1.4-0.6-1.4-1.4V11.3c0-0.8,0.6-1.4,1.4-1.4h19.8c0.8,0,1.4,0.6,1.4,1.4V31.1z M30.3,15.3c0.2,0.2,0.4,0.5,0.4,0.9s-0.1,0.6-0.4,0.9L19.2,28.2c-0.2,0.2-0.5,0.4-0.9,0.4s-0.6-0.1-0.9-0.4l-5.3-5.3 c-0.2-0.2-0.4-0.5-0.4-0.9c0-0.3,0.1-0.6,0.4-0.9l0.3-0.3c0.2-0.2,0.5-0.4,0.9-0.4c0.3,0,0.6,0.1,0.9,0.4l4,4l9.9-9.9 c0.2-0.2,0.5-0.4,0.9-0.4c0.3,0,0.6,0.1,0.9,0.4L30.3,15.3z'/%3E %3C/svg%3E\""

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cpath d='M21.2,13c0.5,0,0.9,0.2,1.2,0.5l12.4,12.4c0.4,0.4,0.5,0.8,0.5,1.2c0,0.5-0.2,0.9-0.5,1.2c-0.4,0.4-0.8,0.5-1.2,0.5H8.8 c-0.5,0-0.9-0.2-1.2-0.5C7.2,28.1,7,27.7,7,27.2c0-0.5,0.2-0.9,0.5-1.2l12.4-12.4C20.3,13.2,20.7,13,21.2,13z'/%3E %3C/svg%3E\""

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cpath d='M7.4,35.6h5.5v-5.5H7.4V35.6z M14.1,35.6h6.1v-5.5h-6.1V35.6z M7.4,28.9h5.5v-6.1H7.4V28.9z M14.1,28.9h6.1v-6.1h-6.1V28.9z M7.4,21.6h5.5v-5.5H7.4V21.6z M21.4,35.6h6.1v-5.5h-6.1V35.6z M14.1,21.6h6.1v-5.5h-6.1V21.6z M28.7,35.6h5.5v-5.5h-5.5V35.6z M21.4,28.9h6.1v-6.1h-6.1V28.9z M14.7,12.5V7c0-0.2-0.1-0.3-0.2-0.4s-0.3-0.2-0.4-0.2h-1.2c-0.2,0-0.3,0.1-0.4,0.2 c-0.1,0.1-0.2,0.3-0.2,0.4v5.5c0,0.2,0.1,0.3,0.2,0.4c0.1,0.1,0.3,0.2,0.4,0.2h1.2c0.2,0,0.3-0.1,0.4-0.2 C14.7,12.8,14.7,12.7,14.7,12.5z M28.7,28.9h5.5v-6.1h-5.5V28.9z M21.4,21.6h6.1v-5.5h-6.1V21.6z M28.7,21.6h5.5v-5.5h-5.5V21.6z M29.3,12.5V7c0-0.2-0.1-0.3-0.2-0.4s-0.3-0.2-0.4-0.2h-1.2c-0.2,0-0.3,0.1-0.4,0.2S26.9,6.9,26.9,7v5.5c0,0.2,0.1,0.3,0.2,0.4 c0.1,0.1,0.3,0.2,0.4,0.2h1.2c0.2,0,0.3-0.1,0.4-0.2C29.2,12.8,29.3,12.7,29.3,12.5z M36.6,11.3v24.3c0,0.7-0.2,1.2-0.7,1.7 c-0.5,0.5-1.1,0.7-1.7,0.7H7.4c-0.7,0-1.2-0.2-1.7-0.7C5.2,36.8,5,36.2,5,35.6V11.3c0-0.7,0.2-1.2,0.7-1.7c0.5-0.5,1.1-0.7,1.7-0.7 h2.4V7c0-0.8,0.3-1.6,0.9-2.1S12.1,4,12.9,4h1.2c0.8,0,1.6,0.3,2.1,0.9c0.6,0.6,0.9,1.3,0.9,2.1v1.8h7.3V7c0-0.8,0.3-1.6,0.9-2.1 C25.9,4.3,26.6,4,27.5,4h1.2c0.8,0,1.6,0.3,2.1,0.9s0.9,1.3,0.9,2.1v1.8h2.4c0.7,0,1.2,0.2,1.7,0.7C36.3,10.1,36.6,10.6,36.6,11.3z'/%3E %3C/svg%3E\""

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cstyle type='text/css'%3E .st0%7Bfill:%23FFFFFF;%7D .st1%7Bfill:%2304BAEE;%7D %3C/style%3E %3Cpath class='st0' d='M34.2,14.5h-27v21.3h27V14.5z'/%3E %3Cpath class='st1' d='M27.5,22.8h-6.1v6.1h6.1V22.8z'/%3E %3Cpath d='M7.4,35.6h5.5v-5.5H7.4V35.6z M14.1,35.6h6.1v-5.5h-6.1V35.6z M7.4,28.9h5.5v-6.1H7.4V28.9z M14.1,28.9h6.1v-6.1h-6.1V28.9z M7.4,21.6h5.5v-5.5H7.4V21.6z M21.4,35.6h6.1v-5.5h-6.1V35.6z M14.1,21.6h6.1v-5.5h-6.1V21.6z M28.7,35.6h5.5v-5.5h-5.5V35.6z M21.4,28.9h6.1v-6.1h-6.1V28.9z M14.7,12.5V7c0-0.2-0.1-0.3-0.2-0.4s-0.3-0.2-0.4-0.2h-1.2c-0.2,0-0.3,0.1-0.4,0.2 c-0.1,0.1-0.2,0.3-0.2,0.4v5.5c0,0.2,0.1,0.3,0.2,0.4c0.1,0.1,0.3,0.2,0.4,0.2h1.2c0.2,0,0.3-0.1,0.4-0.2 C14.7,12.8,14.7,12.7,14.7,12.5z M28.7,28.9h5.5v-6.1h-5.5V28.9z M21.4,21.6h6.1v-5.5h-6.1V21.6z M28.7,21.6h5.5v-5.5h-5.5V21.6z M29.3,12.5V7c0-0.2-0.1-0.3-0.2-0.4s-0.3-0.2-0.4-0.2h-1.2c-0.2,0-0.3,0.1-0.4,0.2S26.9,6.9,26.9,7v5.5c0,0.2,0.1,0.3,0.2,0.4 c0.1,0.1,0.3,0.2,0.4,0.2h1.2c0.2,0,0.3-0.1,0.4-0.2C29.2,12.8,29.3,12.7,29.3,12.5z M36.6,11.3v24.3c0,0.7-0.2,1.2-0.7,1.7 c-0.5,0.5-1.1,0.7-1.7,0.7H7.4c-0.7,0-1.2-0.2-1.7-0.7C5.2,36.8,5,36.2,5,35.6V11.3c0-0.7,0.2-1.2,0.7-1.7c0.5-0.5,1.1-0.7,1.7-0.7 h2.4V7c0-0.8,0.3-1.6,0.9-2.1S12.1,4,12.9,4h1.2c0.8,0,1.6,0.3,2.1,0.9c0.6,0.6,0.9,1.3,0.9,2.1v1.8h7.3V7c0-0.8,0.3-1.6,0.9-2.1 C25.9,4.3,26.6,4,27.5,4h1.2c0.8,0,1.6,0.3,2.1,0.9s0.9,1.3,0.9,2.1v1.8h2.4c0.7,0,1.2,0.2,1.7,0.7C36.3,10.1,36.6,10.6,36.6,11.3z'/%3E %3Crect x='7.4' y='16.1' class='st0' width='12.8' height='19.4'/%3E %3Cpath d='M18.9,25.2c0.2,0.2,0.3,0.4,0.3,0.7c0,0.3-0.1,0.5-0.3,0.7l-5.2,5.2c-0.2,0.2-0.4,0.3-0.7,0.3c-0.3,0-0.5-0.1-0.7-0.3 l-0.6-0.6c-0.2-0.2-0.3-0.4-0.3-0.7c0-0.3,0.1-0.5,0.3-0.7l2.3-2.3H9.9c-0.3,0-0.5-0.1-0.7-0.3C9.1,26.9,9,26.7,9,26.4v-1 c0-0.3,0.1-0.5,0.3-0.7c0.2-0.2,0.4-0.3,0.7-0.3H14L11.7,22c-0.2-0.2-0.3-0.4-0.3-0.7c0-0.3,0.1-0.5,0.3-0.7l0.6-0.6 c0.2-0.2,0.4-0.3,0.7-0.3c0.3,0,0.5,0.1,0.7,0.3L18.9,25.2z'/%3E %3C/svg%3E\""

/***/ }),

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

module.exports = "data:image/gif;base64,R0lGODlhAQCQAKUvAH6t2bW4yLTJ4rbL5K7Q46/Q5LnN5rDQ5LHQ5K7R47vQ6dHR0dLS0tPT09TU1NbW1tfX18rb5tnZ2cXd+dra2snd9sve9cff+83f9N3d3c/g9Mvh/dHh89Pi8tXj8c3k/+zs7O3t7e7u7u/v793z//Dw8N/0//Hx8eH1/+P2/+b3/+j5/+r6//v8/vz9/v///////////////////////////////////////////////////////////////////yH+EUNyZWF0ZWQgd2l0aCBHSU1QACwAAAAAAQCQAAAGUsCA63QqjUSiEChDkUAejgZjQa0CWh5Ph6PBWCqCgUFBLpsVgIh6vU4Q3u/CAUGvX7Pb7jc8Pp+vLCwrKikoJiQTFxsfjI2OH2lsbG5wBHJ1dUEAOw=="

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cpath d='M36.5,21.4v8.2c0,0.2-0.1,0.3-0.2,0.5c-0.1,0.1-0.3,0.2-0.5,0.2H16.4v4.7c0,0.5-0.2,0.9-0.7,1.2c-0.5,0.2-1,0.2-1.4-0.2 l-7.7-6.4c-0.3-0.2-0.4-0.6-0.4-1c0-0.4,0.1-0.7,0.4-1l7.7-6.4c0.4-0.3,0.9-0.4,1.4-0.2c0.5,0.2,0.7,0.6,0.7,1.2v4.5h16v-2.9 c0-0.2,0.1-0.4,0.2-0.5l2.8-2.3c0.2-0.2,0.4-0.2,0.7-0.1C36.4,20.9,36.5,21.1,36.5,21.4z'/%3E %3Cpath d='M6.1,20.8v-8.2c0-0.2,0.1-0.3,0.2-0.5C6.5,12,6.6,12,6.8,12h19.4V7.3c0-0.5,0.2-0.9,0.7-1.2c0.5-0.2,1-0.2,1.4,0.2l7.7,6.4 c0.3,0.2,0.4,0.6,0.4,1c0,0.4-0.1,0.7-0.4,1l-7.7,6.4c-0.4,0.3-0.9,0.4-1.4,0.2c-0.5-0.2-0.7-0.6-0.7-1.2v-4.5h-16v2.9 c0,0.2-0.1,0.4-0.2,0.5l-2.8,2.3c-0.2,0.2-0.4,0.2-0.7,0.1C6.3,21.3,6.1,21.1,6.1,20.8z'/%3E %3C/svg%3E\""

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xml:space='preserve' width='42.5' height='42.5'%3E %3Cpath d='M30.4,8l-7.7,7.7H10.3v2.9c0,0.2-0.1,0.4-0.2,0.5l-2.8,2.3c-0.2,0.2-0.4,0.2-0.7,0.1c-0.3-0.1-0.4-0.3-0.4-0.6v-8.2 c0-0.2,0.1-0.3,0.2-0.5C6.5,12,6.6,12,6.8,12h19.4V7.3c0-0.5,0.2-0.9,0.7-1.2s1-0.2,1.4,0.2L30.4,8z M26.2,20.2 c0,0.5,0.2,0.9,0.7,1.2c0.5,0.2,1,0.2,1.4-0.2l7.7-6.4c0.3-0.2,0.4-0.6,0.4-1s-0.1-0.7-0.4-1l-1.5-1.2l-8.4,8.4V20.2z M36.2,20.8 c-0.3-0.1-0.5-0.1-0.7,0.1l-2.8,2.3c-0.1,0.1-0.2,0.3-0.2,0.5v2.9H19.6L12.1,34l2.2,1.8c0.4,0.4,0.9,0.4,1.4,0.2 c0.5-0.2,0.7-0.6,0.7-1.2v-4.7h19.4c0.2,0,0.3-0.1,0.5-0.2s0.2-0.3,0.2-0.5v-8.2C36.5,21.1,36.4,20.9,36.2,20.8z M15.7,20.8 c-0.5-0.2-1-0.2-1.4,0.2l-7.7,6.4c-0.3,0.2-0.4,0.6-0.4,1s0.1,0.7,0.4,1l1.3,1.1l8.6-8.6C16.4,21.4,16.2,21.1,15.7,20.8z M31.1,9.4 L9.4,31.1l1.8,1.8l21.7-21.7L31.1,9.4z'/%3E %3C/svg%3E\""

/***/ }),

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

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3Csvg version='1.1' id='Ebene_1' x='0px' y='0px' viewBox='0 0 42.5 42.5' style='enable-background:new 0 0 42.5 42.5;' xmlns='http://www.w3.org/2000/svg' width='42.5' height='42.5'%3E %3Cpath d='M 32.1 35.3 L 10.2 35.3 C 8.5 35.3 7 33.8 7 32.1 L 7 10.2 C 7 8.4 8.5 7 10.2 7 L 32.1 7 C 33.9 7 35.3 8.5 35.3 10.2 L 35.3 32.1 C 35.4 33.8 33.9 35.3 32.1 35.3 Z M 9.8 12 L 9.8 31.1 C 9.8 31.9 10.4 32.5 11.2 32.5 L 30.3 32.5 L 9.8 12 Z M 32.5 11.2 C 32.5 10.4 31.9 9.8 31.1 9.8 L 12.1 9.8 L 32.5 30.2 L 32.5 11.2 Z' transform='matrix(-1, 0, 0, -1, 42.304726, 42.299999)'/%3E %3C/svg%3E\""

/***/ }),

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

/*
 * Tine 2.0
 *
 * @package     Calendar
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2017 Metaways Infosystems GmbH (http://www.metaways.de)
 *
 */
Ext.ns('Tine.Calendar.eventActions');
/**
 * set current alternative as definite event
 */

Tine.Calendar.eventActions.setDefiniteEventAction = {
  app: 'Calendar',
  requiredGrant: 'editGrant',
  allowMultiple: false,
  text: 'Set as definite event',
  // _('Set as definite event')
  disabled: true,
  iconCls: 'cal-polls-set-definite-action',
  scope: this,
  confirm: function confirm() {
    return new Promise(function (fulfill, reject) {
      var app = Tine.Tinebase.appMgr.get('Calendar');
      Ext.Msg.confirm(app.i18n._('Set This Date as Definite Event?'), app.i18n._('Do you want to close the poll and remove all other alternatives?'), function (button) {
        if (button == 'yes') {
          fulfill();
        } else {
          reject('canceled');
        }
      });
    });
  }
};

/***/ }),

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

/*
 * Tine 2.0
 *
 * @package     Calendar
 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 * @copyright   Copyright (c) 2017 Metaways Infosystems GmbH (http://www.metaways.de)
 *
 */
Ext.ns('Tine.Calendar');
/**
 * @namespace   Tine.Calendar
 * @class       Tine.Calendar.ResourcePickerCombo
 * @extends     Tine.Tinebase.widgets.form.RecordPickerComboBox
 * @author      Cornelius Weiss <c.weiss@metaways.de>
 */

Tine.Calendar.ResourcePickerCombo = Ext.extend(Tine.Tinebase.widgets.form.RecordPickerComboBox, {
  recordClass: Tine.Calendar.Model.Resource,

  /**
   * init template
   * @private
   */
  initTemplate: function initTemplate() {
    if (!this.tpl) {
      this.tpl = new Ext.XTemplate('<tpl for=".">', '<div class="x-combo-list-item">', '<table>', '<tr>', '<td style="min-width: 20px;">{[this.encodeIconTypes(values.type)]}</td>', '<td width="100%">{[Tine.Tinebase.EncodingHelper.encode(values.name)]}</td>', '</tr>', '<tr>', '<td style="min-width: 20px;">&nbsp</td>', '<td class="cal-attendee-resource-hierarchy">{[this.encodeHierarchy(values.hierarchy)]}</td>', '</tr>', '</table>', '{[Tine.widgets.path.pathsRenderer(values.paths, this.lastQuery)]}', '</div>', '</tpl>', {
        encodeHierarchy: function encodeHierarchy(hierarchy) {
          hierarchy = String(hierarchy).replace(/\//g, ' » ');

          if (hierarchy == 'null') {
            return '';
          }

          return Tine.Tinebase.EncodingHelper.encode(hierarchy);
        },
        encodeIconTypes: function encodeIconTypes(type) {
          icon = Tine.Tinebase.widgets.keyfield.StoreMgr.get('Calendar', 'resourceTypes').getById(type).get('icon');
          return '<img class="tine-grid-row-action-icon" src="' + icon + '"/>';
        }
      });
    }
  }
});
Tine.widgets.form.RecordPickerManager.register('Calendar', 'Resource', Tine.Calendar.ResourcePickerCombo);

/***/ })

}]);