<commit_before>/* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*  http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************************
* This is a script to automate build a 2.3.0 through 3.1.0 snapshot of WP8
* Cordova for delivery to a product team to integrate. The manual process for
* this is described in our wiki. It is assumed that the platform/plugman/plugin
* repos have already been tagged with settings.NEW_TAG.
*/
var settings = require('./corimf-settings.js'),
	tests = require('./corimf-tests.js'),
	shelljs = require('shelljs'),
	tmp = require('temporary');

console.log('PLATFORM_REPO = ' + settings.PLATFORM_REPO);
console.log('REMOTE_ORIGIN = ' + settings.REMOTE_ORIGIN);
console.log('BRANCH = ' + settings.BRANCH);
console.log('NEW_TAG = ' + settings.NEW_TAG);
console.log();

console.log('Running Windows Phone 8 Cordova build of corimf:');
datetime = new Date();
console.log(' Date: ' + datetime.toDateString());
console.log(' Remote origin: ' + settings.REMOTE_ORIGIN);
console.log(' Branch: ' + settings.BRANCH);
console.log(' New Tag: ' + settings.NEW_TAG);
console.log();

tests.checkAboveGitRepo();
tests.checkMajorVersionNum();
tests.checkReposExist(settings.PLUGINS);

var repos = settings.PLUGINS.concat(settings.PLATFORM_REPO);
if (settings.PLUGMAN_REPO.length > 0) repos = repos.concat(settings.PLUGMAN_REPO);

console.log('Checking that we are on the expected ESR branch ' + settings.BRANCH + ' for platform and plugins...');
for (var i = 0; i < repos.length; i++) {
	console.log(repos[i] + ': ');
	shelljs.cd(repos[i]);
	tests.tmpFile = new tmp.File();
	var file2 = new tmp.File();
	tests.tmpFile.writeFileSync(shelljs.exec('git status --porcelain -b').output);
	file2.writeFileSync(shelljs.grep('^##', tests.tmpFile.path));
	if (shelljs.grep(settings.BRANCH + '$', file2.path).length == 0) {
		tests.reportStatus(shelljs.exec('git checkout ' + settings.BRANCH, {silent:true}).code == 0);
	}
	shelljs.cd('..');
	tests.tmpFile.unlink();
	file2.unlink();
}

//tests.pullAndFetchTags(repos);

console.log('Checking that the platform and plugins have the tag ' + settings.NEW_TAG + '...');
for (var i = 0; i < repos.length; i++) {
	console.log(repos[i] + ': ');
	shelljs.cd(repos[i]);
	//shelljs.exec('git fetch --tags', {silent:true});
	tests.reportStatus(shelljs.exec('git rev-parse ' + settings.NEW_TAG, {silent:true}).code == 0);
	shelljs.cd('..');
}

console.log('Checking that the platform and plugins are checked out at the tag ' + settings.NEW_TAG);
for (var i = 0; i < repos.length; i++) {
	console.log(repos[i] + ': ');
	shelljs.cd(repos[i]);
	var actual = shelljs.exec('git log -1 --format=oneline', {silent:true});
	tests.reportStatus(actual.code == 0);
	var desired = shelljs.exec('git rev-parse ' + settings.NEW_TAG, {silent:true});
	tests.reportStatus(desired.code == 0);
	tests.reportStatus(actual.output.split(' ')[0] == desired.output.trim());
	shelljs.cd('..');
}

var pathCorimf = shelljs.pwd();
var PROJECT_DIR = 'example-wp8-' + settings.NEW_TAG;
var SNAPSHOT_DIR = 'forgsa-wp8-' + settings.NEW_TAG;
var pathProject = pathCorimf + '\\' + PROJECT_DIR;
var pathSnapshot = pathCorimf + '\\' + SNAPSHOT_DIR;

console.log('Checking that project ' + PROJECT_DIR + ' does not exist yet...');
tests.reportStatus(!shelljs.test('-d', PROJECT_DIR));

console.log('Checking that snapshot dir ' + SNAPSHOT_DIR + ' does not exist yet...');
tests.reportStatus(!shelljs.test('-d', SNAPSHOT_DIR));

console.log('Creating a new Windows Phone 8 Project...');
tests.reportStatus(shelljs.exec(pathCorimf + '\\cordova-wp8\\wp8\\bin\\create.bat ' + PROJECT_DIR + ' com.example Example'), {silent:true});

if (settings.PLUGINS.length > 0) {
	console.log('Loading pre-reqs for plugman...');
	shelljs.cd(settings.PLUGMAN_REPO);
	if(shelljs.test('-d', 'node_modules')) {
		shelljs.rm('-r', 'node_modules')
	}
	tests.reportStatus(shelljs.exec('npm install', {silent:true}).code == 0);
	shelljs.cd('..');
}

console.log('Installing plugins into project...');
for (var i = 0; i < settings.PLUGINS.length; i++) {
	var pathPlugman = pathCorimf + '\\' + settings.PLUGMAN_REPO + '\\main.js';

	tests.reportStatus(shelljs.exec('node ' + pathPlugman + ' --debug install -platform wp8 -project ' + pathProject + ' -plugin ' + pathCorimf + '\\' + settings.PLUGINS[i], {silent:true}).code == 0);
}

console.log('Building project in Release:AnyCPU mode...');
// wp8 create script does not name sln and csproj files appropriately, so rename them
shelljs.exec('mv CordovaWP8AppProj.csproj example.csproj', {silent:true});
shelljs.exec('mv CordovaWP8Solution.sln example.sln', {silent:true});

// build the sample project in Visual Studio
tests.reportStatus(shelljs.exec('msbuild ' + PROJECT_DIR + '/example.sln /p:Configuration=Release', {silent:true}).code == 0);

console.log('Creating snapshot content in ' + SNAPSHOT_DIR);
shelljs.mkdir(SNAPSHOT_DIR);

// grab the www folder and add it to the snapshot. Should contain cordova.js and
// the plugins
tests.reportStatus(shelljs.exec('cp -r ' + PROJECT_DIR + '/www ' + SNAPSHOT_DIR, {silent:true}).code == 0);

// get the dll from Bin/Release
tests.reportStatus(shelljs.exec('cp ' + PROJECT_DIR + '/Bin/Release/com.example.dll ' + SNAPSHOT_DIR, {silent:true}).code == 0);

console.log('All building complete.');
// Note that the script does not yet zip the snapshot directory; this must be
// done manually for windows compatibility.

<commit_msg>Added IBM-MODIFICATIONS and check for PhoneGap var<commit_after>/* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*  http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************************
* This is a script to automate build a 2.3.0 through 3.1.0 snapshot of WP8
* Cordova for delivery to a product team to integrate. The manual process for
* this is described in our wiki. It is assumed that the platform/plugman/plugin
* repos have already been tagged with settings.NEW_TAG.
*/
var settings = require('./corimf-settings.js'),
	tests = require('./corimf-tests.js'),
	shelljs = require('shelljs'),
	tmp = require('temporary');

console.log('PLATFORM_REPO = ' + settings.PLATFORM_REPO);
console.log('REMOTE_ORIGIN = ' + settings.REMOTE_ORIGIN);
console.log('BRANCH = ' + settings.BRANCH);
console.log('NEW_TAG = ' + settings.NEW_TAG);
console.log();

console.log('Running Windows Phone 8 Cordova build of corimf:');
datetime = new Date();
console.log(' Date: ' + datetime.toDateString());
console.log(' Remote origin: ' + settings.REMOTE_ORIGIN);
console.log(' Branch: ' + settings.BRANCH);
console.log(' New Tag: ' + settings.NEW_TAG);
console.log();

tests.checkAboveGitRepo();
tests.checkMajorVersionNum();
tests.checkReposExist(settings.PLUGINS);

var repos = settings.PLUGINS.concat(settings.PLATFORM_REPO);
if (settings.PLUGMAN_REPO.length > 0) repos = repos.concat(settings.PLUGMAN_REPO);

console.log('Checking that we are on the expected ESR branch ' + settings.BRANCH + ' for platform and plugins...');
for (var i = 0; i < repos.length; i++) {
	console.log(repos[i] + ': ');
	shelljs.cd(repos[i]);
	tests.tmpFile = new tmp.File();
	var file2 = new tmp.File();
	tests.tmpFile.writeFileSync(shelljs.exec('git status --porcelain -b').output);
	file2.writeFileSync(shelljs.grep('^##', tests.tmpFile.path));
	if (shelljs.grep(settings.BRANCH + '$', file2.path).length == 0) {
		tests.reportStatus(shelljs.exec('git checkout ' + settings.BRANCH, {silent:true}).code == 0);
	}
	shelljs.cd('..');
	tests.tmpFile.unlink();
	file2.unlink();
}

tests.pullAndFetchTags(repos);

console.log('Checking that the platform and plugins have the tag ' + settings.NEW_TAG + '...');
for (var i = 0; i < repos.length; i++) {
	console.log(repos[i] + ': ');
	shelljs.cd(repos[i]);
	tests.reportStatus(shelljs.exec('git rev-parse ' + settings.NEW_TAG, {silent:true}).code == 0);
	shelljs.cd('..');
}

console.log('Checking that the platform and plugins are checked out at the tag ' + settings.NEW_TAG);
for (var i = 0; i < repos.length; i++) {
	console.log(repos[i] + ': ');
	shelljs.cd(repos[i]);
	var actual = shelljs.exec('git log -1 --format=oneline', {silent:true});
	tests.reportStatus(actual.code == 0);
	var desired = shelljs.exec('git rev-parse ' + settings.NEW_TAG, {silent:true});
	tests.reportStatus(desired.code == 0);
	tests.reportStatus(actual.output.split(' ')[0] == desired.output.trim());
	shelljs.cd('..');
}

var pathCorimf = shelljs.pwd();
var PROJECT_DIR = 'example-wp8-' + settings.NEW_TAG;
var SNAPSHOT_DIR = 'forgsa-wp8-' + settings.NEW_TAG;
var pathProject = pathCorimf + '\\' + PROJECT_DIR;
var pathSnapshot = pathCorimf + '\\' + SNAPSHOT_DIR;

console.log('Checking that project ' + PROJECT_DIR + ' does not exist yet...');
tests.reportStatus(!shelljs.test('-d', PROJECT_DIR));

console.log('Checking that snapshot dir ' + SNAPSHOT_DIR + ' does not exist yet...');
tests.reportStatus(!shelljs.test('-d', SNAPSHOT_DIR));

console.log('Creating a new Windows Phone 8 Project...');
tests.reportStatus(shelljs.exec(pathCorimf + '\\cordova-wp8\\wp8\\bin\\create.bat ' + PROJECT_DIR + ' com.example Example'), {silent:true});

if (settings.PLUGINS.length > 0) {
	console.log('Loading pre-reqs for plugman...');
	shelljs.cd(settings.PLUGMAN_REPO);
	if(shelljs.test('-d', 'node_modules')) {
		shelljs.rm('-r', 'node_modules')
	}
	tests.reportStatus(shelljs.exec('npm install', {silent:true}).code == 0);
	shelljs.cd('..');
}

console.log('Installing plugins into project...');
for (var i = 0; i < settings.PLUGINS.length; i++) {
	var pathPlugman = pathCorimf + '\\' + settings.PLUGMAN_REPO + '\\main.js';

	tests.reportStatus(shelljs.exec('node ' + pathPlugman + ' --debug install -platform wp8 -project ' + pathProject + ' -plugin ' + pathCorimf + '\\' + settings.PLUGINS[i], {silent:true}).code == 0);
}

console.log('Building project in Release:AnyCPU mode...');
// wp8 create script does not name sln and csproj files appropriately, so rename them
shelljs.exec('mv CordovaWP8AppProj.csproj example.csproj', {silent:true});
shelljs.exec('mv CordovaWP8Solution.sln example.sln', {silent:true});

// build the sample project in Visual Studio
tests.reportStatus(shelljs.exec('msbuild ' + PROJECT_DIR + '/example.sln /p:Configuration=Release', {silent:true}).code == 0);

console.log('Creating snapshot content in ' + SNAPSHOT_DIR);
shelljs.mkdir(SNAPSHOT_DIR);

// grab the www folder and add it to the snapshot. Should contain cordova.js and
// the plugins
tests.reportStatus(shelljs.exec('cp -r ' + PROJECT_DIR + '/www ' + SNAPSHOT_DIR, {silent:true}).code == 0);

// get the dll from Bin/Release
tests.reportStatus(shelljs.exec('cp ' + PROJECT_DIR + '/Bin/Release/com.example.dll ' + SNAPSHOT_DIR, {silent:true}).code == 0);

// get the IBM-MODIFICATIONS.txt
shelljs.mkdir(SNAPSHOT_DIR + '/modifications');
for (var i = 0; i < repos.length; i++) {
	if (shelljs.test('-f', repos[i] + '/IBM-MODIFICATIONS.txt')) {
		tests.reportStatus(shelljs.exec('cp ' + repos[i] + '/IBM-MODIFICATIONS.txt ' + SNAPSHOT_DIR + '/modifications/' + repos[i] + '.IBM-MODIFICATIONS.txt'), {silent:true});
	}
}

console.log('Checking cordova.js file for PhoneGap variable...');
// the following line does not exist in the git repo, but must be included in the copy of
// cordova.js given to WL. Produce a reminder if this line is not present.
if (shelljs.grep('PhoneGap', SNAPSHOT_DIR + '/www/cordova.js').length == 0) {
	console.log('*************************************************************');
	console.log('NOTE: Please append the following line:');
	console.log('var PhoneGap = cordova;');
	console.log('to the cordova js file before uploading to gsa. Do not commit this change to the repo.');
	console.log('*************************************************************');
}

console.log('All building complete.');
// Note that the script does not yet zip the snapshot directory; this must be
// done manually for windows compatibility.<|endoftext|>


<commit_before>/** @babel */

import {GitRepositoryAsync} from 'atom'
import path from 'path'
import fs from 'fs-plus'
import {Point} from 'atom'
import GitService from '../lib/git-service'
import CommitBoxViewModel from '../lib/commit-box-view-model'
import {SummaryPreferredLength} from '../lib/commit-box-view-model'
import {copyRepository} from './helpers'
import {waitsForPromise, it} from './async-spec-helpers'

describe('CommitBoxViewModel', () => {
  let viewModel
  let gitService
  let repoPath

  beforeEach(() => {
    repoPath = copyRepository()

    gitService = new GitService(GitRepositoryAsync.open(repoPath))

    viewModel = new CommitBoxViewModel(gitService)
    waitsForPromise(() => viewModel.update())
  })

  describe('::getBranchName', () => {
    it('returns the current branch', () => {
      expect(viewModel.getBranchName()).toBe('master')
    })
  })

  describe('::commit', () => {
    it('emits a user change event', async () => {
      let changeHandler = jasmine.createSpy()
      viewModel.onDidUserChange(changeHandler)

      await viewModel.commit('hey there')

      expect(changeHandler).toHaveBeenCalled()
    })

    it('commits the staged changes', async () => {
      const newFileName = 'new-file.txt'
      const newFile = path.join(repoPath, newFileName)
      fs.writeFileSync(newFile, 'my fav file')

      let statuses = await gitService.getStatuses()
      expect(statuses[newFileName]).not.toBeUndefined()

      await gitService.stagePath(newFileName)
      await viewModel.commit('hey there')

      statuses = await gitService.getStatuses()
      expect(statuses[newFileName]).toBeUndefined()
    })
  })

  describe('.calculateRemainingCharacters', () => {
    const summary = 'hey kids!'
    const description = 'Version control is good and good for you!'
    const msg = `${summary}\n\n${description}`

    describe('when the summary is being edited', () => {
      it('counts down from 50', () => {
        const remaining = viewModel.calculateRemainingCharacters(msg, new Point(0, 0))
        expect(remaining).toBe(SummaryPreferredLength - summary.length)
      })
    })

    describe('when the description is being edited', () => {
      it('is infinite', () => {
        const msg = 'hey kids!\n\nVersion control is good and good for you!'
        const remaining = viewModel.calculateRemainingCharacters(msg, new Point(3, 0))
        expect(isFinite(remaining)).toBe(false)
      })
    })
  })
})
<commit_msg>Update the spec.<commit_after>/** @babel */

import {GitRepositoryAsync} from 'atom'
import path from 'path'
import fs from 'fs-plus'
import {Point} from 'atom'
import GitService from '../lib/git-service'
import CommitBoxViewModel from '../lib/commit-box-view-model'
import {SummaryPreferredLength} from '../lib/commit-box-view-model'
import {copyRepository} from './helpers'
import {waitsForPromise, it} from './async-spec-helpers'

describe('CommitBoxViewModel', () => {
  let viewModel
  let gitService
  let repoPath

  beforeEach(() => {
    repoPath = copyRepository()

    gitService = new GitService(GitRepositoryAsync.open(repoPath))

    viewModel = new CommitBoxViewModel(gitService)
    waitsForPromise(() => viewModel.update())
  })

  describe('::getBranchName', () => {
    it('returns the current branch', () => {
      expect(viewModel.getBranchName()).toBe('master')
    })
  })

  describe('::commit', () => {
    it('emits a commit event', async () => {
      let commitHandler = jasmine.createSpy()
      viewModel.onDidCommit(commitHandler)

      await viewModel.commit('hey there')

      expect(commitHandler).toHaveBeenCalled()
    })

    it('commits the staged changes', async () => {
      const newFileName = 'new-file.txt'
      const newFile = path.join(repoPath, newFileName)
      fs.writeFileSync(newFile, 'my fav file')

      let statuses = await gitService.getStatuses()
      expect(statuses[newFileName]).not.toBeUndefined()

      await gitService.stagePath(newFileName)
      await viewModel.commit('hey there')

      statuses = await gitService.getStatuses()
      expect(statuses[newFileName]).toBeUndefined()
    })
  })

  describe('.calculateRemainingCharacters', () => {
    const summary = 'hey kids!'
    const description = 'Version control is good and good for you!'
    const msg = `${summary}\n\n${description}`

    describe('when the summary is being edited', () => {
      it('counts down from 50', () => {
        const remaining = viewModel.calculateRemainingCharacters(msg, new Point(0, 0))
        expect(remaining).toBe(SummaryPreferredLength - summary.length)
      })
    })

    describe('when the description is being edited', () => {
      it('is infinite', () => {
        const msg = 'hey kids!\n\nVersion control is good and good for you!'
        const remaining = viewModel.calculateRemainingCharacters(msg, new Point(3, 0))
        expect(isFinite(remaining)).toBe(false)
      })
    })
  })
})
<|endoftext|>


<commit_before>/*  ============================================================================

 Copyright (C) 2006-2016 Talend Inc. - www.talend.com

 This source code is available under agreement available at
 https://github.com/Talend/data-prep/blob/master/LICENSE

 You should have received a copy of the agreement
 along with this program; if not, write to Talend SA
 9 rue Pages 92150 Suresnes, France

 ============================================================================*/

const AGGREGATIONS = ['SUM', 'MAX', 'MIN', 'AVERAGE'];
const LINE_COUNT = 'LINE_COUNT';

/**
 * @ngdoc controller
 * @name data-prep.column-profile-options.controller:ColumnProfileOptionsCtrl
 * @description Column profile header controller
 */
export default class ColumnProfileOptionsCtrl {
    constructor($translate) {
        'ngInject';

        this.$translate = $translate;
        this.aggregations = AGGREGATIONS;
    }

    $onInit() {
        this._updateNumericColumns();
        this._updateCurrentDescription();
        this._updateCurrentShortDescription();
        this.resetSelected();
    }

    $onChanges(changes) {
        if(changes.numericColumns || changes.group) {
            this._updateNumericColumns();
        }

        if(changes.column || changes.aggregation || changes.group) {
            this._updateCurrentDescription();
            this._updateCurrentShortDescription();
        }
    }

    /**
     * @ngdoc method
     * @name selectColumn
     * @methodOf data-prep.column-profile-options.controller:ColumnProfileOptionsCtrl
     * @description Select a column for aggregation callback.
     * It refresh the description and init aggregation type.
     */
    selectColumn() {
        this.selected.aggregation = this.selected.column ?
            (this.aggregation || AGGREGATIONS[0]) :
            null;
        this.updateSelectedDescription();
    }

    /**
     * @ngdoc method
     * @name resetSelected
     * @methodOf data-prep.column-profile-options.controller:ColumnProfileOptionsCtrl
     * @description Reset selected infos with the initial values.
     * This updates the description too.
     */
    resetSelected() {
        this.selected = {
            column: this.column,
            aggregation: this.aggregation,
        };
        this.updateSelectedDescription();
    }

    /**
     * @ngdoc method
     * @name changeAggregation
     * @methodOf data-prep.column-profile-options.controller:ColumnProfileOptionsCtrl
     * @description Perform aggregation change. This is triggered on fom validation.
     */
    changeAggregation() {
        const config = {
            column: this.selected.column,
            aggregation: this.selected.aggregation,
        };

        if (config.column === this.column && config.aggregation === this.aggregation) {
            return;
        }
        this.onAggregationChange(config);
    }

    /**
     * @ngdoc method
     * @name removeAggregation
     * @methodOf data-prep.column-profile-options.controller:ColumnProfileOptionsCtrl
     * @description Remove aggregation.
     */
    removeAggregation() {
        this.selected.column = undefined;
        this.selected.aggregation = undefined;
        this.changeAggregation();
    }

    /**
     * @ngdoc method
     * @name updateSelectedDescription
     * @methodOf data-prep.column-profile-options.controller:ColumnProfileOptionsCtrl
     * @description Update the description of selected aggregation values
     */
    updateSelectedDescription() {
        if (!this.selected.column) {
            this.selected.description = null;
        }
        else {
            const selectedOptions = {
                aggreg: this.$translate.instant(this.selected.aggregation),
                col: this.selected.column.name,
                group: this.group.name,
            };
            this.selected.description = this.$translate.instant('AGGREGATION_DETAILS', selectedOptions);
        }
    }

    /**
     * @ngdoc method
     * @name _updateCurrentDescription
     * @methodOf data-prep.column-profile-options.controller:ColumnProfileOptionsCtrl
     * @description Update the description of initial aggregation values (not the selected ones)
     */
    _updateCurrentDescription() {
        if (!this.column) {
            this.description = null;
        }
        else {
            const currentOptions = {
                aggreg: this.$translate.instant(this.aggregation),
                col: this.column.name,
                group: this.group.name,
            };

            this.$translate('AGGREGATION_DETAILS', currentOptions)
                .then((desc) => { this.description = desc });
        }
    }

    /**
     * @ngdoc method
     * @name _updateCurrentShortDescription
     * @methodOf data-prep.column-profile-options.controller:ColumnProfileOptionsCtrl
     * @description Update the short description of initial aggregation values
     */
    _updateCurrentShortDescription() {
        if(this.aggregation) {
            this.$translate(this.aggregation)
                .then((aggreg) => { this.shortDescription =  `${aggreg} ${this.column.name}` })
        }
        else {
            this.shortDescription =  this.$translate.instant(LINE_COUNT);
        }
    }

    _updateNumericColumns() {
        this.filteredNumericColumns = this.group ?
            this.numericColumns.filter((col) => col.id !== this.group.id) :
            this.numericColumns;
    }
}
<commit_msg>TDP-930: update ng-doc<commit_after>/*  ============================================================================

 Copyright (C) 2006-2016 Talend Inc. - www.talend.com

 This source code is available under agreement available at
 https://github.com/Talend/data-prep/blob/master/LICENSE

 You should have received a copy of the agreement
 along with this program; if not, write to Talend SA
 9 rue Pages 92150 Suresnes, France

 ============================================================================*/

const AGGREGATIONS = ['SUM', 'MAX', 'MIN', 'AVERAGE'];
const LINE_COUNT = 'LINE_COUNT';

/**
 * @ngdoc controller
 * @name data-prep.column-profile-options.controller:ColumnProfileOptionsCtrl
 * @description Column profile header controller
 */
export default class ColumnProfileOptionsCtrl {
    constructor($translate) {
        'ngInject';

        this.$translate = $translate;
        this.aggregations = AGGREGATIONS;
    }

    $onInit() {
        this._updateNumericColumns();
        this._updateCurrentDescription();
        this._updateCurrentShortDescription();
        this.resetSelected();
    }

    $onChanges(changes) {
        if(changes.numericColumns || changes.group) {
            this._updateNumericColumns();
        }

        if(changes.column || changes.aggregation || changes.group) {
            this._updateCurrentDescription();
            this._updateCurrentShortDescription();
        }
    }

    /**
     * @ngdoc method
     * @name selectColumn
     * @methodOf data-prep.column-profile-options.controller:ColumnProfileOptionsCtrl
     * @description Select a column for aggregation callback.
     * It refresh the description and init aggregation type.
     */
    selectColumn() {
        this.selected.aggregation = this.selected.column ?
            (this.aggregation || AGGREGATIONS[0]) :
            null;
        this.updateSelectedDescription();
    }

    /**
     * @ngdoc method
     * @name resetSelected
     * @methodOf data-prep.column-profile-options.controller:ColumnProfileOptionsCtrl
     * @description Reset selected infos with the initial values.
     * This updates the description too.
     */
    resetSelected() {
        this.selected = {
            column: this.column,
            aggregation: this.aggregation,
        };
        this.updateSelectedDescription();
    }

    /**
     * @ngdoc method
     * @name changeAggregation
     * @methodOf data-prep.column-profile-options.controller:ColumnProfileOptionsCtrl
     * @description Perform aggregation change. This is triggered on fom validation.
     */
    changeAggregation() {
        const config = {
            column: this.selected.column,
            aggregation: this.selected.aggregation,
        };

        if (config.column === this.column && config.aggregation === this.aggregation) {
            return;
        }
        this.onAggregationChange(config);
    }

    /**
     * @ngdoc method
     * @name removeAggregation
     * @methodOf data-prep.column-profile-options.controller:ColumnProfileOptionsCtrl
     * @description Remove aggregation.
     */
    removeAggregation() {
        this.selected.column = undefined;
        this.selected.aggregation = undefined;
        this.changeAggregation();
    }

    /**
     * @ngdoc method
     * @name updateSelectedDescription
     * @methodOf data-prep.column-profile-options.controller:ColumnProfileOptionsCtrl
     * @description Update the description of selected aggregation values
     */
    updateSelectedDescription() {
        if (!this.selected.column) {
            this.selected.description = null;
        }
        else {
            const selectedOptions = {
                aggreg: this.$translate.instant(this.selected.aggregation),
                col: this.selected.column.name,
                group: this.group.name,
            };
            this.selected.description = this.$translate.instant('AGGREGATION_DETAILS', selectedOptions);
        }
    }

    /**
     * @ngdoc method
     * @name _updateCurrentDescription
     * @methodOf data-prep.column-profile-options.controller:ColumnProfileOptionsCtrl
     * @description Update the description of initial aggregation values (not the selected ones)
     */
    _updateCurrentDescription() {
        if (!this.column) {
            this.description = null;
        }
        else {
            const currentOptions = {
                aggreg: this.$translate.instant(this.aggregation),
                col: this.column.name,
                group: this.group.name,
            };

            this.$translate('AGGREGATION_DETAILS', currentOptions)
                .then((desc) => { this.description = desc });
        }
    }

    /**
     * @ngdoc method
     * @name _updateCurrentShortDescription
     * @methodOf data-prep.column-profile-options.controller:ColumnProfileOptionsCtrl
     * @description Update the short description of initial aggregation values
     */
    _updateCurrentShortDescription() {
        if(this.aggregation) {
            this.$translate(this.aggregation)
                .then((aggreg) => { this.shortDescription =  `${aggreg} ${this.column.name}` })
        }
        else {
            this.shortDescription =  this.$translate.instant(LINE_COUNT);
        }
    }

    /**
     * @ngdoc method
     * @name _updateNumericColumns
     * @methodOf data-prep.column-profile-options.controller:ColumnProfileOptionsCtrl
     * @description exclude grouping column from filteredNumericColumns
     */
    _updateNumericColumns() {
        this.filteredNumericColumns = this.group ?
            this.numericColumns.filter((col) => col.id !== this.group.id) :
            this.numericColumns;
    }
}
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
 *
 * WSO2 Inc. licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

var UUFClient = {};

(function (UUFClient) {

    var UUF_ZONE_COMMENT_PREFIX = "[UUF-ZONE]";

    /**
     * Zones in the current DOM.
     * @type {{string: {start: Object, end: Object}}}
     */

    var zonesMap;

    // Check whether the JQuery is available.
    if (!window.jQuery) {
        throw new UUFClientException("JQuery is required for UUFClient.");
    }
    // Check whether the Handlebars is available.
    if (!window.Handlebars) {
        throw new UUFClientException("Handlebars JS is required for UUFClient.");
    }

    /**
     * Indicates an error in UUFClient.
     *
     * @param {string} message message of this error
     * @param {Object} [cause] cause of this error
     * @param {number} [statusCode] status code of this error
     * @constructor
     */
    function UUFClientException(message, cause, statusCode) {
        this.message = message;
        this.cause = cause;
        this.statusCode = statusCode;
    }

    /**
     * Populates a zones map by scanning HTML comments in the DOM.
     */
    function populateZonesMap() {
        zonesMap = {};
        $("*").contents().filter(function () {
            // For HTML comments, node type will be 8.
            return this.nodeType === 8;
        }).each(function (i, node) {
            var commentText = node.nodeValue;
            if (!commentText.startsWith(UUF_ZONE_COMMENT_PREFIX)) {
                return;
            }
            var zone;
            try {
                zone = JSON.parse(commentText.substring(UUF_ZONE_COMMENT_PREFIX.length));
            } catch (e) {
                throw new UUFClientException("Cannot parse UUFClient zone comment '" + commentText
                                             + "' as a JSON.");
            }
            if (!zone.name) {
                throw new UUFClientException("Cannot find field 'name' in the UUFClient zone comment '"
                                             + commentText + "'.");
            }
            if (!zone.position) {
                throw new UUFClientException("Cannot find field 'position' in the UUFClient zone comment '"
                                             + commentText + "'.");
            }

            if (!zonesMap[zone.name]) {
                zonesMap[zone.name] = {};
            }
            zonesMap[zone.name][zone.position] = node;
        });
    }

    /**
     * Pushes the content to the specified zone according to the given mode.
     *
     * @param {string} content content to push
     * @param {string} zone name of the zone to push
     * @param {string} mode mode to use. Mode can be either PREPEND, APPEND or OVERWRITE. PREPEND will
     *     add the fragment to the beginning of the existing content of that zone. Mode can be "PREPEND" (put the
     *     pushing content before the existing content), "APPEND" (put the pushing content after the existing content)
     *     or "OVERWRITE" (replace the existing content with the pushing content)
     */
    function pushContent(content, zone, mode) {
        if (!content) {
            console.warn("Content is empty.");
            return;
        }

        switch (mode) {
            case "OVERWRITE":
                var innerContents = $(zone.start).parent().contents();
                innerContents.slice(innerContents.index($(zone.start)) + 1, innerContents.index($(zone.end))).remove();
                $(zone.start).after(content);
                break;
            case "APPEND":
                $(zone.end).before(content);
                break;
            case "PREPEND":
                $(zone.start).after(content);
                break;
            default:
                throw new UUFClientException("Mode '" + mode + "' is not supported.");
        }
    }

    /**
     * Check the zoneName and mode variables for null or empty and check for the callback functions.
     *
     * @param {string} zoneName
     * @param {string} mode
     * @param {?Object} callbacks
     */
    function validate(zoneName, mode, callbacks) {
        if (!zoneName) {
            throw new UUFClientException("Zone name cannot be null or empty.");
        }
        if (!mode) {
            throw new UUFClientException("Mode cannot be null or empty.");
        }
        if (!callbacks["onSuccess"]) {
            throw new UUFClientException("'onSuccess' callback function not found.");
        }
        if (!callbacks["onFailure"]) {
            throw new UUFClientException("'onFailure' callback function not found.");
        }
    }

    /**
     * Renders the specified fragment and pushes to the given zone according to the given mode.
     *
     * @param {string} fragmentFullyQualifiedName fully qualified name of the fragment
     * @param {?Object} templateFillingObject data for the template
     * @param {string} zoneName name of the zone to push
     * @param {string} mode mode to use
     * @param {Function} callbacks callback function
     */
    UUFClient.renderFragment = function (fragmentFullyQualifiedName, templateFillingObject, zoneName, mode, callbacks) {
        if (!fragmentFullyQualifiedName) {
            throw new UUFClientException("Fragment name cannot be null or empty.");
        }
        validate(zoneName, mode, callbacks);

        if (!zonesMap) {
            populateZonesMap();
        }
        var zone = zonesMap[zoneName];
        if (!zone) {
            throw new UUFClientException("Zone '" + zoneName + "' does not exists in current DOM.");
        }

        var url = contextPath + "/fragments/" + fragmentFullyQualifiedName;
        $.ajax({
                   url: url,
                   type: "POST",
                   contentType: 'application/json',
                   data: JSON.stringify(templateFillingObject),
                   success: function (data, textStatus, jqXHR) {
                       var error = pushContent(data, zone, mode);
                       if (error) {
                           callbacks["onFailure"](error);
                           return;
                       }
                       callbacks["onSuccess"](data);
                   },
                   error: function (jqXHR, textStatus, errorThrown) {
                       var msg = "Error occurred while retrieving fragment '" + fragmentFullyQualifiedName
                                 + "' from '" + url + "'.";
                       callbacks["onFailure"](msg, errorThrown);
                   }
               });
    };

    /**
     * Renders the specified embedded Handlebars template and pushes to the given zone according to the given mode.
     *
     * @param {string} templateId id of the handlebars template
     * @param {?Object} templateFillingObject data for the template
     * @param {string} zoneName name of the zone to push
     * @param {string} mode mode to use
     * @param {Function} callbacks callback function
     */
    UUFClient.renderTemplate = function (templateId, templateFillingObject, zoneName, mode, callbacks) {
        if (!templateId) {
            throw new UUFClientException("Template name cannot be null or empty.");
        }
        validate(zoneName, mode, callbacks);

        var source = $("#" + templateId).html();
        if (source) {
            UUFClient.renderTemplateString(source, templateFillingObject, zoneName, mode, callbacks);
        } else {
            throw new UUFClientException("Template '" + templateId + "' not found");
        }
    };

    /**
     * Retrieves the Handlebars template from the specified URL and renders and pushes it to the given zone according
     * to the given mode.
     *
     * @param {string} templateUrl url of the template
     * @param {?Object} templateFillingObject data for the template
     * @param {string} zoneName name of the zone to push
     * @param {string} mode mode to use
     * @param {Function} callbacks callback function
     */
    UUFClient.renderTemplateUrl = function (templateUrl, templateFillingObject, zoneName, mode, callbacks) {
        if (!templateUrl) {
            throw new UUFClientException("Template url cannot be null or empty.");
        }
        validate(zoneName, mode, callbacks);

        $.ajax({
                   url: templateUrl,
                   type: "GET",
                   success: function (data, textStatus, jqXHR) {
                       var contentType = jqXHR.getResponseHeader("content-type") || "";
                       if (contentType.indexOf('text/x-handlebars-template') <= -1) {
                           throw new UUFClientException(
                               "Response content type is incorrect. Found '" + jqXHR.getResponseHeader("content-type")
                               + "' instead of 'text/x-handlebars-template'.");
                       }
                       UUFClient.renderTemplateString(data, templateFillingObject, zoneName, mode);
                       callbacks["onSuccess"](data);
                   },
                   error: function (jqXHR, textStatus, errorThrown) {
                       callbacks["onFailure"]("Error occurred while retrieving template from " + templateUrl + ".",
                                              errorThrown);
                   }
               });
    };

    /**
     * Renders the Handlebars template and pushes to the given zone according to the given mode.
     *
     * @param {string} templateString Handlebars template
     * @param {?Object} templateFillingObject data for the template
     * @param {string} zoneName name of the zone to push
     * @param {string} mode mode to use
     * @param {Function} callbacks callback function
     */
    UUFClient.renderTemplateString = function (templateString, templateFillingObject, zoneName, mode, callbacks) {
        if (!templateString) {
            throw new UUFClientException("Template string cannot be null or empty.");
        }
        validate(zoneName, mode, callbacks);

        if (!zonesMap) {
            var error = populateZonesMap();
            if (error) {
                callbacks["onFailure"](error);
                return;
            }
        }

        var zone = zonesMap[zoneName];
        if (!zone) {
            throw new UUFClientException("Zone '" + zoneName + "' does not exists in current DOM.");
        }

        try {
            var template = Handlebars.compile(templateString);
            var html = template(templateFillingObject);
            pushContent(html, zone, mode);
            callbacks["onSuccess"](html);
        } catch (e) {
            callbacks["onFailure"]("Error occurred while compiling the handlebar template.", e);
        }
    };

})(UUFClient);
<commit_msg>Add ON_SUCCESS, ON_FAILURE constants<commit_after>/**
 * @license
 * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
 *
 * WSO2 Inc. licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

var UUFClient = {};

(function (UUFClient) {

    var UUF_ZONE_COMMENT_PREFIX = "[UUF-ZONE]";
    var ON_SUCCESS = "onSuccess";
    var ON_FAILURE = "onFailure";

    /**
     * Zones in the current DOM.
     * @type {{string: {start: Object, end: Object}}}
     */

    var zonesMap;

    // Check whether the JQuery is available.
    if (!window.jQuery) {
        throw new UUFClientException("JQuery is required for UUFClient.");
    }
    // Check whether the Handlebars is available.
    if (!window.Handlebars) {
        throw new UUFClientException("Handlebars JS is required for UUFClient.");
    }

    /**
     * Indicates an error in UUFClient.
     *
     * @param {string} message message of this error
     * @param {Object} [cause] cause of this error
     * @param {number} [statusCode] status code of this error
     * @constructor
     */
    function UUFClientException(message, cause, statusCode) {
        this.message = message;
        this.cause = cause;
        this.statusCode = statusCode;
    }

    /**
     * Populates a zones map by scanning HTML comments in the DOM.
     */
    function populateZonesMap() {
        zonesMap = {};
        $("*").contents().filter(function () {
            // For HTML comments, node type will be 8.
            return this.nodeType === 8;
        }).each(function (i, node) {
            var commentText = node.nodeValue;
            if (!commentText.startsWith(UUF_ZONE_COMMENT_PREFIX)) {
                return;
            }
            var zone;
            try {
                zone = JSON.parse(commentText.substring(UUF_ZONE_COMMENT_PREFIX.length));
            } catch (e) {
                throw new UUFClientException("Cannot parse UUFClient zone comment '" + commentText
                                             + "' as a JSON.");
            }
            if (!zone.name) {
                throw new UUFClientException("Cannot find field 'name' in the UUFClient zone comment '"
                                             + commentText + "'.");
            }
            if (!zone.position) {
                throw new UUFClientException("Cannot find field 'position' in the UUFClient zone comment '"
                                             + commentText + "'.");
            }

            if (!zonesMap[zone.name]) {
                zonesMap[zone.name] = {};
            }
            zonesMap[zone.name][zone.position] = node;
        });
    }

    /**
     * Pushes the content to the specified zone according to the given mode.
     *
     * @param {string} content content to push
     * @param {string} zone name of the zone to push
     * @param {string} mode mode to use. Mode can be either PREPEND, APPEND or OVERWRITE. PREPEND will
     *     add the fragment to the beginning of the existing content of that zone. Mode can be "PREPEND" (put the
     *     pushing content before the existing content), "APPEND" (put the pushing content after the existing content)
     *     or "OVERWRITE" (replace the existing content with the pushing content)
     */
    function pushContent(content, zone, mode) {
        if (!content) {
            console.warn("Content is empty.");
            return;
        }

        switch (mode) {
            case "OVERWRITE":
                var innerContents = $(zone.start).parent().contents();
                innerContents.slice(innerContents.index($(zone.start)) + 1, innerContents.index($(zone.end))).remove();
                $(zone.start).after(content);
                break;
            case "APPEND":
                $(zone.end).before(content);
                break;
            case "PREPEND":
                $(zone.start).after(content);
                break;
            default:
                throw new UUFClientException("Mode '" + mode + "' is not supported.");
        }
    }

    /**
     * Check the zoneName and mode variables for null or empty and check for the callback functions.
     *
     * @param {string} zoneName
     * @param {string} mode
     * @param {?Object} callbacks
     */
    function validate(zoneName, mode, callbacks) {
        if (!zoneName) {
            throw new UUFClientException("Zone name cannot be null or empty.");
        }
        if (!mode) {
            throw new UUFClientException("Mode cannot be null or empty.");
        }
        if (!callbacks[ON_SUCCESS]) {
            throw new UUFClientException("'onSuccess' callback function not found.");
        }
        if (!callbacks[ON_FAILURE]) {
            throw new UUFClientException("'onFailure' callback function not found.");
        }
    }

    /**
     * Renders the specified fragment and pushes to the given zone according to the given mode.
     *
     * @param {string} fragmentFullyQualifiedName fully qualified name of the fragment
     * @param {?Object} templateFillingObject data for the template
     * @param {string} zoneName name of the zone to push
     * @param {string} mode mode to use
     * @param {Function} callbacks callback function
     */
    UUFClient.renderFragment = function (fragmentFullyQualifiedName, templateFillingObject, zoneName, mode, callbacks) {
        if (!fragmentFullyQualifiedName) {
            throw new UUFClientException("Fragment name cannot be null or empty.");
        }
        validate(zoneName, mode, callbacks);

        if (!zonesMap) {
            populateZonesMap();
        }
        var zone = zonesMap[zoneName];
        if (!zone) {
            throw new UUFClientException("Zone '" + zoneName + "' does not exists in current DOM.");
        }

        var url = contextPath + "/fragments/" + fragmentFullyQualifiedName;
        $.ajax({
                   url: url,
                   type: "POST",
                   contentType: 'application/json',
                   data: JSON.stringify(templateFillingObject),
                   success: function (data, textStatus, jqXHR) {
                       var error = pushContent(data, zone, mode);
                       if (error) {
                           callbacks[ON_FAILURE](error);
                           return;
                       }
                       callbacks[ON_SUCCESS](data);
                   },
                   error: function (jqXHR, textStatus, errorThrown) {
                       var msg = "Error occurred while retrieving fragment '" + fragmentFullyQualifiedName
                                 + "' from '" + url + "'.";
                       callbacks[ON_FAILURE](msg, errorThrown);
                   }
               });
    };

    /**
     * Renders the specified embedded Handlebars template and pushes to the given zone according to the given mode.
     *
     * @param {string} templateId id of the handlebars template
     * @param {?Object} templateFillingObject data for the template
     * @param {string} zoneName name of the zone to push
     * @param {string} mode mode to use
     * @param {Function} callbacks callback function
     */
    UUFClient.renderTemplate = function (templateId, templateFillingObject, zoneName, mode, callbacks) {
        if (!templateId) {
            throw new UUFClientException("Template name cannot be null or empty.");
        }
        validate(zoneName, mode, callbacks);

        var source = $("#" + templateId).html();
        if (source) {
            UUFClient.renderTemplateString(source, templateFillingObject, zoneName, mode, callbacks);
        } else {
            throw new UUFClientException("Template '" + templateId + "' not found");
        }
    };

    /**
     * Retrieves the Handlebars template from the specified URL and renders and pushes it to the given zone according
     * to the given mode.
     *
     * @param {string} templateUrl url of the template
     * @param {?Object} templateFillingObject data for the template
     * @param {string} zoneName name of the zone to push
     * @param {string} mode mode to use
     * @param {Function} callbacks callback function
     */
    UUFClient.renderTemplateUrl = function (templateUrl, templateFillingObject, zoneName, mode, callbacks) {
        if (!templateUrl) {
            throw new UUFClientException("Template url cannot be null or empty.");
        }
        validate(zoneName, mode, callbacks);

        $.ajax({
                   url: templateUrl,
                   type: "GET",
                   success: function (data, textStatus, jqXHR) {
                       var contentType = jqXHR.getResponseHeader("content-type") || "";
                       if (contentType.indexOf('text/x-handlebars-template') <= -1) {
                           throw new UUFClientException(
                               "Response content type is incorrect. Found '" + jqXHR.getResponseHeader("content-type")
                               + "' instead of 'text/x-handlebars-template'.");
                       }
                       UUFClient.renderTemplateString(data, templateFillingObject, zoneName, mode);
                       callbacks[ON_SUCCESS](data);
                   },
                   error: function (jqXHR, textStatus, errorThrown) {
                       callbacks[ON_FAILURE]("Error occurred while retrieving template from " + templateUrl + ".",
                                              errorThrown);
                   }
               });
    };

    /**
     * Renders the Handlebars template and pushes to the given zone according to the given mode.
     *
     * @param {string} templateString Handlebars template
     * @param {?Object} templateFillingObject data for the template
     * @param {string} zoneName name of the zone to push
     * @param {string} mode mode to use
     * @param {Function} callbacks callback function
     */
    UUFClient.renderTemplateString = function (templateString, templateFillingObject, zoneName, mode, callbacks) {
        if (!templateString) {
            throw new UUFClientException("Template string cannot be null or empty.");
        }
        validate(zoneName, mode, callbacks);

        if (!zonesMap) {
            var error = populateZonesMap();
            if (error) {
                callbacks[ON_FAILURE](error);
                return;
            }
        }

        var zone = zonesMap[zoneName];
        if (!zone) {
            throw new UUFClientException("Zone '" + zoneName + "' does not exists in current DOM.");
        }

        try {
            var template = Handlebars.compile(templateString);
            var html = template(templateFillingObject);
            pushContent(html, zone, mode);
            callbacks[ON_SUCCESS](html);
        } catch (e) {
            callbacks[ON_FAILURE]("Error occurred while compiling the handlebar template.", e);
        }
    };

})(UUFClient);
<|endoftext|>


<commit_before>(function ($, ns, channel, window, undefined) {

    var actionDef = {
        icon: 'coral-Icon--globe',
        text: Granite.I18n.get('Configure Shared Content'),
        handler: function (editable, param, target) { // will be called on click
        	var originalDialogSrc = editable.config.dialogSrc;
        	var originalDialog = editable.config.dialog;

        	var dialogSrcArray = editable.config.dialogSrc.split(".html");
        	var langRootRegexp = /^(\/content\/([^/]+\/)+([a-zA-Z]{2}([_-][a-zA-Z]{2})?))(|\/.*)$/g;
        	var match = langRootRegexp.exec(dialogSrcArray[1]);

        	var siteWideDialogSrc = dialogSrcArray[0].replace("_cq_dialog", "_cq_dialogsitewide") +
						        	".html" +
						        	match[1] +
						        	"/jcr:content/sitewideprops/" +
						        	editable.type;

        	editable.config.dialogSrc = siteWideDialogSrc;
        	editable.config.dialog = editable.config.dialog.replace("cq:dialog", "cq:dialogsitewide");

        	ns.edit.actions.doConfigure(editable);

        	//set the dialog and dialogSrc back to the original values so normal edit dialog continues to work
        	editable.config.dialogSrc = originalDialogSrc;
        	editable.config.dialog = originalDialog;

            // do not close toolbar
            return false;
        },
        /*
         * In the event that we need to restrict this to specific components or something, we would potentially
         * do that in this "condition" function. If we don't, we , we would do that here. Otherwise, leave it out!
         */
//        condition: function(editable) {
//            //restrict to just a specific component, otherwise it will show up on all components.
//            var result = editable.type === "fmmp-base/components/content/[path to component here]";
//            return result;
//        },
        isNonMulti: true
    };

    // we listen to the messaging channel
    // to figure out when a layer got activated
    channel.on('cq-layer-activated', function (ev) {
        // we continue if the user switched to the Edit layer
        if (ev.layer === 'Edit') {
            // we use the editable toolbar and register an additional action
            ns.EditorFrame.editableToolbar.registerAction('COMMON-CONTENT', actionDef);
        }
    });

}(jQuery, Granite.author, jQuery(document), this));
<commit_msg>Updated to restrict to add the globe icon to the toolbar, only when a standard dialog exists<commit_after>(function ($, ns, channel, window, undefined) {

    var actionDef = {
        icon: 'coral-Icon--globe',
        text: Granite.I18n.get('Configure Shared Content'),
        handler: function (editable, param, target) { // will be called on click
        	var originalDialogSrc = editable.config.dialogSrc;
        	var originalDialog = editable.config.dialog;

        	var dialogSrcArray = editable.config.dialogSrc.split(".html");
        	var langRootRegexp = /^(\/content\/([^/]+\/)+([a-zA-Z]{2}([_-][a-zA-Z]{2})?))(|\/.*)$/g;
        	var match = langRootRegexp.exec(dialogSrcArray[1]);

        	var siteWideDialogSrc = dialogSrcArray[0].replace("_cq_dialog", "_cq_dialogsitewide") +
						        	".html" +
						        	match[1] +
						        	"/jcr:content/sitewideprops/" +
						        	editable.type;

        	editable.config.dialogSrc = siteWideDialogSrc;
        	editable.config.dialog = editable.config.dialog.replace("cq:dialog", "cq:dialogsitewide");

        	ns.edit.actions.doConfigure(editable);

        	//set the dialog and dialogSrc back to the original values so normal edit dialog continues to work
        	editable.config.dialogSrc = originalDialogSrc;
        	editable.config.dialog = originalDialog;

            // do not close toolbar
            return false;
        },
        /*
         * In the event that we need to restrict this to specific components or something, we would potentially
         * do that in this "condition" function. If we don't, we , we would do that here. Otherwise, leave it out!
         */
        //Restrict to users with correct permissions and if the dialog exists
        condition: function(editable) {
        	var canModify = ns.page.info.permissions && ns.page.info.permissions.modify;
            return !!editable.config.dialog && canModify;
        },
        isNonMulti: true
    };

    // we listen to the messaging channel
    // to figure out when a layer got activated
    channel.on('cq-layer-activated', function (ev) {
        // we continue if the user switched to the Edit layer
        if (ev.layer === 'Edit') {
            // we use the editable toolbar and register an additional action
            ns.EditorFrame.editableToolbar.registerAction('COMMON-CONTENT', actionDef);
        }
    });

}(jQuery, Granite.author, jQuery(document), this));
<|endoftext|>


<commit_before>import translator from '../utils/translator'
import router from '../store/router'
// import config from '../config'
// import stores from '../stores'

var BaseMixin = {
    // init: function() {
    // },

    t: function() {
        return translator.translate(...arguments)
    },

    tRoute: function() {
        return router.buildRoute(...arguments)
    },

    fRoute: function() {
        return () => router.route(...arguments)
    },

    router: router,
    // config: config,
    // s: stores,

    watch: function(names) {
        names = names.split(' ')
        for (let name of names) {
            let watcher = (val) => {
                if (this[name] != val) {
                    this[name] = val
                    // console.log('updating because of', name, 'to', val)
                    this.update()
                }
            }
            let signal = riot.SEC(name)
            // Watch var changes
            riot.control.on(signal, watcher)
            // Unwatch when unmount
            this.on('unmount', () => {
                riot.control.off(signal, watcher)
            })
            // Request load
            riot.control.trigger(riot.VEL(name))
        }
    },

    // Watch var nameData, and request more data for it when nameDepends change
    watchDepends: function(nameData, nameDepends, onChange) {
        // Watch changes on main var
        riot.control.on(riot.SEC(nameData), data => {
            if ((data.key == this[nameDepends]) &&
                (this[nameData] != data.value)) {
                this[nameData] = data.value
                onChange()
            }
        })

        // Watch changes on var which main depends
        riot.control.on(riot.SEC(nameDepends), (valueDepends) => {
            if (this[nameDepends] != valueDepends) {
                this[nameDepends] = valueDepends
                riot.control.trigger(riot.VEL(nameData), this[nameDepends])
            }
        })

        // Load both vars
        console.log('mixing: trigger var:', nameData, 'key:', this[nameDepends])
        riot.control.trigger(riot.VEL(nameDepends))
        riot.control.trigger(riot.VEL(nameData), this[nameDepends])
    },

    // Trigger a change in stores
    triggerChange: function(name, value) {
        riot.control.trigger(riot.VEC(name), value)
    },
}

riot.mixin('base', BaseMixin)
<commit_msg>remove callbacks on unmount to avoid residual callbacks<commit_after>import translator from '../utils/translator'
import router from '../store/router'
// import config from '../config'
// import stores from '../stores'

var BaseMixin = {
    // init: function() {
    // },

    t: function() {
        return translator.translate(...arguments)
    },

    // tRoute: function() {
    //     return router.buildRoute(...arguments)
    // },

    fRoute: function() {
        return () => router.route(...arguments)
    },

    router: router,
    // config: config,
    // s: stores,

    watch: function(names) {
        names = names.split(' ')
        for (let name of names) {
            let watcher = (val) => {
                if (this[name] != val) {
                    this[name] = val
                    // console.log('updating because of', name, 'to', val)
                    this.update()
                }
            }
            let signal = riot.SEC(name)
            // Watch var changes
            riot.control.on(signal, watcher)
            // Unwatch when unmount
            this.on('unmount', () => {
                riot.control.off(signal, watcher)
            })
            // Request load
            riot.control.trigger(riot.VEL(name))
        }
    },

    // Watch var nameData, and request more data for it when nameDepends change
    watchDepends: function(nameData, nameDepends, onChange) {
        // Watch changes on main var
        riot.control.on(riot.SEC(nameData), data => {
            if ((data.key == this[nameDepends]) &&
                (this[nameData] != data.value)) {
                this[nameData] = data.value
                onChange()
            }
        })

        // Watch changes on var which main depends
        riot.control.on(riot.SEC(nameDepends), (valueDepends) => {
            if (this[nameDepends] != valueDepends) {
                this[nameDepends] = valueDepends
                riot.control.trigger(riot.VEL(nameData), this[nameDepends])
            }
        })

        // Load both vars
        console.log('mixing: trigger var:', nameData, 'key:', this[nameDepends])
        riot.control.trigger(riot.VEL(nameDepends))
        riot.control.trigger(riot.VEL(nameData), this[nameDepends])
    },

    // Trigger a change in stores
    triggerChange: function(name, value) {
        riot.control.trigger(riot.VEC(name), value)
    },

    // Register a func to run on control event. Unregister at unmount.
    onControl: function(signal, func) {
        riot.control.on(signal, func)
        this.on('unmount', () => riot.control.off(signal, func))
    }
}

riot.mixin('base', BaseMixin)
<|endoftext|>


<commit_before>var keystone		= require('keystone'),
	async			= require('async'),
	User			= keystone.list('User'),
	Family			= keystone.list('Family'),
	Child			= keystone.list('Child'),
	childService	= require('./service_child'),
	userService		= require('./service_user');

exports.setGalleryPermissions = function setGalleryPermissions(req, res, done) {

	var locals		= res.locals,
		userType	= locals.userType;

	locals.canBookmarkChildren = userType === 'social worker' || userType === 'family' ? true : false;
	locals.canSearchForChildren = userType === 'social worker' || userType === 'family' ? true : false;

	done();
};

/* If the user type is capable of bookmarking children on the site, retrieve any that are already bookmarked */
exports.getBookmarkedChildren = function getBookmarkedChildren(req, res, done) {

	var locals = res.locals;

	// Fetch the user if it has already been retrieved
	if(locals.user === undefined) {

		var userId = req.user.get('_id');

		async.series([
			function(done) { userService.getUserById(req, res, done, userId); }
		], function() {

			locals.bookmarkedChildren = locals.user.get('bookmarkedChildren');
			// execute done function if async is used to continue the flow of execution
			// TODO: if this is used in non-async middleware, done or next should be passed into options and the appropriate one should be executed
			done();

		});

	} else {

		locals.bookmarkedChildren = locals.user.get('bookmarkedChildren');

		done();
	}

};

/*
 *	Frontend services
 */
exports.addChildBookmark = function addChildBookmark(req, res, next) {

	var locals = res.locals;
		userId = req.user.get('_id');
		registrationNumber = req.body.registrationNumber;

	async.parallel([
		function(done) { childService.getChildByRegistrationNumber(req, res, done, registrationNumber); },
		function(done) { userService.getUserById(req, res, done, userId); }
	], function() {

		var childId				= locals.child.get('_id'),
			bookmarkedChildren	= locals.user.get('bookmarkedChildren');
		// Only add the bookmark if it hasn't already been saved.  This is unlikely, and would require a bad state in the system,
		// but the check has been added for an extra layer of safety
		if(bookmarkedChildren.indexOf(childId) === -1) {
			bookmarkedChildren.push(childId);
		}

		locals.user.update({ bookmarkedChildren: bookmarkedChildren }, { multi: false }, function (err, raw) {
			if (err) {
				console.log(err);
			}

			res.send('bookmark added');

		});
	});
};

exports.removeChildBookmark = function removeChildBookmark(req, res, next) {
	var locals = res.locals;
		userId = req.user.get('_id');
		registrationNumber = req.body.registrationNumber;

	async.parallel([
		function(done) { childService.getChildByRegistrationNumber(req, res, done, registrationNumber); },
		function(done) { userService.getUserById(req, res, done, userId); }
	], function() {

		var childId				= locals.child.get('_id'),
			bookmarkedChildren	= locals.user.get('bookmarkedChildren'),
			bookmarkIndex		= bookmarkedChildren.indexOf(childId);
		// Only remove the bookmark if it has already been saved.  This is unlikely, and would require a bad state in the system,
		// but the check has been added for an extra layer of safety
		console.log('1')
		console.log(bookmarkedChildren);
		if(bookmarkedChildren.indexOf(childId) !== -1) {
			bookmarkedChildren.splice(bookmarkIndex, 1);
		}
		console.log('2');
		console.log(bookmarkedChildren);

		locals.user.update({ bookmarkedChildren: bookmarkedChildren }, { multi: false }, function (err, raw) {
			if (err) {
				console.log(err);
			}

			res.send('bookmark added');

		});
	});
};
<commit_msg>#60 | remove unneeded comments<commit_after>var keystone		= require('keystone'),
	async			= require('async'),
	User			= keystone.list('User'),
	Family			= keystone.list('Family'),
	Child			= keystone.list('Child'),
	childService	= require('./service_child'),
	userService		= require('./service_user');

exports.setGalleryPermissions = function setGalleryPermissions(req, res, done) {

	var locals		= res.locals,
		userType	= locals.userType;

	locals.canBookmarkChildren = userType === 'social worker' || userType === 'family' ? true : false;
	locals.canSearchForChildren = userType === 'social worker' || userType === 'family' ? true : false;

	done();
};

/* If the user type is capable of bookmarking children on the site, retrieve any that are already bookmarked */
exports.getBookmarkedChildren = function getBookmarkedChildren(req, res, done) {

	var locals = res.locals;

	// Fetch the user if it has already been retrieved
	if(locals.user === undefined) {

		var userId = req.user.get('_id');

		async.series([
			function(done) { userService.getUserById(req, res, done, userId); }
		], function() {

			locals.bookmarkedChildren = locals.user.get('bookmarkedChildren');
			// execute done function if async is used to continue the flow of execution
			// TODO: if this is used in non-async middleware, done or next should be passed into options and the appropriate one should be executed
			done();

		});

	} else {

		locals.bookmarkedChildren = locals.user.get('bookmarkedChildren');

		done();
	}

};

/*
 *	Frontend services
 */
exports.addChildBookmark = function addChildBookmark(req, res, next) {

	var locals = res.locals;
		userId = req.user.get('_id');
		registrationNumber = req.body.registrationNumber;

	async.parallel([
		function(done) { childService.getChildByRegistrationNumber(req, res, done, registrationNumber); },
		function(done) { userService.getUserById(req, res, done, userId); }
	], function() {

		var childId				= locals.child.get('_id'),
			bookmarkedChildren	= locals.user.get('bookmarkedChildren');
		// Only add the bookmark if it hasn't already been saved.  This is unlikely, and would require a bad state in the system,
		// but the check has been added for an extra layer of safety
		if(bookmarkedChildren.indexOf(childId) === -1) {
			bookmarkedChildren.push(childId);
		}

		locals.user.update({ bookmarkedChildren: bookmarkedChildren }, { multi: false }, function (err, raw) {
			if (err) {
				console.log(err);
			}

			res.send('bookmark added');

		});
	});
};

exports.removeChildBookmark = function removeChildBookmark(req, res, next) {
	var locals = res.locals;
		userId = req.user.get('_id');
		registrationNumber = req.body.registrationNumber;

	async.parallel([
		function(done) { childService.getChildByRegistrationNumber(req, res, done, registrationNumber); },
		function(done) { userService.getUserById(req, res, done, userId); }
	], function() {

		var childId				= locals.child.get('_id'),
			bookmarkedChildren	= locals.user.get('bookmarkedChildren'),
			bookmarkIndex		= bookmarkedChildren.indexOf(childId);
		// Only remove the bookmark if it has already been saved.  This is unlikely, and would require a bad state in the system,
		// but the check has been added for an extra layer of safety
		if(bookmarkedChildren.indexOf(childId) !== -1) {
			bookmarkedChildren.splice(bookmarkIndex, 1);
		}

		locals.user.update({ bookmarkedChildren: bookmarkedChildren }, { multi: false }, function (err, raw) {
			if (err) {
				console.log(err);
			}

			res.send('bookmark added');

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


<commit_before>define(["./OnDemandGrid", "dojo/_base/declare", "dojo/_base/lang", "dojo/dom-construct", "dojo/_base/Deferred", "require"], function(OnDemandGrid, declare, lang, domConstruct, Deferred, require){
	// This module supports parsing grid structure information from an HTML table.
	// This module does NOT support ColumnSets; see GridWithColumnSetsFromHtml

	// name of data attribute to check for column properties
	var bagName = "data-dgrid-props";

	function getSubRowsFromDom(domNode){
		// summary:
		//		generate columns from DOM. Should this be in here, or a separate module?
		var
			columns = [], // to be pushed upon / returned
			trs = domNode.getElementsByTagName("tr"),
			trslen = trs.length,
			getCol = GridFromHtml.utils.getColumnFromCell;

		for(var i = 0; i < trslen; i++){
			var rowColumns = [];
			columns.push(rowColumns);
			var tr = trs[i];
			var ths = tr.getElementsByTagName("th"), thslen = ths.length;
			for(var j = 0; j < thslen; j++){
				rowColumns.push(getCol(ths[j]));
			}
		}
		if(tr){
			// FIXME: this assumes that applicable TRs were ONLY found under one
			// grouping element!  Maybe should limit to thead like dojox grid?
			// (Especially if we ever want to support tbody>tr>td -> renderArray)
			domNode.removeChild(tr.parentNode);
		}

		return columns;
	}

	var GridFromHtml = declare([OnDemandGrid], {
		configStructure: function(){
			// summary:
			//		Configure subRows based on HTML originally in srcNodeRef
			if(!this._checkedTrs){
				this._checkedTrs = true;
				this.subRows = getSubRowsFromDom(this.srcNodeRef, this.subRows);
			}
			return this.inherited(arguments);
		},

		create: function(params, srcNodeRef){
			// We need to replace srcNodeRef, presumably a table, with a div.
			// (Otherwise we'll generate highly invalid markup, which IE doesn't like)
			var
				div = document.createElement("div"),
				id = srcNodeRef.id,
				style = srcNodeRef.getAttribute("style");

			// Copy some commonly-used attributes...
			if(id){ this.id = id; } // will be propagated in List's create
			div.className = srcNodeRef.className;
			style && div.setAttribute("style", style);

			// replace srcNodeRef in DOM with the div
			srcNodeRef.parentNode.replaceChild(div, srcNodeRef);

			(params = params || {}).srcNodeRef = srcNodeRef;
			// call inherited with the new node
			// (but configStructure will look at srcNodeRef)
			this.inherited(arguments, [params, div]);

			// destroy srcNodeRef for good now that we're done with it
			domConstruct.destroy(srcNodeRef);
		}
	});

	// hang some utility functions, potentially useful for extensions
	GridFromHtml.utils = {
		// Functions for getting various types of values from HTML attributes
		getObjFromAttr: function(node, attr){
			// used to for e.g. formatter, get, renderCell
			var val = node.getAttribute(attr);
			return val && lang.getObject(val);
		},
		getBoolFromAttr: function(node, attr){
			// used for e.g. sortable
			var val = node.getAttribute(attr);
			return val && val !== "false";
		},
		getNumFromAttr: function(node, attr){
			// used for e.g. rowSpan, colSpan
			var val = node.getAttribute(attr);
			val = val && Number(val);
			return isNaN(val) ? undefined : val;
		},
		getPropsFromNode: function(node){
			// used to pull properties out of bag e.g. "data-dgrid-props".
			var obj, str = node.getAttribute(bagName);
			if(!str){ return {}; } // no props bag specified!

			// Yes, eval is evil, but this is the same thing that dojo.parser
			// does for data-dojo-props - which is what we want to mimic.
			try{
				obj = eval("({" + str + "})");
			}catch(e){
				throw new Error("Error in " + bagName + " {" + str + "}: " + e.toString());
			}
			return obj;
		},

		// Function for aggregating th attributes into column properties
		getColumnFromCell: function(th){
			var
				getObj = GridFromHtml.utils.getObjFromAttr,
				getBool = GridFromHtml.utils.getBoolFromAttr,
				getNum = GridFromHtml.utils.getNumFromAttr,
				obj = {}, tmp;

			// inspect standard attributes first
			obj.label = th.innerHTML;
			obj.field = th.className || th.innerHTML; // often overridden in props
			if(th.className){ obj.className = th.className; }
			if((tmp = getNum(th, "rowspan"))){ obj.rowSpan = tmp; }
			if((tmp = getNum(th, "colspan"))){ obj.colSpan = tmp; }

			// look for rest of properties in data attribute
			// (properties in data attribute can override the HTML attributes above)
			dojo.mixin(obj, GridFromHtml.utils.getPropsFromNode(th));
			return obj;
			/*
			return {
				label: th.innerHTML,
				field: th.getAttribute("field") || th.className || th.innerHTML,
				className: th.className,
				sortable: getBool(th, "sortable"),
				get: getObj(th, "get"),
				formatter: getObj(th, "formatter"),
				renderCell: getObj(th, "renderCell"),
				renderHeaderCell: getObj(th, "renderHeaderCell"),
				rowSpan: getNum(th, "rowspan"),
				colSpan: getNum(th, "colspan")
			};
			*/
		}
	}
	return GridFromHtml;
});<commit_msg>GridFromHtml: remove old commented return<commit_after>define(["./OnDemandGrid", "dojo/_base/declare", "dojo/_base/lang", "dojo/dom-construct", "dojo/_base/Deferred", "require"], function(OnDemandGrid, declare, lang, domConstruct, Deferred, require){
	// This module supports parsing grid structure information from an HTML table.
	// This module does NOT support ColumnSets; see GridWithColumnSetsFromHtml

	// name of data attribute to check for column properties
	var bagName = "data-dgrid-props";

	function getSubRowsFromDom(domNode){
		// summary:
		//		generate columns from DOM. Should this be in here, or a separate module?
		var
			columns = [], // to be pushed upon / returned
			trs = domNode.getElementsByTagName("tr"),
			trslen = trs.length,
			getCol = GridFromHtml.utils.getColumnFromCell;

		for(var i = 0; i < trslen; i++){
			var rowColumns = [];
			columns.push(rowColumns);
			var tr = trs[i];
			var ths = tr.getElementsByTagName("th"), thslen = ths.length;
			for(var j = 0; j < thslen; j++){
				rowColumns.push(getCol(ths[j]));
			}
		}
		if(tr){
			// FIXME: this assumes that applicable TRs were ONLY found under one
			// grouping element!  Maybe should limit to thead like dojox grid?
			// (Especially if we ever want to support tbody>tr>td -> renderArray)
			domNode.removeChild(tr.parentNode);
		}

		return columns;
	}

	var GridFromHtml = declare([OnDemandGrid], {
		configStructure: function(){
			// summary:
			//		Configure subRows based on HTML originally in srcNodeRef
			if(!this._checkedTrs){
				this._checkedTrs = true;
				this.subRows = getSubRowsFromDom(this.srcNodeRef, this.subRows);
			}
			return this.inherited(arguments);
		},

		create: function(params, srcNodeRef){
			// We need to replace srcNodeRef, presumably a table, with a div.
			// (Otherwise we'll generate highly invalid markup, which IE doesn't like)
			var
				div = document.createElement("div"),
				id = srcNodeRef.id,
				style = srcNodeRef.getAttribute("style");

			// Copy some commonly-used attributes...
			if(id){ this.id = id; } // will be propagated in List's create
			div.className = srcNodeRef.className;
			style && div.setAttribute("style", style);

			// replace srcNodeRef in DOM with the div
			srcNodeRef.parentNode.replaceChild(div, srcNodeRef);

			(params = params || {}).srcNodeRef = srcNodeRef;
			// call inherited with the new node
			// (but configStructure will look at srcNodeRef)
			this.inherited(arguments, [params, div]);

			// destroy srcNodeRef for good now that we're done with it
			domConstruct.destroy(srcNodeRef);
		}
	});

	// hang some utility functions, potentially useful for extensions
	GridFromHtml.utils = {
		// Functions for getting various types of values from HTML attributes
		getObjFromAttr: function(node, attr){
			// used to for e.g. formatter, get, renderCell
			var val = node.getAttribute(attr);
			return val && lang.getObject(val);
		},
		getBoolFromAttr: function(node, attr){
			// used for e.g. sortable
			var val = node.getAttribute(attr);
			return val && val !== "false";
		},
		getNumFromAttr: function(node, attr){
			// used for e.g. rowSpan, colSpan
			var val = node.getAttribute(attr);
			val = val && Number(val);
			return isNaN(val) ? undefined : val;
		},
		getPropsFromNode: function(node){
			// used to pull properties out of bag e.g. "data-dgrid-props".
			var obj, str = node.getAttribute(bagName);
			if(!str){ return {}; } // no props bag specified!

			// Yes, eval is evil, but this is the same thing that dojo.parser
			// does for data-dojo-props - which is what we want to mimic.
			try{
				obj = eval("({" + str + "})");
			}catch(e){
				throw new Error("Error in " + bagName + " {" + str + "}: " + e.toString());
			}
			return obj;
		},

		// Function for aggregating th attributes into column properties
		getColumnFromCell: function(th){
			var
				getObj = GridFromHtml.utils.getObjFromAttr,
				getBool = GridFromHtml.utils.getBoolFromAttr,
				getNum = GridFromHtml.utils.getNumFromAttr,
				obj = {}, tmp;

			// inspect standard attributes first
			obj.label = th.innerHTML;
			obj.field = th.className || th.innerHTML; // often overridden in props
			if(th.className){ obj.className = th.className; }
			if((tmp = getNum(th, "rowspan"))){ obj.rowSpan = tmp; }
			if((tmp = getNum(th, "colspan"))){ obj.colSpan = tmp; }

			// look for rest of properties in data attribute
			// (properties in data attribute can override the HTML attributes above)
			dojo.mixin(obj, GridFromHtml.utils.getPropsFromNode(th));
			return obj;
		}
	}
	return GridFromHtml;
});<|endoftext|>


<commit_before>'use strict';

streamaApp.controller('adminSettingsCtrl', ['$scope', 'apiService', '$sce', function ($scope, apiService, $sce) {

  apiService.settings.list().success(function (data) {
    $scope.settings = data;

    _.forEach(data, function (setting) {
      setting.description = $sce.trustAsHtml(Autolinker.link(setting.description, { newWindow: "true" } ));
    });
    $scope.loading = false;
  });

  $scope.updateMultipleSettings = function (settings) {
    settings.invalid = false;

    apiService.settings.updateMultiple(settings)
      .success(function () {
        window.location.reload();
      })
      .error(function () {
        alertify.error('There was an error saving your settings. Please refer to the server-log.');
      });
  };

  $scope.validateSettings = function (settings) {
    $scope.changeValue(settings);
    $scope.loading = true;

    apiService.settings.validateSettings(settings)
      .success(function (data) {
        alertify.success(data.message || 'validation successful');
        settings.valid = true;
        $scope.loading = false;
      })
      .error(function (data) {
        alertify.error(data.message);
        settings.invalid = true;
        $scope.loading = false;
      });
  };

  $scope.changeValue = function (settings) {
    settings.valid = undefined;
    settings.invalid = undefined;
    settings.dirty = settings.value;
  };

  $scope.anySettingsInvalid = function () {
    return _.find($scope.settings, function (setting) {
        return setting.invalid || (setting.dirty && !setting.valid) || !setting.value;
   });
  };

}]);
<commit_msg>removed redundant error message<commit_after>'use strict';

streamaApp.controller('adminSettingsCtrl', ['$scope', 'apiService', '$sce', function ($scope, apiService, $sce) {

  apiService.settings.list().success(function (data) {
    $scope.settings = data;

    _.forEach(data, function (setting) {
      setting.description = $sce.trustAsHtml(Autolinker.link(setting.description, { newWindow: "true" } ));
    });
    $scope.loading = false;
  });

  $scope.updateMultipleSettings = function (settings) {
    settings.invalid = false;

    apiService.settings.updateMultiple(settings)
      .success(function () {
        window.location.reload();
      })
  };

  $scope.validateSettings = function (settings) {
    $scope.changeValue(settings);
    $scope.loading = true;

    apiService.settings.validateSettings(settings)
      .success(function (data) {
        alertify.success(data.message || 'validation successful');
        settings.valid = true;
        $scope.loading = false;
      })
      .error(function (data) {
        alertify.error(data.message);
        settings.invalid = true;
        $scope.loading = false;
      });
  };

  $scope.changeValue = function (settings) {
    settings.valid = undefined;
    settings.invalid = undefined;
    settings.dirty = settings.value;
  };

  $scope.anySettingsInvalid = function () {
    return _.find($scope.settings, function (setting) {
        return setting.invalid || (setting.dirty && !setting.valid) || !setting.value;
   });
  };

}]);
<|endoftext|>


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

    angular
        .module('app.core')
        .constant('AppSettings', {
            appName: 'Boxing Lab',
            appVersion: 0.1,
            apiUrl: 'http://api.boxing.audienciazero.net'
        });
})();<commit_msg>adds trailing slash to api url in production settings<commit_after>(function() {
    'use strict';

    angular
        .module('app.core')
        .constant('AppSettings', {
            appName: 'Boxing Lab',
            appVersion: 0.1,
            apiUrl: 'http://api.boxing.audienciazero.net/'
        });
})();
<|endoftext|>