<commit_before>'use strict';

const Assert = require('chai').assert;
const request = require('../support/request');
const { defineSupportCode } = require('cucumber');

// Timeout of 15 seconds
const TIMEOUT = 15 * 1000;

/**
 * Helper function to create a collection
 * @method createCollection
 * @param   {Object}  body    The body of the request
 * @returns {Promise}
 */
function createCollection(body) {
    return this.getJwt(this.apiToken)
        .then((response) => {
            this.jwt = response.body.token;

            return request({
                uri: `${this.instance}/${this.namespace}/collections`,
                method: 'POST',
                auth: {
                    bearer: this.jwt
                },
                body,
                json: true
            });
        });
}

/**
 * Helper function to delete a collection
 * @method deleteCollection
 * @param   {Number} [id]  Id of the collection to delete
 * @returns {Promise}
 */
function deleteCollection(id) {
    if (!id) {
        return Promise.resolve();
    }

    return request({
        uri: `${this.instance}/${this.namespace}/collections/${id}`,
        method: 'DELETE',
        auth: {
            bearer: this.jwt
        },
        json: true
    }).then((response) => {
        Assert.strictEqual(response.statusCode, 204);
    });
}

defineSupportCode(({ Before, Given, Then, When, After }) => {
    Before('@collections', function hook() {
        this.repoOrg = this.testOrg;
        this.repoName = 'functional-collections';
        this.pipelineId = null;
        this.firstCollectionId = null;
        this.secondCollectionId = null;
    });

    When(/^they create a new collection "myCollection" with that pipeline$/,
        { timeout: TIMEOUT }, function step() {
            return this.ensurePipelineExists({ repoName: this.repoName })
                .then(() => {
                    const requestBody = {
                        name: 'myCollection',
                        pipelineIds: [this.pipelineId]
                    };

                    return createCollection.call(this, requestBody);
                })
                .then((response) => {
                    Assert.strictEqual(response.statusCode, 201);
                    this.firstCollectionId = response.body.id;
                });
        });

    Then(/^they can see that collection$/, function step() {
        return request({
            uri: `${this.instance}/${this.namespace}/collections/${this.firstCollectionId}`,
            method: 'GET',
            auth: {
                bearer: this.jwt
            },
            json: true
        }).then((response) => {
            Assert.strictEqual(response.statusCode, 200);
            Assert.strictEqual(response.body.name, 'myCollection');
        });
    });

    Then(/^the collection contains that pipeline$/, function step() {
        const pipelineId = parseInt(this.pipelineId, 10);

        return request({
            uri: `${this.instance}/${this.namespace}/collections/${this.firstCollectionId}`,
            method: 'GET',
            auth: {
                bearer: this.jwt
            },
            json: true
        }).then((response) => {
            Assert.strictEqual(response.statusCode, 200);
            Assert.deepEqual(response.body.pipelineIds, [pipelineId]);
        });
    });

    When(/^they create a new collection "myCollection"$/, function step() {
        return createCollection.call(this, { name: 'myCollection' })
            .then((response) => {
                Assert.strictEqual(response.statusCode, 201);
                this.firstCollectionId = response.body.id;
            });
    });

    Then(/^the collection is empty$/, function step() {
        return request({
            uri: `${this.instance}/${this.namespace}/collections/${this.firstCollectionId}`,
            method: 'GET',
            auth: {
                bearer: this.jwt
            },
            json: true
        }).then((response) => {
            Assert.strictEqual(response.statusCode, 200);
            Assert.deepEqual(response.body.pipelineIds, []);
        });
    });

    When(/^they update the collection "myCollection" with that pipeline$/,
        { timeout: TIMEOUT }, function step() {
            return this.ensurePipelineExists({ repoName: this.repoName })
                .then(() => {
                    const pipelineId = parseInt(this.pipelineId, 10);

                    return request({
                        uri: `${this.instance}/${this.namespace}/collections/` +
                            `${this.firstCollectionId}`,
                        method: 'PUT',
                        auth: {
                            bearer: this.jwt
                        },
                        body: {
                            pipelineIds: [pipelineId]
                        },
                        json: true
                    }).then((response) => {
                        Assert.strictEqual(response.statusCode, 200);
                    });
                });
        });

    Given(/^they have a collection "myCollection"$/, function step() {
        return createCollection.call(this, { name: 'myCollection' })
            .then((response) => {
                Assert.oneOf(response.statusCode, [409, 201]);

                if (response.statusCode === 201) {
                    this.firstCollectionId = response.body.id;
                } else {
                    const str = response.body.message;

                    [, this.firstCollectionId] = str.split(': ');
                }
            });
    });

    Given(/^they have a collection "anotherCollection"$/, function step() {
        return createCollection.call(this, { name: 'anotherCollection' })
            .then((response) => {
                Assert.oneOf(response.statusCode, [409, 201]);

                if (response.statusCode === 201) {
                    this.secondCollectionId = response.body.id;
                } else {
                    const str = response.body.message;

                    [, this.secondCollectionId] = str.split(': ');
                }
            });
    });

    When(/^they fetch all their collections$/, function step() {
        return request({
            uri: `${this.instance}/${this.namespace}/collections`,
            method: 'GET',
            auth: {
                bearer: this.jwt
            },
            json: true
        }).then((response) => {
            Assert.strictEqual(response.statusCode, 200);
            this.collections = response.body;
        });
    });

    Then(/^they can see those collections$/, function step() {
        const collectionNames = this.collections.map(c => c.name);

        Assert.strictEqual(this.collections.length, 2);
        Assert.ok(collectionNames.includes('myCollection'));
        Assert.ok(collectionNames.includes('anotherCollection'));
    });

    When(/^they delete that collection$/, function step() {
        return this.ensurePipelineExists({ repoName: this.repoName })
            .then(() =>
                request({
                    uri: `${this.instance}/${this.namespace}/collections/${this.firstCollectionId}`,
                    method: 'DELETE',
                    auth: {
                        bearer: this.jwt
                    },
                    json: true
                })
            )
            .then((response) => {
                Assert.strictEqual(response.statusCode, 204);
            });
    });

    Then(/^that collection no longer exists$/, function step() {
        return request({
            uri: `${this.instance}/${this.namespace}/collections/${this.firstCollectionId}`,
            method: 'GET',
            auth: {
                bearer: this.jwt
            },
            json: true
        }).then((response) => {
            Assert.strictEqual(response.statusCode, 404);
            this.firstCollectionId = null;
        });
    });

    Then(/^that pipeline still exists$/, function step() {
        return request({
            uri: `${this.instance}/${this.namespace}/pipelines/${this.pipelineId}`,
            method: 'GET',
            auth: {
                bearer: this.jwt
            },
            json: true
        }).then((response) => {
            Assert.strictEqual(response.statusCode, 200);
            Assert.strictEqual(response.body.scmRepo.name, `${this.testOrg}/${this.repoName}`);
        });
    });

    When(/^they create another collection with the same name "myCollection"$/, function step() {
        return createCollection.call(this, { name: 'myCollection' })
            .then((response) => {
                Assert.ok(response);
                this.lastResponse = response;
            });
    });

    Then(/^they receive an error regarding unique collections$/, function step() {
        Assert.strictEqual(this.lastResponse.statusCode, 409);
        Assert.strictEqual(this.lastResponse.body.message,
            `Collection already exists with the ID: ${this.firstCollectionId}`);
    });

    After('@collections', function hook() {
        // Delete the collections created in the functional tests if they exist
        return Promise.all([
            deleteCollection.call(this, this.firstCollectionId),
            deleteCollection.call(this, this.secondCollectionId)
        ]);
    });
});
<commit_msg>fix: add timeout to collections func tests<commit_after>'use strict';

const Assert = require('chai').assert;
const request = require('../support/request');
const { defineSupportCode } = require('cucumber');

// Timeout of 15 seconds
const TIMEOUT = 15 * 1000;

/**
 * Helper function to create a collection
 * @method createCollection
 * @param   {Object}  body    The body of the request
 * @returns {Promise}
 */
function createCollection(body) {
    return this.getJwt(this.apiToken)
        .then((response) => {
            this.jwt = response.body.token;

            return request({
                uri: `${this.instance}/${this.namespace}/collections`,
                method: 'POST',
                auth: {
                    bearer: this.jwt
                },
                body,
                json: true
            });
        });
}

/**
 * Helper function to delete a collection
 * @method deleteCollection
 * @param   {Number} [id]  Id of the collection to delete
 * @returns {Promise}
 */
function deleteCollection(id) {
    if (!id) {
        return Promise.resolve();
    }

    return request({
        uri: `${this.instance}/${this.namespace}/collections/${id}`,
        method: 'DELETE',
        auth: {
            bearer: this.jwt
        },
        json: true
    }).then((response) => {
        Assert.strictEqual(response.statusCode, 204);
    });
}

defineSupportCode(({ Before, Given, Then, When, After }) => {
    Before('@collections', function hook() {
        this.repoOrg = this.testOrg;
        this.repoName = 'functional-collections';
        this.pipelineId = null;
        this.firstCollectionId = null;
        this.secondCollectionId = null;
    });

    When(/^they create a new collection "myCollection" with that pipeline$/,
        { timeout: TIMEOUT }, function step() {
            return this.ensurePipelineExists({ repoName: this.repoName })
                .then(() => {
                    const requestBody = {
                        name: 'myCollection',
                        pipelineIds: [this.pipelineId]
                    };

                    return createCollection.call(this, requestBody);
                })
                .then((response) => {
                    Assert.strictEqual(response.statusCode, 201);
                    this.firstCollectionId = response.body.id;
                });
        });

    Then(/^they can see that collection$/, { timeout: TIMEOUT }, function step() {
        return request({
            uri: `${this.instance}/${this.namespace}/collections/${this.firstCollectionId}`,
            method: 'GET',
            auth: {
                bearer: this.jwt
            },
            json: true
        }).then((response) => {
            Assert.strictEqual(response.statusCode, 200);
            Assert.strictEqual(response.body.name, 'myCollection');
        });
    });

    Then(/^the collection contains that pipeline$/, { timeout: TIMEOUT }, function step() {
        const pipelineId = parseInt(this.pipelineId, 10);

        return request({
            uri: `${this.instance}/${this.namespace}/collections/${this.firstCollectionId}`,
            method: 'GET',
            auth: {
                bearer: this.jwt
            },
            json: true
        }).then((response) => {
            Assert.strictEqual(response.statusCode, 200);
            Assert.deepEqual(response.body.pipelineIds, [pipelineId]);
        });
    });

    When(/^they create a new collection "myCollection"$/, { timeout: TIMEOUT }, function step() {
        return createCollection.call(this, { name: 'myCollection' })
            .then((response) => {
                Assert.strictEqual(response.statusCode, 201);
                this.firstCollectionId = response.body.id;
            });
    });

    Then(/^the collection is empty$/, { timeout: TIMEOUT }, function step() {
        return request({
            uri: `${this.instance}/${this.namespace}/collections/${this.firstCollectionId}`,
            method: 'GET',
            auth: {
                bearer: this.jwt
            },
            json: true
        }).then((response) => {
            Assert.strictEqual(response.statusCode, 200);
            Assert.deepEqual(response.body.pipelineIds, []);
        });
    });

    When(/^they update the collection "myCollection" with that pipeline$/,
        { timeout: TIMEOUT }, function step() {
            return this.ensurePipelineExists({ repoName: this.repoName })
                .then(() => {
                    const pipelineId = parseInt(this.pipelineId, 10);

                    return request({
                        uri: `${this.instance}/${this.namespace}/collections/` +
                            `${this.firstCollectionId}`,
                        method: 'PUT',
                        auth: {
                            bearer: this.jwt
                        },
                        body: {
                            pipelineIds: [pipelineId]
                        },
                        json: true
                    }).then((response) => {
                        Assert.strictEqual(response.statusCode, 200);
                    });
                });
        });

    Given(/^they have a collection "myCollection"$/, { timeout: TIMEOUT }, function step() {
        return createCollection.call(this, { name: 'myCollection' })
            .then((response) => {
                Assert.oneOf(response.statusCode, [409, 201]);

                if (response.statusCode === 201) {
                    this.firstCollectionId = response.body.id;
                } else {
                    const str = response.body.message;

                    [, this.firstCollectionId] = str.split(': ');
                }
            });
    });

    Given(/^they have a collection "anotherCollection"$/, { timeout: TIMEOUT }, function step() {
        return createCollection.call(this, { name: 'anotherCollection' })
            .then((response) => {
                Assert.oneOf(response.statusCode, [409, 201]);

                if (response.statusCode === 201) {
                    this.secondCollectionId = response.body.id;
                } else {
                    const str = response.body.message;

                    [, this.secondCollectionId] = str.split(': ');
                }
            });
    });

    When(/^they fetch all their collections$/, { timeout: TIMEOUT }, function step() {
        return request({
            uri: `${this.instance}/${this.namespace}/collections`,
            method: 'GET',
            auth: {
                bearer: this.jwt
            },
            json: true
        }).then((response) => {
            Assert.strictEqual(response.statusCode, 200);
            this.collections = response.body;
        });
    });

    Then(/^they can see those collections$/, function step() {
        const collectionNames = this.collections.map(c => c.name);

        Assert.strictEqual(this.collections.length, 2);
        Assert.ok(collectionNames.includes('myCollection'));
        Assert.ok(collectionNames.includes('anotherCollection'));
    });

    When(/^they delete that collection$/, function step() {
        return this.ensurePipelineExists({ repoName: this.repoName })
            .then(() =>
                request({
                    uri: `${this.instance}/${this.namespace}/collections/${this.firstCollectionId}`,
                    method: 'DELETE',
                    auth: {
                        bearer: this.jwt
                    },
                    json: true
                })
            )
            .then((response) => {
                Assert.strictEqual(response.statusCode, 204);
            });
    });

    Then(/^that collection no longer exists$/, { timeout: TIMEOUT }, function step() {
        return request({
            uri: `${this.instance}/${this.namespace}/collections/${this.firstCollectionId}`,
            method: 'GET',
            auth: {
                bearer: this.jwt
            },
            json: true
        }).then((response) => {
            Assert.strictEqual(response.statusCode, 404);
            this.firstCollectionId = null;
        });
    });

    Then(/^that pipeline still exists$/, { timeout: TIMEOUT }, function step() {
        return request({
            uri: `${this.instance}/${this.namespace}/pipelines/${this.pipelineId}`,
            method: 'GET',
            auth: {
                bearer: this.jwt
            },
            json: true
        }).then((response) => {
            Assert.strictEqual(response.statusCode, 200);
            Assert.strictEqual(response.body.scmRepo.name, `${this.testOrg}/${this.repoName}`);
        });
    });

    When(/^they create another collection with the same name "myCollection"$/,
        { timeout: TIMEOUT }, function step() {
            return createCollection.call(this, { name: 'myCollection' })
                .then((response) => {
                    Assert.ok(response);
                    this.lastResponse = response;
                });
        });

    Then(/^they receive an error regarding unique collections$/, function step() {
        Assert.strictEqual(this.lastResponse.statusCode, 409);
        Assert.strictEqual(this.lastResponse.body.message,
            `Collection already exists with the ID: ${this.firstCollectionId}`);
    });

    After('@collections', function hook() {
        // Delete the collections created in the functional tests if they exist
        return Promise.all([
            deleteCollection.call(this, this.firstCollectionId),
            deleteCollection.call(this, this.secondCollectionId)
        ]);
    });
});
<|endoftext|>


<commit_before>'use strict'

var solc = require('solc/wrapper')
var solcABI = require('solc/abi')

var webworkify = require('webworkify')

var compilerInput = require('./compiler-input')

var remixLib = require('remix-lib')
var EventManager = remixLib.EventManager

var txHelper = require('./txHelper')

/*
  trigger compilationFinished, compilerLoaded, compilationStarted, compilationDuration
*/
function Compiler (handleImportCall) {
  var self = this
  this.event = new EventManager()

  var compileJSON

  var worker = null

  var currentVersion

  var optimize = false

  this.setOptimize = function (_optimize) {
    optimize = _optimize
  }

  var compilationStartTime = null
  this.event.register('compilationFinished', (success, data, source) => {
    if (success && compilationStartTime) {
      this.event.trigger('compilationDuration', [(new Date().getTime()) - compilationStartTime])
    }
    compilationStartTime = null
  })

  this.event.register('compilationStarted', () => {
    compilationStartTime = new Date().getTime()
  })

  var internalCompile = function (files, target, missingInputs) {
    gatherImports(files, target, missingInputs, function (error, input) {
      if (error) {
        self.lastCompilationResult = null
        self.event.trigger('compilationFinished', [false, {'error': { formattedMessage: error, severity: 'error' }}, files])
      } else {
        compileJSON(input, optimize ? 1 : 0)
      }
    })
  }

  var compile = function (files, target) {
    self.event.trigger('compilationStarted', [])
    internalCompile(files, target)
  }
  this.compile = compile

  function setCompileJSON (_compileJSON) {
    compileJSON = _compileJSON
  }
  this.setCompileJSON = setCompileJSON // this is exposed for testing

  function onCompilerLoaded (version) {
    currentVersion = version
    self.event.trigger('compilerLoaded', [version])
  }

  function onInternalCompilerLoaded () {
    if (worker === null) {
      var compiler
      var userAgent = (typeof (navigator) !== 'undefined') && navigator.userAgent ? navigator.userAgent.toLowerCase() : '-'
      if (typeof (window) === 'undefined' || userAgent.indexOf(' electron/') > -1) {
        compiler = require('solc')
      } else {
        compiler = solc(window.Module)
      }

      compileJSON = function (source, optimize, cb) {
        var missingInputs = []
        var missingInputsCallback = function (path) {
          missingInputs.push(path)
          return { error: 'Deferred import' }
        }

        var result
        try {
          var input = compilerInput(source.sources, {optimize: optimize, target: source.target})
          result = compiler.compileStandardWrapper(input, missingInputsCallback)
          result = JSON.parse(result)
        } catch (exception) {
          result = { error: { formattedMessage: 'Uncaught JavaScript exception:\n' + exception, severity: 'error', mode: 'panic' } }
        }

        compilationFinished(result, missingInputs, source)
      }
      onCompilerLoaded(compiler.version())
    }
  }
  // exposed for use in node
  this.onInternalCompilerLoaded = onInternalCompilerLoaded

  this.lastCompilationResult = {
    data: null,
    source: null
  }

  /**
    * return the contract obj of the given @arg name. Uses last compilation result.
    * return null if not found
    * @param {String} name    - contract name
    * @returns contract obj and associated file: { contract, file } or null
    */
  this.getContract = (name) => {
    if (this.lastCompilationResult.data && this.lastCompilationResult.data.contracts) {
      return txHelper.getContract(name, this.lastCompilationResult.data.contracts)
    }
    return null
  }

  /**
    * call the given @arg cb (function) for all the contracts. Uses last compilation result
    * @param {Function} cb    - callback
    */
  this.visitContracts = (cb) => {
    if (this.lastCompilationResult.data && this.lastCompilationResult.data.contracts) {
      return txHelper.visitContracts(this.lastCompilationResult.data.contracts, cb)
    }
    return null
  }

  /**
    * return the compiled contracts from the last compilation result
    * @return {Object}     - contracts
    */
  this.getContracts = () => {
    if (this.lastCompilationResult.data && this.lastCompilationResult.data.contracts) {
      return this.lastCompilationResult.data.contracts
    }
    return null
  }

   /**
    * return the sources from the last compilation result
    * @param {Object} cb    - map of sources
    */
  this.getSources = () => {
    if (this.lastCompilationResult.source) {
      return this.lastCompilationResult.source.sources
    }
    return null
  }

  /**
    * return the sources @arg fileName from the last compilation result
    * @param {Object} cb    - map of sources
    */
  this.getSource = (fileName) => {
    if (this.lastCompilationResult.source) {
      return this.lastCompilationResult.source.sources[fileName]
    }
    return null
  }

  /**
    * return the source from the last compilation result that has the given index. null if source not found
    * @param {Int} index    - index of the source
    */
  this.getSourceName = (index) => {
    if (this.lastCompilationResult.data && this.lastCompilationResult.data.sources) {
      return Object.keys(this.lastCompilationResult.data.sources)[index]
    }
    return null
  }

  function compilationFinished (data, missingInputs, source) {
    var noFatalErrors = true // ie warnings are ok

    function isValidError (error) {
      // The deferred import is not a real error
      // FIXME: maybe have a better check?
      if (/Deferred import/.exec(error.message)) {
        return false
      }

      return error.severity !== 'warning'
    }

    if (data['error'] !== undefined) {
      // Ignore warnings (and the 'Deferred import' error as those are generated by us as a workaround
      if (isValidError(data['error'])) {
        noFatalErrors = false
      }
    }
    if (data['errors'] !== undefined) {
      data['errors'].forEach(function (err) {
        // Ignore warnings and the 'Deferred import' error as those are generated by us as a workaround
        if (isValidError(err)) {
          noFatalErrors = false
        }
      })
    }

    if (!noFatalErrors) {
      // There are fatal errors - abort here
      self.lastCompilationResult = null
      self.event.trigger('compilationFinished', [false, data, source])
    } else if (missingInputs !== undefined && missingInputs.length > 0) {
      // try compiling again with the new set of inputs

      internalCompile(source.sources, source.target, missingInputs)
    } else {
      data = updateInterface(data)

      self.lastCompilationResult = {
        data: data,
        source: source
      }
      self.event.trigger('compilationFinished', [true, data, source])
    }
  }

  // TODO: needs to be changed to be more node friendly
  this.loadVersion = function (usingWorker, url) {
    console.log('Loading ' + url + ' ' + (usingWorker ? 'with worker' : 'without worker'))
    self.event.trigger('loadingCompiler', [url, usingWorker])

    if (usingWorker) {
      loadWorker(url)
    } else {
      loadInternal(url)
    }
  }

  function loadInternal (url) {
    delete window.Module
    // NOTE: workaround some browsers?
    window.Module = undefined

    // Set a safe fallback until the new one is loaded
    setCompileJSON(function (source, optimize) {
      compilationFinished({ error: { formattedMessage: 'Compiler not yet loaded.' } })
    })

    var newScript = document.createElement('script')
    newScript.type = 'text/javascript'
    newScript.src = url
    document.getElementsByTagName('head')[0].appendChild(newScript)
    var check = window.setInterval(function () {
      if (!window.Module) {
        return
      }
      window.clearInterval(check)
      onInternalCompilerLoaded()
    }, 200)
  }

  function loadWorker (url) {
    if (worker !== null) {
      worker.terminate()
    }
    worker = webworkify(require('./compiler-worker.js'))
    var jobs = []
    worker.addEventListener('message', function (msg) {
      var data = msg.data
      switch (data.cmd) {
        case 'versionLoaded':
          onCompilerLoaded(data.data)
          break
        case 'compiled':
          var result
          try {
            result = JSON.parse(data.data)
          } catch (exception) {
            result = { 'error': 'Invalid JSON output from the compiler: ' + exception }
          }
          var sources = {}
          if (data.job in jobs !== undefined) {
            sources = jobs[data.job].sources
            delete jobs[data.job]
          }
          compilationFinished(result, data.missingInputs, sources)
          break
      }
    })
    worker.onerror = function (msg) {
      compilationFinished({ error: 'Worker error: ' + msg.data })
    }
    worker.addEventListener('error', function (msg) {
      compilationFinished({ error: 'Worker error: ' + msg.data })
    })
    compileJSON = function (source, optimize) {
      jobs.push({sources: source})
      worker.postMessage({cmd: 'compile', job: jobs.length - 1, input: compilerInput(source.sources, {optimize: optimize, target: source.target})})
    }
    worker.postMessage({cmd: 'loadVersion', data: url})
  }

  function gatherImports (files, target, importHints, cb) {
    importHints = importHints || []

    // FIXME: This will only match imports if the file begins with one.
    //        It should tokenize by lines and check each.
    // eslint-disable-next-line no-useless-escape
    var importRegex = /^\s*import\s*[\'\"]([^\'\"]+)[\'\"];/g

    for (var fileName in files) {
      var match
      while ((match = importRegex.exec(files[fileName].content))) {
        var importFilePath = match[1]
        if (importFilePath.startsWith('./')) {
          var path = /(.*\/).*/.exec(target)
          if (path !== null) {
            importFilePath = importFilePath.replace('./', path[1])
          } else {
            importFilePath = importFilePath.slice(2)
          }
        }

        // FIXME: should be using includes or sets, but there's also browser compatibility..
        if (importHints.indexOf(importFilePath) === -1) {
          importHints.push(importFilePath)
        }
      }
    }

    while (importHints.length > 0) {
      var m = importHints.pop()
      if (m in files) {
        continue
      }

      if (handleImportCall) {
        handleImportCall(m, function (err, content) {
          if (err) {
            cb(err)
          } else {
            files[m] = { content }
            gatherImports(files, target, importHints, cb)
          }
        })
      }

      return
    }

    cb(null, { 'sources': files, 'target': target })
  }

  function truncateVersion (version) {
    var tmp = /^(\d+.\d+.\d+)/.exec(version)
    if (tmp) {
      return tmp[1]
    }
    return version
  }

  function updateInterface (data) {
    txHelper.visitContracts(data.contracts, (contract) => {
      data.contracts[contract.file][contract.name].abi = solcABI.update(truncateVersion(currentVersion), contract.object.abi)
    })
    return data
  }
}

module.exports = Compiler
<commit_msg>Update compiler.js<commit_after>'use strict'

var solc = require('solc/wrapper')
var solcABI = require('solc/abi')

var webworkify = require('webworkify')

var compilerInput = require('./compiler-input')

var remixLib = require('remix-lib')
var EventManager = remixLib.EventManager

var txHelper = require('./txHelper')

/*
  trigger compilationFinished, compilerLoaded, compilationStarted, compilationDuration
*/
function Compiler (handleImportCall) {
  var self = this
  this.event = new EventManager()

  var compileJSON

  var worker = null

  var currentVersion

  var optimize = false

  this.setOptimize = function (_optimize) {
    optimize = _optimize
  }

  var compilationStartTime = null
  this.event.register('compilationFinished', (success, data, source) => {
    if (success && compilationStartTime) {
      this.event.trigger('compilationDuration', [(new Date().getTime()) - compilationStartTime])
    }
    compilationStartTime = null
  })

  this.event.register('compilationStarted', () => {
    compilationStartTime = new Date().getTime()
  })

  var internalCompile = function (files, target, missingInputs) {
    gatherImports(files, target, missingInputs, function (error, input) {
      if (error) {
        self.lastCompilationResult = null
        self.event.trigger('compilationFinished', [false, {'error': { formattedMessage: error, severity: 'error' }}, files])
      } else {
        compileJSON(input, optimize ? 1 : 0)
      }
    })
  }

  var compile = function (files, target) {
    self.event.trigger('compilationStarted', [])
    internalCompile(files, target)
  }
  this.compile = compile

  function setCompileJSON (_compileJSON) {
    compileJSON = _compileJSON
  }
  this.setCompileJSON = setCompileJSON // this is exposed for testing

  function onCompilerLoaded (version) {
    currentVersion = version
    self.event.trigger('compilerLoaded', [version])
  }

  function onInternalCompilerLoaded () {
    if (worker === null) {
      var compiler
      var userAgent = (typeof (navigator) !== 'undefined') && navigator.userAgent ? navigator.userAgent.toLowerCase() : '-'
      if (typeof (window) === 'undefined' || userAgent.indexOf(' electron/') > -1) {
        compiler = require('solc')
      } else {
        compiler = solc(window.Module)
      }

      compileJSON = function (source, optimize, cb) {
        var missingInputs = []
        var missingInputsCallback = function (path) {
          missingInputs.push(path)
          return { error: 'Deferred import' }
        }

        var result
        try {
          var input = compilerInput(source.sources, {optimize: optimize, target: source.target})
          result = compiler.compileStandardWrapper(input, missingInputsCallback)
          result = JSON.parse(result)
        } catch (exception) {
          result = { error: { formattedMessage: 'Uncaught JavaScript exception:\n' + exception, severity: 'error', mode: 'panic' } }
        }

        compilationFinished(result, missingInputs, source)
      }
      onCompilerLoaded(compiler.version())
    }
  }
  // exposed for use in node
  this.onInternalCompilerLoaded = onInternalCompilerLoaded

  this.lastCompilationResult = {
    data: null,
    source: null
  }

  /**
    * return the contract obj of the given @arg name. Uses last compilation result.
    * return null if not found
    * @param {String} name    - contract name
    * @returns contract obj and associated file: { contract, file } or null
    */
  this.getContract = (name) => {
    if (this.lastCompilationResult.data && this.lastCompilationResult.data.contracts) {
      return txHelper.getContract(name, this.lastCompilationResult.data.contracts)
    }
    return null
  }

  /**
    * call the given @arg cb (function) for all the contracts. Uses last compilation result
    * @param {Function} cb    - callback
    */
  this.visitContracts = (cb) => {
    if (this.lastCompilationResult.data && this.lastCompilationResult.data.contracts) {
      return txHelper.visitContracts(this.lastCompilationResult.data.contracts, cb)
    }
    return null
  }

  /**
    * return the compiled contracts from the last compilation result
    * @return {Object}     - contracts
    */
  this.getContracts = () => {
    if (this.lastCompilationResult.data && this.lastCompilationResult.data.contracts) {
      return this.lastCompilationResult.data.contracts
    }
    return null
  }

   /**
    * return the sources from the last compilation result
    * @param {Object} cb    - map of sources
    */
  this.getSources = () => {
    if (this.lastCompilationResult.source) {
      return this.lastCompilationResult.source.sources
    }
    return null
  }

  /**
    * return the sources @arg fileName from the last compilation result
    * @param {Object} cb    - map of sources
    */
  this.getSource = (fileName) => {
    if (this.lastCompilationResult.source) {
      return this.lastCompilationResult.source.sources[fileName]
    }
    return null
  }

  /**
    * return the source from the last compilation result that has the given index. null if source not found
    * @param {Int} index    - index of the source
    */
  this.getSourceName = (index) => {
    if (this.lastCompilationResult.data && this.lastCompilationResult.data.sources) {
      return Object.keys(this.lastCompilationResult.data.sources)[index]
    }
    return null
  }

  function compilationFinished (data, missingInputs, source) {
    var noFatalErrors = true // ie warnings are ok

    function isValidError (error) {
      // The deferred import is not a real error
      // FIXME: maybe have a better check?
      if (/Deferred import/.exec(error.message)) {
        return false
      }

      return error.severity !== 'warning'
    }

    if (data['error'] !== undefined) {
      // Ignore warnings (and the 'Deferred import' error as those are generated by us as a workaround
      if (isValidError(data['error'])) {
        noFatalErrors = false
      }
    }
    if (data['errors'] !== undefined) {
      data['errors'].forEach(function (err) {
        // Ignore warnings and the 'Deferred import' error as those are generated by us as a workaround
        if (isValidError(err)) {
          noFatalErrors = false
        }
      })
    }

    if (!noFatalErrors) {
      // There are fatal errors - abort here
      self.lastCompilationResult = null
      self.event.trigger('compilationFinished', [false, data, source])
    } else if (missingInputs !== undefined && missingInputs.length > 0) {
      // try compiling again with the new set of inputs

      internalCompile(source.sources, source.target, missingInputs)
    } else {
      data = updateInterface(data)

      self.lastCompilationResult = {
        data: data,
        source: source
      }
      self.event.trigger('compilationFinished', [true, data, source])
    }
  }

  // TODO: needs to be changed to be more node friendly
  this.loadVersion = function (usingWorker, url) {
    console.log('Loading ' + url + ' ' + (usingWorker ? 'with worker' : 'without worker'))
    self.event.trigger('loadingCompiler', [url, usingWorker])

    if (usingWorker) {
      loadWorker(url)
    } else {
      loadInternal(url)
    }
  }

  function loadInternal (url) {
    delete window.Module
    // NOTE: workaround some browsers?
    window.Module = undefined

    // Set a safe fallback until the new one is loaded
    setCompileJSON(function (source, optimize) {
      compilationFinished({ error: { formattedMessage: 'Compiler not yet loaded.' } })
    })

    var newScript = document.createElement('script')
    newScript.type = 'text/javascript'
    newScript.src = url
    document.getElementsByTagName('head')[0].appendChild(newScript)
    var check = window.setInterval(function () {
      if (!window.Module) {
        return
      }
      window.clearInterval(check)
      onInternalCompilerLoaded()
    }, 200)
  }

  function loadWorker (url) {
    if (worker !== null) {
      worker.terminate()
    }
    worker = webworkify(require('./compiler-worker.js'))
    var jobs = []
    worker.addEventListener('message', function (msg) {
      var data = msg.data
      switch (data.cmd) {
        case 'versionLoaded':
          onCompilerLoaded(data.data)
          break
        case 'compiled':
          var result
          try {
            result = JSON.parse(data.data)
          } catch (exception) {
            result = { 'error': 'Invalid JSON output from the compiler: ' + exception }
          }
          var sources = {}
          if (data.job in jobs !== undefined) {
            sources = jobs[data.job].sources
            delete jobs[data.job]
          }
          compilationFinished(result, data.missingInputs, sources)
          break
      }
    })
    worker.onerror = function (msg) {
      compilationFinished({ error: 'Worker error: ' + msg.data })
    }
    worker.addEventListener('error', function (msg) {
      compilationFinished({ error: 'Worker error: ' + msg.data })
    })
    compileJSON = function (source, optimize) {
      jobs.push({sources: source})
      worker.postMessage({cmd: 'compile', job: jobs.length - 1, input: compilerInput(source.sources, {optimize: optimize, target: source.target})})
    }
    worker.postMessage({cmd: 'loadVersion', data: url})
  }

  function gatherImports (files, target, importHints, cb) {
    importHints = importHints || []

    // FIXME: This will only match imports if the file begins with one.
    //        It should tokenize by lines and check each.
    // eslint-disable-next-line no-useless-escape
    var importRegex = /^\s*import\s*[\'\"]([^\'\"]+)[\'\"];/g

    for (var fileName in files) {
      var match
      while ((match = importRegex.exec(files[fileName].content))) {
        var importFilePath = match[1]
        if (importFilePath.startsWith('./')) {
          var path = /(.*\/).*/.exec(fileName)
          if (path !== null) {
            importFilePath = importFilePath.replace('./', path[1])
          } else {
            importFilePath = importFilePath.slice(2)
          }
        }

        // FIXME: should be using includes or sets, but there's also browser compatibility..
        if (importHints.indexOf(importFilePath) === -1) {
          importHints.push(importFilePath)
        }
      }
    }

    while (importHints.length > 0) {
      var m = importHints.pop()
      if (m in files) {
        continue
      }

      if (handleImportCall) {
        handleImportCall(m, function (err, content) {
          if (err) {
            cb(err)
          } else {
            files[m] = { content }
            gatherImports(files, target, importHints, cb)
          }
        })
      }

      return
    }

    cb(null, { 'sources': files, 'target': target })
  }

  function truncateVersion (version) {
    var tmp = /^(\d+.\d+.\d+)/.exec(version)
    if (tmp) {
      return tmp[1]
    }
    return version
  }

  function updateInterface (data) {
    txHelper.visitContracts(data.contracts, (contract) => {
      data.contracts[contract.file][contract.name].abi = solcABI.update(truncateVersion(currentVersion), contract.object.abi)
    })
    return data
  }
}

module.exports = Compiler
<|endoftext|>


<commit_before>// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// MIT License. See license.txt

frappe.provide("frappe.ui.form");
frappe.ui.form.Toolbar = Class.extend({
	init: function(opts) {
		$.extend(this, opts);
		this.refresh();
		this.add_update_button_on_dirty();
		this.setup_editable_title();
	},
	refresh: function() {
		this.make_menu();
		this.set_title();
		this.page.clear_user_actions();
		this.show_title_as_dirty();
		this.set_primary_action();

		if(this.frm.meta.hide_toolbar) {
			this.page.hide_menu();
		} else {
			if(this.frm.doc.__islocal) {
				this.page.hide_menu();
				this.print_icon && this.print_icon.addClass("hide");
			} else {
				this.page.show_menu();
				this.print_icon && this.print_icon.removeClass("hide");
			}
		}
	},
	set_title: function() {
		if(this.frm.meta.title_field) {
			var title = strip_html((this.frm.doc[this.frm.meta.title_field] || "").trim() || this.frm.docname);
			if(this.frm.doc.__islocal || title === this.frm.docname || this.frm.meta.autoname==="hash") {
				this.page.set_title_sub("");
			} else {
				this.page.set_title_sub(this.frm.docname);
			}
		} else {
			var title = this.frm.docname;
		}

		var me = this;
		title = __(title);
		this.page.set_title(title);
		if(this.frm.meta.title_field) {
			frappe.utils.set_title(title + " - " + this.frm.docname);
		}
		this.page.$title_area.toggleClass("editable-title",
			!!(this.is_title_editable() || this.can_rename()));

		this.set_indicator();
	},
	is_title_editable: function() {
		if (this.frm.meta.title_field==="title"
			&& this.frm.perm[0].write
			&& !this.frm.get_docfield("title").options) {
			return true;
		} else {
			return false;
		}
	},
	can_rename: function() {
		return this.frm.perm[0].write && this.frm.meta.allow_rename;
	},
	setup_editable_title: function() {
		var me = this;
		this.page.$title_area.find(".title-text").on("click", function() {
			if(me.is_title_editable()) {
				frappe.prompt({fieldname: "title", fieldtype:"Data",
					label: __("Title"), reqd: 1, "default": me.frm.doc.title },
					function(data) {
						if(data.title) {
							me.frm.set_value("title", data.title);
							if(!me.frm.doc.__islocal) {
								me.frm.save_or_update();
							} else {
								me.set_title();
							}
						}
					}, __("Edit Title"), __("Update"));
			}
			if(me.can_rename()) {
				me.frm.rename_doc();
			}
		});
	},
	get_dropdown_menu: function(label) {
		return this.page.add_dropdown(label);
	},
	set_indicator: function() {
		var indicator = frappe.get_indicator(this.frm.doc);
		if(indicator) {
			this.page.set_indicator(indicator[0], indicator[1]);
		} else {
			this.page.clear_indicator();
		}
	},
	make_menu: function() {
		this.page.clear_icons();
		this.page.clear_menu();
		var me = this;
		var p = this.frm.perm[0];
		var docstatus = cint(this.frm.doc.docstatus);
		var is_submittable = frappe.model.is_submittable(this.frm.doc.doctype)

		var print_settings = frappe.model.get_doc(":Print Settings", "Print Settings")
		var allow_print_for_draft = cint(print_settings.allow_print_for_draft);
		var allow_print_for_cancelled = cint(print_settings.allow_print_for_cancelled);

		// Print
		if(!is_submittable || docstatus == 1  ||
			(allow_print_for_cancelled && docstatus == 2)||
	 		(allow_print_for_draft && docstatus == 0)) {
			if(frappe.model.can_print(null, me.frm)) {
				this.page.add_menu_item(__("Print"), function() {
					me.frm.print_doc();}, true);
				this.print_icon = this.page.add_action_icon("fa fa-print", function() {
					me.frm.print_doc();});
			}
		}

		// email
		if(frappe.model.can_email(null, me.frm) && me.frm.doc.docstatus < 2) {
			this.page.add_menu_item(__("Email"), function() {
				me.frm.email_doc();}, true);
		}

		// Linked With
		if(!me.frm.meta.issingle) {
			this.page.add_menu_item(__('Links'), function() {
				me.show_linked_with();
			}, true)
		}

		// copy
		if(in_list(frappe.boot.user.can_create, me.frm.doctype) && !me.frm.meta.allow_copy) {
			this.page.add_menu_item(__("Duplicate"), function() {
				me.frm.copy_doc();}, true);
		}

		// rename
		if(this.can_rename()) {
			this.page.add_menu_item(__("Rename"), function() {
				me.frm.rename_doc();}, true);
		}

		// reload
		this.page.add_menu_item(__("Reload"), function() {
			me.frm.reload_doc();}, true);

		// delete
		if((cint(me.frm.doc.docstatus) != 1) && !me.frm.doc.__islocal
			&& frappe.model.can_delete(me.frm.doctype)) {
			this.page.add_menu_item(__("Delete"), function() {
				me.frm.savetrash();}, true);
		}

		if(in_list(user_roles, "System Manager")) {
			this.page.add_menu_item(__("Customize"), function() {
				frappe.set_route("Form", "Customize Form", {
					doc_type: me.frm.doctype
				})
			}, true);

			if (frappe.boot.developer_mode===1 && me.frm.meta.issingle) {
				// edit doctype
				this.page.add_menu_item(__("Edit DocType"), function() {
					frappe.set_route('Form', 'DocType', me.frm.doctype);
				}, true);
			}
		}

		// New
		if(p[CREATE] && !this.frm.meta.issingle) {
			this.page.add_menu_item(__("New {0} (Ctrl+B)", [__(me.frm.doctype)]), function() {
				frappe.new_doc(me.frm.doctype, true);}, true);
		}

	},
	can_save: function() {
		return this.get_docstatus()===0;
	},
	can_submit: function() {
		return this.get_docstatus()===0
			&& !this.frm.doc.__islocal
			&& !this.frm.doc.__unsaved
			&& this.frm.perm[0].submit
			&& !this.has_workflow();
	},
	can_update: function() {
		return this.get_docstatus()===1
			&& !this.frm.doc.__islocal
			&& this.frm.perm[0].submit
			&& this.frm.doc.__unsaved
	},
	can_cancel: function() {
		return this.get_docstatus()===1
			&& this.frm.perm[0].cancel
			&& !this.read_only
			&& !this.has_workflow();
	},
	can_amend: function() {
		return this.get_docstatus()===2
			&& this.frm.perm[0].amend
			&& !this.read_only;
	},
	has_workflow: function() {
		if(this._has_workflow === undefined)
			this._has_workflow = frappe.get_list("Workflow", {document_type: this.frm.doctype}).length;
		return this._has_workflow;
	},
	get_docstatus: function() {
		return cint(this.frm.doc.docstatus);
	},
	show_linked_with: function() {
		if(!this.frm.linked_with) {
			this.frm.linked_with = new frappe.ui.form.LinkedWith({
				frm: this.frm
			});
		}
		this.frm.linked_with.show();
	},
	set_primary_action: function(dirty) {
		if (!dirty) {
			// don't clear actions menu if dirty
			this.page.clear_user_actions();
		}

		var status = this.get_action_status();
		if (status) {
			if (status !== this.current_status) {
				this.set_page_actions(status);
			}
		} else {
			this.page.clear_actions();
		}
	},
	get_action_status: function() {
		var status = null;
		if (this.frm.page.current_view_name==='print' || this.frm.hidden) {
			status = "Edit";
		} else if (this.can_submit()) {
			status = "Submit";
		} else if (this.can_save()) {
			if (!this.frm.save_disabled) {
				status = "Save";
			}
		} else if (this.can_update()) {
			status = "Update";
		} else if (this.can_cancel()) {
			status = "Cancel";
		} else if (this.can_amend()) {
			status = "Amend";
		}
		return status;
	},
	set_page_actions: function(status) {
		var me = this;
		this.page.clear_actions();

		if(status!== 'Edit') {
			var perm_to_check = this.frm.action_perm_type_map[status];
			if(!this.frm.perm[0][perm_to_check]) {
				return;
			}
		}

		if(status === "Edit") {
			this.page.set_primary_action(__("Edit"), function() {
				me.frm.page.set_view('main');
				me.frm.set_hidden(false);
			}, 'octicon octicon-pencil');
		} else if(status === "Cancel") {
			this.page.set_secondary_action(__(status), function() {
				me.frm.savecancel(this);
			}, "octicon octicon-circle-slash");
		} else {
			var click = {
				"Save": function() {
					me.frm.save('Save', null, this);
				},
				"Submit": function() {
					me.frm.savesubmit(this);
				},
				"Update": function() {
					me.frm.save('Update', null, this);
				},
				"Amend": function() {
					me.frm.amend_doc();
				}
			}[status];

			var icon = {
				"Save": "octicon octicon-check",
				"Submit": "octicon octicon-lock",
				"Update": "octicon octicon-check",
				"Amend": "octicon octicon-split"
			}[status];

			this.page.set_primary_action(__(status), click, icon);
		}

		this.current_status = status;
	},
	make_cancel_amend_button: function() {
		var me = this;
		var docstatus = cint(this.frm.doc.docstatus);
		var p = this.frm.perm[0];
		var has_workflow = this.has_workflow();

		if(has_workflow) {
			return;
		} else if(docstatus==1 && p[CANCEL]) {
			this.page.set_secondary_action(__('Cancel'), function() {
				me.frm.savecancel(this) }, 'fa fa-ban-circle');
		} else if(docstatus==2 && p[AMEND]) {
			this.page.set_secondary_action(__('Amend'), function() {
				me.frm.amend_doc() }, 'fa fa-pencil', true);
		}
	},
	add_update_button_on_dirty: function() {
		var me = this;
		$(this.frm.wrapper).on("dirty", function() {
			me.show_title_as_dirty();

			// clear workflow actions
			me.frm.page.clear_actions_menu();

			// enable save action
			if(!me.frm.save_disabled) {
				me.set_primary_action(true);
			}
		});
	},
	show_title_as_dirty: function() {
		if(this.frm.save_disabled)
			return;

		if(this.frm.doc.__unsaved) {
			this.page.set_indicator(__("Not Saved"), "orange");
		}

		$(this.frm.wrapper).attr("data-state", this.frm.doc.__unsaved ? "dirty" : "clean");
	}
})
<commit_msg>[fix] show action after duplicate having no action (#2681)<commit_after>// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// MIT License. See license.txt

frappe.provide("frappe.ui.form");
frappe.ui.form.Toolbar = Class.extend({
	init: function(opts) {
		$.extend(this, opts);
		this.refresh();
		this.add_update_button_on_dirty();
		this.setup_editable_title();
	},
	refresh: function() {
		this.make_menu();
		this.set_title();
		this.page.clear_user_actions();
		this.show_title_as_dirty();
		this.set_primary_action();

		if(this.frm.meta.hide_toolbar) {
			this.page.hide_menu();
		} else {
			if(this.frm.doc.__islocal) {
				this.page.hide_menu();
				this.print_icon && this.print_icon.addClass("hide");
			} else {
				this.page.show_menu();
				this.print_icon && this.print_icon.removeClass("hide");
			}
		}
	},
	set_title: function() {
		if(this.frm.meta.title_field) {
			var title = strip_html((this.frm.doc[this.frm.meta.title_field] || "").trim() || this.frm.docname);
			if(this.frm.doc.__islocal || title === this.frm.docname || this.frm.meta.autoname==="hash") {
				this.page.set_title_sub("");
			} else {
				this.page.set_title_sub(this.frm.docname);
			}
		} else {
			var title = this.frm.docname;
		}

		var me = this;
		title = __(title);
		this.page.set_title(title);
		if(this.frm.meta.title_field) {
			frappe.utils.set_title(title + " - " + this.frm.docname);
		}
		this.page.$title_area.toggleClass("editable-title",
			!!(this.is_title_editable() || this.can_rename()));

		this.set_indicator();
	},
	is_title_editable: function() {
		if (this.frm.meta.title_field==="title"
			&& this.frm.perm[0].write
			&& !this.frm.get_docfield("title").options) {
			return true;
		} else {
			return false;
		}
	},
	can_rename: function() {
		return this.frm.perm[0].write && this.frm.meta.allow_rename;
	},
	setup_editable_title: function() {
		var me = this;
		this.page.$title_area.find(".title-text").on("click", function() {
			if(me.is_title_editable()) {
				frappe.prompt({fieldname: "title", fieldtype:"Data",
					label: __("Title"), reqd: 1, "default": me.frm.doc.title },
					function(data) {
						if(data.title) {
							me.frm.set_value("title", data.title);
							if(!me.frm.doc.__islocal) {
								me.frm.save_or_update();
							} else {
								me.set_title();
							}
						}
					}, __("Edit Title"), __("Update"));
			}
			if(me.can_rename()) {
				me.frm.rename_doc();
			}
		});
	},
	get_dropdown_menu: function(label) {
		return this.page.add_dropdown(label);
	},
	set_indicator: function() {
		var indicator = frappe.get_indicator(this.frm.doc);
		if(indicator) {
			this.page.set_indicator(indicator[0], indicator[1]);
		} else {
			this.page.clear_indicator();
		}
	},
	make_menu: function() {
		this.page.clear_icons();
		this.page.clear_menu();
		var me = this;
		var p = this.frm.perm[0];
		var docstatus = cint(this.frm.doc.docstatus);
		var is_submittable = frappe.model.is_submittable(this.frm.doc.doctype)

		var print_settings = frappe.model.get_doc(":Print Settings", "Print Settings")
		var allow_print_for_draft = cint(print_settings.allow_print_for_draft);
		var allow_print_for_cancelled = cint(print_settings.allow_print_for_cancelled);

		// Print
		if(!is_submittable || docstatus == 1  ||
			(allow_print_for_cancelled && docstatus == 2)||
	 		(allow_print_for_draft && docstatus == 0)) {
			if(frappe.model.can_print(null, me.frm)) {
				this.page.add_menu_item(__("Print"), function() {
					me.frm.print_doc();}, true);
				this.print_icon = this.page.add_action_icon("fa fa-print", function() {
					me.frm.print_doc();});
			}
		}

		// email
		if(frappe.model.can_email(null, me.frm) && me.frm.doc.docstatus < 2) {
			this.page.add_menu_item(__("Email"), function() {
				me.frm.email_doc();}, true);
		}

		// Linked With
		if(!me.frm.meta.issingle) {
			this.page.add_menu_item(__('Links'), function() {
				me.show_linked_with();
			}, true)
		}

		// copy
		if(in_list(frappe.boot.user.can_create, me.frm.doctype) && !me.frm.meta.allow_copy) {
			this.page.add_menu_item(__("Duplicate"), function() {
				me.frm.copy_doc();}, true);
		}

		// rename
		if(this.can_rename()) {
			this.page.add_menu_item(__("Rename"), function() {
				me.frm.rename_doc();}, true);
		}

		// reload
		this.page.add_menu_item(__("Reload"), function() {
			me.frm.reload_doc();}, true);

		// delete
		if((cint(me.frm.doc.docstatus) != 1) && !me.frm.doc.__islocal
			&& frappe.model.can_delete(me.frm.doctype)) {
			this.page.add_menu_item(__("Delete"), function() {
				me.frm.savetrash();}, true);
		}

		if(in_list(user_roles, "System Manager")) {
			this.page.add_menu_item(__("Customize"), function() {
				frappe.set_route("Form", "Customize Form", {
					doc_type: me.frm.doctype
				})
			}, true);

			if (frappe.boot.developer_mode===1 && me.frm.meta.issingle) {
				// edit doctype
				this.page.add_menu_item(__("Edit DocType"), function() {
					frappe.set_route('Form', 'DocType', me.frm.doctype);
				}, true);
			}
		}

		// New
		if(p[CREATE] && !this.frm.meta.issingle) {
			this.page.add_menu_item(__("New {0} (Ctrl+B)", [__(me.frm.doctype)]), function() {
				frappe.new_doc(me.frm.doctype, true);}, true);
		}

	},
	can_save: function() {
		return this.get_docstatus()===0;
	},
	can_submit: function() {
		return this.get_docstatus()===0
			&& !this.frm.doc.__islocal
			&& !this.frm.doc.__unsaved
			&& this.frm.perm[0].submit
			&& !this.has_workflow();
	},
	can_update: function() {
		return this.get_docstatus()===1
			&& !this.frm.doc.__islocal
			&& this.frm.perm[0].submit
			&& this.frm.doc.__unsaved
	},
	can_cancel: function() {
		return this.get_docstatus()===1
			&& this.frm.perm[0].cancel
			&& !this.read_only
			&& !this.has_workflow();
	},
	can_amend: function() {
		return this.get_docstatus()===2
			&& this.frm.perm[0].amend
			&& !this.read_only;
	},
	has_workflow: function() {
		if(this._has_workflow === undefined)
			this._has_workflow = frappe.get_list("Workflow", {document_type: this.frm.doctype}).length;
		return this._has_workflow;
	},
	get_docstatus: function() {
		return cint(this.frm.doc.docstatus);
	},
	show_linked_with: function() {
		if(!this.frm.linked_with) {
			this.frm.linked_with = new frappe.ui.form.LinkedWith({
				frm: this.frm
			});
		}
		this.frm.linked_with.show();
	},
	set_primary_action: function(dirty) {
		if (!dirty) {
			// don't clear actions menu if dirty
			this.page.clear_user_actions();
		}

		var status = this.get_action_status();
		if (status) {
			if (status !== this.current_status) {
				this.set_page_actions(status);
			}
		} else {
			this.page.clear_actions();
			this.current_status = null
		}
	},
	get_action_status: function() {
		var status = null;
		if (this.frm.page.current_view_name==='print' || this.frm.hidden) {
			status = "Edit";
		} else if (this.can_submit()) {
			status = "Submit";
		} else if (this.can_save()) {
			if (!this.frm.save_disabled) {
				status = "Save";
			}
		} else if (this.can_update()) {
			status = "Update";
		} else if (this.can_cancel()) {
			status = "Cancel";
		} else if (this.can_amend()) {
			status = "Amend";
		}
		return status;
	},
	set_page_actions: function(status) {
		var me = this;
		this.page.clear_actions();

		if(status!== 'Edit') {
			var perm_to_check = this.frm.action_perm_type_map[status];
			if(!this.frm.perm[0][perm_to_check]) {
				return;
			}
		}

		if(status === "Edit") {
			this.page.set_primary_action(__("Edit"), function() {
				me.frm.page.set_view('main');
				me.frm.set_hidden(false);
			}, 'octicon octicon-pencil');
		} else if(status === "Cancel") {
			this.page.set_secondary_action(__(status), function() {
				me.frm.savecancel(this);
			}, "octicon octicon-circle-slash");
		} else {
			var click = {
				"Save": function() {
					me.frm.save('Save', null, this);
				},
				"Submit": function() {
					me.frm.savesubmit(this);
				},
				"Update": function() {
					me.frm.save('Update', null, this);
				},
				"Amend": function() {
					me.frm.amend_doc();
				}
			}[status];

			var icon = {
				"Save": "octicon octicon-check",
				"Submit": "octicon octicon-lock",
				"Update": "octicon octicon-check",
				"Amend": "octicon octicon-split"
			}[status];

			this.page.set_primary_action(__(status), click, icon);
		}

		this.current_status = status;
	},
	make_cancel_amend_button: function() {
		var me = this;
		var docstatus = cint(this.frm.doc.docstatus);
		var p = this.frm.perm[0];
		var has_workflow = this.has_workflow();

		if(has_workflow) {
			return;
		} else if(docstatus==1 && p[CANCEL]) {
			this.page.set_secondary_action(__('Cancel'), function() {
				me.frm.savecancel(this) }, 'fa fa-ban-circle');
		} else if(docstatus==2 && p[AMEND]) {
			this.page.set_secondary_action(__('Amend'), function() {
				me.frm.amend_doc() }, 'fa fa-pencil', true);
		}
	},
	add_update_button_on_dirty: function() {
		var me = this;
		$(this.frm.wrapper).on("dirty", function() {
			me.show_title_as_dirty();

			// clear workflow actions
			me.frm.page.clear_actions_menu();

			// enable save action
			if(!me.frm.save_disabled) {
				me.set_primary_action(true);
			}
		});
	},
	show_title_as_dirty: function() {
		if(this.frm.save_disabled)
			return;

		if(this.frm.doc.__unsaved) {
			this.page.set_indicator(__("Not Saved"), "orange");
		}

		$(this.frm.wrapper).attr("data-state", this.frm.doc.__unsaved ? "dirty" : "clean");
	}
})
<|endoftext|>


<commit_before>import toGeoJSON from '@mapbox/togeojson';
import osmtogeojson from 'osmtogeojson';

import fm from '../../app';

fm.app.factory("fmMapSearchFiles", function($rootScope, $compile, fmUtils) {
	return function(map, fmMapSearch) {
		const fmMapSearchFiles = {
			parseFiles(files) {
				var ret = {features: [ ], views: [ ], types: { }};
				var errors = false;
				var nextTypeIdx = 1;
				files.forEach(function(file) {
					var geojson = null;

					if(file.match(/^\s*</)) {
						var doc = $.parseXML(file);
						var xml = $(doc).find(":root");

						if(xml.is("gpx"))
							geojson = toGeoJSON.gpx(xml[0]);
						else if(xml.is("kml"))
							geojson = toGeoJSON.kml(xml[0]);
						else if(xml.is("osm"))
							geojson = osmtogeojson(doc);
					} else if(file.match(/^\s*\{/)) {
						var content = JSON.parse(file);
						if(content.type)
							geojson = content;
					}

					if(geojson == null)
						return errors = true;

					var typeMapping = {};

					if(geojson.facilmap) {
						if(geojson.facilmap.types) {
							for(let i in geojson.facilmap.types) {
								typeMapping[i] = nextTypeIdx++;
								ret.types[typeMapping[i]] = geojson.facilmap.types[i];
							}
						}

						if(geojson.facilmap.views)
							ret.views.push(...geojson.facilmap.views);
					}

					var features;
					if(geojson.type == "FeatureCollection")
						features = geojson.features || [ ];
					else if(geojson.type == "Feature")
						features = [ geojson ];
					else
						features = [ { type: "Feature", geometry: geojson, properties: { } } ];

					features.forEach(function(feature) {
						var name;

						if(typeof feature.properties != "object")
							feature.properties = { };

						if(feature.properties.name)
							name = feature.properties.name;
						else if(feature.properties.tags.name)
							name = feature.properties.tags.name;
						else if(feature.properties.type)
							name = feature.properties.type + " " + feature.properties.id;
						else if([ "Polygon", "MultiPolygon" ].indexOf(feature.geometry.type) != -1)
							name = "Polygon";
						else if([ "LineString", "MultiLineString" ].indexOf(feature.geometry.type) != -1)
							name = "Line";
						else if([ "Point", "MultiPoint" ].indexOf(feature.geometry.type) != -1)
							name = "Point";
						else
							name = feature.geometry.type || "Object";

						let f = {
							short_name: name,
							display_name: name,
							extratags: feature.properties.data || feature.properties.tags || fmUtils.flattenObject(feature.properties),
							geojson: feature.geometry,
							type: feature.properties.type || feature.geometry.type
						};

						if(geojson.facilmap) {
							if(feature.properties.typeId && typeMapping[feature.properties.typeId])
								f.fmTypeId = typeMapping[feature.properties.typeId];
							f.fmProperties = feature.properties;
						}

						ret.features.push(f);
					});
				});

				if(errors)
					return map.messages.showMessage("danger", "Some files could not be parsed.");

				return ret;
			}
		};

		return fmMapSearchFiles;
	};
});<commit_msg>Remove huge coordTimes object from GPX search popup<commit_after>import toGeoJSON from '@mapbox/togeojson';
import osmtogeojson from 'osmtogeojson';

import fm from '../../app';

fm.app.factory("fmMapSearchFiles", function($rootScope, $compile, fmUtils) {
	return function(map, fmMapSearch) {
		const fmMapSearchFiles = {
			parseFiles(files) {
				var ret = {features: [ ], views: [ ], types: { }};
				var errors = false;
				var nextTypeIdx = 1;
				files.forEach(function(file) {
					var geojson = null;

					if(file.match(/^\s*</)) {
						var doc = $.parseXML(file);
						var xml = $(doc).find(":root");

						if(xml.is("gpx"))
							geojson = toGeoJSON.gpx(xml[0]);
						else if(xml.is("kml"))
							geojson = toGeoJSON.kml(xml[0]);
						else if(xml.is("osm"))
							geojson = osmtogeojson(doc);
					} else if(file.match(/^\s*\{/)) {
						var content = JSON.parse(file);
						if(content.type)
							geojson = content;
					}

					if(geojson == null)
						return errors = true;

					var typeMapping = {};

					if(geojson.facilmap) {
						if(geojson.facilmap.types) {
							for(let i in geojson.facilmap.types) {
								typeMapping[i] = nextTypeIdx++;
								ret.types[typeMapping[i]] = geojson.facilmap.types[i];
							}
						}

						if(geojson.facilmap.views)
							ret.views.push(...geojson.facilmap.views);
					}

					var features;
					if(geojson.type == "FeatureCollection")
						features = geojson.features || [ ];
					else if(geojson.type == "Feature")
						features = [ geojson ];
					else
						features = [ { type: "Feature", geometry: geojson, properties: { } } ];

					features.forEach(function(feature) {
						var name;

						if(typeof feature.properties != "object")
							feature.properties = { };

						if(feature.properties.name)
							name = feature.properties.name;
						else if(feature.properties.tags.name)
							name = feature.properties.tags.name;
						else if(feature.properties.type)
							name = feature.properties.type + " " + feature.properties.id;
						else if([ "Polygon", "MultiPolygon" ].indexOf(feature.geometry.type) != -1)
							name = "Polygon";
						else if([ "LineString", "MultiLineString" ].indexOf(feature.geometry.type) != -1)
							name = "Line";
						else if([ "Point", "MultiPoint" ].indexOf(feature.geometry.type) != -1)
							name = "Point";
						else
							name = feature.geometry.type || "Object";

						let f = {
							short_name: name,
							display_name: name,
							extratags: feature.properties.data || feature.properties.tags || fmUtils.flattenObject(Object.assign({}, feature.properties, {coordTimes: null})),
							geojson: feature.geometry,
							type: feature.properties.type || feature.geometry.type
						};

						if(geojson.facilmap) {
							if(feature.properties.typeId && typeMapping[feature.properties.typeId])
								f.fmTypeId = typeMapping[feature.properties.typeId];
							f.fmProperties = feature.properties;
						}

						ret.features.push(f);
					});
				});

				if(errors)
					return map.messages.showMessage("danger", "Some files could not be parsed.");

				return ret;
			}
		};

		return fmMapSearchFiles;
	};
});<|endoftext|>


<commit_before>import i18n from '@/i18n'
import { DesktopUtils } from '@/utils/desktopsUtils'
import axios from 'axios'
import { orderBy } from 'lodash'
import { apiV3Segment } from '../../shared/constants'
import { ErrorUtils } from '../../utils/errorUtils'

const getDefaultState = () => {
  return {
    templates: [],
    templates_loaded: false
  }
}

const state = getDefaultState()

export default {
  state,
  getters: {
    getTemplates: state => {
      return state.templates
    },
    getTemplatesLoaded: state => {
      return state.templates_loaded
    }
  },
  mutations: {
    resetTemplatesState: (state) => {
      Object.assign(state, getDefaultState())
    },
    setTemplates: (state, templates) => {
      state.templates = templates
      state.templates_loaded = true
    },
    update_templates: (state, template) => {
      const item = state.templates.find(t => t.id === template.id)
      if (item) {
        Object.assign(item, template)
      }
    },
    setTemplatesLoaded: (state, templatesLoaded) => {
      state.templates_loaded = templatesLoaded
    }
  },
  actions: {
    resetTemplatesState (context) {
      context.commit('resetTemplatesState')
    },
    fetchTemplates ({ commit }) {
      axios.get(`${apiV3Segment}/user/templates`).then(response => {
        commit('setTemplates', DesktopUtils.parseTemplates(orderBy(response.data, ['editable'], ['desc'])))
      }).catch(e => {
        ErrorUtils.handleErrors(e, this._vm.$snotify)
      })
    },
    fetchAllowedTemplates ({ commit }) {
      axios.get(`${apiV3Segment}/user/templates_allowed`).then(response => {
        commit('setTemplates', DesktopUtils.parseTemplates(orderBy(response.data, ['editable'], ['desc'])))
      }).catch(e => {
        ErrorUtils.handleErrors(e, this._vm.$snotify)
      })
    },
    toggleEnabled (context, payload) {
      ErrorUtils.showInfoMessage(this._vm.$snotify, i18n.t(payload.enabled ? 'messages.info.disable-template' : 'messages.info.enable-template'), '', true, 1000)
      axios.put(`${apiV3Segment}/template/update`, payload).then(response => {
        this._vm.$snotify.clear()
        context.commit('update_templates', DesktopUtils.parseTemplate(response.data))
      }).catch(e => {
        ErrorUtils.handleErrors(e, this._vm.$snotify)
      })
    },
    setTemplatesLoaded (context, templatesLoaded) {
      context.commit('setTemplatesLoaded', templatesLoaded)
    }
  }
}
<commit_msg>fix(frontend): new templates allowed url endpoint<commit_after>import i18n from '@/i18n'
import { DesktopUtils } from '@/utils/desktopsUtils'
import axios from 'axios'
import { orderBy } from 'lodash'
import { apiV3Segment } from '../../shared/constants'
import { ErrorUtils } from '../../utils/errorUtils'

const getDefaultState = () => {
  return {
    templates: [],
    templates_loaded: false
  }
}

const state = getDefaultState()

export default {
  state,
  getters: {
    getTemplates: state => {
      return state.templates
    },
    getTemplatesLoaded: state => {
      return state.templates_loaded
    }
  },
  mutations: {
    resetTemplatesState: (state) => {
      Object.assign(state, getDefaultState())
    },
    setTemplates: (state, templates) => {
      state.templates = templates
      state.templates_loaded = true
    },
    update_templates: (state, template) => {
      const item = state.templates.find(t => t.id === template.id)
      if (item) {
        Object.assign(item, template)
      }
    },
    setTemplatesLoaded: (state, templatesLoaded) => {
      state.templates_loaded = templatesLoaded
    }
  },
  actions: {
    resetTemplatesState (context) {
      context.commit('resetTemplatesState')
    },
    fetchTemplates ({ commit }) {
      axios.get(`${apiV3Segment}/user/templates`).then(response => {
        commit('setTemplates', DesktopUtils.parseTemplates(orderBy(response.data, ['editable'], ['desc'])))
      }).catch(e => {
        ErrorUtils.handleErrors(e, this._vm.$snotify)
      })
    },
    fetchAllowedTemplates ({ commit }) {
      axios.get(`${apiV3Segment}/user/templates/allowed`).then(response => {
        commit('setTemplates', DesktopUtils.parseTemplates(orderBy(response.data, ['editable'], ['desc'])))
      }).catch(e => {
        ErrorUtils.handleErrors(e, this._vm.$snotify)
      })
    },
    toggleEnabled (context, payload) {
      ErrorUtils.showInfoMessage(this._vm.$snotify, i18n.t(payload.enabled ? 'messages.info.disable-template' : 'messages.info.enable-template'), '', true, 1000)
      axios.put(`${apiV3Segment}/template/update`, payload).then(response => {
        this._vm.$snotify.clear()
        context.commit('update_templates', DesktopUtils.parseTemplate(response.data))
      }).catch(e => {
        ErrorUtils.handleErrors(e, this._vm.$snotify)
      })
    },
    setTemplatesLoaded (context, templatesLoaded) {
      context.commit('setTemplatesLoaded', templatesLoaded)
    }
  }
}
<|endoftext|>


<commit_before>/* global smallScreenNav:readonly, navAccess:readonly */

/* =========================================================================== *\
    Global Javascript for all pages
\* =========================================================================== */

// Initialization
$(() => {
    smallScreenNav.init();
    navAccess.init();

    // Back to top link handler
    const link = document.querySelector('.js-btop');
    link.addEventListener('click', (e) => {
        e.preventDefault();
        e.stopPropagation();
        window.scrollTo({
            top: 0,
            left: 0,
            behavior: 'smooth',
        });
    });
});
<commit_msg>Update main.js start syntax<commit_after>/* global smallScreenNav:readonly, navAccess:readonly */

/* =========================================================================== *\
    Global Javascript for all pages
\* =========================================================================== */

// Initialization
document.onreadystatechange = function () {
    smallScreenNav.init();
    navAccess.init();

    // Back to top link handler
    const link = document.querySelector('.js-btop');
    link.addEventListener('click', (e) => {
        e.preventDefault();
        e.stopPropagation();
        window.scrollTo({
            top: 0,
            left: 0,
            behavior: 'smooth',
        });
    });
};
<|endoftext|>


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

    grunt.registerTask('process-styles', [
        <% if (useLess) { %>'less:main',/*pre-process */<% } %><% if (useSass) { %>'sass:main',/*pre-process */<% } %>
        'postcss'   /*post-process*/
    ]);
    grunt.registerTask('precompile-templates', [
        <% if (useHandlebars) { %>'handlebars:main'<% } else { %>'jst:main'<% } %>
    ]);
    grunt.registerTask('bundle-scripts', [<% if (useBrowserify) { %>
        'browserify:bundle',
        'uglify:bundle'<% } else { %>
        'requirejs:bundle'<% } %>
    ]);
    grunt.registerTask('compile', [
        'clean:compile',
        'process-styles',
        'precompile-templates'
    ]);
    grunt.registerTask('build', [
        'clean:build',
        'compile',
        'bundle-scripts',
        'htmlmin',<% if (useBrowserify) { %>
        'replace:bundle-url',<% } %>
        <% if (props.compressImages) { %>'imagemin:build',<% } else { %>'copy:images',<% } %>
        'copy:fonts'
    ]);
    grunt.registerTask('demo', 'Build code and open in browser', [
        'build',
        'open:demo',
        'express:demo'
    ]);
    grunt.registerTask('docs', 'Generate documentation with JSDoc3', [
        'clean:docs',
        'jsdoc:app',
        'open:docs'<% if (generateStyleguide) { %>,
        <% if (useLess) { %>'less:main',/*pre-process */<% } %><% if (useSass) { %>'sass:main',/*pre-process */<% } %>
        'postcss:styleguide',
        'open:styleguide'<% } %>
    ]);
    grunt.registerTask('reports', 'Generate code coverage, plato report and documentation - then open all in browser', [
        'plato',
        'cover',
        'open:plato',
        'open:coverage'
    ]);
};
<commit_msg>Removed auto open in docs task<commit_after>module.exports = function(grunt) {
    'use strict';

    grunt.registerTask('process-styles', [
        <% if (useLess) { %>'less:main',/*pre-process */<% } %><% if (useSass) { %>'sass:main',/*pre-process */<% } %>
        'postcss'   /*post-process*/
    ]);
    grunt.registerTask('precompile-templates', [
        <% if (useHandlebars) { %>'handlebars:main'<% } else { %>'jst:main'<% } %>
    ]);
    grunt.registerTask('bundle-scripts', [<% if (useBrowserify) { %>
        'browserify:bundle',
        'uglify:bundle'<% } else { %>
        'requirejs:bundle'<% } %>
    ]);
    grunt.registerTask('compile', [
        'clean:compile',
        'process-styles',
        'precompile-templates'
    ]);
    grunt.registerTask('build', [
        'clean:build',
        'compile',
        'bundle-scripts',
        'htmlmin',<% if (useBrowserify) { %>
        'replace:bundle-url',<% } %>
        <% if (props.compressImages) { %>'imagemin:build',<% } else { %>'copy:images',<% } %>
        'copy:fonts'
    ]);
    grunt.registerTask('demo', 'Build code and open in browser', [
        'build',
        'open:demo',
        'express:demo'
    ]);
    grunt.registerTask('docs', 'Generate documentation with JSDoc3', [
        'clean:docs',
        'jsdoc:app',<% if (generateStyleguide) { %>,
        <% if (useLess) { %>'less:main',/*pre-process */<% } %><% if (useSass) { %>'sass:main',/*pre-process */<% } %>
        'postcss:styleguide'<% } %>
    ]);
    grunt.registerTask('reports', 'Generate code coverage, plato report and documentation - then open all in browser', [
        'plato',
        'cover',
        'open:plato',
        'open:coverage'
    ]);
};
<|endoftext|>


<commit_before>// Generated on <%= (new Date).toISOString().split('T')[0] %> using <%= packagejs.name %> <%= packagejs.version %>
'use strict';

var gulp = require('gulp'),
    prefix = require('gulp-autoprefixer'),
    cssnano = require('gulp-cssnano'),
    usemin = require('gulp-usemin'),
    uglify = require('gulp-uglify'),<% if(useSass) { %>
    expect = require('gulp-expect-file'),
    sass = require('gulp-sass'),<% } %>
    htmlmin = require('gulp-htmlmin'),
    imagemin = require('gulp-imagemin'),
    ngAnnotate = require('gulp-ng-annotate'),
    ngConstant = require('gulp-ng-constant-fork'),
    eslint = require('gulp-eslint'),
    rev = require('gulp-rev'),<% if (testFrameworks.indexOf('protractor') > -1) { %>
    protractor = require('gulp-protractor').protractor,<% } %>
    es = require('event-stream'),
    flatten = require('gulp-flatten'),
    del = require('del'),
    wiredep = require('wiredep').stream,
    runSequence = require('run-sequence'),
    browserSync = require('browser-sync'),
    sourcemaps = require('gulp-sourcemaps'),
    KarmaServer = require('karma').Server,
    plumber = require('gulp-plumber'),
    changed = require('gulp-changed'),
    handleErrors = require('./gulp/handleErrors'),
    serve = require('./gulp/serve'),
    util = require('./gulp/utils'),
    gulpIf = require('gulp-if'),
    footer = require('gulp-footer');

var config = {
    app: '<%= MAIN_SRC_DIR %>',
    dist: '<%= MAIN_SRC_DIR %>dist/',
    test: '<%= TEST_SRC_DIR %>'<% if(useSass) { %>,
    importPath: '<%= MAIN_SRC_DIR %>bower_components',
    scss: '<%= MAIN_SRC_DIR %>scss/',
    sassFiles: '<%= MAIN_SRC_DIR %>scss/**/*.{scss,sass}',
    cssDir: '<%= MAIN_SRC_DIR %>content/css'<% } %>
};

gulp.task('clean', function () {
    return del([config.dist]);
});

gulp.task('test', ['wiredep:test', 'ngconstant:dev'], function (done) {
    new KarmaServer({
        configFile: __dirname + '/' + config.test + 'karma.conf.js',
        singleRun: true
    }, done).start();
});
<% if (testFrameworks.indexOf('protractor') > -1) { %>
gulp.task('protractor', function () {
    return gulp.src([config.test + 'e2e/**/*.js'])
        .pipe(plumber({errorHandler: handleErrors}))
        .pipe(protractor({
            configFile: config.test + 'protractor.conf.js'
        }));
});<% } %>

gulp.task('copy', function () {
    return es.merge( <% if(enableTranslation) { %> // copy i18n folders only if translation is enabled
        gulp.src(config.app + 'i18n/**')
        .pipe(plumber({errorHandler: handleErrors}))
        .pipe(changed(config.dist + 'i18n/'))
        .pipe(gulp.dest(config.dist + 'i18n/')),<% } %>
        gulp.src(config.app + 'bower_components/bootstrap/fonts/*.*')
        .pipe(plumber({errorHandler: handleErrors}))
        .pipe(changed(config.dist + 'content/fonts/'))
        .pipe(gulp.dest(config.dist + 'content/fonts/')),
        gulp.src(config.app + 'content/**/*.{woff,svg,ttf,eot}')
        .pipe(plumber({errorHandler: handleErrors}))
        .pipe(changed(config.dist + 'content/fonts/'))
        .pipe(flatten())
        .pipe(gulp.dest(config.dist + 'content/fonts/')));
});

gulp.task('images', function () {
    return gulp.src(config.app + 'content/images/**')
        .pipe(plumber({errorHandler: handleErrors}))
        .pipe(changed(config.dist + 'content/images'))
        .pipe(imagemin({optimizationLevel: 5}))
        .pipe(gulp.dest(config.dist + 'content/images'))
        .pipe(browserSync.reload({stream: true}));
});
<% if(useSass) { %>
gulp.task('sass', function () {
    return gulp.src(config.sassFiles)
        .pipe(plumber({errorHandler: handleErrors}))
        .pipe(expect(config.sassFiles))
        .pipe(changed(config.cssDir, {extension: '.css'}))
        .pipe(sass({includePaths:config.importPath}).on('error', sass.logError))
        .pipe(gulp.dest(config.cssDir));
});
<% } %>
gulp.task('styles', [<% if(useSass) { %>'sass'<% } %>], function () {
    return gulp.src(config.app + 'content/css')
        .pipe(browserSync.reload({stream: true}));
});

gulp.task('install', function (done) {
    runSequence('wiredep', 'ngconstant:dev'<% if(useSass) { %>, 'sass'<% } %>, done);
});

gulp.task('serve', function () {
    runSequence('install', serve);
});

gulp.task('watch', function () {
    gulp.watch('bower.json', ['wiredep']);
    gulp.watch(['gulpfile.js', <% if(buildTool == 'maven') { %>'pom.xml'<% } else { %>'build.gradle'<% } %>], ['ngconstant:dev']);
    gulp.watch(<% if(useSass) { %>config.scss + '**/*.{scss,sass}'<% } else { %>config.app + 'content/css/**/*.css'<% } %>, ['styles']);
    gulp.watch(config.app + 'content/images/**', ['images']);
    gulp.watch(config.app + 'app/**/*.js', ['eslint']);
    gulp.watch([config.app + '*.html', config.app + 'app/**', config.app + 'i18n/**']).on('change', browserSync.reload);
});

gulp.task('wiredep', ['wiredep:test', 'wiredep:app']);

gulp.task('wiredep:app', function () {
    var stream = gulp.src(config.app + 'index.html')
        .pipe(plumber({errorHandler: handleErrors}))
        .pipe(wiredep({
            exclude: [/angular-i18n/]
        }))
        .pipe(gulp.dest(config.app));

    return <% if (useSass) { %>es.merge(stream, gulp.src(config.scss + '*.{scss,sass}')
        .pipe(plumber({errorHandler: handleErrors}))
        .pipe(wiredep({
            exclude: [
                /angular-i18n/,  // localizations are loaded dynamically
                'bower_components/bootstrap/' // Exclude Bootstrap LESS as we use bootstrap-sass
            ],
            ignorePath: /\.\.\/webapp\/bower_components\// // remove ../webapp/bower_components/ from paths of injected sass files
        }))
        .pipe(gulp.dest(config.scss)));<% } else { %>stream;<% } %>
});

gulp.task('wiredep:test', function () {
    return gulp.src(config.test + 'karma.conf.js')
        .pipe(plumber({errorHandler: handleErrors}))
        .pipe(wiredep({
            exclude: [/angular-i18n/, /angular-scenario/],
            ignorePath: /\.\.\/\.\.\//, // remove ../../ from paths of injected javascripts
            devDependencies: true,
            fileTypes: {
                js: {
                    block: /(([\s\t]*)\/\/\s*bower:*(\S*))(\n|\r|.)*?(\/\/\s*endbower)/gi,
                    detect: {
                        js: /'(.*\.js)'/gi
                    },
                    replace: {
                        js: '\'src/{{filePath}}\','
                    }
                }
            }
        }))
        .pipe(gulp.dest(config.test));
});

gulp.task('build', function (cb) {
    runSequence('clean', 'copy', 'wiredep:app', 'ngconstant:prod', 'usemin', cb);
});

gulp.task('usemin', ['images', 'styles'], function () {
    return gulp.src([config.app + '**/*.html', '!' + config.app + '@(dist|bower_components)/**/*.html'])
        .pipe(plumber({errorHandler: handleErrors}))
        .pipe(usemin({
            css: [
                prefix,
                'concat',
                cssnano,
                rev
            ],
            html: [
                htmlmin.bind(htmlmin, {collapseWhitespace: true})
            ],
            js: [
                sourcemaps.init,
                ngAnnotate,
                footer.bind(footer, ';'),
                'concat',
                uglify.bind(uglify, { mangle: false }),
                rev,
                sourcemaps.write.bind(sourcemaps.write, '.')
            ]
        }))
        .pipe(gulp.dest(config.dist));
});

gulp.task('ngconstant:dev', function () {
    return ngConstant({
        dest: 'app.constants.js',
        name: '<%= angularAppName %>',
        deps:   false,
        noFile: true,
        interpolate: /\{%=(.+?)%\}/g,
        wrap:
            '(function() {\n' +
            '    "use strict";\n' +
            '    // DO NOT EDIT THIS FILE, EDIT THE GULP TASK NGCONSTANT SETTINGS INSTEAD WHICH GENERATES THIS FILE\n' +
            '    {%= __ngModule %}\n' +
            '})();\n',
        constants: {
            ENV: 'dev',
            VERSION: util.parseVersion()
        }
    })
    .pipe(gulp.dest(config.app + 'app/'));
});

gulp.task('ngconstant:prod', function () {
    return ngConstant({
        dest: 'app.constants.js',
        name: '<%= angularAppName %>',
        deps:   false,
        noFile: true,
        interpolate: /\{%=(.+?)%\}/g,
        wrap:
            '(function() {\n' +
            '    "use strict";\n' +
            '    // DO NOT EDIT THIS FILE, EDIT THE GULP TASK NGCONSTANT SETTINGS INSTEAD WHICH GENERATES THIS FILE\n' +
            '    {%= __ngModule %}\n ' +
            '})();\n',
        constants: {
            ENV: 'prod',
            VERSION: util.parseVersion()
        }
    })
    .pipe(gulp.dest(config.app + 'app/'));
});

// check app for eslint errors
gulp.task('eslint', function () {
    return gulp.src(['gulpfile.js', config.app + 'app/**/*.js'])
        .pipe(plumber({errorHandler: handleErrors}))
        .pipe(eslint())
        .pipe(eslint.format())
        .pipe(eslint.failOnError());
});

// check app for eslint errors anf fix some of them
gulp.task('eslint-and-fix', function () {
    return gulp.src(config.app + 'app/**/*.js')
        .pipe(plumber({errorHandler: handleErrors}))
        .pipe(eslint({
            fix: true
        }))
        .pipe(eslint.format())
        .pipe(gulpIf(util.isLintFixed, gulp.dest(config.app + 'app')));
});

<% if (testFrameworks.indexOf('protractor') > -1) { %>
gulp.task('itest', ['protractor']);
<% } %>
gulp.task('default', ['serve']);
<commit_msg>polish gulpfile<commit_after>// Generated on <%= (new Date).toISOString().split('T')[0] %> using <%= packagejs.name %> <%= packagejs.version %>
'use strict';

var gulp = require('gulp'),
    prefix = require('gulp-autoprefixer'),
    cssnano = require('gulp-cssnano'),
    usemin = require('gulp-usemin'),
    uglify = require('gulp-uglify'),<% if(useSass) { %>
    expect = require('gulp-expect-file'),
    sass = require('gulp-sass'),<% } %>
    htmlmin = require('gulp-htmlmin'),
    imagemin = require('gulp-imagemin'),
    ngAnnotate = require('gulp-ng-annotate'),
    ngConstant = require('gulp-ng-constant-fork'),
    eslint = require('gulp-eslint'),
    rev = require('gulp-rev'),<% if (testFrameworks.indexOf('protractor') > -1) { %>
    protractor = require('gulp-protractor').protractor,<% } %>
    es = require('event-stream'),
    flatten = require('gulp-flatten'),
    del = require('del'),
    wiredep = require('wiredep').stream,
    runSequence = require('run-sequence'),
    browserSync = require('browser-sync'),
    sourcemaps = require('gulp-sourcemaps'),
    KarmaServer = require('karma').Server,
    plumber = require('gulp-plumber'),
    changed = require('gulp-changed'),
    handleErrors = require('./gulp/handleErrors'),
    serve = require('./gulp/serve'),
    util = require('./gulp/utils'),
    gulpIf = require('gulp-if'),
    footer = require('gulp-footer');

var config = {
    app: '<%= MAIN_SRC_DIR %>',
    dist: '<%= MAIN_SRC_DIR %>dist/',
    test: '<%= TEST_SRC_DIR %>'<% if(useSass) { %>,
    importPath: '<%= MAIN_SRC_DIR %>bower_components',
    scss: '<%= MAIN_SRC_DIR %>scss/',
    sassSrc: '<%= MAIN_SRC_DIR %>scss/**/*.{scss,sass}',
    cssDir: '<%= MAIN_SRC_DIR %>content/css'<% } %>
};

gulp.task('clean', function () {
    return del([config.dist]);
});

gulp.task('test', ['wiredep:test', 'ngconstant:dev'], function (done) {
    new KarmaServer({
        configFile: __dirname + '/' + config.test + 'karma.conf.js',
        singleRun: true
    }, done).start();
});
<% if (testFrameworks.indexOf('protractor') > -1) { %>
gulp.task('protractor', function () {
    return gulp.src([config.test + 'e2e/**/*.js'])
        .pipe(plumber({errorHandler: handleErrors}))
        .pipe(protractor({
            configFile: config.test + 'protractor.conf.js'
        }));
});<% } %>

gulp.task('copy', function () {
    return es.merge( <% if(enableTranslation) { %> // copy i18n folders only if translation is enabled
        gulp.src(config.app + 'i18n/**')
        .pipe(plumber({errorHandler: handleErrors}))
        .pipe(changed(config.dist + 'i18n/'))
        .pipe(gulp.dest(config.dist + 'i18n/')),<% } %>
        gulp.src(config.app + 'bower_components/bootstrap/fonts/*.*')
        .pipe(plumber({errorHandler: handleErrors}))
        .pipe(changed(config.dist + 'content/fonts/'))
        .pipe(gulp.dest(config.dist + 'content/fonts/')),
        gulp.src(config.app + 'content/**/*.{woff,svg,ttf,eot}')
        .pipe(plumber({errorHandler: handleErrors}))
        .pipe(changed(config.dist + 'content/fonts/'))
        .pipe(flatten())
        .pipe(gulp.dest(config.dist + 'content/fonts/')));
});

gulp.task('images', function () {
    return gulp.src(config.app + 'content/images/**')
        .pipe(plumber({errorHandler: handleErrors}))
        .pipe(changed(config.dist + 'content/images'))
        .pipe(imagemin({optimizationLevel: 5}))
        .pipe(gulp.dest(config.dist + 'content/images'))
        .pipe(browserSync.reload({stream: true}));
});
<% if(useSass) { %>
gulp.task('sass', function () {
    return gulp.src(config.sassSrc)
        .pipe(plumber({errorHandler: handleErrors}))
        .pipe(expect(config.sassSrc))
        .pipe(changed(config.cssDir, {extension: '.css'}))
        .pipe(sass({includePaths:config.importPath}).on('error', sass.logError))
        .pipe(gulp.dest(config.cssDir));
});
<% } %>
gulp.task('styles', [<% if(useSass) { %>'sass'<% } %>], function () {
    return gulp.src(config.app + 'content/css')
        .pipe(browserSync.reload({stream: true}));
});

gulp.task('install', function (done) {
    runSequence('wiredep', 'ngconstant:dev'<% if(useSass) { %>, 'sass'<% } %>, done);
});

gulp.task('serve', function () {
    runSequence('install', 'eslint', serve);
});

gulp.task('watch', function () {
    gulp.watch('bower.json', ['wiredep']);
    gulp.watch(['gulpfile.js', <% if(buildTool == 'maven') { %>'pom.xml'<% } else { %>'build.gradle'<% } %>], ['ngconstant:dev']);
    gulp.watch(<% if(useSass) { %>config.sassSrc<% } else { %>config.app + 'content/css/**/*.css'<% } %>, ['styles']);
    gulp.watch(config.app + 'content/images/**', ['images']);
    //gulp.watch(config.app + 'app/**/*.js', ['eslint']);
    gulp.watch([config.app + '*.html', config.app + 'app/**', config.app + 'i18n/**']).on('change', browserSync.reload);
});

gulp.task('wiredep', ['wiredep:test', 'wiredep:app']);

gulp.task('wiredep:app', function () {
    var stream = gulp.src(config.app + 'index.html')
        .pipe(plumber({errorHandler: handleErrors}))
        .pipe(wiredep({
            exclude: [/angular-i18n/]
        }))
        .pipe(gulp.dest(config.app));

    return <% if (useSass) { %>es.merge(stream, gulp.src(config.sassSrc)
        .pipe(plumber({errorHandler: handleErrors}))
        .pipe(wiredep({
            exclude: [
                /angular-i18n/,  // localizations are loaded dynamically
                'bower_components/bootstrap/' // Exclude Bootstrap LESS as we use bootstrap-sass
            ],
            ignorePath: /\.\.\/webapp\/bower_components\// // remove ../webapp/bower_components/ from paths of injected sass files
        }))
        .pipe(gulp.dest(config.scss)));<% } else { %>stream;<% } %>
});

gulp.task('wiredep:test', function () {
    return gulp.src(config.test + 'karma.conf.js')
        .pipe(plumber({errorHandler: handleErrors}))
        .pipe(wiredep({
            exclude: [/angular-i18n/, /angular-scenario/],
            ignorePath: /\.\.\/\.\.\//, // remove ../../ from paths of injected javascripts
            devDependencies: true,
            fileTypes: {
                js: {
                    block: /(([\s\t]*)\/\/\s*bower:*(\S*))(\n|\r|.)*?(\/\/\s*endbower)/gi,
                    detect: {
                        js: /'(.*\.js)'/gi
                    },
                    replace: {
                        js: '\'src/{{filePath}}\','
                    }
                }
            }
        }))
        .pipe(gulp.dest(config.test));
});

gulp.task('build', function (cb) {
    runSequence('clean', 'copy', 'wiredep:app', 'ngconstant:prod', 'usemin', cb);
});

gulp.task('usemin', ['images', 'styles'], function () {
    return gulp.src([config.app + '**/*.html', '!' + config.app + '@(dist|bower_components)/**/*.html'])
        .pipe(plumber({errorHandler: handleErrors}))
        .pipe(usemin({
            css: [
                prefix,
                'concat',
                cssnano,
                rev
            ],
            html: [
                htmlmin.bind(htmlmin, {collapseWhitespace: true})
            ],
            js: [
                sourcemaps.init,
                ngAnnotate,
                footer.bind(footer, ';'),
                'concat',
                uglify.bind(uglify, { mangle: false }),
                rev,
                sourcemaps.write.bind(sourcemaps.write, '.')
            ]
        }))
        .pipe(gulp.dest(config.dist));
});

gulp.task('ngconstant:dev', function () {
    return ngConstant({
        dest: 'app.constants.js',
        name: '<%= angularAppName %>',
        deps:   false,
        noFile: true,
        interpolate: /\{%=(.+?)%\}/g,
        wrap:
            '(function() {\n' +
            '    "use strict";\n' +
            '    // DO NOT EDIT THIS FILE, EDIT THE GULP TASK NGCONSTANT SETTINGS INSTEAD WHICH GENERATES THIS FILE\n' +
            '    {%= __ngModule %}\n' +
            '})();\n',
        constants: {
            ENV: 'dev',
            VERSION: util.parseVersion()
        }
    })
    .pipe(gulp.dest(config.app + 'app/'));
});

gulp.task('ngconstant:prod', function () {
    return ngConstant({
        dest: 'app.constants.js',
        name: '<%= angularAppName %>',
        deps:   false,
        noFile: true,
        interpolate: /\{%=(.+?)%\}/g,
        wrap:
            '(function() {\n' +
            '    "use strict";\n' +
            '    // DO NOT EDIT THIS FILE, EDIT THE GULP TASK NGCONSTANT SETTINGS INSTEAD WHICH GENERATES THIS FILE\n' +
            '    {%= __ngModule %}\n ' +
            '})();\n',
        constants: {
            ENV: 'prod',
            VERSION: util.parseVersion()
        }
    })
    .pipe(gulp.dest(config.app + 'app/'));
});

// check app for eslint errors
gulp.task('eslint', function () {
    return gulp.src(['gulpfile.js', config.app + 'app/**/*.js'])
        .pipe(plumber({errorHandler: handleErrors}))
        .pipe(eslint())
        .pipe(eslint.format())
        .pipe(eslint.failOnError());
});

// check app for eslint errors anf fix some of them
gulp.task('eslint-and-fix', function () {
    return gulp.src(config.app + 'app/**/*.js')
        .pipe(plumber({errorHandler: handleErrors}))
        .pipe(eslint({
            fix: true
        }))
        .pipe(eslint.format())
        .pipe(gulpIf(util.isLintFixed, gulp.dest(config.app + 'app')));
});

<% if (testFrameworks.indexOf('protractor') > -1) { %>
gulp.task('itest', ['protractor']);
<% } %>
gulp.task('default', ['serve']);
<|endoftext|>