<commit_before>import Ember from 'ember';

const { assert, run: { bind } } = Ember;

export default class {
  constructor() {
    this._listeners = Ember.A();
    this._entered = 0;
  }

  beginListening() {
    let handlers = this._handlers = {
      dragenter: bind(this, 'dragenter'),
      dragleave: bind(this, 'dragleave'),
      dragover:  bind(this, 'dragover'),
      drop:      bind(this, 'drop')
    };

    let body = document.body;
    body.addEventListener('dragenter', handlers.dragenter, {
      passive: true
    });
    body.addEventListener('dragleave', handlers.dragleave, {
      passive: true
    });
    body.addEventListener('dragover', handlers.dragover, {
      passive: false
    });
    body.addEventListener('drop', handlers.drop, {
      passive: false
    });
  }

  endListening() {
    let body = document.body;
    let handlers = this._handlers;
    body.removeEventListener('dragenter', handlers.dragenter, {
      passive: true
    });
    body.removeEventListener('dragleave', handlers.dragleave, {
      passive: true
    });
    body.removeEventListener('dragover', handlers.dragover, {
      passive: false
    });
    body.removeEventListener('drop', handlers.drop, {
      passive: false
    });
  }

  addEventListeners(selector, handlers) {
    if (this._listeners.length === 0) {
      this.beginListening();
    }

    // Listeners are ordered by most specific to least specific
    let insertAt = this._listeners.length;

    for (let i = 0, len = this._listeners.length; i < len; i++) {
      let listener = this._listeners[i];
      assert(`Cannot add multiple listeners for the same element ${selector}, ${listener.selector}`, document.querySelector(selector) !== document.querySelector(listener.selector));

      if (document.querySelector(`${listener.selector} ${selector}`)) {
        insertAt = i;
      }
    }

    this._listeners.splice(insertAt, 0, { selector, handlers });
  }

  removeEventListeners(selector) {
    this._listeners.removeObject(this._listeners.findBy('selector', selector));
    if (this._listeners.length === 0) {
      this.endListening();
    }
  }

  findListener(evt) {
    return this._listeners.find(function ({ selector }) {
      let element = document.querySelector(selector);
      return element === evt.target || element.contains(evt.target);
    });
  }

  dragenter(evt) {
    let listener = this.findListener(evt);

    // Trigger a dragleave because the listener that
    // matched isn't the same as the listener that was
    // previously called for a dragenter
    if (this._listener && listener !== this._listener) {
      this._listener.handlers.dragleave(evt);
    }

    if (listener && listener !== this._listener) {
      listener.handlers.dragenter(evt);
    }

    this._listener = listener;
    this._entered++;
  }

  dragleave(evt) {
    this._entered--;

    // Trigger a dragleave if the file leaves the browser
    if (this._entered === 0 && this._listener) {
      this._listener.handlers.dragleave(evt);
      this._listener = null;
    }
  }

  dragover(evt) {
    evt.preventDefault();
    evt.stopPropagation();
    let listener = this.findListener(evt);
    if (listener) {
      if (this._listener !== listener) {
        if (this._listener) {
          this._listener.handlers.dragleave(evt);
        }
        listener.handlers.dragenter(evt);
      }
      listener.handlers.dragover(evt);
    }
  }

  drop(evt) {
    this._entered = 0;
    evt.preventDefault();
    evt.stopPropagation();
    let listener = this.findListener(evt);
    if (listener) {
      listener.handlers.drop(evt);
    }
  }
}
<commit_msg>nullify _listener after file drop<commit_after>import Ember from 'ember';

const { assert, run: { bind } } = Ember;

export default class {
  constructor() {
    this._listeners = Ember.A();
    this._entered = 0;
  }

  beginListening() {
    let handlers = this._handlers = {
      dragenter: bind(this, 'dragenter'),
      dragleave: bind(this, 'dragleave'),
      dragover:  bind(this, 'dragover'),
      drop:      bind(this, 'drop')
    };

    let body = document.body;
    body.addEventListener('dragenter', handlers.dragenter, {
      passive: true
    });
    body.addEventListener('dragleave', handlers.dragleave, {
      passive: true
    });
    body.addEventListener('dragover', handlers.dragover, {
      passive: false
    });
    body.addEventListener('drop', handlers.drop, {
      passive: false
    });
  }

  endListening() {
    let body = document.body;
    let handlers = this._handlers;
    body.removeEventListener('dragenter', handlers.dragenter, {
      passive: true
    });
    body.removeEventListener('dragleave', handlers.dragleave, {
      passive: true
    });
    body.removeEventListener('dragover', handlers.dragover, {
      passive: false
    });
    body.removeEventListener('drop', handlers.drop, {
      passive: false
    });
  }

  addEventListeners(selector, handlers) {
    if (this._listeners.length === 0) {
      this.beginListening();
    }

    // Listeners are ordered by most specific to least specific
    let insertAt = this._listeners.length;

    for (let i = 0, len = this._listeners.length; i < len; i++) {
      let listener = this._listeners[i];
      assert(`Cannot add multiple listeners for the same element ${selector}, ${listener.selector}`, document.querySelector(selector) !== document.querySelector(listener.selector));

      if (document.querySelector(`${listener.selector} ${selector}`)) {
        insertAt = i;
      }
    }

    this._listeners.splice(insertAt, 0, { selector, handlers });
  }

  removeEventListeners(selector) {
    this._listeners.removeObject(this._listeners.findBy('selector', selector));
    if (this._listeners.length === 0) {
      this.endListening();
    }
  }

  findListener(evt) {
    return this._listeners.find(function ({ selector }) {
      let element = document.querySelector(selector);
      return element === evt.target || element.contains(evt.target);
    });
  }

  dragenter(evt) {
    let listener = this.findListener(evt);

    // Trigger a dragleave because the listener that
    // matched isn't the same as the listener that was
    // previously called for a dragenter
    if (this._listener && listener !== this._listener) {
      this._listener.handlers.dragleave(evt);
    }

    if (listener && listener !== this._listener) {
      listener.handlers.dragenter(evt);
    }

    this._listener = listener;
    this._entered++;
  }

  dragleave(evt) {
    this._entered--;

    // Trigger a dragleave if the file leaves the browser
    if (this._entered === 0 && this._listener) {
      this._listener.handlers.dragleave(evt);
      this._listener = null;
    }
  }

  dragover(evt) {
    evt.preventDefault();
    evt.stopPropagation();
    let listener = this.findListener(evt);
    if (listener) {
      if (this._listener !== listener) {
        if (this._listener) {
          this._listener.handlers.dragleave(evt);
        }
        listener.handlers.dragenter(evt);
      }
      listener.handlers.dragover(evt);
    }
  }

  drop(evt) {
    this._entered = 0;
    evt.preventDefault();
    evt.stopPropagation();
    let listener = this.findListener(evt);
    if (listener) {
      listener.handlers.drop(evt);
      this._listener = null;
    }
  }
}
<|endoftext|>


<commit_before>import Ember from 'ember';

/**
 * Handles Sorting, Searching & Pagination
 */
export default Ember.Object.extend({
  isSorting: false,
  isSearching: false,

  tableDefinition: null,

  rows: [],
  _sortedRows: [],
  _searchedRows: [],

  _searchObserver: Ember.on("init", Ember.observer('tableDefinition.searchText', '_sortedRows.[]', function () {
      Ember.run.once(this, "startSearch");
  })),

  _sortObserver: Ember.on("init", Ember.observer(
    'tableDefinition.sortColumnId',
    'tableDefinition.sortOrder',
    'rows.[]', function () {
      Ember.run.once(this, "startSort");
  })),

  startSearch: function () {
    var searchText = this.get('tableDefinition.searchText'),
        rows = this.get('_sortedRows') || [],
        columns = this.get('tableDefinition.columns');

    function checkRow(column) {
      var value;
      if(!column.get('enableSearch')) {
        return false;
      }
      value = column.getSearchValue(this);
      return (typeof value === 'string') ? value.match(searchText) : false;
    }

    if(searchText) {
      rows = rows.filter(function (row) {
        return columns.some(checkRow, row);
      });
    }

    this.setProperties({
      _searchedRows: rows,
      isSearching: false
    });
  },

  startSort: function () {
    var rows = this.get('rows'),
        sortColumnId = this.get('tableDefinition.sortColumnId'),
        column = this.get('tableDefinition.columns').find(function (element) {
          return element.get('id') === sortColumnId;
        }),
        ascending = this.get('tableDefinition.sortOrder') === 'asc',
        that = this;

    if(rows && rows.get('length') > 0 && column) {
      this.set('isSorting', true);

      Ember.run.later(function () {
        /*
         * Creating sortArray as calling getSortValue form inside the
         * sort function every time would be more costly.
         */
        var sortArray = rows.map(function (row) {
          return {
            value: column.getSortValue(row),
            row: row
          };
        });

        sortArray.sort(function (a, b){
          console.log(a.value, b.value);
          if(ascending ^ (a.value > b.value)) {
            return -1;
          }
          else if(ascending ^ (a.value < b.value)) {
            return 1;
          }
          return 0;
        });

        that.setProperties({
          _sortedRows: sortArray.map(function (record) {
            return record.row;
          }),
          isSorting: false
        });

      });
    }
    else {
      this.set('_sortedRows', rows);
    }
  },

  totalPages: Ember.computed('_searchedRows.length', 'tableDefinition.rowCount', function () {
    return Math.ceil(this.get('_searchedRows.length') / this.get('tableDefinition.rowCount'));
  }),

  // Paginate
  processedRows: Ember.computed('_searchedRows.[]', 'tableDefinition.rowCount', 'tableDefinition.pageNum', function () {
    var rowCount =  this.get('tableDefinition.rowCount'),
        startIndex = (this.get('tableDefinition.pageNum') - 1) * rowCount;
    return this.get('_searchedRows').slice(startIndex, startIndex + rowCount);
  }),
});
<commit_msg>Cleanup<commit_after>import Ember from 'ember';

/**
 * Handles Sorting, Searching & Pagination
 */
export default Ember.Object.extend({
  isSorting: false,
  isSearching: false,

  tableDefinition: null,

  rows: [],
  _sortedRows: [],
  _searchedRows: [],

  _searchObserver: Ember.on("init", Ember.observer('tableDefinition.searchText', '_sortedRows.[]', function () {
      Ember.run.once(this, "startSearch");
  })),

  _sortObserver: Ember.on("init", Ember.observer(
    'tableDefinition.sortColumnId',
    'tableDefinition.sortOrder',
    'rows.[]', function () {
      Ember.run.once(this, "startSort");
  })),

  startSearch: function () {
    var searchText = this.get('tableDefinition.searchText'),
        rows = this.get('_sortedRows') || [],
        columns = this.get('tableDefinition.columns');

    function checkRow(column) {
      var value;
      if(!column.get('enableSearch')) {
        return false;
      }
      value = column.getSearchValue(this);
      return (typeof value === 'string') ? value.match(searchText) : false;
    }

    if(searchText) {
      rows = rows.filter(function (row) {
        return columns.some(checkRow, row);
      });
    }

    this.setProperties({
      _searchedRows: rows,
      isSearching: false
    });
  },

  startSort: function () {
    var rows = this.get('rows'),
        sortColumnId = this.get('tableDefinition.sortColumnId'),
        column = this.get('tableDefinition.columns').find(function (element) {
          return element.get('id') === sortColumnId;
        }),
        ascending = this.get('tableDefinition.sortOrder') === 'asc',
        that = this;

    if(rows && rows.get('length') > 0 && column) {
      this.set('isSorting', true);

      Ember.run.later(function () {
        /*
         * Creating sortArray as calling getSortValue form inside the
         * sort function every time would be more costly.
         */
        var sortArray = rows.map(function (row) {
          return {
            value: column.getSortValue(row),
            row: row
          };
        });

        sortArray.sort(function (a, b){
          if(ascending ^ (a.value > b.value)) {
            return -1;
          }
          else if(ascending ^ (a.value < b.value)) {
            return 1;
          }
          return 0;
        });

        that.setProperties({
          _sortedRows: sortArray.map(function (record) {
            return record.row;
          }),
          isSorting: false
        });

      });
    }
    else {
      this.set('_sortedRows', rows);
    }
  },

  totalPages: Ember.computed('_searchedRows.length', 'tableDefinition.rowCount', function () {
    return Math.ceil(this.get('_searchedRows.length') / this.get('tableDefinition.rowCount'));
  }),

  // Paginate
  processedRows: Ember.computed('_searchedRows.[]', 'tableDefinition.rowCount', 'tableDefinition.pageNum', function () {
    var rowCount =  this.get('tableDefinition.rowCount'),
        startIndex = (this.get('tableDefinition.pageNum') - 1) * rowCount;
    return this.get('_searchedRows').slice(startIndex, startIndex + rowCount);
  }),
});
<|endoftext|>


<commit_before>var debug = require('debug')('SebastiaanLuca:Controls:Controls');

var util = require('util');
var EventEmitter = require('events').EventEmitter;

var Gpio = require('onoff').Gpio;

//

var Controls = function Controls() {

    var self = this;

    // Input
    var btnPlayPause = new Gpio(4, 'in', 'both');
    var btnPlayPausePressTime = (new Date().getTime());

    // Output
    var appRunningIndicatorLed = new Gpio(25, 'out');

    var init = function () {
        // Turn on LED indicating application is running
        appRunningIndicatorLed.writeSync(1);
    };

    var quit = function () {
        debug('Cleaning up our mess.');

        // Clear perhipherals
        btnPlayPause.unexport();
        appRunningIndicatorLed.unexport();
    };

    // Watch play/pause button input
    btnPlayPause.watch(function (err, status) {
        if (err) {
            throw err;
        }

        // Handle when button is released
        if (status != 1) {
            return;
        }

        // Handle contact bounce
        // @ http://arduino.stackexchange.com/questions/408/why-does-my-sketch-report-too-many-button-presses
        // TODO: move to separate Button module so we can reuse it?
        var timeDifference = (new Date().getTime()) - btnPlayPausePressTime;

        if (timeDifference < 320) {
            debug('Contact bounce detected, skipping button press!');

            return;
        }

        // Handle button press
        debug('Button pressed');
        self.emit('playPauseButtonPressed');

        // Save current time for future reference
        btnPlayPausePressTime = (new Date().getTime());
    });

    init();

    // Gracefully exit on CTRL+C and errors
    process.on('forceQuitApplication', quit);

};

//

// Class inherits EventEmitter so we can dispatch and listen to events on the object itself
util.inherits(Controls, EventEmitter);

module.exports = new Controls();<commit_msg>Use correct pins<commit_after>var debug = require('debug')('SebastiaanLuca:Controls:Controls');

var util = require('util');
var EventEmitter = require('events').EventEmitter;

var Gpio = require('onoff').Gpio;

//

var Controls = function Controls() {

    var self = this;

    // Input
    var btnPlayPause = new Gpio(17, 'in', 'both');
    var btnPlayPausePressTime = (new Date().getTime());

    // Output
    var appRunningIndicatorLed = new Gpio(25, 'out');

    var init = function () {
        // Turn on LED indicating application is running
        appRunningIndicatorLed.writeSync(1);
    };

    var quit = function () {
        debug('Cleaning up our mess.');

        // Clear perhipherals
        btnPlayPause.unexport();
        appRunningIndicatorLed.unexport();
    };

    // Watch play/pause button input
    btnPlayPause.watch(function (err, status) {
        if (err) {
            throw err;
        }

        // Handle when button is released
        if (status != 1) {
            return;
        }

        // Handle contact bounce
        // @ http://arduino.stackexchange.com/questions/408/why-does-my-sketch-report-too-many-button-presses
        // TODO: move to separate Button module so we can reuse it?
        var timeDifference = (new Date().getTime()) - btnPlayPausePressTime;

        if (timeDifference < 320) {
            debug('Contact bounce detected, skipping button press!');

            return;
        }

        // Handle button press
        debug('Button pressed');
        self.emit('playPauseButtonPressed');

        // Save current time for future reference
        btnPlayPausePressTime = (new Date().getTime());
    });

    init();

    // Gracefully exit on CTRL+C and errors
    process.on('forceQuitApplication', quit);

};

//

// Class inherits EventEmitter so we can dispatch and listen to events on the object itself
util.inherits(Controls, EventEmitter);

module.exports = new Controls();<|endoftext|>


<commit_before>app.factory('Base64', function() {
    var keyStr = 'ABCDEFGHIJKLMNOP' +
        'QRSTUVWXYZabcdef' +
        'ghijklmnopqrstuv' +
        'wxyz0123456789+/' +
        '=';
    return {
        encode: function (input) {
            var output = "";
            var chr1, chr2, chr3 = "";
            var enc1, enc2, enc3, enc4 = "";
            var i = 0;

            do {
                chr1 = input.charCodeAt(i++);
                chr2 = input.charCodeAt(i++);
                chr3 = input.charCodeAt(i++);

                enc1 = chr1 >> 2;
                enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
                enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
                enc4 = chr3 & 63;

                if (isNaN(chr2)) {
                    enc3 = enc4 = 64;
                } else if (isNaN(chr3)) {
                    enc4 = 64;
                }

                output = output +
                    keyStr.charAt(enc1) +
                    keyStr.charAt(enc2) +
                    keyStr.charAt(enc3) +
                    keyStr.charAt(enc4);
                chr1 = chr2 = chr3 = "";
                enc1 = enc2 = enc3 = enc4 = "";
            } while (i < input.length);

            return output;
        },

        decode: function (input) {
            var output = "";
            var chr1, chr2, chr3 = "";
            var enc1, enc2, enc3, enc4 = "";
            var i = 0;

            // remove all characters that are not A-Z, a-z, 0-9, +, /, or =
            var base64test = /[^A-Za-z0-9\+\/\=]/g;
            if (base64test.exec(input)) {
                alert("There were invalid base64 characters in the input text.\n" +
                    "Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\n" +
                    "Expect errors in decoding.");
            }
            input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

            do {
                enc1 = keyStr.indexOf(input.charAt(i++));
                enc2 = keyStr.indexOf(input.charAt(i++));
                enc3 = keyStr.indexOf(input.charAt(i++));
                enc4 = keyStr.indexOf(input.charAt(i++));

                chr1 = (enc1 << 2) | (enc2 >> 4);
                chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
                chr3 = ((enc3 & 3) << 6) | enc4;

                output = output + String.fromCharCode(chr1);

                if (enc3 != 64) {
                    output = output + String.fromCharCode(chr2);
                }
                if (enc4 != 64) {
                    output = output + String.fromCharCode(chr3);
                }

                chr1 = chr2 = chr3 = "";
                enc1 = enc2 = enc3 = enc4 = "";

            } while (i < input.length);

            return output;
        }
    };
});

app.factory('UserServices', function ($http, Base64) {
//app.factory('Auth', function ($cookieStore, $http) {
//    initialize to whatever is in the cookie, if anything
//    $http.defaults.headers.common['Authorization'] = 'Basic ' + $cookieStore.get('authdata');

    var user = { isLogged: false,
    		     username: ''};

    return {
        setCredentials: function (username, password) {
            var encoded = Base64.encode(username + ':' + password);
            $http.defaults.headers.common.Authorization = 'Basic ' + encoded;
            user.isLogged = true;
            user.username = username;
//            $cookieStore.put('authdata', encoded);
        },
        clearCredentials: function () {
            document.execCommand("ClearAuthenticationCache");
            $http.defaults.headers.common.Authorization = 'Basic ';
            user.isLogged = false;
            user.username = '';
//            $cookieStore.remove('authdata');
        },
        isLogged: function() {
            return user.isLogged;
        }
    };
});

app.factory('CategoryAPI', function($http, $resource) {
    // Define the resource for the category API to be shared by all other services and controllers

//    Auth.setCredentials('dedalusj@gmail.com','idathik');

	return $resource('http://localhost\\:5000/api/categories/:categoryId/:resource', {categoryId:'@id', resource: '@res'});
});

app.factory('CategoryServices', function(CategoryAPI) {
    // defines a categories service that can load the list from the backend and can cache it
    var data;
    var categories = function(callback) {
        data = CategoryAPI.query(callback);
        return data;
    }
    return {
        getCategories: function(callback) {
            if(data) {
                return data;
            } else {
                return categories(callback);
            }
        }
    };
});

app.factory('SubcategoryServices', function(CategoryAPI) {
    // defines a subcategories service that can load the list from the backend or returned cached data if the id of the category is unchanged
    var data;
    var categoryId;
    var subcategories = function(parentId, callback) {
        categoryId = parentId;
        data = CategoryAPI.query({categoryId: parentId, resource: 'subcategories'},callback);
        return data;
    }
    return {
        getSubcategories: function(parentId, callback) {
            if (data && parentId === categoryId) {
                return data;
            } else {
                return subcategories(parentId, callback);
            }
        }
    };
});<commit_msg>Added a service for the REST API address<commit_after>app.factory('Base64', function() {
    var keyStr = 'ABCDEFGHIJKLMNOP' +
        'QRSTUVWXYZabcdef' +
        'ghijklmnopqrstuv' +
        'wxyz0123456789+/' +
        '=';
    return {
        encode: function (input) {
            var output = "";
            var chr1, chr2, chr3 = "";
            var enc1, enc2, enc3, enc4 = "";
            var i = 0;

            do {
                chr1 = input.charCodeAt(i++);
                chr2 = input.charCodeAt(i++);
                chr3 = input.charCodeAt(i++);

                enc1 = chr1 >> 2;
                enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
                enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
                enc4 = chr3 & 63;

                if (isNaN(chr2)) {
                    enc3 = enc4 = 64;
                } else if (isNaN(chr3)) {
                    enc4 = 64;
                }

                output = output +
                    keyStr.charAt(enc1) +
                    keyStr.charAt(enc2) +
                    keyStr.charAt(enc3) +
                    keyStr.charAt(enc4);
                chr1 = chr2 = chr3 = "";
                enc1 = enc2 = enc3 = enc4 = "";
            } while (i < input.length);

            return output;
        },

        decode: function (input) {
            var output = "";
            var chr1, chr2, chr3 = "";
            var enc1, enc2, enc3, enc4 = "";
            var i = 0;

            // remove all characters that are not A-Z, a-z, 0-9, +, /, or =
            var base64test = /[^A-Za-z0-9\+\/\=]/g;
            if (base64test.exec(input)) {
                alert("There were invalid base64 characters in the input text.\n" +
                    "Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\n" +
                    "Expect errors in decoding.");
            }
            input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

            do {
                enc1 = keyStr.indexOf(input.charAt(i++));
                enc2 = keyStr.indexOf(input.charAt(i++));
                enc3 = keyStr.indexOf(input.charAt(i++));
                enc4 = keyStr.indexOf(input.charAt(i++));

                chr1 = (enc1 << 2) | (enc2 >> 4);
                chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
                chr3 = ((enc3 & 3) << 6) | enc4;

                output = output + String.fromCharCode(chr1);

                if (enc3 != 64) {
                    output = output + String.fromCharCode(chr2);
                }
                if (enc4 != 64) {
                    output = output + String.fromCharCode(chr3);
                }

                chr1 = chr2 = chr3 = "";
                enc1 = enc2 = enc3 = enc4 = "";

            } while (i < input.length);

            return output;
        }
    };
});

app.factory('Address',function() {
    return 'http://localhost\\:5000/api';
});

app.factory('UserServices', function ($http, Base64) {
//app.factory('Auth', function ($cookieStore, $http) {
//    initialize to whatever is in the cookie, if anything
//    $http.defaults.headers.common['Authorization'] = 'Basic ' + $cookieStore.get('authdata');

    var user = { isLogged: false,
    		     username: ''};

    return {
        setCredentials: function (username, password) {
            var encoded = Base64.encode(username + ':' + password);
            $http.defaults.headers.common.Authorization = 'Basic ' + encoded;
            user.isLogged = true;
            user.username = username;
//            $cookieStore.put('authdata', encoded);
        },
        clearCredentials: function () {
            document.execCommand("ClearAuthenticationCache");
            $http.defaults.headers.common.Authorization = 'Basic ';
            user.isLogged = false;
            user.username = '';
//            $cookieStore.remove('authdata');
        },
        isLogged: function() {
            return user.isLogged;
        }
    };
});

app.factory('CategoryAPI', function($http, $resource, Address) {
    // Define the resource for the category API to be shared by all other services and controllers
    var resourceAddress = Address.concat('/categories/:categoryId/:resource');
    return $resource(resourceAddress,{categoryId:'@id', resource: '@res'});
});

app.factory('CategoryServices', function(CategoryAPI) {
    // defines a categories service that can load the list from the backend and can cache it
    var data;
    var categories = function(callback) {
        data = CategoryAPI.query(callback);
        return data;
    }
    return {
        getCategories: function(callback) {
            if(data) {
                return data;
            } else {
                return categories(callback);
            }
        }
    };
});

app.factory('SubcategoryServices', function(CategoryAPI) {
    // defines a subcategories service that can load the list from the backend or returned cached data if the id of the category is unchanged
    var data;
    var categoryId;
    var subcategories = function(parentId, callback) {
        categoryId = parentId;
        data = CategoryAPI.query({categoryId: parentId, resource: 'subcategories'},callback);
        return data;
    }
    return {
        getSubcategories: function(parentId, callback) {
            if (data && parentId === categoryId) {
                return data;
            } else {
                return subcategories(parentId, callback);
            }
        }
    };
});<|endoftext|>


<commit_before>import h from 'react-hyperscript'
import { isNil, path, prop, pipe, values, any, forEach, either, not, equals } from 'ramda'
import { connect as connectFeathers } from 'feathers-action-react'
import { compose } from 'recompose'

import { agents, profiles, relationships, credentials } from 'dogstack-agents/actions'
import getMyGroupsProps from '../getters/getMyGroupsProps'
import MyGroups from '../components/MyGroups'

export default compose(
  connectFeathers({
    selector: getMyGroupsProps,
    actions: {
      agents,
      profiles,
      relationships,
      credentials
    },
    query: (props) => {
      var queries = []
      const { currentAgent, currentAgentGroupIds } = props.selected

      if (currentAgent) {
        queries.push({
          service: 'profiles',
          params: {
            query: {
              agentId: currentAgent.id
            }
          }
        })
        queries.push({
          service: 'relationships',
          params: {
            query: {
              targetId: currentAgent.id
            }
          }
        })
      }

      if (currentAgentGroupIds) {
        queries.push({
          service: 'profiles',
          params: {
            query: {
              agentId: {
                $in: currentAgentGroupIds
              }
            }
          }
        })
      }

      return queries
    },
    shouldQueryAgain: (props, status, prevProps) => {
      if (status.isPending) return false

      const { currentAgent: prevCurrentAgent, currentAgentGroupIds: prevCurrentAgentGroupIds } = prevProps.selected
      const { currentAgent, currentAgentGroupIds } = props.selected

      if (isNil(prevCurrentAgent) && not(isNil(currentAgent))) return true
      if (not(equals(prevCurrentAgentGroupIds, currentAgentGroupIds))) return true

      return false
    }
  })
)(props => {
  const { currentAgent, actions, currentAgentGroupProfiles } = props

  if (isNil(currentAgent)) {
    return null
  }

  return h(MyGroups, {
    initialValues: currentAgent.profile,
    updateProfile: (nextProfile) => {
      actions.profiles.update(currentAgent.profile.id, nextProfile)
    },
    agentType: 'my',
    isEditing: true,
    agent: currentAgent,
    currentAgentGroupProfiles: currentAgentGroupProfiles
  })
})
<commit_msg>feat(profile): cleaned up container<commit_after>import h from 'react-hyperscript'
import { isNil, path, prop, pipe, values, any, forEach, either, not, equals } from 'ramda'
import { connect as connectFeathers } from 'feathers-action-react'
import { compose } from 'recompose'

import { agents, profiles, relationships, credentials } from 'dogstack-agents/actions'
import getMyGroupsProps from '../getters/getMyGroupsProps'
import MyGroups from '../components/MyGroups'

export default compose(
  connectFeathers({
    selector: getMyGroupsProps,
    actions: {
      agents,
      profiles,
      relationships,
      credentials
    },
    query: (props) => {
      var queries = []
      const { currentAgent, currentAgentGroupIds } = props.selected

      if (currentAgent) {
        queries.push({
          service: 'profiles',
          params: {
            query: {
              agentId: currentAgent.id
            }
          }
        })
        queries.push({
          service: 'relationships',
          params: {
            query: {
              targetId: currentAgent.id
            }
          }
        })
      }

      if (currentAgentGroupIds) {
        queries.push({
          service: 'profiles',
          params: {
            query: {
              agentId: {
                $in: currentAgentGroupIds
              }
            }
          }
        })
      }

      return queries
    },
    shouldQueryAgain: (props, status, prevProps) => {
      if (status.isPending) return false

      const { currentAgent: prevCurrentAgent, currentAgentGroupIds: prevCurrentAgentGroupIds } = prevProps.selected
      const { currentAgent, currentAgentGroupIds } = props.selected

      if (isNil(prevCurrentAgent) && not(isNil(currentAgent))) return true
      if (not(equals(prevCurrentAgentGroupIds, currentAgentGroupIds))) return true

      return false
    }
  })
)(props => {
  const { currentAgent, currentAgentGroupProfiles } = props

  if (isNil(currentAgent)) {
    return null
  }

  return h(MyGroups, {
    currentAgent: currentAgent,
    currentAgentGroupProfiles: currentAgentGroupProfiles
  })
})
<|endoftext|>


<commit_before>define([
    '/common/common-constants.js',
    '/common/common-hash.js',
    '/bower_components/localforage/dist/localforage.min.js',
    '/customize/application_config.js',
], function (Constants, Hash, localForage, AppConfig) {
    var LocalStore = {};

    LocalStore.setThumbnail = function (key, value, cb) {
        localForage.setItem(key, value, cb);
    };
    LocalStore.getThumbnail = function (key, cb) {
        localForage.getItem(key, cb);
    };
    LocalStore.clearThumbnail = function (cb) {
        cb = cb || function () {};
        localForage.clear(cb);
    };

    LocalStore.setFSHash = function (hash) {
        var sHash = Hash.serializeHash(hash);
        localStorage[Constants.fileHashKey] = sHash;
    };
    LocalStore.getFSHash = function () {
        var hash = localStorage[Constants.fileHashKey];

        if (['undefined', 'undefined/'].indexOf(hash) !== -1) {
            localStorage.removeItem(Constants.fileHashKey);
            return;
        }

        if (hash) {
            var sHash = Hash.serializeHash(hash);
            if (sHash !== hash) { localStorage[Constants.fileHashKey] = sHash; }
        }

        return hash;
    };

    var getUserHash = LocalStore.getUserHash = function () {
        var hash = localStorage[Constants.userHashKey];

        if (['undefined', 'undefined/'].indexOf(hash) !== -1) {
            localStorage.removeItem(Constants.userHashKey);
            return;
        }

        if (hash) {
            var sHash = Hash.serializeHash(hash);
            if (sHash !== hash) { localStorage[Constants.userHashKey] = sHash; }
        }

        return hash;
    };

    LocalStore.setUserHash = function (hash) {
        var sHash = Hash.serializeHash(hash);
        localStorage[Constants.userHashKey] = sHash;
    };

    LocalStore.getBlockHash = function () {
        return localStorage[Constants.blockHashKey];
    };

    LocalStore.setBlockHash = function (hash) {
        localStorage[Constants.blockHashKey] = hash;
    };

    LocalStore.getAccountName = function () {
        return localStorage[Constants.userNameKey];
    };

    LocalStore.isLoggedIn = function () {
        return typeof getUserHash() === "string";
    };

    LocalStore.login = function (hash, name, cb) {
        if (!hash) { throw new Error('expected a user hash'); }
        if (!name) { throw new Error('expected a user name'); }
        hash = Hash.serializeHash(hash);
        localStorage.setItem(Constants.userHashKey, hash);
        localStorage.setItem(Constants.userNameKey, name);
        if (cb) { cb(); }
    };
    var eraseTempSessionValues = LocalStore.eraseTempSessionValues = function () {
        // delete sessionStorage values that might have been left over
        // from the main page's /user redirect
        [
            'login',
            'login_user',
            'login_pass',
            'login_rmb',
            'register'
        ].forEach(function (k) {
            delete sessionStorage[k];
        });
    };
    var logoutHandlers = [];
    LocalStore.logout = function (cb, isDeletion) {
        [
            Constants.userNameKey,
            Constants.userHashKey,
            Constants.blockHashKey,
            'loginToken',
            'plan',
        ].forEach(function (k) {
            sessionStorage.removeItem(k);
            localStorage.removeItem(k);
            delete localStorage[k];
            delete sessionStorage[k];
        });
        LocalStore.clearThumbnail();
        // Make sure we have an FS_hash in localStorage before reloading all the tabs
        // so that we don't end up with tabs using different anon hashes
        if (!LocalStore.getFSHash()) {
            LocalStore.setFSHash(Hash.createRandomHash('drive'));
        }
        eraseTempSessionValues();

        if (!isDeletion) {
            logoutHandlers.forEach(function (h) {
                if (typeof (h) === "function") { h(); }
            });
        }

        if (typeof(AppConfig.customizeLogout) === 'function') {
            return void AppConfig.customizeLogout(cb);
        }

        if (cb) { cb(); }
    };
    var loginHandlers = [];
    LocalStore.loginReload = function () {
        loginHandlers.forEach(function (h) {
            if (typeof (h) === "function") { h(); }
        });
        document.location.reload();
    };
    LocalStore.onLogin = function (h) {
        if (typeof (h) !== "function") { return; }
        if (loginHandlers.indexOf(h) !== -1) { return; }
        loginHandlers.push(h);
    };
    LocalStore.onLogout = function (h) {
        if (typeof (h) !== "function") { return; }
        if (logoutHandlers.indexOf(h) !== -1) { return; }
        logoutHandlers.push(h);
    };

    return LocalStore;
});
<commit_msg>Clear localStorage settings on logout<commit_after>define([
    '/common/common-constants.js',
    '/common/common-hash.js',
    '/bower_components/localforage/dist/localforage.min.js',
    '/customize/application_config.js',
], function (Constants, Hash, localForage, AppConfig) {
    var LocalStore = {};

    LocalStore.setThumbnail = function (key, value, cb) {
        localForage.setItem(key, value, cb);
    };
    LocalStore.getThumbnail = function (key, cb) {
        localForage.getItem(key, cb);
    };
    LocalStore.clearThumbnail = function (cb) {
        cb = cb || function () {};
        localForage.clear(cb);
    };

    LocalStore.setFSHash = function (hash) {
        var sHash = Hash.serializeHash(hash);
        localStorage[Constants.fileHashKey] = sHash;
    };
    LocalStore.getFSHash = function () {
        var hash = localStorage[Constants.fileHashKey];

        if (['undefined', 'undefined/'].indexOf(hash) !== -1) {
            localStorage.removeItem(Constants.fileHashKey);
            return;
        }

        if (hash) {
            var sHash = Hash.serializeHash(hash);
            if (sHash !== hash) { localStorage[Constants.fileHashKey] = sHash; }
        }

        return hash;
    };

    var getUserHash = LocalStore.getUserHash = function () {
        var hash = localStorage[Constants.userHashKey];

        if (['undefined', 'undefined/'].indexOf(hash) !== -1) {
            localStorage.removeItem(Constants.userHashKey);
            return;
        }

        if (hash) {
            var sHash = Hash.serializeHash(hash);
            if (sHash !== hash) { localStorage[Constants.userHashKey] = sHash; }
        }

        return hash;
    };

    LocalStore.setUserHash = function (hash) {
        var sHash = Hash.serializeHash(hash);
        localStorage[Constants.userHashKey] = sHash;
    };

    LocalStore.getBlockHash = function () {
        return localStorage[Constants.blockHashKey];
    };

    LocalStore.setBlockHash = function (hash) {
        localStorage[Constants.blockHashKey] = hash;
    };

    LocalStore.getAccountName = function () {
        return localStorage[Constants.userNameKey];
    };

    LocalStore.isLoggedIn = function () {
        return typeof getUserHash() === "string";
    };

    LocalStore.login = function (hash, name, cb) {
        if (!hash) { throw new Error('expected a user hash'); }
        if (!name) { throw new Error('expected a user name'); }
        hash = Hash.serializeHash(hash);
        localStorage.setItem(Constants.userHashKey, hash);
        localStorage.setItem(Constants.userNameKey, name);
        if (cb) { cb(); }
    };
    var eraseTempSessionValues = LocalStore.eraseTempSessionValues = function () {
        // delete sessionStorage values that might have been left over
        // from the main page's /user redirect
        [
            'login',
            'login_user',
            'login_pass',
            'login_rmb',
            'register'
        ].forEach(function (k) {
            delete sessionStorage[k];
        });
    };
    var logoutHandlers = [];
    LocalStore.logout = function (cb, isDeletion) {
        [
            Constants.userNameKey,
            Constants.userHashKey,
            Constants.blockHashKey,
            'loginToken',
            'plan',
        ].forEach(function (k) {
            sessionStorage.removeItem(k);
            localStorage.removeItem(k);
            delete localStorage[k];
            delete sessionStorage[k];
        });
        try {
            Object.keys(localStorage || {}).forEach(function (k) {
                // Remvoe everything in localStorage except CACHE and FS_hash
                if (/^CRYPTPAD_CACHE/.test(k) || /^LESS_CACHE/.test(k) || k === Constants.fileHashKey) { return; }
                delete localStorage[k];
            });
        } catch (e) { console.error(e); }
        LocalStore.clearThumbnail();
        // Make sure we have an FS_hash in localStorage before reloading all the tabs
        // so that we don't end up with tabs using different anon hashes
        if (!LocalStore.getFSHash()) {
            LocalStore.setFSHash(Hash.createRandomHash('drive'));
        }
        eraseTempSessionValues();

        if (!isDeletion) {
            logoutHandlers.forEach(function (h) {
                if (typeof (h) === "function") { h(); }
            });
        }

        if (typeof(AppConfig.customizeLogout) === 'function') {
            return void AppConfig.customizeLogout(cb);
        }

        if (cb) { cb(); }
    };
    var loginHandlers = [];
    LocalStore.loginReload = function () {
        loginHandlers.forEach(function (h) {
            if (typeof (h) === "function") { h(); }
        });
        document.location.reload();
    };
    LocalStore.onLogin = function (h) {
        if (typeof (h) !== "function") { return; }
        if (loginHandlers.indexOf(h) !== -1) { return; }
        loginHandlers.push(h);
    };
    LocalStore.onLogout = function (h) {
        if (typeof (h) !== "function") { return; }
        if (logoutHandlers.indexOf(h) !== -1) { return; }
        logoutHandlers.push(h);
    };

    return LocalStore;
});
<|endoftext|>


<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

//******************************
// Class GestionnairePubs
function GestionnairePubs() {
  var self = this;

  var nbreClic, totalClic;
  var pubActuelle, totalPubs;

  // constructeur
  this.initialise = function(_parent) {
    self.parent = _parent;
    self.nbreClic = 0;
    self.pubActuelle = 0;
    self.totalClic = 0;
    self.totalPubs = 0;

  };

  this.parametrage = function() {

    self.totalClic = parseInt(pubsJson["config"]["frequence"]);
    self.totalPubs = parseInt(pubsJson["pubs"].length);

    console.log("self.totalClic : "+self.totalClic+" et self.totalPubs : "+self.totalPubs);

  };

  this.testAffichage = function(){
    self.nbreClic++;

    console.log("self.nbreClic : "+self.nbreClic);

    if(self.nbreClic >= self.totalClic){
      self.nbreClic = 0;
      return true;
    }else{
      return false;
    }
  };

  this.affichePub = function(){
    self.pubActuelle++;

    if(self.pubActuelle >= self.totalPubs){
      self.pubActuelle = 0;
    }

    console.log("pub à afficher : "+self.pubActuelle);

   //window.plugins.childBrowser.showWebPage('http://lebiscuit.free.fr/MT/',{ showLocationBar: false });

   var ref = window.open(pubsJson["pubs"][self.pubActuelle]['url'], '_blank', 'location=yes');

    // close InAppBrowser after X seconds if available
    if(pubsJson["pubs"][self.pubActuelle]['duration'] != 0)
    {
      setTimeout(function() {
          ref.close();
      }, pubsJson["pubs"][self.pubActuelle]['duration']);
    }

   self.nbreClic = 0;

  };

}<commit_msg>suppression barre url et toolbar et autorisation viewportscale<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

//******************************
// Class GestionnairePubs
function GestionnairePubs() {
  var self = this;

  var nbreClic, totalClic;
  var pubActuelle, totalPubs;

  // constructeur
  this.initialise = function(_parent) {
    self.parent = _parent;
    self.nbreClic = 0;
    self.pubActuelle = 0;
    self.totalClic = 0;
    self.totalPubs = 0;

  };

  this.parametrage = function() {

    self.totalClic = parseInt(pubsJson["config"]["frequence"]);
    self.totalPubs = parseInt(pubsJson["pubs"].length);

    console.log("self.totalClic : "+self.totalClic+" et self.totalPubs : "+self.totalPubs);

  };

  this.testAffichage = function(){
    self.nbreClic++;

    console.log("self.nbreClic : "+self.nbreClic);

    if(self.nbreClic >= self.totalClic){
      self.nbreClic = 0;
      return true;
    }else{
      return false;
    }
  };

  this.affichePub = function(){
    self.pubActuelle++;

    if(self.pubActuelle >= self.totalPubs){
      self.pubActuelle = 0;
    }

    console.log("pub à afficher : "+self.pubActuelle);

   //window.plugins.childBrowser.showWebPage('http://lebiscuit.free.fr/MT/',{ showLocationBar: false });

   var ref = window.open(pubsJson["pubs"][self.pubActuelle]['url'], '_blank', 'location=no,toolbar=no,enableViewportScale=yes,');

    // close InAppBrowser after X seconds if available
    if(pubsJson["pubs"][self.pubActuelle]['duration'] != 0)
    {
      setTimeout(function() {
          ref.close();
      }, pubsJson["pubs"][self.pubActuelle]['duration']);
    }

   self.nbreClic = 0;

  };

}<|endoftext|>


<commit_before>(function(angular, $, _) {

  angular.module('civicase').config(function($routeProvider) {
      $routeProvider.when('/case', {
        reloadOnSearch: false,
        controller: 'CivicaseDashboardCtrl',
        templateUrl: '~/civicase/DashboardCtrl.html'
      });
    }
  );

  angular.module('civicase').controller('CivicaseDashboardCtrl', function($scope) {
    var ts = $scope.ts = CRM.ts('civicase');
    $scope.$bindToRoute({
      param: 'dtab',
      expr: 'activeTab',
      format: 'json',
      default: 0
    });

    $scope.$bindToRoute({
      param: 'dme',
      expr: 'myCasesOnly',
      format: 'json',
      default: 0
    });
  });

})(angular, CRM.$, CRM._);
<commit_msg>CRM-20756 - civicaseDashboardCtrl - Fix URL bindings<commit_after>(function(angular, $, _) {

  angular.module('civicase').config(function($routeProvider) {
      $routeProvider.when('/case', {
        reloadOnSearch: false,
        controller: 'CivicaseDashboardCtrl',
        templateUrl: '~/civicase/DashboardCtrl.html'
      });
    }
  );

  angular.module('civicase').controller('CivicaseDashboardCtrl', function($scope) {
    var ts = $scope.ts = CRM.ts('civicase');
    $scope.$bindToRoute({
      param: 'dtab',
      expr: 'activeTab',
      format: 'int',
      default: 0
    });

    $scope.$bindToRoute({
      param: 'dme',
      expr: 'myCasesOnly',
      format: 'bool',
      default: false
    });
  });

})(angular, CRM.$, CRM._);
<|endoftext|>


<commit_before>module.exports = function (grunt) {
  'use strict';

  grunt.initConfig({
    clean: {
      build: './dist/*'
    },

    babel: {
      options: {
        sourceMap: false,
        optional: ['spec.protoToAssign']
      },
      common: {
        options: {
          modules: 'common'
        },
        files: [{
          expand: true,
          cwd: 'src/',
          src: ['**/*.js'],
          dest: 'dist/'
        }]
      },
    },

    watch: {
      transpile: {
        files: 'src/**/*.js',
        tasks: ['babel']
      }
    },

    jshint: {
      options: {
        force: true,
        jshintrc: '../../.jshintrc'
      },
      lib: {
        src: 'src/**/*.js'
      },
      gruntfile: {
        src: 'Gruntfile.js'
      }
    },

    release: {
      options: {
        file: 'package.json',
        npm: true
      }
    },

    protractor: {
      options: {
        configFile: 'conf.js',
        keepAlive: true,
        noColor: true
      },
      test: {
        button: {
          options: {
            configFile: 'conf.js'
          }
        }
      }
    }

  });

  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-release');
  grunt.loadNpmTasks('grunt-babel');
  grunt.loadNpmTasks('grunt-protractor-runner');

  grunt.registerTask('default', ['clean', 'jshint', 'babel']);
  grunt.registerTask('dev', ['clean', 'jshint', 'babel', 'watch']);
  grunt.registerTask('test', ['protractor:test']);
};
<commit_msg>fix jshint path<commit_after>module.exports = function (grunt) {
  'use strict';

  grunt.initConfig({
    clean: {
      build: './dist/*'
    },

    babel: {
      options: {
        sourceMap: false,
        optional: ['spec.protoToAssign']
      },
      common: {
        options: {
          modules: 'common'
        },
        files: [{
          expand: true,
          cwd: 'src/',
          src: ['**/*.js'],
          dest: 'dist/'
        }]
      },
    },

    watch: {
      transpile: {
        files: 'src/**/*.js',
        tasks: ['babel']
      }
    },

    jshint: {
      options: {
        force: true,
        jshintrc: '../.jshintrc'
      },
      lib: {
        src: 'src/**/*.js'
      },
      gruntfile: {
        src: 'Gruntfile.js'
      }
    },

    release: {
      options: {
        file: 'package.json',
        npm: true
      }
    },

    protractor: {
      options: {
        configFile: 'conf.js',
        keepAlive: true,
        noColor: true
      },
      test: {
        button: {
          options: {
            configFile: 'conf.js'
          }
        }
      }
    }

  });

  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-release');
  grunt.loadNpmTasks('grunt-babel');
  grunt.loadNpmTasks('grunt-protractor-runner');

  grunt.registerTask('default', ['clean', 'jshint', 'babel']);
  grunt.registerTask('dev', ['clean', 'jshint', 'babel', 'watch']);
  grunt.registerTask('test', ['protractor:test']);
};
<|endoftext|>


<commit_before>import React, { Component } from 'react'
import { kea, useActions, useValues } from 'kea'

import { Button, Tree, Icon, Tag } from 'antd'

import Node from './node'
import { columnIcon } from '../../connection/subset/form/models/edit-field'

import explorerLogic from 'scenes/explorer/logic'
import viewsLogic from 'scenes/header/views/logic'
import { useSelector } from 'react-redux'
import locationSelector from 'lib/selectors/location'
import naturalCompare from 'string-natural-compare'
import HighlightText from 'lib/utils/highlight-text'
import FavouriteStar from './node/favourite-star'
import FilterButton from './node/filter-button'

const { TreeNode } = Tree;

const logic = kea({
  connect: {
    values: [
      explorerLogic, ['structure', 'selectedModel']
    ]
  },
  selectors: ({ selectors }) => ({
    sortedStructure: [
      () => [selectors.structure],
      (structure) => {
        const newStructure = {}

        Object.entries(structure).sort((a, b) => naturalCompare(a[0], b[0])).forEach(([model, { custom, columns, links }]) => {
          newStructure[model] = [
            ...Object.entries(custom).map(([key, meta]) => ({ key, type: 'custom', meta, editType: 'old' })),
            ...Object.entries(columns).map(([key, meta]) => ({ key, type: 'column', meta, editType: 'old' })),
            ...Object.entries(links).map(([key, meta]) => ({ key, type: 'link', meta, editType: 'old' }))
          ].sort((a, b) => naturalCompare(a.key, b.key))
        })

        return newStructure
      }
    ],
  })
})

const stringIn = (search, string) => {
  let i = 0
  const s = search.toLowerCase()
  string.toLowerCase().split('').forEach(letter => {
    if (i < s.length && s[i] === letter) {
      i++
    }
  })
  return i >= s.length
}

function renderTreeNodes ({ key, path, field, localSearch, model, focusSearch, sortedStructure, treeState }) {
  const childNodes = Object.values(sortedStructure[model] || {})

  const title = field
    ? (
      <>
        {localSearch ? <HighlightText highlight={localSearch}>{key}</HighlightText> : key}
        {' '}
        {field.type === 'link' ? (
          <Icon type='link' /> {field.meta.model}
        ) : (

            <FavouriteStar path={path} />
            <FilterButton path={path} />

        )}
      </>
    ) : {model}

  return (
    <TreeNode key={path}
              isLeaf={field && field.type !== 'link'}
              title={title}
              className={field ? `field-type-${field.type}` : ''}
              switcherIcon={field && field.type !== 'link' ? <Icon type={columnIcon[field.meta.type] || 'question-circle'} /> : null}>
      {treeState[path] && childNodes.
        filter(child => !localSearch || stringIn(localSearch.split(' ')[0], `${path}.${child.key}`)).
        map(child => {
          return renderTreeNodes({
            path: `${path}.${child.key}`,
            field: child,
            model: child.meta && child.meta.model,
            localSearch: localSearch.split(' ').slice(1).join(' '),
            key: child.key,
            focusSearch: focusSearch,
            sortedStructure,
            treeState
          })
        })}
    </TreeNode>
  )
}

export default function SelectedModel () {
  const { selectedModel, savedViews, modelFavourites, search, treeState, expandedKeys } = useValues(explorerLogic)
  const { closeModel, focusSearch, openUrl, closeTreeNode, openTreeNode, setExpandedKeys } = useActions(explorerLogic)

  const { sortedStructure } = useValues(logic)

  const { openView } = useActions(viewsLogic)
  const { pathname: urlPath, search: urlSearch } = useSelector(locationSelector)

  const url = urlPath + urlSearch

  function onTreeClick (key) {
    console.log(key)
  }

  return (

        <Button type='link' icon='close' style={{float: 'right'}} onClick={closeModel} />

{selectedModel}

      <Tree
        showIcon
        switcherIcon={<Icon type="down" />}
        expandedKeys={expandedKeys}
        onExpand={setExpandedKeys}
        selectable
        selectedKeys={[]}
        onSelect={(([key]) => onTreeClick(key))}
      >
        {/*<TreeNode title={<>Saved views (0)</>} key="...saved">*/}
        {/*  <TreeNode title="id" switcherIcon={<Icon type='idcard' />} key="saved-1" />*/}
        {/*</TreeNode>*/}
        {/*<TreeNode title={<>Favourite fields (0)</>} key="...favourite">*/}
        {/*  <TreeNode title="id" switcherIcon={<Icon type='idcard' />} key="favourite-1" />*/}
        {/*</TreeNode>*/}
        {renderTreeNodes({ key: selectedModel, path: selectedModel, localSearch: search, model: selectedModel, focusSearch, sortedStructure, treeState, closeTreeNode, openTreeNode })}
      </Tree>

            Saved views ({savedViews.length})

          {savedViews.map(view => (

 openView(view._id)}
                  style={{ fontWeight: url === view.path ? 'bold' : 'normal' }}>
                  {view.name}

          ))}

            Favourite fields ({modelFavourites.length})

          {modelFavourites.map(favourite => (
            <Node
              key={favourite}
              path={favourite}
              localSearch=''
              connection={favourite.substring(selectedModel.length + 1)}
              focusSearch={focusSearch} />
          ))}

      <Node key={selectedModel}
            path={selectedModel}
            localSearch={search}
            model={selectedModel}
            focusSearch={focusSearch} />

  )
}
<commit_msg>show idcard for primary key<commit_after>import React, { Component } from 'react'
import { kea, useActions, useValues } from 'kea'

import { Button, Tree, Icon, Tag } from 'antd'

import Node from './node'
import { columnIcon } from '../../connection/subset/form/models/edit-field'

import explorerLogic from 'scenes/explorer/logic'
import viewsLogic from 'scenes/header/views/logic'
import { useSelector } from 'react-redux'
import locationSelector from 'lib/selectors/location'
import naturalCompare from 'string-natural-compare'
import HighlightText from 'lib/utils/highlight-text'
import FavouriteStar from './node/favourite-star'
import FilterButton from './node/filter-button'

const { TreeNode } = Tree;

const logic = kea({
  connect: {
    values: [
      explorerLogic, ['structure', 'selectedModel']
    ]
  },
  selectors: ({ selectors }) => ({
    sortedStructure: [
      () => [selectors.structure],
      (structure) => {
        const newStructure = {}

        Object.entries(structure).sort((a, b) => naturalCompare(a[0], b[0])).forEach(([model, { custom, columns, links }]) => {
          newStructure[model] = [
            ...Object.entries(custom).map(([key, meta]) => ({ key, type: 'custom', meta, editType: 'old' })),
            ...Object.entries(columns).map(([key, meta]) => ({ key, type: 'column', meta, editType: 'old' })),
            ...Object.entries(links).map(([key, meta]) => ({ key, type: 'link', meta, editType: 'old' }))
          ].sort((a, b) => naturalCompare(a.key, b.key))
        })

        return newStructure
      }
    ],
  })
})

const stringIn = (search, string) => {
  let i = 0
  const s = search.toLowerCase()
  string.toLowerCase().split('').forEach(letter => {
    if (i < s.length && s[i] === letter) {
      i++
    }
  })
  return i >= s.length
}

function renderTreeNodes ({ key, path, field, localSearch, model, focusSearch, sortedStructure, treeState }) {
  const childNodes = Object.values(sortedStructure[model] || {})

  const title = field
    ? (
      <>
        {localSearch ? <HighlightText highlight={localSearch}>{key}</HighlightText> : key}
        {' '}
        {field.type === 'link' ? (
          <Icon type='link' /> {field.meta.model}
        ) : (

            <FavouriteStar path={path} />
            <FilterButton path={path} />

        )}
      </>
    ) : {model}

  return (
    <TreeNode key={path}
              isLeaf={field && field.type !== 'link'}
              title={title}
              className={field ? `field-type-${field.type}` : ''}
              switcherIcon={field && field.type !== 'link' ? <Icon type={field.meta.index === 'primary_key' ? 'idcard' : (columnIcon[field.meta.type] || 'question-circle')} /> : null}>
      {treeState[path] && childNodes.
        filter(child => !localSearch || stringIn(localSearch.split(' ')[0], `${path}.${child.key}`)).
        map(child => {
          return renderTreeNodes({
            path: `${path}.${child.key}`,
            field: child,
            model: child.meta && child.meta.model,
            localSearch: localSearch.split(' ').slice(1).join(' '),
            key: child.key,
            focusSearch: focusSearch,
            sortedStructure,
            treeState
          })
        })}
    </TreeNode>
  )
}

export default function SelectedModel () {
  const { selectedModel, savedViews, modelFavourites, search, treeState, expandedKeys } = useValues(explorerLogic)
  const { closeModel, focusSearch, openUrl, closeTreeNode, openTreeNode, setExpandedKeys } = useActions(explorerLogic)

  const { sortedStructure } = useValues(logic)

  const { openView } = useActions(viewsLogic)
  const { pathname: urlPath, search: urlSearch } = useSelector(locationSelector)

  const url = urlPath + urlSearch

  function onTreeClick (key) {
    console.log(key)
  }

  return (

        <Button type='link' icon='close' style={{float: 'right'}} onClick={closeModel} />

{selectedModel}

      <Tree
        showIcon
        switcherIcon={<Icon type="down" />}
        expandedKeys={expandedKeys}
        onExpand={setExpandedKeys}
        selectable
        selectedKeys={[]}
        onSelect={(([key]) => onTreeClick(key))}
      >
        {/*<TreeNode title={<>Saved views (0)</>} key="...saved">*/}
        {/*  <TreeNode title="id" switcherIcon={<Icon type='idcard' />} key="saved-1" />*/}
        {/*</TreeNode>*/}
        {/*<TreeNode title={<>Favourite fields (0)</>} key="...favourite">*/}
        {/*  <TreeNode title="id" switcherIcon={<Icon type='idcard' />} key="favourite-1" />*/}
        {/*</TreeNode>*/}
        {renderTreeNodes({ key: selectedModel, path: selectedModel, localSearch: search, model: selectedModel, focusSearch, sortedStructure, treeState, closeTreeNode, openTreeNode })}
      </Tree>

            Saved views ({savedViews.length})

          {savedViews.map(view => (

 openView(view._id)}
                  style={{ fontWeight: url === view.path ? 'bold' : 'normal' }}>
                  {view.name}

          ))}

            Favourite fields ({modelFavourites.length})

          {modelFavourites.map(favourite => (
            <Node
              key={favourite}
              path={favourite}
              localSearch=''
              connection={favourite.substring(selectedModel.length + 1)}
              focusSearch={focusSearch} />
          ))}

      <Node key={selectedModel}
            path={selectedModel}
            localSearch={search}
            model={selectedModel}
            focusSearch={focusSearch} />

  )
}
<|endoftext|>


<commit_before>// @flow

import React from "react";
import { ChoiceType, QuestionType, AddressType } from "../../types";
import type {
  QuestionSubmissionsMapType
} from "../../types/QuestionSubmissionsMapType";
import type {
  QuestionSubmissionMapValueType
} from "../../types/QuestionSubmissionMapValueType";
import {
  String,
  Content,
  Text,
  Boolean,
  Select,
  MultiSelect,
  Checkboxes,
  Radio
} from "./widgets";
import { List } from "immutable";
import EmailValidator from "./Validators/EmailValidator";
import NumberValidator from "./Validators/NumberValidator";
import Address from "./widgets/Address";

type Props = {
  question: QuestionType,
  submission: QuestionSubmissionMapValueType,
  submissions: QuestionSubmissionsMapType,
  setSubmission: Function,
  addError: Function,
  removeError: Function,
  errorMessage: string
};

function renderQuestion(props: Props) {
  const {
    question,
    submission,
    setSubmission,
    addError,
    removeError,
    errorMessage
  } = props;
  const id = `${question.get("id")}`;
  const required = question.required;
  const questionWidget = getQuestionWidget(
    question.get("type"),
    question.get("validateAs"),
    question.get("placeholder"),
    id,
    question.get("content"),
    question.get("label"),
    required,
    submission,
    setSubmission,
    addError,
    removeError,
    question.get("choices"),
    errorMessage
  );

  let requiredElement;
  if (required) {
    requiredElement =  (required);
  } else {
    requiredElement = "";
  }

  return (

        {labelForElement(question)}
        {requiredElement}

      {questionWidget}

  );
}

function labelForElement(question: QuestionType) {
  if (question.get("type") === "boolean") {
    return "";
  } else {
    return question.get("label");
  }
}

function shouldDisplayQuestion(props: Props) {
  const { question, submissions } = props;
  const dependency = question.questionDependency;
  if (dependency) {
    const dependentChoicesSelected =
      // for each dependency choice
      dependency.choices
        .map(choice => {
          return submissions.find((submissionList, key) => {
            return !!submissionList.find(qs => qs.value === `${choice.id}`);
          });
        })
        .filter(a => a !== undefined);

    if (dependentChoicesSelected.size > 0) {
      return dependency.display;
    } else {
      return !dependency.display;
    }
  } else {
    return true;
  }
}

export default function Question(props: Props) {
  if (shouldDisplayQuestion(props)) {
    return renderQuestion(props);
  } else {
    return
;
  }
}

function getQuestionWidget(
  type: string,
  validateAs: string,
  placeholder: string,
  id: string,
  content: string,
  label: string,
  required: boolean,
  submission: QuestionSubmissionMapValueType,
  setSubmission: Function,
  addError: Function,
  removeError: Function,
  choices: List<ChoiceType>,
  errorMessage: string
) {
  const onChange = e => {
    if (validateAs === "email") {
      if (EmailValidator.valid(e.target.value)) {
        removeError(id);
      } else {
        addError(id, "This is not an email");
      }
    }

    if (validateAs === "number") {
      if (NumberValidator.valid(e.target.value)) {
        removeError(id);
      } else {
        addError(id, "This is not a number");
      }
    }
    setSubmission(id, List([e.target.value]), type);
  };
  const onChangeCheckBox = e =>
    setSubmission(id, List([e.target.checked]), type);
  const onChangeRadio = value => setSubmission(id, List([value]), type);
  const onChangeMultiSelect = values => setSubmission(id, List(values), type);
  const onAddressChange = address => setSubmission(id, List([address]), type);
  // FIXME: handle multiselect
  switch (type) {
    case "content":
      return <Content content={content} />;
    case "string":
      return (
        <String
          id={id}
          content={content}
          placeholder={placeholder}
          value={submission.get(0) ? submission.get(0).get("value") : ""}
          onChange={onChange}
          errorMessage={errorMessage}
          required={required}
        />
      );
    case "text":
      return (
        <Text
          id={id}
          content={content}
          placeholder={placeholder}
          value={submission.get(0) ? submission.get(0).get("value") : ""}
          onChange={onChange}
        />
      );
    case "address":
      return (
        <Address
          id={id}
          content={content}
          placeholder={placeholder}
          value={
            submission.get(0)
              ? submission.get(0).get("value")
              : new AddressType()
          }
          onChange={onAddressChange}
        />
      );
    case "boolean":
      return (
        <Boolean
          id={id}
          label={label}
          content={content}
          value={submission.get(0) ? submission.get(0).get("value") : ""}
          onChange={onChangeCheckBox}
        />
      );
    case "select":
      return (
        <Select
          content={content}
          id={id}
          value={submission.get(0) ? submission.get(0).get("value") : ""}
          onChange={onChange}
          choices={choices}
        />
      );
    case "multi_select":
      return (
        <MultiSelect
          content={content}
          id={id}
          values={submission.map(x => x.get("value"))}
          onChange={onChangeMultiSelect}
          choices={choices}
        />
      );
    case "checkboxes":
      return <Checkboxes choices={choices} />;
    case "radio":
      return (
        <Radio
          name={"radio-1"}
          content={content}
          id={id}
          value={submission.get(0) ? submission.get(0).get("value") : ""}
          onChange={onChangeRadio}
          choices={choices}
        />
      );
    default:
      return
;
  }
}
<commit_msg>Fix MultiSelect in RespondToForm component<commit_after>// @flow

import React from "react";
import { ChoiceType, QuestionType, AddressType } from "../../types";
import type {
  QuestionSubmissionsMapType
} from "../../types/QuestionSubmissionsMapType";
import type {
  QuestionSubmissionMapValueType
} from "../../types/QuestionSubmissionMapValueType";
import {
  String,
  Content,
  Text,
  Boolean,
  Select,
  MultiSelect,
  Checkboxes,
  Radio
} from "./widgets";
import { List } from "immutable";
import EmailValidator from "./Validators/EmailValidator";
import NumberValidator from "./Validators/NumberValidator";
import Address from "./widgets/Address";

type Props = {
  question: QuestionType,
  submission: QuestionSubmissionMapValueType,
  submissions: QuestionSubmissionsMapType,
  setSubmission: Function,
  addError: Function,
  removeError: Function,
  errorMessage: string
};

function renderQuestion(props: Props) {
  const {
    question,
    submission,
    setSubmission,
    addError,
    removeError,
    errorMessage
  } = props;
  const id = `${question.get("id")}`;
  const required = question.required;
  const questionWidget = getQuestionWidget(
    question.get("type"),
    question.get("validateAs"),
    question.get("placeholder"),
    id,
    question.get("content"),
    question.get("label"),
    required,
    submission,
    setSubmission,
    addError,
    removeError,
    question.get("choices"),
    errorMessage
  );

  let requiredElement;
  if (required) {
    requiredElement =  (required);
  } else {
    requiredElement = "";
  }

  return (

        {labelForElement(question)}
        {requiredElement}

      {questionWidget}

  );
}

function labelForElement(question: QuestionType) {
  if (question.get("type") === "boolean") {
    return "";
  } else {
    return question.get("label");
  }
}

function shouldDisplayQuestion(props: Props) {
  const { question, submissions } = props;
  const dependency = question.questionDependency;
  if (dependency) {
    const dependentChoicesSelected =
      // for each dependency choice
      dependency.choices
        .map(choice => {
          return submissions.find((submissionList, key) => {
            return !!submissionList.find(qs => qs.value === `${choice.id}`);
          });
        })
        .filter(a => a !== undefined);

    if (dependentChoicesSelected.size > 0) {
      return dependency.display;
    } else {
      return !dependency.display;
    }
  } else {
    return true;
  }
}

export default function Question(props: Props) {
  if (shouldDisplayQuestion(props)) {
    return renderQuestion(props);
  } else {
    return
;
  }
}

function getQuestionWidget(
  type: string,
  validateAs: string,
  placeholder: string,
  id: string,
  content: string,
  label: string,
  required: boolean,
  submission: QuestionSubmissionMapValueType,
  setSubmission: Function,
  addError: Function,
  removeError: Function,
  choices: List<ChoiceType>,
  errorMessage: string
) {
  const onChange = e => {
    if (validateAs === "email") {
      if (EmailValidator.valid(e.target.value)) {
        removeError(id);
      } else {
        addError(id, "This is not an email");
      }
    }

    if (validateAs === "number") {
      if (NumberValidator.valid(e.target.value)) {
        removeError(id);
      } else {
        addError(id, "This is not a number");
      }
    }
    setSubmission(id, List([e.target.value]), type);
  };
  const onChangeCheckBox = e =>
    setSubmission(id, List([e.target.checked]), type);
  const onChangeRadio = value => setSubmission(id, List([value]), type);
  const onChangeMultiSelect = values => setSubmission(id, List(values), type);
  const onAddressChange = address => setSubmission(id, List([address]), type);
  // FIXME: handle multiselect
  switch (type) {
    case "content":
      return <Content content={content} />;
    case "string":
      return (
        <String
          id={id}
          content={content}
          placeholder={placeholder}
          value={submission.get(0) ? submission.get(0).get("value") : ""}
          onChange={onChange}
          errorMessage={errorMessage}
          required={required}
        />
      );
    case "text":
      return (
        <Text
          id={id}
          content={content}
          placeholder={placeholder}
          value={submission.get(0) ? submission.get(0).get("value") : ""}
          onChange={onChange}
        />
      );
    case "address":
      return (
        <Address
          id={id}
          content={content}
          placeholder={placeholder}
          value={
            submission.get(0)
              ? submission.get(0).get("value")
              : new AddressType()
          }
          onChange={onAddressChange}
        />
      );
    case "boolean":
      return (
        <Boolean
          id={id}
          label={label}
          content={content}
          value={submission.get(0) ? submission.get(0).get("value") : ""}
          onChange={onChangeCheckBox}
        />
      );
    case "select":
      return (
        <Select
          content={content}
          id={id}
          value={submission.get(0) ? submission.get(0).get("value") : ""}
          onChange={onChange}
          choices={choices}
        />
      );
    case "multiselect":
      return (
        <MultiSelect
          content={content}
          id={id}
          values={submission.map(x => x.get("value"))}
          onChange={onChangeMultiSelect}
          choices={choices}
        />
      );
    case "checkboxes":
      return <Checkboxes choices={choices} />;
    case "radio":
      return (
        <Radio
          name={"radio-1"}
          content={content}
          id={id}
          value={submission.get(0) ? submission.get(0).get("value") : ""}
          onChange={onChangeRadio}
          choices={choices}
        />
      );
    default:
      return
;
  }
}
<|endoftext|>


<commit_before>import Ember from 'ember';

export default Ember.Controller.extend({
    actions: {
        addProperty: function (entity, property, value, prefix) {
            var normalizedValue = value;

            var prefixBase = 10;
            var prefixPower = 0;

            if (Ember.isEmpty(prefix)) {
                var pattern = /^(\d+)((\D+)(\d+)?)?(\D+)?$/i;
                var full, whole, ign, separator, frac, suffix;
                var match = value.match(pattern);

                if (match == null) {
                    this.growl.error("Cannot parse "+value);
                    return;
                }

                [full, whole, ign, separator, frac, suffix] = match;

                if (whole == null && frac == null) {
                    this.growl.error("Cannot parse value "+value);
                    return;
                }

                // When 1k5 format is used it has a priority
                if (separator && separator != ".") {
                    suffix = separator;
                }

                // Support micro sign 'µ' alias 'u'
                if (separator == "u") {
                    separator = "µ";
                }

                console.log([full, whole, ign, separator, frac, suffix]);

                var unit = property.get('unit.symbol');
                var foundPrefix = null;
                var prefixScore = 0;

                if (suffix) {
                    property.get('unit.prefixes').forEach(function (prefix) {
                        console.log(prefix.get('prefix') + unit);
                        if (prefix.get('prefix') == suffix && prefixScore < 4) {
                            foundPrefix = prefix;
                            prefixScore = 4;
                        } else if (prefix.get('prefix') + unit == suffix && prefixScore < 5) {
                            foundPrefix = prefix;
                            prefixScore = 5;
                        } else if (prefix.get('prefix').toLowerCase() == suffix.toLowerCase() && prefixScore < 2) {
                            foundPrefix = prefix;
                            prefixScore = 2;
                        } else if ((prefix.get('prefix') + unit).toLowerCase() == suffix.toLowerCase() && prefixScore < 3) {
                            foundPrefix = prefix;
                            prefixScore = 3;
                        }
                    });
                }

                if (suffix && foundPrefix == null) {
                    this.growl.error("Cannot parse units in " + value);
                    return;
                }

                value = parseFloat((whole ? whole : "0") + "." + (frac ? frac : "0"));
                if (foundPrefix) {
                    prefixBase = foundPrefix.get('base');
                    prefixPower = foundPrefix.get('power');
                }
            } else {
                prefixBase = prefix.get('base');
                prefixPower = prefix.get('power');
            }

            var baseBase = property.get('base.base');
            var basePower = property.get('base.power');
            var multiplyPower = Math.pow(prefixBase, prefixPower) / Math.pow(baseBase, basePower);
            normalizedValue = value * multiplyPower;

            var propertyId = property.get('id');
            entity.get('properties').pushObject(property);

            var values = entity.get('values');
            values.set(propertyId, normalizedValue);

            var self = this;
            entity.save().catch(function (e) {
                e.rollback();
            });
        },
        removeProperty: function (entity, property) {
            entity.get('properties').removeObject(property);
            entity.get('values').set(property.get('id'), null);

            entity.save().catch(function (e) {
                e.rollback();
            });
        },
        enableAddProperty: function () {
            this.set('propertyAddingAllowed', true);
        },
        disableAddProperty: function () {
            this.set('propertyAddingAllowed', false);
        },
        createEmptyGroup: function (name) {
            var self = this;
            var g = this.store.createRecord('group', {
                name: name,
                flagged: true
            });

            g.save().catch(function () {
                g.destroy();
            }).then(function (g) {
                self.get('model.groups').pushObject(g);
                self.get('model').save().catch(function (e) {
                    self.get('model.groups').removeObject(g);
                });
            });
        },
        removeGroup: function (group) {
            var model = this.model;
            model.get('groups').removeObject(group);
            model.save().catch(function () {
                model.rollback();
            });
        },
        showAddGroup: function () {
            this.set('displayAddGroup', true);
        },
        hideAddGroup: function () {
            this.set('displayAddGroup', false);
        },
        createEmptyFootprint: function (name) {
            var self = this;

            var g = this.store.createRecord('footprint', {
                name: name,
                flagged: true
            });

            g.save().catch(function () {
                g.destroy();
            }).then(function (fp) {
                self.get('model.footprints').pushObject(fp);
                self.get('model').save().catch(function (e) {
                    self.get('model.footprints').removeObject(fp);
                });
            });
        },
        removeFootprint: function (footprint) {
            var model = this.model;
            model.get('footprints').removeObject(footprint);
            model.save().catch(function () {
                model.rollback();
            });
        },
        showAddFootprint: function () {
            this.set('displayAddFootprint', true);
        },
        hideAddFootprint: function () {
            this.set('displayAddFootprint', false);
        },
        addSeeAlso: function (type) {
            var model = this.model;
            if (type == this.model) {
                return;
            }

            model.get('seeAlso').pushObject(type);
            model.save().catch(function () {
                model.rollback();
            });
        },
        removeSeeAlso: function (type) {
            var model = this.model;
            model.get('seeAlso').removeObject(type);
            model.save().catch(function () {
                model.rollback();
            });
        },
        showAddSeeAlso: function () {
            this.set('displayAddSeeAlso', true);
        },
        hideAddSeeAlso: function () {
            this.set('displayAddSeeAlso', false);
        },
        createBox: function (name) {
            var box = this.store.createRecord('box', {
                name: name,
                flagged: true
            });

            box.save().catch(function (err) {
                this.growl.error(err);
                box.destroy();
            });
        },
        showMoveLot: function (lot) {
            this.set('moveLot', lot);
            this.set('moveLotCount', lot.get('count'));
            this.set('moveLotToBox', lot.get('location'));
        },
        moveLot: function (lot, destination, count) {
            // close dialog
            this.set('moveLot', null);
            // bubble up
            return true;
        }
    },
    needs: "application",
    propertySorting: ['name'],
    sortedProperties: Ember.computed.sort('controllers.application.availableProperties', 'propertySorting'),

    typeSorting: ['fullName'],
    sortedTypes: Ember.computed.sort('controllers.application.availableTypes', 'typeSorting'),

    groupSorting: ['fullName'],
    sortedGroups: Ember.computed.sort('controllers.application.availableGroups', 'groupSorting'),

    footprintSorting: ['fullName'],
    sortedFootprints: Ember.computed.sort('controllers.application.availableFootprints', 'footprintSorting'),

    boxSorting: ['fullName'],
    sortedBoxes: Ember.computed.sort('controllers.application.availableLocations', 'boxSorting'),

    unitPrefixes: function () {
        return this.get('propertyToAdd.unit.prefixes');
    }.property('propertyToAdd.unit.prefixes', 'propertyToAdd.unit.prefixes.@each'),

    unitHint: function () {
        if (this.get('propertyValuePrefixToAdd')) {
            return "Enter value: 1 or 1.5";
        } else {
            var symbol = this.get('propertyToAdd.unit.symbol');
            var prefix = "p";

            var prefixes = this.get('propertyToAdd.unit.prefixes');
            console.log(prefixes);

            if (prefixes && prefixes.get('length') > 0) {
                var single = prefixes.get('firstObject');
                console.log(single);
                if (single) {
                    prefix = single.get('prefix');
                    console.log(prefix);
                }
            }
            var t = "Enter value: 1, 1.5, 1" + prefix + "5, 1.5" + prefix;
            if (symbol) {
                t += ", 1" + prefix + "5" + symbol + ", 1" + prefix + symbol + ", 1.5" + prefix + symbol;
            }
            return t;
        }
    }.property('propertyToAdd.unit', 'propertyToAdd.unit.symbol', 'propertyValuePrefixToAdd',
        'propertyToAdd.unit.prefixes', 'propertyToAdd.unit.prefixes.@each'),

    prefixSorting: ['power10'],
    sortedUnitPrefixes: Ember.computed.sort('unitPrefixes', 'prefixSorting'),

    propertyAddingAllowed: false,
    addPropertyIncomplete: function () {
        return Ember.isEmpty(this.get('propertyToAdd')) || Ember.isEmpty(this.get('propertyValueToAdd'));
    }.property('propertyToAdd', 'propertyValueToAdd'),

    moveLotToBox: null,
    moveLotDisabled: function () {
        return Ember.isEmpty(this.get('moveLotToBox')) || Ember.isEmpty(this.get('moveLotCount'));
    }.property('moveLotToBox', 'moveLotCount')
});
<commit_msg>Save footprint and group changes in type immediately<commit_after>import Ember from 'ember';

export default Ember.Controller.extend({
    actions: {
        addProperty: function (entity, property, value, prefix) {
            var normalizedValue = value;

            var prefixBase = 10;
            var prefixPower = 0;

            if (Ember.isEmpty(prefix)) {
                var pattern = /^(\d+)((\D+)(\d+)?)?(\D+)?$/i;
                var full, whole, ign, separator, frac, suffix;
                var match = value.match(pattern);

                if (match == null) {
                    this.growl.error("Cannot parse "+value);
                    return;
                }

                [full, whole, ign, separator, frac, suffix] = match;

                if (whole == null && frac == null) {
                    this.growl.error("Cannot parse value "+value);
                    return;
                }

                // When 1k5 format is used it has a priority
                if (separator && separator != ".") {
                    suffix = separator;
                }

                // Support micro sign 'µ' alias 'u'
                if (separator == "u") {
                    separator = "µ";
                }

                console.log([full, whole, ign, separator, frac, suffix]);

                var unit = property.get('unit.symbol');
                var foundPrefix = null;
                var prefixScore = 0;

                if (suffix) {
                    property.get('unit.prefixes').forEach(function (prefix) {
                        console.log(prefix.get('prefix') + unit);
                        if (prefix.get('prefix') == suffix && prefixScore < 4) {
                            foundPrefix = prefix;
                            prefixScore = 4;
                        } else if (prefix.get('prefix') + unit == suffix && prefixScore < 5) {
                            foundPrefix = prefix;
                            prefixScore = 5;
                        } else if (prefix.get('prefix').toLowerCase() == suffix.toLowerCase() && prefixScore < 2) {
                            foundPrefix = prefix;
                            prefixScore = 2;
                        } else if ((prefix.get('prefix') + unit).toLowerCase() == suffix.toLowerCase() && prefixScore < 3) {
                            foundPrefix = prefix;
                            prefixScore = 3;
                        }
                    });
                }

                if (suffix && foundPrefix == null) {
                    this.growl.error("Cannot parse units in " + value);
                    return;
                }

                value = parseFloat((whole ? whole : "0") + "." + (frac ? frac : "0"));
                if (foundPrefix) {
                    prefixBase = foundPrefix.get('base');
                    prefixPower = foundPrefix.get('power');
                }
            } else {
                prefixBase = prefix.get('base');
                prefixPower = prefix.get('power');
            }

            var baseBase = property.get('base.base');
            var basePower = property.get('base.power');
            var multiplyPower = Math.pow(prefixBase, prefixPower) / Math.pow(baseBase, basePower);
            normalizedValue = value * multiplyPower;

            var propertyId = property.get('id');
            entity.get('properties').pushObject(property);

            var values = entity.get('values');
            values.set(propertyId, normalizedValue);

            var self = this;
            entity.save().catch(function (e) {
                e.rollback();
            });
        },
        removeProperty: function (entity, property) {
            entity.get('properties').removeObject(property);
            entity.get('values').set(property.get('id'), null);

            entity.save().catch(function (e) {
                e.rollback();
            });
        },
        enableAddProperty: function () {
            this.set('propertyAddingAllowed', true);
        },
        disableAddProperty: function () {
            this.set('propertyAddingAllowed', false);
        },
        createEmptyGroup: function (name) {
            var self = this;
            var g = this.store.createRecord('group', {
                name: name,
                flagged: true
            });

            g.save().catch(function () {
                g.destroy();
            }).then(function (g) {
                self.get('model.groups').pushObject(g);
                self.get('model').save().catch(function (e) {
                    self.get('model.groups').removeObject(g);
                });
            });
        },
        removeGroup: function (group) {
            var model = this.model;
            model.get('groups').removeObject(group);
            model.save().catch(function () {
                model.rollback();
            });
        },
        showAddGroup: function () {
            this.set('displayAddGroup', true);
        },
        hideAddGroup: function () {
            this.set('displayAddGroup', false);
        },
        createEmptyFootprint: function (name) {
            var self = this;

            var g = this.store.createRecord('footprint', {
                name: name,
                flagged: true
            });

            g.save().catch(function () {
                g.destroy();
            }).then(function (fp) {
                self.get('model.footprints').pushObject(fp);
                self.get('model').save().catch(function (e) {
                    self.get('model.footprints').removeObject(fp);
                });
            });
        },
        removeFootprint: function (footprint) {
            var model = this.model;
            model.get('footprints').removeObject(footprint);
            model.save().catch(function () {
                model.rollback();
            });
        },
        showAddFootprint: function () {
            this.set('displayAddFootprint', true);
        },
        hideAddFootprint: function () {
            this.set('displayAddFootprint', false);
        },
        addSeeAlso: function (type) {
            var model = this.model;
            if (type == this.model) {
                return;
            }

            model.get('seeAlso').pushObject(type);
            model.save().catch(function () {
                model.rollback();
            });
        },
        removeSeeAlso: function (type) {
            var model = this.model;
            model.get('seeAlso').removeObject(type);
            model.save().catch(function () {
                model.rollback();
            });
        },
        showAddSeeAlso: function () {
            this.set('displayAddSeeAlso', true);
        },
        hideAddSeeAlso: function () {
            this.set('displayAddSeeAlso', false);
        },
        createBox: function (name) {
            var box = this.store.createRecord('box', {
                name: name,
                flagged: true
            });

            box.save().catch(function (err) {
                this.growl.error(err);
                box.destroy();
            });
        },
        showMoveLot: function (lot) {
            this.set('moveLot', lot);
            this.set('moveLotCount', lot.get('count'));
            this.set('moveLotToBox', lot.get('location'));
        },
        moveLot: function (lot, destination, count) {
            // close dialog
            this.set('moveLot', null);
            // bubble up
            return true;
        }
    },
    needs: "application",
    propertySorting: ['name'],
    sortedProperties: Ember.computed.sort('controllers.application.availableProperties', 'propertySorting'),

    typeSorting: ['fullName'],
    sortedTypes: Ember.computed.sort('controllers.application.availableTypes', 'typeSorting'),

    groupSorting: ['fullName'],
    sortedGroups: Ember.computed.sort('controllers.application.availableGroups', 'groupSorting'),

    footprintSorting: ['fullName'],
    sortedFootprints: Ember.computed.sort('controllers.application.availableFootprints', 'footprintSorting'),

    boxSorting: ['fullName'],
    sortedBoxes: Ember.computed.sort('controllers.application.availableLocations', 'boxSorting'),

    unitPrefixes: function () {
        return this.get('propertyToAdd.unit.prefixes');
    }.property('propertyToAdd.unit.prefixes', 'propertyToAdd.unit.prefixes.@each'),

    unitHint: function () {
        if (this.get('propertyValuePrefixToAdd')) {
            return "Enter value: 1 or 1.5";
        } else {
            var symbol = this.get('propertyToAdd.unit.symbol');
            var prefix = "p";

            var prefixes = this.get('propertyToAdd.unit.prefixes');
            console.log(prefixes);

            if (prefixes && prefixes.get('length') > 0) {
                var single = prefixes.get('firstObject');
                console.log(single);
                if (single) {
                    prefix = single.get('prefix');
                    console.log(prefix);
                }
            }
            var t = "Enter value: 1, 1.5, 1" + prefix + "5, 1.5" + prefix;
            if (symbol) {
                t += ", 1" + prefix + "5" + symbol + ", 1" + prefix + symbol + ", 1.5" + prefix + symbol;
            }
            return t;
        }
    }.property('propertyToAdd.unit', 'propertyToAdd.unit.symbol', 'propertyValuePrefixToAdd',
        'propertyToAdd.unit.prefixes', 'propertyToAdd.unit.prefixes.@each'),

    prefixSorting: ['power10'],
    sortedUnitPrefixes: Ember.computed.sort('unitPrefixes', 'prefixSorting'),

    propertyAddingAllowed: false,
    addPropertyIncomplete: function () {
        return Ember.isEmpty(this.get('propertyToAdd')) || Ember.isEmpty(this.get('propertyValueToAdd'));
    }.property('propertyToAdd', 'propertyValueToAdd'),

    moveLotToBox: null,
    moveLotDisabled: function () {
        return Ember.isEmpty(this.get('moveLotToBox')) || Ember.isEmpty(this.get('moveLotCount'));
    }.property('moveLotToBox', 'moveLotCount'),

    saveChanges: function () {
        var model = this.get('model');
        model.save().catch(function () {
            model.rollback();
        })
    }.observes('model.footprints', 'model.groups')
});
<|endoftext|>