<commit_before>describe("luga.data.region.Handlebars", function(){

	"use strict";

	let testRecords, loadedDs, testDiv, attributesDiv, configRegion, attributesRegion, testObserver;
	beforeEach(function(){

		jasmineFixtures.loadHTML("data/region/Handlebars/ladies.htm");

		testRecords = jasmineFixtures.read("data/ladies.json");
		loadedDs = new luga.data.DataSet({uuid: "testDs", records: testRecords});

		testDiv = document.createElement("div");
		testDiv.textContent = "Ciao Mamma";

		attributesDiv = document.createElement("div");
		attributesDiv.setAttribute("data-lugaregion", "true");
		attributesDiv.setAttribute("data-lugaregion-datasource-uuid", "testDs");
		attributesDiv.setAttribute("data-lugaregion-template-id", "ladiesTemplate");
		attributesDiv.textContent = "Test";

		configRegion = new luga.data.region.Handlebars({
			node: testDiv,
			ds: loadedDs,
			templateId: "ladiesTemplate"
		});
		attributesRegion = new luga.data.region.Handlebars({node: attributesDiv});

		testObserver = {
			onRegionRenderedHandler: function(){
			}
		};
		configRegion.addObserver(testObserver);
		spyOn(testObserver, "onRegionRenderedHandler");

	});

	afterEach(function(){
		luga.data.dataSourceRegistry = {};
	});

	it("Is the default region type", function(){
		expect(luga.data.region.Handlebars).toBeDefined();
		expect(luga.type(luga.data.region.Handlebars)).toEqual("function");
	});

	it("Implements the luga.data.region.Base abstract class", function(){
		expect(configRegion).toMatchDuckType(new luga.data.region.Base({node: testDiv, ds: loadedDs}));
	});

	describe("Its constructor options are the same as luga.data.region.Base and may also contains:", function(){

		describe("options.templateId either", function(){

			it("Retrieves the value from the node's data-lugaregion-template-id custom attribute", function(){
				expect(attributesRegion.config.templateId).toEqual("ladiesTemplate");
			});
			it("Uses the value specified inside the option argument", function(){
				expect(configRegion.config.templateId).toEqual("ladiesTemplate");
			});
			it("Throws an exception if unable to find an HTML element matching the given id", function(){
				expect(function(){
					new luga.data.region.Handlebars({
						node: testDiv,
						dsUuid: "testDs",
						templateId: "missing"
					});
				}).toThrow();
			});
			it("Default to null", function(){
				const testRegion = new luga.data.region.Handlebars({
					node: testDiv,
					dsUuid: "testDs"
				});
				expect(testRegion.config.templateId).toBeNull();
			});

		});

	});

	describe(".template stores the compiled Handlebars template", function(){

		describe("If options.templateId is null:", function(){
			it("Assumes the node's HTML contains the template", function(){
				spyOn(Handlebars, "compile");
				new luga.data.region.Handlebars({
					node: testDiv,
					dsUuid: "testDs"
				});
				expect(Handlebars.compile).toHaveBeenCalledWith(testDiv.innerHTML);
			});
		});

		describe("Else, assumes the HTML element matching options.templateId contains the template", function(){

			describe("If the HTML has no 'src' attribute", function(){

				it("Assumes the HTML element contains the template", function(){
					spyOn(Handlebars, "compile");
					new luga.data.region.Handlebars({
						node: testDiv,
						dsUuid: "testDs",
						templateId: "ladiesTemplate"
					});
					expect(Handlebars.compile).toHaveBeenCalledWith(document.getElementById("ladiesTemplate").innerHTML);
				});

			});
			describe("Else:", function(){

				it("Use XHR to fetch the external template", function(){

					spyOn(Handlebars, "compile").and.callThrough();
					jasmine.Ajax.install();
					jasmine.Ajax.stubRequest("mock.htm").andReturn({
						contentType: "text/html",
						status: 200,
						responseText: "stub Handlebars"
					});

					new luga.data.region.Handlebars({
						node: testDiv,
						dsUuid: "testDs",
						templateId: "mockTemplate"
					});

					expect(Handlebars.compile).toHaveBeenCalledWith("stub Handlebars");
				});

				it("Throw an error and does not compile/render if the external template is missing", function(){

					spyOn(Handlebars, "compile");
					jasmine.Ajax.install();
					jasmine.Ajax.stubRequest("missing.htm").andReturn({
						status: 404
					});

					expect(function(){
						new luga.data.region.Handlebars({
							node: testDiv,
							dsUuid: "testDs",
							templateId: "missingTemplate"
						});
					}).toThrow();
					expect(Handlebars.compile).not.toHaveBeenCalled();
				});

				afterEach(function(){
					jasmine.Ajax.uninstall();
				});

			});

		});

	});

	describe(".generateHtml()", function(){
		it("Pass the dataSource's context to the compiled template", function(){
			spyOn(configRegion, "template");
			configRegion.generateHtml();
			expect(configRegion.template).toHaveBeenCalledWith(configRegion.dataSource.getContext());
		});
	});

	describe(".render()", function(){

		let testRegion;
		beforeEach(function(){
			testRegion = new luga.data.region.Handlebars({
				node: testDiv,
				dsUuid: "testDs",
				templateId: "ladiesTemplate"
			});
		});

		describe("First:", function(){
			it("Calls .generateHtml()", function(){
				spyOn(testRegion, "generateHtml").and.callThrough();
				testRegion.render();
				expect(testRegion.generateHtml).toHaveBeenCalled();
			});
		});

		describe("Then:", function(){
			it("Injects the generated HTML inside the node", function(){
				const newHtml = testRegion.generateHtml();
				testRegion.render();
				expect(testRegion.config.node.innerHTML).toEqual(newHtml);
			});
		});

		describe("Then:", function(){
			it("Calls .applyTraits()", function(){
				spyOn(testRegion, "applyTraits").and.callThrough();
				testRegion.render();
				expect(testRegion.applyTraits).toHaveBeenCalled();
			});
		});

		describe("Finally:", function(){
			it("Triggers a 'regionRendered' notification. Passing along the region's description", function(){
				configRegion.render();
				const desc = luga.data.region.utils.assembleRegionDescription(configRegion);
				expect(testObserver.onRegionRenderedHandler).toHaveBeenCalledWith(desc);
			});
		});

	});

});<commit_msg>Added test to formalize Handlebars dependancy<commit_after>describe("luga.data.region.Handlebars", function(){

	"use strict";

	let testRecords, loadedDs, testDiv, attributesDiv, configRegion, attributesRegion, testObserver;
	beforeEach(function(){

		jasmineFixtures.loadHTML("data/region/Handlebars/ladies.htm");

		testRecords = jasmineFixtures.read("data/ladies.json");
		loadedDs = new luga.data.DataSet({uuid: "testDs", records: testRecords});

		testDiv = document.createElement("div");
		testDiv.textContent = "Ciao Mamma";

		attributesDiv = document.createElement("div");
		attributesDiv.setAttribute("data-lugaregion", "true");
		attributesDiv.setAttribute("data-lugaregion-datasource-uuid", "testDs");
		attributesDiv.setAttribute("data-lugaregion-template-id", "ladiesTemplate");
		attributesDiv.textContent = "Test";

		configRegion = new luga.data.region.Handlebars({
			node: testDiv,
			ds: loadedDs,
			templateId: "ladiesTemplate"
		});
		attributesRegion = new luga.data.region.Handlebars({node: attributesDiv});

		testObserver = {
			onRegionRenderedHandler: function(){
			}
		};
		configRegion.addObserver(testObserver);
		spyOn(testObserver, "onRegionRenderedHandler");

	});

	afterEach(function(){
		luga.data.dataSourceRegistry = {};
	});

	it("Requires Handlebars in order to work", function(){
		expect(Handlebars).toBeDefined();
	});

	it("Is the default region type", function(){
		expect(luga.data.region.Handlebars).toBeDefined();
		expect(luga.type(luga.data.region.Handlebars)).toEqual("function");
	});

	it("Implements the luga.data.region.Base abstract class", function(){
		expect(configRegion).toMatchDuckType(new luga.data.region.Base({node: testDiv, ds: loadedDs}));
	});

	describe("Its constructor options are the same as luga.data.region.Base and may also contains:", function(){

		describe("options.templateId either", function(){

			it("Retrieves the value from the node's data-lugaregion-template-id custom attribute", function(){
				expect(attributesRegion.config.templateId).toEqual("ladiesTemplate");
			});
			it("Uses the value specified inside the option argument", function(){
				expect(configRegion.config.templateId).toEqual("ladiesTemplate");
			});
			it("Throws an exception if unable to find an HTML element matching the given id", function(){
				expect(function(){
					new luga.data.region.Handlebars({
						node: testDiv,
						dsUuid: "testDs",
						templateId: "missing"
					});
				}).toThrow();
			});
			it("Default to null", function(){
				const testRegion = new luga.data.region.Handlebars({
					node: testDiv,
					dsUuid: "testDs"
				});
				expect(testRegion.config.templateId).toBeNull();
			});

		});

	});

	describe(".template stores the compiled Handlebars template", function(){

		describe("If options.templateId is null:", function(){
			it("Assumes the node's HTML contains the template", function(){
				spyOn(Handlebars, "compile");
				new luga.data.region.Handlebars({
					node: testDiv,
					dsUuid: "testDs"
				});
				expect(Handlebars.compile).toHaveBeenCalledWith(testDiv.innerHTML);
			});
		});

		describe("Else, assumes the HTML element matching options.templateId contains the template", function(){

			describe("If the HTML has no 'src' attribute", function(){

				it("Assumes the HTML element contains the template", function(){
					spyOn(Handlebars, "compile");
					new luga.data.region.Handlebars({
						node: testDiv,
						dsUuid: "testDs",
						templateId: "ladiesTemplate"
					});
					expect(Handlebars.compile).toHaveBeenCalledWith(document.getElementById("ladiesTemplate").innerHTML);
				});

			});
			describe("Else:", function(){

				it("Use XHR to fetch the external template", function(){

					spyOn(Handlebars, "compile").and.callThrough();
					jasmine.Ajax.install();
					jasmine.Ajax.stubRequest("mock.htm").andReturn({
						contentType: "text/html",
						status: 200,
						responseText: "stub Handlebars"
					});

					new luga.data.region.Handlebars({
						node: testDiv,
						dsUuid: "testDs",
						templateId: "mockTemplate"
					});

					expect(Handlebars.compile).toHaveBeenCalledWith("stub Handlebars");
				});

				it("Throw an error and does not compile/render if the external template is missing", function(){

					spyOn(Handlebars, "compile");
					jasmine.Ajax.install();
					jasmine.Ajax.stubRequest("missing.htm").andReturn({
						status: 404
					});

					expect(function(){
						new luga.data.region.Handlebars({
							node: testDiv,
							dsUuid: "testDs",
							templateId: "missingTemplate"
						});
					}).toThrow();
					expect(Handlebars.compile).not.toHaveBeenCalled();
				});

				afterEach(function(){
					jasmine.Ajax.uninstall();
				});

			});

		});

	});

	describe(".generateHtml()", function(){
		it("Pass the dataSource's context to the compiled template", function(){
			spyOn(configRegion, "template");
			configRegion.generateHtml();
			expect(configRegion.template).toHaveBeenCalledWith(configRegion.dataSource.getContext());
		});
	});

	describe(".render()", function(){

		let testRegion;
		beforeEach(function(){
			testRegion = new luga.data.region.Handlebars({
				node: testDiv,
				dsUuid: "testDs",
				templateId: "ladiesTemplate"
			});
		});

		describe("First:", function(){
			it("Calls .generateHtml()", function(){
				spyOn(testRegion, "generateHtml").and.callThrough();
				testRegion.render();
				expect(testRegion.generateHtml).toHaveBeenCalled();
			});
		});

		describe("Then:", function(){
			it("Injects the generated HTML inside the node", function(){
				const newHtml = testRegion.generateHtml();
				testRegion.render();
				expect(testRegion.config.node.innerHTML).toEqual(newHtml);
			});
		});

		describe("Then:", function(){
			it("Calls .applyTraits()", function(){
				spyOn(testRegion, "applyTraits").and.callThrough();
				testRegion.render();
				expect(testRegion.applyTraits).toHaveBeenCalled();
			});
		});

		describe("Finally:", function(){
			it("Triggers a 'regionRendered' notification. Passing along the region's description", function(){
				configRegion.render();
				const desc = luga.data.region.utils.assembleRegionDescription(configRegion);
				expect(testObserver.onRegionRenderedHandler).toHaveBeenCalledWith(desc);
			});
		});

	});

});<|endoftext|>


<commit_before>'use strict';

/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
	Schema = mongoose.Schema;

/**
 * Order Schema
 */
var OrderSchema = new Schema({
	store: {
		type: Object
	},
  order: {
    type: Object
  },
  user: {
    type: Object
  },
	created: {
		type: Date,
		default: Date.now
	}
});

mongoose.model('Order', OrderSchema);
<commit_msg>customer added in orders<commit_after>'use strict';

/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
	Schema = mongoose.Schema;

/**
 * Order Schema
 */
var OrderSchema = new Schema({
	store: {
		type: Object
	},
  order: {
    type: Object
  },
  customer: {
    type: Object
  },
	created: {
		type: Date,
		default: Date.now
	}
});

mongoose.model('Order', OrderSchema);
<|endoftext|>


<commit_before>var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
	if (this.readyState == 4 && this.status == 200) {
		render(JSON.parse(this.responseText));
	}
};
xhttp.open("GET", "./api/v1/preferences", true);
xhttp.send();

function render(preferences) {
	for(var i = 0; i < preferences.length; ++i) {
		renderPref(preferences[i]);
	}
}

function renderPref(pref) {
	console.log(pref);
	var div = document.createElement("div");
	switch(pref.type) {
	case "boolean":
		var checked = getBoolean(pref.key, pref.defaultValue) ? "checked " : "";
		div.innerHTML = "<input " + checked + " type=\"checkbox\">" + pref.name;
		div.firstElementChild.onchange = function() {
			updatedBoolean(pref.key, this.checked);
		};
		break;

	case "enum":
		var selectedValue = getEnum(pref.key, pref.defaultValue);
		var innerHTML = pref.name + ": <select>";
		for(var key in pref.values){
			if(!pref.values.hasOwnProperty(key)) continue;
			var selected = selectedValue === key ? " selected" : "";
			innerHTML += "<option" + selected + " value=\""+ key +"\">" + pref.values[key] + "</option>";
		}
		innerHTML += "</select>";
		div.innerHTML= innerHTML;
		div.firstElementChild.onchange = function() {
			updatedEnum(pref.key, this.value);
		};
		break;

	default:
		div.innerHTML = pref.name + " is not supported by the UI";
	}

	content.appendChild(div);
}

function updatedBoolean(key, value) {
	localStorage.setItem(key, value);
}

function updatedEnum(key, value) {
	localStorage.setItem(key, value);
}

function getBoolean(key, defaultValue) {
	if(!localStorage.hasOwnProperty(key)){
		return defaultValue;
	}
	return localStorage.getItem(key) === "true";
}

function getEnum(key, defaultValue) {
	if(!localStorage.hasOwnProperty(key)){
		return defaultValue;
	}
	return localStorage.getItem(key);
}<commit_msg>Fix bug in settings html (firefox)<commit_after>var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
	if (this.readyState == 4 && this.status == 200) {
		render(JSON.parse(this.responseText));
	}
};
xhttp.open("GET", "./api/v1/preferences", true);
xhttp.send();

function render(preferences) {
	for(var i = 0; i < preferences.length; ++i) {
		renderPref(preferences[i]);
	}
}

function renderPref(pref) {
	console.log(pref);
	var div = document.createElement("div");
	switch(pref.type) {
	case "boolean":
		var checked = getBoolean(pref.key, pref.defaultValue) ? "checked " : "";
		div.innerHTML = "<input " + checked + " type=\"checkbox\">" + pref.name;
		div.firstElementChild.onchange = function() {
			updatedBoolean(pref.key, this.checked);
		};
		break;

	case "enum":
		var selectedValue = getEnum(pref.key, pref.defaultValue);
		var innerHTML = pref.name + ": <select>";
		for(var key in pref.values){
			if(!pref.values.hasOwnProperty(key)) continue;
			var selected = selectedValue === key ? " selected" : "";
			innerHTML += "<option" + selected + " value=\""+ key +"\">" + pref.values[key] + "</option>";
		}
		innerHTML += "</select>";
		div.innerHTML= innerHTML;
		div.firstElementChild.onchange = function() {
			updatedEnum(pref.key, this.value);
		};
		break;

	default:
		div.innerHTML = pref.name + " is not supported by the UI";
	}

	document.getElementById("content").appendChild(div);
}

function updatedBoolean(key, value) {
	localStorage.setItem(key, value);
}

function updatedEnum(key, value) {
	localStorage.setItem(key, value);
}

function getBoolean(key, defaultValue) {
	if(!localStorage.hasOwnProperty(key)){
		return defaultValue;
	}
	return localStorage.getItem(key) === "true";
}

function getEnum(key, defaultValue) {
	if(!localStorage.hasOwnProperty(key)){
		return defaultValue;
	}
	return localStorage.getItem(key);
}<|endoftext|>


<commit_before>'use strict';

import assert from 'power-assert';
import fs from 'fs';
import path from 'path';
import * as nws from 'node-web-server';

import jsdom from 'mocha-jsdom';
jsdom();

import ContributionStatus from '../../../app/js/KeepMeContributing';

describe('ContributionStatus', function(){
  before(function(){
    /**
     * @type {ContributionStatus}
     */
    this.describedInstance = new ContributionStatus({
      username: 'igrep',
      apiUrl: 'http://localhost:8999'
    });
  });

  after(() => { nws.stop(); });

  describe('#queryHasContributedAt', function(){
    before(function(){
      /**
       * @type {function(Date): boolean}
       */
      this.subjectFunction = function(date){
        return this.describedInstance.queryHasContributedAt(date);
      };
    });

    context('given a response of https://github.com/users/igrep/contributions', function(){
      before(() => {
        /**
         * serve fixtures because sinon.js didn't work maybe because
         * fakeServer can't modify XMLHttpRequest correctly.
         */
        nws.run(
          {
            host: 'localhost',
            port: 8999,
            docRoot: 'github.com',
            MIME: { '': 'text/html; charset=utf-8' }
          },
          path.normalize(path.join(__dirname, '../../fixtures/'))
        );
      });

      context("the argument date's contribution count is 0", function(){
        it('returns false', function(){
          return this.subjectFunction(new Date('2015-07-31')).then((result) => { assert(result === false); });
        });
      });

      context("the argument date's contribution count is 2", function(){
        it('returns true', function(){
          return this.subjectFunction(new Date('2015-07-23')).then((result) => { assert(result === true); });
        });
      });

      context("the argument date's contribution count is 1", function(){
        it('returns true', function(){
          return this.subjectFunction(new Date('2015-07-29')).then((result) => { assert(result === true); });
        });
      });

      context("the argument date's contribution count is present", function(){
        it('returns false', function(){
          return this.subjectFunction(new Date('2015-08-01')).then((result) => { assert(result === false); });
        });
      });

    });
  });
});
<commit_msg>delete unused variable<commit_after>'use strict';

import assert from 'power-assert';
import path from 'path';
import * as nws from 'node-web-server';

import jsdom from 'mocha-jsdom';
jsdom();

import ContributionStatus from '../../../app/js/KeepMeContributing';

describe('ContributionStatus', function(){
  before(function(){
    /**
     * @type {ContributionStatus}
     */
    this.describedInstance = new ContributionStatus({
      username: 'igrep',
      apiUrl: 'http://localhost:8999'
    });
  });

  after(() => { nws.stop(); });

  describe('#queryHasContributedAt', function(){
    before(function(){
      /**
       * @type {function(Date): boolean}
       */
      this.subjectFunction = function(date){
        return this.describedInstance.queryHasContributedAt(date);
      };
    });

    context('given a response of https://github.com/users/igrep/contributions', function(){
      before(() => {
        /**
         * serve fixtures because sinon.js didn't work maybe because
         * fakeServer can't modify XMLHttpRequest correctly.
         */
        nws.run(
          {
            host: 'localhost',
            port: 8999,
            docRoot: 'github.com',
            MIME: { '': 'text/html; charset=utf-8' }
          },
          path.normalize(path.join(__dirname, '../../fixtures/'))
        );
      });

      context("the argument date's contribution count is 0", function(){
        it('returns false', function(){
          return this.subjectFunction(new Date('2015-07-31')).then((result) => { assert(result === false); });
        });
      });

      context("the argument date's contribution count is 2", function(){
        it('returns true', function(){
          return this.subjectFunction(new Date('2015-07-23')).then((result) => { assert(result === true); });
        });
      });

      context("the argument date's contribution count is 1", function(){
        it('returns true', function(){
          return this.subjectFunction(new Date('2015-07-29')).then((result) => { assert(result === true); });
        });
      });

      context("the argument date's contribution count is present", function(){
        it('returns false', function(){
          return this.subjectFunction(new Date('2015-08-01')).then((result) => { assert(result === false); });
        });
      });

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


<commit_before>import {inject} from 'aurelia-framework';
import {Router} from 'aurelia-router';
import {HttpClient, json} from 'aurelia-fetch-client';
import 'fetch';

@inject(HttpClient, Router)
export class EditClient {
  heading = 'Edit Client';
  submitText = 'Update Client';

  name = "";
  id = "";
  enabled = true;
  claimsUri = "";

  isNewClient = false;
  clientAdded = false;

  constructor(http, router) {
    http.configure(config => {
      config
        .useStandardConfiguration()
        .withBaseUrl('http://localhost:56627');
    });

    this.http = http;
    this.router = router;
  }

  activate(params) {
    this.id = params.id;
    this.isNewClient = !this.id;

    if (this.isNewClient) {
      this.heading = "New Client";
      this.submitText = "Add Client";
    } else {
      return this.http.fetch('/api/clients/' + this.id)
        .then(response => response.json(), response => {
          console.error("Error getting client " + this.id + ": " + JSON.stringify());
          this.errorMessage = "Error getting client " + this.id;
        })
        .then(client => {
          this.name = client.name;
          this.enabled = client.enabled;
          this.claimsUri = client.claimsUri;
        });
    }
  }

  submit() {
    var client = {
      id: this.id,
      name: this.name,
      enabled: this.enabled,
      claimsUri: this.claimsUri
    };
    if (this.isNewClient) {
      this.http.fetch('/api/clients', {
        method: 'post',
        body: json(client)
      })
        .then(response => {
          this.clientAdded = true;
        }, response => {
          console.error("Error creating client: " + JSON.stringify(response));
          this.errorMessage = "Error creating client";
        });
    } else {
      this.http.fetch('/api/clients/' + this.id, {
        method: 'put',
        body: json(client)
      })
        .then(response => {
          console.log("Client updated!");
        }, response => {
          console.error("Error updating client " + this.id + ": " + JSON.stringify(response));
          this.errorMessage = "Error updating client";
        });
    }
  }

  manage() {
    this.router.navigateToRoute('manageClient', { id: this.id });
  }
}
<commit_msg>Correcting URI for users api<commit_after>import {inject} from 'aurelia-framework';
import {Router} from 'aurelia-router';
import {HttpClient, json} from 'aurelia-fetch-client';
import 'fetch';

@inject(HttpClient, Router)
export class EditClient {
  heading = 'Edit Client';
  submitText = 'Update Client';

  name = "";
  id = "";
  enabled = true;
  claimsUri = "";

  isNewClient = false;
  clientAdded = false;

  constructor(http, router) {
    http.configure(config => {
      config
        .useStandardConfiguration()
        .withBaseUrl('https://localhost:44392');
    });

    this.http = http;
    this.router = router;
  }

  activate(params) {
    this.id = params.id;
    this.isNewClient = !this.id;

    if (this.isNewClient) {
      this.heading = "New Client";
      this.submitText = "Add Client";
    } else {
      return this.http.fetch('/api/clients/' + this.id)
        .then(response => response.json(), response => {
          console.error("Error getting client " + this.id + ": " + JSON.stringify());
          this.errorMessage = "Error getting client " + this.id;
        })
        .then(client => {
          this.name = client.name;
          this.enabled = client.enabled;
          this.claimsUri = client.claimsUri;
        });
    }
  }

  submit() {
    var client = {
      id: this.id,
      name: this.name,
      enabled: this.enabled,
      claimsUri: this.claimsUri
    };
    if (this.isNewClient) {
      this.http.fetch('/api/clients', {
        method: 'post',
        body: json(client)
      })
        .then(response => {
          this.clientAdded = true;
        }, response => {
          console.error("Error creating client: " + JSON.stringify(response));
          this.errorMessage = "Error creating client";
        });
    } else {
      this.http.fetch('/api/clients/' + this.id, {
        method: 'put',
        body: json(client)
      })
        .then(response => {
          console.log("Client updated!");
        }, response => {
          console.error("Error updating client " + this.id + ": " + JSON.stringify(response));
          this.errorMessage = "Error updating client";
        });
    }
  }

  manage() {
    this.router.navigateToRoute('manageClient', { id: this.id });
  }
}
<|endoftext|>


<commit_before>/**
 * This file is part of Superdesk.
 *
 * Copyright 2013, 2014 Sourcefabric z.u. and contributors.
 *
 * For the full copyright and license information, please see the
 * AUTHORS and LICENSE files distributed with this source code, or
 * at https://www.sourcefabric.org/superdesk/license
 */

(function() {
    'use strict';

    var app = angular.module('superdesk.publish', ['superdesk.users', 'superdesk.publish.filters']);

    app.value('transmissionTypes', {
        ftp: {
            label: 'FTP',
            templateUrl: 'scripts/superdesk-publish/views/ftp-config.html'
        },
        email: {
            label: 'Email',
            templateUrl: 'scripts/superdesk-publish/views/email-config.html'
        },
        ODBC: {
            label: 'ODBC',
            templateUrl: 'scripts/superdesk-publish/views/odbc-config.html'
        },
        File: {
            label: 'File',
            templateUrl: 'scripts/superdesk-publish/views/file-config.html'
        },
        pull: {
            label: 'Pull'
        },
        PublicArchive: {
            label: 'Public Archive',
            templateUrl: 'scripts/superdesk-publish/views/public-archive-config.html'
        }
    });

    AdminPublishSettingsController.$inject = ['$scope', 'privileges'];
    function AdminPublishSettingsController($scope, privileges) {
        var user_privileges = privileges.privileges;

        $scope.showSubscribers  = Boolean(user_privileges.subscribers);
        $scope.showFilterConditions  = Boolean(user_privileges.publish_filters);
    }

    AdminPublishSettingsService.$inject = ['api', '$q'];
    function AdminPublishSettingsService(api, $q) {
        var _fetch = function(endpoint, criteria) {
            return api[endpoint].query(criteria);
        };

        var service = {
            fetchSubscribers: function(criteria) {
                criteria = criteria || {};
                return _fetch('subscribers', criteria);
            },

            fetchSubscribersByKeyword: function(keyword) {
                return this.fetchSubscribers({
                    where: JSON.stringify({
                        '$or': [
                            {name: {'$regex': keyword, '$options': '-i'}}
                        ]
                    })
                });
            },

            fetchSubscribersByIds: function(ids) {
                var parts = [];
                _.each(ids, function(id) {
                    parts.push({_id: id});
                });
                return this.fetchSubscribers({
                    where: JSON.stringify({'$or': parts})
                });
            },

            fetchPublishErrors: function() {
                var criteria = {'io_type': 'publish'};
                return _fetch('io_errors', criteria);
            }
        };

        return service;
    }

    DestinationDirective.$inject = ['transmissionTypes'];
    function DestinationDirective(transmissionTypes) {
        return {
            templateUrl: 'scripts/superdesk-publish/views/destination.html',
            scope: {
                destination: '=',
                actions: '='
            },
            link: function ($scope) {
                $scope.types = transmissionTypes;
            }
        };
    }

    DataConsistencyController.$inject = ['$scope', 'api'];
    function DataConsistencyController($scope, api) {
        $scope.consistency_records = null;

        function fetchConsistencyRecords () {
            var criteria = criteria || {};
            criteria.max_results = 200;
            return api.consistency.query(criteria);
        }

        $scope.reload = function() {
            fetchConsistencyRecords().then(function(data) {
                $scope.consistency_records = data._items;
                $scope.lastRefreshedAt = new Date();
            });
        };

        $scope.reload ();
    }

    PublishQueueController.$inject = ['$scope', 'adminPublishSettingsService', 'api', '$q', 'notify', '$location'];
    function PublishQueueController($scope, adminPublishSettingsService, api, $q, notify, $location) {
        $scope.subscribers = null;
        $scope.subscriberLookup = {};
        $scope.publish_queue = [];
        $scope.selectedFilterSubscriber = null;
        $scope.multiSelectCount = 0;
        $scope.selectedQueueItems = [];
        $scope.showResendBtn = false;
        $scope.showCancelBtn = false;
        $scope.selected = {};

        var promises = [];

        promises.push(adminPublishSettingsService.fetchSubscribers().then(function(items) {
            $scope.subscribers = items._items;
            _.each(items._items, function(item) {
                $scope.subscriberLookup[item._id] = item;
            });
        }));

        function fetchPublishQueue () {
            var criteria = criteria || {};
            criteria.max_results = 200;
            criteria.sort = '[(\'published_seq_num\',-1)]';

            if ($scope.selectedFilterSubscriber !== null) {
                criteria.where = {'subscriber_id': $scope.selectedFilterSubscriber._id};
            }

            return api.publish_queue.query(criteria);
        }

        $scope.reload = function() {
            $q.all(promises).then(function() {
                fetchPublishQueue().then(function(queue) {
                    var queuedItems = queue._items;

                    _.forEach(queuedItems, function(item) {
                        angular.extend(item, {'selected': false});
                    });

                    $scope.publish_queue = queuedItems;
                    $scope.lastRefreshedAt = new Date();
                    $scope.showResendBtn = false;
                    $scope.showCacnelBtn = false;

                    previewItem();
                });
            });
        };

        $scope.buildNewSchedule = function (item) {
            var pick_fields = ['item_id', 'item_version', 'publishing_action', 'formatted_item', 'headline',
                'content_type', 'subscriber_id', 'unique_name', 'destination'];

            var newItem = _.pick(item, pick_fields);
            return newItem;
        };

        $scope.scheduleToSend = function(item) {
            var queueItems = [];

            if (angular.isDefined(item)) {
                queueItems.push($scope.buildNewSchedule(item));
            } else if ($scope.multiSelectCount > 0) {
                _.forEach($scope.selectedQueueItems, function(item) {
                    queueItems.push($scope.buildNewSchedule(item));
                });
            }

            api.publish_queue.save([], queueItems).then(
                function(response) {
                    $scope.reload();
                    $scope.cancelSelection();
                },
                function(response) {
                    if (angular.isDefined(response.data._issues)) {
                        if (angular.isDefined(response.data._issues['validator exception'])) {
                            notify.error(gettext('Error: ' + response.data._issues['validator exception']));
                        }
                    } else {
                        notify.error(gettext('Error: Failed to re-schedule'));
                    }
                }
            );
        };

        $scope.filterSchedule = function(item, type) {
            if (type === 'subscriber') {
                $scope.selectedFilterSubscriber = item;
            }

            $scope.multiSelectCount = 0;
            fetchPublishQueue().then(function(queue) {
                var queuedItems = queue._items;

                _.forEach(queuedItems, function(item) {
                    angular.extend(item, {'selected': false});
                });

                $scope.publish_queue = queuedItems;
                $scope.lastRefreshedAt = new Date();
                $scope.showResendBtn = false;
                $scope.showCancelBtn = false;
                $scope.selectedQueueItems = [];
            });
        };

        $scope.selectQueuedItem = function(queuedItem) {
            if (queuedItem.selected) {
                $scope.selectedQueueItems = _.union($scope.selectedQueueItems, [queuedItem]);
            } else {
                $scope.selectedQueueItems = _.without($scope.selectedQueueItems, queuedItem);
            }

            var idx = _.findIndex($scope.selectedQueueItems, function(item) {
                return item.state === 'pending' || item.state === 'in-progress' || item.state === 'canceled';
            });

            if (idx === -1) {
                $scope.showResendBtn = true;
                $scope.showCancelBtn = false;
            } else {
                idx = _.findIndex($scope.selectedQueueItems, function(item) {
                    return item.state === 'success' || item.state === 'in-progress' || item.state === 'canceled' ||
                        item.state === 'error';
                });

                if (idx === -1) {
                    $scope.showResendBtn = false;
                    $scope.showCancelBtn = true;
                } else {
                    $scope.showResendBtn = false;
                    $scope.showCancelBtn = false;
                }
            }

            $scope.multiSelectCount = $scope.selectedQueueItems.length;
        };

        $scope.cancelSelection = function() {
            $scope.selectedFilterSubscriber = null;
            $scope.selectedQueueItems = [];
            $scope.multiSelectCount = 0;
            $scope.filterSchedule();
        };

        function refreshQueueState (data) {
            var item = _.find($scope.publish_queue, {'_id': data.queue_id});

            if (item) {
                var fields = ['error_message', 'completed_at', 'state'];
                angular.extend(item, _.pick(data, fields));
                $scope.$apply();
            }
        }

        $scope.preview = function(queueItem) {
            $location.search('_id', queueItem ? queueItem._id : queueItem);
        };

        function previewItem() {
            var queueItem = _.find($scope.publish_queue, {_id: $location.search()._id}) || null;
            if (queueItem) {
                api.archive.getById(queueItem.item_id)
                .then(function(item) {
                    $scope.selected.preview = item;
                });
            } else {
                $scope.selected.preview = null;
            }
        }

        $scope.$on('$routeUpdate', previewItem);

        $scope.$on('publish_queue:update', function(evt, data) { refreshQueueState(data); });
        $scope.reload();
    }

    SubscribersDirective.$inject = ['gettext', 'notify', 'api', 'adminPublishSettingsService', 'modal', 'metadata', 'filters', '$q'];
    function SubscribersDirective(gettext, notify, api, adminPublishSettingsService, modal, metadata, filters, $q) {
        return {
            templateUrl: 'scripts/superdesk-publish/views/subscribers.html',
            link: function ($scope) {
                $scope.subscriber = null;
                $scope.origSubscriber = null;
                $scope.subscribers = null;
                $scope.newDestination = null;
                $scope.publishFilters = null;
                $scope.geoRestrictions = null;
                $scope.subTypes = null;

                if (angular.isDefined(metadata.values.geographical_restrictions)) {
                    $scope.geoRestrictions = metadata.values.geographical_restrictions;
                    $scope.subTypes = metadata.values.subscriber_types;
                } else {
                    metadata.fetchMetadataValues().then(function() {
                        $scope.geoRestrictions = metadata.values.geographical_restrictions;
                        $scope.subTypes = metadata.values.subscriber_types;
                    });
                }

                function fetchSubscribers() {
                    adminPublishSettingsService.fetchSubscribers().then(
                        function(result) {
                            $scope.subscribers = result;
                        }
                    );
                }

                var fetchPublishFilters = function() {
                    return api.query('publish_filters').then(function(filters) {
                        $scope.publishFilters = filters._items;
                    });
                };

                var initGlobalFilters = function() {
                    if (!$scope.subscriber) {
                        return;
                    }

                    if (!$scope.subscriber.global_filters) {
                        $scope.subscriber.global_filters = {};
                    }

                    _.each($scope.globalFilters, function(filter) {
                        if (!(filter._id in $scope.subscriber.global_filters)) {
                            $scope.subscriber.global_filters[filter._id] = true;
                        }
                    });
                };

                var fetchGlobalPublishFilters = function() {
                    return filters.getGlobalPublishFilters().then(function(filters) {
                        $scope.globalFilters = filters;
                    });
                };

                function fetchPublishErrors() {
                    return adminPublishSettingsService.fetchPublishErrors().then(function(result) {
                        $scope.all_errors = result._items[0].all_errors;
                    });
                }

                $scope.addNewDestination = function() {
                    $scope.newDestination = {};
                };

                $scope.cancelNewDestination = function() {
                    $scope.newDestination = null;
                };

                $scope.saveNewDestination = function() {
                    $scope.subscriber.destinations.push($scope.newDestination);
                    $scope.newDestination = null;
                };

                $scope.deleteDestination = function(destination) {
                    _.remove($scope.subscriber.destinations, destination);
                };

                $scope.save = function() {

                    if ($scope.subscriber.publish_filter && $scope.subscriber.publish_filter.filter_id === '') {
                        $scope.subscriber.publish_filter.filter_id = null;
                    }

                    api.subscribers.save($scope.origSubscriber, $scope.subscriber)
                        .then(
                            function() {
                                notify.success(gettext('Subscriber saved.'));
                                $scope.cancel();
                            },
                            function(response) {
                                if (angular.isDefined(response.data._issues)) {
                                    if (angular.isDefined(response.data._issues['validator exception'])) {
                                        notify.error(gettext('Error: ' + response.data._issues['validator exception']));
                                    } else if (angular.isDefined(response.data._issues.name) &&
                                        angular.isDefined(response.data._issues.name.unique)) {
                                        notify.error(gettext('Error: Subscriber with Name ' + $scope.subscriber.name +
                                            ' already exists.'));
                                    }
                                } else {
                                    notify.error(gettext('Error: Failed to save Subscriber.'));
                                }
                            }
                        ).then(fetchSubscribers);
                };

                $scope.edit = function(subscriber) {
                    var promises = [];
                    promises.push(fetchPublishErrors());
                    promises.push(fetchPublishFilters());
                    promises.push(fetchGlobalPublishFilters());

                    $q.all(promises).then(function() {
                        $scope.origSubscriber = subscriber || {};
                        $scope.subscriber = _.create($scope.origSubscriber);
                        $scope.subscriber.critical_errors = $scope.origSubscriber.critical_errors;
                        $scope.subscriber.publish_filter = $scope.origSubscriber.publish_filter || {};
                        $scope.subscriber.global_filters =  $scope.origSubscriber.global_filters || {};
                        $scope.subscriber.publish_filter.filter_type = $scope.subscriber.publish_filter.filter_type  || 'blocking';
                        initGlobalFilters();
                    }, function() {
                        notify.error(gettext('Subscriber could not be initialized!'));
                    });
                };

                $scope.remove = function(subscriber) {
                    modal.confirm(gettext('Are you sure you want to delete subscriber?'))
                    .then(function() {
                        return api.subscribers.remove(subscriber);
                    })
                    .then(function(result) {
                        _.remove($scope.subscribers, subscriber);
                    }, function(response) {
                        if (angular.isDefined(response.data._message)) {
                            notify.error(gettext('Error: ' + response.data._message));
                        } else {
                            notify.error(gettext('There is an error. Subscriber cannot be deleted.'));
                        }
                    })
                    .then(fetchSubscribers);
                };

                $scope.cancel = function() {
                    $scope.origSubscriber = null;
                    $scope.subscriber = null;
                    $scope.newDestination = null;
                };

                fetchSubscribers();
            }
        };
    }

    app
        .service('adminPublishSettingsService', AdminPublishSettingsService)
        .directive('sdAdminPubSubscribers', SubscribersDirective)
        .directive('sdDestination', DestinationDirective)
        .controller('publishQueueCtrl', PublishQueueController);

    app
        .config(['superdeskProvider', function(superdesk) {
            superdesk
                .activity('/settings/publish', {
                    label: gettext('Publish'),
                    templateUrl: 'scripts/superdesk-publish/views/settings.html',
                    controller: AdminPublishSettingsController,
                    category: superdesk.MENU_SETTINGS,
                    privileges: {subscribers: 1},
                    priority: 2000,
                    beta: true
                })
                .activity('/publish_queue', {
                    label: gettext('Publish Queue'),
                    templateUrl: 'scripts/superdesk-publish/views/publish-queue.html',
                    controller: PublishQueueController,
                    category: superdesk.MENU_MAIN,
                    privileges: {publish_queue: 1}
                })
                .activity('/settings/data_consistency', {
                    label: gettext('Data Consistency'),
                    templateUrl: 'scripts/superdesk-publish/views/data-consistency.html',
                    controller: DataConsistencyController,
                    category: superdesk.MENU_SETTINGS,
                    privileges: {subscribers: 1},
                    priority: 2000,
                    beta: true
                });
        }])
        .config(['apiProvider', function(apiProvider) {
            apiProvider.api('subscribers', {
                type: 'http',
                backend: {
                    rel: 'subscribers'
                }
            });
            apiProvider.api('publish_queue', {
                type: 'http',
                backend: {
                    rel: 'publish_queue'
                }
            });
            apiProvider.api('consistency', {
                type: 'http',
                backend: {
                    rel: 'consistency'
                }
            });
            apiProvider.api('formatted_item', {
                type: 'http',
                backend: {
                    rel: 'formatted_item'
                }
            });
            apiProvider.api('io_errors', {
                type: 'http',
                backend: {
                    rel: 'io_errors'
                }
            });
        }]);

    return app;
})();
<commit_msg>[SD-2684] Changes were overwritten by one of the previous merge.<commit_after>/**
 * This file is part of Superdesk.
 *
 * Copyright 2013, 2014 Sourcefabric z.u. and contributors.
 *
 * For the full copyright and license information, please see the
 * AUTHORS and LICENSE files distributed with this source code, or
 * at https://www.sourcefabric.org/superdesk/license
 */

(function() {
    'use strict';

    var app = angular.module('superdesk.publish', ['superdesk.users', 'superdesk.publish.filters']);

    app.value('transmissionTypes', {
        ftp: {
            label: 'FTP',
            templateUrl: 'scripts/superdesk-publish/views/ftp-config.html'
        },
        email: {
            label: 'Email',
            templateUrl: 'scripts/superdesk-publish/views/email-config.html'
        },
        ODBC: {
            label: 'ODBC',
            templateUrl: 'scripts/superdesk-publish/views/odbc-config.html'
        },
        File: {
            label: 'File',
            templateUrl: 'scripts/superdesk-publish/views/file-config.html'
        },
        pull: {
            label: 'Pull'
        },
        PublicArchive: {
            label: 'Public Archive',
            templateUrl: 'scripts/superdesk-publish/views/public-archive-config.html'
        }
    });

    AdminPublishSettingsController.$inject = ['$scope', 'privileges'];
    function AdminPublishSettingsController($scope, privileges) {
        var user_privileges = privileges.privileges;

        $scope.showSubscribers  = Boolean(user_privileges.subscribers);
        $scope.showFilterConditions  = Boolean(user_privileges.publish_filters);
    }

    AdminPublishSettingsService.$inject = ['api', '$q'];
    function AdminPublishSettingsService(api, $q) {
        var _fetch = function(endpoint, criteria) {
            return api[endpoint].query(criteria);
        };

        var service = {
            fetchSubscribers: function(criteria) {
                criteria = criteria || {};
                return _fetch('subscribers', criteria);
            },

            fetchSubscribersByKeyword: function(keyword) {
                return this.fetchSubscribers({
                    where: JSON.stringify({
                        '$or': [
                            {name: {'$regex': keyword, '$options': '-i'}}
                        ]
                    })
                });
            },

            fetchSubscribersByIds: function(ids) {
                var parts = [];
                _.each(ids, function(id) {
                    parts.push({_id: id});
                });
                return this.fetchSubscribers({
                    where: JSON.stringify({'$or': parts})
                });
            },

            fetchPublishErrors: function() {
                var criteria = {'io_type': 'publish'};
                return _fetch('io_errors', criteria);
            }
        };

        return service;
    }

    DestinationDirective.$inject = ['transmissionTypes'];
    function DestinationDirective(transmissionTypes) {
        return {
            templateUrl: 'scripts/superdesk-publish/views/destination.html',
            scope: {
                destination: '=',
                actions: '='
            },
            link: function ($scope) {
                $scope.types = transmissionTypes;
            }
        };
    }

    DataConsistencyController.$inject = ['$scope', 'api'];
    function DataConsistencyController($scope, api) {
        $scope.consistency_records = null;

        function fetchConsistencyRecords () {
            var criteria = criteria || {};
            criteria.max_results = 200;
            return api.consistency.query(criteria);
        }

        $scope.reload = function() {
            fetchConsistencyRecords().then(function(data) {
                $scope.consistency_records = data._items;
                $scope.lastRefreshedAt = new Date();
            });
        };

        $scope.reload ();
    }

    PublishQueueController.$inject = ['$scope', 'adminPublishSettingsService', 'api', '$q', 'notify', '$location'];
    function PublishQueueController($scope, adminPublishSettingsService, api, $q, notify, $location) {
        $scope.subscribers = null;
        $scope.subscriberLookup = {};
        $scope.publish_queue = [];
        $scope.selectedFilterSubscriber = null;
        $scope.multiSelectCount = 0;
        $scope.selectedQueueItems = [];
        $scope.showResendBtn = false;
        $scope.showCancelBtn = false;
        $scope.selected = {};

        var promises = [];

        promises.push(adminPublishSettingsService.fetchSubscribers().then(function(items) {
            $scope.subscribers = items._items;
            _.each(items._items, function(item) {
                $scope.subscriberLookup[item._id] = item;
            });
        }));

        function fetchPublishQueue () {
            var criteria = criteria || {};
            criteria.max_results = 200;
            criteria.sort = '[(\'published_seq_num\',-1)]';

            if ($scope.selectedFilterSubscriber !== null) {
                criteria.where = {'subscriber_id': $scope.selectedFilterSubscriber._id};
            }

            return api.publish_queue.query(criteria);
        }

        $scope.reload = function() {
            $q.all(promises).then(function() {
                fetchPublishQueue().then(function(queue) {
                    var queuedItems = queue._items;

                    _.forEach(queuedItems, function(item) {
                        angular.extend(item, {'selected': false});
                    });

                    $scope.publish_queue = queuedItems;
                    $scope.lastRefreshedAt = new Date();
                    $scope.showResendBtn = false;
                    $scope.showCacnelBtn = false;

                    previewItem();
                });
            });
        };

        $scope.buildNewSchedule = function (item) {
            var pick_fields = ['item_id', 'item_version', 'publishing_action', 'formatted_item', 'headline',
                'content_type', 'subscriber_id', 'unique_name', 'destination'];

            var newItem = _.pick(item, pick_fields);
            return newItem;
        };

        $scope.scheduleToSend = function(item) {
            var queueItems = [];

            if (angular.isDefined(item)) {
                queueItems.push($scope.buildNewSchedule(item));
            } else if ($scope.multiSelectCount > 0) {
                _.forEach($scope.selectedQueueItems, function(item) {
                    queueItems.push($scope.buildNewSchedule(item));
                });
            }

            api.publish_queue.save([], queueItems).then(
                function(response) {
                    $scope.reload();
                    $scope.cancelSelection();
                },
                function(response) {
                    if (angular.isDefined(response.data._issues)) {
                        if (angular.isDefined(response.data._issues['validator exception'])) {
                            notify.error(gettext('Error: ' + response.data._issues['validator exception']));
                        }
                    } else {
                        notify.error(gettext('Error: Failed to re-schedule'));
                    }
                }
            );
        };

        $scope.filterSchedule = function(item, type) {
            if (type === 'subscriber') {
                $scope.selectedFilterSubscriber = item;
            }

            $scope.multiSelectCount = 0;
            fetchPublishQueue().then(function(queue) {
                var queuedItems = queue._items;

                _.forEach(queuedItems, function(item) {
                    angular.extend(item, {'selected': false});
                });

                $scope.publish_queue = queuedItems;
                $scope.lastRefreshedAt = new Date();
                $scope.showResendBtn = false;
                $scope.showCancelBtn = false;
                $scope.selectedQueueItems = [];
            });
        };

        $scope.selectQueuedItem = function(queuedItem) {
            if (queuedItem.selected) {
                $scope.selectedQueueItems = _.union($scope.selectedQueueItems, [queuedItem]);
            } else {
                $scope.selectedQueueItems = _.without($scope.selectedQueueItems, queuedItem);
            }

            var idx = _.findIndex($scope.selectedQueueItems, function(item) {
                return item.state === 'pending' || item.state === 'in-progress' || item.state === 'canceled';
            });

            if (idx === -1) {
                $scope.showResendBtn = true;
                $scope.showCancelBtn = false;
            } else {
                idx = _.findIndex($scope.selectedQueueItems, function(item) {
                    return item.state === 'success' || item.state === 'in-progress' || item.state === 'canceled' ||
                        item.state === 'error';
                });

                if (idx === -1) {
                    $scope.showResendBtn = false;
                    $scope.showCancelBtn = true;
                } else {
                    $scope.showResendBtn = false;
                    $scope.showCancelBtn = false;
                }
            }

            $scope.multiSelectCount = $scope.selectedQueueItems.length;
        };

        $scope.cancelSelection = function() {
            $scope.selectedFilterSubscriber = null;
            $scope.selectedQueueItems = [];
            $scope.multiSelectCount = 0;
            $scope.filterSchedule();
        };

        function refreshQueueState (data) {
            var item = _.find($scope.publish_queue, {'_id': data.queue_id});

            if (item) {
                var fields = ['error_message', 'completed_at', 'state'];
                angular.extend(item, _.pick(data, fields));
                $scope.$apply();
            }
        }

        $scope.preview = function(queueItem) {
            $location.search('_id', queueItem ? queueItem._id : queueItem);
        };

        function previewItem() {
            var queueItem = _.find($scope.publish_queue, {_id: $location.search()._id}) || null;
            if (queueItem) {
                api.archive.getById(queueItem.item_id)
                .then(function(item) {
                    $scope.selected.preview = item;
                });
            } else {
                $scope.selected.preview = null;
            }
        }

        $scope.$on('$routeUpdate', previewItem);

        $scope.$on('publish_queue:update', function(evt, data) { refreshQueueState(data); });
        $scope.reload();
    }

    SubscribersDirective.$inject = ['gettext', 'notify', 'api', 'adminPublishSettingsService', 'modal', 'metadata', 'filters', '$q'];
    function SubscribersDirective(gettext, notify, api, adminPublishSettingsService, modal, metadata, filters, $q) {
        return {
            templateUrl: 'scripts/superdesk-publish/views/subscribers.html',
            link: function ($scope) {
                $scope.subscriber = null;
                $scope.origSubscriber = null;
                $scope.subscribers = null;
                $scope.newDestination = null;
                $scope.publishFilters = null;
                $scope.geoRestrictions = null;
                $scope.subTypes = null;

                if (angular.isDefined(metadata.values.geographical_restrictions)) {
                    $scope.geoRestrictions = metadata.values.geographical_restrictions;
                    $scope.subTypes = metadata.values.subscriber_types;
                } else {
                    metadata.fetchMetadataValues().then(function() {
                        $scope.geoRestrictions = metadata.values.geographical_restrictions;
                        $scope.subTypes = metadata.values.subscriber_types;
                    });
                }

                function fetchSubscribers() {
                    adminPublishSettingsService.fetchSubscribers().then(
                        function(result) {
                            $scope.subscribers = result;
                        }
                    );
                }

                var fetchPublishFilters = function() {
                    return api.query('publish_filters').then(function(filters) {
                        $scope.publishFilters = filters._items;
                    });
                };

                var initGlobalFilters = function() {
                    if (!$scope.subscriber) {
                        return;
                    }

                    if (!$scope.subscriber.global_filters) {
                        $scope.subscriber.global_filters = {};
                    }

                    _.each($scope.globalFilters, function(filter) {
                        if (!(filter._id in $scope.subscriber.global_filters)) {
                            $scope.subscriber.global_filters[filter._id] = true;
                        }
                    });
                };

                var fetchGlobalPublishFilters = function() {
                    return filters.getGlobalPublishFilters().then(function(filters) {
                        $scope.globalFilters = filters;
                    });
                };

                function fetchPublishErrors() {
                    return adminPublishSettingsService.fetchPublishErrors().then(function(result) {
                        $scope.all_errors = result._items[0].all_errors;
                    });
                }

                $scope.addNewDestination = function() {
                    $scope.newDestination = {};
                };

                $scope.cancelNewDestination = function() {
                    $scope.newDestination = null;
                };

                $scope.saveNewDestination = function() {
                    $scope.subscriber.destinations.push($scope.newDestination);
                    $scope.newDestination = null;
                };

                $scope.deleteDestination = function(destination) {
                    _.remove($scope.subscriber.destinations, destination);
                };

                $scope.save = function() {

                    if ($scope.subscriber.publish_filter && $scope.subscriber.publish_filter.filter_id === '') {
                        $scope.subscriber.publish_filter.filter_id = null;
                    }

                    api.subscribers.save($scope.origSubscriber, $scope.subscriber)
                        .then(
                            function() {
                                notify.success(gettext('Subscriber saved.'));
                                $scope.cancel();
                            },
                            function(response) {
                                if (angular.isDefined(response.data._issues)) {
                                    if (angular.isDefined(response.data._issues['validator exception'])) {
                                        notify.error(gettext('Error: ' + response.data._issues['validator exception']));
                                    } else if (angular.isDefined(response.data._issues.name) &&
                                        angular.isDefined(response.data._issues.name.unique)) {
                                        notify.error(gettext('Error: Subscriber with Name ' + $scope.subscriber.name +
                                            ' already exists.'));
                                    } else if (angular.isDefined(response.data._issues.destinations)) {
                                        notify.error(gettext('Error: Subscriber must have at least one destination.'));
                                    }
                                } else {
                                    notify.error(gettext('Error: Failed to save Subscriber.'));
                                }
                            }
                        ).then(fetchSubscribers);
                };

                $scope.edit = function(subscriber) {
                    var promises = [];
                    promises.push(fetchPublishErrors());
                    promises.push(fetchPublishFilters());
                    promises.push(fetchGlobalPublishFilters());

                    $q.all(promises).then(function() {
                        $scope.origSubscriber = subscriber || {};
                        $scope.subscriber = _.create($scope.origSubscriber);
                        $scope.subscriber.critical_errors = $scope.origSubscriber.critical_errors;
                        $scope.subscriber.publish_filter = $scope.origSubscriber.publish_filter || {};
                        $scope.subscriber.destinations = $scope.subscriber.destinations || [];
                        $scope.subscriber.global_filters =  $scope.origSubscriber.global_filters || {};
                        $scope.subscriber.publish_filter.filter_type = $scope.subscriber.publish_filter.filter_type  || 'blocking';
                        initGlobalFilters();
                    }, function() {
                        notify.error(gettext('Subscriber could not be initialized!'));
                    });
                };

                $scope.remove = function(subscriber) {
                    modal.confirm(gettext('Are you sure you want to delete subscriber?'))
                    .then(function() {
                        return api.subscribers.remove(subscriber);
                    })
                    .then(function(result) {
                        _.remove($scope.subscribers, subscriber);
                    }, function(response) {
                        if (angular.isDefined(response.data._message)) {
                            notify.error(gettext('Error: ' + response.data._message));
                        } else {
                            notify.error(gettext('There is an error. Subscriber cannot be deleted.'));
                        }
                    })
                    .then(fetchSubscribers);
                };

                $scope.cancel = function() {
                    $scope.origSubscriber = null;
                    $scope.subscriber = null;
                    $scope.newDestination = null;
                };

                fetchSubscribers();
            }
        };
    }

    app
        .service('adminPublishSettingsService', AdminPublishSettingsService)
        .directive('sdAdminPubSubscribers', SubscribersDirective)
        .directive('sdDestination', DestinationDirective)
        .controller('publishQueueCtrl', PublishQueueController);

    app
        .config(['superdeskProvider', function(superdesk) {
            superdesk
                .activity('/settings/publish', {
                    label: gettext('Publish'),
                    templateUrl: 'scripts/superdesk-publish/views/settings.html',
                    controller: AdminPublishSettingsController,
                    category: superdesk.MENU_SETTINGS,
                    privileges: {subscribers: 1},
                    priority: 2000,
                    beta: true
                })
                .activity('/publish_queue', {
                    label: gettext('Publish Queue'),
                    templateUrl: 'scripts/superdesk-publish/views/publish-queue.html',
                    controller: PublishQueueController,
                    category: superdesk.MENU_MAIN,
                    privileges: {publish_queue: 1}
                })
                .activity('/settings/data_consistency', {
                    label: gettext('Data Consistency'),
                    templateUrl: 'scripts/superdesk-publish/views/data-consistency.html',
                    controller: DataConsistencyController,
                    category: superdesk.MENU_SETTINGS,
                    privileges: {subscribers: 1},
                    priority: 2000,
                    beta: true
                });
        }])
        .config(['apiProvider', function(apiProvider) {
            apiProvider.api('subscribers', {
                type: 'http',
                backend: {
                    rel: 'subscribers'
                }
            });
            apiProvider.api('publish_queue', {
                type: 'http',
                backend: {
                    rel: 'publish_queue'
                }
            });
            apiProvider.api('consistency', {
                type: 'http',
                backend: {
                    rel: 'consistency'
                }
            });
            apiProvider.api('formatted_item', {
                type: 'http',
                backend: {
                    rel: 'formatted_item'
                }
            });
            apiProvider.api('io_errors', {
                type: 'http',
                backend: {
                    rel: 'io_errors'
                }
            });
        }]);

    return app;
})();
<|endoftext|>


<commit_before>var mongoose     = require('mongoose');
var Schema       = mongoose.Schema;

var Objectid = mongoose.Schema.Types.ObjectId;
var Membership = require('./membership_model');
var Location = require('./location_model');
var User = require('./user_model');

var OrganisationSchema   = new Schema({
	name: { type: String, unique: true, index: true },
	tel: String,
	mobile: String,
	email: String,
	website: String,
	address: String,
	twitter: String,
	facebook: String,
	linkedin: String,
	img: String,
	about: String,
	user_id: { type: Objectid, ref: 'User' },
	sage_uid: Number,
	vat: String,
	location_id: { type: Objectid, ref: 'Location' },
	space_total: { type: Number, default: 0 }, //Debit + Credit
	stuff_total: { type: Number, default: 0 }, //Debit + Credit
	membership: { type: Objectid, ref: 'Membership' },
	space_credits_per_month_override: Number,
	stuff_credits_per_month_override: Number,
	cost_per_month_override: Number,
	_owner_id: Objectid,
	_deleted: { type: Boolean, default: false, index: true },
});

OrganisationSchema.set("_perms", {
	admin: "crud",
	owner: "crud",
	user: "cr",
	all: "r"
});

module.exports = mongoose.model('Organisation', OrganisationSchema);<commit_msg>Bandwidth override<commit_after>var mongoose     = require('mongoose');
var Schema       = mongoose.Schema;

var Objectid = mongoose.Schema.Types.ObjectId;
var Membership = require('./membership_model');
var Location = require('./location_model');
var User = require('./user_model');

var OrganisationSchema   = new Schema({
	name: { type: String, unique: true, index: true },
	tel: String,
	mobile: String,
	email: String,
	website: String,
	address: String,
	twitter: String,
	facebook: String,
	linkedin: String,
	img: String,
	about: String,
	user_id: { type: Objectid, ref: 'User' },
	sage_uid: Number,
	vat: String,
	location_id: { type: Objectid, ref: 'Location' },
	space_total: { type: Number, default: 0 }, //Debit + Credit
	stuff_total: { type: Number, default: 0 }, //Debit + Credit
	membership: { type: Objectid, ref: 'Membership' },
	space_credits_per_month_override: Number,
	stuff_credits_per_month_override: Number,
	bandwidth_per_month_override: Number,
	cost_per_month_override: Number,
	_owner_id: Objectid,
	_deleted: { type: Boolean, default: false, index: true },
});

OrganisationSchema.set("_perms", {
	admin: "crud",
	owner: "crud",
	user: "cr",
	all: "r"
});

module.exports = mongoose.model('Organisation', OrganisationSchema);<|endoftext|>


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

  angular.module('app.states')
    .run(appRun);

  /** @ngInject */
  function appRun(routerHelper) {
    routerHelper.configureStates(getStates());
  }

  function getStates() {
    return {
      'blueprints.list': {
        url: '', // No url, this state is the index of projects
        templateUrl: 'app/states/blueprints/list/list.html',
        controller: StateController,
        controllerAs: 'vm',
        title: N_('Blueprint List'),
        resolve: {
          blueprints: resolveBlueprints
        }
      }
    };
  }

  /** @ngInject */
  function resolveBlueprints(CollectionsApi) {
    var options = {
      mock: true,
      expand: 'resources'
    };

    return CollectionsApi.query('blueprints', options);
  }

  /** @ngInject */
  function StateController($state, blueprints, BlueprintsState, BlueprintDetailsModal, BlueprintDeleteModal, Notifications, $filter,
                           $rootScope, Language) {
    /* jshint validthis: true */
    var vm = this;

    vm.title = __('Blueprint List');

    // For mock RESTFul api operations
    if (!BlueprintsState.getBlueprints()) {
      BlueprintsState.setBlueprints(blueprints.resources);
    }

    vm.blueprints = BlueprintsState.getBlueprints();

    /* This notification 'splice' code doesn't work.  Splice needs a third argument, the items to splice in
     * Not sure what this code is trying to accomplish, but it exists in login, request list, & services list
    if (angular.isDefined($rootScope.notifications) && $rootScope.notifications.data.length > 0) {
      $rootScope.notifications.data.splice(0, $rootScope.notifications.data.length);
    }
    */

    vm.blueprintsList = angular.copy(vm.blueprints);

    vm.listConfig = {
      selectItems: false,
      showSelectBox: true,
      onClick: handleClick,
      onCheckBoxChange: handleCheckBoxChange
    };

    vm.actionButtons = [
      {
        name: __('Publish'),
        title: __('Publish Blueprint'),
        actionFn: publishBlueprint
      }
    ];

    vm.enableButtonForItemFn = function(action, item) {
      if (action.name === __('Publish')) {
        if (item.num_nodes > 0 && !item.published) {
          return true;
        } else {
          return false;
        }
      }
    };

    vm.menuActions = [
      {
        name: __('Edit'),
        title: __('Edit Blueprint'),
        actionFn: editBlueprint
      },
      {
        name: __('Duplicate'),
        title: __('Duplicate Blueprint'),
        actionFn: duplicateBlueprint
      },
      {
        name: __('Delete'),
        title: __('Delete Blueprint'),
        actionFn: deleteBlueprint
      }
    ];

    vm.toolbarConfig = {
      filterConfig: {
        fields: [
          {
            id: 'name',
            title: __('Name'),
            placeholder: __('Filter by Name'),
            filterType: 'text'
          },
          {
            id: 'visibility',
            title: __('Visibility'),
            placeholder: __('Filter by Visibility'),
            filterType: 'text'
          },
          {
            id: 'catalog',
            title: __('Catalog'),
            placeholder: __('Filter by Catalog'),
            filterType: 'text'
          }
        ],
        resultsCount: vm.blueprintsList.length,
        appliedFilters: BlueprintsState.getFilters(),
        onFilterChange: filterChange
      },
      sortConfig: {
        fields: [
          {
            id: 'name',
            title: __('Name'),
            sortType: 'alpha'
          },
          {
            id: 'last_modified',
            title: __('Last Modified'),
            sortType: 'numeric'
          },
          {
            id: 'num_nodes',
            title: __('Items'),
            sortType: 'numeric'
          },
          {
            id: 'visibility',
            title: __('Visibility'),
            sortType: 'alpha'
          },
          {
            id: 'catalog',
            title: __('Catalog'),
            sortType: 'alpha'
          }
        ],
        onSortChange: sortChange,
        isAscending: BlueprintsState.getSort().isAscending,
        currentField: BlueprintsState.getSort().currentField
      },
      actionsConfig: {
        primaryActions: [
          {
            name: __('Create'),
            title: __('Create a new Blueprint'),
            actionFn: createBlueprint
          },
          {
            name: __('Delete'),
            title: __('Delete Blueprint'),
            actionFn: deleteBlueprints,
            isDisabled: (BlueprintsState.getSelectedBlueprints().length === 0)
          }
        ]
      }
    };

    function createBlueprint(action) {
      $state.go('blueprints.designer');
    }

    function editBlueprint(action, item) {
      $state.go('blueprints.designer', {blueprintId: item.id});
    }

    function duplicateBlueprint(action, item) {
      BlueprintsState.duplicateBlueprint(item);
      $state.go($state.current, {}, {reload: true});
    }

    function publishBlueprint(action, item) {
      if (item.num_nodes === 0) {
        Notifications.error(__('Cannot publish a blueprint with no service items.'), false, false);

        // Make sure all notifications disappear after delay
        if (angular.isDefined($rootScope.notifications) && $rootScope.notifications.data.length > 0) {
          for (var i = 0; i < $rootScope.notifications.data.length; i++) {
            $rootScope.notifications.data[i].isPersistent = false;
          }
        }
      } else {
        BlueprintDetailsModal.showModal('publish', item);
      }
    }

    function deleteBlueprint(action, item) {
      BlueprintDeleteModal.showModal([item]);
    }

    function deleteBlueprints(action) {
      BlueprintDeleteModal.showModal(BlueprintsState.getSelectedBlueprints());
    }

    function canDeleteBlueprints() {
      return BlueprintsState.getSelectedBlueprints().length > 0;
    }

    function updateActionForItemFn(action, item) {
      return (action.name === 'Publish') && (item.published !== null);
    }

    /* Apply the filtering to the data list */
    filterChange(BlueprintsState.getFilters());

    function handleClick(item, e) {
      $state.go('blueprints.designer', {blueprintId: item.id});
    }

    function handleCheckBoxChange(item, e) {
      BlueprintsState.handleSelectionChange(item);
      vm.toolbarConfig.actionsConfig.primaryActions[1].isDisabled = !canDeleteBlueprints();
    }

    function sortChange(sortId, isAscending) {
      vm.blueprintsList.sort(compareFn);

      /* Keep track of the current sorting state */
      BlueprintsState.setSort(sortId, vm.toolbarConfig.sortConfig.isAscending);
    }

    function compareFn(item1, item2) {
      var compValue = 0;
      if (vm.toolbarConfig.sortConfig.currentField.id === 'name') {
        compValue = item1.name.localeCompare(item2.name);
      } else if (vm.toolbarConfig.sortConfig.currentField.id === 'last_modified') {
        compValue = new Date(item1.last_modified) - new Date(item2.last_modified);
      } else if (vm.toolbarConfig.sortConfig.currentField.id === 'num_nodes') {
        compValue = item1.num_nodes - item2.num_nodes;
      } else if (vm.toolbarConfig.sortConfig.currentField.id === 'visibility') {
        compValue = item1.visibility.name.localeCompare(item2.visibility.name);
      } else if (vm.toolbarConfig.sortConfig.currentField.id === 'catalog') {
        if (!item1.catalog) {
          compValue = -1;
        } else if (!item2.catalog) {
          compValue = 1;
        } else {
          compValue = item1.catalog.name.localeCompare(item2.catalog.name);
        }
      }

      if (!vm.toolbarConfig.sortConfig.isAscending) {
        compValue = compValue * -1;
      }

      return compValue;
    }

    function filterChange(filters) {
      applyFilters(filters);
      vm.toolbarConfig.filterConfig.resultsCount = vm.blueprintsList.length;
    }

    function applyFilters(filters) {
      vm.blueprintsList = [];
      if (filters && filters.length > 0) {
        angular.forEach(vm.blueprints, filterChecker);
      } else {
        vm.blueprintsList = vm.blueprints;
      }

      /* Keep track of the current filtering state */
      BlueprintsState.setFilters(filters);

      /* Make sure sorting direction is maintained */
      sortChange(BlueprintsState.getSort().currentField, BlueprintsState.getSort().isAscending);

      function filterChecker(item) {
        if (matchesFilters(item, filters)) {
          vm.blueprintsList.push(item);
        }
      }
    }

    function matchesFilters(item, filters) {
      var matches = true;
      angular.forEach(filters, filterMatcher);

      function filterMatcher(filter) {
        if (!matchesFilter(item, filter)) {
          matches = false;

          return false;
        }
      }

      return matches;
    }

    function matchesFilter(item, filter) {
      if (filter.id === 'name') {
        return item.name.toLowerCase().indexOf(filter.value.toLowerCase()) !== -1;
      } else if (filter.id === 'visibility') {
        return item.visibility.name.toLowerCase().indexOf(filter.value.toLowerCase()) !== -1;
      } else if (filter.id === 'catalog') {
        if (filter.value.toLowerCase() === "unassigned" && !item.catalog) {
          return true;
        } else if (!item.catalog) {
          return false;
        } else {
          return item.catalog.name.toLowerCase().indexOf(filter.value.toLowerCase()) !== -1;
        }
      }

      return false;
    }

    Language.fixState(BlueprintsState, vm.toolbarConfig);
  }
})();
<commit_msg>SSUI Designer: Blueprint List - Updated Catagory filter to select values<commit_after>(function() {
  'use strict';

  angular.module('app.states')
    .run(appRun);

  /** @ngInject */
  function appRun(routerHelper) {
    routerHelper.configureStates(getStates());
  }

  function getStates() {
    return {
      'blueprints.list': {
        url: '', // No url, this state is the index of projects
        templateUrl: 'app/states/blueprints/list/list.html',
        controller: StateController,
        controllerAs: 'vm',
        title: N_('Blueprint List'),
        resolve: {
          blueprints: resolveBlueprints,
          serviceCatalogs: resolveServiceCatalogs
        }
      }
    };
  }

  /** @ngInject */
  function resolveBlueprints(CollectionsApi) {
    var options = {
      mock: true,
      expand: 'resources'
    };

    return CollectionsApi.query('blueprints', options);
  }

  function resolveServiceCatalogs(CollectionsApi) {
    var options = {
      expand: 'resources',
      sort_by: 'name',
      sort_options: 'ignore_case'};

    return CollectionsApi.query('service_catalogs', options);
  }

  /** @ngInject */
  function StateController($state, blueprints, BlueprintsState, serviceCatalogs, BlueprintDetailsModal, BlueprintDeleteModal, Notifications,
                           $rootScope, Language) {
    /* jshint validthis: true */
    var vm = this;
    var categoryNames = [];

    vm.title = __('Blueprint List');

    // For mock RESTFul api operations
    if (!BlueprintsState.getBlueprints()) {
      BlueprintsState.setBlueprints(blueprints.resources);
    }

    vm.blueprints = BlueprintsState.getBlueprints();
    angular.forEach(vm.blueprints, addMockCategoryFilter);

    vm.serviceCatalogs = serviceCatalogs.resources;
    angular.forEach(vm.serviceCatalogs, addCategoryFilter);

    function addMockCategoryFilter(blueprint) {
      if (!blueprint.catalog) {
        if (!categoryNames.includes(__('Unassigned'))) {
          categoryNames.push(__('Unassigned'));
        }
      } else {
        categoryNames.push(blueprint.catalog.name);
      }
    }

    function addCategoryFilter(item) {
      categoryNames.push(item.name);
    }

    /* This notification 'splice' code doesn't work.  Splice needs a third argument, the items to splice in
     * Not sure what this code is trying to accomplish, but it exists in login, request list, & services list
    if (angular.isDefined($rootScope.notifications) && $rootScope.notifications.data.length > 0) {
      $rootScope.notifications.data.splice(0, $rootScope.notifications.data.length);
    }
    */

    vm.blueprintsList = angular.copy(vm.blueprints);

    vm.listConfig = {
      selectItems: false,
      showSelectBox: true,
      onClick: handleClick,
      onCheckBoxChange: handleCheckBoxChange
    };

    vm.actionButtons = [
      {
        name: __('Publish'),
        title: __('Publish Blueprint'),
        actionFn: publishBlueprint
      }
    ];

    vm.enableButtonForItemFn = function(action, item) {
      if (action.name === __('Publish')) {
        if (item.num_nodes > 0 && !item.published) {
          return true;
        } else {
          return false;
        }
      }
    };

    vm.menuActions = [
      {
        name: __('Edit'),
        title: __('Edit Blueprint'),
        actionFn: editBlueprint
      },
      {
        name: __('Duplicate'),
        title: __('Duplicate Blueprint'),
        actionFn: duplicateBlueprint
      },
      {
        name: __('Delete'),
        title: __('Delete Blueprint'),
        actionFn: deleteBlueprint
      }
    ];

    vm.toolbarConfig = {
      filterConfig: {
        fields: [
          {
            id: 'name',
            title: __('Name'),
            placeholder: __('Filter by Name'),
            filterType: 'text'
          },
          {
            id: 'visibility',
            title: __('Visibility'),
            placeholder: __('Filter by Visibility'),
            filterType: 'text'
          },
          {
            id: 'catalog',
            title: __('Catalog'),
            placeholder: __('Filter by Catalog'),
            filterType: 'select',
            filterValues: categoryNames
          }
        ],
        resultsCount: vm.blueprintsList.length,
        appliedFilters: BlueprintsState.getFilters(),
        onFilterChange: filterChange
      },
      sortConfig: {
        fields: [
          {
            id: 'name',
            title: __('Name'),
            sortType: 'alpha'
          },
          {
            id: 'last_modified',
            title: __('Last Modified'),
            sortType: 'numeric'
          },
          {
            id: 'num_nodes',
            title: __('Items'),
            sortType: 'numeric'
          },
          {
            id: 'visibility',
            title: __('Visibility'),
            sortType: 'alpha'
          },
          {
            id: 'catalog',
            title: __('Catalog'),
            sortType: 'alpha'
          }
        ],
        onSortChange: sortChange,
        isAscending: BlueprintsState.getSort().isAscending,
        currentField: BlueprintsState.getSort().currentField
      },
      actionsConfig: {
        primaryActions: [
          {
            name: __('Create'),
            title: __('Create a new Blueprint'),
            actionFn: createBlueprint
          },
          {
            name: __('Delete'),
            title: __('Delete Blueprint'),
            actionFn: deleteBlueprints,
            isDisabled: (BlueprintsState.getSelectedBlueprints().length === 0)
          }
        ]
      }
    };

    function createBlueprint(action) {
      $state.go('blueprints.designer');
    }

    function editBlueprint(action, item) {
      $state.go('blueprints.designer', {blueprintId: item.id});
    }

    function duplicateBlueprint(action, item) {
      BlueprintsState.duplicateBlueprint(item);
      $state.go($state.current, {}, {reload: true});
    }

    function publishBlueprint(action, item) {
      if (item.num_nodes === 0) {
        Notifications.error(__('Cannot publish a blueprint with no service items.'), false, false);

        // Make sure all notifications disappear after delay
        if (angular.isDefined($rootScope.notifications) && $rootScope.notifications.data.length > 0) {
          for (var i = 0; i < $rootScope.notifications.data.length; i++) {
            $rootScope.notifications.data[i].isPersistent = false;
          }
        }
      } else {
        BlueprintDetailsModal.showModal('publish', item);
      }
    }

    function deleteBlueprint(action, item) {
      BlueprintDeleteModal.showModal([item]);
    }

    function deleteBlueprints(action) {
      BlueprintDeleteModal.showModal(BlueprintsState.getSelectedBlueprints());
    }

    function canDeleteBlueprints() {
      return BlueprintsState.getSelectedBlueprints().length > 0;
    }

    function updateActionForItemFn(action, item) {
      return (action.name === 'Publish') && (item.published !== null);
    }

    /* Apply the filtering to the data list */
    filterChange(BlueprintsState.getFilters());

    function handleClick(item, e) {
      $state.go('blueprints.designer', {blueprintId: item.id});
    }

    function handleCheckBoxChange(item, e) {
      BlueprintsState.handleSelectionChange(item);
      vm.toolbarConfig.actionsConfig.primaryActions[1].isDisabled = !canDeleteBlueprints();
    }

    function sortChange(sortId, isAscending) {
      vm.blueprintsList.sort(compareFn);

      /* Keep track of the current sorting state */
      BlueprintsState.setSort(sortId, vm.toolbarConfig.sortConfig.isAscending);
    }

    function compareFn(item1, item2) {
      var compValue = 0;
      if (vm.toolbarConfig.sortConfig.currentField.id === 'name') {
        compValue = item1.name.localeCompare(item2.name);
      } else if (vm.toolbarConfig.sortConfig.currentField.id === 'last_modified') {
        compValue = new Date(item1.last_modified) - new Date(item2.last_modified);
      } else if (vm.toolbarConfig.sortConfig.currentField.id === 'num_nodes') {
        compValue = item1.num_nodes - item2.num_nodes;
      } else if (vm.toolbarConfig.sortConfig.currentField.id === 'visibility') {
        compValue = item1.visibility.name.localeCompare(item2.visibility.name);
      } else if (vm.toolbarConfig.sortConfig.currentField.id === 'catalog') {
        if (!item1.catalog) {
          compValue = -1;
        } else if (!item2.catalog) {
          compValue = 1;
        } else {
          compValue = item1.catalog.name.localeCompare(item2.catalog.name);
        }
      }

      if (!vm.toolbarConfig.sortConfig.isAscending) {
        compValue = compValue * -1;
      }

      return compValue;
    }

    function filterChange(filters) {
      applyFilters(filters);
      vm.toolbarConfig.filterConfig.resultsCount = vm.blueprintsList.length;
    }

    function applyFilters(filters) {
      vm.blueprintsList = [];
      if (filters && filters.length > 0) {
        angular.forEach(vm.blueprints, filterChecker);
      } else {
        vm.blueprintsList = vm.blueprints;
      }

      /* Keep track of the current filtering state */
      BlueprintsState.setFilters(filters);

      /* Make sure sorting direction is maintained */
      sortChange(BlueprintsState.getSort().currentField, BlueprintsState.getSort().isAscending);

      function filterChecker(item) {
        if (matchesFilters(item, filters)) {
          vm.blueprintsList.push(item);
        }
      }
    }

    function matchesFilters(item, filters) {
      var matches = true;
      angular.forEach(filters, filterMatcher);

      function filterMatcher(filter) {
        if (!matchesFilter(item, filter)) {
          matches = false;

          return false;
        }
      }

      return matches;
    }

    function matchesFilter(item, filter) {
      if (filter.id === 'name') {
        return item.name.toLowerCase().indexOf(filter.value.toLowerCase()) !== -1;
      } else if (filter.id === 'visibility') {
        return item.visibility.name.toLowerCase().indexOf(filter.value.toLowerCase()) !== -1;
      } else if (filter.id === 'catalog') {
        if (filter.value.toLowerCase() === "unassigned" && !item.catalog) {
          return true;
        } else if (!item.catalog) {
          return false;
        } else {
          return item.catalog.name.toLowerCase().indexOf(filter.value.toLowerCase()) !== -1;
        }
      }

      return false;
    }

    Language.fixState(BlueprintsState, vm.toolbarConfig);
  }
})();
<|endoftext|>


<commit_before>/*global describe, it, beforeEach, expect, spyOn*/
/*eslint camelcase: 0, no-invalid-this: 0 */

const DrawCard = require('../../../server/game/drawcard.js');

describe('the DrawCard', function() {
    describe('the useStealthToBypass() function', function() {
        function createCard() {
            let card = new DrawCard({}, {});
            spyOn(card, 'canBeBypassedByStealth').and.returnValue(true);
            return card;
        }

        describe('when the card does not have stealth', function() {
            beforeEach(function() {
                this.source = createCard();
                this.target = createCard();
            });

            it('should return false.', function() {
                expect(this.source.useStealthToBypass(this.target)).toBe(false);
            });
        });

        describe('when the card has stealth and the target does not', function() {
            beforeEach(function() {
                this.source = createCard();
                this.source.addKeyword('Stealth');
                this.target = createCard();
            });

            it('should return true.', function() {
                expect(this.source.useStealthToBypass(this.target)).toBe(true);
            });

            it('should mark the target card as being bypassed', function() {
                this.source.useStealthToBypass(this.target);
                expect(this.target.stealth).toBe(true);
            });

            it('should set the stealth target on the source card', function() {
                this.source.useStealthToBypass(this.target);
                expect(this.source.stealthTarget).toBe(this.target);
            });
        });

        describe('when the target cannot be bypassed', function() {
            beforeEach(function() {
                this.source = createCard();
                this.source.addKeyword('Stealth');
                this.target = createCard();
                this.target.canBeBypassedByStealth.and.returnValue(false);
            });

            it('should return false', function() {
                expect(this.source.useStealthToBypass(this.target)).toBe(false);
            });

            it('should not mark the target card as being bypassed', function() {
                this.source.useStealthToBypass(this.target);
                expect(this.target.stealth).toBeFalsy();
            });

            it('should not set the stealth target on the source card', function() {
                this.source.useStealthToBypass(this.target);
                expect(this.source.stealthTarget).toBeUndefined();
            });
        });
    });
});
<commit_msg>Removed unneeded keywords<commit_after><|endoftext|>