<commit_before>import GeometryEdge from "./geometryEdge";
import graphlib from '@dagrejs/graphlib';
import paper from 'paper';

export default class GeometryGraph{
    constructor(){
        //TODO: Do all the initializations here
        this.__nodes = new Map();
        this.__nodecount = 0;
        this.__edgecount = 0;
        this.__edgeData = new Map();

        this.__networkGraph = new graphlib.Graph({directed:false});

    }

    addEdge(start, end, data){
        let startnode = this.findNode(start);
        let endnode = this.findNode(end);

        let edgeobject = new GeometryEdge(startnode, endnode, data.type, String(this.__edgecount++), data);

        this.__edgeData.set(edgeobject.id, edgeobject);

        this.__networkGraph.setEdge(startnode, endnode, edgeobject.id);

    }

    findNode(node) {
        for(let key of this.__nodes.keys()){
            let nodetocheck = this.__nodes.get(key);

            if(GeometryGraph.computeDistance(node, nodetocheck) < 0.000001){
                return key;
            }
        }

        //If it comes to this, then it means that the node does not exist
        let newkey = String(this.__nodecount++);
        this.__nodes.set( newkey , node);

        return newkey;
    }

    generateGeometry() {
        //TODO: Generate Geometry
        console.log("Cycles:", graphlib.alg.findCycles(this.__networkGraph));
        console.log("Edges:", this.__networkGraph.edges());
        console.log("Nodes:", this.__nodes);
        console.log("Edge Data:", this.__edgeData);
        let path = new paper.CompoundPath();

        //graphlib.alg.findCycles(this.__networkGraph);
        let graphcomponents = graphlib.alg.components(this.__networkGraph)
        console.log("Components:", graphcomponents);

        /*
        Step 1 - Iterate through each of the components (disconnected components)
        Step 2 - Draw outline for each of the components
         */

        for (let component of graphcomponents) {
            this.drawComponent(component, path);
        }

        return path;
    }

    drawComponent(component, path) {
        /*
        Step 1 - Take the starting node
        Step 2 - start traversing through the component and start making a path with segments
         */

        console.log("Graph component",component);

        //Get the first item in the component

        // let startnode = this.__nodes.get(component[0]);
        // console.log("startnode", startnode);

        let segments = [];
        let startnode = this.__nodes.get(component[0]);
        let endnode = null;
        console.log("test ?");
        //Get traversal
        let traversal =  graphlib.alg.preorder(this.__networkGraph, component[0]);

        let childpath = new paper.Path();

        for(let i = 0; i< traversal.length; i++ ) {
            let noderef = traversal[i];
            let node = this.__nodes.get(noderef);
            let nextnoderef;
            if((i+1) == traversal.length){
                //Last Node
                nextnoderef = traversal[0];
            }else{
                //All other nodes
                nextnoderef = traversal[i+1];
            }

            //Get the edge
            let edge = this.__getEdge(noderef, nextnoderef);

            console.log("Edge:", edge);
            console.log("Edge Type:", edge.type);
            switch (edge.type) {
                case "LINE":
                    childpath.add(new paper.Point(node.x, node.y));
                    break;
                case "ARC":
                    if(i == 0){
                        //If its the first one we need to add the initial vertex
                        childpath.add(new paper.Point(node.x, node.y));
                    }
                    let nextnode = this.__nodes.get(nextnoderef);
                    let endpoint = new paper.Point(nextnode.x, nextnode.y);
                    let midpoint = this.getARCMidpoint(edge.dxfData);
                    childpath.arcTo(midpoint, endpoint);
                    break;
            }

        }

        path.addChild(childpath);

        // //Generate Lines for everything
        // for(let i = 0; i< traversal.length; i++ ){
        //     let node = this.__nodes.get(traversal[i]);
        //
        //     console.log("Line:", "Start", startnode, "End" , endnode);
        //     //TODO: Draw curve for curves
        //     let line = new paper.Path.Line(new paper.Point(startnode.x, endnode.y), new paper.Point(endnode.x, endnode.y));
        //     childpath.add(line);
        // }
        //
        // startnode = endnode;
        // endnode = this.__nodes.get(component[0]);
        // console.log("Line:", "Start", startnode, "End" , endnode);
        //
        // //Last segment to close everything off
        // childpath.add(new paper.Path.Line(
        //     // new paper.Point(startnode.x, endnode.y),
        //     new paper.Point(endnode.x, endnode.y))
        // );
        //
        // console.log(path);

        //Now join all the segments
        // let joinedpath = null;
        // for(let i = 0; i < segments.length; i++){
        //     if(joinedpath == null){
        //         joinedpath = segments[i];
        //     }
        //     joinedpath.join(segments[i]);
        // }

        // console.log("Joined Path", joinedpath);
        // console.log("Segments:", segments);

        // path.addChild(joinedpath);
    }

    getARCMidpoint(dxfData) {
        console.log("DXF:",dxfData);
        let center = new paper.Point(dxfData.center.x, dxfData.center.y);
        let radius = dxfData.radius;
        let startAngle = dxfData.startAngle;
        let endAngle = dxfData.endAngle; //* 180/Math.PI;
        let midAngle = (startAngle + endAngle)/2;

        let midpoint = new paper.Point(center.x + radius* Math.cos(midAngle), center.y + radius* Math.sin(midAngle));

        return midpoint;
    }

    __getEdge(source, target){
        let edgeref = this.__networkGraph.edge(source, target);
        return this.__edgeData.get(edgeref);
    }

    static computeDistance(node, nodetocheck){
        let sqdist = Math.pow((node.x - nodetocheck.x), 2) + Math.pow((node.y - nodetocheck.y), 2);
        //TODO: check if there is a z component
        return Math.sqrt(sqdist);
    }
}<commit_msg>Fixed issue where arc start point was not being captured in the logic<commit_after>import GeometryEdge from "./geometryEdge";
import graphlib from '@dagrejs/graphlib';
import paper from 'paper';

export default class GeometryGraph{
    constructor(){
        //TODO: Do all the initializations here
        this.__nodes = new Map();
        this.__nodecount = 0;
        this.__edgecount = 0;
        this.__edgeData = new Map();

        this.__networkGraph = new graphlib.Graph({directed:false});

    }

    addEdge(start, end, data){
        let startnode = this.findNode(start);
        let endnode = this.findNode(end);

        let edgeobject = new GeometryEdge(startnode, endnode, data.type, String(this.__edgecount++), data);

        this.__edgeData.set(edgeobject.id, edgeobject);

        this.__networkGraph.setEdge(startnode, endnode, edgeobject.id);

    }

    findNode(node) {
        for(let key of this.__nodes.keys()){
            let nodetocheck = this.__nodes.get(key);

            if(GeometryGraph.computeDistance(node, nodetocheck) < 0.000001){
                return key;
            }
        }

        //If it comes to this, then it means that the node does not exist
        let newkey = String(this.__nodecount++);
        this.__nodes.set( newkey , node);

        return newkey;
    }

    generateGeometry() {
        //TODO: Generate Geometry
        console.log("Cycles:", graphlib.alg.findCycles(this.__networkGraph));
        console.log("Edges:", this.__networkGraph.edges());
        console.log("Nodes:", this.__nodes);
        console.log("Edge Data:", this.__edgeData);
        let path = new paper.CompoundPath();

        //graphlib.alg.findCycles(this.__networkGraph);
        let graphcomponents = graphlib.alg.components(this.__networkGraph)
        console.log("Components:", graphcomponents);

        /*
        Step 1 - Iterate through each of the components (disconnected components)
        Step 2 - Draw outline for each of the components
         */

        for (let component of graphcomponents) {
            this.drawComponent(component, path);
        }

        return path;
    }

    drawComponent(component, path) {
        /*
        Step 1 - Take the starting node
        Step 2 - start traversing through the component and start making a path with segments
         */

        console.log("Graph component",component);

        //Get the first item in the component

        // let startnode = this.__nodes.get(component[0]);
        // console.log("startnode", startnode);

        let segments = [];
        let startnode = this.__nodes.get(component[0]);
        let endnode = null;
        console.log("test ?");
        //Get traversal
        let traversal =  graphlib.alg.preorder(this.__networkGraph, component[0]);

        let childpath = new paper.Path();

        for(let i = 0; i< traversal.length; i++ ) {
            let noderef = traversal[i];
            let node = this.__nodes.get(noderef);
            let nextnoderef;
            if((i+1) == traversal.length){
                //Last Node
                nextnoderef = traversal[0];
            }else{
                //All other nodes
                nextnoderef = traversal[i+1];
            }

            //Get the edge
            let edge = this.__getEdge(noderef, nextnoderef);

            console.log("Edge:", edge);
            console.log("Edge Type:", edge.type);
            switch (edge.type) {
                case "LINE":
                    childpath.add(new paper.Point(node.x, node.y));
                    break;
                case "ARC":
                    childpath.add(new paper.Point(node.x, node.y));
                    let nextnode = this.__nodes.get(nextnoderef);
                    let endpoint = new paper.Point(nextnode.x, nextnode.y);
                    let midpoint = this.getARCMidpoint(edge.dxfData);
                    childpath.arcTo(midpoint, endpoint);
                    break;
            }

        }

        path.addChild(childpath);

        // //Generate Lines for everything
        // for(let i = 0; i< traversal.length; i++ ){
        //     let node = this.__nodes.get(traversal[i]);
        //
        //     console.log("Line:", "Start", startnode, "End" , endnode);
        //     //TODO: Draw curve for curves
        //     let line = new paper.Path.Line(new paper.Point(startnode.x, endnode.y), new paper.Point(endnode.x, endnode.y));
        //     childpath.add(line);
        // }
        //
        // startnode = endnode;
        // endnode = this.__nodes.get(component[0]);
        // console.log("Line:", "Start", startnode, "End" , endnode);
        //
        // //Last segment to close everything off
        // childpath.add(new paper.Path.Line(
        //     // new paper.Point(startnode.x, endnode.y),
        //     new paper.Point(endnode.x, endnode.y))
        // );
        //
        // console.log(path);

        //Now join all the segments
        // let joinedpath = null;
        // for(let i = 0; i < segments.length; i++){
        //     if(joinedpath == null){
        //         joinedpath = segments[i];
        //     }
        //     joinedpath.join(segments[i]);
        // }

        // console.log("Joined Path", joinedpath);
        // console.log("Segments:", segments);

        // path.addChild(joinedpath);
    }

    getARCMidpoint(dxfData) {
        console.log("DXF:",dxfData);
        let center = new paper.Point(dxfData.center.x, dxfData.center.y);
        let radius = dxfData.radius;
        let startAngle = dxfData.startAngle;
        let endAngle = dxfData.endAngle; //* 180/Math.PI;
        let midAngle = (startAngle + endAngle)/2;

        let midpoint = new paper.Point(center.x + radius* Math.cos(midAngle), center.y + radius* Math.sin(midAngle));

        return midpoint;
    }

    __getEdge(source, target){
        let edgeref = this.__networkGraph.edge(source, target);
        return this.__edgeData.get(edgeref);
    }

    static computeDistance(node, nodetocheck){
        let sqdist = Math.pow((node.x - nodetocheck.x), 2) + Math.pow((node.y - nodetocheck.y), 2);
        //TODO: check if there is a z component
        return Math.sqrt(sqdist);
    }
}<|endoftext|>


<commit_before>var menuItems = [
  'fav',
  'rt',
  'rt-now',
  'fav-and-rt',
  'fav-and-rt-now'
];

function installMenuItems() {
  for (let id of menuItems)
  {
    browser.contextMenus.create({
      id: id,
      title: browser.i18n.getMessage('contextMenu.' + id + '.label'),
      contexts: ['page', 'tab', 'link']
    });
  }
}

installMenuItems();

browser.contextMenus.onClicked.addListener(function(aInfo, aTab) {
  let url = aInfo.linkUrl;
  log('procesing url = ' + url);
  switch (aInfo.menuItemId) {
    case 'fav':
      send_dm('fav', url).then(onResponse, onError);
      break;
    case 'rt':
      send_dm('rt', url).then(onResponse, onError);
      break;
    case 'rt-now':
      send_dm('rt!', url).then(onResponse, onError);
      break;
    case 'fav-and-rt':
      send_dm('fr', url).then(onResponse, onError);
      break;
    case 'fav-and-rt-now':
      send_dm('fr!', url).then(onResponse, onError);
      break;
  }
});

function send_dm(...aArgs) {
  return browser.runtime.sendNativeMessage('com.add0n.node', {
    cmd: 'exec',
    command: configs.tweetsh_path,
    arguments: [
      'dm',
      configs.target_account,
      aArgs.join(' ')
    ]
  })
}

function onResponse(aResponse) {
  log('Received: ' + aResponse);
}

function onError(aError) {
  log('Error: ' + aError);
}

<commit_msg>Don't process non-tweet URLs<commit_after>var menuItems = [
  'fav',
  'rt',
  'rt-now',
  'fav-and-rt',
  'fav-and-rt-now'
];

function installMenuItems() {
  for (let id of menuItems)
  {
    browser.contextMenus.create({
      id: id,
      title: browser.i18n.getMessage('contextMenu.' + id + '.label'),
      contexts: ['page', 'tab', 'link']
    });
  }
}

installMenuItems();

browser.contextMenus.onClicked.addListener(function(aInfo, aTab) {
  let url = aInfo.linkUrl || aInfo.pageUrl || aTab.url;
  log('procesing url = ' + url);

  let match = url.match(/^[^:]+:\/\/(?:[^/]*\.)?twitter.com\/(?:[^\/]+|i\/web)\/status\/([\d]+)/);
  if (!match) {
    log('not a tweet');
    return;
  }

  let id = match[1];
  log('processing id = ' + id);

  switch (aInfo.menuItemId) {
    case 'fav':
      send_dm('fav', id).then(onResponse, onError);
      break;
    case 'rt':
      send_dm('rt', id).then(onResponse, onError);
      break;
    case 'rt-now':
      send_dm('rt!', id).then(onResponse, onError);
      break;
    case 'fav-and-rt':
      send_dm('fr', id).then(onResponse, onError);
      break;
    case 'fav-and-rt-now':
      send_dm('fr!', id).then(onResponse, onError);
      break;
  }
});

function send_dm(...aArgs) {
  return browser.runtime.sendNativeMessage('com.add0n.node', {
    cmd: 'exec',
    command: configs.tweetsh_path,
    arguments: [
      'dm',
      configs.target_account,
      aArgs.join(' ')
    ]
  })
}

function onResponse(aResponse) {
  log('Received: ' + aResponse);
}

function onError(aError) {
  log('Error: ' + aError);
}

<|endoftext|>


<commit_before>import React, { Component} from 'react';
import NoteSection         from './NoteSection';
import '../styles/Modes.css';
import app_data            from '../config/data.js';
import chevronLeft         from '../statics/feather/chevron-left.svg';
import chevronRight        from '../statics/feather/chevron-right.svg';
import music               from '../statics/feather/music.svg';
import list                from '../statics/feather/list.svg';

class Modes extends Component {
    constructor(props) {
        super(props);
        this.state = {
            modes:                  app_data.modes,
            mode_to_chromatic:      app_data.mode_to_chromatic,
            sharp_based_chromatic:  app_data.sharp_based_chromatic,
            flat_based_chromatic:   app_data.flat_based_chromatic,
            current_mode: 0,
            current_offset: 0,
            notes_array    : [],
            header_array   : [],
            interval_array : [],
            blurb_array    : []
        };
        this.incrementMode= this.incrementMode.bind(this);
        this.decrementMode= this.decrementMode.bind(this);
        this.changeMode= this.changeMode.bind(this);
        this.changePitch= this.changePitch.bind(this);
    }
    componentWillMount() {
        let header_array   = [];
        let notes_array   = [];
        let interval_array = [];
        let blurb_array    = [];
        let mode_to_chromatic = this.state.mode_to_chromatic;
        let i              = 0;
        for (let mode of this.state.modes) {
            header_array.push(

{mode.name}

            );
            interval_array.push(
                mode.notes
            );
            blurb_array.push(

{mode.blurb}

            );
            notes_array.push(mode.notes.map((note) => {
                return mode_to_chromatic[note];
            }));
        }
        this.setState({
            header_array: header_array,
            interval_array: interval_array,
            notes_array: notes_array,
            blurb_array: blurb_array
        });
    }

    incrementMode() {
        this.setState({
            current_mode: (this.state.current_mode + 1) %7
        });
    }

    decrementMode() {
        this.setState({
            current_mode: (this.state.current_mode + 6) % 7
        });
    }

    changeMode() {
        this.setState({
            current_offset: (this.state.current_offset + 1)
        }, () => {console.log(this.state.current_offset)});
    }
    changePitch() {
        this.setState({
            current_offset: (this.state.current_offset + 11)
        }, () => {console.log(this.state.current_offset)});
    }

    render() {
        return (

                {/* Mode and Blurb */}

                        {this.state.header_array[this.state.current_mode]}
                        {this.state.blurb_array[this.state.current_mode]}

                { /* Notes */ }

                <NoteSection notes={this.state.notes_array[this.state.current_mode]}
                    intervals={this.state.interval_array[this.state.current_mode]}
                    offset={this.state.current_offset}
                    mode_to_chromatic={this.state.mode_to_chromatic}
                    sharp_based_chromatic={this.state.sharp_based_chromatic}
                    flat_based_chromatic={this.state.flat_based_chromatic}
                />

                { /* Buttons */ }

                    <button onClick={this.decrementMode} className="left-btn btn">

                    </button>

                    <button onClick={this.changeMode} className="mode-btn btn" >

                        Choose Mode

                    </button>

                    <button onClick={this.incrementMode} className="right-btn btn">

                    </button>

                    <button onClick={this.changePitch} className="pitch-btn btn">

                        Starting Pitch

                    </button>

        );
    }
}

export default Modes;
<commit_msg>Add support for keypresses<commit_after>import React, { Component} from 'react';
import NoteSection         from './NoteSection';
import '../styles/Modes.css';
import app_data            from '../config/data.js';
import chevronLeft         from '../statics/feather/chevron-left.svg';
import chevronRight        from '../statics/feather/chevron-right.svg';
import music               from '../statics/feather/music.svg';
import list                from '../statics/feather/list.svg';

class Modes extends Component {
    constructor(props) {
        super(props);
        this.state = {
            modes:                  app_data.modes,
            mode_to_chromatic:      app_data.mode_to_chromatic,
            sharp_based_chromatic:  app_data.sharp_based_chromatic,
            flat_based_chromatic:   app_data.flat_based_chromatic,
            current_mode: 0,
            current_offset: 0,
            notes_array    : [],
            header_array   : [],
            interval_array : [],
            blurb_array    : [],
            left_keys:  ['H', 'h', 'j', 'J', 'ArrowLeft', 'ArrowDown', 'Backspace'],
            right_keys:  ['L', 'l', 'k', 'K', 'ArrowRight', 'ArrowUp', 'Space']
        };
        this.incrementMode= this.incrementMode.bind(this);
        this.decrementMode= this.decrementMode.bind(this);
        this.changeMode= this.changeMode.bind(this);
        this.changePitch= this.changePitch.bind(this);
        this.handleKeypress= this.handleKeypress.bind(this);
    }

    componentDidMount() {
        document.addEventListener('keyup', this.handleKeypress);
    }

    componentWillUnmount() {
        document.removeeventlistener('keyup', this.handleKeypress);
    }
    componentWillMount() {
        let header_array   = [];
        let notes_array   = [];
        let interval_array = [];
        let blurb_array    = [];
        let mode_to_chromatic = this.state.mode_to_chromatic;
        let i              = 0;
        for (let mode of this.state.modes) {
            header_array.push(

{mode.name}

            );
            interval_array.push(
                mode.notes
            );
            blurb_array.push(

{mode.blurb}

            );
            notes_array.push(mode.notes.map((note) => {
                return mode_to_chromatic[note];
            }));
        }
        this.setState({
            header_array: header_array,
            interval_array: interval_array,
            notes_array: notes_array,
            blurb_array: blurb_array
        });
    }
    handleKeypress(event) {
        let key = event.key;
        if (this.state.left_keys.indexOf(key) > -1) {
            this.decrementMode();
        }
        else if (this.state.right_keys.indexOf(key) > -1) {
            this.incrementMode();
        }

    }

    incrementMode() {
        this.setState({
            current_mode: (this.state.current_mode + 1) %7
        });
    }

    decrementMode() {
        this.setState({
            current_mode: (this.state.current_mode + 6) % 7
        });
    }

    changeMode() {
        this.setState({
            current_offset: (this.state.current_offset + 1)
        }, () => {console.log(this.state.current_offset)});
    }
    changePitch() {
        this.setState({
            current_offset: (this.state.current_offset + 11)
        }, () => {console.log(this.state.current_offset)});
    }

    render() {
        return (

                {/* Mode and Blurb */}

                        {this.state.header_array[this.state.current_mode]}
                        {this.state.blurb_array[this.state.current_mode]}

                { /* Notes */ }

                <NoteSection notes={this.state.notes_array[this.state.current_mode]}
                    intervals={this.state.interval_array[this.state.current_mode]}
                    offset={this.state.current_offset}
                    mode_to_chromatic={this.state.mode_to_chromatic}
                    sharp_based_chromatic={this.state.sharp_based_chromatic}
                    flat_based_chromatic={this.state.flat_based_chromatic}
                />

                { /* Buttons */ }

                    <button onClick={this.decrementMode} className="left-btn btn">

                    </button>

                    <button onClick={this.changeMode} className="mode-btn btn" >

                        Choose Mode

                    </button>

                    <button onClick={this.incrementMode} className="right-btn btn">

                    </button>

                    <button onClick={this.changePitch} className="pitch-btn btn">

                        Starting Pitch

                    </button>

        );
    }
}

export default Modes;
<|endoftext|>


<commit_before>'use strict';

var resolveProcessingStepFullPath = require('../../utils/resolve-processing-step-full-path')
  , serializeValue                = require('dbjs/_setup/serialize/value')
  , unserializeValue              = require('dbjs/_setup/unserialize/value')
  , capitalize                    = require('es5-ext/string/#/capitalize')
  , db                            = require('../../db')
  , Set                           = require('es6-set')
  , processingStepsMeta           = require('../../processing-steps-meta')
  , uuid                          = require('time-uuid')
  , uniqIdPrefix                  = 'abcdefghiklmnopqrstuvxyz'[Math.floor(Math.random() * 24)];

var getPathSuffix = function () {
	return 'statusHistory/map/' + uniqIdPrefix + uuid();
};

var rejectionItem = function (ownerType, types, value) {
	var reason = {};
	reason.types = typeof types === 'object' ? types : [];
	reason.value = value || '';
	reason.ownerType = ownerType || '';

	return reason;
};

var reasonObject = function (storage, event) {
	var reason      = {},
		path        = event.id.slice(0, event.id.indexOf('status')),
		userStorage = require('mano').dbDriver.getStorage('user'),
		prefix, otherValue;

	if (event.type !== 'direct') return;
	reason.hasOnlySystemicReasons = true;
	reason.rejectionType = unserializeValue(event.data.value);

	//rejectionReasons -> processingStep
	reason.rejectionReasons = [];
	if (reason.rejectionType === 'rejected') {
		reason.hasOnlySystemicReasons = false;
		storage.get(path + 'rejectionReason')(function (data) {
			if (!data || !data.value) return;
			otherValue = unserializeValue(data.value);
		});
		reason.rejectionReasons.push(rejectionItem('processingStep', ['other'], otherValue));
	}

	//rejectionReasons -> data
	storage.get(event.ownerId + '/dataForms/rejectReason')(function (data) {
		if (!data || !data.value) return;
		reason.hasOnlySystemicReasons = false;
		reason.rejectionReasons.push(rejectionItem('data', ['other'], unserializeValue(data.value)));
	});

	//rejectionReasons -> requirementUploads
	storage.getComputed(event.ownerId + '/requirementUploads/applicable')(function (data) {
		if (!data) return;
		var types, applicableRequirementUploads = data.value;
		applicableRequirementUploads.forEach(function (requirementUpload) {
			types = [];
			otherValue = '';
			if (!requirementUpload.hasOwnProperty('key')) return;
			prefix = requirementUpload.key.slice(1);
			storage.get(prefix + '/status')(function (upload) {
				if (!upload || !upload.value || unserializeValue(upload.value) !== 'invalid') return;
				storage.get(prefix + '/rejectReasonTypes*illegible')(function (type) {
					if (!type || !type.value || unserializeValue(type.value) !== true) return;
					types.push('illegible');
				});
				storage.get(prefix + '/rejectReasonTypes*invalid')(function (type) {
					if (!type || !type.value || unserializeValue(type.value) !== true) return;
					types.push('invalid');
				});
				storage.get(prefix + '/rejectReasonTypes*other')(function (type) {
					if (!type || !type.value || unserializeValue(type.value) !== true) return;
					reason.hasOnlySystemicReasons = false;
					types.push('other');
					storage.get(prefix + '/rejectReasonMemo')(function (memo) {
						if (!memo || !memo.value) return;
						otherValue = unserializeValue(memo.value);
					});
				});
				reason.rejectionReasons.push(rejectionItem('requirementUpload', types, otherValue));
			});
		});
	});

	//rejectionReasons -> paymentReceiptUploads
	storage.getComputed(event.ownerId + '/paymentReceiptUploads/applicable')(function (data) {
		if (!data) return;
		var types, applicablePaymentReceiptUploads = data.value;
		applicablePaymentReceiptUploads.forEach(function (paymentReceiptUpload) {
			types = [];
			otherValue = '';
			if (!paymentReceiptUpload.hasOwnProperty('key')) return;
			prefix = paymentReceiptUpload.key.slice(1);
			storage.get(prefix + '/status')(function (upload) {
				if (!upload || !upload.value || unserializeValue(upload.value) !== 'invalid') return;
				reason.hasOnlySystemicReasons = false;
				types.push('other');
				storage.get(prefix + '/rejectReasonMemo')(
					function (rejectReasonMemo) {
						if (!rejectReasonMemo || !rejectReasonMemo.value) return;
						otherValue = unserializeValue(rejectReasonMemo.value);
					}
				);
				reason.rejectionReasons.push(rejectionItem('paymentReceipt', types, otherValue));
			});
		});
	});

	//service
	reason.service = {};
	reason.service.type = capitalize.call(storage.name);
	reason.service.id = event.ownerId;
	storage.getComputed(event.ownerId + '/businessName')(function (data) {
		if (!data || !data.value) return;
		reason.service.businessName = unserializeValue(data.value);
	});

	//operator
	reason.operator = {};
	storage.get(path + 'processor')(function (data) {
		if (!data || !data.value) return;
		reason.operator.id = data.value.slice(1);
		userStorage.getComputed(reason.operator.id + '/fullName')(function (data) {
			if (!data || !data.value) return;
			reason.operator.name = unserializeValue(data.value);
		});
	});

	//processingStep
	reason.processingStep = {};
	reason.processingStep.path = '/' + event.path.slice(0, event.path.indexOf('status') - 1);
	reason.processingStep.label = capitalize.call(reason.processingStep.path.slice(
		reason.processingStep.path.lastIndexOf('/') + 1
	));
	reason.date = Math.round(event.data.stamp / 1000);

	return reason;
};

var storeLog = function (storage, logPath/*, options */) {
	var options = Object(arguments[2]);
	return function (event) {
		var status, oldStatus, resolvedPath, logPathResolved;
		logPathResolved = logPath ? logPath + '/' + getPathSuffix() : getPathSuffix();
		if (event.type === 'direct' && logPathResolved.startsWith('processingSteps')) {
			console.log(JSON.stringify(reasonObject(storage, event)));
		}
		if (event.type !== 'computed') return;
		// We don't want to save null, as status is cardinalProperty of nested map and
		// needs to be set in order to avoid inconsistency with in memory engine
		status    = unserializeValue(event.data.value) || '';
		oldStatus = (event.old && unserializeValue(event.old.value)) || '';

		// We ignore such cases, they may happen when direct overwrites computed
		if (status === oldStatus) return;
		if (options.processorPath) {
			storage.get(event.ownerId + '/' + options.processorPath)(function (data) {
				if (data && data.value[0] === '7') {
					resolvedPath = event.ownerId + '/' + logPathResolved + '/processor';
					return storage.store(resolvedPath, data.value);
				}
			}).done();
		}
		resolvedPath = event.ownerId + '/' + logPathResolved + '/status';
		storage.store(resolvedPath, serializeValue(status)).done();
	};
};

module.exports = function () {
	var allStorages = new Set(), driver;
	// Cannot be initialized before call
	driver = require('mano').dbDriver;
	Object.keys(processingStepsMeta).forEach(function (stepMetaKey) {
		var stepPath, storages;
		stepPath = 'processingSteps/map/' + resolveProcessingStepFullPath(stepMetaKey);
		storages = processingStepsMeta[stepMetaKey]._services;
		if (!storages) throw new Error("Storages must be set");
		storages = storages.map(function (storageName) {
			return driver.getStorage('businessProcess' + capitalize.call(storageName));
		});
		storages.forEach(function (storage) {
			allStorages.add(storage);
			storage.on('key:' + stepPath + '/status',
				storeLog(storage, stepPath, { processorPath: stepPath + '/processor' })
				);
		});
	});
	allStorages.forEach(function (storage) {
		storage.on('key:status', storeLog(storage));
		db[capitalize.call(storage.name)].prototype.certificates.map.forEach(function (cert) {
			var certificatePath = 'certificates/map/' + cert.key;
			storage.on('key:' + certificatePath + '/status',
				storeLog(storage, certificatePath));
		});
	});
};
<commit_msg>modified status-history-logger to query data from memoryDb instead of storage and added error handling for it<commit_after>'use strict';

var resolveProcessingStepFullPath = require('../../utils/resolve-processing-step-full-path')
  , serializeValue                = require('dbjs/_setup/serialize/value')
  , unserializeValue              = require('dbjs/_setup/unserialize/value')
  , capitalize                    = require('es5-ext/string/#/capitalize')
  , db                            = require('../../db')
  , Set                           = require('es6-set')
  , processingStepsMeta           = require('../../processing-steps-meta')
  , uuid                          = require('time-uuid')
  , uniqIdPrefix                  = 'abcdefghiklmnopqrstuvxyz'[Math.floor(Math.random() * 24)]
  , queryMemoryDb                 = require('mano').queryMemoryDb;

var getPathSuffix = function () {
	return 'statusHistory/map/' + uniqIdPrefix + uuid();
};

var storeLog = function (storage, logPath/*, options */) {
	var options = Object(arguments[2]);
	return function (event) {
		var status, oldStatus, resolvedPath, logPathResolved;
		logPathResolved = logPath ? logPath + '/' + getPathSuffix() : getPathSuffix();

		if (event.type !== 'computed') return;
		// We don't want to save null, as status is cardinalProperty of nested map and
		// needs to be set in order to avoid inconsistency with in memory engine
		status    = unserializeValue(event.data.value) || '';
		oldStatus = (event.old && unserializeValue(event.old.value)) || '';

		// We ignore such cases, they may happen when direct overwrites computed
		if (status === oldStatus) return;
		if (options.processorPath) {
			storage.get(event.ownerId + '/' + options.processorPath)(function (data) {
				if (data && data.value[0] === '7') {
					resolvedPath = event.ownerId + '/' + logPathResolved + '/processor';
					return storage.store(resolvedPath, data.value);
				}
			}).done();
		}
		resolvedPath = event.ownerId + '/' + logPathResolved + '/status';
		storage.store(resolvedPath, serializeValue(status)).done();
	};
};

var saveRejectionReason = function (event) {
	var status;
	if (event.type !== 'direct') return;
	if (!event.path.startsWith('processingSteps')) return;
	status = unserializeValue(event.data.value);
	if (status !== 'rejected' && status !== 'sentBack') return;

	return queryMemoryDb([event.ownerId], 'businessProcessRejectionReasons', {
		businessProcessId: event.ownerId
	}).done(function (reasonObject) {
		//TODO here should be added logic for saving the reasonObject
		console.log(JSON.stringify(reasonObject));
	}, function (err) {
		console.error(err);
	});
};

module.exports = function () {
	var allStorages = new Set(), driver;
	// Cannot be initialized before call
	driver = require('mano').dbDriver;
	Object.keys(processingStepsMeta).forEach(function (stepMetaKey) {
		var stepPath, storages;
		stepPath = 'processingSteps/map/' + resolveProcessingStepFullPath(stepMetaKey);
		storages = processingStepsMeta[stepMetaKey]._services;
		if (!storages) throw new Error("Storages must be set");
		storages = storages.map(function (storageName) {
			return driver.getStorage('businessProcess' + capitalize.call(storageName));
		});
		storages.forEach(function (storage) {
			allStorages.add(storage);
			storage.on('key:' + stepPath + '/status', function (event) {
				storeLog(storage, stepPath, { processorPath: stepPath + '/processor' })(event);
				saveRejectionReason(event);
			});
		});
	});

	allStorages.forEach(function (storage) {
		storage.on('key:status', storeLog(storage));
		db[capitalize.call(storage.name)].prototype.certificates.map.forEach(function (cert) {
			var certificatePath = 'certificates/map/' + cert.key;
			storage.on('key:' + certificatePath + '/status',
				storeLog(storage, certificatePath));//
		});
	});
};
<|endoftext|>


<commit_before>define([
    "dojo/Evented",
    "dojo/_base/declare",
    "dojo/_base/lang",
    "dojo/has",
    "esri/kernel",
    "dijit/_WidgetBase",
    "dijit/a11yclick",
    "dijit/_TemplatedMixin",
    "dojo/on",
    "dojo/Deferred",
    // load template
    "dojo/text!zesri/dijit/templates/LocateButton.html",
    "dojo/i18n!zesri/nls/jsapi",
    "dojo/dom-class",
    "dojo/dom-style",
    "esri/geometry/webMercatorUtils",
    "esri/geometry/Point",
    "esri/SpatialReference",
    "esri/graphic",
    "esri/symbols/PictureMarkerSymbol",
    "esri/layers/GraphicsLayer"
],
function (
    Evented,
    declare,
    lang,
    has, esriNS,
    _WidgetBase, a11yclick, _TemplatedMixin,
    on,
    Deferred,
    dijitTemplate, i18n,
    domClass, domStyle,
    webMercatorUtils, Point, SpatialReference,
    Graphic, PictureMarkerSymbol,
    GraphicsLayer
) {
    var Widget = declare([_WidgetBase, _TemplatedMixin, Evented], {
        declaredClass: "esri.dijit.LocateButton",
        templateString: dijitTemplate,
        options: {
            theme: "LocateButton",
            map: null,
            visible: true,
            highlightLocation: true,
            symbol: new PictureMarkerSymbol(require.toUrl("esri/dijit") + '/images/blue-dot.png', 21, 21),
            infoTemplate: null,
            scale: null,
            geolocationOptions: {
                maximumAge: 0,
                timeout: 15000,
                enableHighAccuracy: true
            }
        },
        // lifecycle: 1
        constructor: function(options, srcRefNode) {
            // mix in settings and defaults
            var defaults = lang.mixin({}, this.options, options);
            // widget node
            this.domNode = srcRefNode;
            this._i18n = i18n;
            if (!navigator.geolocation) {
                defaults.visible = false;
            }
            // properties
            this.set("map", defaults.map);
            this.set("theme", defaults.theme);
            this.set("visible", defaults.visible);
            this.set("scale", defaults.scale);
            this.set("highlightLocation", defaults.highlightLocation);
            this.set("symbol", defaults.symbol);
            this.set("infoTemplate", defaults.infoTemplate);
            this.set("geolocationOptions", defaults.geolocationOptions);
            // listeners
            this.watch("theme", this._updateThemeWatch);
            this.watch("visible", this._visible);
            // classes
            this._css = {
                container: "locateContainer",
                locate: "zoomLocateButton",
                loading: "loading"
            };
        },
        // bind listener for button to action
        postCreate: function() {
            this.inherited(arguments);
            this.own(
                on(this._locateNode, a11yclick, lang.hitch(this, this.locate))
            );
        },
        // start widget. called by user
        startup: function() {
            // map not defined
            if (!this.map) {
                this.destroy();
                console.log('LocateButton::map required');
            }
            this._graphics = new GraphicsLayer();
            this.map.addLayer(this._graphics);
            // when map is loaded
            if (this.map.loaded) {
                this._init();
            } else {
                on(this.map, "load", lang.hitch(this, function() {
                    this._init();
                }));
            }
        },
        // connections/subscriptions will be cleaned up during the destroy() lifecycle phase
        destroy: function() {
            this.inherited(arguments);
        },
        /* ---------------- */
        /* Public Events */
        /* ---------------- */
        // locate
        // load
        /* ---------------- */
        /* Public Functions */
        /* ---------------- */
        clear: function(){
            this._graphics.clear();
        },
        locate: function() {
            var def = new Deferred();
            // add loading class
            this._showLoading();
            // geolocation support
            if (navigator.geolocation) {
                // get location
                navigator.geolocation.getCurrentPosition(lang.hitch(this, function(position) {
                    // position returned
                    if (position) {
                        // point info
                        var latitude = position.coords.latitude;
                        var longitude = position.coords.longitude;
                        // scale info
                        var scale = this.get("scale") || position.coords.accuracy || 50000;
                        // set point
                        var pt = webMercatorUtils.geographicToWebMercator(new Point(longitude, latitude, new SpatialReference(4326)));
                        if(pt){
                            // set scale
                            this.map.setScale(scale);
                            // center on point
                            this.map.centerAt(pt).then(lang.hitch(this, function(){
                                // highlight enabled
                                if(this.get("highlightLocation")){
                                    this.clear();
                                }
                                // graphic attributes
                                var attributes = {
                                    position: position
                                };
                                // create graphic
                                var graphic = new Graphic(pt, this.get("symbol"), attributes, this.get("infoTemplate"));
                                // highlight enabled
                                if(this.get("highlightLocation")){
                                    this._graphics.add(graphic);
                                }
                                // hide loading class
                                this._hideLoading();
                                // set event
                                var locateEvt = {graphic: graphic, scale: scale, position: position};
                                this.emit("locate", locateEvt);
                                def.resolve(locateEvt);
                            }), lang.hitch(this, function(error){
                                def.reject(error.message);
                            });
                        }
                        else{
                            // remove loading class
                            this._hideLoading();
                            def.reject('LocateButton::Invalid point');
                            console.log('LocateButton::Invalid point');
                        }
                    }
                    else{
                        // remove loading class
                        this._hideLoading();
                        console.log('LocateButton::Invalid position');
                        def.reject('LocateButton::Invalid position');
                    }
                }), lang.hitch(this, function(err) {
                    // remove loading class
                    this._hideLoading();
                    var errorMessage = 'LocateButton::' + err.code + ":" + err.message;
                    console.log(errorMessage);
                    def.reject(errorMessage);
                }), this.get('geolocationOptions'));
            }
            else{
                this._hideLoading();
                console.log('LocateButton::geolocation unsupported');
                def.reject('LocateButton::geolocation unsupported');
            }
            return def.promise;
        },
        show: function(){
            this.set("visible", true);
        },
        hide: function(){
            this.set("visible", false);
        },
        /* ---------------- */
        /* Private Functions */
        /* ---------------- */
        _showLoading: function(){
            domClass.add(this._locateNode, this._css.loading);
        },
        _hideLoading: function(){
            domClass.remove(this._locateNode, this._css.loading);
        },
        _init: function() {
            this._visible();
            this.set("loaded", true);
            this.emit("load", {});
        },
        _updateThemeWatch: function(attr, oldVal, newVal) {
            domClass.remove(this.domNode, oldVal);
            domClass.add(this.domNode, newVal);
        },
        _visible: function(){
            if(this.get("visible")){
                domStyle.set(this.domNode, 'display', 'block');
            }
            else{
                domStyle.set(this.domNode, 'display', 'none');
            }
        }
    });
    if (has("extend-esri")) {
        lang.setObject("dijit.LocateButton", Widget, esriNS);
    }
    return Widget;
});
<commit_msg>no message<commit_after>define([
    "dojo/Evented",
    "dojo/_base/declare",
    "dojo/_base/lang",
    "dojo/has",
    "esri/kernel",
    "dijit/_WidgetBase",
    "dijit/a11yclick",
    "dijit/_TemplatedMixin",
    "dojo/on",
    "dojo/Deferred",
    // load template
    "dojo/text!zesri/dijit/templates/LocateButton.html",
    "dojo/i18n!zesri/nls/jsapi",
    "dojo/dom-class",
    "dojo/dom-style",
    "esri/geometry/webMercatorUtils",
    "esri/geometry/Point",
    "esri/SpatialReference",
    "esri/graphic",
    "esri/symbols/PictureMarkerSymbol",
    "esri/layers/GraphicsLayer"
],
function (
    Evented,
    declare,
    lang,
    has, esriNS,
    _WidgetBase, a11yclick, _TemplatedMixin,
    on,
    Deferred,
    dijitTemplate, i18n,
    domClass, domStyle,
    webMercatorUtils, Point, SpatialReference,
    Graphic, PictureMarkerSymbol,
    GraphicsLayer
) {
    var Widget = declare([_WidgetBase, _TemplatedMixin, Evented], {
        declaredClass: "esri.dijit.LocateButton",
        templateString: dijitTemplate,
        options: {
            theme: "LocateButton",
            map: null,
            visible: true,
            highlightLocation: true,
            symbol: new PictureMarkerSymbol(require.toUrl("esri/dijit") + '/images/blue-dot.png', 21, 21),
            infoTemplate: null,
            scale: null,
            geolocationOptions: {
                maximumAge: 0,
                timeout: 15000,
                enableHighAccuracy: true
            }
        },
        // lifecycle: 1
        constructor: function(options, srcRefNode) {
            // mix in settings and defaults
            var defaults = lang.mixin({}, this.options, options);
            // widget node
            this.domNode = srcRefNode;
            this._i18n = i18n;
            if (!navigator.geolocation) {
                defaults.visible = false;
            }
            // properties
            this.set("map", defaults.map);
            this.set("theme", defaults.theme);
            this.set("visible", defaults.visible);
            this.set("scale", defaults.scale);
            this.set("highlightLocation", defaults.highlightLocation);
            this.set("symbol", defaults.symbol);
            this.set("infoTemplate", defaults.infoTemplate);
            this.set("geolocationOptions", defaults.geolocationOptions);
            // listeners
            this.watch("theme", this._updateThemeWatch);
            this.watch("visible", this._visible);
            // classes
            this._css = {
                container: "locateContainer",
                locate: "zoomLocateButton",
                loading: "loading"
            };
        },
        // bind listener for button to action
        postCreate: function() {
            this.inherited(arguments);
            this.own(
                on(this._locateNode, a11yclick, lang.hitch(this, this.locate))
            );
        },
        // start widget. called by user
        startup: function() {
            // map not defined
            if (!this.map) {
                this.destroy();
                console.log('LocateButton::map required');
            }
            this._graphics = new GraphicsLayer();
            this.map.addLayer(this._graphics);
            // when map is loaded
            if (this.map.loaded) {
                this._init();
            } else {
                on(this.map, "load", lang.hitch(this, function() {
                    this._init();
                }));
            }
        },
        // connections/subscriptions will be cleaned up during the destroy() lifecycle phase
        destroy: function() {
            this.inherited(arguments);
        },
        /* ---------------- */
        /* Public Events */
        /* ---------------- */
        // locate
        // load
        /* ---------------- */
        /* Public Functions */
        /* ---------------- */
        clear: function(){
            this._graphics.clear();
        },
        locate: function() {
            var def = new Deferred();
            // add loading class
            this._showLoading();
            // geolocation support
            if (navigator.geolocation) {
                // get location
                navigator.geolocation.getCurrentPosition(lang.hitch(this, function(position) {
                    // position returned
                    if (position) {
                        // point info
                        var latitude = position.coords.latitude;
                        var longitude = position.coords.longitude;
                        // scale info
                        var scale = this.get("scale") || position.coords.accuracy || 50000;
                        // set point
                        var pt = webMercatorUtils.geographicToWebMercator(new Point(longitude, latitude, new SpatialReference(4326)));
                        if(pt){
                            // set scale
                            this.map.setScale(scale);
                            // center on point
                            this.map.centerAt(pt).then(lang.hitch(this, function(){
                                // highlight enabled
                                if(this.get("highlightLocation")){
                                    this.clear();
                                }
                                // graphic attributes
                                var attributes = {
                                    position: position
                                };
                                // create graphic
                                var graphic = new Graphic(pt, this.get("symbol"), attributes, this.get("infoTemplate"));
                                // highlight enabled
                                if(this.get("highlightLocation")){
                                    this._graphics.add(graphic);
                                }
                                // hide loading class
                                this._hideLoading();
                                // set event
                                var locateEvt = {graphic: graphic, scale: scale, position: position};
                                this.emit("locate", locateEvt);
                                def.resolve(locateEvt);
                            }), lang.hitch(this, function(error){
                                def.reject(error.message);
                            }));
                        }
                        else{
                            // remove loading class
                            this._hideLoading();
                            def.reject('LocateButton::Invalid point');
                            console.log('LocateButton::Invalid point');
                        }
                    }
                    else{
                        // remove loading class
                        this._hideLoading();
                        console.log('LocateButton::Invalid position');
                        def.reject('LocateButton::Invalid position');
                    }
                }), lang.hitch(this, function(err) {
                    // remove loading class
                    this._hideLoading();
                    var errorMessage = 'LocateButton::' + err.code + ":" + err.message;
                    console.log(errorMessage);
                    def.reject(errorMessage);
                }), this.get('geolocationOptions'));
            }
            else{
                this._hideLoading();
                console.log('LocateButton::geolocation unsupported');
                def.reject('LocateButton::geolocation unsupported');
            }
            return def.promise;
        },
        show: function(){
            this.set("visible", true);
        },
        hide: function(){
            this.set("visible", false);
        },
        /* ---------------- */
        /* Private Functions */
        /* ---------------- */
        _showLoading: function(){
            domClass.add(this._locateNode, this._css.loading);
        },
        _hideLoading: function(){
            domClass.remove(this._locateNode, this._css.loading);
        },
        _init: function() {
            this._visible();
            this.set("loaded", true);
            this.emit("load", {});
        },
        _updateThemeWatch: function(attr, oldVal, newVal) {
            domClass.remove(this.domNode, oldVal);
            domClass.add(this.domNode, newVal);
        },
        _visible: function(){
            if(this.get("visible")){
                domStyle.set(this.domNode, 'display', 'block');
            }
            else{
                domStyle.set(this.domNode, 'display', 'none');
            }
        }
    });
    if (has("extend-esri")) {
        lang.setObject("dijit.LocateButton", Widget, esriNS);
    }
    return Widget;
});
<|endoftext|>


<commit_before>/** get entity instance(s) from the datastore by key(s) */
  // if the entity is in the cache, return it
  // get the model of the entity using the key
  // construct the SQL statement
  // create an empty entity object
  // execute the statment asyc
  // collect results, handle errors, construct setters and getters, put into
  // the cache and return the entity to the callback, all within a closure

/** create an new entity instance by class */
  // get the model of the entity using the key
  // for each property in the model:
    // construct setters and getters
    // if required properties are not passed; raise exception
    // put into the cache and return the entity to the caller

/** construct an SQL select statement */
  // start the statement string
  // build each property string
  // append the "FROM tablename" clause
  // build and append required JOIN clauses

/** Create and store a transaction */
  // For each entity in the cache:
    // if the updated attribute is true:
      // create and normalize operations on the entity
      // append each operation to the operations list
  // if there are no items in the operations list, return false;
  // create a new thread
    // create and store the transaction locally
    // return the normalized transaction to the callback

/** create a transaction and store locally with the given operation list */
  // create an SQL statement from each operation type
  // start an SQLite transaction
  // for each entity in the transcation content:
    // assert that the entity does not already exist
    // for each operation:
      // if update operation:
        // if 1 to 1 relationship; add change to the update statement
        // if 1 to many [??? or many to many]; create and execute update
      // if remove operation:
        // if 1 to 1 relationship; add null change to the update statement
        // if 1 to many or many to many; create and execute delete
      // if append operation:
        // if 1 to 1 relationship; add change to the insert statement
        // if 1 to many or many to many; create and execute insert
  // create the SQL transaction record statement
  // bind the parameters, setting state to 1
  // insert the transaction record
  // commit the SQLite transaction

/** Entity */
  // init stored property value dict
  // init the key object

/** Key */
  // init the realm, kind, and uri
<commit_msg>2nd draft of db module.<commit_after>let EXPORTED_SYMBOLS = ["db"];

const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;

Cu.import("resource://crownconstruction/modules/lib.js");
Cu.import("resource://crownconstruction/modules/toolkit.js");
Cu.import("resource://crownconstruction/modules/log.js");
Cu.import("resource://crownconstruction/modules/configs.js");
Cu.import("resource://crownconstruction/modules/model.js");

/** Entity */
function Entity(key, props)
{
  this.key = function Ent_key() {
    return key;
  };
  this.persistedProperties = function Ent_pp() {
    return props;
  };
}

/** Key */
function Key()
{
  let parts = arguments.length = 1 ? arguments[0].split(" ") ? arguments;
  this.realm = parts[0];
  this.class = model.getClassForKind(parts[1]);
  this.kind = parts[1];
  this.uri = parts[2];
}

/**
 * @constructor
 * Create a Transaction object.
 */
function Transaction(user, message, content)
{
  this.uid = getUUID();
  this.seq = new Date().getTime();
  this.datetime = getUTCDateTime();
  this.message = message;
  this.user = user;
  this.content = content;
}

let db = {};
db.connection = null;
db.logger = null;
db.cache = {};
db.updates = [];
db.Entity = Entity;
db.Key = Key;
db.Transaction = Transaction;

let _burning = false;

db.launch = function DB_launch()
{
  if(_burning)
    return;

  db.logger = log.getLogger("db");
  db.connection = db.getConnection();

  _burning = true;
};

/** create an new entity instance by class */
db.createNewEntity = function DB_createNewEntity(kind)
{
  let props = model.getProperties(kind);
  assert(props, "A model for kind '"+ kind +"' could not be found.");
  if(!props) {
    throw new TypeError("A model for kind '"+ kind
        +"' could not be found.");
  }

  let key = new Key(configs.get("realm"), kind, getUUID());
  let ent = new Entity(key, {});
  db.cache[key.uri] = ent;
  db.updates.push(ent);
  return key;
};

db.all = function DB_all(kind)
{
  let schema = db.buildSchema(kind);
  let sql = db.buildSQL(kind, schema.columns, schema.joins);
  let stmt = db.createStatement(sql);

  while(stmt.executeStep())
    db.updateQueryResults(schema.columns, stmt.row, results);
};

db.updateQueryResults = function DB_updateQueryResults(cols, row, results)
{
};

db.buildSchema = function DB_buildSchema(kind)
{
  let props = model.getProperties(kind);
  assert(props, "A model for kind '"+ kind +"' could not be found.");
  if(!props) {
    throw new TypeError("A model for kind '"+ kind
        +"' could not be found.");
  }

  let cols = [{table: kind, column: "uri"}];
  let joins = [];

  for(let p in props)
  {
    // a 1 to 1 relationship
    if(model.getCardinal(kind, p) == 1)
      cols.push({table: kind, column: p});

    // a 1 to many relationship or many to many relationship
    else {
      cols.push({table: kind +"_"+ p, column: p});
      joins.push({root: kind, table: kind +"_"+ p});
    }
  }

  return {columns: cols, joins: joins};
};

/**
 * construct an SQL select statement
 * @param {string} The root table name selecting from
 * @param {array} an array of objects repr columns to select in the form
 *   table: the table name
 *   column: the col name
 * @param {array} an array of objects repr joins in the form
 *   root: the table name of the root entity
 *   table: the name of the join table
 */
db.buildSQL = function DB_buildSQL(table, selectProperties, joins)
{
  let sql = "SELECT ";

  function creatcol(col) {
    let rv = col.table +"."+ col.column +" as "+
        col.table +"_"+ col.column;
    return rv;
  }

  let cols = [cretecol(c) for each(c in selectProperties)];
  sql += cols.join(",") +" FROM "+ table;

  if(!joins.length)
    return sql;

  sql += "\n";

  function createjoin(join) {
    let rv = "INNER JOIN "+ join.table +" on "+
        join.root +".uri="+ join.table +"."+ join.root;
    return rv;
  }

  let js = [createjoin(j) for each(j in joins)];

  return sql + js.join("\n");
};

db.TRANSACTION_STATE =
{
  /** transaction has never been attempted locally or remotely */
  init: 0,

  /** transaction has not been committed locally or remotely and
   * was aborted locally */
  localIncomplete: 1,

  /** transaction has been committed locally, but not remotely */
  localNew: 2,

  /** transaction has been commited remotely, but not yet locally */
  remoteNew: 3,

  /** transaction has been committed remotely,
   * but caused and error loally */
  localError: 4

  /** transaction is committed locally and remotely, but not confirmed */
  remoteConfirm: 5,

  /** transaction is completed locally and remotely and confirmed */
  complete: 7,
};

db.executeStatement = function DB_executeStatement(stmt, sql)
{
};

db.indexof = function DB_indexOf(uri, kind)
{
};

/** @returns {object}
 *   table: the name of the table
 *   keycol: the name of the key col in the table
 *   valuecol: the name of the value col in the table
 */
db.getFKMeta = function DB_getFKMeta(kind, propname)
{
};

/**
 * @returns {object}
 *   table: the name of the table
 *   colname: the name of the column
 */
db.getMeta = function DB_getMeta(kind, propname)
{
};

/** Create and store a transaction */
db.commit = function DB_commit(user, message, callback)
{
  let entities =
    [db.normalizeEntity(ent) for each(ent in db.cache) if(ent.modified)];

  let cleanEntities = [ent for each(ent in entities) if(ent)];

  // if there are no items in the operations list, return false;
  if(!cleanEntities.length)
    return false;

  let txn = new Transaction(user, message, cleanEntities);

  // create a new thread to store the transaction
  let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
  timer.initWithCallback(function DB_commitThread() {
        db.applyTransactionThread(txn, callback);
      }, 1, Ci.nsITimer.TYPE_ONE_SHOT);
}

db.normalizeEntity = function DB_normalizeEntity(aEntity)
{
  let props = model.getProperties(aEntity.key().kind);
  assert((typeof(props) == "object"), "invalid Entity.key().kind");

  let persistedProps = aEntity.persistedProperties();
  let ops = [];
  for(let p in props)
  {
    let prop = props[p];
    let stored =  persistedProps[p];
    if(!stored)
      continue;

    let current = aEntity[p];
    assert((typeof(current) != "undefined"), "missing Entity property "+ p);

    let op = db.normalizeOperation(prop.uri, stored, current);
    if(op)
      ops.push(op);
  }

  if(!ops.length)
    return null;

  return
  {
    uri: aEntity.key().uri,
    class: aEntity.key().class,
    operations: ops
  };
}

db.normalizeOperation = function DB_normalizeOperation(uri, stored, current)
{
  if(stored == current)
    return null;

  if(stored == null)
    return ["append", uri, current];

  if(current == null)
    return ["remove", uri, current];

  return ["update", uri, current];
};

/**
 * Apply the transaction on a background thread
 * todo: we need a garbage collection routine
 */
db.applyTransactionThread = function DB_applyTxnThread(transaction, callback)
{
  // apply the transaction locally
  let state = db.applyTransaction(transaction, db.TRANSACTION_STATE.init);
  if(state == db.TRANSACTION_STATE.localNew)
  {
    assert(false, "failed bringing transaction to state "+
        "db.TRANSACTION_STATE.localNew");
    db.logger.fatal("Applying initialized transaction failed.");
    return true;
    callback(false);
  }
  // return the normalized transaction to the callback
  callback(transaction);
  return true;
};

/**
 * Apply a transaction to the local datastore.
 *
 * @param {object} a dcube.Transaction object
 * @param {int} one of db.TRANSACTION_STATE representing
 *   the current state of the transaction
 *
 * @returns false on failure or one of db.TRANSACTION_STATE
 */
db.applyTransaction = function DB_applyTxn(aTransaction, aState)
{
  // fast track if the caller is only setting the state of an
  // existing transaction
  if(aState == db.TRANSACTION_STATE.remoteConfirm)
  {
    // todo: we need to rollback transactions in state == 5
    var sql = "UPDATE OR ABORT transaction_record SET "+
        "state=:state WHERE uid=:uid";
    var stmt = db.connection.createStatement(sql);
    stmt.params.state = aState;
    stmt.params.uid = aTransaction.uid;
    try {
      db.executeStatement(stmt, sql);
    } catch(e) {
      db.logger.fatal(e.message);
      assert(false, e.message);
      return false;
    }
    return db.TRANSACTION_STATE.complete;
  }

  // a transaction happens within an SQLite transaction
  db.connection.beginTransaction();

  // flag that will be false if no changes were made
  var entityCommitted = false;
  var rollback = false;
  // for each entity in the transcation content:
  aTransaction.content.foreach(function DB_applyEntity(ent)
    {
      if(rollback)
        return;

      if(typeof(ent.class) != "string") {
        db.logger.warn("invalid class uri '"+
          ent.class +"' in db.createAndStoreTransaction()");
        rollback = true;
        db.connection.rollbackTransaction();
        assert(false, "invalid class uri: "+ ent.class);
        return;
      }
      let kind = model.getKindForClass(ent.class);
      // assert the dataclass exists in our ontology

      if(typeof(kind) != "string") {
        db.logger.warn("kind does not exist for class '"+
          ent.class +"' in db.createAndStoreTransaction()");
        rollback = true;
        db.connection.rollbackTransaction();
        assert(false, "kind does not exist for class: "+ ent.class);
        return;
      }

      if(typeof(ent.uri) != "string") {
        db.logger.warn("invalid entity uri '"+
          ent.uri +"' in db.createAndStoreTransaction()");
        rollback = true;
        db.connection.rollbackTransaction();
        assert(false, "invalid entity uri: "+ ent.uri);
        return;
      }
      let index = db.indexof(ent.uri, kind);

      if(!tk.isarray(ent.operations)) {
        db.logger.warn("entity operations is not a list: '"+
          ent.operations +"' in db.createAndStoreTransaction()");
        rollback = true;
        db.connection.rollbackTransaction();
        assert(false, "entity operations is not a list: "+ ent.operations);
        return;
      }

      // updates to make to the entity
      let updateSet = {updates: []};
      let insertSet = {updates: [], cols: []};
      let ops = Iterator(ent.operations);
      for(let [i, op] in ops)
      {
        let method = op[0];
        if(typeof(method) != "string") {
          db.logger.warn("method '"+ op[1] +"' is invalid data operation "+
            "in db.createAndStoreTransaction()");
          rollback = true;
          db.connection.rollbackTransaction();
          assert(false,
              "method '"+ op[1] +"' is invalid data operation");
          return;
        }

        if(!index && (method == "update" || method == "remove")) {
          db.logger.warn(method +" a property on a non-existing entity '"+
              ent.uri"'");
          rollback = true;
          db.connection.rollbackTransaction();
          assert(false,
              method +" a property on a non-existing entity");
          return;
        }

        let propname = model.getPropertyName(kind, op[1]);

        if(typeof(propname) != "string") {
          db.logger.warn("property '"+ op[1] +"' does not exist for class '"+
            ent.class +"' in db.createAndStoreTransaction()");
          rollback = true;
          db.connection.rollbackTransaction();
          assert(false,
              "property '"+ op[1]+"' does not exist for class: "+ ent.class);
          return;
        }

        let target = op[3];
        if(typeof(target) != "string") {
          db.logger.warn("invalid operation target '"+
            target +"' in db.createAndStoreTransaction()");
          rollback = true;
          db.connection.rollbackTransaction();
          assert(false, "invalid operation target: "+ target);
          return;
        }

        let cardinal = model.getCardinal(kind, propname);
        let range = model.getRange(kind, propname);

        if(method == "update")
        {
          // if 1 to 1 relationship; add change to the update statement
          if(cardinal == 1)
          {
            var meta = db.getMeta(kind, propname);
            updateSet.updates.push(meta.colname +"=:"+ meta.colname);
            updateSet[meta.colname] = target;
            continue;
          }

          // if 1 to many [??? or many to many]; create and execute update
          if(range == "resource"){
            rollback = true;
            assert(false, "unexpected many to many relationship");
            return;
          }
          var meta = db.getFKMeta(kind, propname);
          // we ignore any unique matches, because if the key value pair
          // has already been updated to match this operation, we don't
          // need to do anything to maintain expected consistency
          var sql = "UPDATE OR IGNORE "+ meta.table
            +" SET "+ meta.valuecol +"=:val"
            +" WHERE "+ meta.keycol +"=:uri";
          var stmt = db.connection.createStatement(sql);
          stmt.params.val = target;
          stmt.params.uri = ent.uri;
          try {
            var result = db.executeStatement(stmt, sql);
          } catch(e) {
            rollback = true;
            db.connection.rollbackTransaction();
            db.logger.warn(e.message);
            assert(false, e.message);
            return;
          }
          stmt.finalize();
          continue;
        }

        if(method == "remove")
        {
          // if 1 to 1 relationship; add null change to the update statement
          if(cardinal == 1)
          {
            var meta = db.getMeta(kind, propname);
            updateSet.updates.push(meta.colname +"=:"+ meta.colname);
            updateSet[meta.colname] = null;
            continue;
          }

          // if 1 to many or many to many; create and execute delete
          var meta = db.getFKMeta(kind, propname);
          var sql = "DELETE FROM "+ meta.table +" WHERE "+
              meta.keycol +"=:uri AND "+ meta.valuecol +"=:val";
          var stmt = db.connection.createStatement(sql);
          stmt.params.val = target;
          stmt.params.uri = ent.uri;
          try {
            var result = db.executeStatement(stmt, sql);
          } catch(e) {
            rollback = true;
            db.connection.rollbackTransaction();
            db.logger.warn(e.message);
            assert(false, e.message);
            return;
          }
          stmt.finalize();
          continue;
        }

        if(method == "append")
        {
          // if 1 to 1 relationship;
          // add change to the insert or update statement
          if(cardinal == 1)
          {
            var meta = db.getMeta(kind, propname);
            if(index) // entity already exists
            {
              updateSet.updates.push(meta.colname +"=:"+ meta.colname);
              updateSet[meta.colname] = target;
              continue;
            }
            // entity does not yet exist in our db
            insertSet.cols.push(meta.colname);
            insertSet.updates.push(":"+ meta.colname);
            insertSet[meta.colname] = target;
            continue;
          }

          // if 1 to many or many to many; create and execute insert
          var meta = db.getFKMeta(kind, propname);

          // if the property key-value already exists, we skip it
          var sql = "INSERT OR IGNORE INTO "+ meta.table +" WHERE "+
              meta.keycol +"=:uri AND "+ meta.valuecol +"=:val";

          var stmt = db.connection.createStatement(sql);
          stmt.params.val = target;
          stmt.params.uri = ent.uri;
          try {
            var result = db.executeStatement(stmt, sql);
          } catch(e) {
            rollback = true;
            db.connection.rollbackTransaction();
            db.logger.warn(e.message);
            assert(false, e.message);
            return;
          }
          stmt.finalize();
          continue;
        }
      }

      // we should not allow a set of insert operations along with a set
      // of update operations on properties with a cardinality of 1
      if(updateSet.updates.length && insertSet.updates.length) {
        rollback = true;
        assert(false, "invalid date operations");
        return;
      }

      if(updateSet.updates.length)
      {
        var meta = db.getMeta(kind);
        let sql = "UPDATE "+ meta.table +" SET "+ updateSet.updates.join(",")
            +" WHERE rowid=:index";
        var stmt = db.connection.createStatement(sql);
        for(let p in updateSet) {
          if(p != "updates")
            stmt.params[p] = updateSet[p];
        }

        try {
          var result = db.executeStatement(stmt, sql);
        } catch(e) {
          rollback = true;
          db.connection.rollbackTransaction();
          db.logger.warn(e.message);
          assert(false, e.message);
          return;
        }
        stmt.finalize();
      }

      if(insertSet.updates.length)
      {
        var meta = db.getMeta(kind);
        let sql = "INSERT INTO "+ meta.table +" ("+ insertSet.cols.join(",")
            +") VALUES ("+ insertSet.updates.join(",") +")";
        var stmt = db.connection.createStatement(sql);
        for(let p in insertSet) {
          if(p != "updates" || p != "cols")
            stmt.params[p] = insertSet[p];
        }

        try {
          var result = db.executeStatement(stmt, sql);
        } catch(e) {
          rollback = true;
          db.connection.rollbackTransaction();
          db.logger.warn(e.message);
          assert(false, e.message);
          return;
        }
        stmt.finalize();
      }

      // at least 1 entity was written
      entityCommitted = true;
    });

  // create the SQL transaction record statement and bind params
  var insertsql = "INSERT INTO transaction_record "+
      "VALUES (:uid, :datetime, :message, :user, :serial, :state)";
  var stmt = db.connection.createStatement(insertsql);
  stmt.params.uid = aTransaction.uid;
  stmt.params.datetime = aTransaction.datetime;
  stmt.params.message = aTransaction.message;
  stmt.params.user = aTransaction.user;
  stmt.params.serial = aTransaction.serial;

  if(!rollback && entityCommited)
  {
    if(aState == db.TRANSACTION_STATE.remoteNew)
      stmt.params.state = db.TRANSACTION_STATE.complete;
    else
      stmt.params.state = db.TRANSACTION_STATE.localNew;

    try {
      var result = db.executeStatement(stmt, insertsql);
    } catch(e) {
      stmt.finalize();
      db.connection.rollbackTransaction();
      db.logger.fatal(e.message);
      assert(false, e.message);
      return false; // the caller should quarentine this transaction
    }

    stmt.finalize();
    db.connection.commitTransaction();
    return true;
  }

  else
  {
    var rv = false;
    if(aState == db.TRANSACTION_STATE.remoteNew) {
      rv = db.TRANSACTION_STATE.localError;
      stmt.params.state = rv;
    }
    else {
      rv = db.TRANSACTION_STATE.localIncomplete;
      stmt.params.state = rv;
    }

    try {
      var result = db.executeStatement(stmt, insertsql);
    } catch(e) {
      stmt.finalize();
      db.logger.fatal(e.message);
      if(!rollback)
        db.connection.rollbackTransaction();
      assert(false, e.message);
      return false; // the caller should quarentine this transaction
    }

    stmt.finalize();
    return rv;
  }
}
<|endoftext|>


<commit_before>'use strict';

angular.module('app')
    .controller('RequestCtrl', ['$scope', '$state', '$rootScope', '$rester', '$data', '$mdDialog', '$error',
        function ($scope, $state, $rootScope, $rester, $data, $mdDialog, $error) {

            $state.current.data = {
                actions: [
                    {
                        title: 'Save request',
                        icon: 'save',
                        action: saveRequest
                    }
                ]
            };

            $scope.$watch('request.id', function () {
                $state.current.data.actions.splice(1, 1);
                if ($scope.request.hasOwnProperty('id')) {
                    $state.current.data.actions.push({
                        title: 'Delete request',
                        icon: 'delete',
                        action: deleteRequest
                    });
                }
            });

            $scope.$watchGroup(['request.collection', 'request.title'], function () {
                var collection = $scope.request.collection || '<no collection>',
                    title = $scope.request.title || '<no title>';

                $state.current.data.title = `${collection} / ${title}`;
            });

            $scope.time = null;
            $scope.request = new $data.Request();
            $scope.response = null;
            $scope.requestMethodSearch = '';
            $scope.requestIsSending = false;

            function updateState(newStateParams) {
                $scope.requestIsSending = false;
                $scope.requestMethodSearch = '';

                if (newStateParams.historyId) {
                    $data.getHistoryEntry(+newStateParams.historyId).then(historyEntry => {
                        if (historyEntry.request.id != newStateParams.id) {
                            $error.show();
                            $state.go('main.request.new');
                        } else {
                            $scope.time = historyEntry.time;
                            $scope.request = historyEntry.request;
                            $scope.response = historyEntry.response;
                        }
                    });
                } else if (newStateParams.id) {
                    $data.getRequest(+newStateParams.id).then(request => {
                        $scope.time = null;
                        $scope.request = request;
                        $scope.response = null;
                    });
                } else {
                    $scope.time = null;
                    $scope.request = new $data.Request();
                    $scope.response = null;
                }
            }

            updateState($state.params);
            $rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {
                toState.data = fromState.data;
                updateState(toParams);
            });

            $scope.queryRequestMethods = function (query) {
                if (!query) return [];

                var methods = ['DELETE', 'GET', 'HEAD', 'POST', 'PUT'],
                    uppercaseQuery = angular.uppercase(query);

                if (methods.indexOf(uppercaseQuery) === -1) {
                    methods.push(uppercaseQuery);
                    methods.sort();
                }

                return methods.filter(m => m.indexOf(uppercaseQuery) > -1);
            };

            $scope.sendRequest = function () {
                $scope.requestIsSending = true;
                $rester.sendRequest($scope.request)
                    .then(response => {
                        $scope.requestIsSending = false;

                        $data.addHistoryEntry(Object.assign(new $data.HistoryEntry(), {
                            time: new Date(),
                            request: $scope.request,
                            response: response
                        })).then(historyId => {
                            $state.go('main.request.history', {
                                id: $scope.request.id,
                                historyId: historyId
                            });
                        });
                    })
                    .catch(e => {
                        $scope.requestIsSending = false;
                        $error.show(e);
                    });
            };

            $scope.getResponseBadgeModifierClass = function() {
                if (!$scope.response) return;

                var status = $scope.response.status;
                if (status >= 100 && status < 200) {
                    return 'badge--info';
                } else if (status >= 200 && status < 300) {
                    return 'badge--success';
                } else if (status >= 300 && status < 400) {
                    return 'badge--info';
                } else if (status >= 400) {
                    return 'badge--warn';
                }
            };

            function saveRequest($event) {
                $mdDialog.show({
                    targetEvent: $event,
                    templateUrl: 'views/dialogs/save-request.html',
                    controller: 'DialogSaveRequestCtrl',
                    locals: {
                        isNew: !$scope.request.hasOwnProperty('id'),
                        collection: $scope.request.collection,
                        title: $scope.request.title,
                        showHistoryWarning: $scope.request.hasOwnProperty('id') && $state.params.historyId
                    }
                }).then(input => {
                    $scope.request.collection = input.collection;
                    $scope.request.title = input.title;
                    if (!input.overwrite) {
                        delete $scope.request.id;
                    }

                    $data.putRequest($scope.request).then(() => {
                        $state.go('main.request', {
                            id: $scope.request.id
                        })
                    });
                });
            }

            function deleteRequest($event) {
                $mdDialog.show($mdDialog.confirm()
                    .targetEvent($event)
                    .content('Are you sure you want to delete the request?')
                    .ok('Delete')
                    .cancel('Cancel')
                ).then(() => {
                    $data.deleteRequest($scope.request).then(() => {
                        $state.go('main.request', {
                            id: null
                        });
                    });
                });
            }

        }
    ]);
<commit_msg>Show history time in title.<commit_after>'use strict';

angular.module('app')
    .controller('RequestCtrl', ['$scope', '$state', '$rootScope', '$rester', '$data', '$mdDialog', '$error', '$filter',
        function ($scope, $state, $rootScope, $rester, $data, $mdDialog, $error, $filter) {

            $state.current.data = {
                actions: [
                    {
                        title: 'Save request',
                        icon: 'save',
                        action: saveRequest
                    }
                ]
            };

            $scope.$watch('request.id', function () {
                $state.current.data.actions.splice(1, 1);
                if ($scope.request.hasOwnProperty('id')) {
                    $state.current.data.actions.push({
                        title: 'Delete request',
                        icon: 'delete',
                        action: deleteRequest
                    });
                }
            });

            $scope.$watchGroup(['request.collection', 'request.title', 'time'], function () {
                var collection = $scope.request.collection || '<no collection>',
                    title = $scope.request.title || '<no title>',
                    time = $scope.time ? $filter('date')($scope.time, 'yyyy-MM-dd HH:mm:ss') : '';

                $state.current.data.title = `${collection} / ${title}`;
                if (time) {
                    $state.current.data.title += ` (${time})`;
                }
            });

            $scope.time = null;
            $scope.request = new $data.Request();
            $scope.response = null;
            $scope.requestMethodSearch = '';
            $scope.requestIsSending = false;

            function updateState(newStateParams) {
                $scope.requestIsSending = false;
                $scope.requestMethodSearch = '';

                if (newStateParams.historyId) {
                    $data.getHistoryEntry(+newStateParams.historyId).then(historyEntry => {
                        if (historyEntry.request.id != newStateParams.id) {
                            $error.show();
                            $state.go('main.request.new');
                        } else {
                            $scope.time = historyEntry.time;
                            $scope.request = historyEntry.request;
                            $scope.response = historyEntry.response;
                        }
                    });
                } else if (newStateParams.id) {
                    $data.getRequest(+newStateParams.id).then(request => {
                        $scope.time = null;
                        $scope.request = request;
                        $scope.response = null;
                    });
                } else {
                    $scope.time = null;
                    $scope.request = new $data.Request();
                    $scope.response = null;
                }
            }

            updateState($state.params);
            $rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {
                toState.data = fromState.data;
                updateState(toParams);
            });

            $scope.queryRequestMethods = function (query) {
                if (!query) return [];

                var methods = ['DELETE', 'GET', 'HEAD', 'POST', 'PUT'],
                    uppercaseQuery = angular.uppercase(query);

                if (methods.indexOf(uppercaseQuery) === -1) {
                    methods.push(uppercaseQuery);
                    methods.sort();
                }

                return methods.filter(m => m.indexOf(uppercaseQuery) > -1);
            };

            $scope.sendRequest = function () {
                $scope.requestIsSending = true;
                $rester.sendRequest($scope.request)
                    .then(response => {
                        $scope.requestIsSending = false;

                        $data.addHistoryEntry(Object.assign(new $data.HistoryEntry(), {
                            time: new Date(),
                            request: $scope.request,
                            response: response
                        })).then(historyId => {
                            $state.go('main.request.history', {
                                id: $scope.request.id,
                                historyId: historyId
                            });
                        });
                    })
                    .catch(e => {
                        $scope.requestIsSending = false;
                        $error.show(e);
                    });
            };

            $scope.getResponseBadgeModifierClass = function() {
                if (!$scope.response) return;

                var status = $scope.response.status;
                if (status >= 100 && status < 200) {
                    return 'badge--info';
                } else if (status >= 200 && status < 300) {
                    return 'badge--success';
                } else if (status >= 300 && status < 400) {
                    return 'badge--info';
                } else if (status >= 400) {
                    return 'badge--warn';
                }
            };

            function saveRequest($event) {
                $mdDialog.show({
                    targetEvent: $event,
                    templateUrl: 'views/dialogs/save-request.html',
                    controller: 'DialogSaveRequestCtrl',
                    locals: {
                        isNew: !$scope.request.hasOwnProperty('id'),
                        collection: $scope.request.collection,
                        title: $scope.request.title,
                        showHistoryWarning: $scope.request.hasOwnProperty('id') && $state.params.historyId
                    }
                }).then(input => {
                    $scope.request.collection = input.collection;
                    $scope.request.title = input.title;
                    if (!input.overwrite) {
                        delete $scope.request.id;
                    }

                    $data.putRequest($scope.request).then(() => {
                        $state.go('main.request', {
                            id: $scope.request.id
                        })
                    });
                });
            }

            function deleteRequest($event) {
                $mdDialog.show($mdDialog.confirm()
                    .targetEvent($event)
                    .content('Are you sure you want to delete the request?')
                    .ok('Delete')
                    .cancel('Cancel')
                ).then(() => {
                    $data.deleteRequest($scope.request).then(() => {
                        $state.go('main.request.new');
                    });
                });
            }

        }
    ]);
<|endoftext|>