<commit_before>'use strict';

var uuid = require('node-uuid'),
    Q = require('q'),
    _ = require('lodash'),
    path = require('path'),
    config = require(path.join(__dirname,'../config')),
    platforms = config.platforms;

function Manifold(manifoldLib){
    this.lib = manifoldLib;
}

Manifold.prototype.createManifestFromUrl = function(url,client){
    var self = this;

    if(url.indexOf('http') === -1){
        url = 'http://'+url;
    }

    return Q.Promise(function(resolve,reject){
        self.lib.manifestTools.getManifestFromSite(url, function(err, manifestInfo) {
            if (err) {
                if(err.message !== 'Failed to retrieve manifest from site.'){
                    return reject(err);
                }else{
                    manifestInfo = {
                        content: {
                        },
                        format: 'w3c'
                    };
                }
            }

            var manifest = _.assign(manifestInfo,{ id: uuid.v4().slice(0,8) });

            self.validateManifest(manifest)
                .then(function(manifest){
                    client.set(manifest.id,JSON.stringify(manifest));
                    return resolve(manifest);
                })
                .fail(reject);
        });
    });
};

Manifold.prototype.createManifestFromFile = function(file,client){
    var self = this;

    return Q.Promise(function(resolve,reject){
        self.lib.manifestTools.getManifestFromFile(file.path, function (err, manifestInfo) {
            if (err) { return reject(err); }

            var manifest = _.assign(manifestInfo,{ id: uuid.v4().slice(0,8) });
            self.validateManifest(manifest)
                .then(function(manifest){
                    client.set(manifest.id,JSON.stringify(manifest));
                    return resolve(manifest);
                })
                .fail(reject);
        });
    });
};

Manifold.prototype.validateManifest = function(manifest){
    var self = this;

    return Q.Promise(function(resolve,reject){
        self.lib.manifestTools.validateManifest(manifest, platforms, function(err,results){
            if(err){ return reject(err); }

            var errors = _.filter(results,{level: 'error'}),
            suggestions = _.filter(results,{level: 'suggestion'}),
            warnings = _.filter(results,{level: 'warning'});

            self.assignValidationErrors(errors,manifest);
            self.assignSuggestions(suggestions,manifest);
            self.assignWarnings(warnings,manifest);

            return resolve(manifest);
        });
    });
};

Manifold.prototype.updateManifest = function(manifestId,updates,client) {
    var self = this;

    return Q.Promise(function(resolve,reject){
        client.get(manifestId,function(err,reply){
            if(err) return reject(err);
            if(!reply) return reject(new Error('Manifest not found'));

            var manifest = JSON.parse(reply);
            manifest.content = updates;

            return self.validateManifest(manifest)
                .then(function(manifest){
                    client.set(manifest.id,JSON.stringify(manifest));

                    resolve(manifest);
                });
        });
    });
};

Manifold.prototype.normalize = function(manifest){
    var self = this;

    return Q.Promise(function(resolve,reject){
        console.log('Validating start url...');
        self.lib.manifestTools.validateAndNormalizeStartUrl(manifest.content.start_url,manifest,function(err,normManifest){
            if(err){
                console.log('Normalizing Error',err);
                return reject(err);
            }

            manifest = _.assign(manifest,normManifest);

            resolve(manifest);
        });
    });
};

Manifold.prototype.createProject = function(manifest,outputDir,platforms,buildCordova){
    var self = this;

    return Q.Promise(function(resolve, reject){
        var cleanManifest = _.omit(manifest,'id');
        console.log('Building the project...',cleanManifest,outputDir,platforms,buildCordova);
        self.lib.projectBuilder.createApps(cleanManifest, outputDir, platforms, buildCordova, function (err) {

            if(err){
                console.log('Create Projects Errors!!!',err);
                return reject(err);
            }

            return resolve();
        });
    });
};

Manifold.prototype.assignValidationErrors = function(errors,manifest){
    var data = { errors: []};

    _.each(errors,function(e){
        if(_.any(data.errors,'member',e.member)){
            var error = _.find(data.errors,{ memeber: e.member });
            error.issues = error.issues || [];
            error.issues.push({ description: e.description, platform: e.platform, code: e.code });
        }else{
            data.errors.push({
                member: e.member,
                issues: [{
                    description: e.description,
                    platform: e.platform,
                    code: e.code
                }]
            });
        }
    });

    manifest = _.assign(manifest,data);
};

Manifold.prototype.assignSuggestions = function(suggestions,manifest){
    var data = { suggestions: []};

    _.each(suggestions,function(s){
        if(_.any(data.suggestions,'member',s.member)){
            var suggestion = _.find(data.suggestions,'member',s.member);
            suggestion.issues = suggestion.issues || [];
            suggestion.issues.push({ description: s.description, platform: s.platform, code: s.code });
        }else{
            data.suggestions.push({
                member: s.member,
                issues: [{
                    description: s.description,
                    platform: s.platform,
                    code: s.code
                }]
            });
        }
    });

    manifest = _.assign(manifest,data);
};

Manifold.prototype.assignWarnings = function(warnings,manifest){
    var data = { warnings: []};

    _.each(warnings,function(w){
        if(_.any(data.warnings,'member',w.member)){
            var warning = _.find(data.warnings,'member',w.member);
            warning.issues = warning.issues || [];
            warning.issues.push({ description: w.description, platform: w.platform, code: w.code });
        }else{
            data.warnings.push({
                member: w.member,
                issues: [{
                    description: w.description,
                    platform: w.platform,
                    code: w.code
                }]
            });
        }
    });

    manifest = _.assign(manifest,data);
};

exports.create = function(manifoldLib){
    return new Manifold(manifoldLib);
};
<commit_msg>One more quick fix for errors<commit_after>'use strict';

var uuid = require('node-uuid'),
    Q = require('q'),
    _ = require('lodash'),
    path = require('path'),
    config = require(path.join(__dirname,'../config')),
    platforms = config.platforms;

function Manifold(manifoldLib){
    this.lib = manifoldLib;
}

Manifold.prototype.createManifestFromUrl = function(url,client){
    var self = this;

    if(url.indexOf('http') === -1){
        url = 'http://'+url;
    }

    return Q.Promise(function(resolve,reject){
        self.lib.manifestTools.getManifestFromSite(url, function(err, manifestInfo) {
            if (err) {
                if(err.message !== 'Failed to retrieve manifest from site.'){
                    return reject(err);
                }else{
                    manifestInfo = {
                        content: {
                        },
                        format: 'w3c'
                    };
                }
            }

            var manifest = _.assign(manifestInfo,{ id: uuid.v4().slice(0,8) });

            self.validateManifest(manifest)
                .then(function(manifest){
                    client.set(manifest.id,JSON.stringify(manifest));
                    return resolve(manifest);
                })
                .fail(reject);
        });
    });
};

Manifold.prototype.createManifestFromFile = function(file,client){
    var self = this;

    return Q.Promise(function(resolve,reject){
        self.lib.manifestTools.getManifestFromFile(file.path, function (err, manifestInfo) {
            if (err) { return reject(err); }

            var manifest = _.assign(manifestInfo,{ id: uuid.v4().slice(0,8) });
            self.validateManifest(manifest)
                .then(function(manifest){
                    client.set(manifest.id,JSON.stringify(manifest));
                    return resolve(manifest);
                })
                .fail(reject);
        });
    });
};

Manifold.prototype.validateManifest = function(manifest){
    var self = this;

    return Q.Promise(function(resolve,reject){
        self.lib.manifestTools.validateManifest(manifest, platforms, function(err,results){
            if(err){ return reject(err); }

            var errors = _.filter(results,{level: 'error'}),
            suggestions = _.filter(results,{level: 'suggestion'}),
            warnings = _.filter(results,{level: 'warning'});

            self.assignValidationErrors(errors,manifest);
            self.assignSuggestions(suggestions,manifest);
            self.assignWarnings(warnings,manifest);

            return resolve(manifest);
        });
    });
};

Manifold.prototype.updateManifest = function(manifestId,updates,client) {
    var self = this;

    return Q.Promise(function(resolve,reject){
        client.get(manifestId,function(err,reply){
            if(err) return reject(err);
            if(!reply) return reject(new Error('Manifest not found'));

            var manifest = JSON.parse(reply);
            manifest.content = updates;

            return self.validateManifest(manifest)
                .then(function(manifest){
                    client.set(manifest.id,JSON.stringify(manifest));

                    resolve(manifest);
                });
        });
    });
};

Manifold.prototype.normalize = function(manifest){
    var self = this;

    return Q.Promise(function(resolve,reject){
        console.log('Validating start url...');
        self.lib.manifestTools.validateAndNormalizeStartUrl(manifest.content.start_url,manifest,function(err,normManifest){
            if(err){
                console.log('Normalizing Error',err);
                return reject(err);
            }

            manifest = _.assign(manifest,normManifest);

            resolve(manifest);
        });
    });
};

Manifold.prototype.createProject = function(manifest,outputDir,platforms,buildCordova){
    var self = this;

    return Q.Promise(function(resolve, reject){
        var cleanManifest = _.omit(manifest,'id');
        console.log('Building the project...',cleanManifest,outputDir,platforms,buildCordova);
        self.lib.projectBuilder.createApps(cleanManifest, outputDir, platforms, buildCordova, function (err) {

            if(err){
                console.log('Create Projects Errors!!!',err);
                return reject(err);
            }

            return resolve();
        });
    });
};

Manifold.prototype.assignValidationErrors = function(errors,manifest){
    var data = { errors: []};

    _.each(errors,function(e){
        if(_.any(data.errors,'member',e.member)){
            var error = _.find(data.errors,'member',e.member);
            error.issues = error.issues || [];
            error.issues.push({ description: e.description, platform: e.platform, code: e.code });
        }else{
            data.errors.push({
                member: e.member,
                issues: [{
                    description: e.description,
                    platform: e.platform,
                    code: e.code
                }]
            });
        }
    });

    manifest = _.assign(manifest,data);
};

Manifold.prototype.assignSuggestions = function(suggestions,manifest){
    var data = { suggestions: []};

    _.each(suggestions,function(s){
        if(_.any(data.suggestions,'member',s.member)){
            var suggestion = _.find(data.suggestions,'member',s.member);
            suggestion.issues = suggestion.issues || [];
            suggestion.issues.push({ description: s.description, platform: s.platform, code: s.code });
        }else{
            data.suggestions.push({
                member: s.member,
                issues: [{
                    description: s.description,
                    platform: s.platform,
                    code: s.code
                }]
            });
        }
    });

    manifest = _.assign(manifest,data);
};

Manifold.prototype.assignWarnings = function(warnings,manifest){
    var data = { warnings: []};

    _.each(warnings,function(w){
        if(_.any(data.warnings,'member',w.member)){
            var warning = _.find(data.warnings,'member',w.member);
            warning.issues = warning.issues || [];
            warning.issues.push({ description: w.description, platform: w.platform, code: w.code });
        }else{
            data.warnings.push({
                member: w.member,
                issues: [{
                    description: w.description,
                    platform: w.platform,
                    code: w.code
                }]
            });
        }
    });

    manifest = _.assign(manifest,data);
};

exports.create = function(manifoldLib){
    return new Manifold(manifoldLib);
};
<|endoftext|>


<commit_before>import {
  platform, DefaultDOMElement, AbstractEditor,
  Toolbar, EditorSession, DOMSelection
} from 'substance'
import SheetContextSection from './SheetContextSection'
import SheetStatusBar from './SheetStatusBar'
import FormulaBar from './FormulaBar'
import FormulaEditor from './FormulaEditor'

export default class SheetEditor extends AbstractEditor {

  constructor(...args) {
    super(...args)
    // a context for FormulaBar and FormulaEditor
    this._formulaEditorContext = this._createFormulaEditorContext()
    // true when the cursor is either in the FormularBar or the FormulaEditor
    this._isEditing = false

    this.handleActions({
      'updateCell': this._updateCell,
      'cancelCellEditing': this._cancelCellEditing,
      'editCell': this._editCell,
      'requestSelectionChange': this._requestSelectionChange
    })
  }

  getChildContext() {
    let editorSession = this.props.editorSession
    return Object.assign({}, super.getChildContext(), {
      configurator: editorSession.getConfigurator(),
      host: this.props.host,
      issueManager: editorSession.getManager('issue-manager'),
      // TODO: get rid of this
      cellEditorSession: this._cellEditorSession
    })
  }

  getInitialState() {
    return {
      showContext: false,
      contextId: null,
      cellId: null
    }
  }

  didMount() {
    super.didMount()

    const editorSession = this.props.editorSession
    if (platform.inBrowser) {
      DefaultDOMElement.wrap(window).on('resize', this._onResize, this)
    }
    editorSession.onUpdate('selection', this._onSelectionChange, this)

    this._formulaEditorContext.editorSession.onUpdate('selection', this._onCellEditorSelectionChange, this)
    // TODO: is it really necessary to have this in the first line?
    // always render a second time to render for the real element dimensions
    // because the table with fixed layout needs exact dimensions
    this.rerender()
  }

  dispose() {
    super.dispose()
    const editorSession = this.props.editorSession
    if (platform.inBrowser) {
      DefaultDOMElement.wrap(window).off(this)
    }
    editorSession.off(this)
    this._formulaEditorContext.editorSession.off(this)
  }

  render($$) {
    let el = $$('div').addClass('sc-sheet-editor')
    el.append(
      $$('div').addClass('se-main-section').append(
        this._renderToolpane($$),
        this._renderContent($$),
        this._renderStatusbar($$)
      )
    )
    if(this.state.showContext) {
      el.append(
        $$(SheetContextSection, {
          contextId: this.state.contextId,
          cellId: this.state.cellId
        }).ref('context')
      )
    }
    return el
  }

  _renderToolpane($$) {
    const configurator = this.getConfigurator()
    let el = $$('div').addClass('se-tool-pane')
    el.append(
      $$(FormulaBar, {
        node: this._formulaEditorContext.node,
        context: this._formulaEditorContext
      }),
      $$(Toolbar, {
        toolPanel: configurator.getToolPanel('toolbar')
      }).ref('toolbar')
    )
    return el
  }

  _renderContent($$) {
    let el = $$('div').addClass('se-body')
    el.append(
      this._renderSheet($$)
    )
    return el
  }

  _renderSheet($$) {
    const sheet = this.getDocument()
    const formulaEditorContext = this._formulaEditorContext
    // only rendering the sheet when mounted
    // so that we have real width and height
    if (this.isMounted()) {
      const SheetComponent = this.getComponent('sheet')
      return $$(SheetComponent, {
        sheet,
        overlays: [
          $$(FormulaEditor, {
            context: formulaEditorContext
          })
            .ref('formulaEditor')
            .css({
              position: 'absolute',
              display: 'none'
            })
        ]
      }).ref('sheet')
    } else {
      return $$('div')
    }
  }

  _renderStatusbar($$) {
    return $$(SheetStatusBar, {}).ref('sheet-statusbar')
  }

  getWidth() {
    if (this.el) {
      return this.el.getWidth()
    } else {
      return 1000
    }
  }

  getHeight() {
    if (this.el) {
      return this.el.getHeight()
    } else {
      return 750
    }
  }

  setSelectionOnCell(cellId) {
    const sheet = this.getDocument()
    let cell = sheet.get(cellId)
    let row = cell.parentNode
    let colIdx = row._childNodes.indexOf(cell.id)
    let rowIdx = row.parentNode._childNodes.indexOf(row.id)
    let selData = {
      type: 'range',
      anchorRow: rowIdx,
      focusRow: rowIdx,
      anchorCol: colIdx,
      focusCol: colIdx
    }

    this.props.editorSession.setSelection({
      type: 'custom',
      customType: 'sheet',
      data: selData,
      surfaceId: this.refs.sheet.getId()
    })
  }

  setSelectionOnSheet() {
    const sheet = this.getDocument()
    let selData = {
      type: 'range',
      anchorRow: 0,
      focusRow: sheet.getRowCount() - 1,
      anchorCol: 0,
      focusCol: sheet.getColumnCount() - 1
    }

    this.props.editorSession.setSelection({
      type: 'custom',
      customType: 'sheet',
      data: selData,
      surfaceId: this.refs.sheet.getId()
    })
  }

  toggleContext(contextId, cellId) {
    if(cellId === null && !this.state.showContext) return
    if (this.state.showContext && this.state.contextId === contextId && cellId === undefined) {
      this.setState({
        showContext: false
      })
    } else {
      this.setState({
        showContext: true,
        contextId,
        cellId
      })
    }
  }

  // a context propagated by FormulaBar and FormulaEditor
  _createFormulaEditorContext() {
    const configurator = this.props.editorSession.configurator
    // a document with only one node used by cell editors
    // i.e. expression bar, or popover editor on enter
    let cellEditorDoc = this.getDocument().newInstance()
    // TODO: use an id instead of storing the node on the doc
    let node = cellEditorDoc.createElement('cell')
    let editorSession = new EditorSession(cellEditorDoc, {
      configurator: configurator
    })
    const self = this
    // HACK: creating inline an object which DOMSelection needs to work
    // TODO: either use a helper to create the DOMSelection
    // or change DOMSelection's ctor to be better usable
    let domSelection = new DOMSelection({
      getDocument() { return cellEditorDoc },
      getSurfaceManager() { return editorSession.surfaceManager },
      getElement() { return self.getElement() }
    })
    return {
      editorSession,
      domSelection,
      node,
      markersManager: editorSession.markersManager,
      surfaceManager: editorSession.surfaceManager
    }
  }

  _onResize() {
    if (platform.inBrowser) {
      if (!this._rafId) {
        this._rafId = window.requestAnimationFrame(() => {
          this._rafId = null
          this.refs.sheet.resize()
        })
      }
    }
  }

  _getSheetSelection() {
    return this.getEditorSession().getSelection().data || {}
  }

  _onSelectionChange() {
    let formulaEditorSession = this._formulaEditorContext.editorSession
    let cell = this._getAnchorCell()
    this._setFormula(cell.textContent)
    if (this._isEditing) {
      this._isEditing = false
      this._hideFormulaEditor()
      formulaEditorSession.setSelection(null)
    }
  }

  _onCellEditorSelectionChange(sel) {
    let sheetSel = this._getSheetSelection()
    let formulaEditorSession = this._formulaEditorContext.editorSession
    if (!sel.isNull() && !this._isEditing) {
      this._isEditing = true
      this._currentSelection = this.getEditorSession().getSelection()
      this._showFormulaEditor(sheetSel.anchorRow, sheetSel.anchorCol)
      formulaEditorSession.resetHistory()
    }
  }

  /*
    This gets called when the user starts editing a cell
    At this time it should be sure that the table cell
    is already rendered.
  */
  _showFormulaEditor(rowIdx, colIdx) {
    const formulaEditor = this.refs.formulaEditor
    let rect = this.refs.sheet.getCellRect(rowIdx, colIdx)
    formulaEditor.css({
      display: 'block',
      position: 'absolute',
      top: rect.top,
      left: rect.left,
      "min-width": rect.width+'px',
      "min-height": rect.height+'px'
    })
  }

  _hideFormulaEditor() {
    const formulaEditor = this.refs.formulaEditor
    formulaEditor.css({
      display: 'none',
      top: 0, left: 0
    })
  }

  _setFormula(val, sel) {
    let context = this._formulaEditorContext
    let node = context.node
    let formulaEditorSession = this._formulaEditorContext.editorSession
    formulaEditorSession.transaction(tx => {
      tx.set(node.getPath(), val)
      tx.setSelection(sel)
    })
  }

  _cancelCellEditing() {
    // just renew the the selection
    let editorSession = this.getEditorSession()
    editorSession.setSelection(editorSession.getSelection())
  }

  /*
    Request inline editor
  */
  _editCell(initialValue) {
    let formulaEditorSession = this._formulaEditorContext.editorSession
    let formulaNode = this._formulaEditorContext.node
    if (initialValue) {
      this._setFormula(initialValue)
    }
    let pos = formulaNode.textContent.length
    formulaEditorSession.setSelection({
      type: 'property',
      path: formulaNode.getPath(),
      startOffset: pos,
      surfaceId: 'formula-editor'
    })
  }

  _requestSelectionChange(newSelection) {
    let editorSession = this.getEditorSession()
    if (this._isEditing) {
      console.info('TODO: Implement range selector', newSelection)
    } else {
      editorSession.setSelection(newSelection)
    }
  }

  _updateCell() {
    let editorSession = this.getEditorSession()
    let cell = this._getAnchorCell()
    let newValue = this._formulaEditorContext.node.getText()
    // HACK: need to set the selection 'silently' so that
    // this works fine with undo/redo (-> before state)
    let newSel = this.refs.sheet.shiftSelection(1, 0, false)
    editorSession._setSelection(this._currentSelection)
    editorSession.transaction(tx => {
      tx.set(cell.getPath(), newValue)
      tx.setSelection(newSel)
    })
  }

  _getAnchorCell() {
    let sel = this._getSheetSelection()
    return this.getDocument().getCell(sel.anchorRow, sel.anchorCol)
  }

}
<commit_msg>Fix issue with recovering selections on undo/redo<commit_after>import {
  platform, DefaultDOMElement, AbstractEditor,
  Toolbar, EditorSession, DOMSelection
} from 'substance'
import SheetContextSection from './SheetContextSection'
import SheetStatusBar from './SheetStatusBar'
import FormulaBar from './FormulaBar'
import FormulaEditor from './FormulaEditor'

export default class SheetEditor extends AbstractEditor {

  constructor(...args) {
    super(...args)
    // a context for FormulaBar and FormulaEditor
    this._formulaEditorContext = this._createFormulaEditorContext()
    // true when the cursor is either in the FormularBar or the FormulaEditor
    this._isEditing = false

    this.handleActions({
      'updateCell': this._updateCell,
      'cancelCellEditing': this._cancelCellEditing,
      'editCell': this._editCell,
      'requestSelectionChange': this._requestSelectionChange
    })
  }

  getChildContext() {
    let editorSession = this.props.editorSession
    return Object.assign({}, super.getChildContext(), {
      configurator: editorSession.getConfigurator(),
      host: this.props.host,
      issueManager: editorSession.getManager('issue-manager'),
      // TODO: get rid of this
      cellEditorSession: this._cellEditorSession
    })
  }

  getInitialState() {
    return {
      showContext: false,
      contextId: null,
      cellId: null
    }
  }

  didMount() {
    super.didMount()

    const editorSession = this.props.editorSession
    if (platform.inBrowser) {
      DefaultDOMElement.wrap(window).on('resize', this._onResize, this)
    }
    editorSession.onUpdate('selection', this._onSelectionChange, this)

    this._formulaEditorContext.editorSession.onUpdate('selection', this._onCellEditorSelectionChange, this)
    // TODO: is it really necessary to have this in the first line?
    // always render a second time to render for the real element dimensions
    // because the table with fixed layout needs exact dimensions
    this.rerender()
  }

  dispose() {
    super.dispose()
    const editorSession = this.props.editorSession
    if (platform.inBrowser) {
      DefaultDOMElement.wrap(window).off(this)
    }
    editorSession.off(this)
    this._formulaEditorContext.editorSession.off(this)
  }

  render($$) {
    let el = $$('div').addClass('sc-sheet-editor')
    el.append(
      $$('div').addClass('se-main-section').append(
        this._renderToolpane($$),
        this._renderContent($$),
        this._renderStatusbar($$)
      )
    )
    if(this.state.showContext) {
      el.append(
        $$(SheetContextSection, {
          contextId: this.state.contextId,
          cellId: this.state.cellId
        }).ref('context')
      )
    }
    return el
  }

  _renderToolpane($$) {
    const configurator = this.getConfigurator()
    let el = $$('div').addClass('se-tool-pane')
    el.append(
      $$(FormulaBar, {
        node: this._formulaEditorContext.node,
        context: this._formulaEditorContext
      }),
      $$(Toolbar, {
        toolPanel: configurator.getToolPanel('toolbar')
      }).ref('toolbar')
    )
    return el
  }

  _renderContent($$) {
    let el = $$('div').addClass('se-body')
    el.append(
      this._renderSheet($$)
    )
    return el
  }

  _renderSheet($$) {
    const sheet = this.getDocument()
    const formulaEditorContext = this._formulaEditorContext
    // only rendering the sheet when mounted
    // so that we have real width and height
    if (this.isMounted()) {
      const SheetComponent = this.getComponent('sheet')
      return $$(SheetComponent, {
        sheet,
        overlays: [
          $$(FormulaEditor, {
            context: formulaEditorContext
          })
            .ref('formulaEditor')
            .css({
              position: 'absolute',
              display: 'none'
            })
        ]
      }).ref('sheet')
    } else {
      return $$('div')
    }
  }

  _renderStatusbar($$) {
    return $$(SheetStatusBar, {}).ref('sheet-statusbar')
  }

  getWidth() {
    if (this.el) {
      return this.el.getWidth()
    } else {
      return 1000
    }
  }

  getHeight() {
    if (this.el) {
      return this.el.getHeight()
    } else {
      return 750
    }
  }

  setSelectionOnCell(cellId) {
    const sheet = this.getDocument()
    let cell = sheet.get(cellId)
    let row = cell.parentNode
    let colIdx = row._childNodes.indexOf(cell.id)
    let rowIdx = row.parentNode._childNodes.indexOf(row.id)
    let selData = {
      type: 'range',
      anchorRow: rowIdx,
      focusRow: rowIdx,
      anchorCol: colIdx,
      focusCol: colIdx
    }

    this.props.editorSession.setSelection({
      type: 'custom',
      customType: 'sheet',
      data: selData,
      surfaceId: this.refs.sheet.getId()
    })
  }

  setSelectionOnSheet() {
    const sheet = this.getDocument()
    let selData = {
      type: 'range',
      anchorRow: 0,
      focusRow: sheet.getRowCount() - 1,
      anchorCol: 0,
      focusCol: sheet.getColumnCount() - 1
    }

    this.props.editorSession.setSelection({
      type: 'custom',
      customType: 'sheet',
      data: selData,
      surfaceId: this.refs.sheet.getId()
    })
  }

  toggleContext(contextId, cellId) {
    if(cellId === null && !this.state.showContext) return
    if (this.state.showContext && this.state.contextId === contextId && cellId === undefined) {
      this.setState({
        showContext: false
      })
    } else {
      this.setState({
        showContext: true,
        contextId,
        cellId
      })
    }
  }

  // a context propagated by FormulaBar and FormulaEditor
  _createFormulaEditorContext() {
    const configurator = this.props.editorSession.configurator
    // a document with only one node used by cell editors
    // i.e. expression bar, or popover editor on enter
    let cellEditorDoc = this.getDocument().newInstance()
    // TODO: use an id instead of storing the node on the doc
    let node = cellEditorDoc.createElement('cell')
    let editorSession = new EditorSession(cellEditorDoc, {
      configurator: configurator
    })
    const self = this
    // HACK: creating inline an object which DOMSelection needs to work
    // TODO: either use a helper to create the DOMSelection
    // or change DOMSelection's ctor to be better usable
    let domSelection = new DOMSelection({
      getDocument() { return cellEditorDoc },
      getSurfaceManager() { return editorSession.surfaceManager },
      getElement() { return self.getElement() }
    })
    return {
      editorSession,
      domSelection,
      node,
      markersManager: editorSession.markersManager,
      surfaceManager: editorSession.surfaceManager
    }
  }

  _onResize() {
    if (platform.inBrowser) {
      if (!this._rafId) {
        this._rafId = window.requestAnimationFrame(() => {
          this._rafId = null
          this.refs.sheet.resize()
        })
      }
    }
  }

  _getSheetSelection() {
    return this.getEditorSession().getSelection().data || {}
  }

  _onSelectionChange() {
    let formulaEditorSession = this._formulaEditorContext.editorSession
    let cell = this._getAnchorCell()
    this._setFormula(cell.textContent)
    if (this._isEditing) {
      this._isEditing = false
      this._hideFormulaEditor()
      formulaEditorSession.setSelection(null)
    }
  }

  _onCellEditorSelectionChange(sel) {
    let sheetSel = this._getSheetSelection()
    let formulaEditorSession = this._formulaEditorContext.editorSession
    if (!sel.isNull() && !this._isEditing) {
      this._isEditing = true
      this._currentSelection = this.getEditorSession().getSelection()
      this._showFormulaEditor(sheetSel.anchorRow, sheetSel.anchorCol)
      formulaEditorSession.resetHistory()
    }
  }

  /*
    This gets called when the user starts editing a cell
    At this time it should be sure that the table cell
    is already rendered.
  */
  _showFormulaEditor(rowIdx, colIdx) {
    const formulaEditor = this.refs.formulaEditor
    let rect = this.refs.sheet.getCellRect(rowIdx, colIdx)
    formulaEditor.css({
      display: 'block',
      position: 'absolute',
      top: rect.top,
      left: rect.left,
      "min-width": rect.width+'px',
      "min-height": rect.height+'px'
    })
  }

  _hideFormulaEditor() {
    const formulaEditor = this.refs.formulaEditor
    formulaEditor.css({
      display: 'none',
      top: 0, left: 0
    })
  }

  _setFormula(val, sel) {
    let context = this._formulaEditorContext
    let node = context.node
    let formulaEditorSession = this._formulaEditorContext.editorSession
    formulaEditorSession.transaction(tx => {
      tx.set(node.getPath(), val)
      tx.setSelection(sel)
    })
  }

  _cancelCellEditing() {
    // just renew the the selection
    let editorSession = this.getEditorSession()
    editorSession.setSelection(editorSession.getSelection())
  }

  /*
    Request inline editor
  */
  _editCell(initialValue) {
    let formulaEditorSession = this._formulaEditorContext.editorSession
    let formulaNode = this._formulaEditorContext.node
    if (initialValue) {
      this._setFormula(initialValue)
    }
    let pos = formulaNode.textContent.length
    formulaEditorSession.setSelection({
      type: 'property',
      path: formulaNode.getPath(),
      startOffset: pos,
      surfaceId: 'formula-editor'
    })
  }

  _requestSelectionChange(newSelection) {
    let editorSession = this.getEditorSession()
    if (this._isEditing) {
      console.info('TODO: Implement range selector', newSelection)
    } else {
      editorSession.setSelection(newSelection)
    }
  }

  _updateCell() {
    let editorSession = this.getEditorSession()
    let cell = this._getAnchorCell()
    let newValue = this._formulaEditorContext.node.getText()
    // HACK: need to set the selection 'silently' so that
    // this works fine with undo/redo (-> before state)
    // plus: setting the selection in the transaction
    // leads to an inintuitiv undo/redo behavior
    // thus we are updating the selection in an extra update (which is not landing in the history)
    let newSel = this.refs.sheet.shiftSelection(1, 0, false)
    editorSession._setSelection(this._currentSelection)
    editorSession.transaction(tx => {
      tx.set(cell.getPath(), newValue)
    })
    editorSession.setSelection(newSel)
  }

  _getAnchorCell() {
    let sel = this._getSheetSelection()
    return this.getDocument().getCell(sel.anchorRow, sel.anchorCol)
  }

}
<|endoftext|>


<commit_before>import { EventEmitter, forEach, map } from 'substance'
import CellIssue from '../shared/CellIssue'

// EXPERIMENTAL: a first shot for a linter running
// in the 'background' checking every cell
// and rescheduling checks when cells change
export default class SheetLinter extends EventEmitter {

  constructor(sheet, editorSession) {
    super()

    this.sheet = sheet
    this.editorSession = editorSession
    this.issueManager = editorSession.issueManager

    this.queue = []
    this.issues = []
    this.state = 'initial'

    // TODO: need to rethink this when we want to use this
    // for a different underlying implementation, e.g an embedded table
    this._sheetNode = sheet.getRootNode()
    this._doc = this._sheetNode.getDocument()

    editorSession.onRender('document', this._onDocumentChange, this, { path: [this._sheetNode.id]})
  }

  dispose() {
    super.dispose()
    this.editorSession.off(this)
  }

  start() {
    if (this._isInitial()) {
      this.warmup()
    }
    if (this._isStopped()) {
      this._setState('running')
      this.step()
    }
  }

  restart() {
    this._setState('initial')
    this.start()
  }

  warmup() {
    this.queue = []
    const sheet = this.sheet
    let N = sheet.getRowCount()
    let M = sheet.getColumnCount()
    for (let i = 0; i < N; i++) {
      for (let j = 0; j < M; j++) {
        let cell = sheet.getCell(i, j)
        this.queue.push(cell)
      }
    }
    this.firstShot = true
    this._setState('stopped')
  }

  step() {
    if (this.queue.length > 0) {
      this.action()
      if (this._isRunning()) {
        setTimeout(() => {
          this.step()
        })
      }
    } else {
      this._setState('stopped')
      if(!this.firstShot) {
        this.issueManager.set('linter', this.issues)
        this.issues = []
      }
      this.firstShot = false
    }
  }

  action() {
    let next = this.queue.shift()
    if (!next) return
    switch(next.type) {
      case 'cell': {
        // Note: retrieving the cell
        if (this.sheet.contains(next.id)) {
          this.validateCell(next)
        }
        break
      }
      default:
        //
    }

  }

  validateCell(cell) {
    let sheet = this.sheet
    checkType(cell, sheet, this)
  }

  addIssue(issue) {
    if(this.firstShot) {
      this.issueManager.add('linter', issue)
    } else {
      this.issues.push(issue)
    }
  }

  _onDocumentChange(change) {
    let needsUpdate = false
    const sheet = this.sheet
    const N = sheet.getRowCount()
    // TODO we need to detect all relevant changes
    // for scheduling checks
    let cells = {}
    let cols = {}
    for (let i = 0; i < change.ops.length; i++) {
      let op = change.ops[i]
      let nodeId = op.path[0]
      let node = this._doc.get(nodeId)
      if (!node) continue
      // revalidate on all cell changes
      if (node.type === 'cell') {
        cells[node.id] = node
        needsUpdate = true
      } else if (node.type === 'col') {
        if (op.path[2] === 'type') {
          cols[node.id] = node
          needsUpdate = true
        }
      }
    }
    // extract all cell ids for changed columns
    forEach(cols, (column) => {
      let colIdx = sheet.getColumnIndex(column)
      for (let i = 0; i < N; i++) {
        let cell = sheet.getCell(i, colIdx)
        cells[cell.id] = cell
      }
    })
    if (needsUpdate) {
      let newChecks = map(cells)
      // revalidate existing
      let revalidations = []
      let issues = this.issueManager.getIssues('linter')
      issues.forEach((issue) => {
        if (issue.isCellIssue() && !cells[issue.cellId]) {
          let cell = this._doc.get(issue.cellId)
          cells[issue.cellId] = cell
          revalidations.push(cell)
        }
      })

      this.queue = newChecks.concat(revalidations).concat(this.queue)
      this.issueManager.clear('linter')

      if(this.firstShot) {
        this.restart()
      } else {
        this.start()
      }
    }
  }

  _isRunning() {
    return this.state === 'running'
  }

  _isInitial() {
    return this.state === 'initial'
  }

  _isStopped() {
    return this.state === 'stopped'
  }

  _setState(state) {
    this.state = state
    this.emit(state)
  }

}

// EXPERIMENTAL:
function checkType(cell, sheet, linter) {
  let type = sheet.getCellType(cell)
  let str = cell.textContent
  // HACK: do not test dynamic expressions for now
  if (/^\s*=/.exec(str)) return

  let wrongType = false
  switch (type) {
    case 'integer': {
      wrongType = (isNaN(str) || !isInt(str))
      break
    }
    case 'number': {
      wrongType = isNaN(str)
      break
    }
    case 'boolean': {
      wrongType = (str !== 'false' && str !== 'true')
      break
    }
    case 'string':
    case 'any':
      // nothing
      break
    default:
      // nothing
  }
  if (wrongType) {
    let expected = type
    let actual = autoDetectType(str)
    let msg = `Cell content is of wrong type. Expected a ${expected}, but it is a ${actual}`
    //linter.addIssue(new CellTypeError(cell, expected, actual))
    linter.addIssue(new CellIssue(cell.id, 'linter', msg, 2))
  }
}

// TODO: these should go into cellHelpers
function isInt(str) {
  return (parseInt(str, 10) == str) // eslint-disable-line eqeqeq
}

// TODO: we need to discuss if we want to
// allow '1' as float, or if we want to force '1.0' when type is float
function isFloat(str) {
  return (str.indexOf('.') !== -1)
}

function autoDetectType(str) {
  // numbers
  if (!isNaN(str)) {
    if (isInt(str)) {
      return 'integer'
    }
    if (isFloat(str)) {
      return 'float'
    }
    return 'number'
  }
  // boolean
  if (str === 'false' || str === 'true') {
    return 'boolean'
  }
  // TODO: add more
  return 'string'
}
<commit_msg>Do not check cell type if it is empty<commit_after>import { EventEmitter, forEach, map } from 'substance'
import CellIssue from '../shared/CellIssue'

// EXPERIMENTAL: a first shot for a linter running
// in the 'background' checking every cell
// and rescheduling checks when cells change
export default class SheetLinter extends EventEmitter {

  constructor(sheet, editorSession) {
    super()

    this.sheet = sheet
    this.editorSession = editorSession
    this.issueManager = editorSession.issueManager

    this.queue = []
    this.issues = []
    this.state = 'initial'

    // TODO: need to rethink this when we want to use this
    // for a different underlying implementation, e.g an embedded table
    this._sheetNode = sheet.getRootNode()
    this._doc = this._sheetNode.getDocument()

    editorSession.onRender('document', this._onDocumentChange, this, { path: [this._sheetNode.id]})
  }

  dispose() {
    super.dispose()
    this.editorSession.off(this)
  }

  start() {
    if (this._isInitial()) {
      this.warmup()
    }
    if (this._isStopped()) {
      this._setState('running')
      this.step()
    }
  }

  restart() {
    this._setState('initial')
    this.start()
  }

  warmup() {
    this.queue = []
    const sheet = this.sheet
    let N = sheet.getRowCount()
    let M = sheet.getColumnCount()
    for (let i = 0; i < N; i++) {
      for (let j = 0; j < M; j++) {
        let cell = sheet.getCell(i, j)
        this.queue.push(cell)
      }
    }
    this.firstShot = true
    this._setState('stopped')
  }

  step() {
    if (this.queue.length > 0) {
      this.action()
      if (this._isRunning()) {
        setTimeout(() => {
          this.step()
        })
      }
    } else {
      this._setState('stopped')
      if(!this.firstShot) {
        this.issueManager.set('linter', this.issues)
        this.issues = []
      }
      this.firstShot = false
    }
  }

  action() {
    let next = this.queue.shift()
    if (!next) return
    switch(next.type) {
      case 'cell': {
        // Note: retrieving the cell
        if (this.sheet.contains(next.id)) {
          this.validateCell(next)
        }
        break
      }
      default:
        //
    }

  }

  validateCell(cell) {
    let sheet = this.sheet
    checkType(cell, sheet, this)
  }

  addIssue(issue) {
    if(this.firstShot) {
      this.issueManager.add('linter', issue)
    } else {
      this.issues.push(issue)
    }
  }

  _onDocumentChange(change) {
    let needsUpdate = false
    const sheet = this.sheet
    const N = sheet.getRowCount()
    // TODO we need to detect all relevant changes
    // for scheduling checks
    let cells = {}
    let cols = {}
    for (let i = 0; i < change.ops.length; i++) {
      let op = change.ops[i]
      let nodeId = op.path[0]
      let node = this._doc.get(nodeId)
      if (!node) continue
      // revalidate on all cell changes
      if (node.type === 'cell') {
        cells[node.id] = node
        needsUpdate = true
      } else if (node.type === 'col') {
        if (op.path[2] === 'type') {
          cols[node.id] = node
          needsUpdate = true
        }
      }
    }
    // extract all cell ids for changed columns
    forEach(cols, (column) => {
      let colIdx = sheet.getColumnIndex(column)
      for (let i = 0; i < N; i++) {
        let cell = sheet.getCell(i, colIdx)
        cells[cell.id] = cell
      }
    })
    if (needsUpdate) {
      let newChecks = map(cells)
      // revalidate existing
      let revalidations = []
      let issues = this.issueManager.getIssues('linter')
      issues.forEach((issue) => {
        if (issue.isCellIssue() && !cells[issue.cellId]) {
          let cell = this._doc.get(issue.cellId)
          cells[issue.cellId] = cell
          revalidations.push(cell)
        }
      })

      this.queue = newChecks.concat(revalidations).concat(this.queue)
      this.issueManager.clear('linter')

      if(this.firstShot) {
        this.restart()
      } else {
        this.start()
      }
    }
  }

  _isRunning() {
    return this.state === 'running'
  }

  _isInitial() {
    return this.state === 'initial'
  }

  _isStopped() {
    return this.state === 'stopped'
  }

  _setState(state) {
    this.state = state
    this.emit(state)
  }

}

// EXPERIMENTAL:
function checkType(cell, sheet, linter) {
  let str = cell.text()

  // Do not check cell type if it has no content!
  if (!str) return

  let type = sheet.getCellType(cell)
  // HACK: do not test dynamic expressions for now
  if (/^\s*=/.exec(str)) return

  let wrongType = false
  switch (type) {
    case 'integer': {
      wrongType = (isNaN(str) || !isInt(str))
      break
    }
    case 'number': {
      wrongType = isNaN(str)
      break
    }
    case 'boolean': {
      wrongType = (str !== 'false' && str !== 'true')
      break
    }
    case 'string':
    case 'any':
      // nothing
      break
    default:
      // nothing
  }
  if (wrongType) {
    let expected = type
    let actual = autoDetectType(str)
    let msg = `Cell content is of wrong type. Expected a ${expected}, but it is a ${actual}`
    //linter.addIssue(new CellTypeError(cell, expected, actual))
    linter.addIssue(new CellIssue(cell.id, 'linter', msg, 2))
  }
}

// TODO: these should go into cellHelpers
function isInt(str) {
  return (parseInt(str, 10) == str) // eslint-disable-line eqeqeq
}

// TODO: we need to discuss if we want to
// allow '1' as float, or if we want to force '1.0' when type is float
function isFloat(str) {
  return (str.indexOf('.') !== -1)
}

function autoDetectType(str) {
  // numbers
  if (!isNaN(str)) {
    if (isInt(str)) {
      return 'integer'
    }
    if (isFloat(str)) {
      return 'float'
    }
    return 'number'
  }
  // boolean
  if (str === 'false' || str === 'true') {
    return 'boolean'
  }
  // TODO: add more
  return 'string'
}
<|endoftext|>


<commit_before>$(document).ready(function () {

  $.ajax({
    method: "GET",
    url: window.CRM.root + "/api/groups/" + window.CRM.currentGroup + "/roles",
    dataType: "json"
  }).done(function (data) {
    window.CRM.groupRoles = data.ListOptions;
    $("#newRoleSelection").select2({
      data: $(window.CRM.groupRoles).map(function () {
        return {
          id: this.OptionId,
          text: i18next.t(this.OptionName)
        };
      })
    });
    initDataTable();
    //echo '<option value="' . $role['lst_OptionID'] . '">' . $role['lst_OptionName'] . '</option>';
  });

  $(".personSearch").select2({
    minimumInputLength: 2,
    language: window.CRM.shortLocale,
    ajax: {
      url: function (params) {
        return window.CRM.root + "/api/persons/search/" + params.term;
      },
      dataType: 'json',
      delay: 250,
      data: function (params) {
        return {
          q: params.term, // search term
          page: params.page
        };
      },
      processResults: function (rdata, page) {
        return {results: rdata};
      },
      cache: true
    }
  });

  $(".personSearch").on("select2:select", function (e) {
      window.CRM.groups.promptSelection({Type:window.CRM.groups.selectTypes.Role,GroupID:window.CRM.currentGroup},function(selection){
        window.CRM.groups.addPerson(window.CRM.currentGroup, e.params.data.objid,selection.RoleID).done(function (data) {
          $(".personSearch").val(null).trigger('change');
          window.CRM.DataTableAPI.ajax.reload();/* we reload the data no need to add the person inside the dataTable */
        });
      });
  });

  $("#deleteSelectedRows").click(function () {
    var deletedRows = window.CRM.DataTableAPI.rows('.selected').data()
    bootbox.confirm({
      message: i18next.t("Are you sure you want to remove the selected group members?") + " (" + deletedRows.length + ") ",
      buttons: {
        confirm: {
          label:  i18next.t('Yes'),
            className: 'btn-success'
        },
        cancel: {
          label:  i18next.t('No'),
          className: 'btn-danger'
        }
      },
      callback: function (result)
      {
        if (result)
        {
          $.each(deletedRows, function (index, value) {
            window.CRM.groups.removePerson(window.CRM.currentGroup,value.PersonId).done(
              function(){
                window.CRM.DataTableAPI.row(function (idx, data, node) {
                  if (data.PersonId == value.PersonId) {
                    return true;
                  }
                }).remove();
                window.CRM.DataTableAPI.rows().invalidate().draw(true);
            });
          });
        }
      }
    });

  });

  $("#addSelectedToCart").click(function () {
    if (window.CRM.DataTableAPI.rows('.selected').length > 0)
    {
      var selectedPersons = {
        "Persons" : $.map(window.CRM.DataTableAPI.rows('.selected').data(), function(val,i){
                      return val.PersonId;
                    })
      };
      window.CRM.cart.addPerson(selectedPersons.Persons);
    }

  });

  //copy membership
  $("#addSelectedToGroup").click(function () {
    window.CRM.groups.promptSelection({Type:window.CRM.groups.selectTypes.Group|window.CRM.groups.selectTypes.Role}, function(data){
      selectedRows = window.CRM.DataTableAPI.rows('.selected').data()
      $.each(selectedRows, function (index, value) {
        window.CRM.groups.addPerson(data.GroupID,value.PersonId,data.RoleID);
    });
    });
  });

  $("#moveSelectedToGroup").click(function () {
    window.CRM.groups.promptSelection({Type:window.CRM.groups.selectTypes.Group|window.CRM.groups.selectTypes.Role},function(data){
      selectedRows = window.CRM.DataTableAPI.rows('.selected').data()
      $.each(selectedRows, function (index, value) {
        console.log(data);
        window.CRM.groups.addPerson(data.GroupID,value.PersonId,data.RoleID);
        window.CRM.groups.removePerson(window.CRM.currentGroup,value.PersonId).done(
          function () {
            window.CRM.DataTableAPI.row(function (idx, data, node) {
              if (data.PersonId == value.PersonId) {
                return true;
              }
            }).remove();
            window.CRM.DataTableAPI.rows().invalidate().draw(true);
        });
      });
    });
  });

  $("#AddGroupMembersToCart").click(function () {
    window.CRM.cart.addGroup($(this).data("groupid"));
  })

  $(document).on("click", ".changeMembership", function (e) {
    var PersonID = $(e.currentTarget).data("personid");
    window.CRM.groups.promptSelection({Type:window.CRM.groups.selectTypes.Role,GroupID:window.CRM.currentGroup},function(selection){
      window.CRM.groups.addPerson(window.CRM.currentGroup,PersonID,selection.RoleID).done(function(){
        window.CRM.DataTableAPI.row(function (idx, data, node) {
        if (data.PersonId == PersonID) {
          data.RoleId = selection.RoleID;
          return true;
        }
      });
      window.CRM.DataTableAPI.rows().invalidate().draw(true);
      });
    });
    e.stopPropagation();
  });

});

function initDataTable() {
  var DataTableOpts = {
    ajax: {
      url: window.CRM.root + "/api/groups/" + window.CRM.currentGroup + "/members",
      dataSrc: "Person2group2roleP2g2rs"
    },
    "language": {
      "url": window.CRM.plugin.dataTable.language.url
    },
      responsive: true,
      "language": {
          "url": window.CRM.plugin.dataTable.language.url
      },
      "dom": window.CRM.plugin.dataTable.dom,
      "tableTools": {
          "sSwfPath": window.CRM.plugin.dataTable.tableTools.sSwfPath
      },
    columns: [
      {
        width: 'auto',
        title: i18next.t('Name'),
        data: 'PersonId',
        render: function (data, type, full, meta) {
          return ' &nbsp ' + full.Person.FirstName + " " + full.Person.LastName + '';
        }
      },
      {
        width: 'auto',
        title: i18next.t('Group Role'),
        data: 'RoleId',
        render: function (data, type, full, meta) {
          thisRole = $(window.CRM.groupRoles).filter(function (index, item) {
            return item.OptionId == data
          })[0];
          return i18next.t(thisRole.OptionName) + '<button class="changeMembership" data-personid=' + full.PersonId + '></button>';
        }
      },
      {
        width: 'auto',
        title: i18next.t('Address'),
        render: function (data, type, full, meta) {
          return full.Person.Address1 + " " + full.Person.Address2;
        }
      },
      {
        width: 'auto',
        title: i18next.t('City'),
        data: 'Person.City'
      },
      {
        width: 'auto',
        title: i18next.t('State'),
        data: 'Person.State'
      },
      {
        width: 'auto',
        title: i18next.t('Zip Code'),
        data: 'Person.Zip'
      },
      {
        width: 'auto',
        title: i18next.t('Cell Phone'),
        data: 'Person.CellPhone'
      },
      {
        width: 'auto',
        title: i18next.t('Email'),
        data: 'Person.Email'
      }
    ],
    "fnDrawCallback": function (oSettings) {
      $("#iTotalMembers").text(oSettings.aoData.length);
    },
    "createdRow": function (row, data, index) {
      $(row).addClass("groupRow");
    }
  };
  $.extend(DataTableOpts,window.CRM.plugin.DataTable);
  window.CRM.DataTableAPI = $("#membersTable").DataTable(DataTableOpts);

  $('#isGroupActive').change(function () {
    $.ajax({
      type: 'POST', // define the type of HTTP verb we want to use (POST for our form)
      url: window.CRM.root + '/api/groups/' + window.CRM.currentGroup + '/settings/active/' + $(this).prop('checked'),
      dataType: 'json', // what type of data do we expect back from the server
      encode: true
    });
  });

  $('#isGroupEmailExport').change(function () {
    $.ajax({
      type: 'POST', // define the type of HTTP verb we want to use (POST for our form)
      url: window.CRM.root + '/api/groups/' + window.CRM.currentGroup + '/settings/email/export/' + $(this).prop('checked'),
      dataType: 'json', // what type of data do we expect back from the server
      encode: true
    });
  });

  $(document).on('click', '.groupRow', function () {
    $(this).toggleClass('selected');
    var selectedRows = window.CRM.DataTableAPI.rows('.selected').data().length;
    $("#deleteSelectedRows").prop('disabled', !(selectedRows));
    $("#deleteSelectedRows").text(i18next.t("Remove")+" (" + selectedRows + ") "+i18next.t("Members from group"));
    $("#buttonDropdown").prop('disabled', !(selectedRows));
    $("#addSelectedToGroup").prop('disabled', !(selectedRows));
    $("#addSelectedToGroup").html(i18next.t("Add")+"  (" + selectedRows + ") "+i18next.t("Members to another group"));
    $("#addSelectedToCart").prop('disabled', !(selectedRows));
    $("#addSelectedToCart").html(i18next.t("Add")+"  (" + selectedRows + ") "+i18next.t("Members to cart"));
    $("#moveSelectedToGroup").prop('disabled', !(selectedRows));
	  $("#moveSelectedToGroup").html(i18next.t("Move")+"  (" + selectedRows + ") "+i18next.t("Members to another group"));
  });

}
<commit_msg>Fixed Null Address 2 display (#4230)<commit_after>$(document).ready(function () {

  $.ajax({
    method: "GET",
    url: window.CRM.root + "/api/groups/" + window.CRM.currentGroup + "/roles",
    dataType: "json"
  }).done(function (data) {
    window.CRM.groupRoles = data.ListOptions;
    $("#newRoleSelection").select2({
      data: $(window.CRM.groupRoles).map(function () {
        return {
          id: this.OptionId,
          text: i18next.t(this.OptionName)
        };
      })
    });
    initDataTable();
    //echo '<option value="' . $role['lst_OptionID'] . '">' . $role['lst_OptionName'] . '</option>';
  });

  $(".personSearch").select2({
    minimumInputLength: 2,
    language: window.CRM.shortLocale,
    ajax: {
      url: function (params) {
        return window.CRM.root + "/api/persons/search/" + params.term;
      },
      dataType: 'json',
      delay: 250,
      data: function (params) {
        return {
          q: params.term, // search term
          page: params.page
        };
      },
      processResults: function (rdata, page) {
        return {results: rdata};
      },
      cache: true
    }
  });

  $(".personSearch").on("select2:select", function (e) {
      window.CRM.groups.promptSelection({Type:window.CRM.groups.selectTypes.Role,GroupID:window.CRM.currentGroup},function(selection){
        window.CRM.groups.addPerson(window.CRM.currentGroup, e.params.data.objid,selection.RoleID).done(function (data) {
          $(".personSearch").val(null).trigger('change');
          window.CRM.DataTableAPI.ajax.reload();/* we reload the data no need to add the person inside the dataTable */
        });
      });
  });

  $("#deleteSelectedRows").click(function () {
    var deletedRows = window.CRM.DataTableAPI.rows('.selected').data()
    bootbox.confirm({
      message: i18next.t("Are you sure you want to remove the selected group members?") + " (" + deletedRows.length + ") ",
      buttons: {
        confirm: {
          label:  i18next.t('Yes'),
            className: 'btn-success'
        },
        cancel: {
          label:  i18next.t('No'),
          className: 'btn-danger'
        }
      },
      callback: function (result)
      {
        if (result)
        {
          $.each(deletedRows, function (index, value) {
            window.CRM.groups.removePerson(window.CRM.currentGroup,value.PersonId).done(
              function(){
                window.CRM.DataTableAPI.row(function (idx, data, node) {
                  if (data.PersonId == value.PersonId) {
                    return true;
                  }
                }).remove();
                window.CRM.DataTableAPI.rows().invalidate().draw(true);
            });
          });
        }
      }
    });

  });

  $("#addSelectedToCart").click(function () {
    if (window.CRM.DataTableAPI.rows('.selected').length > 0)
    {
      var selectedPersons = {
        "Persons" : $.map(window.CRM.DataTableAPI.rows('.selected').data(), function(val,i){
                      return val.PersonId;
                    })
      };
      window.CRM.cart.addPerson(selectedPersons.Persons);
    }

  });

  //copy membership
  $("#addSelectedToGroup").click(function () {
    window.CRM.groups.promptSelection({Type:window.CRM.groups.selectTypes.Group|window.CRM.groups.selectTypes.Role}, function(data){
      selectedRows = window.CRM.DataTableAPI.rows('.selected').data()
      $.each(selectedRows, function (index, value) {
        window.CRM.groups.addPerson(data.GroupID,value.PersonId,data.RoleID);
    });
    });
  });

  $("#moveSelectedToGroup").click(function () {
    window.CRM.groups.promptSelection({Type:window.CRM.groups.selectTypes.Group|window.CRM.groups.selectTypes.Role},function(data){
      selectedRows = window.CRM.DataTableAPI.rows('.selected').data()
      $.each(selectedRows, function (index, value) {
        console.log(data);
        window.CRM.groups.addPerson(data.GroupID,value.PersonId,data.RoleID);
        window.CRM.groups.removePerson(window.CRM.currentGroup,value.PersonId).done(
          function () {
            window.CRM.DataTableAPI.row(function (idx, data, node) {
              if (data.PersonId == value.PersonId) {
                return true;
              }
            }).remove();
            window.CRM.DataTableAPI.rows().invalidate().draw(true);
        });
      });
    });
  });

  $("#AddGroupMembersToCart").click(function () {
    window.CRM.cart.addGroup($(this).data("groupid"));
  })

  $(document).on("click", ".changeMembership", function (e) {
    var PersonID = $(e.currentTarget).data("personid");
    window.CRM.groups.promptSelection({Type:window.CRM.groups.selectTypes.Role,GroupID:window.CRM.currentGroup},function(selection){
      window.CRM.groups.addPerson(window.CRM.currentGroup,PersonID,selection.RoleID).done(function(){
        window.CRM.DataTableAPI.row(function (idx, data, node) {
        if (data.PersonId == PersonID) {
          data.RoleId = selection.RoleID;
          return true;
        }
      });
      window.CRM.DataTableAPI.rows().invalidate().draw(true);
      });
    });
    e.stopPropagation();
  });

});

function initDataTable() {
  var DataTableOpts = {
    ajax: {
      url: window.CRM.root + "/api/groups/" + window.CRM.currentGroup + "/members",
      dataSrc: "Person2group2roleP2g2rs"
    },
    "language": {
      "url": window.CRM.plugin.dataTable.language.url
    },
      responsive: true,
      "language": {
          "url": window.CRM.plugin.dataTable.language.url
      },
      "dom": window.CRM.plugin.dataTable.dom,
      "tableTools": {
          "sSwfPath": window.CRM.plugin.dataTable.tableTools.sSwfPath
      },
    columns: [
      {
        width: 'auto',
        title: i18next.t('Name'),
        data: 'PersonId',
        render: function (data, type, full, meta) {
          return ' &nbsp ' + full.Person.FirstName + " " + full.Person.LastName + '';
        }
      },
      {
        width: 'auto',
        title: i18next.t('Group Role'),
        data: 'RoleId',
        render: function (data, type, full, meta) {
          thisRole = $(window.CRM.groupRoles).filter(function (index, item) {
            return item.OptionId == data
          })[0];
          return i18next.t(thisRole.OptionName) + '<button class="changeMembership" data-personid=' + full.PersonId + '></button>';
        }
      },
      {
        width: 'auto',
        title: i18next.t('Address'),
        render: function (data, type, full, meta) {
          var address = full.Person.Address1;
          if (full.Person.Address2) {
              address += " " + full.Person.Address2;
          }
          return address;
        }
      },
      {
        width: 'auto',
        title: i18next.t('City'),
        data: 'Person.City'
      },
      {
        width: 'auto',
        title: i18next.t('State'),
        data: 'Person.State'
      },
      {
        width: 'auto',
        title: i18next.t('Zip Code'),
        data: 'Person.Zip'
      },
      {
        width: 'auto',
        title: i18next.t('Cell Phone'),
        data: 'Person.CellPhone'
      },
      {
        width: 'auto',
        title: i18next.t('Email'),
        data: 'Person.Email'
      }
    ],
    "fnDrawCallback": function (oSettings) {
      $("#iTotalMembers").text(oSettings.aoData.length);
    },
    "createdRow": function (row, data, index) {
      $(row).addClass("groupRow");
    }
  };
  $.extend(DataTableOpts,window.CRM.plugin.DataTable);
  window.CRM.DataTableAPI = $("#membersTable").DataTable(DataTableOpts);

  $('#isGroupActive').change(function () {
    $.ajax({
      type: 'POST', // define the type of HTTP verb we want to use (POST for our form)
      url: window.CRM.root + '/api/groups/' + window.CRM.currentGroup + '/settings/active/' + $(this).prop('checked'),
      dataType: 'json', // what type of data do we expect back from the server
      encode: true
    });
  });

  $('#isGroupEmailExport').change(function () {
    $.ajax({
      type: 'POST', // define the type of HTTP verb we want to use (POST for our form)
      url: window.CRM.root + '/api/groups/' + window.CRM.currentGroup + '/settings/email/export/' + $(this).prop('checked'),
      dataType: 'json', // what type of data do we expect back from the server
      encode: true
    });
  });

  $(document).on('click', '.groupRow', function () {
    $(this).toggleClass('selected');
    var selectedRows = window.CRM.DataTableAPI.rows('.selected').data().length;
    $("#deleteSelectedRows").prop('disabled', !(selectedRows));
    $("#deleteSelectedRows").text(i18next.t("Remove")+" (" + selectedRows + ") "+i18next.t("Members from group"));
    $("#buttonDropdown").prop('disabled', !(selectedRows));
    $("#addSelectedToGroup").prop('disabled', !(selectedRows));
    $("#addSelectedToGroup").html(i18next.t("Add")+"  (" + selectedRows + ") "+i18next.t("Members to another group"));
    $("#addSelectedToCart").prop('disabled', !(selectedRows));
    $("#addSelectedToCart").html(i18next.t("Add")+"  (" + selectedRows + ") "+i18next.t("Members to cart"));
    $("#moveSelectedToGroup").prop('disabled', !(selectedRows));
	  $("#moveSelectedToGroup").html(i18next.t("Move")+"  (" + selectedRows + ") "+i18next.t("Members to another group"));
  });

}
<|endoftext|>


<commit_before>var slimScroller = function (){
    'use strict';

    var targetPosition,horizontal,clock,elapsed,duration,startPosition,total,callback;
    var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame;

    var scroll = function (target, horizontal, durationTime, callbackFunction) {
        duration = durationTime || 500;
        horizontal = horizontal || false;
        callback = callbackFunction || false;
        startPosition = (horizontal) ? window.pageXOffset : window.pageYOffset;
        total = (horizontal) ? document.body.offsetWidth - window.innerWidth : document.body.offsetHeight - window.innerHeight;
        targetPosition = (parsePosition(target) > total) ? total : parsePosition(target);

        clock = Date.now();
        step();
    };
    var easeInOutCubic = function (time) {
        return (time < 0.5) ? 4 * time * time * time : (time - 1) * (2 * time - 2) * (2 * time - 2) + 1;
    };
    var calculatePosition = function () {
        return (elapsed > duration) ? targetPosition : startPosition + (targetPosition - startPosition) * easeInOutCubic(elapsed / duration);
    };
    var parsePosition = function (target){
        var parseNumber = parseInt(target);
        var parseElement = target.offsetLeft;
        var parseSelector;
        try{
            parseSelector = document.querySelector(target);
        }catch(e){}

        if (parseNumber) {
            // Target is pixel value
            return parseNumber;
        }else if(parseSelector){
            // Target is CSS-selector
            return (horizontal) ? document.querySelector(target).offsetLeft : document.querySelector(target).offsetTop;
        }else if(parseElement !== undefined){
            // Target is HTML-element
            return (horizontal) ? parseElement : target.offsetTop;
        }else{
            // Unknown type
            throw new Error('Unknown type as target');
        }
    };
    var step = function () {
        elapsed = Date.now() - clock;
        var stepPosition = calculatePosition();

        if (horizontal){
            window.scroll(stepPosition, 0);
        }else{
            window.scroll(0, stepPosition);
        }
        if (elapsed > duration) {
            if (callback) {
                callback([window.scrollX,window.scrollY]);
            }
        } else {
            requestAnimationFrame(step);
        }
    };
    var bind = function (time, callbackFunction) {
        var allAnchors = document.querySelectorAll('a');
        var i;
        for (i = 0; i < allAnchors.length; i++) {
            if (allAnchors[i].href == window.location.href.split('#')[0] + '#' + allAnchors[i].href.split('#')[1]) {
                allAnchors[i].addEventListener('click', function (event) {
                    event.preventDefault();
                    slimScroller.scroll('#'+event.target.href.split('#')[1], null, time, callbackFunction);
                    window.location.href = event.target.href;
                });
            }
        }
    };
    return {
        scroll: scroll,
        bind: bind
    };
}();<commit_msg>Returning<commit_after>var slimScroller = function (){
    'use strict';

    var targetPosition,horizontal,clock,elapsed,duration,startPosition,total,callback;
    var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame;

    var scroll = function (target, horizontal, durationTime, callbackFunction) {
        duration = durationTime || 500;
        horizontal = horizontal || false;
        callback = callbackFunction || false;
        startPosition = (horizontal) ? window.pageXOffset : window.pageYOffset;
        total = (horizontal) ? document.body.offsetWidth - window.innerWidth : document.body.offsetHeight - window.innerHeight;
        targetPosition = (parsePosition(target) > total) ? total : parsePosition(target);

        clock = Date.now();
        step();
    };
    var easeInOutCubic = function (time) {
        return (time < 0.5) ? 4 * time * time * time : (time - 1) * (2 * time - 2) * (2 * time - 2) + 1;
    };
    var calculatePosition = function () {
        return (elapsed > duration) ? targetPosition : startPosition + (targetPosition - startPosition) * easeInOutCubic(elapsed / duration);
    };
    var parsePosition = function (target){
        var parseNumber = parseInt(target);
        var parseElement = target.offsetLeft;
        var parseSelector;
        try{
            parseSelector = document.querySelector(target);
        }catch(e){}

        if (parseNumber) {
            // Target is pixel value
            return parseNumber;
        }else if(parseSelector){
            // Target is CSS-selector
            return (horizontal) ? document.querySelector(target).offsetLeft : document.querySelector(target).offsetTop;
        }else if(parseElement !== undefined){
            // Target is HTML-element
            return (horizontal) ? parseElement : target.offsetTop;
        }else{
            // Unknown type
            throw new Error('Unknown type as target');
        }
    };
    var step = function () {
        elapsed = Date.now() - clock;
        var stepPosition = calculatePosition();

        if (horizontal){
            window.scroll(stepPosition, 0);
        }else{
            window.scroll(0, stepPosition);
        }
        if (elapsed > duration) {
            if (callback) {
                callback([window.scrollX,window.scrollY]);
            }
        } else {
            requestAnimationFrame(step);
        }
    };
    var bind = function (time, callbackFunction) {
        var allAnchors = document.querySelectorAll('a');
        var i;
        for (i = 0; i < allAnchors.length; i++) {
            if (allAnchors[i].href == window.location.href.split('#')[0] + '#' + allAnchors[i].href.split('#')[1]) {
                allAnchors[i].addEventListener('click', function (event) {
                    event.preventDefault();
                    slimScroller.scroll('#'+event.target.href.split('#')[1], null, time, callbackFunction);
                    window.location.href = event.target.href;
                    return;
                });
            }
        }
    };
    return {
        scroll: scroll,
        bind: bind
    };
}();<|endoftext|>


<commit_before><commit_msg>Basic implementation<commit_after><|endoftext|>


<commit_before><commit_msg>cleanup<commit_after><|endoftext|>


<commit_before><commit_msg>Fix identation<commit_after><|endoftext|>


<commit_before>var profile = (function () {
  return {
    resourceTags: {
      test: function (filename, mid) {
        return filename.indexOf("test/") >= 0;
      },

      copyOnly: function (filename, mid) {
        return filename.indexOf("log4javascript_uncompressed.js") >= 0;
      },

      amd: function (filename, mid) {
        return false;
//        return filename.indexOf(".js") >= 0
//          && filename.indexOf("log4javascript_uncompressed.js") < 0
//          && filename.indexOf(".profile.js") < 0
//          && filename.indexOf("test/") < 0;
      }
    }
  };
})();
<commit_msg>profile.js for oddsAndEnds is improved now.<commit_after>var profile = (function () {
  function isTest(filename, mid) {
    return filename.indexOf("test/") >= 0;
  }

  function isCopyOnly(filename, mid) {
    return filename.indexOf("log4javascript_uncompressed.js") >= 0;
  }

  function isAmd(filename, mid) {
    return filename.indexOf(".js/") >= 0 && filename.indexOf(".profile.js") < 0;
  }

  return {
    resourceTags: {
      test: function (filename, mid) {
        return isTest(filename, mid);
      },

      copyOnly: function (filename, mid) {
        return isCopyOnly(filename, mid);
      },

      amd: function (filename, mid) {
        return isAmd(filename, mid);
      }
    }
  };
})();
<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import { validProps } from '../../../utils/ether';
import { StyledCheckableInput, StyledCheckableInputWrapper } from './checkable-input.style';
import FormField from '../form-field';
import HiddenCheckableInput from './hidden-checkable-input.component';
import guid from '../../../utils/helpers/guid';

class CheckableInput extends React.Component {
  constructor(props) {
    super(props);
    this.inputId = guid();
  }

  formFieldProps = (props) => {
    return {
      ...validProps(this, 'fieldHelpInline'),
      name: this.inputId,
      labelHelpIcon: 'info',
      reverse: !props.reverse
    };
  }

  inputProps = () => {
    const {
      children, fieldHelp, labelHelp, ...inputProps
    } = {
      ...validProps(this, ['disabled', 'onChange', 'type']),
      id: this.inputId
    };

    return inputProps;
  };

  render() {
    return (
      <StyledCheckableInputWrapper>
        <FormField { ...this.formFieldProps(this.props) }>
          <StyledCheckableInput>
            <HiddenCheckableInput { ...this.inputProps(this.props) } />
            {this.props.children}
          </StyledCheckableInput>
        </FormField>
      </StyledCheckableInputWrapper>
    );
  }
}

CheckableInput.propTypes = {
  /** Set the value of the CheckableInput */
  checked: PropTypes.bool,
  /** Used to set the visible aspect of the input (i.e. the checkbox sprite, input slider etc) */
  children: PropTypes.node,
  /** Toggles disabling of input */
  disabled: PropTypes.bool,
  /** Toggles error styles */
  error: PropTypes.bool,
  /** Displays fieldHelp inline with the CheckableInput */
  fieldHelpInline: PropTypes.bool,
  /** Sets percentage-based input width */
  inputWidth: PropTypes.number,
  /** Sets label alignment - accepted values: 'left' (default), 'right' */
  labelAlign: PropTypes.string,
  /** Sets percentage-based label width */
  labelWidth: PropTypes.number,
  /** Accepts a callback function which can be used to update parent state on change */
  onChange: PropTypes.func,
  /** Reverses label and CheckableInput display */
  reverse: PropTypes.bool
};

CheckableInput.defaultProps = {
  reverse: false
};

export default CheckableInput;
<commit_msg>Post-rebase fixes<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import { validProps } from '../../../utils/ether';
import { StyledCheckableInput, StyledCheckableInputWrapper } from './checkable-input.style';
import FormField from '../form-field';
import HiddenCheckableInput from './hidden-checkable-input.component';
import guid from '../../../utils/helpers/guid';

class CheckableInput extends React.Component {
  constructor(props) {
    super(props);
    this.inputId = guid();
  }

  formFieldProps = (props) => {
    return {
      ...validProps(this, 'fieldHelpInline'),
      name: this.inputId,
      labelHelpIcon: 'info',
      reverse: !props.reverse
    };
  }

  inputProps = () => {
    const {
      children, fieldHelp, labelHelp, ...inputProps
    } = {
      ...validProps(this, ['disabled', 'onChange', 'type']),
      id: this.inputId
    };

    return inputProps;
  };

  render() {
    return (
      <StyledCheckableInputWrapper>
        <FormField {...this.formFieldProps(this.props)}>
          <StyledCheckableInput>
            <HiddenCheckableInput {...this.inputProps(this.props)} />
            {this.props.children}
          </StyledCheckableInput>
        </FormField>
      </StyledCheckableInputWrapper>
    );
  }
}

CheckableInput.propTypes = {
  /** Set the value of the CheckableInput */
  checked: PropTypes.bool,
  /** Used to set the visible aspect of the input (i.e. the checkbox sprite, input slider etc) */
  children: PropTypes.node,
  /** Toggles disabling of input */
  disabled: PropTypes.bool,
  /** Toggles error styles */
  error: PropTypes.bool,
  /** Displays fieldHelp inline with the CheckableInput */
  fieldHelpInline: PropTypes.bool,
  /** Sets percentage-based input width */
  inputWidth: PropTypes.number,
  /** Sets label alignment - accepted values: 'left' (default), 'right' */
  labelAlign: PropTypes.string,
  /** Sets percentage-based label width */
  labelWidth: PropTypes.number,
  /** Accepts a callback function which can be used to update parent state on change */
  onChange: PropTypes.func,
  /** Reverses label and CheckableInput display */
  reverse: PropTypes.bool,
  /** Specifies input type, 'checkbox' or 'switch' */
  type: PropTypes.string.isRequired
};

CheckableInput.defaultProps = {
  reverse: false
};

export default CheckableInput;
<|endoftext|>


<commit_before>'use strict';
var React = require('react');
var _ = require('underscore');
var moment = require('moment');
var globals = require('../../globals');
var RestMixin = require('../../rest').RestMixin;
var vciFormHelper = require('./shared/form');
var CurationInterpretationForm = vciFormHelper.CurationInterpretationForm;
var CompleteSection = require('./shared/complete_section').CompleteSection;

var panel = require('../../../libs/bootstrap/panel');
var form = require('../../../libs/bootstrap/form');

var PanelGroup = panel.PanelGroup;
var Panel = panel.Panel;
var Form = form.Form;
var FormMixin = form.FormMixin;
var Input = form.Input;
var InputMixin = form.InputMixin;

// Display the curator data of the curation data
var CurationInterpretationFunctional = module.exports.CurationInterpretationFunctional = React.createClass({
    mixins: [RestMixin],

    propTypes: {
        data: React.PropTypes.object,
        interpretation: React.PropTypes.object,
        updateInterpretationObj: React.PropTypes.func,
        href_url: React.PropTypes.object
    },

    getInitialState: function() {
        return {
            clinvar_id: null,
            interpretation: this.props.interpretation
        };
    },

    componentWillReceiveProps: function(nextProps) {
        this.setState({interpretation: nextProps.interpretation});
    },

    render: function() {
        return (

                {this.state.interpretation ?
                    <CompleteSection interpretation={this.state.interpretation} tabName="functional" updateInterpretationObj={this.props.updateInterpretationObj} />
                : null}
                <PanelGroup accordion><Panel title="Does variant result in LOF?" panelBodyClassName="panel-wide-content" open>
                    {(this.props.data && this.state.interpretation) ?

                                <CurationInterpretationForm renderedFormContent={criteriaGroup1} criteria={['PM1']}
                                    evidenceData={null} evidenceDataUpdated={true}
                                    formDataUpdater={criteriaGroup1Update} variantUuid={this.props.data['@id']}
                                    interpretation={this.state.interpretation} updateInterpretationObj={this.props.updateInterpretationObj} />

                    : null}
                </Panel></PanelGroup>
                <PanelGroup accordion><Panel title="Is LOF known mechanism for disease of interest?" panelBodyClassName="panel-wide-content" open>
                    {(this.props.data && this.state.interpretation) ?

                                <CurationInterpretationForm renderedFormContent={criteriaGroup2} criteria={['BS3', 'PS3']}
                                    evidenceData={null} evidenceDataUpdated={true} criteriaCrossCheck={[['BS3', 'PS3']]}
                                    formDataUpdater={criteriaGroup2Update} variantUuid={this.props.data['@id']} formChangeHandler={criteriaGroup2Change}
                                    interpretation={this.state.interpretation} updateInterpretationObj={this.props.updateInterpretationObj} />

                    : null}
                </Panel></PanelGroup>

        );
    }
});

// code for rendering of this group of interpretation forms
var criteriaGroup1 = function() {
    let criteriaList1 = ['PM1'], // array of criteria code handled subgroup of this section
        hiddenList1 = [false]; // array indicating hidden status of explanation boxes for above list of criteria codes
    return (

            {vciFormHelper.evalFormSectionWrapper.call(this,
                vciFormHelper.evalFormNoteSectionWrapper.call(this, criteriaList1),
                vciFormHelper.evalFormDropdownSectionWrapper.call(this, criteriaList1),
                vciFormHelper.evalFormExplanationSectionWrapper.call(this, criteriaList1, hiddenList1, null, null),
                false
            )}

    );
};
// code for updating the form values of interpretation forms upon receiving
// existing interpretations and evaluations
var criteriaGroup1Update = function(nextProps) {
    vciFormHelper.updateEvalForm.call(this, nextProps, ['PM1'], null);
};

// code for rendering of this group of interpretation forms
var criteriaGroup2 = function() {
    let criteriaList1 = ['BS3', 'PS3'], // array of criteria code handled subgroup of this section
        hiddenList1 = [false, true]; // array indicating hidden status of explanation boxes for above list of criteria codes
    return (

            {vciFormHelper.evalFormSectionWrapper.call(this,
                vciFormHelper.evalFormNoteSectionWrapper.call(this, criteriaList1),
                vciFormHelper.evalFormDropdownSectionWrapper.call(this, criteriaList1),
                vciFormHelper.evalFormExplanationSectionWrapper.call(this, criteriaList1, hiddenList1, null, null),
                false
            )}

    );
};
// code for updating the form values of interpretation forms upon receiving
// existing interpretations and evaluations
var criteriaGroup2Update = function(nextProps) {
    vciFormHelper.updateEvalForm.call(this, nextProps, ['BS3', 'PS3'], null);
};
// code for handling logic within the form
var criteriaGroup2Change = function(ref, e) {
    // Both explanation boxes for both criteria of each group must be the same
    vciFormHelper.shareExplanation.call(this, ref, ['BS3', 'PS3']);
};
<commit_msg>Renamed 'functional' to 'experimental' for tabName props<commit_after>'use strict';
var React = require('react');
var _ = require('underscore');
var moment = require('moment');
var globals = require('../../globals');
var RestMixin = require('../../rest').RestMixin;
var vciFormHelper = require('./shared/form');
var CurationInterpretationForm = vciFormHelper.CurationInterpretationForm;
var CompleteSection = require('./shared/complete_section').CompleteSection;

var panel = require('../../../libs/bootstrap/panel');
var form = require('../../../libs/bootstrap/form');

var PanelGroup = panel.PanelGroup;
var Panel = panel.Panel;
var Form = form.Form;
var FormMixin = form.FormMixin;
var Input = form.Input;
var InputMixin = form.InputMixin;

// Display the curator data of the curation data
var CurationInterpretationFunctional = module.exports.CurationInterpretationFunctional = React.createClass({
    mixins: [RestMixin],

    propTypes: {
        data: React.PropTypes.object,
        interpretation: React.PropTypes.object,
        updateInterpretationObj: React.PropTypes.func,
        href_url: React.PropTypes.object
    },

    getInitialState: function() {
        return {
            clinvar_id: null,
            interpretation: this.props.interpretation
        };
    },

    componentWillReceiveProps: function(nextProps) {
        this.setState({interpretation: nextProps.interpretation});
    },

    render: function() {
        return (

                {this.state.interpretation ?
                    <CompleteSection interpretation={this.state.interpretation} tabName="experimental" updateInterpretationObj={this.props.updateInterpretationObj} />
                : null}
                <PanelGroup accordion><Panel title="Does variant result in LOF?" panelBodyClassName="panel-wide-content" open>
                    {(this.props.data && this.state.interpretation) ?

                                <CurationInterpretationForm renderedFormContent={criteriaGroup1} criteria={['PM1']}
                                    evidenceData={null} evidenceDataUpdated={true}
                                    formDataUpdater={criteriaGroup1Update} variantUuid={this.props.data['@id']}
                                    interpretation={this.state.interpretation} updateInterpretationObj={this.props.updateInterpretationObj} />

                    : null}
                </Panel></PanelGroup>
                <PanelGroup accordion><Panel title="Is LOF known mechanism for disease of interest?" panelBodyClassName="panel-wide-content" open>
                    {(this.props.data && this.state.interpretation) ?

                                <CurationInterpretationForm renderedFormContent={criteriaGroup2} criteria={['BS3', 'PS3']}
                                    evidenceData={null} evidenceDataUpdated={true} criteriaCrossCheck={[['BS3', 'PS3']]}
                                    formDataUpdater={criteriaGroup2Update} variantUuid={this.props.data['@id']} formChangeHandler={criteriaGroup2Change}
                                    interpretation={this.state.interpretation} updateInterpretationObj={this.props.updateInterpretationObj} />

                    : null}
                </Panel></PanelGroup>

        );
    }
});

// code for rendering of this group of interpretation forms
var criteriaGroup1 = function() {
    let criteriaList1 = ['PM1'], // array of criteria code handled subgroup of this section
        hiddenList1 = [false]; // array indicating hidden status of explanation boxes for above list of criteria codes
    return (

            {vciFormHelper.evalFormSectionWrapper.call(this,
                vciFormHelper.evalFormNoteSectionWrapper.call(this, criteriaList1),
                vciFormHelper.evalFormDropdownSectionWrapper.call(this, criteriaList1),
                vciFormHelper.evalFormExplanationSectionWrapper.call(this, criteriaList1, hiddenList1, null, null),
                false
            )}

    );
};
// code for updating the form values of interpretation forms upon receiving
// existing interpretations and evaluations
var criteriaGroup1Update = function(nextProps) {
    vciFormHelper.updateEvalForm.call(this, nextProps, ['PM1'], null);
};

// code for rendering of this group of interpretation forms
var criteriaGroup2 = function() {
    let criteriaList1 = ['BS3', 'PS3'], // array of criteria code handled subgroup of this section
        hiddenList1 = [false, true]; // array indicating hidden status of explanation boxes for above list of criteria codes
    return (

            {vciFormHelper.evalFormSectionWrapper.call(this,
                vciFormHelper.evalFormNoteSectionWrapper.call(this, criteriaList1),
                vciFormHelper.evalFormDropdownSectionWrapper.call(this, criteriaList1),
                vciFormHelper.evalFormExplanationSectionWrapper.call(this, criteriaList1, hiddenList1, null, null),
                false
            )}

    );
};
// code for updating the form values of interpretation forms upon receiving
// existing interpretations and evaluations
var criteriaGroup2Update = function(nextProps) {
    vciFormHelper.updateEvalForm.call(this, nextProps, ['BS3', 'PS3'], null);
};
// code for handling logic within the form
var criteriaGroup2Change = function(ref, e) {
    // Both explanation boxes for both criteria of each group must be the same
    vciFormHelper.shareExplanation.call(this, ref, ['BS3', 'PS3']);
};
<|endoftext|>


<commit_before><commit_msg>Added rioCommand.js that will replace rioCLI.js<commit_after><|endoftext|>


<commit_before><commit_msg>fix cwc payload persistence<commit_after><|endoftext|>


<commit_before>/*
This file is part of the Juju GUI, which lets users view and manage Juju
environments within a graphical interface (https://launchpad.net/juju-gui).
Copyright (C) 2017 Canonical Ltd.

This program is free software: you can redistribute it and/or modify it under
the terms of the GNU Affero General Public License version 3, as published by
the Free Software Foundation.

This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero
General Public License for more details.

You should have received a copy of the GNU Affero General Public License along
with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

'use strict';

const AccountPaymentCharges = React.createClass({
  displayName: 'AccountPaymentCharges',

  propTypes: {
    acl: React.PropTypes.object.isRequired,
    addNotification: React.PropTypes.func.isRequired,
    getCharges: React.PropTypes.func.isRequired,
    getReceipt: React.PropTypes.func.isRequired,
    username: React.PropTypes.string.isRequired
  },

  getInitialState: function() {
    this.xhrs = [];
    return {
      charges: null,
      loading: false,
      showPopup: ''
    };
  },

  componentWillMount: function() {
    this._getCharges();
  },

  componentWillUnmount: function() {
    this.xhrs.forEach((xhr) => {
      xhr && xhr.abort && xhr.abort();
    });
  },

  /**
    Show or hide the receipt popup.

    @param chargeId {String|Null} The charge to display.
  */
  _togglePopup: function(chargeId=null) {
    this.setState({showPopup: chargeId});
  },

  /**
    Get the payment details for the user.

    @method _getCharges
  */
  _getCharges: function() {
    this.setState({loading: true}, () => {
      const username = this.props.username;
      const xhr = this.props.getCharges(username, (error, response) => {
        if (error) {
          const message = 'Could not load the list of charges';
          this.props.addNotification({
            title: message,
            message: `${message}: ${error}`,
            level: 'error'
          });
          console.error(message, error);
          return;
        }
        this.setState({loading: false, charges: response});
      });
      this.xhrs.push(xhr);
    });
  },

  /**
    Generate the line items for a charge.

    @param lineItems {Array} The list of line items.
    @returns {Object} The markup for the line items.
  */
  _generateLineItems: function(lineItems) {
    if (!lineItems || !lineItems.length) {
      return (

          There are no items for this charge.

);
    }
    const items = lineItems.map((item, i) => {
      return (

            {item.name}

            {item.details}

            {item.usage}

            {item.price}

);
    });
    return (

Charges for:

              Name

              Details

              Usage

              Price

          {items}

);
  },

  /**
    Generate the list of charges.

    @returns {Object} The markup for the list of charges.
  */
  _generateCharges: function() {
    if (this.state.loading) {
      return <juju.components.Spinner />;
    }
    const charges = this.state.charges;
    if (!charges || !charges.length) {
      return (

          You do not have any charges.

);
    }
    let list = charges.map(charge => {
      return (
        <juju.components.ExpandingRow
          classes={{
            'twelve-col': true,
            'user-profile__list-row': true
          }}
          clickable={true}
          key={charge.id}>

              {charge.statementId}

              <juju.components.DateDisplay
                date={charge.for}
                relative={true} />

              {charge.price / 100} {charge.currency}

              {charge.vat / 100} {charge.currency}

              {(charge.price + charge.vat) / 100} {charge.currency}

              <juju.components.GenericButton
                action={this._togglePopup.bind(this, charge.id)}
                disabled={false}
                type="inline-neutral"
                title="Show receipt" />

            {this._generateLineItems(charge.lineItems)}

        </juju.components.ExpandingRow>);
    });
    return (

            ID

            Date

            Price

            VAT

            Total

        {list}

);
  },

  /**
    Generate the receipt popup.

    @returns {Object} The terms popup markup.
  */
  _generatePopup: function() {
    const charge = this.state.showPopup;
    if (!charge) {
      return null;
    }
    return (
      <juju.components.ReceiptPopup
        addNotification={this.props.addNotification}
        close={this._togglePopup}
        chargeId={charge}
        getReceipt={this.props.getReceipt} />);
  },

  render: function() {
    return (

            Charges

          {this._generateCharges()}
          {this._generatePopup()}

    );
  }

});

YUI.add('account-payment-charges', function() {
  juju.components.AccountPaymentCharges = AccountPaymentCharges;
}, '0.1.0', {
  requires: [
    'date-display',
    'expanding-row',
    'generic-button',
    'loading-spinner',
    'receipt-popup'
  ]
});
<commit_msg>Update AccountPaymentCharges to use es6 class.<commit_after>/*
This file is part of the Juju GUI, which lets users view and manage Juju
environments within a graphical interface (https://launchpad.net/juju-gui).
Copyright (C) 2017 Canonical Ltd.

This program is free software: you can redistribute it and/or modify it under
the terms of the GNU Affero General Public License version 3, as published by
the Free Software Foundation.

This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero
General Public License for more details.

You should have received a copy of the GNU Affero General Public License along
with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

'use strict';

class AccountPaymentCharges extends React.Component {
  constructor() {
    super();
    this.xhrs = [];
    this.state = {
      charges: null,
      loading: false,
      showPopup: ''
    };
  }

  componentWillMount() {
    this._getCharges();
  }

  componentWillUnmount() {
    this.xhrs.forEach((xhr) => {
      xhr && xhr.abort && xhr.abort();
    });
  }

  /**
    Show or hide the receipt popup.

    @param chargeId {String|Null} The charge to display.
  */
  _togglePopup(chargeId=null) {
    this.setState({showPopup: chargeId});
  }

  /**
    Get the payment details for the user.

    @method _getCharges
  */
  _getCharges() {
    this.setState({loading: true}, () => {
      const username = this.props.username;
      const xhr = this.props.getCharges(username, (error, response) => {
        if (error) {
          const message = 'Could not load the list of charges';
          this.props.addNotification({
            title: message,
            message: `${message}: ${error}`,
            level: 'error'
          });
          console.error(message, error);
          return;
        }
        this.setState({loading: false, charges: response});
      });
      this.xhrs.push(xhr);
    });
  }

  /**
    Generate the line items for a charge.

    @param lineItems {Array} The list of line items.
    @returns {Object} The markup for the line items.
  */
  _generateLineItems(lineItems) {
    if (!lineItems || !lineItems.length) {
      return (

          There are no items for this charge.

);
    }
    const items = lineItems.map((item, i) => {
      return (

            {item.name}

            {item.details}

            {item.usage}

            {item.price}

);
    });
    return (

Charges for:

              Name

              Details

              Usage

              Price

          {items}

);
  }

  /**
    Generate the list of charges.

    @returns {Object} The markup for the list of charges.
  */
  _generateCharges() {
    if (this.state.loading) {
      return <juju.components.Spinner />;
    }
    const charges = this.state.charges;
    if (!charges || !charges.length) {
      return (

          You do not have any charges.

);
    }
    let list = charges.map(charge => {
      return (
        <juju.components.ExpandingRow
          classes={{
            'twelve-col': true,
            'user-profile__list-row': true
          }}
          clickable={true}
          key={charge.id}>

              {charge.statementId}

              <juju.components.DateDisplay
                date={charge.for}
                relative={true} />

              {charge.price / 100} {charge.currency}

              {charge.vat / 100} {charge.currency}

              {(charge.price + charge.vat) / 100} {charge.currency}

              <juju.components.GenericButton
                action={this._togglePopup.bind(this, charge.id)}
                disabled={false}
                type="inline-neutral"
                title="Show receipt" />

            {this._generateLineItems(charge.lineItems)}

        </juju.components.ExpandingRow>);
    });
    return (

            ID

            Date

            Price

            VAT

            Total

        {list}

);
  }

  /**
    Generate the receipt popup.

    @returns {Object} The terms popup markup.
  */
  _generatePopup() {
    const charge = this.state.showPopup;
    if (!charge) {
      return null;
    }
    return (
      <juju.components.ReceiptPopup
        addNotification={this.props.addNotification}
        close={this._togglePopup}
        chargeId={charge}
        getReceipt={this.props.getReceipt} />);
  }

  render() {
    return (

            Charges

          {this._generateCharges()}
          {this._generatePopup()}

    );
  }
};

AccountPaymentCharges.propTypes = {
  acl: React.PropTypes.object.isRequired,
  addNotification: React.PropTypes.func.isRequired,
  getCharges: React.PropTypes.func.isRequired,
  getReceipt: React.PropTypes.func.isRequired,
  username: React.PropTypes.string.isRequired
};

YUI.add('account-payment-charges', function() {
  juju.components.AccountPaymentCharges = AccountPaymentCharges;
}, '0.1.0', {
  requires: [
    'date-display',
    'expanding-row',
    'generic-button',
    'loading-spinner',
    'receipt-popup'
  ]
});
<|endoftext|>