<commit_before>const fs = require('fs');
const cp = require('child_process');
const im = require('imagemagick');
const readline = require('readline');
const commandLineArgs = require('command-line-args');

const fullWidth = 1920;
const fullHeight = 1080;
const outDir = './clips';

const optionDefinitions = [
  { name: 'delimiter', alias: 'd', type: String },
  { name: 'font', alias: 'f', type: String },
  { name: 'fontfamily', alias: 'a', type: String },
  { name: 'imagefolder', alias: 'i', type: String },
  { name: 'justify', alias: 'j', type: String },
  { name: 'lines', alias: 'l', type: Number },
  { name: 'music', alias: 'm', type: String },
  { name: 'size', alias: 's', type: Number },
  { name: 'text', alias: 't', type: String },
];
const options = commandLineArgs(optionDefinitions);

class TextBlock {
  constructor(text, i, j, font, fontsize) {
    this.text = text;
    this.font = font;
    this.fontsize = fontsize;
    this.i = i;
    this.j = j;
    this.x = 0;
    this.y = 0;
    this.width = 0;
    this.height = 0;
    this.fillSize(text, font, fontsize);
  }

  fillSize(text, font, fontsize) {
    im.convert([
      '-debug', 'annotate',
      'xc:',
      '-font', font,
      '-pointsize', fontsize,
      '-annotate', 0,
      text, 'null:'
    ], function (err, output) {
      if (err) {
        // In this case, stderr should have the output
        console.log('ERR: ' + err + '\n');
      } else if (output) {
        console.log('OUT: ' + output + '\n');
      }
    });
  }
}

var delimiter = options.hasOwnProperty('delimiter') ? options.delimiter : '===';
var font = options.font;
var fontfamily = options.fontfamily;
var justify = options.hasOwnProperty('justify') ? options.justify : 'c';
var nlines = options.hasOwnProperty('lines') ? options.lines : -1;
var music = options.music;
var fontsize = options.hasOwnProperty('size') ? options.size : '48';
var text = options.text;
var imgfolder = options.hasOwnProperty('imagefolder') ? options.imagefolder : '';

if (!options.hasOwnProperty('fontfamily')
 || !options.hasOwnProperty('music')
 || !options.hasOwnProperty('text')) {
  // Can't do anything useful without input
  return;
}

var proc = cp.spawnSync('/usr/bin/soxi', [ '-D', music ]);
var time = parseFloat(proc.stdout.toString().trim(), 10);
var images = [];
var finished = [];
var pages = 1;
var timePerPage = 1;
var lineReader = readline.createInterface({
  terminal: false,
  input: fs.createReadStream(text)
});
var screens = [];
var screenful = [];

lineReader.on('line', function (line) {
  if (line.startsWith(delimiter)) {
    var length = screenful.length;
    var reDelimiter = new RegExp('^' + delimiter, 'i');
    var bgimage = line.replace(reDelimiter, '').trim();
    var imageName = './bg-' + ('0000' + (screens.length + 1)).slice(-5) + '.png';

    images.push(imageName);
    createBackgroundImage(imgfolder, bgimage, screens.length, imageName);

    if (length < nlines) {
      var toAdd = Math.trunc((nlines - length) / 2);
      for (var l = 0; l < toAdd; l++) {
        screenful.unshift('');
      }
    }

    screens.push(screenful);
    screenful = [];
  } else {
    screenful.push(line);
  }
});
lineReader.on('close', function() {
  setTimeout(foregroundImages, 100);
});

function foregroundImages() {
  if (images.length != finished.length) {
    console.log('Waiting for image processing (' + finished.length + ' of ' + images.length + ')...');
    setTimeout(foregroundImages, 100);
  } else {
    pages = screens.length;
    timePerPage = time / pages;

    console.log('Runs for ' + time + 's, or ' + timePerPage + 's per page.');
    setTimeout(videoFromImages, 100);
    for (var page = 0; page < pages; page++) {
      var imageName = './credit-' + ('0000' + (page + 1)).slice(-5) + '.png';
      var bgImageName = './bg-' + ('0000' + (page + 1)).slice(-5) + '.png';
      var blocks = [];
      var lines = screens[page];
      var contents = lines.join('\n');
      var imageNames = [];

      if (nlines > 0) {
        var lineHeight = fullHeight / nlines;

        for (var l = 0; l < lines.length; l++) {
          if (lines[l].startsWith('[')) {
            var imagelist = lines[l].split(' ');
            var yoff = l * lineHeight;
            var cmdConvert = [];

            for (var ii = 0 ; ii < imagelist.length; ii++) {
              cmdConvert.push(imgfolder + '/' + imagelist[ii].slice(1, -1));
            }

            cmdConvert.push('+append');
            cmdConvert.push('line-' + ('00' + l).slice(-2) + '.png');

            im.convert(cmdConvert, function(err, output) {
              if (err) {
                console.log(err);
              }
            });

            lines[l] = '';
          }
        }
      }

      for (var ll = 0; ll < lines.length; ll++) {
        var fields = lines[ll].split('\t');

        for (var ff = 0; ff < fields.length; ff++) {
          blocks.push(new TextBlock(fields[ff], ll, ff, font, fontsize));
        }
      }

      images.push(imageName);
      im.convert([
        '-page', '+0+0', bgImageName,
        '-background', 'rgba(0,0,0,0)',
        '-fill', '#F0F0B0',
        '-font', font,
        '-size', fullWidth + 'x' + fullHeight,
        '-pointsize', fontsize,
        '-gravity', 'Center',
        'pango:' + contents + '',
        '-layers', 'flatten',
        imageName
      ], function (err, output) {
        if (err) {
          console.log(err);
        }

        finished.push(page);
      });
    }
  }
}

function videoFromImages() {
  if (images.length != finished.length) {
    console.log('Waiting for image processing (' + finished.length + ' of ' + images.length + ')...');
    setTimeout(videoFromImages, 100);
  } else {
    var outfile = text + '.mp4';
    fs.stat(outfile, function(err, stat) {
      if(err == null) {
        fs.unlink(outfile);
      }
      cp.spawnSync('/usr/bin/ffmpeg', [
        '-framerate', 1 / timePerPage,
        '-i', 'credit-%05d.png',
        '-i', music,
        '-safe', '0',
        '-strict', '-2',
        '-c:v', 'libx264',
        '-b:a', '4.5M',
        '-b:v', '4.5M',
        '-minrate', '4.5M',
        '-maxrate', '4.5M',
        '-bufsize', '4.5M',
        '-r', 30,
        '-shortest',
        '-pix_fmt', 'yuv420p',
        '-af', 'aresample=async=1',
        '-max_muxing_queue_size', '9999',
        text + '.mp4'
      ]);
      for (var i = 0; i < images.length; i++) {
        fs.unlink(images[i]);
      }
    });
  }
}

function createBackgroundImage(imgfolder, bgimage, number, imageName) {
    if (bgimage !== '') {
      im.convert([
        imgfolder + '/' + bgimage,
        '-background', '#000030',
        '-gravity', 'Center',
        '-extent', fullWidth + 'x' + fullHeight,
        imageName
      ], function (err, output) {
        if (err) {
          console.log(err);
        } else {
          finished.push('bg' + number);
        }
      });
    } else {
      im.convert([
        '-size', fullWidth + 'x' + fullHeight,
        'xc:#000030',
        imageName
      ], function (err, output) {
        if (err) {
          console.log(err);
        } else {
          finished.push('bg' + number);
        }
      });
    }
}
<commit_msg>Factor out page number calculation<commit_after>const fs = require('fs');
const cp = require('child_process');
const im = require('imagemagick');
const readline = require('readline');
const commandLineArgs = require('command-line-args');

const fullWidth = 1920;
const fullHeight = 1080;
const outDir = './clips';

const optionDefinitions = [
  { name: 'delimiter', alias: 'd', type: String },
  { name: 'font', alias: 'f', type: String },
  { name: 'fontfamily', alias: 'a', type: String },
  { name: 'imagefolder', alias: 'i', type: String },
  { name: 'justify', alias: 'j', type: String },
  { name: 'lines', alias: 'l', type: Number },
  { name: 'music', alias: 'm', type: String },
  { name: 'size', alias: 's', type: Number },
  { name: 'text', alias: 't', type: String },
];
const options = commandLineArgs(optionDefinitions);

class TextBlock {
  constructor(text, i, j, font, fontsize) {
    this.text = text;
    this.font = font;
    this.fontsize = fontsize;
    this.i = i;
    this.j = j;
    this.x = 0;
    this.y = 0;
    this.width = 0;
    this.height = 0;
    this.fillSize(text, font, fontsize);
  }

  fillSize(text, font, fontsize) {
    im.convert([
      '-debug', 'annotate',
      'xc:',
      '-font', font,
      '-pointsize', fontsize,
      '-annotate', 0,
      text, 'null:'
    ], function (err, output) {
      if (err) {
        // In this case, stderr should have the output
        console.log('ERR: ' + err + '\n');
      } else if (output) {
        console.log('OUT: ' + output + '\n');
      }
    });
  }
}

var delimiter = options.hasOwnProperty('delimiter') ? options.delimiter : '===';
var font = options.font;
var fontfamily = options.fontfamily;
var justify = options.hasOwnProperty('justify') ? options.justify : 'c';
var nlines = options.hasOwnProperty('lines') ? options.lines : -1;
var music = options.music;
var fontsize = options.hasOwnProperty('size') ? options.size : '48';
var text = options.text;
var imgfolder = options.hasOwnProperty('imagefolder') ? options.imagefolder : '';

if (!options.hasOwnProperty('fontfamily')
 || !options.hasOwnProperty('music')
 || !options.hasOwnProperty('text')) {
  // Can't do anything useful without input
  return;
}

var proc = cp.spawnSync('/usr/bin/soxi', [ '-D', music ]);
var time = parseFloat(proc.stdout.toString().trim(), 10);
var images = [];
var finished = [];
var pages = 1;
var timePerPage = 1;
var lineReader = readline.createInterface({
  terminal: false,
  input: fs.createReadStream(text)
});
var screens = [];
var screenful = [];

lineReader.on('line', function (line) {
  if (line.startsWith(delimiter)) {
    var length = screenful.length;
    var reDelimiter = new RegExp('^' + delimiter, 'i');
    var bgimage = line.replace(reDelimiter, '').trim();
    var imageName = './bg-' + ('0000' + (screens.length + 1)).slice(-5) + '.png';

    images.push(imageName);
    createBackgroundImage(imgfolder, bgimage, screens.length, imageName);

    if (length < nlines) {
      var toAdd = Math.trunc((nlines - length) / 2);
      for (var l = 0; l < toAdd; l++) {
        screenful.unshift('');
      }
    }

    screens.push(screenful);
    screenful = [];
  } else {
    screenful.push(line);
  }
});
lineReader.on('close', function() {
  setTimeout(foregroundImages, 100);
});

function foregroundImages() {
  if (images.length != finished.length) {
    console.log('Waiting for image processing (' + finished.length + ' of ' + images.length + ')...');
    setTimeout(foregroundImages, 100);
  } else {
    pages = screens.length;
    timePerPage = time / pages;

    console.log('Runs for ' + time + 's, or ' + timePerPage + 's per page.');
    setTimeout(videoFromImages, 100);
    for (var page = 0; page < pages; page++) {
      var pageNumber = ('0000' + (page + 1)).slice(-5);
      var imageName = './credit-' + pageNumber + '.png';
      var bgImageName = './bg-' + pageNumber + '.png';
      var blocks = [];
      var lines = screens[page];
      var contents = lines.join('\n');
      var imageNames = [];

      if (nlines > 0) {
        var lineHeight = fullHeight / nlines;

        for (var l = 0; l < lines.length; l++) {
          if (lines[l].startsWith('[')) {
            var imagelist = lines[l].split(' ');
            var yoff = l * lineHeight;
            var cmdConvert = [];

            for (var ii = 0 ; ii < imagelist.length; ii++) {
              cmdConvert.push(imgfolder + '/' + imagelist[ii].slice(1, -1));
            }

            cmdConvert.push('+append');
            cmdConvert.push('line-' + ('00' + l).slice(-2) + '.png');

            im.convert(cmdConvert, function(err, output) {
              if (err) {
                console.log(err);
              }
            });

            lines[l] = '';
          }
        }
      }

      for (var ll = 0; ll < lines.length; ll++) {
        var fields = lines[ll].split('\t');

        for (var ff = 0; ff < fields.length; ff++) {
          blocks.push(new TextBlock(fields[ff], ll, ff, font, fontsize));
        }
      }

      images.push(imageName);
      im.convert([
        '-page', '+0+0', bgImageName,
        '-background', 'rgba(0,0,0,0)',
        '-fill', '#F0F0B0',
        '-font', font,
        '-size', fullWidth + 'x' + fullHeight,
        '-pointsize', fontsize,
        '-gravity', 'Center',
        'pango:' + contents + '',
        '-layers', 'flatten',
        imageName
      ], function (err, output) {
        if (err) {
          console.log(err);
        }

        finished.push(page);
      });
    }
  }
}

function videoFromImages() {
  if (images.length != finished.length) {
    console.log('Waiting for image processing (' + finished.length + ' of ' + images.length + ')...');
    setTimeout(videoFromImages, 100);
  } else {
    var outfile = text + '.mp4';
    fs.stat(outfile, function(err, stat) {
      if(err == null) {
        fs.unlink(outfile);
      }
      cp.spawnSync('/usr/bin/ffmpeg', [
        '-framerate', 1 / timePerPage,
        '-i', 'credit-%05d.png',
        '-i', music,
        '-safe', '0',
        '-strict', '-2',
        '-c:v', 'libx264',
        '-b:a', '4.5M',
        '-b:v', '4.5M',
        '-minrate', '4.5M',
        '-maxrate', '4.5M',
        '-bufsize', '4.5M',
        '-r', 30,
        '-shortest',
        '-pix_fmt', 'yuv420p',
        '-af', 'aresample=async=1',
        '-max_muxing_queue_size', '9999',
        text + '.mp4'
      ]);
      for (var i = 0; i < images.length; i++) {
        fs.unlink(images[i]);
      }
    });
  }
}

function createBackgroundImage(imgfolder, bgimage, number, imageName) {
    if (bgimage !== '') {
      im.convert([
        imgfolder + '/' + bgimage,
        '-background', '#000030',
        '-gravity', 'Center',
        '-extent', fullWidth + 'x' + fullHeight,
        imageName
      ], function (err, output) {
        if (err) {
          console.log(err);
        } else {
          finished.push('bg' + number);
        }
      });
    } else {
      im.convert([
        '-size', fullWidth + 'x' + fullHeight,
        'xc:#000030',
        imageName
      ], function (err, output) {
        if (err) {
          console.log(err);
        } else {
          finished.push('bg' + number);
        }
      });
    }
}
<|endoftext|>


<commit_before>'use babel'

import { client } from '../connection'
import tcp from '../connection/process/tcp'
import { CompositeDisposable } from 'atom'
import { paths } from '../misc'
import modules from './modules'
import pty from 'pty.js'
import { debounce, once } from 'underscore-plus'

var { changemodule, resetprompt, validatepath, fullpath } = client.import({msg: ['changemodule', 'resetprompt'], rpc: ['validatepath', 'fullpath']})

export function activate (ink) {
  if (atom.config.get('julia-client.juliaOptions.consoleStyle') != 'REPL-based') return

  let subs = new CompositeDisposable()

  let terminal = ink.InkTerminal.fromId('julia-terminal')

  console.log(terminal);

  terminal.getTitle = () => {return 'Console'}
  terminal.class = 'julia-terminal'
  terminal.write('\x1b[32mPress Enter to start Julia.\x1b[0m')
  terminal.startRequested = () => client.boot()

  modules.onDidChange(debounce(() => changemodule({mod: modules.current(), cols: terminal.terminal.cols}), 200))

  client.onBoot((proc) => {
    terminal.attach(proc.ty)

    let linkHandler = (event, uri) => {
      [uri, line] = uri.split(':')
      fullpath(uri).then((path) => ink.Opener.open(path, parseInt(line) - 1))
    }

    let validator = (uri, cb) => {
      validatepath(uri).then((isvalid) => {
        cb(isvalid)
      })
    }

    let uriRegex = /[(\.\/)|\/][^\s]+\.jl(:\d+)?/

    // doesn't handle multiline URIs properly due to upstream bug (xterm.js#24)
    terminal.terminal.registerLinkMatcher(uriRegex, linkHandler, {validationCallback: validator})

    // if provided from cycler cache we usually need to write a prompt
    if (proc.wasCached) {
      resetprompt()
    }

    proc.onExit(() => {
      terminal.detach()
      terminal.write('\r\x1b[31mJulia has stopped.\x1b[0m  Press Enter to start a new session.')
      terminal.terminal.deregisterLinkMatcher(linkHandler)
    })
  })

  client.handle({
    updateWorkspace: () => require('./workspace').update(),
    clearconsole: () => terminal.clear()
  })

  subs.add(atom.commands.add('atom-workspace', 'julia-client:open-console', () => {
    terminal.open().then(() => terminal.show())
  }))

  subs.add(atom.commands.add('atom-workspace', 'julia-client:clear-terminal', () => {
    terminal.clear()
  }))

  subs.add(atom.commands.add('atom-workspace', 'julia-client:new-terminal', () => {
    let term = ink.InkTerminal.fromId(`terminal-julia-${Math.floor(Math.random()*10000000)}`)
    term.attach(shellPty())
    if (open) term.open().then(() => term.show())
  }))

  // handle deserialized terminals
  atom.workspace.getPaneItems().forEach((item) => {
    if (item.id && item.name === 'InkTerminal' && item.id.match(/terminal\-julia\-\d+/)) {
      if (!item.ty) {
        item.attach(shellPty())
      }
    }
  })
}

function shellPty () {
  return pty.fork(atom.config.get("julia-client.terminal"), [], {
      cols: 100,
      rows: 30
    })
}

export function deactivate () {
  if (subs) subs.dispose()
}
<commit_msg>better uri regex<commit_after>'use babel'

import { client } from '../connection'
import tcp from '../connection/process/tcp'
import { CompositeDisposable } from 'atom'
import { paths } from '../misc'
import modules from './modules'
import pty from 'pty.js'
import { debounce, once } from 'underscore-plus'

var { changemodule, resetprompt, validatepath, fullpath } = client.import({msg: ['changemodule', 'resetprompt'], rpc: ['validatepath', 'fullpath']})

let uriRegex
if (process.platform == 'win32') {
  uriRegex = /((([a-zA-Z]:|\.\.?|\~)|([^\0<>\?\|\/\s!$`&*()\[\]+'":;])+)?((\\|\/)([^\0<>\?\|\/\s!$`&*()\[\]+'":;])+)+)(\:\d+)?/
} else {
  uriRegex = /(((\.\.?|\~)|([^\0\s!$`&*()\[\]+'":;\\])+)?(\/([^\0\s!$`&*()\[\]+'":;\\])+)+)(\:\d+)?/
}

export function activate (ink) {
  if (atom.config.get('julia-client.juliaOptions.consoleStyle') != 'REPL-based') return

  let subs = new CompositeDisposable()

  let terminal = ink.InkTerminal.fromId('julia-terminal')

  console.log(terminal);

  terminal.getTitle = () => {return 'Console'}
  terminal.class = 'julia-terminal'
  terminal.write('\x1b[32mPress Enter to start Julia.\x1b[0m')
  terminal.startRequested = () => client.boot()

  modules.onDidChange(debounce(() => changemodule({mod: modules.current(), cols: terminal.terminal.cols}), 200))

  client.onBoot((proc) => {
    terminal.attach(proc.ty)

    let linkHandler = (event, uri) => {
      [uri, line] = uri.split(':')
      fullpath(uri).then((path) => ink.Opener.open(path, parseInt(line) - 1), {pending: true})
    }

    let validator = (uri, cb) => {
      validatepath(uri).then((isvalid) => {
        cb(isvalid)
      })
    }

    // doesn't handle multiline URIs properly due to upstream bug (xterm.js#24)
    terminal.terminal.registerLinkMatcher(uriRegex, linkHandler, {validationCallback: validator})

    // if provided from cycler cache we usually need to write a prompt
    if (proc.wasCached) {
      resetprompt()
    }

    proc.onExit(() => {
      terminal.detach()
      terminal.write('\r\x1b[31mJulia has stopped.\x1b[0m  Press Enter to start a new session.')
      terminal.terminal.deregisterLinkMatcher(linkHandler)
    })
  })

  client.handle({
    updateWorkspace: () => require('./workspace').update(),
    clearconsole: () => terminal.clear()
  })

  subs.add(atom.commands.add('atom-workspace', 'julia-client:open-console', () => {
    terminal.open().then(() => terminal.show())
  }))

  subs.add(atom.commands.add('atom-workspace', 'julia-client:clear-terminal', () => {
    terminal.clear()
  }))

  subs.add(atom.commands.add('atom-workspace', 'julia-client:new-terminal', () => {
    let term = ink.InkTerminal.fromId(`terminal-julia-${Math.floor(Math.random()*10000000)}`)
    term.attach(shellPty())
    if (open) term.open().then(() => term.show())
  }))

  // handle deserialized terminals
  atom.workspace.getPaneItems().forEach((item) => {
    if (item.id && item.name === 'InkTerminal' && item.id.match(/terminal\-julia\-\d+/)) {
      if (!item.ty) {
        item.attach(shellPty())
      }
    }
  })
}

function shellPty () {
  return pty.fork(atom.config.get("julia-client.terminal"), [], {
      cols: 100,
      rows: 30
    })
}

export function deactivate () {
  if (subs) subs.dispose()
}
<|endoftext|>


<commit_before>function parseUrlParams(location) {
  var param_dict = {};

  var params = location.search.replace(/^\?/, '').split('&');
  for (var i in params) {
    var param = params[i];

    var equation_index = param.indexOf('=');
    if (equation_index == -1) equation_index = param.length;

    // Skip params with empty name
    if (!equation_index) continue;

    var param_name = decodeURIComponent(param.substr(0, equation_index));
    var param_value = decodeURIComponent(param.substr(equation_index + 1));
    param_dict[param_name] = param_value;
  }

  return param_dict;
}

function fillUsingParams(mapping, button) {
  var url_params = parseUrlParams(window.location);

  for (var control_selector in mapping) {
    var value_from_param = mapping[control_selector];
    if (!(value_from_param in url_params)) continue;

    var value = url_params[value_from_param];
    if (!value) continue;

    var control = jQuery(control_selector);
    if (control.is('input')) {
      if (control.type == 'text' || control.type == 'hidden') {
        control.val(value);
      } else if (control.type == 'radio') {
        control.checked = true;
      }
    } else if (control.is('textarea')) {
      control.val(value);
    } else if (control.is('select')) {
      var options = jQuery('option', control);
      for (var i in options)
        if(options[i].text.startsWith(value)) {
          control.selectpicker('val', options[i].text);
          break;
        }
    }
  }
}
<commit_msg>CLARIN switchboard sends url (to nextcloud) in data parameter<commit_after>function parseUrlParams(location) {
  var param_dict = {};

  var params = location.search.replace(/^\?/, '').split('&');
  for (var i in params) {
    var param = params[i];

    var equation_index = param.indexOf('=');
    if (equation_index == -1) equation_index = param.length;

    // Skip params with empty name
    if (!equation_index) continue;

    var param_name = decodeURIComponent(param.substr(0, equation_index));
    var param_value = decodeURIComponent(param.substr(equation_index + 1));
    param_dict[param_name] = param_value;
  }

  return param_dict;
}

function fillUsingParams(mapping, button) {
  var url_params = parseUrlParams(window.location);

  for (var control_selector in mapping) {
    var value_from_param = mapping[control_selector];
    if (!(value_from_param in url_params)) continue;

    var value = url_params[value_from_param];
    if (!value) continue;

    var control = jQuery(control_selector);
    if (control.is('input')) {
      if (control.type == 'text' || control.type == 'hidden') {
        control.val(value);
      } else if (control.type == 'radio') {
        control.checked = true;
      }
    } else if (control.is('textarea')) {
      // specific handling of url-only values
      // - load the contents instead of the url value
      var url_pattern = new RegExp(
        '^((news|(ht|f)tp(s?)):\\/\\/)'+
        '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|'+
        '((\\d{1,3}\\.){3}\\d{1,3}))'+
        '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*'+
        '(\\?[;&a-z\\d%_.~+=-]*)?'+
        '(\\#[-a-z\\d_]*)?$','i');
      if (url_pattern.test(value))
      {
        var xhr = new XMLHttpRequest();
        xhr.open('GET', value, false);
        xhr.onload = function () {
            if (this.status === 200) {
              control.val(this.responseText);
            }
        };
        xhr.send();
      }else {
        control.val(value);
      }
    } else if (control.is('select')) {
      var options = jQuery('option', control);
      for (var i in options)
        if(options[i].text.startsWith(value)) {
          control.selectpicker('val', options[i].text);
          break;
        }
    }
  }
}
<|endoftext|>


<commit_before>const async = require('async');
const Viz = require('viz.js');
const fs = require('fs');

class GraphGenerator {
  constructor(embark, options) {
    const self = this;
    this.events = embark.events;

    this.events.setCommandHandler("graph:create", function(options, cb) {
      self.generate(options);
      cb();
    });
  }

  generate(options) {
    const self = this;
    let id = 0;
    let contractString = "";
    let relationshipString = "";
    let idMapping = {};
    let contractInheritance = {};
    let contracts = {};
    let contractsDependencies = {};

    async.waterfall([
      function getContractList(next) {
        self.events.request('contracts:list', (err, _contracts) => {
          contracts = _contracts;
          next();
        });
      },
      function getContractsDependencies(next) {
        self.events.request('contracts:dependencies', (err, _contractsDependencies) => {
          contractsDependencies = _contractsDependencies;
          next();
        });
      },
      function (next) {
        for (let contract of contracts) {
          if (options.skipUndeployed && !contract.deploy) continue;

          id++;

          idMapping[contract.className] = id;

          let contractLabel = "";

          contractLabel += `${contract.className}`;
          let tooltip = contract.className;

          if (contract.instanceOf !== undefined && contracts[contract.instanceOf] !== undefined) {
            contractInheritance[contract.className] = contract.instanceOf;
            contractLabel += ": " + contract.instanceOf;
            tooltip += " instance of " + contract.instanceOf;
          } else {
            if (!(options.skipFunctions === true && options.skipEvents === true)) contractLabel += "|";

            for (let i = 0; i < contract.abiDefinition.length; i++) {
              let abiDef = contract.abiDefinition[i];
              if (abiDef.type == 'event' && options.skipEvents) continue;
              if (['constructor', 'fallback'].indexOf(abiDef.type) > -1 && options.skipFunctions) continue;

              switch(abiDef.type){
                case 'fallback':
                  contractLabel += "«fallback»()\\l";
                  break;
                case 'constructor':
                  contractLabel += "«constructor»(";
                  abiDef.inputs.forEach(function(elem, index){
                    contractLabel += (index == 0 ? "" : ", ") + elem.type;
                  });
                  contractLabel += ")\\l";
                  break;
                case 'event':
                  contractLabel += "«event»" + abiDef.name  + "(";
                  abiDef.inputs.forEach(function(elem, index){
                    contractLabel += (index == 0 ? "" : ", ") + elem.type;
                  });
                  contractLabel += ")\\l";
                  break;
                default: break;
              }
            }

            let fHashes = contract.functionHashes;
            if (fHashes != {} && fHashes != undefined && !options.skipFunctions){
              for (let method in contract.functionHashes){
                contractLabel += method + '\\l';
              }
            }
          }

          let others = '';
          if (!contract.deploy){
            others = 'fontcolor="#c3c3c3", color="#a0a0a0"';
            tooltip += " (not deployed)";
          }

          contractString += `${id}[label = "{${contractLabel}}", tooltip="${tooltip}", fillcolor=gray95, ${others}]\n`;
        }
        next();
      },
      function (next) {
        for (let c in contractsDependencies) {
          let contractDependencies = Array.from(new Set(contractsDependencies[c]));
          contractDependencies.forEach((d) => {
            if (idMapping[c] !== undefined && idMapping[d] !== undefined) {
              if ((options.skipUndeployed && contracts[c].deploy && contracts[d].deploy) || !options.skipUndeployed) {
                relationshipString += `${idMapping[d]}->${idMapping[c]}[constraint=true, arrowtail=diamond, tooltip="${c} uses ${d}"]\n`;
              }
            }
          });
        }
        next();
      },
      function (next) {
        for (let c in contractInheritance){
          if(options.skipUndeployed && !contracts[contractInheritance[c]].deploy) continue;

          relationshipString += `${idMapping[contractInheritance[c]]}->${idMapping[c]}[tooltip="${c} instance of ${contractInheritance[c]}"]\n`;
        }
        console.log("-----");
        console.log(relationshipString);
        console.log("-----");
        next();
      },
      function (next) {
        let dot = `
        digraph Contracts {
            node[shape=record,style=filled]
            edge[dir=back, arrowtail=empty]
            ${contractString}
            ${relationshipString}
        }`;

        console.log(dot);
        let svg = Viz(dot);

        let filename = "diagram.svg";

        fs.writeFileSync(filename, svg, (err) => {
          if (err) throw err;
          next();
        });
      }
    ], function(_err, _result) {
    });
  }
}

module.exports = GraphGenerator;
<commit_msg>add find contract<commit_after>const async = require('async');
const Viz = require('viz.js');
const fs = require('fs');

class GraphGenerator {
  constructor(embark, options) {
    const self = this;
    this.events = embark.events;
    this.contracts = [];

    this.events.setCommandHandler("graph:create", function(options, cb) {
      self.generate(options);
      cb();
    });
  }

  generate(options) {
    const self = this;
    let id = 0;
    let contractString = "";
    let relationshipString = "";
    let idMapping = {};
    let contractInheritance = {};
    let contractsDependencies = {};

    async.waterfall([
      function getContractList(next) {
        self.events.request('contracts:list', (err, contracts) => {
          self.contracts = contracts;
          next();
        });
      },
      function getContractsDependencies(next) {
        self.events.request('contracts:dependencies', (err, _contractsDependencies) => {
          contractsDependencies = _contractsDependencies;
          next();
        });
      },
      function (next) {
        for (let contract of self.contracts) {
          if (options.skipUndeployed && !contract.deploy) continue;

          id++;

          idMapping[contract.className] = id;

          let contractLabel = "";

          contractLabel += `${contract.className}`;
          let tooltip = contract.className;

          if (contract.instanceOf !== undefined && self.getContract(contract.instanceOf) !== undefined) {
            contractInheritance[contract.className] = contract.instanceOf;
            contractLabel += ": " + contract.instanceOf;
            tooltip += " instance of " + contract.instanceOf;
          } else {
            if (!(options.skipFunctions === true && options.skipEvents === true)) contractLabel += "|";

            for (let i = 0; i < contract.abiDefinition.length; i++) {
              let abiDef = contract.abiDefinition[i];
              if (abiDef.type == 'event' && options.skipEvents) continue;
              if (['constructor', 'fallback'].indexOf(abiDef.type) > -1 && options.skipFunctions) continue;

              switch(abiDef.type){
                case 'fallback':
                  contractLabel += "«fallback»()\\l";
                  break;
                case 'constructor':
                  contractLabel += "«constructor»(";
                  abiDef.inputs.forEach(function(elem, index){
                    contractLabel += (index == 0 ? "" : ", ") + elem.type;
                  });
                  contractLabel += ")\\l";
                  break;
                case 'event':
                  contractLabel += "«event»" + abiDef.name  + "(";
                  abiDef.inputs.forEach(function(elem, index){
                    contractLabel += (index == 0 ? "" : ", ") + elem.type;
                  });
                  contractLabel += ")\\l";
                  break;
                default: break;
              }
            }

            let fHashes = contract.functionHashes;
            if (fHashes != {} && fHashes != undefined && !options.skipFunctions){
              for (let method in contract.functionHashes){
                contractLabel += method + '\\l';
              }
            }
          }

          let others = '';
          if (!contract.deploy){
            others = 'fontcolor="#c3c3c3", color="#a0a0a0"';
            tooltip += " (not deployed)";
          }

          contractString += `${id}[label = "{${contractLabel}}", tooltip="${tooltip}", fillcolor=gray95, ${others}]\n`;
        }
        next();
      },
      function (next) {
        for (let c in contractsDependencies) {
          let contractDependencies = Array.from(new Set(contractsDependencies[c]));
          contractDependencies.forEach((d) => {
            if (idMapping[c] !== undefined && idMapping[d] !== undefined) {
              if ((options.skipUndeployed && self.getContract(c).deploy && self.getContract(d).deploy) || !options.skipUndeployed) {
                relationshipString += `${idMapping[d]}->${idMapping[c]}[constraint=true, arrowtail=diamond, tooltip="${c} uses ${d}"]\n`;
              }
            }
          });
        }
        next();
      },
      function (next) {
        for (let c in contractInheritance){
          if(options.skipUndeployed && !self.getContract(contractInheritance[c]).deploy) continue;

          relationshipString += `${idMapping[contractInheritance[c]]}->${idMapping[c]}[tooltip="${c} instance of ${contractInheritance[c]}"]\n`;
        }
        next();
      },
      function (next) {
        let dot = `
        digraph Contracts {
            node[shape=record,style=filled]
            edge[dir=back, arrowtail=empty]
            ${contractString}
            ${relationshipString}
        }`;

        let svg = Viz(dot);

        let filename = "diagram.svg";

        fs.writeFileSync(filename, svg, (err) => {
          if (err) throw err;
          next();
        });
      }
    ], function(_err, _result) {
    });
  }

  getContract(contractName) {
    return this.contracts.find((contract) => { return contract.className === contractName });
  }
}

module.exports = GraphGenerator;
<|endoftext|>


<commit_before>/* @flow */
import React from 'react';
import Box from 'grommet/components/Box';
import Form from 'grommet/components/Form';
import FormFields from 'grommet/components/FormFields';
import FormField from 'grommet/components/FormField';
import Select from 'grommet/components/Select';
import Button from 'grommet/components/Button';
import Footer from 'grommet/components/Footer';
import RadioButton from 'grommet/components/RadioButton';
import validation from './validation';

export type AssetType = 'path' | 'href';
export type ButtonType = 'Button' | 'Anchor';

type State = {
  label: ?string,
  primary: ?string,
  path: ?string,
  href: ?string,
  buttonType: ?string,
  assetType: AssetType,
  error: {
    label: ?string,
    path: ?string,
    href: ?string,
  }
};

type Props = {
  onSubmit?: Function,
  onChange?: Function,
  label?: string,
  children?: React$Element<any>, // eslint-disable-line
  primary?: boolean,
  buttonType?: ButtonType,
  href?: string,
  assetType?: AssetType,
  path?: string,
  asset?: {
    path?: string,
  }
};

export default class BlockButtonForm extends React.Component {
  constructor(props: Props) {
    super(props);
    (this:any).onChange = this.onChange.bind(this);
    (this:any).onSubmit = this.onSubmit.bind(this);
    (this:any).formIsValid = this.formIsValid.bind(this);
    (this:any).onChangeAssetType = this.onChangeAssetType.bind(this);
    const { path, primary, label, buttonType, href, assetType } = props;
    const labelInput = label || '';
    const primaryInput = primary || 'True';
    const buttonTypeInput = buttonType || 'Button';
    const pathInput = path || '';
    const hrefInput = href || '';
    const assetTypeInput = assetType || 'path';
    this.state = {
      label: labelInput,
      primary: primaryInput,
      path: pathInput,
      buttonType: buttonTypeInput,
      href: hrefInput,
      assetType: assetTypeInput,
      error: {
        label: null,
        path: null,
        href: null,
      },
    };
  }

  state: State;

  componentWillReceiveProps({ asset }: Props) {
    if (asset && asset.path !== this.state.path) {
      this.setState({
        path: asset.path,
      });
    }
  }

  onChange(e: any) {
    const { target, option } = e;
    if (option) {
      this.setState({
        [`${target.id}`]: option,
      });
    } else {
      this.setState({
        [`${target.id}`]: target.value,
      });
    }
    if (this.props.onChange) {
      this.props.onChange(e);
    }
  }

  onChangeAssetType() {
    const { assetType } = this.state;
    let newType = 'href';
    if (assetType === 'href') {
      newType = 'path';
    }
    this.setState({
      assetType: newType,
    });
  }

  onSubmit(event: any) {
    event.preventDefault();
    if (this.formIsValid() && this.props.onSubmit) {
      if (this.props.onSubmit) {
        this.props.onSubmit(event);
      }
    }
  }

  props: Props;

  formIsValid() {
    const { path, label, href, assetType } = this.state;
    const hrefError = validation.validUrl(href) === true
      ? null
      : 'Please enter a valid url, containing a protocol such as http://';
    const pathError = validation.validLength(path)
      ? null
      : 'Please enter a valid path';
    const labelError = validation.validLength(label)
      ? null
      : 'Please enter a valid label';
    this.setState({
      error: {
        href: hrefError,
        path: pathError,
        label: labelError,
      },
    });
    if (assetType === 'path') {
      return pathError === null && labelError === null;
    }
    return hrefError === null && labelError === null;
  }

  render() {
    const { children } = this.props;
    const {
      label,
      primary,
      path,
      buttonType,
      assetType,
      href,
      error,
    } = this.state;
    return (
      <Box colorIndex="light-2" pad="medium">
        <Form>
          <FormFields>
            <fieldset>
              <FormField
                label="Label"
                error={error.label}
                help="Enter a label that will appear on the button"
                htmlFor="label"
              >
                <input
                  id="label"
                  name="label"
                  type="text"
                  value={label}
                  onChange={this.onChange}
                />
              </FormField>
              <FormField
                error={assetType === 'path' ? error.path : error.href}
                help={assetType === 'path'
                  ? 'Enter a path to an internal asset, such as /uploads/image.png'
                  : 'Enter a url to an external site, such as http://google.com/image.png'}
                label="Link"
                htmlFor={assetType === 'path' ? 'path' : 'href'}
              >
                {assetType === 'path' ?
                  <input
                    id="path"
                    name="path"
                    type="text"
                    value={path}
                    onChange={this.onChange}
                  />
                :
                  <input
                    id="href"
                    name="href"
                    type="text"
                    value={href}
                    onChange={this.onChange}
                  />
                }
              </FormField>
              <FormField
                label="Asset Link Type"
                help="What type of asset should the button link to?"
              >
                <Box direction="row" pad={{ vertical: 'small', horizontal: 'medium' }}>
                  <RadioButton
                    id="internal"
                    label="Internal Asset"
                    checked={(assetType === 'path')}
                    onChange={this.onChangeAssetType}
                    name="internal"
                  />
                  <RadioButton
                    id="external"
                    checked={(assetType !== 'path')}
                    label="External URL"
                    onChange={this.onChangeAssetType}
                    name="external"
                  />
                </Box>
              </FormField>
              <FormField
                label="Button Type"
                htmlFor="buttonType"
                help="What type of button would you like to use?  Button or Anchor?"
              >
                <Select
                  onChange={this.onChange}
                  value={buttonType || ''}
                  options={['Button', 'Anchor']}
                  name="buttonType"
                  id="buttonType"
                />
              </FormField>
              <FormField
                label="Primary"
                htmlFor="primary"
                help={buttonType === 'Anchor'
                  ? 'Should the anchor have the arrow icon in front of it?'
                  : 'Should the button be filled in with the brand color?'
                }
              >
                <Select
                  onChange={this.onChange}
                  value={primary || ''}
                  options={['True', 'False']}
                  name="primary"
                  id="primary"
                />
              </FormField>
            </fieldset>
            {assetType === 'path' && children && children}
          </FormFields>
          <Footer pad="medium">
            <Button
              onClick={this.onSubmit}
              type="submit"
              label="Done"
            />
          </Footer>
        </Form>
      </Box>
    );
  }
}

<commit_msg>Feat: call on change for asset type in block button form<commit_after>/* @flow */
import React from 'react';
import Box from 'grommet/components/Box';
import Form from 'grommet/components/Form';
import FormFields from 'grommet/components/FormFields';
import FormField from 'grommet/components/FormField';
import Select from 'grommet/components/Select';
import Button from 'grommet/components/Button';
import Footer from 'grommet/components/Footer';
import RadioButton from 'grommet/components/RadioButton';
import validation from './validation';

export type AssetType = 'path' | 'href';
export type ButtonType = 'Button' | 'Anchor';
export type Primary = 'True' | 'False';

type State = {
  label: ?string,
  primary: ?Primary,
  path: ?string,
  href: ?string,
  buttonType: ?string,
  assetType: AssetType,
  error: {
    label: ?string,
    path: ?string,
    href: ?string,
  }
};

type Props = {
  onSubmit?: Function,
  onChange?: Function,
  label?: string,
  children?: React$Element<any>, // eslint-disable-line
  primary?: Primary,
  buttonType?: ButtonType,
  href?: string,
  assetType?: AssetType,
  path?: string,
  asset?: {
    path?: string,
  }
};

export default class BlockButtonForm extends React.Component {
  constructor(props: Props) {
    super(props);
    (this:any).onChange = this.onChange.bind(this);
    (this:any).onSubmit = this.onSubmit.bind(this);
    (this:any).formIsValid = this.formIsValid.bind(this);
    (this:any).onChangeAssetType = this.onChangeAssetType.bind(this);
    const { path, primary, label, buttonType, href, assetType } = props;
    const labelInput = label || '';
    const primaryInput = primary || 'True';
    const buttonTypeInput = buttonType || 'Button';
    const pathInput = path || '';
    const hrefInput = href || '';
    const assetTypeInput = assetType || 'path';
    this.state = {
      label: labelInput,
      primary: primaryInput,
      path: pathInput,
      buttonType: buttonTypeInput,
      href: hrefInput,
      assetType: assetTypeInput,
      error: {
        label: null,
        path: null,
        href: null,
      },
    };
  }

  state: State;

  componentWillReceiveProps({ asset }: Props) {
    if (asset && asset.path !== this.state.path) {
      this.setState({
        path: asset.path,
      });
    }
  }

  onChange(e: any) {
    const { target, option } = e;
    if (option) {
      this.setState({
        [`${target.id}`]: option,
      });
    } else {
      this.setState({
        [`${target.id}`]: target.value,
      });
    }
    if (this.props.onChange) {
      this.props.onChange(e);
    }
  }

  onChangeAssetType() {
    const { assetType } = this.state;
    let newType = 'href';
    if (assetType === 'href') {
      newType = 'path';
    }
    const event = {
      target: {
        id: 'assetType',
        value: newType,
      },
    };
    if (this.props.onChange) {
      this.props.onChange(event);
    }
    this.setState({
      assetType: newType,
    });
  }

  onSubmit(event: any) {
    event.preventDefault();
    if (this.formIsValid() && this.props.onSubmit) {
      if (this.props.onSubmit) {
        this.props.onSubmit(event);
      }
    }
  }

  props: Props;

  formIsValid() {
    const { path, label, href, assetType } = this.state;
    const hrefError = validation.validUrl(href) === true
      ? null
      : 'Please enter a valid url, containing a protocol such as http://';
    const pathError = validation.validLength(path)
      ? null
      : 'Please enter a valid path';
    const labelError = validation.validLength(label)
      ? null
      : 'Please enter a valid label';
    this.setState({
      error: {
        href: hrefError,
        path: pathError,
        label: labelError,
      },
    });
    if (assetType === 'path') {
      return pathError === null && labelError === null;
    }
    return hrefError === null && labelError === null;
  }

  render() {
    const { children } = this.props;
    const {
      label,
      primary,
      path,
      buttonType,
      assetType,
      href,
      error,
    } = this.state;
    return (
      <Box colorIndex="light-2" pad="medium">
        <Form>
          <FormFields>
            <fieldset>
              <FormField
                label="Label"
                error={error.label}
                help="Enter a label that will appear on the button"
                htmlFor="label"
              >
                <input
                  id="label"
                  name="label"
                  type="text"
                  value={label}
                  onChange={this.onChange}
                />
              </FormField>
              <FormField
                error={assetType === 'path' ? error.path : error.href}
                help={assetType === 'path'
                  ? 'Enter a path to an internal asset, such as /uploads/image.png'
                  : 'Enter a url to an external site, such as http://google.com/image.png'}
                label="Link"
                htmlFor={assetType === 'path' ? 'path' : 'href'}
              >
                {assetType === 'path' ?
                  <input
                    id="path"
                    name="path"
                    type="text"
                    value={path}
                    onChange={this.onChange}
                  />
                :
                  <input
                    id="href"
                    name="href"
                    type="text"
                    value={href}
                    onChange={this.onChange}
                  />
                }
              </FormField>
              <FormField
                label="Asset Link Type"
                help="What type of asset should the button link to?"
              >
                <Box direction="row" pad={{ vertical: 'small', horizontal: 'medium' }}>
                  <RadioButton
                    id="internal"
                    label="Internal Asset"
                    checked={(assetType === 'path')}
                    onChange={this.onChangeAssetType}
                    name="internal"
                  />
                  <RadioButton
                    id="external"
                    checked={(assetType !== 'path')}
                    label="External URL"
                    onChange={this.onChangeAssetType}
                    name="external"
                  />
                </Box>
              </FormField>
              <FormField
                label="Button Type"
                htmlFor="buttonType"
                help="What type of button would you like to use?  Button or Anchor?"
              >
                <Select
                  onChange={this.onChange}
                  value={buttonType || ''}
                  options={['Button', 'Anchor']}
                  name="buttonType"
                  id="buttonType"
                />
              </FormField>
              <FormField
                label="Primary"
                htmlFor="primary"
                help={buttonType === 'Anchor'
                  ? 'Should the anchor have the arrow icon in front of it?'
                  : 'Should the button be filled in with the brand color?'
                }
              >
                <Select
                  onChange={this.onChange}
                  value={primary || ''}
                  options={['True', 'False']}
                  name="primary"
                  id="primary"
                />
              </FormField>
            </fieldset>
            {assetType === 'path' && children && children}
          </FormFields>
          <Footer pad="medium">
            <Button
              onClick={this.onSubmit}
              type="submit"
              label="Done"
            />
          </Footer>
        </Form>
      </Box>
    );
  }
}

<|endoftext|>


<commit_before>cracklord.controller('JobsController', ['$scope', 'JobsService', 'QueueService', 'growl', 'ResourceList', '$interval', function JobsController($scope, JobsService, QueueService, growl, ResourceList, $interval) {
	var timer
	$scope.listreordered = false;

	$scope.sortableOptions = {
		handle: '.draghandle',
		axis: 'y',
		stop: function(e, ui) {
			$scope.listreordered = true;
		}
	};

	$scope.loadJobs = function() {
		$scope.jobs = JobsService.query(
			//Our success handler
			function(data) {
				$scope.listreordered = false;
				for(var i = 0; i < $scope.jobs.length; i++) {
					if($scope.jobs[i].resourceid) {
						var id = $scope.jobs[i].resourceid;
						var resource = ResourceList.get(id);
						if(resource) {
							$scope.jobs[i].resourcecolor = "background-color: rgb("+resource.color.r+","+resource.color.g+","+resource.color.b+");";
						}
					}
					$scope.jobs[i].expanded = false;
				}

			},
			//Our error handler
			function(error) {
				switch (error.status) {
					case 400: growl.error("You sent bad data, check your input and if it's correct get in touch with us on github"); break;
					case 403: growl.warning("You're not allowed to do that..."); break;
					case 404: growl.error("That object was not found."); break;
					case 409: growl.error("The request could not be completed because there was a conflict with the existing resource."); break;
					case 500: growl.error("An internal server error occured while trying to add the resource."); break;
				}
			}
		);
	}

	$scope.reloadJobs = function() {
		JobsService.query(
			function(data) {
				for(var i = 0; i < $scope.jobs.length; i++) {
					var jobid = $scope.jobs[i].id

					for(var j = 0; j < data.length; j++) {
						if(data[j].id === $scope.jobs[i].id) {
							for(var prop in data[j]) {
								if(data[j].hasOwnProperty(prop)) {
									$scope.jobs[i][prop] = data[j][prop]
								}
							}
						}
					}
				}
			},
			function(error) {
				growl.error("Unable to automatically update job data.")
			}
		)
	}

	//Setup a timer to refresh the data on a regular basis.
	timer = $interval(function() {
		$scope.reloadJobs();
	}, 15000);

	$scope.$on('$destroy', function() {
		$interval.cancel(timer)
	});

	//Initially we'll also load our data
	$scope.loadJobs();
}]);

cracklord.directive('jobReorderConfirm', ['QueueService', 'growl', function jobReorderConfirm(QueueService, growl) {
	return {
		restrict: 'E',
		templateUrl: 'components/Jobs/jobsReorderConfirm.html',
		replace: true,
		scope: {
			reload: "&",
			jobs: "=",
			dragstatus: "="
		},
		controller: function($scope) {
			$scope.reorderConfirm = function() {
				var ids = $scope.jobs.map(function (job) {
					if(job) {
						return job.id;
					}
				});

				QueueService.reorder(ids)
					.success(function(data, status, headers, config) {
						growl.success("Job data reordered successfully.");
						$scope.dragstatus = false;
						$scope.reload();
					})
					.error(function(data, status, headers, config) {
						switch (status) {
							case 400: growl.error("You sent bad data, check your input and if it's correct get in touch with us on github"); break;
							case 403: growl.warning("You're not allowed to do that..."); break;
							case 404: growl.error("Somehow the queue object was not found... this is bad."); break;
							case 409: growl.error("The request could not be completed because there was a conflict."); break;
							case 500: growl.error("An internal server error occured while trying to reorder the queue."); break;
						}
						$scope.dragstatus = false;
					});
			}

			$scope.reorderCancel = function() {
				$scope.dragstatus = false;
				$scope.reload();
				growl.info("Reordering of jobs cancelled.")
			}
		}
	}
}]);

cracklord.directive('jobDetail', ['JobsService', 'ToolsService', 'growl', 'ResourceList', '$interval', '$q', function jobDetail(JobsService, ToolsService, growl, ResourceList, $interval, $q) {
	return {
		restrict: 'E',
		templateUrl: 'components/Jobs/jobsViewDetail.html',
		scope: {
			jobid: '@',
			visibility: '='
		},
		controller: function($scope) {
			// Mmmmmmmm.... Donut.
			$scope.processDonut = function(animate) {
				$scope.donut = {};
				$scope.donut.labels = ['Processed', 'Remaining'];

				var total = 100 - $scope.detail.progress;
				$scope.donut.data = [$scope.detail.progress, total];
				$scope.donut.colors = [ '#337ab7', '#aaaaaa' ];
				$scope.donut.options = {
					'animateRotate': animate,
					'animation': animate
				}
			};

			$scope.processLine = function(animate) {
				$scope.line = {};
				$scope.line.series = [ $scope.detail.performancetitle ];
				$scope.line.data = [];
				$scope.line.data[0] = [];
				$scope.line.labels = [];
				$scope.line.options = {
					'pointDot': false,
					'showTooltips': false,
					'animation': animate
				};
				$scope.line.colors = [
					'#d43f3a'
				]

				for(var time in $scope.detail.performancedata) {
					$scope.line.data[0].push($scope.detail.performancedata[time]);
					$scope.line.labels.push("");
				}
			}
		},
		link: function($scope, $element, $attrs) {
			var timer

			$scope.loadData = function(animate) {
				return $q(function(resolve, reject) {
					JobsService.get({id: $scope.jobid},
						function success(data) {
							$scope.detail = data.job;
							$scope.processDonut(animate);
							$scope.processLine(animate);
							resolve();
						},
						function error(error) {
							growl.error("There was a problem loading job details.")
							$($element).find('div.slider').slideUp("slow", function() {
								$element.parent().hide();
							});
							reject();
						}
					);
				})
			}

			$scope.$watch('visibility', function(newval, oldval) {
				if(newval === true) {
					$scope.loadData(true).then(function() {
						if($scope.detail) {
							var resource = ResourceList.get($scope.detail.resourceid);
							if(resource) {
								$scope.resource = {}
								$scope.resource.name = resource.name;
							}

							ToolsService.get({id: $scope.detail.toolid},
								function toolsuccess(data) {
									$scope.tool = data.tool;
								}
							);
						}

						$element.parent().show();
						$element.find('.slider').slideDown();

						if(!timer) {
							timer = $interval(function() {
								//Disable the reload animation at this point
								$scope.loadData(false);
							}, 15000);
						}
					})
				} else {
					$interval.cancel(timer)
					timer = null
					$($element).find('div.slider').slideUp("slow", function() {
						$element.parent().hide();
					});
				}
			});

			$scope.$on('$destroy', function() {
				$interval.cancel(timer)
			});
		},
	}
}]);

cracklord.filter('currentJobs', ['JOB_STATUS_RUNNING', 'JOB_STATUS_COMPLETED', function(JOB_STATUS_RUNNING, JOB_STATUS_COMPLETED) {
	return function(items) {
		var filtered = [];
		for (var i = 0; i < items.length; i++) {
			var item = angularjs.copy(items[i]);
			if(JOB_STATUS_RUNNING.indexOf(item.status)) {
				filtered.push(item);
			}
		}
		return filtered;
	};
}]);

cracklord.controller('CreateJobController', ['$scope', '$state', 'ToolsService', 'JobsService', 'growl', function CreateJobController($scope, $state, ToolsService, JobsService, growl) {
	$scope.formData = {};
	$scope.formData.params = {};

	$scope.toolChange = function() {
		var id = $scope.formData.tool.id;
		var tool = ToolsService.get({id: id},
			function(data) {
				$scope.tool = data.tool;
			},
			function(error) {
				growl.error("An error occured while trying to load tool information.");
			}
		);
	}

	$scope.processNewJobForm = function() {
		var newjob = new JobsService();

		newjob.toolid = $scope.formData.tool.id;
		newjob.name = $scope.formData.name;
		newjob.params = $scope.formData.params;

		JobsService.save(newjob,
			function(data) {
				growl.success("Job successfully added");
				$state.transitionTo('jobs');
			},
			function(error) {
				switch (error.status) {
					case 400: growl.error("You sent bad data, check your input and if it's correct get in touch with us on github"); break;
					case 403: growl.warning("You're not allowed to do that..."); break;
					case 404: growl.error("That object was not found."); break;
					case 409: growl.error("The request could not be completed because there was a conflict with the existing resource."); break;
					case 500: growl.error("An internal server error occured while trying to add the resource."); break;
				}
			}
		);
	}
}]);<commit_msg>Resolves #53<commit_after>cracklord.controller('JobsController', ['$scope', 'JobsService', 'QueueService', 'growl', 'ResourceList', '$interval', function JobsController($scope, JobsService, QueueService, growl, ResourceList, $interval) {
	var timer
	$scope.listreordered = false;
	ResourceList.load();

	$scope.sortableOptions = {
		handle: '.draghandle',
		axis: 'y',
		stop: function(e, ui) {
			$scope.listreordered = true;
		}
	};

	$scope.loadJobs = function() {
		$scope.jobs = JobsService.query(
			//Our success handler
			function(data) {
				$scope.listreordered = false;
				for(var i = 0; i < $scope.jobs.length; i++) {
					if($scope.jobs[i].resourceid) {
						var id = $scope.jobs[i].resourceid;
						var resource = ResourceList.get(id);
						if(resource) {
							$scope.jobs[i].resourcecolor = "background-color: rgb("+resource.color.r+","+resource.color.g+","+resource.color.b+");";
						}
					}
					$scope.jobs[i].expanded = false;
				}

			},
			//Our error handler
			function(error) {
				switch (error.status) {
					case 400: growl.error("You sent bad data, check your input and if it's correct get in touch with us on github"); break;
					case 403: growl.warning("You're not allowed to do that..."); break;
					case 404: growl.error("That object was not found."); break;
					case 409: growl.error("The request could not be completed because there was a conflict with the existing resource."); break;
					case 500: growl.error("An internal server error occured while trying to add the resource."); break;
				}
			}
		);
	}

	$scope.reloadJobs = function() {
		JobsService.query(
			function(data) {
				for(var i = 0; i < $scope.jobs.length; i++) {
					var jobid = $scope.jobs[i].id

					for(var j = 0; j < data.length; j++) {
						if(data[j].id === $scope.jobs[i].id) {
							for(var prop in data[j]) {
								if(data[j].hasOwnProperty(prop)) {
									$scope.jobs[i][prop] = data[j][prop]
								}
							}
						}
					}
				}
			},
			function(error) {
				growl.error("Unable to automatically update job data.")
			}
		)
	}

	//Setup a timer to refresh the data on a regular basis.
	timer = $interval(function() {
		$scope.reloadJobs();
	}, 15000);

	$scope.$on('$destroy', function() {
		$interval.cancel(timer)
	});

	//Initially we'll also load our data
	$scope.loadJobs();
}]);

cracklord.directive('jobReorderConfirm', ['QueueService', 'growl', function jobReorderConfirm(QueueService, growl) {
	return {
		restrict: 'E',
		templateUrl: 'components/Jobs/jobsReorderConfirm.html',
		replace: true,
		scope: {
			reload: "&",
			jobs: "=",
			dragstatus: "="
		},
		controller: function($scope) {
			$scope.reorderConfirm = function() {
				var ids = $scope.jobs.map(function (job) {
					if(job) {
						return job.id;
					}
				});

				QueueService.reorder(ids)
					.success(function(data, status, headers, config) {
						growl.success("Job data reordered successfully.");
						$scope.dragstatus = false;
						$scope.reload();
					})
					.error(function(data, status, headers, config) {
						switch (status) {
							case 400: growl.error("You sent bad data, check your input and if it's correct get in touch with us on github"); break;
							case 403: growl.warning("You're not allowed to do that..."); break;
							case 404: growl.error("Somehow the queue object was not found... this is bad."); break;
							case 409: growl.error("The request could not be completed because there was a conflict."); break;
							case 500: growl.error("An internal server error occured while trying to reorder the queue."); break;
						}
						$scope.dragstatus = false;
					});
			}

			$scope.reorderCancel = function() {
				$scope.dragstatus = false;
				$scope.reload();
				growl.info("Reordering of jobs cancelled.")
			}
		}
	}
}]);

cracklord.directive('jobDetail', ['JobsService', 'ToolsService', 'growl', 'ResourceList', '$interval', '$q', function jobDetail(JobsService, ToolsService, growl, ResourceList, $interval, $q) {
	return {
		restrict: 'E',
		templateUrl: 'components/Jobs/jobsViewDetail.html',
		scope: {
			jobid: '@',
			visibility: '='
		},
		controller: function($scope) {
			// Mmmmmmmm.... Donut.
			$scope.processDonut = function(animate) {
				$scope.donut = {};
				$scope.donut.labels = ['Processed', 'Remaining'];

				var total = 100 - $scope.detail.progress;
				$scope.donut.data = [$scope.detail.progress, total];
				$scope.donut.colors = [ '#337ab7', '#aaaaaa' ];
				$scope.donut.options = {
					'animateRotate': animate,
					'animation': animate
				}
			};

			$scope.processLine = function(animate) {
				$scope.line = {};
				$scope.line.series = [ $scope.detail.performancetitle ];
				$scope.line.data = [];
				$scope.line.data[0] = [];
				$scope.line.labels = [];
				$scope.line.options = {
					'pointDot': false,
					'showTooltips': false,
					'animation': animate
				};
				$scope.line.colors = [
					'#d43f3a'
				]

				for(var time in $scope.detail.performancedata) {
					$scope.line.data[0].push($scope.detail.performancedata[time]);
					$scope.line.labels.push("");
				}
			}
		},
		link: function($scope, $element, $attrs) {
			var timer

			$scope.loadData = function(animate) {
				return $q(function(resolve, reject) {
					JobsService.get({id: $scope.jobid},
						function success(data) {
							$scope.detail = data.job;
							$scope.processDonut(animate);
							$scope.processLine(animate);
							resolve();
						},
						function error(error) {
							growl.error("There was a problem loading job details.")
							$($element).find('div.slider').slideUp("slow", function() {
								$element.parent().hide();
							});
							reject();
						}
					);
				})
			}

			$scope.$watch('visibility', function(newval, oldval) {
				if(newval === true) {
					$scope.loadData(true).then(function() {
						if($scope.detail) {
							var resource = ResourceList.get($scope.detail.resourceid);
							if(resource) {
								$scope.resource = {}
								$scope.resource.name = resource.name;
							}

							ToolsService.get({id: $scope.detail.toolid},
								function toolsuccess(data) {
									$scope.tool = data.tool;
								}
							);
						}

						$element.parent().show();
						$element.find('.slider').slideDown();

						if(!timer) {
							timer = $interval(function() {
								//Disable the reload animation at this point
								$scope.loadData(false);
							}, 15000);
						}
					})
				} else {
					$interval.cancel(timer)
					timer = null
					$($element).find('div.slider').slideUp("slow", function() {
						$element.parent().hide();
					});
				}
			});

			$scope.$on('$destroy', function() {
				$interval.cancel(timer)
			});
		},
	}
}]);

cracklord.filter('currentJobs', ['JOB_STATUS_RUNNING', 'JOB_STATUS_COMPLETED', function(JOB_STATUS_RUNNING, JOB_STATUS_COMPLETED) {
	return function(items) {
		var filtered = [];
		for (var i = 0; i < items.length; i++) {
			var item = angularjs.copy(items[i]);
			if(JOB_STATUS_RUNNING.indexOf(item.status)) {
				filtered.push(item);
			}
		}
		return filtered;
	};
}]);

cracklord.controller('CreateJobController', ['$scope', '$state', 'ToolsService', 'JobsService', 'growl', function CreateJobController($scope, $state, ToolsService, JobsService, growl) {
	$scope.formData = {};
	$scope.formData.params = {};

	$scope.toolChange = function() {
		var id = $scope.formData.tool.id;
		var tool = ToolsService.get({id: id},
			function(data) {
				$scope.tool = data.tool;
			},
			function(error) {
				growl.error("An error occured while trying to load tool information.");
			}
		);
	}

	$scope.processNewJobForm = function() {
		var newjob = new JobsService();

		newjob.toolid = $scope.formData.tool.id;
		newjob.name = $scope.formData.name;
		newjob.params = $scope.formData.params;

		JobsService.save(newjob,
			function(data) {
				growl.success("Job successfully added");
				$state.transitionTo('jobs');
			},
			function(error) {
				switch (error.status) {
					case 400: growl.error("You sent bad data, check your input and if it's correct get in touch with us on github"); break;
					case 403: growl.warning("You're not allowed to do that..."); break;
					case 404: growl.error("That object was not found."); break;
					case 409: growl.error("The request could not be completed because there was a conflict with the existing resource."); break;
					case 500: growl.error("An internal server error occured while trying to add the resource."); break;
				}
			}
		);
	}
}]);<|endoftext|>


<commit_before>// 已提交一览
mainApp.controller("flowSubmitListCtl", function ($scope, mineGrid, mineHttp, mineUtil) {
    mineHttp.constant("newsType", function (data) {
        $scope.newsTypes = data.content;
    });
    mineGrid.gridPageInit("gridOptions", $scope, {
        data: 'myData',
        multiSelect: false,
        selectWithCheckboxOnly: true,
        requestMethod: "POST",
        requestUrl: fullPath("admin/flow/list/submit"),
        columnDefs: [
            {field: 'processId', width: 80, displayName: '流程号'},
            {field: 'status', width: 70, displayName: '状态'},
            {field: 'businessSource', width: 70, displayName: '来源'},
            {field: 'businessType', width: 100, displayName: '类型'},
            {
                field: 'subject',
                displayName: '主题',
                cellTemplate: "<mine-action action='businessPreview(row.entity)' name='{{row.entity.subject}}'></mine-action>"
            },
            {field: 'nextTaskName', width: 150, displayName: '当前流程'},
            {field: 'taskName', width: 150, displayName: '已完成流程'},
            {field: 'processTime', width: 150, displayName: '申请时间'},
            {field: 'processTimeEnd', width: 150, displayName: '完成时间'},
            {
                field: 'id',
                displayName: '操作',
                width: 100,
                sortable: false,
                cellTemplate: "<mine-action icon='fa fa-sticky-note-o' action='preview(row.entity)' name='查看'></mine-action>"
            }
        ]
    });
    $scope.gridPageQueryCallback = function (data) {
        return {data: data.content.rows, total: data.content.total};
    };
    $scope.query = function () {
        $scope.gridPageQuery({}, $scope.filter);
    };
    $scope.businessPreview = function (flow) {
        mineUtil.modal("admin/_news/newsPreview.htm", "newsPreviewCtl", flow.businessNumber, "lg");
    };
    $scope.preview = function (flow) {
        mineUtil.modal("admin/_flow/flowPreview.htm", "flowPreviewCtl", flow, "lg");
    };
    $scope.query();
});
// 未通过一览
mainApp.controller("flowRejectListCtl", function ($scope, $state, mineGrid, mineHttp, mineUtil) {
    mineGrid.gridPageInit("gridOptions", $scope, {
        data: 'myData',
        multiSelect: false,
        selectWithCheckboxOnly: true,
        requestMethod: "POST",
        requestUrl: fullPath("admin/flow/list/reject"),
        columnDefs: [
            {field: 'processId', width: 80, displayName: '流程号'},
            {field: 'businessSource', width: 70, displayName: '来源'},
            {field: 'businessType', width: 100, displayName: '类型'},
            {
                field: 'subject',
                displayName: '主题',
                cellTemplate: "<mine-action action='businessPreview(row.entity)' name='{{row.entity.subject}}'></mine-action>"
            },
            {field: 'rejectTime', width: 150, displayName: '退回时间'},
            {
                field: 'id',
                displayName: '操作',
                width: 200,
                sortable: false,
                cellTemplate: "
<mine-action icon='fa fa-sticky-note-o' action='preview(row.entity)' name='查看'></mine-action>" +
                "<mine-action icon='fa fa-sticky-note-o' action='edit(row.entity)' name='修改'></mine-action>" +
                "<mine-action icon='fa fa-sticky-note-o' action='cancel(row.entity)' name='撤消'></mine-action>
"
            }
        ]
    });
    $scope.gridPageQueryCallback = function (data) {
        return {data: data.content.rows, total: data.content.total};
    };
    $scope.query = function () {
        $scope.gridPageQuery({}, $scope.filter);
    };
    $scope.businessPreview = function (flow) {
        mineUtil.modal("admin/_news/newsPreview.htm", "newsPreviewCtl", flow.businessNumber, "lg");
    };
    $scope.preview = function (flow) {
        mineUtil.modal("admin/_flow/flowPreview.htm", "flowPreviewCtl", flow, "lg");
    };
    $scope.edit = function (flow) {
        $state.go("news.edit", {number: flow.businessNumber});
    };
    $scope.cancel = function (flow) {
        alert(flow.businessNumber);
    };
    $scope.query();
});
// 待处理一览
mainApp.controller("flowPendingListCtl", function ($scope, $state, mineHttp, mineGrid, mineUtil) {
    mineHttp.constant("newsType", function (data) {
        $scope.newsTypes = data.content;
    });
    mineGrid.gridPageInit("gridOptions", $scope, {
        data: 'myData',
        multiSelect: false,
        selectWithCheckboxOnly: true,
        requestMethod: "POST",
        requestUrl: fullPath("admin/flow/list/pending"),
        columnDefs: [
            {field: 'processId', width: 80, displayName: '流程号'},
            {field: 'businessSource', width: 70, displayName: '来源'},
            {field: 'businessType', width: 100, displayName: '类型'},
            {
                field: 'subject',
                displayName: '主题',
                cellTemplate: "<mine-action action='preview(row.entity)' name='{{row.entity.subject}}'></mine-action>"
            },
            {field: 'applyUser', width: 150, displayName: '申请人'},
            {field: 'applyTime', width: 150, displayName: '申请时间'},
            {field: 'taskCreatedAt', width: 150, displayName: '接收时间'},
            {
                field: 'id',
                displayName: '操作',
                width: 150,
                sortable: false,
                cellTemplate: "<mine-action icon='fa fa-sticky-note-o' action='approve(row.entity)' name='审核'></mine-action>"
            }
        ]
    });
    $scope.gridPageQueryCallback = function (data) {
        return {data: data.content.rows, total: data.content.total};
    };
    $scope.query = function () {
        $scope.gridPageQuery({}, $scope.filter);
    };
    $scope.approve = function (flow) {
        $state.go("flow.approve", {taskId: flow.taskId, processId: flow.processId});
    };
    $scope.preview = function (flow) {
        mineUtil.modal("admin/_news/newsPreview.htm", "newsPreviewCtl", flow.businessNumber, "lg");
    };
    $scope.query();
});
// 已审批一览
mainApp.controller("flowApproveListCtl", function ($scope, $state, mineGrid, mineUtil) {
    mineGrid.gridPageInit("gridOptions", $scope, {
        data: 'myData',
        multiSelect: false,
        selectWithCheckboxOnly: true,
        requestMethod: "POST",
        requestUrl: fullPath("admin/flow/list/approve"),
        columnDefs: [
            {field: 'processId', width: 80, displayName: '流程号'},
            {field: 'taskId', width: 80, displayName: '任务号'},
            {field: 'businessSource', width: 70, displayName: '来源'},
            {field: 'businessType', width: 100, displayName: '类型'},
            {
                field: 'subject',
                displayName: '主题',
                cellTemplate: "<mine-action action='businessPreview(row.entity)' name='{{row.entity.subject}}'></mine-action>"
            },
            {field: 'taskName', width: 150, displayName: '处理流程'},
            {
                field: 'process',
                width: 150,
                displayName: '处理结果',
                cellTemplate: "{{row.entity.processMessage}}"
            },
            {field: 'processTime', width: 150, displayName: '处理时间'},
            {
                field: 'id',
                displayName: '操作',
                width: 150,
                sortable: false,
                cellTemplate: "<mine-action icon='fa fa-sticky-note-o' action='preview(row.entity)' name='详情'></mine-action>"
            }
        ]
    });
    $scope.gridPageQueryCallback = function (data) {
        return {data: data.content.rows, total: data.content.total};
    };
    $scope.query = function () {
        $scope.gridPageQuery({}, $scope.filter);
    };
    $scope.businessPreview = function (flow) {
        mineUtil.modal("admin/_news/newsPreview.htm", "newsPreviewCtl", flow.businessNumber, "lg");
    };
    $scope.preview = function (flow) {
        mineUtil.modal("admin/_flow/flowPreview.htm", "flowPreviewCtl", flow, "lg");
    };
    $scope.query();
});
// 审批页
mainApp.controller("flowApproveCtl", function ($scope, $stateParams, mineHttp, mineUtil) {
    var taskId = $stateParams.taskId;
    var processId = $stateParams.processId;
    $scope.approve = {};
    $scope.approve.taskId = taskId;
    $scope.approve.process = "2";
    $scope.preview = function (flow) {
        mineUtil.modal("admin/_news/newsPreview.htm", "newsPreviewCtl", flow.businessNumber, "lg");
    };
    mineHttp.send("GET", "admin/flow/" + processId + "/approve", null, function (result) {
        $scope.flow = result.content;
    });
    $scope.approveSubmit = function () {
        mineHttp.send("POST", "admin/flow/approve", {data: $scope.approve}, function (result) {
            $scope.flow = result.content;
        });
    }
});
// 审批预览页
mainApp.controller("flowPreviewCtl", function ($scope, $uibModalInstance, mineHttp, data) {
    mineHttp.send("GET", "admin/flow/" + data.processId, null, function (result) {
        $scope.flow = result.content;
        $scope.approveHistories = result.content.approveHistories;
    });
    $scope.cancel = function () {
        $uibModalInstance.dismiss('cancel');
    };
});<commit_msg>approve<commit_after>// 已提交一览
mainApp.controller("flowSubmitListCtl", function ($scope, mineGrid, mineHttp, mineUtil) {
    mineHttp.constant("newsType", function (data) {
        $scope.newsTypes = data.content;
    });
    mineGrid.gridPageInit("gridOptions", $scope, {
        data: 'myData',
        multiSelect: false,
        selectWithCheckboxOnly: true,
        requestMethod: "POST",
        requestUrl: fullPath("admin/flow/list/submit"),
        columnDefs: [
            {field: 'processId', width: 80, displayName: '流程号'},
            {field: 'status', width: 70, displayName: '状态'},
            {field: 'businessSource', width: 70, displayName: '来源'},
            {field: 'businessType', width: 100, displayName: '类型'},
            {
                field: 'subject',
                displayName: '主题',
                cellTemplate: "<mine-action action='businessPreview(row.entity)' name='{{row.entity.subject}}'></mine-action>"
            },
            {field: 'nextTaskName', width: 150, displayName: '当前流程'},
            {field: 'taskName', width: 150, displayName: '已完成流程'},
            {field: 'processTime', width: 150, displayName: '申请时间'},
            {field: 'processTimeEnd', width: 150, displayName: '完成时间'},
            {
                field: 'id',
                displayName: '操作',
                width: 100,
                sortable: false,
                cellTemplate: "<mine-action icon='fa fa-sticky-note-o' action='preview(row.entity)' name='查看'></mine-action>"
            }
        ]
    });
    $scope.gridPageQueryCallback = function (data) {
        return {data: data.content.rows, total: data.content.total};
    };
    $scope.query = function () {
        $scope.gridPageQuery({}, $scope.filter);
    };
    $scope.businessPreview = function (flow) {
        mineUtil.modal("admin/_news/newsPreview.htm", "newsPreviewCtl", flow.businessNumber, "lg");
    };
    $scope.preview = function (flow) {
        mineUtil.modal("admin/_flow/flowPreview.htm", "flowPreviewCtl", flow, "lg");
    };
    $scope.query();
});
// 未通过一览
mainApp.controller("flowRejectListCtl", function ($scope, $state, mineGrid, mineHttp, mineUtil) {
    mineGrid.gridPageInit("gridOptions", $scope, {
        data: 'myData',
        multiSelect: false,
        selectWithCheckboxOnly: true,
        requestMethod: "POST",
        requestUrl: fullPath("admin/flow/list/reject"),
        columnDefs: [
            {field: 'processId', width: 80, displayName: '流程号'},
            {field: 'businessSource', width: 70, displayName: '来源'},
            {field: 'businessType', width: 100, displayName: '类型'},
            {
                field: 'subject',
                displayName: '主题',
                cellTemplate: "<mine-action action='businessPreview(row.entity)' name='{{row.entity.subject}}'></mine-action>"
            },
            {field: 'rejectTime', width: 150, displayName: '退回时间'},
            {
                field: 'id',
                displayName: '操作',
                width: 200,
                sortable: false,
                cellTemplate: "
<mine-action icon='fa fa-sticky-note-o' action='preview(row.entity)' name='查看'></mine-action>" +
                "<mine-action icon='fa fa-sticky-note-o' action='edit(row.entity)' name='修改'></mine-action>" +
                "<mine-action icon='fa fa-sticky-note-o' action='cancel(row.entity)' name='撤消'></mine-action>
"
            }
        ]
    });
    $scope.gridPageQueryCallback = function (data) {
        return {data: data.content.rows, total: data.content.total};
    };
    $scope.query = function () {
        $scope.gridPageQuery({}, $scope.filter);
    };
    $scope.businessPreview = function (flow) {
        mineUtil.modal("admin/_news/newsPreview.htm", "newsPreviewCtl", flow.businessNumber, "lg");
    };
    $scope.preview = function (flow) {
        mineUtil.modal("admin/_flow/flowPreview.htm", "flowPreviewCtl", flow, "lg");
    };
    $scope.edit = function (flow) {
        $state.go("news.edit", {number: flow.businessNumber});
    };
    $scope.cancel = function (flow) {
        alert(flow.businessNumber);
    };
    $scope.query();
});
// 待处理一览
mainApp.controller("flowPendingListCtl", function ($scope, $state, mineHttp, mineGrid, mineUtil) {
    mineHttp.constant("newsType", function (data) {
        $scope.newsTypes = data.content;
    });
    mineGrid.gridPageInit("gridOptions", $scope, {
        data: 'myData',
        multiSelect: false,
        selectWithCheckboxOnly: true,
        requestMethod: "POST",
        requestUrl: fullPath("admin/flow/list/pending"),
        columnDefs: [
            {field: 'processId', width: 80, displayName: '流程号'},
            {field: 'businessSource', width: 70, displayName: '来源'},
            {field: 'businessType', width: 100, displayName: '类型'},
            {
                field: 'subject',
                displayName: '主题',
                cellTemplate: "<mine-action action='preview(row.entity)' name='{{row.entity.subject}}'></mine-action>"
            },
            {field: 'applyUser', width: 150, displayName: '申请人'},
            {field: 'applyTime', width: 150, displayName: '申请时间'},
            {field: 'receiveTime', width: 150, displayName: '接收时间'},
            {
                field: 'id',
                displayName: '操作',
                width: 150,
                sortable: false,
                cellTemplate: "<mine-action icon='fa fa-sticky-note-o' action='approve(row.entity)' name='审核'></mine-action>"
            }
        ]
    });
    $scope.gridPageQueryCallback = function (data) {
        return {data: data.content.rows, total: data.content.total};
    };
    $scope.query = function () {
        $scope.gridPageQuery({}, $scope.filter);
    };
    $scope.approve = function (flow) {
        $state.go("flow.approve", {taskId: flow.taskId, processId: flow.processId});
    };
    $scope.preview = function (flow) {
        mineUtil.modal("admin/_news/newsPreview.htm", "newsPreviewCtl", flow.businessNumber, "lg");
    };
    $scope.query();
});
// 已审批一览
mainApp.controller("flowApproveListCtl", function ($scope, $state, mineGrid, mineUtil) {
    mineGrid.gridPageInit("gridOptions", $scope, {
        data: 'myData',
        multiSelect: false,
        selectWithCheckboxOnly: true,
        requestMethod: "POST",
        requestUrl: fullPath("admin/flow/list/approve"),
        columnDefs: [
            {field: 'processId', width: 80, displayName: '流程号'},
            {field: 'taskId', width: 80, displayName: '任务号'},
            {field: 'businessSource', width: 70, displayName: '来源'},
            {field: 'businessType', width: 100, displayName: '类型'},
            {
                field: 'subject',
                displayName: '主题',
                cellTemplate: "<mine-action action='businessPreview(row.entity)' name='{{row.entity.subject}}'></mine-action>"
            },
            {field: 'taskName', width: 150, displayName: '处理流程'},
            {
                field: 'process',
                width: 150,
                displayName: '处理结果',
                cellTemplate: "{{row.entity.processMessage}}"
            },
            {field: 'processTime', width: 150, displayName: '处理时间'},
            {
                field: 'id',
                displayName: '操作',
                width: 150,
                sortable: false,
                cellTemplate: "<mine-action icon='fa fa-sticky-note-o' action='preview(row.entity)' name='详情'></mine-action>"
            }
        ]
    });
    $scope.gridPageQueryCallback = function (data) {
        return {data: data.content.rows, total: data.content.total};
    };
    $scope.query = function () {
        $scope.gridPageQuery({}, $scope.filter);
    };
    $scope.businessPreview = function (flow) {
        mineUtil.modal("admin/_news/newsPreview.htm", "newsPreviewCtl", flow.businessNumber, "lg");
    };
    $scope.preview = function (flow) {
        mineUtil.modal("admin/_flow/flowPreview.htm", "flowPreviewCtl", flow, "lg");
    };
    $scope.query();
});
// 审批页
mainApp.controller("flowApproveCtl", function ($scope, $stateParams, mineHttp, mineUtil) {
    var taskId = $stateParams.taskId;
    var processId = $stateParams.processId;
    $scope.approve = {};
    $scope.approve.taskId = taskId;
    $scope.approve.process = "2";
    $scope.preview = function (flow) {
        mineUtil.modal("admin/_news/newsPreview.htm", "newsPreviewCtl", flow.businessNumber, "lg");
    };
    mineHttp.send("GET", "admin/flow/" + processId + "/approve", null, function (result) {
        $scope.flow = result.content;
    });
    $scope.approveSubmit = function () {
        mineHttp.send("POST", "admin/flow/approve", {data: $scope.approve}, function (result) {
            $scope.flow = result.content;
        });
    }
});
// 审批预览页
mainApp.controller("flowPreviewCtl", function ($scope, $uibModalInstance, mineHttp, data) {
    mineHttp.send("GET", "admin/flow/" + data.processId, null, function (result) {
        $scope.flow = result.content;
        $scope.approveHistories = result.content.approveHistories;
    });
    $scope.cancel = function () {
        $uibModalInstance.dismiss('cancel');
    };
});<|endoftext|>