<commit_before>/**
 * Created by vagrant on 9/28/16.
 */

import {HttpClient} from 'aurelia-http-client';
import {bindable, bindingMode, decorators} from 'aurelia-framework';

let client = new HttpClient();

export const FilepanelCustomElement = decorators (
    bindable({ name: 'tableid', defaultBindingMode: bindingMode.oneTime }),
    bindable('allowDestruction')
     ).on(class {
    constructor() {
        this.files = [];
        this.filescount = this.files.length;
        this.path= "";
        this.dynatable = {};
        //not yet accessible here console.log("file panel constructed:" + this.tableid);
        client.configure(config=>{
            config.withHeader('Accept','application/json');
            config.withHeader('Content-Type','application/json');
        });

        this.handleBodyClick = e => {
            console.log(e.target);
        };
    }

    attached() {
        //console.log("file panel attached:" + this.tableid);
        client.get("/metadataservice/sbfiles")
            .then(data => {
                if (data.response) {
                    this.files = JSON.parse(data.response,this.dateTimeReviver);//populate window list

                    this.files.forEach(function (item,index,arr){if (arr[index].attributes & 16) arr[index].size="DIR"})
                    this.filescount =  this.files.length;
                    this.dynatable = $('#'+this.tableid).dynatable({
                        dataset: {records: this.files},
                        features: {
                            paginate: false,
                            search: false,
                            recordCount: false,
                            perPageSelect: false
                        }
                    });
                    let a = this;
                    this.dynatable.on('click', 'tr', function () {
                        if (this.children[1].innerText.endsWith('DIR')) //if directory in second column
                            a.changefolder(this.firstChild.innerText);
                        else
                            //do some file related stuff
                            console.log(this.firstChild.innerText);
                    });
                }
            })
    }

    dateTimeReviver(key, value) {
        var a;
        if (typeof value === 'string') {
            a = /\/Date\(([\d\+]*)\)\//.exec(value);
            if (a) {
                return new Date(parseInt(a[1])).toLocaleDateString('en-GB');
            }
        }
        return value;
    }

    //removes last subdirectory
    cdup(){
        let sepIndex= this.path.lastIndexOf('/');
        this.path = this.path.substring(0,sepIndex);
    }

    //adds subdirectory to the path
    cddown(subdir) {
        this.path+='/'+subdir;
    }

    changefolder(folder){
        if (folder=='..') this.cdup();
        else this.cddown(folder);
        client.get("/metadataservice/sbfiles/"+this.path)
            .then(data => {
                if (data.response) {
                    this.files = JSON.parse(data.response,this.dateTimeReviver);//populate window list
                    this.filescount =  this.files.length;
                    if (this.path.length>0) {//non root path
                        this.files.unshift({name: "..", size: "UP DIR",date:""}); //up dir item
                    }
                    this.files.forEach (function (item,index,arr){if (arr[index].attributes & 16) arr[index].size="DIR"})
                    var d = this.dynatable.data('dynatable');
                    d.settings.dataset.originalRecords = this.files;
                    d.process();
                    let a = this;
                }
            })
    }

    });

<commit_msg>code cleanup<commit_after>/**
 * Created by vagrant on 9/28/16.
 */

import {HttpClient} from 'aurelia-http-client';
import {bindable, bindingMode, decorators} from 'aurelia-framework';

let client = new HttpClient();

export const FilepanelCustomElement = decorators (
    bindable({ name: 'tableid', defaultBindingMode: bindingMode.oneTime }),
    bindable('allowDestruction')
     ).on(class {

    constructor() {
        this.files = [];
        this.filescount = this.files.length;
        this.path= "";
        this.dynatable = {};
        //not yet accessible here console.log("file panel constructed:" + this.tableid);
        client.configure(config=>{
            config.withHeader('Accept','application/json');
            config.withHeader('Content-Type','application/json');
        });

        this.handleBodyClick = e => {
            console.log(e.target);
        };
    }

    attached() {
        //console.log("file panel attached:" + this.tableid);
        client.get("/metadataservice/sbfiles")
            .then(data => {
                if (data.response) {
                    this.populateFiles(dataresponse);

                    this.dynatable = $('#'+this.tableid).dynatable({
                        dataset: {records: this.files},
                        features: {
                            paginate: false,
                            search: false,
                            recordCount: false,
                            perPageSelect: false
                        }
                    });
                    let a = this;
                    this.dynatable.on('click', 'tr', function () {
                        if (this.children[1].innerText.endsWith('DIR')) //if directory in second column
                            a.changefolder(this.firstChild.innerText);
                        else
                            //do some file related stuff
                            console.log(this.firstChild.innerText);
                    });
                }
            })
    }

    dateTimeReviver(key, value) {
        var a;
        if (typeof value === 'string') {
            a = /\/Date\(([\d\+]*)\)\//.exec(value);
            if (a) {
                return new Date(parseInt(a[1])).toLocaleDateString('en-GB');
            }
        }
        return value;
    }

    //removes last subdirectory
    cdup(){
        let sepIndex= this.path.lastIndexOf('/');
        this.path = this.path.substring(0,sepIndex);
    }

    //adds subdirectory to the path
    cddown(subdir) {
        this.path+='/'+subdir;
    }

    //change folder, reads the folder content and updates the table structure
    changefolder(folder){
        if (folder=='..') this.cdup();
        else this.cddown(folder);
        client.get("/metadataservice/sbfiles/"+this.path)
            .then(data => {
                if (data.response) {
                    this.populateFiles(data.response);
                    //update files in table view
                    var d = this.dynatable.data('dynatable');
                    d.settings.dataset.originalRecords = this.files;
                    d.process();
                    let a = this;
                }
            })
    }

    populateFiles(dataresponse){
        this.files = JSON.parse(dataresponse,this.dateTimeReviver);//populate window list
        this.filescount =  this.files.length;
        if (this.path.length>0) {//non root path
            this.files.unshift({name: "..", size: "UP DIR",date:""}); //up dir item
        }
        this.files.forEach (function (item,index,arr){if (arr[index].attributes & 16) arr[index].size="DIR"})
    }

});

<|endoftext|>


<commit_before>// (C) Copyright 2014-2015 Hewlett Packard Enterprise Development LP

var React = require('react');
var Link = require('react-router').Link;
var jsxToString = require('jsx-to-string');
var DocsArticle = require('../../DocsArticle');
var Box = require('grommet/components/Box');
var Section = require('grommet/components/Section');
var Anchor = require('grommet/components/Anchor');

function convertAnchorToString(anchorJSX) {
  return jsxToString(anchorJSX, {
    keyValueOverride: {
      onClick: 'this._onClick'
    }
  });
}

var AnchorDoc = React.createClass({

  contextTypes: {
    routePrefix: React.PropTypes.string.isRequired
  },

  _onClick: function () {
    // no-op
  },

  _renderAnchorCode(heading, anchorJSX) {
    return (

{heading}

          {anchorJSX}

          {convertAnchorToString(anchorJSX)}

    );
  },

  render: function() {

    var defaultAnchor = (
      <Anchor href=""  onClick={this._onClick}>Child text</Anchor>
    );

    var primaryAnchor = (
      <Anchor href="" label="Label text" primary={true} onClick={this._onClick} />
    );

    var iconAnchor = (
      <Anchor href="" icon="Add" onClick={this._onClick} />
    );

    var targetAnchor = (
      <Anchor href="" target="_blank" label="Text" onClick={this._onClick} />
    );

    var inHeaderAnchor = (

        <Anchor href="" label="Text" onClick={this._onClick} />

    );

    var coloredContextAnchor = (

        <Box pad="small">
          <Anchor href="" onClick={this._onClick}>Text</Anchor>
        </Box>
        <Box pad="small">
          <Anchor href="" primary={true} icon="Checkmark" onClick={this._onClick}>Text</Anchor>
        </Box>
        <Box pad="small">
          <Anchor href="" icon="Add" onClick={this._onClick} />
        </Box>

    );

    var disabledAnchor = (
      <Anchor primary={true} disabled={true}>Text</Anchor>
    );

    return (
      <DocsArticle title="Anchor" colorIndex="neutral-3">

A text link. We have a separate component from the
        browser base so we can style it. You can either set the icon and/or
        label properties or just use children.

          {"<Anchor href=\"...\">label</Anchor>"}

Options

disabled       true|false

              Whether to disable the anchor. Default is false.

href           {"{location}"}

Hyperlink reference to place in the anchor.

icon           {"{name}"}

Name of an icon to place in the anchor.
              See <Link to={this.context.routePrefix + "icon"}>Icon</Link>.

label          {"{text}"}

Label text to place in the anchor.

onClick        {"{func}"}

Click handler.

primary        true|false

Whether this is a primary anchor.

tag            {"{text}"}

The DOM tag to use for the element. The default is {''}.
              This should be used in conjunction with components like
              Link from React Router. In this case, Link controls the
              navigation while Anchor controls the styling.

target         {"{location}"}

              Target of the link,
              examples targets=_blank|_self|_parent|_top|framename.

Example

          {this._renderAnchorCode('Default', defaultAnchor)}
          {this._renderAnchorCode('Primary, Label', primaryAnchor)}
          {this._renderAnchorCode('Icon', iconAnchor)}
          {this._renderAnchorCode('Target', targetAnchor)}
          {this._renderAnchorCode('Disabled', disabledAnchor)}
          {this._renderAnchorCode('In a Header', inHeaderAnchor)}
          {this._renderAnchorCode('Colored context', coloredContextAnchor)}

      </DocsArticle>
    );
  }
});

module.exports = AnchorDoc;
<commit_msg>updating anchor doc to include icon + label (without primary) example<commit_after>// (C) Copyright 2014-2015 Hewlett Packard Enterprise Development LP

var React = require('react');
var Link = require('react-router').Link;
var jsxToString = require('jsx-to-string');
var DocsArticle = require('../../DocsArticle');
var Box = require('grommet/components/Box');
var Section = require('grommet/components/Section');
var Anchor = require('grommet/components/Anchor');

function convertAnchorToString(anchorJSX) {
  return jsxToString(anchorJSX, {
    keyValueOverride: {
      onClick: 'this._onClick'
    }
  });
}

var AnchorDoc = React.createClass({

  contextTypes: {
    routePrefix: React.PropTypes.string.isRequired
  },

  _onClick: function () {
    // no-op
  },

  _renderAnchorCode(heading, anchorJSX) {
    return (

{heading}

          {anchorJSX}

          {convertAnchorToString(anchorJSX)}

    );
  },

  render: function() {

    var defaultAnchor = (
      <Anchor href=""  onClick={this._onClick}>Child text</Anchor>
    );

    var primaryAnchor = (
      <Anchor href="" label="Label text" primary={true} onClick={this._onClick} />
    );

    var iconLabelAnchor = (
      <Anchor href="" icon="Checkmark" label="Text" onClick={this._onClick} />
    );

    var iconAnchor = (
      <Anchor href="" icon="Add" onClick={this._onClick} />
    );

    var targetAnchor = (
      <Anchor href="" target="_blank" label="Text" onClick={this._onClick} />
    );

    var inHeaderAnchor = (

        <Anchor href="" label="Text" onClick={this._onClick} />

    );

    var coloredContextAnchor = (

        <Box pad="small">
          <Anchor href="" onClick={this._onClick}>Text</Anchor>
        </Box>
        <Box pad="small">
          <Anchor href="" primary={true} label="Text" onClick={this._onClick} />
        </Box>
        <Box pad="small">
          <Anchor href="" icon="Add" onClick={this._onClick} />
        </Box>

    );

    var disabledAnchor = (
      <Anchor primary={true} disabled={true}>Text</Anchor>
    );

    return (
      <DocsArticle title="Anchor" colorIndex="neutral-3">

A text link. We have a separate component from the
        browser base so we can style it. You can either set the icon and/or
        label properties or just use children.

          {"<Anchor href=\"...\">label</Anchor>"}

Options

disabled       true|false

              Whether to disable the anchor. Default is false.

href           {"{location}"}

Hyperlink reference to place in the anchor.

icon           {"{name}"}

Name of an icon to place in the anchor.
              See <Link to={this.context.routePrefix + "icon"}>Icon</Link>.

label          {"{text}"}

Label text to place in the anchor.

onClick        {"{func}"}

Click handler.

primary        true|false

Whether this is a primary anchor.

tag            {"{text}"}

The DOM tag to use for the element. The default is {''}.
              This should be used in conjunction with components like
              Link from React Router. In this case, Link controls the
              navigation while Anchor controls the styling.

target         {"{location}"}

              Target of the link,
              examples targets=_blank|_self|_parent|_top|framename.

Example

          {this._renderAnchorCode('Default', defaultAnchor)}
          {this._renderAnchorCode('Primary, Label', primaryAnchor)}
          {this._renderAnchorCode('Icon, Label', iconLabelAnchor)}
          {this._renderAnchorCode('Icon', iconAnchor)}
          {this._renderAnchorCode('Target', targetAnchor)}
          {this._renderAnchorCode('Disabled', disabledAnchor)}
          {this._renderAnchorCode('In a Header', inHeaderAnchor)}
          {this._renderAnchorCode('Colored context', coloredContextAnchor)}

      </DocsArticle>
    );
  }
});

module.exports = AnchorDoc;
<|endoftext|>


<commit_before>/* eslint-env es6 */
/* exported createNumericInput */
const createNumericInput = (() => {
  'use strict';

  /*
    In order:

      - Optional minus sign.
      - Any number of digits.
      - Optional decimal separator.
      - Any number of digits.

    Note: This will accept the empty string, '-', '.', and '-.'.
   */
  const NUMBER_REGEX = /^-?\d*\.?\d*$/;

  const UP = 38;
  const DOWN = 40;

  function round( number, precision ) {
    return parseFloat( number.toFixed( precision ) );
  }

  function isModified( event, modifiers ) {
    return [ 'shiftKey', 'ctrlKey', 'altKey', 'metaKey' ].every( modifier => {
      if ( modifiers.includes( modifier ) ) {
        return event[ modifier ];
      }

      return !event[ modifier ];
    });
  }

  function expandSelection( string, range, callback ) {
    let [ start, end ] = range;

    while ( start > 0 && callback( string.slice( start - 1, end ) ) ) {
      start--;
    }

    while ( end < string.length && callback( string.slice( start, end + 1 ) ) ) {
      end++;
    }

    return [ start, end ];
  }

  return function create( input ) {
    function onInput( event ) {
      let step;

      // Check modifier keys.
      if ( isModified( event, [ 'ctrlKey' ] ) ) {
        step = 1;
      } else if ( isModified( event, [ 'altKey' ] ) ) {
        step = 0.1;
      } else if ( isModified( event, [ 'altKey', 'metaKey' ] ) ) {
        step = 10;
      } else {
        return;
      }

      if ( event.keyCode === DOWN ) {
        step = -step;
      } else if ( event.keyCode !== UP ) {
        return;
      }

      // Calculate selection range of number.
      const range = expandSelection(
        input.value,
        [ input.selectionStart, input.selectionEnd ],
        string => NUMBER_REGEX.test( string )
      );

      // Calculate new number.
      const number = parseFloat( input.value.slice( range[0], range[1] ) );
      if ( isNaN( number ) ) {
        return;
      }

      const numberString = String( round( number + step, 6 ) );

      // Insert number string into current string.
      input.value = (
        input.value.slice( 0, range[0] ) +
        numberString +
        input.value.slice( range[1] )
      );

      // Highlight current number.
      input.setSelectionRange( range[0], range[0] + numberString.length );

      // Force update on input event.
      event.preventDefault();
      input.dispatchEvent( new Event( 'input' ) );
    }

    input.addEventListener( 'keydown', onInput );

    return function destroy() {
      input.removeEventListener( 'keydown', onInput );
    };
  };
})();
<commit_msg>lathe: Add undo/redo support to numeric input.<commit_after>/* eslint-env es6 */
/* exported createNumericInput */
const createNumericInput = (() => {
  'use strict';

  /*
    In order:

      - Optional minus sign.
      - Any number of digits.
      - Optional decimal separator.
      - Any number of digits.

    Note: This will accept the empty string, '-', '.', and '-.'.
   */
  const NUMBER_REGEX = /^-?\d*\.?\d*$/;

  const UP = 38;
  const DOWN = 40;

  function round( number, precision ) {
    return parseFloat( number.toFixed( precision ) );
  }

  function isModified( event, modifiers ) {
    return [ 'shiftKey', 'ctrlKey', 'altKey', 'metaKey' ].every( modifier => {
      if ( modifiers.includes( modifier ) ) {
        return event[ modifier ];
      }

      return !event[ modifier ];
    });
  }

  function expandSelection( string, range, callback ) {
    let [ start, end ] = range;

    while ( start > 0 && callback( string.slice( start - 1, end ) ) ) {
      start--;
    }

    while ( end < string.length && callback( string.slice( start, end + 1 ) ) ) {
      end++;
    }

    return [ start, end ];
  }

  return function create( input ) {
    function onInput( event ) {
      let step;

      // Check modifier keys.
      if ( isModified( event, [ 'ctrlKey' ] ) ) {
        step = 1;
      } else if ( isModified( event, [ 'altKey' ] ) ) {
        step = 0.1;
      } else if ( isModified( event, [ 'altKey', 'metaKey' ] ) ) {
        step = 10;
      } else {
        return;
      }

      if ( event.keyCode === DOWN ) {
        step = -step;
      } else if ( event.keyCode !== UP ) {
        return;
      }

      // Calculate selection range of first number.
      const range = expandSelection(
        input.value,
        [ input.selectionStart, input.selectionStart ],
        string => NUMBER_REGEX.test( string )
      );

      // Calculate new number.
      const number = parseFloat( input.value.slice( range[0], range[1] ) );
      if ( isNaN( number ) ) {
        return;
      }

      const numberString = String( round( number + step, 6 ) );

      // Highlight first number.
      input.setSelectionRange( range[0], range[1] );

      // Insert number string into selection.
      document.execCommand( 'insertText', false, numberString );

      // Highlight current selection.
      input.setSelectionRange( range[0], range[0] + numberString.length );

      // Force default arrow-key actions.
      event.preventDefault();
    }

    input.addEventListener( 'keydown', onInput );

    return function destroy() {
      input.removeEventListener( 'keydown', onInput );
    };
  };
})();
<|endoftext|>


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

    angular
        .module('orange')
        .factory('MedicationService', MedicationService);

    MedicationService.$inject = ['$q', 'n2w', 'notifications', 'PatientPagingService', 'errorList'];

    /* @ngInject */
    function MedicationService($q, n2w, notify, PatientPagingService, errorList) {
        var Service = function () {
            PatientPagingService.call(this);

            this.apiEndpoint = 'medications';

            this.errorItemNotFound = errorList.INVALID_MEDICATION_ID;
            this.errorItemNotFoundText = 'Medication not found';
            this.afterErrorItemNotFoundState = 'app.medications';
        };

        Service.prototype = Object.create(PatientPagingService.prototype);
        Service.prototype.removeItem = removeItem;
        Service.prototype.newItemSuccess = newItemSuccess;
        Service.prototype.saveItem = saveItem;

        Service.prototype.getEventText = getEventText;
        Service.prototype.getMedicationText = getMedicationText;
        Service.prototype.setMedicationSchedule = setMedicationSchedule;
        Service.prototype.setMedicationEvents = setMedicationEvents;
        Service.prototype.setNotifications = setNotifications;

        return new Service();

        function saveItem(savedItem) {
            var promise = PatientPagingService.prototype.saveItem.call(this, savedItem);
            if (savedItem.id) {
                promise = promise.then(function () {
                    notify.updateNotify();
                })
            }
            return promise;
        }

        function removeItem(removedItem) {
            var self = this;
            return PatientPagingService.prototype.removeItem.call(this, removedItem).then(function () {
                notify.updateNotify();
                return self.items;
            });
        }

        function newItemSuccess(newItem, addCondition) {
            if (addCondition === undefined) {
                addCondition = true;
            }
            var importCondition = !newItem['import_id'] || !_.find(this.items, {import_id: newItem['import_id']});
            PatientPagingService.prototype.newItemSuccess.call(this, newItem, addCondition && importCondition);
            notify.addNotifyByMedication(newItem);
        }

        function setNotifications(notifications) {
            var promises = [],
                medication = this.item;
            for (var i = 0, len = medication.schedule.times.length; i < len; i++) {
                var time = medication.schedule.times[i];
                var notification = notifications[i] || 30;
                console.log('setting notification time', medication.id, time.id, notification);
                var promise = medication.all('times').one(time.id.toString()).customPUT({
                   user: notification
                });
                promises.push(promise);
            }
            return $q.all(promises);
        }

        function setMedicationSchedule(schedule) {
            this.item.schedule = schedule;
        }

        function setMedicationEvents(events) {
            this.item.schedule.times = events;
        }

        function getEventText(event) {
            var result = '';
            var units = this.item.dose.quantity;
            result += _.capitalize(n2w.toWords(units || 0));
            result += ' unit' + (units === 1 ? '' : 's');
            if (event.type == 'exact') {
                result += ' at ' + event.time;
            } else {
                if (event.when === 'after' && event.event === 'sleep') {
                    result += ' ' + 'after wake';
                } else {
                    result += ' ' + event.when + ' ' + event.event;
                }

            }
            return result;
        }

        function getMedicationText(medication) {
            var text = '';
            if (medication && medication.schedule.times && medication.schedule.times.length) {
                var eventsCount = medication.schedule.times.length;
                text += eventsCount;
                text += ' event' + (eventsCount > 1 ? 's' : '') + ' per day'
            }

            return text;
        }
    }
})();
<commit_msg>[artefact][ORANGE-131] Fix medication service<commit_after>(function () {
    "use strict";

    angular
        .module('orange')
        .factory('MedicationService', MedicationService);

    MedicationService.$inject = ['$q', 'n2w', 'notifications', 'PatientPagingService', 'errorList'];

    /* @ngInject */
    function MedicationService($q, n2w, notify, PatientPagingService, errorList) {
        var Service = function () {
            PatientPagingService.call(this);

            this.apiEndpoint = 'medications';

            this.errorItemNotFound = errorList.INVALID_MEDICATION_ID;
            this.errorItemNotFoundText = 'Medication not found';
        };

        Service.prototype = Object.create(PatientPagingService.prototype);
        Service.prototype.removeItem = removeItem;
        Service.prototype.newItemSuccess = newItemSuccess;
        Service.prototype.saveItem = saveItem;

        Service.prototype.getEventText = getEventText;
        Service.prototype.getMedicationText = getMedicationText;
        Service.prototype.setMedicationSchedule = setMedicationSchedule;
        Service.prototype.setMedicationEvents = setMedicationEvents;
        Service.prototype.setNotifications = setNotifications;

        return new Service();

        function saveItem(savedItem) {
            var promise = PatientPagingService.prototype.saveItem.call(this, savedItem);
            if (savedItem.id) {
                promise = promise.then(function () {
                    notify.updateNotify();
                })
            }
            return promise;
        }

        function removeItem(removedItem) {
            var self = this;
            return PatientPagingService.prototype.removeItem.call(this, removedItem).then(function () {
                notify.updateNotify();
                return self.items;
            });
        }

        function newItemSuccess(newItem, addCondition) {
            if (addCondition === undefined) {
                addCondition = true;
            }
            var importCondition = !newItem['import_id'] || !_.find(this.items, {import_id: newItem['import_id']});
            PatientPagingService.prototype.newItemSuccess.call(this, newItem, addCondition && importCondition);
            notify.addNotifyByMedication(newItem);
        }

        function setNotifications(notifications) {
            var promises = [],
                medication = this.item;
            for (var i = 0, len = medication.schedule.times.length; i < len; i++) {
                var time = medication.schedule.times[i];
                var notification = notifications[i] || 30;
                console.log('setting notification time', medication.id, time.id, notification);
                var promise = medication.all('times').one(time.id.toString()).customPUT({
                   user: notification
                });
                promises.push(promise);
            }
            return $q.all(promises);
        }

        function setMedicationSchedule(schedule) {
            this.item.schedule = schedule;
        }

        function setMedicationEvents(events) {
            this.item.schedule.times = events;
        }

        function getEventText(event) {
            var result = '';
            var units = this.item.dose.quantity;
            result += _.capitalize(n2w.toWords(units || 0));
            result += ' unit' + (units === 1 ? '' : 's');
            if (event.type == 'exact') {
                result += ' at ' + event.time;
            } else {
                if (event.when === 'after' && event.event === 'sleep') {
                    result += ' ' + 'after wake';
                } else {
                    result += ' ' + event.when + ' ' + event.event;
                }

            }
            return result;
        }

        function getMedicationText(medication) {
            var text = '';
            if (medication && medication.schedule.times && medication.schedule.times.length) {
                var eventsCount = medication.schedule.times.length;
                text += eventsCount;
                text += ' event' + (eventsCount > 1 ? 's' : '') + ' per day'
            }

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


<commit_before>// @flow

const R = require('ramda');
const { sendToLagoonLogs } = require('@lagoon/commons/src/logs');
const { createMiscTask } = require('@lagoon/commons/src/tasks');
const { query, isPatchEmpty } = require('../../util/db');
const {
  pubSub,
  createEnvironmentFilteredSubscriber,
} = require('../../clients/pubSub');
const Sql = require('./sql');
const Helpers = require('./helpers');
const projectSql = require('../project/sql');
const environmentSql = require('../environment/sql');
const environmentHelpers = require('../environment/helpers');
const EVENTS = require('./events');

/* ::

import type {ResolversObj} from '../';

*/

const restoreStatusTypeToString = R.cond([
  [R.equals('PENDING'), R.toLower],
  [R.equals('SUCCESSFUL'), R.toLower],
  [R.equals('FAILED'), R.toLower],
  [R.T, R.identity],
]);

const getBackupsByEnvironmentId = async (
  { id: environmentId },
  { includeDeleted },
  { sqlClient, hasPermission },
) => {
  const environment = await environmentHelpers(sqlClient).getEnvironmentById(environmentId);
  await hasPermission('backup', 'view', {
    project: environment.project,
  });

  const rows = await query(
    sqlClient,
    Sql.selectBackupsByEnvironmentId({ environmentId, includeDeleted }),
  );

  const newestFirst = R.sort(R.descend(R.prop('created')), rows);

  return newestFirst;
};

const addBackup = async (
  root,
  {
    input: {
      id, environment: environmentId, source, backupId, created,
    },
  },
  { sqlClient, hasPermission },
) => {
  const environment = await environmentHelpers(sqlClient).getEnvironmentById(environmentId);
  await hasPermission('backukp', 'add', {
    project: environment.project,
  });

  const {
    info: { insertId },
  } = await query(
    sqlClient,
    Sql.insertBackup({
      id,
      environment: environmentId,
      source,
      backupId,
      created,
    }),
  );
  const rows = await query(sqlClient, Sql.selectBackup(insertId));
  const backup = R.prop(0, rows);

  pubSub.publish(EVENTS.BACKUP.ADDED, backup);

  return backup;
};

const deleteBackup = async (
  root,
  { input: { backupId } },
  {
    sqlClient,
    hasPermission,
  },
) => {
  const perms = await query(sqlClient, Sql.selectPermsForBackup(backupId));

  await hasPermission('backup', 'delete', {
    project: R.path(['0', 'pid'], perms),
  });

  await query(sqlClient, Sql.deleteBackup(backupId));

  const rows = await query(sqlClient, Sql.selectBackupByBackupId(backupId));
  pubSub.publish(EVENTS.BACKUP.DELETED, R.prop(0, rows));

  return 'success';
};

const deleteAllBackups = async (
  root,
  args,
  { sqlClient, hasPermission },
) => {
  await hasPermission('backup', 'deleteAll');

  await query(sqlClient, Sql.truncateBackup());

  // TODO: Check rows for success
  return 'success';
};

const addRestore = async (
  root,
  {
    input: {
      id,
      backupId,
      status: unformattedStatus,
      restoreLocation,
      created,
      execute,
    },
  },
  { sqlClient, hasPermission },
) => {
  const perms = await query(sqlClient, Sql.selectPermsForBackup(backupId));

  await hasPermission('restore', 'add', {
    project: R.path(['0', 'pid'], perms),
  });

  const status = restoreStatusTypeToString(unformattedStatus);
  const {
    info: { insertId },
  } = await query(
    sqlClient,
    Sql.insertRestore({
      id,
      backupId,
      status,
      restoreLocation,
      created,
    }),
  );
  let rows = await query(sqlClient, Sql.selectRestore(insertId));
  const restoreData = Helpers.makeS3TempLink(R.prop(0, rows));

  rows = await query(sqlClient, Sql.selectBackupByBackupId(backupId));
  const backupData = R.prop(0, rows);

  pubSub.publish(EVENTS.BACKUP.UPDATED, backupData);

  // Allow creating restore data w/o executing the restore
  if (execute === false) {
    try {
      await hasPermission('restore', 'addNoExec', {
        project: R.path(['0', 'pid'], perms),
      });
      return restoreData;
    } catch (err) {
      // Not allowed to stop execution.
    }
  }

  rows = await query(
    sqlClient,
    environmentSql.selectEnvironmentById(backupData.environment),
  );
  const environmentData = R.prop(0, rows);

  rows = await query(
    sqlClient,
    projectSql.selectProject(environmentData.project),
  );
  const projectData = R.prop(0, rows);

  const data = {
    backup: backupData,
    restore: restoreData,
    environment: environmentData,
    project: projectData,
  };

  try {
    await createMiscTask({ key: 'restic:backup:restore', data });
  } catch (error) {
    sendToLagoonLogs(
      'error',
      '',
      '',
      'api:addRestore',
      { restoreId: restoreData.id, backupId },
      `Restore not initiated, reason: ${error}`,
    );
  }

  return restoreData;
};

const updateRestore = async (
  root,
  {
    input: {
      backupId,
      patch,
      patch: { status: unformattedStatus, created, restoreLocation },
    },
  },
  {
    sqlClient,
    hasPermission,
  },
) => {
  const status = restoreStatusTypeToString(unformattedStatus);

  if (isPatchEmpty({ patch })) {
    throw new Error('Input patch requires at least 1 attribute');
  }

  const permsRestore = await query(sqlClient, Sql.selectPermsForRestore(backupId));
  const permsBackup = await query(sqlClient, Sql.selectPermsForBackup(backupId));

  // Check access to modify restore as it currently stands
  await hasPermission('restore', 'update', {
    project: R.path(['0', 'pid'], permsRestore),
  });
  // Check access to modify restore as it will be updated
  await hasPermission('backup', 'view', {
    project: R.path(['0', 'pid'], permsBackup),
  });

  await query(
    sqlClient,
    Sql.updateRestore({
      backupId,
      patch: {
        status,
        created,
        restoreLocation,
      },
    }),
  );

  let rows = await query(sqlClient, Sql.selectRestoreByBackupId(backupId));
  const restoreData = Helpers.makeS3TempLink(R.prop(0, rows));

  rows = await query(sqlClient, Sql.selectBackupByBackupId(backupId));
  const backupData = R.prop(0, rows);

  pubSub.publish(EVENTS.BACKUP.UPDATED, backupData);

  return restoreData;
};

const getRestoreByBackupId = async ({ backupId }, args, { sqlClient, hasPermission }) => {
  const permsBackup = await query(sqlClient, Sql.selectPermsForBackup(backupId));

  await hasPermission('backup', 'view', {
    project: R.path(['0', 'pid'], permsBackup),
  });

  const rows = await query(sqlClient, Sql.selectRestoreByBackupId(backupId));

  return Helpers.makeS3TempLink(R.prop(0, rows));
};

const backupSubscriber = createEnvironmentFilteredSubscriber([
  EVENTS.BACKUP.ADDED,
  EVENTS.BACKUP.UPDATED,
  EVENTS.BACKUP.DELETED,
]);

const Resolvers /* : ResolversObj */ = {
  addBackup,
  getBackupsByEnvironmentId,
  deleteBackup,
  deleteAllBackups,
  addRestore,
  getRestoreByBackupId,
  updateRestore,
  backupSubscriber,
};

module.exports = Resolvers;
<commit_msg>correct backup name<commit_after>// @flow

const R = require('ramda');
const { sendToLagoonLogs } = require('@lagoon/commons/src/logs');
const { createMiscTask } = require('@lagoon/commons/src/tasks');
const { query, isPatchEmpty } = require('../../util/db');
const {
  pubSub,
  createEnvironmentFilteredSubscriber,
} = require('../../clients/pubSub');
const Sql = require('./sql');
const Helpers = require('./helpers');
const projectSql = require('../project/sql');
const environmentSql = require('../environment/sql');
const environmentHelpers = require('../environment/helpers');
const EVENTS = require('./events');

/* ::

import type {ResolversObj} from '../';

*/

const restoreStatusTypeToString = R.cond([
  [R.equals('PENDING'), R.toLower],
  [R.equals('SUCCESSFUL'), R.toLower],
  [R.equals('FAILED'), R.toLower],
  [R.T, R.identity],
]);

const getBackupsByEnvironmentId = async (
  { id: environmentId },
  { includeDeleted },
  { sqlClient, hasPermission },
) => {
  const environment = await environmentHelpers(sqlClient).getEnvironmentById(environmentId);
  await hasPermission('backup', 'view', {
    project: environment.project,
  });

  const rows = await query(
    sqlClient,
    Sql.selectBackupsByEnvironmentId({ environmentId, includeDeleted }),
  );

  const newestFirst = R.sort(R.descend(R.prop('created')), rows);

  return newestFirst;
};

const addBackup = async (
  root,
  {
    input: {
      id, environment: environmentId, source, backupId, created,
    },
  },
  { sqlClient, hasPermission },
) => {
  const environment = await environmentHelpers(sqlClient).getEnvironmentById(environmentId);
  await hasPermission('backup', 'add', {
    project: environment.project,
  });

  const {
    info: { insertId },
  } = await query(
    sqlClient,
    Sql.insertBackup({
      id,
      environment: environmentId,
      source,
      backupId,
      created,
    }),
  );
  const rows = await query(sqlClient, Sql.selectBackup(insertId));
  const backup = R.prop(0, rows);

  pubSub.publish(EVENTS.BACKUP.ADDED, backup);

  return backup;
};

const deleteBackup = async (
  root,
  { input: { backupId } },
  {
    sqlClient,
    hasPermission,
  },
) => {
  const perms = await query(sqlClient, Sql.selectPermsForBackup(backupId));

  await hasPermission('backup', 'delete', {
    project: R.path(['0', 'pid'], perms),
  });

  await query(sqlClient, Sql.deleteBackup(backupId));

  const rows = await query(sqlClient, Sql.selectBackupByBackupId(backupId));
  pubSub.publish(EVENTS.BACKUP.DELETED, R.prop(0, rows));

  return 'success';
};

const deleteAllBackups = async (
  root,
  args,
  { sqlClient, hasPermission },
) => {
  await hasPermission('backup', 'deleteAll');

  await query(sqlClient, Sql.truncateBackup());

  // TODO: Check rows for success
  return 'success';
};

const addRestore = async (
  root,
  {
    input: {
      id,
      backupId,
      status: unformattedStatus,
      restoreLocation,
      created,
      execute,
    },
  },
  { sqlClient, hasPermission },
) => {
  const perms = await query(sqlClient, Sql.selectPermsForBackup(backupId));

  await hasPermission('restore', 'add', {
    project: R.path(['0', 'pid'], perms),
  });

  const status = restoreStatusTypeToString(unformattedStatus);
  const {
    info: { insertId },
  } = await query(
    sqlClient,
    Sql.insertRestore({
      id,
      backupId,
      status,
      restoreLocation,
      created,
    }),
  );
  let rows = await query(sqlClient, Sql.selectRestore(insertId));
  const restoreData = Helpers.makeS3TempLink(R.prop(0, rows));

  rows = await query(sqlClient, Sql.selectBackupByBackupId(backupId));
  const backupData = R.prop(0, rows);

  pubSub.publish(EVENTS.BACKUP.UPDATED, backupData);

  // Allow creating restore data w/o executing the restore
  if (execute === false) {
    try {
      await hasPermission('restore', 'addNoExec', {
        project: R.path(['0', 'pid'], perms),
      });
      return restoreData;
    } catch (err) {
      // Not allowed to stop execution.
    }
  }

  rows = await query(
    sqlClient,
    environmentSql.selectEnvironmentById(backupData.environment),
  );
  const environmentData = R.prop(0, rows);

  rows = await query(
    sqlClient,
    projectSql.selectProject(environmentData.project),
  );
  const projectData = R.prop(0, rows);

  const data = {
    backup: backupData,
    restore: restoreData,
    environment: environmentData,
    project: projectData,
  };

  try {
    await createMiscTask({ key: 'restic:backup:restore', data });
  } catch (error) {
    sendToLagoonLogs(
      'error',
      '',
      '',
      'api:addRestore',
      { restoreId: restoreData.id, backupId },
      `Restore not initiated, reason: ${error}`,
    );
  }

  return restoreData;
};

const updateRestore = async (
  root,
  {
    input: {
      backupId,
      patch,
      patch: { status: unformattedStatus, created, restoreLocation },
    },
  },
  {
    sqlClient,
    hasPermission,
  },
) => {
  const status = restoreStatusTypeToString(unformattedStatus);

  if (isPatchEmpty({ patch })) {
    throw new Error('Input patch requires at least 1 attribute');
  }

  const permsRestore = await query(sqlClient, Sql.selectPermsForRestore(backupId));
  const permsBackup = await query(sqlClient, Sql.selectPermsForBackup(backupId));

  // Check access to modify restore as it currently stands
  await hasPermission('restore', 'update', {
    project: R.path(['0', 'pid'], permsRestore),
  });
  // Check access to modify restore as it will be updated
  await hasPermission('backup', 'view', {
    project: R.path(['0', 'pid'], permsBackup),
  });

  await query(
    sqlClient,
    Sql.updateRestore({
      backupId,
      patch: {
        status,
        created,
        restoreLocation,
      },
    }),
  );

  let rows = await query(sqlClient, Sql.selectRestoreByBackupId(backupId));
  const restoreData = Helpers.makeS3TempLink(R.prop(0, rows));

  rows = await query(sqlClient, Sql.selectBackupByBackupId(backupId));
  const backupData = R.prop(0, rows);

  pubSub.publish(EVENTS.BACKUP.UPDATED, backupData);

  return restoreData;
};

const getRestoreByBackupId = async ({ backupId }, args, { sqlClient, hasPermission }) => {
  const permsBackup = await query(sqlClient, Sql.selectPermsForBackup(backupId));

  await hasPermission('backup', 'view', {
    project: R.path(['0', 'pid'], permsBackup),
  });

  const rows = await query(sqlClient, Sql.selectRestoreByBackupId(backupId));

  return Helpers.makeS3TempLink(R.prop(0, rows));
};

const backupSubscriber = createEnvironmentFilteredSubscriber([
  EVENTS.BACKUP.ADDED,
  EVENTS.BACKUP.UPDATED,
  EVENTS.BACKUP.DELETED,
]);

const Resolvers /* : ResolversObj */ = {
  addBackup,
  getBackupsByEnvironmentId,
  deleteBackup,
  deleteAllBackups,
  addRestore,
  getRestoreByBackupId,
  updateRestore,
  backupSubscriber,
};

module.exports = Resolvers;
<|endoftext|>


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

    angular.module('adminApp')
        .factory('controlPanelFactory', ['$http', controlPanelFactory]);

    function controlPanelFactory($http) {

        function getUnpublishedPosts() {
            return $http.get("/api/admin/unpublished");
        }

        function getPublishedPosts() {
            return $http.get("/api/admin/published");
        }

        function getUsers() {
            return $http.get("/api/admin/users");
        }

        function approvePost(post, isPublished) {
            //set isPublished status
            post.isPublished = isPublished;

            return $http.post("/api/admin/approve", post);
        }

        function banUser(user) {
            return $http.post("/api/admin/ban", user);
        }

        function unbanUser(user) {
            return $http.post("/api/admin/unban", user);
        }

        var service = {
            getUnpublishedPosts: getUnpublishedPosts,
            getPublishedPosts: getPublishedPosts,
            getUsers: getUsers,
            approvePost: approvePost,
            banUser: banUser,
            unbanUser: unbanUser
        };

        return service;
    };

})();<commit_msg>Added getPost method<commit_after>(function () {
    'use strict';

    angular.module('adminApp')
        .factory('controlPanelFactory', ['$http', controlPanelFactory]);

    function controlPanelFactory($http) {

        function getUnpublishedPosts() {
            return $http.get("/api/admin/unpublished");
        }

        function getPublishedPosts() {
            return $http.get("/api/admin/published");
        }

        function getUsers() {
            return $http.get("/api/admin/users");
        }

        function getPost(id) {
            return $http.get("/api/admin/post/" + id);
        }

        function approvePost(post, isPublished) {
            //set isPublished status
            post.isPublished = isPublished;

            return $http.post("/api/admin/approve", post);
        }

        function banUser(user) {
            return $http.post("/api/admin/ban", user);
        }

        function unbanUser(user) {
            return $http.post("/api/admin/unban", user);
        }

        var service = {
            getUnpublishedPosts: getUnpublishedPosts,
            getPublishedPosts: getPublishedPosts,
            getUsers: getUsers,
            approvePost: approvePost,
            banUser: banUser,
            unbanUser: unbanUser,
            getPost: getPost
        }

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


<commit_before>const Me = imports.misc.extensionUtils.getCurrentExtension();
const Gettext = imports.gettext.domain(Me.metadata.uuid);
const Utils = Me.imports.utils;
const DeskChangerControl = Me.imports.ui.control;

const Gio = imports.gi.Gio;
const GObject = imports.gi.GObject;
const Main = imports.ui.main;
const Meta = imports.gi.Meta;
const PopupMenu = imports.ui.popupMenu;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const Util = imports.misc.util;
const _ = Gettext.gettext;

var ControlsMenuItem = GObject.registerClass(
class DeskChangerPopupMenuControlsMenuItem extends PopupMenu.PopupBaseMenuItem {
    _init(daemon, settings) {
        super._init({'can_focus': false, 'reactive': false});
        this._bindings = [];

        this._addKeyBinding('next-wallpaper', () => {
            daemon.next();
        }, settings);
        this._addKeyBinding('prev-wallpaper', () => {
            daemon.prev();
        }, settings);

        this._next = new DeskChangerControl.ButtonControl('media-skip-forward', () => {
            daemon.next();
        });
        this._prev = new DeskChangerControl.ButtonControl('media-skip-backward', () => {
            if (!daemon.prev()) {
                Main.notifyError('DeskChanger', _('No more wallpapers available in history'));
            }
        });
        this._random = new DeskChangerControl.StateButtonControl([
            {
                icon: 'media-playlist-shuffle',
                name: 'random',
            },
            {
                icon: 'media-playlist-repeat',
                name: 'ordered',
            },
        ], (state) => {
            Utils.debug(`setting order to ${state}`);
            settings.random = (state === 'random');
        });
        this._random.set_state((settings.random)? 'random' : 'ordered');

        this.add(this._prev, {expand: true, x_fill: false});
        this.add(this._random, {expand: true, x_fill: false});
        this.add(this._next, {expand: true, x_fill: false});
    }

    _addKeyBinding(key, handler, settings) {
        let success = false;
        success = Main.wm.addKeybinding(
            key,
            settings,
            Meta.KeyBindingFlags.NONE,
            Shell.ActionMode.NORMAL,
            handler
        );

        this._bindings.push(key);
        if (success) {
            Utils.debug('added keybinding ' + key);
        } else {
            Utils.debug('failed to add keybinding ' + key);
            Utils.debug(success);
        }
    }

    _removeKeyBinding(key) {
        if (this._bindings.indexOf(key)) {
            this._bindings.splice(this._bindings.indexOf(key), 1);
        }

        Utils.debug('removing keybinding ' + key);
        Main.wm.removeKeybinding(key);
    }
}
);

var DaemonMenuItem = GObject.registerClass(
class DeskChangerPopupMenuDaemonMenuItem extends PopupMenu.PopupSwitchMenuItem {
    _init(daemon) {
        super._init(_('DeskChanger Daemon'), daemon.running);
        this._daemon = daemon;
        this._toggled_id = this.connect('toggled', () => {
            (daemon.running)? daemon.stop() : daemon.start();
        });
        this._daemon_id = daemon.connect('toggled', () => {
            this.setToggleState(daemon.running);
        });
    }

    destroy() {
        if (this._toggled_id) {
            this.disconnect(this._toggled_id);
        }
        this._toggled_id = null;

        if (this._daemon_id) {
            this._daemon.disconnect(this._daemon_id);
        }
        this._daemon_id = null;

        super.destroy();
    }
}
);

var OpenCurrentMenuItem = GObject.registerClass(
class DeskChangerPopupMenuOpenCurrent extends PopupMenu.PopupMenuItem {
    _init() {
        super._init(_('Open current wallpaper'));
        this._background = new Gio.Settings({'schema': 'org.gnome.desktop.background'});
        this._activate_id = this.connect('activate', () => {
            Utils.debug(`opening current wallpaper ${this._background.get_string('picture-uri')}`);
            Util.spawn(['xdg-open', this._background.get_string('picture-uri')]);
        });
        Utils.debug(`connect active (${this._activate_id})`);
    }

    destroy() {
        Utils.debug(`disconnect active (${this._activate_id})`);
        this.disconnect(this._activate_id);

        super.destroy();
    }
}
);

let PopupMenuItem = GObject.registerClass(
class DeskChangerPopupMenuItem extends PopupMenu.PopupMenuItem {
    _init(label, value, settings, key) {
        super._init(label);
        this._value = value;
        this._key = key;
        this._key_normalized = key.replace('_', '-');
        this._settings = settings;

        if (settings[this._key] === this._value) {
            this.setOrnament(PopupMenu.Ornament.DOT);
        }

        this._handler_key_changed = settings.connect(`changed::${this._key_normalized}`, () => {
            if (settings[key] === value) {
                this.setOrnament(PopupMenu.Ornament.DOT);
            } else {
                this.setOrnament(PopupMenu.Ornament.NONE);
            }
        });

        this._handler_id = this.connect('activate', () => {
            settings[key] = value;
        });
    }

    destroy() {
        if (this._handler_key_changed) {
            this._settings.disconnect(this._handler_key_changed);
            this._handler_key_changed = null;
        }

        if (this._handler_id) {
            this.disconnect(this._handler_id);
            this._handler_id = null;
        }

        super.destroy();
    }
}
);

let PopupSubMenuMenuItem = GObject.registerClass(
class DeskChangerPopupSubMenuMenuItem extends PopupMenu.PopupSubMenuMenuItem {
    _init(prefix, key, settings, sensitive=true) {
        super._init('');
        this._prefix = prefix;
        this._settings = settings;
        this._changed_id = settings.connect(`changed::${key.replace('_', '-')}`, () => {
            this.setLabel(settings[key]);
        });
        this.setLabel(settings[key]);
        this.setSensitive(sensitive);
    }

    destroy() {
        if (this._changed_id) {
            this._settings.disconnect(this._changed_id);
        }

        super.destroy();
    }

    setLabel(label) {
        this.label.text = `${this._prefix}: ${label}`;
    }
}
);

var PreviewMenuItem = GObject.registerClass(
class DeskChangerPopupMenuPreviewMenuItem extends PopupMenu.PopupBaseMenuItem {
    _init(daemon) {
        super._init({reactive: true});
        this._box = new St.BoxLayout({vertical: true});
        this.add_actor(this._box);
        this._prefix = new St.Label({text: _('Open next wallpaper')});
        this._box.add(this._prefix);
        this._preview = new DeskChangerControl.PreviewControl(220, daemon);
        this._box.add(this._preview);
        this._activate_id = this.connect('activate', () => {
            if (this._preview.file) {
                Utils.debug(`opening file ${this._preview.file}`);
                Util.spawn(['xdg-open', this._preview.file]);
            } else {
                Utils.error('no preview set');
            }
        });
        Utils.debug(`connect activate ${this._activate_id}`);
    }

    destroy() {
        Utils.debug(`disconnect activate ${this._activate_id}`);
        this.disconnect(this._activate_id);

        this._preview.destroy();
        this._prefix.destroy();
        this._box.destroy();
        super.destroy();
    }
}
);

let ProfileMenuItem = GObject.registerClass({
    Abstract: true,
},
class DeskChangerPopupSubMenuMenuItemProfile extends PopupSubMenuMenuItem {
    _init(label, key, settings, sensitive=true) {
        super._init(label, key, settings, sensitive);
        this._settings = settings;
        this._profiles_changed_id = settings.connect('changed::profiles', () => {
            this._populate_profiles(settings, key);
        });
        this._populate_profiles(settings, key);
    }

    destroy() {
        this._settings.disconnect(this._profiles_changed_id);
        super.destroy();
    }

    _populate_profiles(settings, key) {
        this.menu.removeAll();
        for (let index in settings.profiles) {
            let item = new PopupMenuItem(index, index, settings, key);
            this.menu.addMenuItem(item);
        }
    }
}
);

var ProfileDesktopMenuItem = GObject.registerClass(
class DeskChangerPopupSubMenuMenuItemProfileDesktop extends ProfileMenuItem {
    _init(settings, sensitive = true) {
        super._init(_('Desktop Profile'), 'current_profile', settings, sensitive);
    }
}
);

var ProfileLockScreenMenuItem = GObject.registerClass(
class DeskChangerPopupSubMenuMenuItemProfileLockScreen extends ProfileMenuItem {
    _init(settings, sensitive=true) {
        super._init(_('Lock Screen Profile'), 'lockscreen_profile', settings, sensitive);
    }

    setLabel(label) {
        if (!label) {
            label = '(inherited)';
        }

        super.setLabel(label);
    }

    _populate_profiles(settings, key) {
        super._populate_profiles(settings, 'lockscreen_profile', key);

        let inherit = new PopupMenuItem(_('(inherit from desktop)'), '', settings, key);
        this.menu.addMenuItem(inherit);
    }
}
);

var RotationMenuItem = GObject.registerClass(
class DeskChangerPopupMenuRotationMenuItem extends PopupSubMenuMenuItem {
    _init(settings, sensitive=true) {
        super._init(_('Rotation mode'), 'rotation', settings, sensitive);
        this.menu.addMenuItem(new PopupMenuItem(_('Interval timer'), 'interval', settings, 'rotation'));
        this.menu.addMenuItem(new PopupMenuItem(_('Beginning of hour'), 'hourly', settings, 'rotation'));
        this.menu.addMenuItem(new PopupMenuItem(_('Disabled'), 'disabled', settings, 'rotation'));
    }
}
);

var SwitchMenuItem = GObject.registerClass(
class DeskChangerPopupSwitchMenuItem extends PopupMenu.PopupSwitchMenuItem {
    _init(label, key, settings) {
        super._init(label, settings[key]);
        this._settings = settings;
        this._key = key;
        this._key_normalized = key.replace('_', '-');
        this._handler_changed = settings.connect(`changed::${this._key_normalized}`, (settings, key) => {
            this.setToggleState(settings.get_boolean(key));
        });
        this._handler_toggled = this.connect('toggled', () => {
            this._settings[this._key] = this.state;
        });
    }

    destroy() {
        if (this._handler_changed) {
            this._settings.disconnect(this._handler_changed);
        }

        if (this._handler_toggled) {
            this._settings.disconnect(this._handler_toggled);
        }

        super.destroy();
    }
}
);
<commit_msg>Minor update to set label on init<commit_after>const Me = imports.misc.extensionUtils.getCurrentExtension();
const Gettext = imports.gettext.domain(Me.metadata.uuid);
const Utils = Me.imports.utils;
const DeskChangerControl = Me.imports.ui.control;

const Gio = imports.gi.Gio;
const GObject = imports.gi.GObject;
const Main = imports.ui.main;
const Meta = imports.gi.Meta;
const PopupMenu = imports.ui.popupMenu;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const Util = imports.misc.util;
const _ = Gettext.gettext;

var ControlsMenuItem = GObject.registerClass(
class DeskChangerPopupMenuControlsMenuItem extends PopupMenu.PopupBaseMenuItem {
    _init(daemon, settings) {
        super._init({'can_focus': false, 'reactive': false});
        this._bindings = [];

        this._addKeyBinding('next-wallpaper', () => {
            daemon.next();
        }, settings);
        this._addKeyBinding('prev-wallpaper', () => {
            daemon.prev();
        }, settings);

        this._next = new DeskChangerControl.ButtonControl('media-skip-forward', () => {
            daemon.next();
        });
        this._prev = new DeskChangerControl.ButtonControl('media-skip-backward', () => {
            if (!daemon.prev()) {
                Main.notifyError('DeskChanger', _('No more wallpapers available in history'));
            }
        });
        this._random = new DeskChangerControl.StateButtonControl([
            {
                icon: 'media-playlist-shuffle',
                name: 'random',
            },
            {
                icon: 'media-playlist-repeat',
                name: 'ordered',
            },
        ], (state) => {
            Utils.debug(`setting order to ${state}`);
            settings.random = (state === 'random');
        });
        this._random.set_state((settings.random)? 'random' : 'ordered');

        this.add(this._prev, {expand: true, x_fill: false});
        this.add(this._random, {expand: true, x_fill: false});
        this.add(this._next, {expand: true, x_fill: false});
    }

    _addKeyBinding(key, handler, settings) {
        let success = false;
        success = Main.wm.addKeybinding(
            key,
            settings,
            Meta.KeyBindingFlags.NONE,
            Shell.ActionMode.NORMAL,
            handler
        );

        this._bindings.push(key);
        if (success) {
            Utils.debug('added keybinding ' + key);
        } else {
            Utils.debug('failed to add keybinding ' + key);
            Utils.debug(success);
        }
    }

    _removeKeyBinding(key) {
        if (this._bindings.indexOf(key)) {
            this._bindings.splice(this._bindings.indexOf(key), 1);
        }

        Utils.debug('removing keybinding ' + key);
        Main.wm.removeKeybinding(key);
    }
}
);

var DaemonMenuItem = GObject.registerClass(
class DeskChangerPopupMenuDaemonMenuItem extends PopupMenu.PopupSwitchMenuItem {
    _init(daemon) {
        super._init(_('DeskChanger Daemon'), daemon.running);
        this._daemon = daemon;
        this._toggled_id = this.connect('toggled', () => {
            (daemon.running)? daemon.stop() : daemon.start();
        });
        this._daemon_id = daemon.connect('toggled', () => {
            this.setToggleState(daemon.running);
        });
    }

    destroy() {
        if (this._toggled_id) {
            this.disconnect(this._toggled_id);
        }
        this._toggled_id = null;

        if (this._daemon_id) {
            this._daemon.disconnect(this._daemon_id);
        }
        this._daemon_id = null;

        super.destroy();
    }
}
);

var OpenCurrentMenuItem = GObject.registerClass(
class DeskChangerPopupMenuOpenCurrent extends PopupMenu.PopupMenuItem {
    _init() {
        super._init(_('Open current wallpaper'));
        this._background = new Gio.Settings({'schema': 'org.gnome.desktop.background'});
        this._activate_id = this.connect('activate', () => {
            Utils.debug(`opening current wallpaper ${this._background.get_string('picture-uri')}`);
            Util.spawn(['xdg-open', this._background.get_string('picture-uri')]);
        });
        Utils.debug(`connect active (${this._activate_id})`);
    }

    destroy() {
        Utils.debug(`disconnect active (${this._activate_id})`);
        this.disconnect(this._activate_id);

        super.destroy();
    }
}
);

let PopupMenuItem = GObject.registerClass(
class DeskChangerPopupMenuItem extends PopupMenu.PopupMenuItem {
    _init(label, value, settings, key) {
        super._init(label);
        this._value = value;
        this._key = key;
        this._key_normalized = key.replace('_', '-');
        this._settings = settings;

        if (settings[this._key] === this._value) {
            this.setOrnament(PopupMenu.Ornament.DOT);
        }

        this._handler_key_changed = settings.connect(`changed::${this._key_normalized}`, () => {
            if (settings[key] === value) {
                this.setOrnament(PopupMenu.Ornament.DOT);
            } else {
                this.setOrnament(PopupMenu.Ornament.NONE);
            }
        });

        this._handler_id = this.connect('activate', () => {
            settings[key] = value;
        });
    }

    destroy() {
        if (this._handler_key_changed) {
            this._settings.disconnect(this._handler_key_changed);
            this._handler_key_changed = null;
        }

        if (this._handler_id) {
            this.disconnect(this._handler_id);
            this._handler_id = null;
        }

        super.destroy();
    }
}
);

let PopupSubMenuMenuItem = GObject.registerClass(
class DeskChangerPopupSubMenuMenuItem extends PopupMenu.PopupSubMenuMenuItem {
    _init(prefix, key, settings, sensitive=true) {
        super._init(`${prefix}: ${settings[key]}`);
        this._prefix = prefix;
        this._settings = settings;
        this._changed_id = settings.connect(`changed::${key.replace('_', '-')}`, () => {
            this.setLabel(settings[key]);
        });
        this.setSensitive(sensitive);
    }

    destroy() {
        if (this._changed_id) {
            this._settings.disconnect(this._changed_id);
        }

        super.destroy();
    }

    setLabel(label) {
        this.label.text = `${this._prefix}: ${label}`;
    }
}
);

var PreviewMenuItem = GObject.registerClass(
class DeskChangerPopupMenuPreviewMenuItem extends PopupMenu.PopupBaseMenuItem {
    _init(daemon) {
        super._init({reactive: true});
        this._box = new St.BoxLayout({vertical: true});
        this.add_actor(this._box);
        this._prefix = new St.Label({text: _('Open next wallpaper')});
        this._box.add(this._prefix);
        this._preview = new DeskChangerControl.PreviewControl(220, daemon);
        this._box.add(this._preview);
        this._activate_id = this.connect('activate', () => {
            if (this._preview.file) {
                Utils.debug(`opening file ${this._preview.file}`);
                Util.spawn(['xdg-open', this._preview.file]);
            } else {
                Utils.error('no preview set');
            }
        });
        Utils.debug(`connect activate ${this._activate_id}`);
    }

    destroy() {
        Utils.debug(`disconnect activate ${this._activate_id}`);
        this.disconnect(this._activate_id);

        this._preview.destroy();
        this._prefix.destroy();
        this._box.destroy();
        super.destroy();
    }
}
);

let ProfileMenuItem = GObject.registerClass({
    Abstract: true,
},
class DeskChangerPopupSubMenuMenuItemProfile extends PopupSubMenuMenuItem {
    _init(label, key, settings, sensitive=true) {
        super._init(label, key, settings, sensitive);
        this._settings = settings;
        this._profiles_changed_id = settings.connect('changed::profiles', () => {
            this._populate_profiles(settings, key);
        });
        this._populate_profiles(settings, key);
    }

    destroy() {
        this._settings.disconnect(this._profiles_changed_id);
        super.destroy();
    }

    _populate_profiles(settings, key) {
        this.menu.removeAll();
        for (let index in settings.profiles) {
            let item = new PopupMenuItem(index, index, settings, key);
            this.menu.addMenuItem(item);
        }
    }
}
);

var ProfileDesktopMenuItem = GObject.registerClass(
class DeskChangerPopupSubMenuMenuItemProfileDesktop extends ProfileMenuItem {
    _init(settings, sensitive = true) {
        super._init(_('Desktop Profile'), 'current_profile', settings, sensitive);
    }
}
);

var ProfileLockScreenMenuItem = GObject.registerClass(
class DeskChangerPopupSubMenuMenuItemProfileLockScreen extends ProfileMenuItem {
    _init(settings, sensitive=true) {
        super._init(_('Lock Screen Profile'), 'lockscreen_profile', settings, sensitive);
    }

    setLabel(label) {
        if (!label) {
            label = '(inherited)';
        }

        super.setLabel(label);
    }

    _populate_profiles(settings, key) {
        super._populate_profiles(settings, 'lockscreen_profile', key);

        let inherit = new PopupMenuItem(_('(inherit from desktop)'), '', settings, key);
        this.menu.addMenuItem(inherit);
    }
}
);

var RotationMenuItem = GObject.registerClass(
class DeskChangerPopupMenuRotationMenuItem extends PopupSubMenuMenuItem {
    _init(settings, sensitive=true) {
        super._init(_('Rotation mode'), 'rotation', settings, sensitive);
        this.menu.addMenuItem(new PopupMenuItem(_('Interval timer'), 'interval', settings, 'rotation'));
        this.menu.addMenuItem(new PopupMenuItem(_('Beginning of hour'), 'hourly', settings, 'rotation'));
        this.menu.addMenuItem(new PopupMenuItem(_('Disabled'), 'disabled', settings, 'rotation'));
    }
}
);

var SwitchMenuItem = GObject.registerClass(
class DeskChangerPopupSwitchMenuItem extends PopupMenu.PopupSwitchMenuItem {
    _init(label, key, settings) {
        super._init(label, settings[key]);
        this._settings = settings;
        this._key = key;
        this._key_normalized = key.replace('_', '-');
        this._handler_changed = settings.connect(`changed::${this._key_normalized}`, (settings, key) => {
            this.setToggleState(settings.get_boolean(key));
        });
        this._handler_toggled = this.connect('toggled', () => {
            this._settings[this._key] = this.state;
        });
    }

    destroy() {
        if (this._handler_changed) {
            this._settings.disconnect(this._handler_changed);
        }

        if (this._handler_toggled) {
            this._settings.disconnect(this._handler_toggled);
        }

        super.destroy();
    }
}
);
<|endoftext|>


<commit_before>/*
eslint no-shadow: ["error", { "allow": ["$scope"] }]
*/
/*
eslint no-underscore-dangle: ["error", { "allow": ["_id",] }]
*/

const taskControl = function taksControl($scope, $mdDialog, $mdToast, db) {
  $scope.current = undefined;
  $scope.isShown = true;
  $scope.do = false;
  $scope.delete = false;

  $scope.markAsDone = (taskId) => {
    db.markAsDone(taskId, (err) => {
      if (!err) {
        $mdToast.show(
          $mdToast.simple()
          .textContent('Task done.')
          .position('bottom start')
          .hideDelay(1000)
        );
      }
    });
  };
  $scope.remove = (taskId) => {
    db.remove(taskId, (err) => {
      if (!err) {
        $mdToast.show(
          $mdToast.simple()
          .textContent('Task deleted.')
          .position('bottom start')
          .hideDelay(1000)
        );
      }
    });
  };

  function DialogController($scope, task) {
    $scope.task = task;
    $scope.cancel = function cancel() {
      $mdDialog.cancel();
    };
    $scope.update = function update(newTask) {
      if (newTask) {
        $mdDialog.hide(newTask);
      }
    };
  }
  $scope.edit = (ev, cur) => {
    $mdDialog.show({
      controller: DialogController,
      locals: {
        task: cur.text,
      },
      templateUrl: 'app/components/tasks/templates/editTaskDialog.html',
      parent: angular.element(document.body),
      targetEvent: ev,
      clickOutsideToClose: true,
    })
    .then((task) => {
      db.edit(cur._id, task, (err) => {
        if (!err) {
          db.find('open', (tasks) => {
            $scope.openTasks = tasks;
            $scope.$apply();
          });
          db.find('overdue', (tasks) => {
            $scope.overdueTasks = tasks;
            $scope.$apply();
          });
          $mdToast.show(
            $mdToast.simple()
            .textContent('Task edited.')
            .position('bottom start')
            .hideDelay(1000)
          );
        }
      });
    });
  };
  $scope.$on('Update tasks', () => {
    db.find('open', (tasks) => {
      $scope.openTasks = tasks;
    });
    db.find('overdue', (tasks) => {
      $scope.overdueTasks = tasks;
    });
  });
  db.find('open', (tasks) => {
    $scope.openTasks = tasks;
    $scope.$apply();
  });
  db.find('overdue', (tasks) => {
    $scope.overdueTasks = tasks;
    $scope.$apply();
  });
};

angular.module('MainApp')
  .controller('TaskControl', taskControl);
<commit_msg>Update tasks_controller to support not-yet tasks<commit_after>/*
eslint no-shadow: ["error", { "allow": ["$scope"] }]
*/
/*
eslint no-underscore-dangle: ["error", { "allow": ["_id",] }]
*/

const taskControl = function taksControl($scope, $mdDialog, $mdToast, db) {
  $scope.current = undefined;
  $scope.isShown = true;
  $scope.do = false;
  $scope.delete = false;

  $scope.markAsDone = (taskId) => {
    db.markAsDone(taskId, (err) => {
      if (!err) {
        $mdToast.show(
          $mdToast.simple()
          .textContent('Task done.')
          .position('bottom start')
          .hideDelay(1000)
        );
      }
    });
  };
  $scope.remove = (taskId) => {
    db.remove(taskId, (err) => {
      if (!err) {
        $mdToast.show(
          $mdToast.simple()
          .textContent('Task deleted.')
          .position('bottom start')
          .hideDelay(1000)
        );
      }
    });
  };

  function DialogController($scope, task) {
    $scope.task = task;
    $scope.cancel = function cancel() {
      $mdDialog.cancel();
    };
    $scope.update = function update(newTask) {
      if (newTask) {
        $mdDialog.hide(newTask);
      }
    };
  }
  $scope.edit = (ev, cur) => {
    $mdDialog.show({
      controller: DialogController,
      locals: {
        task: cur.text,
      },
      templateUrl: 'app/components/tasks/templates/editTaskDialog.html',
      parent: angular.element(document.body),
      targetEvent: ev,
      clickOutsideToClose: true,
    })
    .then((task) => {
      db.edit(cur._id, task, (err) => {
        if (!err) {
          db.find('open', (tasks) => {
            $scope.openTasks = tasks;
            $scope.$apply();
          });
          db.find('overdue', (tasks) => {
            $scope.overdueTasks = tasks;
            $scope.$apply();
          });
          db.find('notyet', (tasks) => {
            $scope.notYetTasks = tasks;
            $scope.$apply();
          });
          $mdToast.show(
            $mdToast.simple()
            .textContent('Task edited.')
            .position('bottom start')
            .hideDelay(1000)
          );
        }
      });
    });
  };
  $scope.$on('Update tasks', () => {
    db.find('open', (tasks) => {
      $scope.openTasks = tasks;
    });
    db.find('overdue', (tasks) => {
      $scope.overdueTasks = tasks;
    });
    db.find('notyet', (tasks) => {
      $scope.notYetTasks = tasks;
    });
  });
  db.find('open', (tasks) => {
    $scope.openTasks = tasks;
    $scope.$apply();
  });
  db.find('overdue', (tasks) => {
    $scope.overdueTasks = tasks;
    $scope.$apply();
  });
  db.find('notyet', (tasks) => {
    $scope.notYetTasks = tasks;
    $scope.$apply();
  });
};

angular.module('MainApp')
  .controller('TaskControl', taskControl);
<|endoftext|>