<commit_before>/*!
 * ${copyright}
 */

sap.ui.define(['jquery.sap.global', 'sap/ui/core/library'],
	function () {
		"use strict";

		// sap.ui.require(["sap/ui/core/support/appInfo"], function (appInfo) {}); TODO remove
		var versionInfo = sap.ui.getVersionInfo();
		var configurationInfo = sap.ui.getCore().getConfiguration();

		//================================================================================
		// Technical Information
		//================================================================================

		function _getLibraries() {
			var request = jQuery.sap.syncGetJSON(sap.ui.resource('', 'sap-ui-version.json'));
			var formattedLibraries = Object.create(null);

			if (request.success) {
				var libraries = request.data && request.data.libraries;

				libraries.forEach(function (element, index, array) {
					formattedLibraries[element.name] = element.version;
				});
			}

			return formattedLibraries;
		}

		function _getLoadedLibraries() {
			var libraries = sap.ui.getCore().getLoadedLibraries();
			var formattedLibraries = Object.create(null);

			Object.keys(sap.ui.getCore().getLoadedLibraries()).forEach(function (element, index, array) {
				formattedLibraries[element] = libraries[element].version;
			});

			return formattedLibraries;
		}

		// Name space for all technical information about the framework
		var frameworkInformation = {

			commonInformation: {
				frameWorkName: (versionInfo.gav && versionInfo.gav.indexOf('openui5') !== -1) ? 'OpenUI5' : 'SAPUI5',
				version: sap.ui.version,
				buildTime: sap.ui.buildinfo.buildtime,
				lastChange: sap.ui.buildinfo.lastchange,
				userAgent: navigator.userAgent,
				applicationHREF: window.location.href,
				documentTitle: document.title,
				documentMode: document.documentMode || '',
				debugMode: jQuery.sap.debug(),
				statistics: jQuery.sap.statistics()
			},

			configurationBootstrap: window['sap-ui-config'] || Object.create(null),

			configurationComputed: {
				theme: configurationInfo.getTheme(),
				language: configurationInfo.getLanguage(),
				formatLocale: configurationInfo.getFormatLocale(),
				accessibility: configurationInfo.getAccessibility(),
				animation: configurationInfo.getAnimation(),
				rtl: configurationInfo.getRTL(),
				debug: configurationInfo.getDebug(),
				inspect: configurationInfo.getInspect(),
				originInfo: configurationInfo.getOriginInfo(),
				noDuplicateIds: configurationInfo.getNoDuplicateIds()
			},

			libraries: _getLibraries(),

			loadedLibraries: _getLoadedLibraries(),

			loadedModules: jQuery.sap.getAllDeclaredModules().sort(),

			URLParameters: jQuery.sap.getUriParameters().mParams
		};

		//================================================================================
		// Control tree Information
		//================================================================================

		/**
		 * Name space for all methods related to control trees
		 * @type {{_createRenderedTreeModel: Function}}
		 */
		var controlTree = {

			/**
			 * Create data model of the rendered controls as a tree
			 * @param (Element) nodeElement - HTML DOM element from which the function will star searching
			 * @param {array} resultArray - Array that will contains all the information
			 */
			_createRenderedTreeModel: function (nodeElement, resultArray) {
				var node = nodeElement,
					childNode = node.firstElementChild,
					results = resultArray,
					subResult;

				if (node.getAttribute('data-sap-ui') && sap.ui.getCore().byId(node.id)) {
					results.push({
						id: node.id,
						name: sap.ui.getCore().byId(node.id).getMetadata().getName(),
						type: 'data-sap-ui',
						content: []
					});

					subResult = results[results.length - 1].content;
				} else {
					subResult = results;
				}

				while (childNode) {
					this._createRenderedTreeModel(childNode, subResult);
					childNode = childNode.nextElementSibling;
				}
			}
		};

		//================================================================================
		// Control Information
		//================================================================================

		/**
		 * Name space for all information relevant for UI5 control
		 * @type {{_getOwnProperties: Function, _copyInheritedProperties: Function, _getInheritedProperties: Function, _getProperties: Function}}
		 */
		var controlInformation = {

			// Control Properties Info
			//================================================================================

			/**
			 *
			 * @param control
			 * @returns {null}
			 * @private
			 */
			_getOwnProperties: function (control) {
				var result = Object.create(null);
				var controlPropertiesFromMetadata = control.getMetadata().getProperties();

				Object.keys(controlPropertiesFromMetadata).forEach(function (key) {
					result[key] = Object.create(null);
					result[key].value = control.getProperty(key);
					result[key].type = controlPropertiesFromMetadata[key].type;
				});

				return result;
			},

			/**
			 *
			 * @param control
			 * @param inheritedMetadata
			 * @returns {null}
			 * @private
			 */
			_copyInheritedProperties: function (control, inheritedMetadata) {
				var inheritedMetadataProperties = inheritedMetadata.getProperties();

				var result = Object.create(null);
				result.controlName = inheritedMetadata.getName();
				result.controlProperties = Object.create(null);

				Object.keys(inheritedMetadataProperties).forEach(function (key) {
					result.controlProperties[key] = Object.create(null);

					// Check if the property is used in the control
					if (control.getProperty(key)) {
						result.controlProperties[key].value = control.getProperty(key);
					} else {
						result.controlProperties[key].value = inheritedMetadataProperties[key].defaultValue;
					}

					result.controlProperties[key].type = inheritedMetadataProperties[key].type;
				});

				return result;
			},

			/**
			 *
			 * @param control
			 * @returns {Array}
			 * @private
			 */
			_getInheritedProperties: function (control) {
				var result = [];
				var inheritedMetadata = control.getMetadata().getParent();

				while (inheritedMetadata instanceof sap.ui.core.ElementMetadata) {
					result.push(this._copyInheritedProperties(control, inheritedMetadata));
					inheritedMetadata = inheritedMetadata.getParent();
				}

				return result;
			},

			/**
			 *
			 * @param controlId
			 * @returns {null}
			 * @private
			 */
			_getProperties: function (controlId) {
				var control = sap.ui.getCore().byId(controlId);

				var properties = Object.create(null);
				properties.own = this._getOwnProperties(control);
				properties.inherited = this._getInheritedProperties(control);

				return properties;
			},

			// Binding Info
			//================================================================================

			/**
			 * @param {Object} bindingContext
			 * @returns {{name: string, path: *}}
			 * @private
			 */
			_getModelFromContext: function (bindingContext) {
				var model = {
					name: (!bindingContext.sModelName) ? 'default' : bindingContext.sModelName,
					path: bindingContext.getPath()
				};

				if (bindingContext.oModel) {
					model.mode = bindingContext.oModel.sDefaultBindingMode;
					model.type = bindingContext.oModel.getMetadata()._sClassName;
					model.data = bindingContext.oModel.oData;
				}

				return model;
			},

			/**
			 *
			 * @param {Object} control
			 * @returns {Object}
			 * @private
			 */
			_getBindDataForProperties: function (control) {
				// TODO need some default value if there is no available data

				var properties = control.getMetadata().getAllProperties();
				var propertiesBindingData = Object.create(null);

				for (var key in properties) {
					if (properties.hasOwnProperty(key)) {
						if (control.getBinding(key)) {
							propertiesBindingData[key] = Object.create(null);
							propertiesBindingData[key].path = control.getBinding(key).sPath;
							propertiesBindingData[key].value = control.getBinding(key).oValue;
							propertiesBindingData[key].type = control.getBinding(key).sInternalType;
							propertiesBindingData[key].mode = control.getBinding(key).sMode;
							propertiesBindingData[key].model = this._getModelFromContext(control.getBinding(key));
						}
					}
				}

				return propertiesBindingData;
			},

			/**
			 *
			 * @param {Object} control
			 * @returns {Object}
			 * @private
			 */
			_getBindDataForAggregations: function (control) {
				// TODO need some default value if there is no available data

				var aggregations = control.getMetadata().getAllAggregations();
				var aggregationsBindingData = Object.create(null);

				for (var key in aggregations) {
					if (aggregations.hasOwnProperty(key)) {
						if (control.getBinding(key)) {
							aggregationsBindingData[key] = Object.create(null);
							aggregationsBindingData[key].model = this._getModelFromContext(control.getBinding(key));
						}
					}
				}

				return aggregationsBindingData;
			}
		};

		//================================================================================
		// Public API
		//================================================================================

		/**
		 * Global object that provide common information for all support tools
		 * @type {{getFrameworkInformation: Function, getRenderedControlTree: Function, getControlProperties: Function, getControlBindingInformation: Function}}
		 */
		return {

			/**
			 * Common information about the framework
			 * @returns {{commonInformation: {frameWorkName: string, version: string, buildTime: (string|string), lastChange: (string|string), userAgent: *, applicationHREF: string}, configurationBootstrap: *, configurationComputed: {theme: (*|string), language: (*|string), formatLocale: (*|string), accessibility: (*|boolean), animation: (*|boolean), rtl: (*|boolean), debug: (*|boolean), inspect: (*|boolean), originInfo: (*|boolean), noDuplicateIds: (*|boolean)}, libraries: (*|libraryConfig|oLibs), loadedLibraries: map, loadedModules: Array.<string>, URLParameters: *}}
			 */
			getFrameworkInformation: function () {
				return frameworkInformation;
			},

			/**
			 * Array model of the rendered control as a tree
			 * @returns {Array}
			 */
			getRenderedControlTree: function () {
				var renderedControlTreeModel = [];
				controlTree._createRenderedTreeModel(document.body, renderedControlTreeModel);

				return renderedControlTreeModel;
			},

			/**
			 *
			 * @param {string} controlId
			 * @returns {Object}
			 */
			getControlProperties: function (controlId) {
				return controlInformation._getProperties(controlId);
			},

			/**
			 *
			 * @param control
			 * @returns {*}
			 */
			getControlBindingData: function (controlId) {
				var control = sap.ui.getCore().byId(controlId);

				if (!control) {
					return Object.create(null);
				}

				var bindingData = Object.create(null);
				var bindingContext = control.getBindingContext();

				//this available only for directly bound controls
				// TODO need some default value if there is no available data
				if (bindingContext) {
					bindingData.contextPath = bindingContext.sPath;
				}

				bindingData.aggregations = controlInformation._getBindDataForAggregations(control);
				bindingData.properties = controlInformation._getBindDataForProperties(control);

				return bindingData;
			}
		};

	}, /* bExport= */ false);
<commit_msg>[INTERNEAL][FIX] toolsAPI: Added check for sap-ui-version.json file<commit_after>/*!
 * ${copyright}
 */

sap.ui.define(['jquery.sap.global', 'sap/ui/core/library'],
	function () {
		"use strict";

		// sap.ui.require(["sap/ui/core/support/toolsAPI"], function (toolsAPI) {g=toolsAPI}); TODO remove
		var versionInfo = sap.ui.getVersionInfo();
		var configurationInfo = sap.ui.getCore().getConfiguration();

		//================================================================================
		// Technical Information
		//================================================================================

		function _getLibraries() {
			var libraries = sap.ui.versioninfo ? sap.ui.versioninfo.libraries : undefined;
			var formattedLibraries = Object.create(null);

			if (libraries !== undefined) {
				libraries.forEach(function (element, index, array) {
					formattedLibraries[element.name] = element.version;
				});
			}

			return formattedLibraries;
		}

		function _getLoadedLibraries() {
			var libraries = sap.ui.getCore().getLoadedLibraries();
			var formattedLibraries = Object.create(null);

			Object.keys(sap.ui.getCore().getLoadedLibraries()).forEach(function (element, index, array) {
				formattedLibraries[element] = libraries[element].version;
			});

			return formattedLibraries;
		}

		// Name space for all technical information about the framework
		var frameworkInformation = {

			commonInformation: {
				frameWorkName: (versionInfo.gav && versionInfo.gav.indexOf('openui5') !== -1) ? 'OpenUI5' : 'SAPUI5',
				version: sap.ui.version,
				buildTime: sap.ui.buildinfo.buildtime,
				lastChange: sap.ui.buildinfo.lastchange,
				userAgent: navigator.userAgent,
				applicationHREF: window.location.href,
				documentTitle: document.title,
				documentMode: document.documentMode || '',
				debugMode: jQuery.sap.debug(),
				statistics: jQuery.sap.statistics()
			},

			configurationBootstrap: window['sap-ui-config'] || Object.create(null),

			configurationComputed: {
				theme: configurationInfo.getTheme(),
				language: configurationInfo.getLanguage(),
				formatLocale: configurationInfo.getFormatLocale(),
				accessibility: configurationInfo.getAccessibility(),
				animation: configurationInfo.getAnimation(),
				rtl: configurationInfo.getRTL(),
				debug: configurationInfo.getDebug(),
				inspect: configurationInfo.getInspect(),
				originInfo: configurationInfo.getOriginInfo(),
				noDuplicateIds: configurationInfo.getNoDuplicateIds()
			},

			libraries: _getLibraries(),

			loadedLibraries: _getLoadedLibraries(),

			loadedModules: jQuery.sap.getAllDeclaredModules().sort(),

			URLParameters: jQuery.sap.getUriParameters().mParams
		};

		//================================================================================
		// Control tree Information
		//================================================================================

		/**
		 * Name space for all methods related to control trees
		 * @type {{_createRenderedTreeModel: Function}}
		 */
		var controlTree = {

			/**
			 * Create data model of the rendered controls as a tree
			 * @param (Element) nodeElement - HTML DOM element from which the function will star searching
			 * @param {array} resultArray - Array that will contains all the information
			 */
			_createRenderedTreeModel: function (nodeElement, resultArray) {
				var node = nodeElement,
					childNode = node.firstElementChild,
					results = resultArray,
					subResult;

				if (node.getAttribute('data-sap-ui') && sap.ui.getCore().byId(node.id)) {
					results.push({
						id: node.id,
						name: sap.ui.getCore().byId(node.id).getMetadata().getName(),
						type: 'data-sap-ui',
						content: []
					});

					subResult = results[results.length - 1].content;
				} else {
					subResult = results;
				}

				while (childNode) {
					this._createRenderedTreeModel(childNode, subResult);
					childNode = childNode.nextElementSibling;
				}
			}
		};

		//================================================================================
		// Control Information
		//================================================================================

		/**
		 * Name space for all information relevant for UI5 control
		 * @type {{_getOwnProperties: Function, _copyInheritedProperties: Function, _getInheritedProperties: Function, _getProperties: Function}}
		 */
		var controlInformation = {

			// Control Properties Info
			//================================================================================

			/**
			 *
			 * @param control
			 * @returns {null}
			 * @private
			 */
			_getOwnProperties: function (control) {
				var result = Object.create(null);
				var controlPropertiesFromMetadata = control.getMetadata().getProperties();

				Object.keys(controlPropertiesFromMetadata).forEach(function (key) {
					result[key] = Object.create(null);
					result[key].value = control.getProperty(key);
					result[key].type = controlPropertiesFromMetadata[key].type;
				});

				return result;
			},

			/**
			 *
			 * @param control
			 * @param inheritedMetadata
			 * @returns {null}
			 * @private
			 */
			_copyInheritedProperties: function (control, inheritedMetadata) {
				var inheritedMetadataProperties = inheritedMetadata.getProperties();

				var result = Object.create(null);
				result.controlName = inheritedMetadata.getName();
				result.controlProperties = Object.create(null);

				Object.keys(inheritedMetadataProperties).forEach(function (key) {
					result.controlProperties[key] = Object.create(null);

					// Check if the property is used in the control
					if (control.getProperty(key)) {
						result.controlProperties[key].value = control.getProperty(key);
					} else {
						result.controlProperties[key].value = inheritedMetadataProperties[key].defaultValue;
					}

					result.controlProperties[key].type = inheritedMetadataProperties[key].type;
				});

				return result;
			},

			/**
			 *
			 * @param control
			 * @returns {Array}
			 * @private
			 */
			_getInheritedProperties: function (control) {
				var result = [];
				var inheritedMetadata = control.getMetadata().getParent();

				while (inheritedMetadata instanceof sap.ui.core.ElementMetadata) {
					result.push(this._copyInheritedProperties(control, inheritedMetadata));
					inheritedMetadata = inheritedMetadata.getParent();
				}

				return result;
			},

			/**
			 *
			 * @param controlId
			 * @returns {null}
			 * @private
			 */
			_getProperties: function (controlId) {
				var control = sap.ui.getCore().byId(controlId);

				var properties = Object.create(null);
				properties.own = this._getOwnProperties(control);
				properties.inherited = this._getInheritedProperties(control);

				return properties;
			},

			// Binding Info
			//================================================================================

			/**
			 * @param {Object} bindingContext
			 * @returns {{name: string, path: *}}
			 * @private
			 */
			_getModelFromContext: function (bindingContext) {
				var model = {
					name: (!bindingContext.sModelName) ? 'default' : bindingContext.sModelName,
					path: bindingContext.getPath()
				};

				if (bindingContext.oModel) {
					model.mode = bindingContext.oModel.sDefaultBindingMode;
					model.type = bindingContext.oModel.getMetadata()._sClassName;
					model.data = bindingContext.oModel.oData;
				}

				return model;
			},

			/**
			 *
			 * @param {Object} control
			 * @returns {Object}
			 * @private
			 */
			_getBindDataForProperties: function (control) {
				// TODO need some default value if there is no available data

				var properties = control.getMetadata().getAllProperties();
				var propertiesBindingData = Object.create(null);

				for (var key in properties) {
					if (properties.hasOwnProperty(key)) {
						if (control.getBinding(key)) {
							propertiesBindingData[key] = Object.create(null);
							propertiesBindingData[key].path = control.getBinding(key).sPath;
							propertiesBindingData[key].value = control.getBinding(key).oValue;
							propertiesBindingData[key].type = control.getBinding(key).sInternalType;
							propertiesBindingData[key].mode = control.getBinding(key).sMode;
							propertiesBindingData[key].model = this._getModelFromContext(control.getBinding(key));
						}
					}
				}

				return propertiesBindingData;
			},

			/**
			 *
			 * @param {Object} control
			 * @returns {Object}
			 * @private
			 */
			_getBindDataForAggregations: function (control) {
				// TODO need some default value if there is no available data

				var aggregations = control.getMetadata().getAllAggregations();
				var aggregationsBindingData = Object.create(null);

				for (var key in aggregations) {
					if (aggregations.hasOwnProperty(key)) {
						if (control.getBinding(key)) {
							aggregationsBindingData[key] = Object.create(null);
							aggregationsBindingData[key].model = this._getModelFromContext(control.getBinding(key));
						}
					}
				}

				return aggregationsBindingData;
			}
		};

		//================================================================================
		// Public API
		//================================================================================

		/**
		 * Global object that provide common information for all support tools
		 * @type {{getFrameworkInformation: Function, getRenderedControlTree: Function, getControlProperties: Function, getControlBindingInformation: Function}}
		 */
		return {

			/**
			 * Common information about the framework
			 * @returns {{commonInformation: {frameWorkName: string, version: string, buildTime: (string|string), lastChange: (string|string), userAgent: *, applicationHREF: string}, configurationBootstrap: *, configurationComputed: {theme: (*|string), language: (*|string), formatLocale: (*|string), accessibility: (*|boolean), animation: (*|boolean), rtl: (*|boolean), debug: (*|boolean), inspect: (*|boolean), originInfo: (*|boolean), noDuplicateIds: (*|boolean)}, libraries: (*|libraryConfig|oLibs), loadedLibraries: map, loadedModules: Array.<string>, URLParameters: *}}
			 */
			getFrameworkInformation: function () {
				return frameworkInformation;
			},

			/**
			 * Array model of the rendered control as a tree
			 * @returns {Array}
			 */
			getRenderedControlTree: function () {
				var renderedControlTreeModel = [];
				controlTree._createRenderedTreeModel(document.body, renderedControlTreeModel);

				return renderedControlTreeModel;
			},

			/**
			 *
			 * @param {string} controlId
			 * @returns {Object}
			 */
			getControlProperties: function (controlId) {
				return controlInformation._getProperties(controlId);
			},

			/**
			 *
			 * @param control
			 * @returns {*}
			 */
			getControlBindingData: function (controlId) {
				var control = sap.ui.getCore().byId(controlId);

				if (!control) {
					return Object.create(null);
				}

				var bindingData = Object.create(null);
				var bindingContext = control.getBindingContext();

				//this available only for directly bound controls
				// TODO need some default value if there is no available data
				if (bindingContext) {
					bindingData.contextPath = bindingContext.sPath;
				}

				bindingData.aggregations = controlInformation._getBindDataForAggregations(control);
				bindingData.properties = controlInformation._getBindDataForProperties(control);

				return bindingData;
			}
		};

	}, /* bExport= */ false);
<|endoftext|>


<commit_before>'use strict';

/* global moment */
{
  class AvailabilityCalendar {
    start(el) {
      this.$el = el;
      this.$slotsUri = this.$el.data('slots-uri')
      this.$modal = this.$el.find('.js-availability-modal')

      $(this.$el).fullCalendar({
        header: {
          right: 'agendaDay agendaWeek prev,next'
        },
        resourceLabelText: 'Rooms',
        groupByDateAndResource: true,
        nowIndicator: true,
        allDaySlot: false,
        buttonText: {
          today: 'Jump to today'
        },
        slotLabelInterval: { 'minutes': 60 },
        displayEventTime: false,
        columnFormat: 'ddd D/M',
        height: 'auto',
        maxTime: '18:00:00',
        minTime: '09:00:00',
        weekends: false,
        defaultView: 'agendaWeek',
        slotDuration: '00:10:00',
        showNonCurrentDates: false,
        defaultDate: moment(el.data('default-date')),
        firstDay: 1,
        resources: el.data('rooms-uri'),
        timezone: 'local',
        eventSources: [
          {
            url: this.$slotsUri,
            cache: true,
            rendering: 'background',
            eventType: 'slot'
          }
        ],
        dayClick: (date, jsEvent, _, resourceObject) => {
          jsEvent.preventDefault()

          if (jsEvent.target.classList.contains('js-slot')) {
            this.deleteSlot(jsEvent)
          } else {
            this.createSlot(date, resourceObject)
          }
        },
        eventRender: (event, element) => {
          $(element).attr('id', event.id).addClass('t-slot js-slot')
        },
        resourceRender: (resource, labelTds) => {
          labelTds.addClass('t-room')
        },
        loading: (isLoading) => {
          this.insertLoadingView();

          if (!isLoading && this.$loadingSpinner) {
            clearTimeout(this.loadingTimeout);
            return this.$loadingSpinner.addClass('hide');
          }

          this.loadingTimeout = setTimeout(() => {
            if (isLoading && this.$loadingSpinner) {
              this.$loadingSpinner.removeClass('hide');
            }
          }, 200);
        },
        schedulerLicenseKey: 'GPL-My-Project-Is-Open-Source'
      });
    }

    deleteSlot(jsEvent) {
      if (confirm('Are you sure you want to delete this slot?')) {
        this.showSpinner()

        const id = jsEvent.target.id

        $.ajax({
          type: 'DELETE',
          url: `${this.$slotsUri}/${id}`,
          headers: { 'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content') },
          success: () => {
            $(this.$el).fullCalendar('refetchEvents')

            this.showSuccess()
          },
          complete: () => {
            this.hideSpinner()
          }
        })
      }
    }

    showSpinner() {
      this.$loadingSpinner.removeClass('hide');
    }

    hideSpinner() {
      this.$loadingSpinner.addClass('hide');
    }

    insertLoadingView() {
      if (this.$loadingSpinner) {
        return;
      }

      this.$loadingSpinner = $(`

`);

      this.$loadingSpinner.appendTo($('.fc-view-container'));
    }

    showSuccess() {
      $('.alert')
        .hide()
        .filter('.alert-success')
        .show()
        .delay(3000)
        .fadeOut('slow');
    }

    createSlot(date, resourceObject) {
      this.showSpinner()

      $.post({
        url: this.$slotsUri,
        data: { start_at: date.utc().format(), room_id: resourceObject.id },
        headers: { 'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content') },
        success: () => {
          $(this.$el).fullCalendar('refetchEvents')
        },
        complete: () => {
          this.hideSpinner()
        }
      })
    }
  }

  window.GOVUKAdmin.Modules.AvailabilityCalendar = AvailabilityCalendar;
}
<commit_msg>Only show spinner when loading slots<commit_after>'use strict';

/* global moment */
{
  class AvailabilityCalendar {
    start(el) {
      this.$el = el;
      this.$slotsUri = this.$el.data('slots-uri')
      this.$modal = this.$el.find('.js-availability-modal')

      $(this.$el).fullCalendar({
        header: {
          right: 'agendaDay agendaWeek prev,next'
        },
        resourceLabelText: 'Rooms',
        groupByDateAndResource: true,
        nowIndicator: true,
        allDaySlot: false,
        buttonText: {
          today: 'Jump to today'
        },
        slotLabelInterval: { 'minutes': 60 },
        displayEventTime: false,
        columnFormat: 'ddd D/M',
        height: 'auto',
        maxTime: '18:00:00',
        minTime: '09:00:00',
        weekends: false,
        defaultView: 'agendaWeek',
        slotDuration: '00:10:00',
        showNonCurrentDates: false,
        defaultDate: moment(el.data('default-date')),
        firstDay: 1,
        resources: el.data('rooms-uri'),
        timezone: 'local',
        eventSources: [
          {
            url: this.$slotsUri,
            cache: true,
            rendering: 'background',
            eventType: 'slot'
          }
        ],
        dayClick: (date, jsEvent, _, resourceObject) => {
          jsEvent.preventDefault()

          if (jsEvent.target.classList.contains('js-slot')) {
            this.deleteSlot(jsEvent)
          } else {
            this.createSlot(date, resourceObject)
          }
        },
        eventRender: (event, element) => {
          $(element).attr('id', event.id).addClass('t-slot js-slot')
        },
        resourceRender: (resource, labelTds) => {
          labelTds.addClass('t-room')
        },
        loading: (isLoading) => {
          this.insertLoadingView();

          if (!isLoading && this.$loadingSpinner) {
            clearTimeout(this.loadingTimeout);
            return this.$loadingSpinner.addClass('hide');
          }

          this.loadingTimeout = setTimeout(() => {
            if (isLoading && this.$loadingSpinner) {
              this.$loadingSpinner.removeClass('hide');
            }
          }, 200);
        },
        schedulerLicenseKey: 'GPL-My-Project-Is-Open-Source'
      });
    }

    deleteSlot(jsEvent) {
      if (confirm('Are you sure you want to delete this slot?')) {
        const id = jsEvent.target.id

        $.ajax({
          type: 'DELETE',
          url: `${this.$slotsUri}/${id}`,
          headers: { 'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content') },
          success: () => {
            $(this.$el).fullCalendar('refetchEvents')

            this.showSuccess()
          }
        })
      }
    }

    showSpinner() {
      this.$loadingSpinner.removeClass('hide');
    }

    hideSpinner() {
      this.$loadingSpinner.addClass('hide');
    }

    insertLoadingView() {
      if (this.$loadingSpinner) {
        return;
      }

      this.$loadingSpinner = $(`

`);

      this.$loadingSpinner.appendTo($('.fc-view-container'));
    }

    showSuccess() {
      $('.alert')
        .hide()
        .filter('.alert-success')
        .show()
        .delay(3000)
        .fadeOut('slow');
    }

    createSlot(date, resourceObject) {
      $.post({
        url: this.$slotsUri,
        data: { start_at: date.utc().format(), room_id: resourceObject.id },
        headers: { 'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content') },
        success: () => {
          $(this.$el).fullCalendar('refetchEvents')
        }
      })
    }
  }

  window.GOVUKAdmin.Modules.AvailabilityCalendar = AvailabilityCalendar;
}
<|endoftext|>


<commit_before>App.Components.DatePickerComponent = Frontend.Component.extend({
    setup: function($elements) {

        $elements.each(function(i, element) {
            var $container = $(element);
            var $selectContainer = $container.find('select.form-control:first').parent();
            $container.find('select.form-control').hide();

            var pickerMarkup = '
<input type="text" class="form-control"/>
';
            $selectContainer.append(pickerMarkup);

            var type = $container.hasClass('dateTime') ? 'dateTime' : 'date';
            var format = 'DD.MM.YYYY';
            if(type === 'dateTime') {
                format = 'DD.MM.YYYY HH:mm';
            }

            var $picker = $selectContainer.find('.input-group.date');
            $picker.datetimepicker({
                format: format,
                sideBySide: true,
                locale: this.Controller.getVar('locale') || 'en',
                date: this._getDateFromSelects($container)
            });

            // Update the selects to the correct values after a datepicker change
            $picker.on('dp.change', function(e) {
                var $container = $(e.currentTarget).parents('.form-group');
                this._updateSelects($container, e.date);
            }.bind(this));
        }.bind(this));
    },
    _updateSelects: function($selectContainer, date) {
        $selectContainer.find('select.form-control').each(function(i, el) {
            var $select = $(el);
            if($select.attr('name').indexOf('[year]') > -1) {
                $select.val(date.year());
            }
            if($select.attr('name').indexOf('[month]') > -1) {
                $select.val(date.format('MM'));
            }
            if($select.attr('name').indexOf('[day]') > -1) {
                $select.val(date.format('DD'));
            }
            if($select.attr('name').indexOf('[hour]') > -1) {
                $select.val(date.format('HH'));
            }
            if($select.attr('name').indexOf('[minute]') > -1) {
                $select.val(date.format('mm'));
            }
        });
    },
    _getDateFromSelects: function($selectContainer) {
        var date = moment();
        $selectContainer.find('select.form-control').each(function(i, el) {
            var $select = $(el);
            var val = parseInt($select.val(), 10);
            if($select.attr('name').indexOf('[year]') > -1) {
                date.year(val);
            }
            if($select.attr('name').indexOf('[month]') > -1) {
                date.month(val - 1);
            }
            if($select.attr('name').indexOf('[day]') > -1) {
                date.date(val);
            }
            if($select.attr('name').indexOf('[hour]') > -1) {
                date.hour(val);
            }
            if($select.attr('name').indexOf('[minute]') > -1) {
                date.minute(val);
            }
        });
        return date;
    }
});<commit_msg>make datepicker input nullable<commit_after>App.Components.DatePickerComponent = Frontend.Component.extend({
    setup: function($elements) {

        $elements.each(function(i, element) {
            var $container = $(element);
            var $selectContainer = $container.find('select.form-control:first').parent();
            $container.find('select.form-control').hide();

            var pickerMarkup = '
<input type="text" class="form-control"/>
';
            $selectContainer.append(pickerMarkup);

            var type = $container.hasClass('dateTime') ? 'dateTime' : 'date';
            var format = 'DD.MM.YYYY';
            if(type === 'dateTime') {
                format = 'DD.MM.YYYY HH:mm';
            }

            var $picker = $selectContainer.find('.input-group.date');
            $picker.datetimepicker({
                format: format,
                sideBySide: true,
                locale: this.Controller.getVar('locale') || 'en',
                date: this._getDateFromSelects($container)
            });

            // Update the selects to the correct values after a datepicker change
            $picker.on('dp.change', function(e) {
                var $container = $(e.currentTarget).parents('.form-group');
                this._updateSelects($container, e.date, $(e.currentTarget));
            }.bind(this));
        }.bind(this));
    },
    _updateSelects: function($selectContainer, date, input) {
		if (input.find('input').val().length == 0) {
			$selectContainer.find('select.form-control option[selected="selected"]').each(function(i, el) {
				$(el).removeAttr("selected");
			 });
			 return null;
		}
        $selectContainer.find('select.form-control').each(function(i, el) {
            var $select = $(el);
            if($select.attr('name').indexOf('[year]') > -1) {
                $select.val(date.year());
            }
            if($select.attr('name').indexOf('[month]') > -1) {
                $select.val(date.format('MM'));
            }
            if($select.attr('name').indexOf('[day]') > -1) {
                $select.val(date.format('DD'));
            }
            if($select.attr('name').indexOf('[hour]') > -1) {
                $select.val(date.format('HH'));
            }
            if($select.attr('name').indexOf('[minute]') > -1) {
                $select.val(date.format('mm'));
            }
        });
    },
    _getDateFromSelects: function($selectContainer) {
        var date = moment();
        $selectContainer.find('select.form-control').each(function(i, el) {
            var $select = $(el);
            var val = parseInt($select.val(), 10);
            if($select.attr('name').indexOf('[year]') > -1) {
                date.year(val);
            }
            if($select.attr('name').indexOf('[month]') > -1) {
                date.month(val - 1);
            }
            if($select.attr('name').indexOf('[day]') > -1) {
                date.date(val);
            }
            if($select.attr('name').indexOf('[hour]') > -1) {
                date.hour(val);
            }
            if($select.attr('name').indexOf('[minute]') > -1) {
                date.minute(val);
            }
        });
        return date;
    }
});<|endoftext|>


<commit_before>'use strict';

var gulp = require('gulp'),
    concat = require('gulp-concat'),
    uglify = require('gulp-uglify'),
    rename = require('gulp-rename'),
    sass = require('gulp-sass'),
    watch = require('gulp-watch'),
    clean = require('gulp-clean'),
    gutil = require('gulp-util'),
    liveReload = require('gulp-livereload'),
    minify = require('gulp-minify-css'),
    merge = require('merge-stream'),
    ncu = require('npm-check-updates');

gulp.task('update', function () {
    ncu.run({
        // Always specify the path to the package file
        packageFile:  'package.json',
        // Any command-line option can be specified here:
        silent:       true,
        jsonUpgraded: true
    }).then(function (upgraded) {
        console.log('dependencies to upgrade:', upgraded);
        console.log('Use: ncu --upgradeAll & npm install');
    });
});

gulp.task('clean', function (done) {
    gulp.src(['dist'], {
        read: false
    })
        .pipe(clean())
        .on('end', function () {
            gutil.log('All cleaned!');
        });
        done();
});

gulp.task('clean-js', function (done) {
    gulp.src(['dist/js/*.js'], {
        read: false
    })
        .pipe(clean());
        done();
});

gulp.task('clean-css', function (done) {
    gulp.src(['dist/css/*.css'], {
        read: false
    })
        .pipe(clean());
        done();
});

gulp.task('concat-minify-js', function (done) {
    gulp.src([
        "assets/libs/jquery-2.2.3.js",
        "assets/libs/modernizr-custom.js",
        "bower_components/wow/dist/wow.js",
        "assets/js/main.js"
    ])
        .pipe(concat('build'))
        .pipe(uglify())
        .pipe(rename({
            extname: ".min.js"
        }))
        .pipe(gulp.dest('dist/js'))
        .pipe(liveReload({
            auto: false
        }))
        .on('end', function () {
            gutil.log('Scripts concatenated and merged!');
        });
    done();
});

gulp.task('concat-minify-css', function (done) {
    var sassStream = gulp.src('src/scss/main.scss')
        .pipe(sass({
            errLogToConsole: true
        }));

    var cssStream = gulp.src([
        "bower_components/flexboxgrid/dist/flexboxgrid.css",
        "bower_components/wow/css/libs/animate.css"
    ]);

    return merge(sassStream, cssStream)
        .pipe(concat('build.min.css'))
        .pipe(minify({
            keepBreaks: true
        }))
        .pipe(gulp.dest('dist/css'))
        .on('end', function () {
            gutil.log('Styles concatenated and merged!');
            done();
        });
});

gulp.task('watch', function () {
    gulp.watch('./src/scss/**/*.scss', gulp.series('clean-css', 'concat-minify-css'));
    gulp.watch('./assets/js/*.js', gulp.series('clean-js', 'concat-minify-js'));
});

gulp.task('default', gulp.series('clean', 'concat-minify-js', 'concat-minify-css', 'watch'));
<commit_msg>Gulp fixes<commit_after>'use strict';

var gulp = require('gulp'),
    concat = require('gulp-concat'),
    uglify = require('gulp-uglify'),
    rename = require('gulp-rename'),
    sass = require('gulp-sass'),
    watch = require('gulp-watch'),
    clean = require('gulp-clean'),
    gutil = require('gulp-util'),
    liveReload = require('gulp-livereload'),
    minify = require('gulp-minify-css'),
    merge = require('merge-stream'),
    ncu = require('npm-check-updates');

gulp.task('update', function () {
    ncu.run({
        // Always specify the path to the package file
        packageFile:  'package.json',
        // Any command-line option can be specified here:
        silent:       true,
        jsonUpgraded: true
    }).then(function (upgraded) {
        console.log('dependencies to upgrade:', upgraded);
        console.log('Use: ncu --upgradeAll & npm install');
    });
});

gulp.task('clean', function (done) {
    gulp.src(['dist'], {
        read: false
    })
        .pipe(clean())
        .on('end', function () {
            gutil.log('All cleaned!');
        });
        done();
});

gulp.task('clean-js', function (done) {
    gulp.src(['dist/js/*.js'], {
        read: false
    })
        .pipe(clean());
        done();
});

gulp.task('clean-css', function (done) {
    gulp.src(['dist/css/*.css'], {
        read: false
    })
        .pipe(clean());
        done();
});

gulp.task('concat-minify-js', function (done) {
    gulp.src([
        "assets/libs/jquery-2.2.3.js",
        "assets/libs/modernizr-custom.js",
        "bower_components/wow/dist/wow.js",
        "assets/js/main.js"
    ])
        .pipe(concat('build'))
        .pipe(uglify())
        .pipe(rename({
            extname: ".min.js"
        }))
        .pipe(gulp.dest('dist/js'))
        .pipe(liveReload({
            auto: false
        }))
        .on('end', function () {
            gutil.log('Scripts concatenated and merged!');
        });
    done();
});

gulp.task('concat-minify-css', function (done) {
    var sassStream = gulp.src('src/scss/main.scss')
        .pipe(sass({
            errLogToConsole: true
        }));

    var cssStream = gulp.src([
        "bower_components/flexboxgrid/dist/flexboxgrid.css",
        "bower_components/wow/css/libs/animate.css"
    ]);

    var mergedStream = merge(sassStream, cssStream)
        .pipe(concat('build.min.css'))
        .pipe(minify({
            keepBreaks: true
        }))
        .pipe(gulp.dest('dist/css'))
        .on('end', function () {
            gutil.log('Styles concatenated and merged!');
        });

    done();

    return mergedStream;
});

gulp.task('watch', function (done) {
    gulp.watch('./src/scss/**/*.scss', gulp.series('concat-minify-css'));
    gulp.watch('./assets/js/*.js', gulp.series('concat-minify-js'));
    done();
});

gulp.task('default', gulp.series('concat-minify-css',
    gulp.parallel('concat-minify-js', 'watch')
));<|endoftext|>


<commit_before>import Em from 'ember';

export default Em.Route.extend({
  beforeModel() {
    return this.get("session").fetch().catch((error) => {
      Em.Logger.error('User not authenticated. Redirecting to sign in. Error:', error);
      this.transitionTo('signin');
    });
  },

  actions: {
    signOut() {
      this.get("session").close();
    }
  }
});
<commit_msg>Redirect any from index to notes route.<commit_after>import Ember from 'ember';

const {
  Logger,
  run
} = Ember;

export default Ember.Route.extend({
  beforeModel() {
    return this.get("session").fetch().catch((error) => {
      Logger.error('User not authenticated. Redirecting to sign in. Error:', error);
      this.transitionTo('signin');
    });
  },

  redirect() {
    run.next(this, () => {
      const appController = this.controllerFor('application');
      if (appController.get('currentPath') === 'index') {
        this.transitionTo('notes');
      }
    });
  },

  actions: {
    signOut() {
      this.get("session").close();
    }
  }
});
<|endoftext|>


<commit_before>

<commit_msg>add some java script for updating collection status table content<commit_after>

<|endoftext|>


<commit_before>var log = require('./utils/log');
var chalk = require('chalk');

var url = require('url');
var path = require('path');
var express = require('express');

function Server(OJ, ip, port) {
  var app = express();

  // Run OJ once to ensure clean first build
  OJ.run();

  var requestHandler = function(request, response, next) {
    var path = url.parse(request.url);

    // Use index.html if no path was supplied
    if(path.href == '/') {
      path = '/index.html';
    }

    // Remove the slash
    var path = path.pathname.substring(1);

    var requestPaths = [path];

    // Run OJ for the requested file
    OJ.run(requestPaths, function() {
      next();
    });
  };

  app.configure(function(){
    app.use(requestHandler);
    app.use(express.static(path.resolve(OJ.buildPath)));
  });

  app.listen(port, ip, function() {
    log('http server listening on: ' + ip + ':' + port);
  });
}

module.exports = Server;<commit_msg>Fix server URL parsing for /<commit_after>var log = require('./utils/log');
var chalk = require('chalk');

var url = require('url');
var path = require('path');
var express = require('express');

function Server(OJ, ip, port) {
  var app = express();

  // Run OJ once to ensure clean first build
  OJ.run();

  var requestHandler = function(request, response, next) {
    var path = url.parse(request.url);

    // Use index.html if no path was supplied
    if(path.href == '/') {
      path = url.parse('/index.html');
    }

    // Remove the slash
    path = path.pathname.substring(1);

    var requestPaths = [path];

    // Run OJ for the requested file
    OJ.run(requestPaths, function() {
      next();
    });
  };

  app.configure(function(){
    app.use(requestHandler);
    app.use(express.static(path.resolve(OJ.buildPath)));
  });

  app.listen(port, ip, function() {
    log('http server listening on: ' + ip + ':' + port);
  });
}

module.exports = Server;<|endoftext|>


<commit_before>var Paddle = function(game) {
  this.game = game;
  this.size = { x: 120, y: 15 };
  this.gameSize = {x: this.game.size.x, y: this.game.size.y}
  this.position = { x: this.game.size.x/2-60, y: this.game.size.y-15 };
  this.keyboarder = new Keyboarder();
}

Paddle.prototype = {

  draw: function(canvas) {
    canvas.beginPath();
    canvas.rect(this.position.x, this.position.y, this.size.x, this.size.y )
    canvas.fillStyle = "#D03ACD";
    canvas.fill();
    canvas.closePath();
  },

  move: function() {
    var paddle_move_speed = 12

    if (this.keyboarder.isDown(this.keyboarder.KEYS.LEFT) && (this.position.x > 0)) {
      this.position.x -= paddle_move_speed;
    } else if (this.keyboarder.isDown(this.keyboarder.KEYS.RIGHT) && (this.position.x < this.gameSize.x-this.size.x)) {
      this.position.x += paddle_move_speed;
    }
  }
}

var Keyboarder = function() {
  var keyState = {};
  document.addEventListener('keydown', function(e) {
    keyState[e.keyCode] = true;
  });

  document.addEventListener('keyup', function(e) {
    keyState[e.keyCode] = false;
  });

  this.isDown = function(keyCode) {
    return keyState[keyCode] === true;
  };

  this.KEYS = { LEFT: 37, RIGHT: 39 };
};

module.exports = Paddle;<commit_msg>Made paddle big Had to because it was impossible to hit all angels<commit_after>var Paddle = function(game) {
  this.game = game;
  this.size = { x: 150, y: 15 };
  this.gameSize = {x: this.game.size.x, y: this.game.size.y}
  this.position = { x: this.game.size.x/2-60, y: this.game.size.y-15 };
  this.keyboarder = new Keyboarder();
}

Paddle.prototype = {

  draw: function(canvas) {
    canvas.beginPath();
    canvas.rect(this.position.x, this.position.y, this.size.x, this.size.y )
    canvas.fillStyle = "#D03ACD";
    canvas.fill();
    canvas.closePath();
  },

  move: function() {
    var paddle_move_speed = 12

    if (this.keyboarder.isDown(this.keyboarder.KEYS.LEFT) && (this.position.x > 0)) {
      this.position.x -= paddle_move_speed;
    } else if (this.keyboarder.isDown(this.keyboarder.KEYS.RIGHT) && (this.position.x < this.gameSize.x-this.size.x)) {
      this.position.x += paddle_move_speed;
    }
  }
}

var Keyboarder = function() {
  var keyState = {};
  document.addEventListener('keydown', function(e) {
    keyState[e.keyCode] = true;
  });

  document.addEventListener('keyup', function(e) {
    keyState[e.keyCode] = false;
  });

  this.isDown = function(keyCode) {
    return keyState[keyCode] === true;
  };

  this.KEYS = { LEFT: 37, RIGHT: 39 };
};

module.exports = Paddle;<|endoftext|>


<commit_before>/*
Copyright 2016 First People's Cultural Council

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import _ from 'underscore';
import StringHelpers from 'common/StringHelpers';

import Nuxeo from 'nuxeo';

import BaseOperations from 'operations/BaseOperations';
import IntlService from "views/services/intl";

const TIMEOUT = 60000;

export default class DirectoryOperations extends BaseOperations {

    /**
     * Gets one or more documents based on a path or id.
     * Allows for additional complex queries to be executed.
     */
    static getDocuments(path = "", type = "Document", queryAppend = " ORDER BY dc:title", headers = null, params = null) {

        let defaultParams = {};
        let defaultHeaders = {};

        params = Object.assign(defaultParams, params);
        headers = Object.assign(defaultHeaders, headers);

        let properties = this.properties;

        // Replace Percent Sign
        queryAppend = queryAppend.replace(/%/g, "%25");

        let requestBody;

        // Switch between direct REST access and controlled mode
        if (path.indexOf('/api') === 0) {
            // NOTE: Do not escape single quotes in this mode
            requestBody = path.replace('/api/v1', '');
        } else {

            let where = 'ecm:path STARTSWITH \'' + StringHelpers.clean(path) + '\'';

            if (StringHelpers.isUUID(path)) {
                where = 'ecm:parentId = \'' + StringHelpers.clean(path) + '\'';
            }

            requestBody = '/query?query=SELECT * FROM ' + type + ' WHERE ' + where + ' AND ecm:currentLifeCycleState <> \'deleted\'' + queryAppend;
        }

        return new Promise(
            function (resolve, reject) {
                properties.client.request(
                    requestBody,
                    params
                )
                    .get(headers)
                    .then((docs) => {
                        resolve(docs);
                    }).catch((error) => {

                    if (error.hasOwnProperty('response')) {
                        error.response.json().then(
                            (jsonError) => {
                                reject(StringHelpers.extractErrorMessage(jsonError));
                            }
                        );
                    } else {
                        return reject(error || IntlService.instance.translate({
                            key: 'operations.could_not_access_server',
                            default: 'Could not access server',
                            case: 'first'
                        }));
                    }
                });

                setTimeout(function () {
                    reject('Server timeout while attempting to get documents.');
                }, TIMEOUT);
            });
    }

    static getDocumentsViaPageProvider(page_provider = "", type = "Document", queryAppend = "", headers = null, params = null) {

        let defaultParams = {};
        let defaultHeaders = {};

        params = Object.assign(defaultParams, params);
        headers = Object.assign(defaultHeaders, headers);

        let properties = this.properties;

        return new Promise(
            function (resolve, reject) {
                properties.client.request(
                    '/query/' + page_provider + '?' + queryAppend,
                    params
                )
                    .get({headers: headers})
                    .then((docs) => {
                        resolve(docs);
                    }).catch((error) => {
                    reject(IntlService.instance.translate({
                        key: 'operations.could_not_access_server',
                        default: 'Could not access server',
                        case: 'first'
                    }));
                });
            });
    }

    static getDirectory(name = "", headers = {}, params = {}) {

        let properties = this.properties;

        return new Promise(
            function (resolve, reject) {
                properties.client
                    .directory(name)
                    .fetchAll()
                    .then((directory) => {
                        resolve(directory);
                    }).catch((error) => {
                    reject(IntlService.instance.translate({
                        key: 'operations.could_not_retrieve_directory',
                        default: 'Could not retrieve directory',
                        case: 'first'
                    }));
                });
            });
    }

    /**
     * Get all documents of a certain type based on a path
     * These documents are expected to contain other entries
     * E.g. FVFamily, FVLanguage, FVDialect
     */
    getDocumentsByPath(path = "", headers = null, params = null) {
        // Expose fields to promise
        let client = this.client;
        let selectDefault = this.selectDefault;
        let domain = this.properties.domain;

        path = StringHelpers.clean(path);

        // Initialize and empty document list from type
        let documentList = new this.directoryTypePlural(null);

        return new Promise(
            // The resolver function is called with the ability to resolve or
            // reject the promise
            function (resolve, reject) {

                let defaultParams = {
                    query:
                    "SELECT * FROM " + documentList.model.prototype.entityTypeName + " WHERE (ecm:path STARTSWITH '/" + domain + path + "' AND " + selectDefault + ") ORDER BY dc:title"
                };

                let defaultHeaders = {};

                params = Object.assign(defaultParams, params);
                headers = Object.assign(defaultHeaders, headers);

                client.operation('Document.Query')
                    .params(params)
                    .execute(headers).then((response) => {

                    if (response.entries && response.entries.length > 0) {

                        documentList.add(response.entries);
                        documentList.totalResultSize = response.totalSize;

                        resolve(documentList);
                    } else {
                        reject(IntlService.instance.translate({
                            key: 'operations.no_found',
                            default: 'No ' + documentList.model.prototype.entityTypeName + ' found',
                            params: [documentList.model.prototype.entityTypeName],
                            case: 'first',
                            append: '!'
                        }));
                    }
                }).catch((error) => {
                    throw error
                });
            });
    }

    // Unused methods below (needs refactoring or removing soon)
    getSubjects(client) {
        return new Promise(
            function (resolve, reject) {

                client.request('directory/subtopic')
                    .get(function (error, data) {
                        if (error) {
                            // something went wrong
                            throw error;
                        }

                        if (data.entries.length > 0) {
                            //entry.properties.label
                            var subtopics = _.object(_.map(data.entries, function (entry) {
                                return [entry.properties.id, entry.properties.id];
                            }));
                            resolve(subtopics);
                        } else {
                            reject(IntlService.instance.translate({
                                key: 'operations.workspace_not_found',
                                default: 'Workspace not found',
                                case: 'first'
                            }));
                        }

                    });
            });
    }

    getPartsOfSpeech(client) {
        return new Promise(
            function (resolve, reject) {

                client.request('directory/parts_speech')
                    .get(function (error, data) {
                        if (error) {
                            // something went wrong
                            throw error;
                        }

                        if (data.entries.length > 0) {
                            //entry.properties.label
                            var parts_speech = _.object(_.map(data.entries, function (entry) {
                                return [entry.properties.id, entry.properties.id];
                            }));
                            resolve(parts_speech);
                        } else {
                            reject(IntlService.instance.translate({
                                key: 'operations.workspace_not_found',
                                default: 'Workspace not found',
                                case: 'first'
                            }));
                        }

                    });

            });
    }

    /*getWordsByLangauge (client, language) {
      return new Promise(
          // The resolver function is called with the ability to resolve or
          // reject the promise
          function(resolve, reject) {

            language = StringHelpers.clean(StringHelpers);

            client.operation('Document.Query')
              .params({
                query: "SELECT * FROM Document WHERE (dc:title = '" + language + "' AND ecm:primaryType = 'Workspace' AND ecm:currentLifeCycleState <> 'deleted'))"
              })
            .execute(function(error, response) {
              if (error) {
                throw error;
              }
              // Create a Workspace Document based on returned data

              if (response.entries.length > 0) {
                var workspaceID = response.entries[0].uid;

                client.operation('Document.Query')
                  .params({
                    query: "SELECT * FROM Document WHERE (ecm:parentId = '" + workspaceID + "' AND ecm:primaryType = 'Word' AND ecm:currentLifeCycleState <> 'deleted')"
                  })
                .execute(function(error, response) {

                      // Handle error
                  if (error) {
                    throw error;
                  }

                  var nuxeoListDocs = new Words(response.entries);
                  resolve(nuxeoListDocs.toJSON());

                });
              } else {
                reject('Workspace not found');
              }

            });
      });
    }*/
}<commit_msg>Added getDocuments which performs API requests directly<commit_after>/*
Copyright 2016 First People's Cultural Council

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import _ from 'underscore';
import StringHelpers from 'common/StringHelpers';

import request from 'request';

import Nuxeo from 'nuxeo';

import BaseOperations from 'operations/BaseOperations';
import IntlService from "views/services/intl";

const TIMEOUT = 60000;

export default class DirectoryOperations extends BaseOperations {

    /**
     * Gets one or more documents based on a path or id.
     * Allows for additional complex queries to be executed.
     */
    static getDocumentsViaAPI(path = "", headers) {

        let requestBody;

        return new Promise(
            function (resolve, reject) {

                let options = {
                    url: path,
                    headers: headers
                };

                request(options, function (error, response, body) {

                    if (error || response.statusCode != 200) {
                        if (error.hasOwnProperty('response')) {
                            error.response.json().then(
                                (jsonError) => {
                                    reject(StringHelpers.extractErrorMessage(jsonError));
                                }
                            );
                        } else {
                            let errorMessage = "Attempting to retrieve " + path;

                            if (error) {
                                errorMessage += " has resulted in ";
                            } else {
                                errorMessage += " - ";
                            }

                            return reject(errorMessage + (error || IntlService.instance.translate({
                                key: 'operations.could_not_access_server',
                                default: 'Could not access server',
                                case: 'first'
                            })));
                        }
                    } else {
                        resolve(JSON.parse(body));
                    }

                    reject('An unknown error has occured.');
                });

                setTimeout(function () {
                    reject('Server timeout while attempting to get documents.');
                }, TIMEOUT);
            });
    }

    /**
     * Gets one or more documents based on a path or id.
     * Allows for additional complex queries to be executed.
     */
    static getDocuments(path = "", type = "Document", queryAppend = " ORDER BY dc:title", headers = null, params = null) {

        let defaultParams = {};
        let defaultHeaders = {};

        params = Object.assign(defaultParams, params);
        headers = Object.assign(defaultHeaders, headers);

        let properties = this.properties;

        // Replace Percent Sign
        queryAppend = queryAppend.replace(/%/g, "%25");

        let requestBody;

        // Switch between direct REST access and controlled mode
        if (path.indexOf('/api') === 0) {
            // NOTE: Do not escape single quotes in this mode
            requestBody = path.replace('/api/v1', '');
        } else {

            let where = 'ecm:path STARTSWITH \'' + StringHelpers.clean(path) + '\'';

            if (StringHelpers.isUUID(path)) {
                where = 'ecm:parentId = \'' + StringHelpers.clean(path) + '\'';
            }

            requestBody = '/query?query=SELECT * FROM ' + type + ' WHERE ' + where + ' AND ecm:currentLifeCycleState <> \'deleted\'' + queryAppend;
        }

        return new Promise(
            function (resolve, reject) {
                properties.client.request(
                    requestBody,
                    params
                )
                    .get(headers)
                    .then((docs) => {
                        resolve(docs);
                    }).catch((error) => {

                    if (error.hasOwnProperty('response')) {
                        error.response.json().then(
                            (jsonError) => {
                                reject(StringHelpers.extractErrorMessage(jsonError));
                            }
                        );
                    } else {
                        return reject(error || IntlService.instance.translate({
                            key: 'operations.could_not_access_server',
                            default: 'Could not access server',
                            case: 'first'
                        }));
                    }
                });

                setTimeout(function () {
                    reject('Server timeout while attempting to get documents.');
                }, TIMEOUT);
            });
    }

    static getDocumentsViaPageProvider(page_provider = "", type = "Document", queryAppend = "", headers = null, params = null) {

        let defaultParams = {};
        let defaultHeaders = {};

        params = Object.assign(defaultParams, params);
        headers = Object.assign(defaultHeaders, headers);

        let properties = this.properties;

        return new Promise(
            function (resolve, reject) {
                properties.client.request(
                    '/query/' + page_provider + '?' + queryAppend,
                    params
                )
                    .get({headers: headers})
                    .then((docs) => {
                        resolve(docs);
                    }).catch((error) => {
                    reject(IntlService.instance.translate({
                        key: 'operations.could_not_access_server',
                        default: 'Could not access server',
                        case: 'first'
                    }));
                });
            });
    }

    static getDirectory(name = "", headers = {}, params = {}) {

        let properties = this.properties;

        return new Promise(
            function (resolve, reject) {
                properties.client
                    .directory(name)
                    .fetchAll()
                    .then((directory) => {
                        resolve(directory);
                    }).catch((error) => {
                    reject(IntlService.instance.translate({
                        key: 'operations.could_not_retrieve_directory',
                        default: 'Could not retrieve directory',
                        case: 'first'
                    }));
                });
            });
    }

    /**
     * Get all documents of a certain type based on a path
     * These documents are expected to contain other entries
     * E.g. FVFamily, FVLanguage, FVDialect
     */
    getDocumentsByPath(path = "", headers = null, params = null) {
        // Expose fields to promise
        let client = this.client;
        let selectDefault = this.selectDefault;
        let domain = this.properties.domain;

        path = StringHelpers.clean(path);

        // Initialize and empty document list from type
        let documentList = new this.directoryTypePlural(null);

        return new Promise(
            // The resolver function is called with the ability to resolve or
            // reject the promise
            function (resolve, reject) {

                let defaultParams = {
                    query:
                    "SELECT * FROM " + documentList.model.prototype.entityTypeName + " WHERE (ecm:path STARTSWITH '/" + domain + path + "' AND " + selectDefault + ") ORDER BY dc:title"
                };

                let defaultHeaders = {};

                params = Object.assign(defaultParams, params);
                headers = Object.assign(defaultHeaders, headers);

                client.operation('Document.Query')
                    .params(params)
                    .execute(headers).then((response) => {

                    if (response.entries && response.entries.length > 0) {

                        documentList.add(response.entries);
                        documentList.totalResultSize = response.totalSize;

                        resolve(documentList);
                    } else {
                        reject(IntlService.instance.translate({
                            key: 'operations.no_found',
                            default: 'No ' + documentList.model.prototype.entityTypeName + ' found',
                            params: [documentList.model.prototype.entityTypeName],
                            case: 'first',
                            append: '!'
                        }));
                    }
                }).catch((error) => {
                    throw error
                });
            });
    }

    // Unused methods below (needs refactoring or removing soon)
    getSubjects(client) {
        return new Promise(
            function (resolve, reject) {

                client.request('directory/subtopic')
                    .get(function (error, data) {
                        if (error) {
                            // something went wrong
                            throw error;
                        }

                        if (data.entries.length > 0) {
                            //entry.properties.label
                            var subtopics = _.object(_.map(data.entries, function (entry) {
                                return [entry.properties.id, entry.properties.id];
                            }));
                            resolve(subtopics);
                        } else {
                            reject(IntlService.instance.translate({
                                key: 'operations.workspace_not_found',
                                default: 'Workspace not found',
                                case: 'first'
                            }));
                        }

                    });
            });
    }

    getPartsOfSpeech(client) {
        return new Promise(
            function (resolve, reject) {

                client.request('directory/parts_speech')
                    .get(function (error, data) {
                        if (error) {
                            // something went wrong
                            throw error;
                        }

                        if (data.entries.length > 0) {
                            //entry.properties.label
                            var parts_speech = _.object(_.map(data.entries, function (entry) {
                                return [entry.properties.id, entry.properties.id];
                            }));
                            resolve(parts_speech);
                        } else {
                            reject(IntlService.instance.translate({
                                key: 'operations.workspace_not_found',
                                default: 'Workspace not found',
                                case: 'first'
                            }));
                        }

                    });

            });
    }

    /*getWordsByLangauge (client, language) {
      return new Promise(
          // The resolver function is called with the ability to resolve or
          // reject the promise
          function(resolve, reject) {

            language = StringHelpers.clean(StringHelpers);

            client.operation('Document.Query')
              .params({
                query: "SELECT * FROM Document WHERE (dc:title = '" + language + "' AND ecm:primaryType = 'Workspace' AND ecm:currentLifeCycleState <> 'deleted'))"
              })
            .execute(function(error, response) {
              if (error) {
                throw error;
              }
              // Create a Workspace Document based on returned data

              if (response.entries.length > 0) {
                var workspaceID = response.entries[0].uid;

                client.operation('Document.Query')
                  .params({
                    query: "SELECT * FROM Document WHERE (ecm:parentId = '" + workspaceID + "' AND ecm:primaryType = 'Word' AND ecm:currentLifeCycleState <> 'deleted')"
                  })
                .execute(function(error, response) {

                      // Handle error
                  if (error) {
                    throw error;
                  }

                  var nuxeoListDocs = new Words(response.entries);
                  resolve(nuxeoListDocs.toJSON());

                });
              } else {
                reject('Workspace not found');
              }

            });
      });
    }*/
}<|endoftext|>


<commit_before>// Everything starts better with coffee
var coffee = require("coffee-script");
var express = require("express");

var nconf = require("nconf").use("memory")
  .argv()
  .env()
  .file({file: "config.json"})
  .defaults({
    "PORT": 8080
  });

if (!nconf.get("host")) {
  console.error("The host option is required for Plunker to start");
} else {

  var host = nconf.get("host");

  // Configure global paths
  if (nconf.get("nosubdomains")) {
    nconf.set("url:www", "http://" + host);
    nconf.set("url:raw", "http://" + host + "/raw");
    nconf.set("url:run", "http://" + host + "/run");
    nconf.set("url:api", "http://" + host + "/api");
  } else {
    nconf.set("url:www", "http://" + host);
    nconf.set("url:raw", "http://raw." + host);
    nconf.set("url:run", "http://run." + host);
    nconf.set("url:api", "http://api." + host);
  }

  // Create and start the parent server
  express.createServer()
    //.use(express.logger())
    .use(require("express-subdomains").use("raw").use("api").use("run").use("embed").middleware)
    .use("/api", require("./servers/api"))
    .use("/raw", require("./servers/raw"))
    .use("/run", require("./servers/run"))
    .use("/embed", require("./servers/embed"))
    .use(require("./servers/www"))
    .listen(nconf.get("PORT"));

  console.log("Started plunker in", nconf.get("NODE_ENV") || "development", "at", nconf.get("host"), "on port", nconf.get("PORT"), "using subdomains:", !nconf.get("nosubdomains"));
}
<commit_msg>Listen on correct host<commit_after>// Everything starts better with coffee
var coffee = require("coffee-script");
var express = require("express");

var nconf = require("nconf").use("memory")
  .argv()
  .env()
  .file({file: "config.json"})
  .defaults({
    "PORT": 8080
  });

if (!nconf.get("host")) {
  console.error("The host option is required for Plunker to start");
} else {

  var host = nconf.get("host") + ":" + nconf.get("PORT");

  // Configure global paths
  if (nconf.get("nosubdomains")) {
    nconf.set("url:www", "http://" + host);
    nconf.set("url:raw", "http://" + host + "/raw");
    nconf.set("url:run", "http://" + host + "/run");
    nconf.set("url:api", "http://" + host + "/api");
  } else {
    nconf.set("url:www", "http://" + host);
    nconf.set("url:raw", "http://raw." + host);
    nconf.set("url:run", "http://run." + host);
    nconf.set("url:api", "http://api." + host);
  }

  // Create and start the parent server
  express.createServer()
    //.use(express.logger())
    .use(require("express-subdomains").use("raw").use("api").use("run").use("embed").middleware)
    .use("/api", require("./servers/api"))
    .use("/raw", require("./servers/raw"))
    .use("/run", require("./servers/run"))
    .use("/embed", require("./servers/embed"))
    .use(require("./servers/www"))
    .listen(nconf.get("PORT"));

  console.log("Started plunker in", nconf.get("NODE_ENV") || "development", "at", nconf.get("host"), "on port", nconf.get("PORT"), "using subdomains:", !nconf.get("nosubdomains"));
}
<|endoftext|>


<commit_before>import manifest from '../../../package.json';
import filePaths from '../utils/file-paths';
import platform from '../utils/platform';
import prefs from '../utils/prefs';
import {debounce} from 'lodash';
import shell from 'shell';

import BrowserWindow from 'browser-window';
import EventEmitter from 'events';

class MainWindowManager extends EventEmitter {

  constructor(manifest, options) {
    super();

    this.manifest = manifest;
    this.options = options;

    this.forceClose = false;
    this.updateInProgress = false;
    this.startHidden = options.osStartup && prefs.get('launch-startup-hidden');
  }

  setTrayManager(trayManager) {
    this.trayManager = trayManager;
  }

  createWindow() {
    log('creating main window');

    const bounds = prefs.get('window-bounds');
    const defaultOptions = {
      title: this.manifest.productName,
      backgroundColor: '#f2f2f2',
      useContentSize: true,
      minWidth: 355,
      minHeight: 355,
      show: false
    };

    const options = Object.assign(defaultOptions, bounds);
    this.window = new BrowserWindow(options);
  }

  initWindow() {
    // Replace the default user agent
    const cleanUA = this.getCleanUserAgent();
    this.window.webContents.setUserAgent(cleanUA);

    // Bind webContents events to local methods
    this.window.webContents.on('new-window', ::this.onNewWindow);
    this.window.webContents.on('dom-ready', ::this.onDomReady);

    // Bind events to local methods
    this.window.on('enter-full-screen', ::this.onEnterFullScreen);
    this.window.on('leave-full-screen', ::this.onLeaveFullScreen);
    this.window.on('closed', ::this.onClosed);
    this.window.on('close', ::this.onClose);
    this.window.on('focus', ::this.onFocus);
    this.window.on('blur', ::this.onBlur);

    // Save the bounds on resize or move
    const saveBounds = debounce(::this.saveBounds, 500);
    this.window.on('resize', saveBounds);
    this.window.on('move', saveBounds);

    // Restore full screen state
    if (!platform.isLinux) {
      const isFullScreen = prefs.get('window-full-screen');
      this.window.setFullScreen(isFullScreen);
      // doesn't work correctly on Linux: setFullScreen makes
      // the app full screen even if it's called with false
    }

    // Finally, load the app html
    this.window.loadURL(filePaths.getHtmlFile('app.html'));
  }

  /**
   * Called when the 'new-window' event is emitted.
   */
  onNewWindow(event, url) {
    // Open urls in an external browser
    if (prefs.get('links-in-browser')) {
      log('opening url externally', url);
      event.preventDefault();
      shell.openExternal(url);
    } else {
      log('opening url in-app', url);
    }
  }

  /**
   * Called when the 'dom-ready' event is emitted.
   */
  onDomReady() {
    // Show the window
    log('onDomReady');
    if (!this.startHidden && !this.window.isVisible()) {
      this.window.show();
    }
  }

  /**
   * Called when the 'enter-full-screen' event is emitted.
   */
  onEnterFullScreen() {
    if (platform.isLinux) {
      return; // this event isn't triggered correctly on linux
    }
    // Save in prefs
    prefs.set('window-full-screen', true);
  }

  /**
   * Called when the 'leave-full-screen' event is emitted.
   */
  onLeaveFullScreen() {
    if (platform.isLinux) {
      return; // this event isn't triggered correctly on linux
    }
    // Save in prefs
    prefs.set('window-full-screen', false);
  }

  /**
   * Called when the 'closed' event is emitted.
   * Remove the internal reference to the window.
   */
  onClosed() {
    log('onClosed');
    this.window = null;
    this.emit('closed');
  }

  /**
   * Called when the 'close' event is emitted.
   */
  onClose(event) {
    // Just hide the window unless...
    log('onClose');

    // The app is being updated
    if (this.updateInProgress) {
      return;
    }

    // Or the window is force closed (app quitting)
    if (platform.isDarwin && !this.forceClose) {
      event.preventDefault();
      this.window.hide();
    }

    // Or the app is not running in the tray.
    if (platform.isWin && !this.forceClose && prefs.get('show-tray')) {
      event.preventDefault();
      this.window.hide();

      // Inform the user the app is still running
      if (!prefs.get('quit-behaviour-taught')) {
        this.trayManager.tray.displayBalloon({
          title: manifest.productName,
          content: manifest.productName + ' will keep running in the tray until you quit it.'
        });
        prefs.set('quit-behaviour-taught', true);
      }
    }
  }

  /**
   * Called when the 'focus' event is emitted.
   */
  onFocus() {
    // Also focus the webview
    log('onFocus');
    this.window.webContents.send('call-webview-method', 'focus');
  }

  /**
   * Called when the 'blur' event is emitted.
   */
  onBlur() {
    // Also blur the webview
    log('onBlur');
    this.window.webContents.send('call-webview-method', 'blur');
  }

  /**
   * Persist the current window's state.
   */
  saveBounds() {
    if (this.window.isFullScreen()) {
      return;
    }

    log('saving bounds');
    const bounds = this.window.getBounds();
    prefs.set('window-bounds', bounds);
  }

  /**
   * Remove identifiable information (e.g. app name) from the UA string.
   */
  getCleanUserAgent() {
    return this.window.webContents.getUserAgent()
      .replace(new RegExp(this.manifest.productName + '/[\\S]*', 'g'), '')
      .replace(new RegExp('Electron/[\\S]*', 'g'), '')
      .replace(new RegExp('\\s+', 'g'), '');
  }

  /**
   * Show and focus or create the main window.
   */
  showOrCreate() {
    if (this.window) {
      this.window.show();
    } else {
      this.createWindow();
      this.initWindow();
    }
  }

}

export default MainWindowManager;
<commit_msg>Fix window closing even with tray icon (Linux)<commit_after>import manifest from '../../../package.json';
import filePaths from '../utils/file-paths';
import platform from '../utils/platform';
import prefs from '../utils/prefs';
import {debounce} from 'lodash';
import shell from 'shell';

import BrowserWindow from 'browser-window';
import EventEmitter from 'events';

class MainWindowManager extends EventEmitter {

  constructor(manifest, options) {
    super();

    this.manifest = manifest;
    this.options = options;

    this.forceClose = false;
    this.updateInProgress = false;
    this.startHidden = options.osStartup && prefs.get('launch-startup-hidden');
  }

  setTrayManager(trayManager) {
    this.trayManager = trayManager;
  }

  createWindow() {
    log('creating main window');

    const bounds = prefs.get('window-bounds');
    const defaultOptions = {
      title: this.manifest.productName,
      backgroundColor: '#f2f2f2',
      useContentSize: true,
      minWidth: 355,
      minHeight: 355,
      show: false
    };

    const options = Object.assign(defaultOptions, bounds);
    this.window = new BrowserWindow(options);
  }

  initWindow() {
    // Replace the default user agent
    const cleanUA = this.getCleanUserAgent();
    this.window.webContents.setUserAgent(cleanUA);

    // Bind webContents events to local methods
    this.window.webContents.on('new-window', ::this.onNewWindow);
    this.window.webContents.on('dom-ready', ::this.onDomReady);

    // Bind events to local methods
    this.window.on('enter-full-screen', ::this.onEnterFullScreen);
    this.window.on('leave-full-screen', ::this.onLeaveFullScreen);
    this.window.on('closed', ::this.onClosed);
    this.window.on('close', ::this.onClose);
    this.window.on('focus', ::this.onFocus);
    this.window.on('blur', ::this.onBlur);

    // Save the bounds on resize or move
    const saveBounds = debounce(::this.saveBounds, 500);
    this.window.on('resize', saveBounds);
    this.window.on('move', saveBounds);

    // Restore full screen state
    if (!platform.isLinux) {
      const isFullScreen = prefs.get('window-full-screen');
      this.window.setFullScreen(isFullScreen);
      // doesn't work correctly on Linux: setFullScreen makes
      // the app full screen even if it's called with false
    }

    // Finally, load the app html
    this.window.loadURL(filePaths.getHtmlFile('app.html'));
  }

  /**
   * Called when the 'new-window' event is emitted.
   */
  onNewWindow(event, url) {
    // Open urls in an external browser
    if (prefs.get('links-in-browser')) {
      log('opening url externally', url);
      event.preventDefault();
      shell.openExternal(url);
    } else {
      log('opening url in-app', url);
    }
  }

  /**
   * Called when the 'dom-ready' event is emitted.
   */
  onDomReady() {
    // Show the window
    log('onDomReady');
    if (!this.startHidden && !this.window.isVisible()) {
      this.window.show();
    }
  }

  /**
   * Called when the 'enter-full-screen' event is emitted.
   */
  onEnterFullScreen() {
    if (platform.isLinux) {
      return; // this event isn't triggered correctly on linux
    }
    // Save in prefs
    prefs.set('window-full-screen', true);
  }

  /**
   * Called when the 'leave-full-screen' event is emitted.
   */
  onLeaveFullScreen() {
    if (platform.isLinux) {
      return; // this event isn't triggered correctly on linux
    }
    // Save in prefs
    prefs.set('window-full-screen', false);
  }

  /**
   * Called when the 'closed' event is emitted.
   * Remove the internal reference to the window.
   */
  onClosed() {
    log('onClosed');
    this.window = null;
    this.emit('closed');
  }

  /**
   * Called when the 'close' event is emitted.
   */
  onClose(event) {
    // Just hide the window unless...
    log('onClose');

    // The app is being updated
    if (this.updateInProgress) {
      return;
    }

    // Or the window is force closed (app quitting)
    if (platform.isDarwin && !this.forceClose) {
      event.preventDefault();
      this.window.hide();
    }

    // Or the app is not running in the tray.
    if (!this.forceClose && prefs.get('show-tray')) {
      event.preventDefault();
      this.window.hide();

      // Inform the user the app is still running
      if (platform.isWin && !prefs.get('quit-behaviour-taught')) {
        this.trayManager.tray.displayBalloon({
          title: manifest.productName,
          content: manifest.productName + ' will keep running in the tray until you quit it.'
        });
        prefs.set('quit-behaviour-taught', true);
      }
    }
  }

  /**
   * Called when the 'focus' event is emitted.
   */
  onFocus() {
    // Also focus the webview
    log('onFocus');
    this.window.webContents.send('call-webview-method', 'focus');
  }

  /**
   * Called when the 'blur' event is emitted.
   */
  onBlur() {
    // Also blur the webview
    log('onBlur');
    this.window.webContents.send('call-webview-method', 'blur');
  }

  /**
   * Persist the current window's state.
   */
  saveBounds() {
    if (this.window.isFullScreen()) {
      return;
    }

    log('saving bounds');
    const bounds = this.window.getBounds();
    prefs.set('window-bounds', bounds);
  }

  /**
   * Remove identifiable information (e.g. app name) from the UA string.
   */
  getCleanUserAgent() {
    return this.window.webContents.getUserAgent()
      .replace(new RegExp(this.manifest.productName + '/[\\S]*', 'g'), '')
      .replace(new RegExp('Electron/[\\S]*', 'g'), '')
      .replace(new RegExp('\\s+', 'g'), '');
  }

  /**
   * Show and focus or create the main window.
   */
  showOrCreate() {
    if (this.window) {
      this.window.show();
    } else {
      this.createWindow();
      this.initWindow();
    }
  }

}

export default MainWindowManager;
<|endoftext|>