<commit_before> function get_tmax(data) {
  var tmax = 0;
  for (i = 0; i < data.dg.length; i++) {
    if (data.dg[i][0] > tmax) {
     tmax = data.dg[i][0];
    }
  }
  for (i = 0; i < data.ds.length; i++) {
    if (data.ds[i][0] > tmax) {
     tmax = data.ds[i][0];
    }
  }
  return tmax;
 }

 function get_ymax(data) {
  var ymax = data[0][1];
  for (i = 1; i < data.length; i++) {
    if (data[i][1] > ymax) {
     ymax = data[i][1];
    }
  }
  return ymax;
 }

 function get_ymin(data) {
  var ymin = data[0][1];
  for (i = 1; i < data.length; i++) {
    if (data[i][1] < ymin) {
     ymin = data[i][1];
    }
  }
  return ymin;
 }

 function update(data, id) {

 var colors = {"dg": "black", "ds": "steelblue"};

 var div_width = $('.svg-container').width();

  var margin = {top: 10, right: 80, bottom: 60, left: 80},
      width = 0.9 * div_width - margin.left - margin.right,
      height = 500 - margin.top - margin.bottom;

  var tmax = get_tmax(data);
  var dgmax = get_ymax(data.dg);
  var dgmin = get_ymin(data.dg);
  var dsmax = get_ymax(data.ds);
  var dsmin = get_ymin(data.ds);

  var y_dg = d3.scale.log()
       .domain([0.9 * dgmin, 1.1 * dgmax])
       .range([height, 0]);

  var y_ds = d3.scale.log()
       .domain([0.9 * dsmin, 1.1 * dsmax])
       .range([height, 0]);

 var y = {"dg": y_dg, "ds": y_ds};

  var x = d3.scale.linear()
       .domain([0, 1.1 * tmax])
       .range([0, width]);

  var xAxis = d3.svg.axis()
      .scale(x)
      .orient("bottom");

  var xAxisTop = d3.svg.axis()
     .scale(x)
     .orient("bottom")
     .tickFormat("");

  var yAxis_dg = d3.svg.axis()
      .scale(y_dg)
      .orient("left");

  var yAxis_ds = d3.svg.axis()
      .scale(y_ds)
      .orient("right");

  var chart_ext = d3.select("."+id)
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.bottom + margin.top);

  var chart = chart_ext.append("g")
       .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

  chart.append("g")
       .attr("class", "d3-axis")
       .attr("transform", "translate(0," + height + ")")
       .call(xAxis)
       .append("text")
       .attr("x", width / 2)
       .attr("y", 40)
       .style("text-anchor", "middle")
       .text("Time from infection [days]");

 // Draw the x Grid lines
 chart.append("g")
     .attr("class", "grid")
     .attr("transform", "translate(0," + height + ")")
     .call(make_x_axis()
         .tickSize(-height, 0, 0)
         .tickFormat("")
     );

 chart.append("g")
      .attr("class", "d3-axis")
      .call(xAxisTop);

 var dgTextBox = chart.append("g")
       .attr("class", "d3-axis")
       .call(yAxis_dg)
       .append("g")
       .attr("class", "d3-axis-textbox")
       .attr("transform", "rotate(-90)");

 dgTextBox.append("text")
       .attr("dy", "-4.7em")
       .attr("x", -height / 2)
       .style("text-anchor", "middle")
       .text("Divergence");

 dgTextBox.append("circle")
      .attr("class", "circles dgAxis")
      .attr("cy", "-5.1em")
      .attr("cx", -0.65 * height)
      .attr("r", 7)
      .style("fill", colors.dg);

 var dsTextBox = chart.append("g")
       .attr("class", "d3-axis")
       .attr("transform", "translate(" + width + " ,0)")
       .call(yAxis_ds)
       .append("g")
       .attr("class", "d3-axis-textbox")
       .attr("transform", "rotate(+90)");

 dsTextBox.append("text")
       .attr("dy", "-5em")
       .attr("x", height / 2)
       .style("text-anchor", "middle")
       .text("Diversity");

 dsTextBox.append("rect")
      .attr("class", "circles dsAxis")
      .attr("y", "-5.8em")
      .attr("x", 0.35 * height)
      .attr("width", 14)
      .attr("height", 14)
      .style("fill", colors.ds);

  chart.append("g")
       .attr("class", "circles DG")
       .selectAll()
       .data(data.dg)
       .enter()
       .append("circle")
       .attr("class", "circle")
       .attr("cx", function(d) { return x(d[0]); })
       .attr("cy", function(d) { return y_dg(d[1]); })
       .attr("r", 6);

  chart.append("g")
       .attr("class", "circles DS")
       .selectAll()
       .data(data.ds)
       .enter()
       .append("rect")
       .attr("class", "rect")
       .attr("x", function(d) { return x(d[0]) - 3; })
       .attr("y", function(d) { return y_ds(d[1]) - 3; })
       .attr("width", 12)
       .attr("height", 12)
       .style("fill", "steelblue");

 // function for the x grid lines
 function make_x_axis() {
     return d3.svg.axis()
         .scale(x)
         .orient("bottom");
 }

 }

<commit_msg>Grids for divdiv<commit_after> function get_tmax(data) {
  var tmax = 0;
  for (i = 0; i < data.dg.length; i++) {
    if (data.dg[i][0] > tmax) {
     tmax = data.dg[i][0];
    }
  }
  for (i = 0; i < data.ds.length; i++) {
    if (data.ds[i][0] > tmax) {
     tmax = data.ds[i][0];
    }
  }
  return tmax;
 }

 function get_ymax(data) {
  var ymax = data[0][1];
  for (i = 1; i < data.length; i++) {
    if (data[i][1] > ymax) {
     ymax = data[i][1];
    }
  }
  return ymax;
 }

 function get_ymin(data) {
  var ymin = data[0][1];
  for (i = 1; i < data.length; i++) {
    if (data[i][1] < ymin) {
     ymin = data[i][1];
    }
  }
  return ymin;
 }

 function update(data, id) {

 var colors = {"dg": "black", "ds": "steelblue"};

 var div_width = $('.svg-container').width();

  var margin = {top: 10, right: 80, bottom: 60, left: 80},
      width = 0.9 * div_width - margin.left - margin.right,
      height = 500 - margin.top - margin.bottom;

  var tmax = get_tmax(data);
  var dgmax = get_ymax(data.dg);
  var dgmin = get_ymin(data.dg);
  var dsmax = get_ymax(data.ds);
  var dsmin = get_ymin(data.ds);

  var y = d3.scale.log()
       .domain([1e-3, 0.5])
       .range([height, 0]);

  var x = d3.scale.linear()
       .domain([0, 1.1 * tmax])
       .range([0, width]);

  var xAxis = d3.svg.axis()
      .scale(x)
      .orient("bottom");

  var xAxisTop = d3.svg.axis()
     .scale(x)
     .orient("bottom")
     .tickFormat("");

 var xAxisGrid = d3.svg.axis()
      .scale(x)
      .orient("bottom")
      .tickSize(-height, 0, 0)
      .tickFormat("");

  var yAxis_dg = d3.svg.axis()
      .scale(y)
      .orient("left");

  var yAxis_ds = d3.svg.axis()
      .scale(y)
      .orient("right");

 var yAxisGrid = d3.svg.axis()
      .scale(y)
      .orient("right")
      .tickSize(width, 0, 0)
      .tickFormat("");

  var chart_ext = d3.select("."+id)
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.bottom + margin.top);

  var chart = chart_ext.append("g")
       .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

 // Draw the grid lines (they should stay behind)
 chart.append("g")
     .attr("class", "grid")
     .attr("transform", "translate(0," + height + ")")
     .call(xAxisGrid);

 chart.append("g")
     .attr("class", "grid")
     .call(yAxisGrid);

 chart.append("g")
       .attr("class", "d3-axis")
       .attr("transform", "translate(0," + height + ")")
       .call(xAxis)
       .append("text")
       .attr("x", width / 2)
       .attr("y", 40)
       .style("text-anchor", "middle")
       .text("Time from infection [days]");

 chart.append("g")
      .attr("class", "d3-axis")
      .call(xAxisTop);

 var dgTextBox = chart.append("g")
       .attr("class", "d3-axis")
       .call(yAxis_dg)
       .append("g")
       .attr("class", "d3-axis-textbox")
       .attr("transform", "rotate(-90)");

 dgTextBox.append("text")
       .attr("dy", "-4.7em")
       .attr("x", -height / 2)
       .style("text-anchor", "middle")
       .text("Divergence");

 dgTextBox.append("circle")
      .attr("class", "circles dgAxis")
      .attr("cy", "-5.1em")
      .attr("cx", -0.65 * height)
      .attr("r", 7)
      .style("fill", colors.dg);

 var dsTextBox = chart.append("g")
       .attr("class", "d3-axis")
       .attr("transform", "translate(" + width + " ,0)")
       .call(yAxis_ds)
       .append("g")
       .attr("class", "d3-axis-textbox")
       .attr("transform", "rotate(+90)");

 dsTextBox.append("text")
       .attr("dy", "-5em")
       .attr("x", height / 2)
       .style("text-anchor", "middle")
       .text("Diversity");

 dsTextBox.append("rect")
      .attr("class", "circles dsAxis")
      .attr("y", "-5.8em")
      .attr("x", 0.35 * height)
      .attr("width", 14)
      .attr("height", 14)
      .style("fill", colors.ds);

  chart.append("g")
       .attr("class", "circles DG")
       .selectAll()
       .data(data.dg)
       .enter()
       .append("circle")
       .attr("class", "circle")
       .attr("cx", function(d) { return x(d[0]); })
       .attr("cy", function(d) { return y(d[1]); })
       .attr("r", 6);

  chart.append("g")
       .attr("class", "circles DS")
       .selectAll()
       .data(data.ds)
       .enter()
       .append("rect")
       .attr("class", "rect")
       .attr("x", function(d) { return x(d[0]) - 3; })
       .attr("y", function(d) { return y(d[1]) - 3; })
       .attr("width", 12)
       .attr("height", 12)
       .style("fill", "steelblue");

 }

<|endoftext|>


<commit_before>var maze;
var mazeGenerator;

function setup(){
  createCanvas(windowWidth, windowHeight);
  maze = new Maze(width, height);
  frameRate(30);
  strokeWeight(4);

  let startingCell = maze.startingCell();
  mazeGenerator = new MazeGenerator(maze, startingCell);
}

function draw(){
  background(0);
  mazeGenerator.tick();
  maze.draw();
  mazeGenerator.draw();
}

function mousePressed(){
  mazeGenerator.tick();
}

class Maze {
  constructor(_width, _height) {
    this.cellWidth = 40;
    let mazeWidth = floor(width / this.cellWidth) * this.cellWidth;
    let mazeHeight = floor(height / this.cellWidth) * this.cellWidth;
    this.mazeSize = new Rect(0, 0, mazeWidth, mazeHeight);
    this.grid = new CellGrid(this.mazeSize, this, this.cellWidth);
    this.grid.initCells();

    // this.startingCell().state = MazeCell.CELL_OPEN;
    // this.targetCell().state = MazeCell.CELL_OPEN;
  }

  startingCell(){
    return this.grid.cells[this.grid.numCols + 1];
  }

  targetCell(){
    return this.grid.cells[this.numCells - this.grid.numCols - 1];
  }

  createCell(tmpRow, tmpCol, i){
    let cell = new MazeCell(tmpRow, tmpCol, i, this);

    if (this.grid.isEdgeRowCol(tmpRow, tmpCol)) {
      // effectively make walls around the overall grid
      cell.state = MazeCell.CELL_SOLID;
      cell.bottomWall = MazeCell.WALL_SOLID;
      cell.rightWall = MazeCell.WALL_SOLID;
    }
    if (tmpRow == this.grid.numRows-2){
      cell.bottomWall = MazeCell.WALL_SOLID;
    }
    if (tmpCol == this.grid.numCols-2){
      cell.rightWall = MazeCell.WALL_SOLID;
    }
    return cell;
  }

  draw(){
    this.grid.renderViews();
  }
}

class MazeGenerator {
  constructor(maze, cell, targetCell){
    this.maze = maze;
    this.visitedCells = [];
    this.moveToCell(cell);
    this.targetCell = targetCell;
    this.state = MazeGenerator.STATE_GENERATING;
  }

  static get STATE_GENERATING(){ return 0; }
  static get STATE_STUCK(){ return -1; }

  get x(){
    return this.maze.cellWidth/2 + this.cell._col * this.maze.cellWidth;
  }
  get y(){
    return this.maze.cellWidth/2 + this.cell._row * this.maze.cellWidth;
  }

  tick(){
    if (this.cell == this.maze.targetCell()){
      // console.log("Got to the end!");
      return;
    }

    this.exploreCell();
  }

  moveToCell(cell){
    if (this.cell != undefined){
      this.visitedCells.push(this.cell);
    }
    this.cell = cell;
    this.cell.state = MazeCell.CELL_OPEN;
  }

  exploreCell(){
    let unknownWalls = this.cell.unknownWalls;

    if (unknownWalls == undefined || unknownWalls.length == 0){
      this.stepBackwards();
      return;
    }

    let selectedWall;
    if (unknownWalls.length == 1){
      // console.log("... only one choice");
      selectedWall = unknownWalls[0];
      if (!this.canWalkInDirection(selectedWall)){
        this.cell.closeWall(selectedWall);
        return;
      }
    }else{
      let randomSelection = floor(random(unknownWalls.length));
      selectedWall = unknownWalls[randomSelection];
      // console.log("selected wall: " + selectedWall);

      if (!this.canWalkInDirection(selectedWall)){
        this.cell.closeWall(selectedWall);
        return;
      }

      let randomClose = floor(random(5));
      if (randomClose == 0) {
        let nextIdx = (randomSelection+1) % unknownWalls.length;
        let wallToClose = unknownWalls[nextIdx];
        // console.log("Wall to close: " + wallToClose);
        this.cell.closeWall(wallToClose);
      }
    }

    this.cell.openWall(selectedWall);
    this.walkInDirection(selectedWall);
  }

  stepBackwards(){
    if (this.visitedCells.length == 0){
      // console.log("stuck, painted into a corner");
      this.state = MazeGenerator.STATE_STUCK;
      return;
    }

    this.cell = this.visitedCells.pop();
  }

  canWalkInDirection(direction){
    // before walking/opening doors, should check that next Cell is not
    // in the visitedCells (should not loop back)
    // ... if it is:
    // close the selected Wall, and choose another wall
    let potentialCell = this.cellForDirection(direction);
    let alreadyVisited = this.visitedCells.includes(potentialCell);
    return !alreadyVisited;
  }

  walkInDirection(direction){
    this.moveToCell(this.cellForDirection(direction));
  }

  cellForDirection(direction){
    switch(direction) {
      case 0:
        return this.cell.cellAbove;
      case 1:
        return this.cell.cellToRight;
      case 2:
        return this.cell.cellBelow;
      case 3:
        return this.cell.cellToLeft;
    }
  }

  draw(){
    fill(200, 200, 50);
    noStroke();
    let cellWidth = maze.cellWidth;
    ellipse(this.x, this.y, 0.5 * cellWidth, 0.5 * cellWidth);
  }
}

class MazeCell {
  constructor(row, col, index, maze){
    // variable names are dictated by CellGrid
    this._row = row;
    this._col = col;
    this._idx = index;

    this.maze = maze;
    this.grid = maze.grid;
    this.rightWall = MazeCell.WALL_UNKNOWN;
    this.bottomWall = MazeCell.WALL_UNKNOWN;
    this.state = MazeCell.CELL_UNKNOWN;
  }

  get cellAbove() { return this.grid.cellAbove(this._idx); }
  get cellToRight() { return this.grid.cellToRight(this._idx); }
  get cellBelow() { return this.grid.cellBelow(this._idx); }
  get cellToLeft() { return this.grid.cellToLeft(this._idx); }

  static get WALL_UNKNOWN(){ return -1; }
  static get WALL_OPEN(){ return 0; }
  static get WALL_SOLID(){ return 1; }

  static get CELL_UNKNOWN(){ return -1; }
  static get CELL_OPEN(){ return 0; }
  static get CELL_SOLID(){ return 1; }

  static get REJECTED(){ return -2; }

  get leftWall() {
    let idxToLeft = this.grid.cellIndexToLeft(this._idx);
    if (idxToLeft == undefined){
      return MazeCell.WALL_SOLID;
    }

    let cell =  this.grid.cells[idxToLeft];
    if (cell.state == MazeCell.CELL_SOLID){
      return MazeCell.WALL_SOLID;
    }else{
      return cell.rightWall;
    }
  }

  get topWall() {
    let idxToAbove = this.grid.cellIndexAbove(this._idx);
    if (idxToAbove == undefined){
      return MazeCell.WALL_SOLID;
    }

    let cell =  this.grid.cells[idxToAbove];
    if (cell.state == MazeCell.CELL_SOLID){
      return MazeCell.WALL_SOLID;
    }else{
      return cell.bottomWall;
    }
  }

  openWall(wallIdx){
    switch(wallIdx) {
      case 0:
        this.cellAbove.bottomWall = MazeCell.WALL_OPEN;
        break;
      case 1:
        this.rightWall = MazeCell.WALL_OPEN;
        break;
      case 2:
        this.bottomWall = MazeCell.WALL_OPEN;
        break;
      case 3:
        this.cellToLeft.rightWall = MazeCell.WALL_OPEN;
        break;
    }
  }

  closeWall(wallIdx){
    switch(wallIdx) {
      case 0:
        this.cellAbove.bottomWall = MazeCell.WALL_SOLID;
        break;
      case 1:
        this.rightWall = MazeCell.WALL_SOLID;
        break;
      case 2:
        this.bottomWall = MazeCell.WALL_SOLID;
        break;
      case 3:
        this.cellToLeft.rightWall = MazeCell.WALL_SOLID;
        break;
    }
  }

  get walls(){ return [this.topWall, this.rightWall, this.bottomWall, this.leftWall]; }

  get unknownWalls(){
    return this.walls.map( (wall, i) => {
        return (wall == MazeCell.WALL_UNKNOWN) ? i : MazeCell.REJECTED;
      }).filter( (idx) => {return idx != MazeCell.REJECTED; });
  }

  get openWalls(){
    return this.walls.map( (wall, i) => {
        return (wall == MazeCell.WALL_OPEN) ? i : MazeCell.REJECTED;
      }).filter( (idx) => {return idx != MazeCell.REJECTED; });
  }

  static get wall_states(){
    return [MazeCell.WALL_UNKNOWN, MazeCell.WALL_OPEN, MazeCell.WALL_SOLID];
  }

  static get cell_states(){
    return [MazeCell.CELL_UNKNOWN, MazeCell.CELL_OPEN, MazeCell.CELL_SOLID];
  }
}

// Class name is dictated by CellGrid
class CellViewer {
  renderCell(tmpCell, tmpX, tmpY, cellWidth, cellHeight){
    fill(this.colorForCellState(tmpCell.state));
    noStroke();
    rect(tmpX, tmpY, cellWidth, cellHeight);

    stroke(this.colorForWallState(tmpCell.rightWall));
    line(tmpX + cellWidth, tmpY, tmpX + cellWidth, tmpY + cellHeight);

    stroke(this.colorForWallState(tmpCell.bottomWall));
    line(tmpX, tmpY + cellHeight, tmpX + cellWidth, tmpY + cellHeight);
  }

  get colors(){
    return {
      unknown: color(80),
      unknown_line: color(120),
      open: color(100, 180, 100),
      open_line: color(120, 200, 120),
      solid: color(0)
    };
  }

  colorForWallState(wallState){
    switch (wallState) {
      case MazeCell.WALL_UNKNOWN: return this.colors.unknown_line;
      case MazeCell.WALL_OPEN:    return this.colors.open_line;
      case MazeCell.WALL_SOLID: return this.colors.solid;
    }
  }

  colorForCellState(cellState){
    switch (cellState) {
      case MazeCell.CELL_UNKNOWN: return this.colors.unknown;
      case MazeCell.CELL_OPEN:    return this.colors.open;
      case MazeCell.CELL_SOLID:   return this.colors.solid;
    }
  }
}
<commit_msg>p5js/maze-generator - Refactor leftWall and topWall<commit_after>var maze;
var mazeGenerator;

function setup(){
  createCanvas(windowWidth, windowHeight);
  maze = new Maze(width, height);
  frameRate(30);
  strokeWeight(4);

  let startingCell = maze.startingCell();
  mazeGenerator = new MazeGenerator(maze, startingCell);
}

function draw(){
  background(0);
  mazeGenerator.tick();
  maze.draw();
  mazeGenerator.draw();
}

function mousePressed(){
  mazeGenerator.tick();
}

class Maze {
  constructor(_width, _height) {
    this.cellWidth = 40;
    let mazeWidth = floor(width / this.cellWidth) * this.cellWidth;
    let mazeHeight = floor(height / this.cellWidth) * this.cellWidth;
    this.mazeSize = new Rect(0, 0, mazeWidth, mazeHeight);
    this.grid = new CellGrid(this.mazeSize, this, this.cellWidth);
    this.grid.initCells();

    // this.startingCell().state = MazeCell.CELL_OPEN;
    // this.targetCell().state = MazeCell.CELL_OPEN;
  }

  startingCell(){
    return this.grid.cells[this.grid.numCols + 1];
  }

  targetCell(){
    return this.grid.cells[this.numCells - this.grid.numCols - 1];
  }

  createCell(tmpRow, tmpCol, i){
    let cell = new MazeCell(tmpRow, tmpCol, i, this);

    if (this.grid.isEdgeRowCol(tmpRow, tmpCol)) {
      // effectively make walls around the overall grid
      cell.state = MazeCell.CELL_SOLID;
      cell.bottomWall = MazeCell.WALL_SOLID;
      cell.rightWall = MazeCell.WALL_SOLID;
    }
    if (tmpRow == this.grid.numRows-2){
      cell.bottomWall = MazeCell.WALL_SOLID;
    }
    if (tmpCol == this.grid.numCols-2){
      cell.rightWall = MazeCell.WALL_SOLID;
    }
    return cell;
  }

  draw(){
    this.grid.renderViews();
  }
}

class MazeGenerator {
  constructor(maze, cell, targetCell){
    this.maze = maze;
    this.visitedCells = [];
    this.moveToCell(cell);
    this.targetCell = targetCell;
    this.state = MazeGenerator.STATE_GENERATING;
  }

  static get STATE_GENERATING(){ return 0; }
  static get STATE_STUCK(){ return -1; }

  get x(){
    return this.maze.cellWidth/2 + this.cell._col * this.maze.cellWidth;
  }
  get y(){
    return this.maze.cellWidth/2 + this.cell._row * this.maze.cellWidth;
  }

  tick(){
    if (this.cell == this.maze.targetCell()){
      // console.log("Got to the end!");
      return;
    }

    this.exploreCell();
  }

  moveToCell(cell){
    if (this.cell != undefined){
      this.visitedCells.push(this.cell);
    }
    this.cell = cell;
    this.cell.state = MazeCell.CELL_OPEN;
  }

  exploreCell(){
    let unknownWalls = this.cell.unknownWalls;

    if (unknownWalls == undefined || unknownWalls.length == 0){
      this.stepBackwards();
      return;
    }

    let selectedWall;
    if (unknownWalls.length == 1){
      // console.log("... only one choice");
      selectedWall = unknownWalls[0];
      if (!this.canWalkInDirection(selectedWall)){
        this.cell.closeWall(selectedWall);
        return;
      }
    }else{
      let randomSelection = floor(random(unknownWalls.length));
      selectedWall = unknownWalls[randomSelection];
      // console.log("selected wall: " + selectedWall);

      if (!this.canWalkInDirection(selectedWall)){
        this.cell.closeWall(selectedWall);
        return;
      }

      let randomClose = floor(random(5));
      if (randomClose == 0) {
        let nextIdx = (randomSelection+1) % unknownWalls.length;
        let wallToClose = unknownWalls[nextIdx];
        // console.log("Wall to close: " + wallToClose);
        this.cell.closeWall(wallToClose);
      }
    }

    this.cell.openWall(selectedWall);
    this.walkInDirection(selectedWall);
  }

  stepBackwards(){
    if (this.visitedCells.length == 0){
      // console.log("stuck, painted into a corner");
      this.state = MazeGenerator.STATE_STUCK;
      return;
    }

    this.cell = this.visitedCells.pop();
  }

  canWalkInDirection(direction){
    // before walking/opening doors, should check that next Cell is not
    // in the visitedCells (should not loop back)
    // ... if it is:
    // close the selected Wall, and choose another wall
    let potentialCell = this.cellForDirection(direction);
    let alreadyVisited = this.visitedCells.includes(potentialCell);
    return !alreadyVisited;
  }

  walkInDirection(direction){
    this.moveToCell(this.cellForDirection(direction));
  }

  cellForDirection(direction){
    switch(direction) {
      case 0:
        return this.cell.cellAbove;
      case 1:
        return this.cell.cellToRight;
      case 2:
        return this.cell.cellBelow;
      case 3:
        return this.cell.cellToLeft;
    }
  }

  draw(){
    fill(200, 200, 50);
    noStroke();
    let cellWidth = maze.cellWidth;
    ellipse(this.x, this.y, 0.5 * cellWidth, 0.5 * cellWidth);
  }
}

class MazeCell {
  constructor(row, col, index, maze){
    // variable names are dictated by CellGrid
    this._row = row;
    this._col = col;
    this._idx = index;

    this.maze = maze;
    this.grid = maze.grid;
    this.rightWall = MazeCell.WALL_UNKNOWN;
    this.bottomWall = MazeCell.WALL_UNKNOWN;
    this.state = MazeCell.CELL_UNKNOWN;
  }

  get cellAbove() { return this.grid.cellAbove(this._idx); }
  get cellToRight() { return this.grid.cellToRight(this._idx); }
  get cellBelow() { return this.grid.cellBelow(this._idx); }
  get cellToLeft() { return this.grid.cellToLeft(this._idx); }

  static get WALL_UNKNOWN(){ return -1; }
  static get WALL_OPEN(){ return 0; }
  static get WALL_SOLID(){ return 1; }

  static get CELL_UNKNOWN(){ return -1; }
  static get CELL_OPEN(){ return 0; }
  static get CELL_SOLID(){ return 1; }

  static get REJECTED(){ return -2; }

  get leftWall() {
    return this.cellToLeft.rightWall;
  }

  get topWall() {
    return this.cellAbove.bottomWall;
  }

  openWall(wallIdx){
    switch(wallIdx) {
      case 0:
        this.cellAbove.bottomWall = MazeCell.WALL_OPEN;
        break;
      case 1:
        this.rightWall = MazeCell.WALL_OPEN;
        break;
      case 2:
        this.bottomWall = MazeCell.WALL_OPEN;
        break;
      case 3:
        this.cellToLeft.rightWall = MazeCell.WALL_OPEN;
        break;
    }
  }

  closeWall(wallIdx){
    switch(wallIdx) {
      case 0:
        this.cellAbove.bottomWall = MazeCell.WALL_SOLID;
        break;
      case 1:
        this.rightWall = MazeCell.WALL_SOLID;
        break;
      case 2:
        this.bottomWall = MazeCell.WALL_SOLID;
        break;
      case 3:
        this.cellToLeft.rightWall = MazeCell.WALL_SOLID;
        break;
    }
  }

  get walls(){ return [this.topWall, this.rightWall, this.bottomWall, this.leftWall]; }

  get unknownWalls(){
    return this.walls.map( (wall, i) => {
        return (wall == MazeCell.WALL_UNKNOWN) ? i : MazeCell.REJECTED;
      }).filter( (idx) => {return idx != MazeCell.REJECTED; });
  }

  get openWalls(){
    return this.walls.map( (wall, i) => {
        return (wall == MazeCell.WALL_OPEN) ? i : MazeCell.REJECTED;
      }).filter( (idx) => {return idx != MazeCell.REJECTED; });
  }

  static get wall_states(){
    return [MazeCell.WALL_UNKNOWN, MazeCell.WALL_OPEN, MazeCell.WALL_SOLID];
  }

  static get cell_states(){
    return [MazeCell.CELL_UNKNOWN, MazeCell.CELL_OPEN, MazeCell.CELL_SOLID];
  }
}

// Class name is dictated by CellGrid
class CellViewer {
  renderCell(tmpCell, tmpX, tmpY, cellWidth, cellHeight){
    fill(this.colorForCellState(tmpCell.state));
    noStroke();
    rect(tmpX, tmpY, cellWidth, cellHeight);

    stroke(this.colorForWallState(tmpCell.rightWall));
    line(tmpX + cellWidth, tmpY, tmpX + cellWidth, tmpY + cellHeight);

    stroke(this.colorForWallState(tmpCell.bottomWall));
    line(tmpX, tmpY + cellHeight, tmpX + cellWidth, tmpY + cellHeight);
  }

  get colors(){
    return {
      unknown: color(80),
      unknown_line: color(120),
      open: color(100, 180, 100),
      open_line: color(120, 200, 120),
      solid: color(0)
    };
  }

  colorForWallState(wallState){
    switch (wallState) {
      case MazeCell.WALL_UNKNOWN: return this.colors.unknown_line;
      case MazeCell.WALL_OPEN:    return this.colors.open_line;
      case MazeCell.WALL_SOLID: return this.colors.solid;
    }
  }

  colorForCellState(cellState){
    switch (cellState) {
      case MazeCell.CELL_UNKNOWN: return this.colors.unknown;
      case MazeCell.CELL_OPEN:    return this.colors.open;
      case MazeCell.CELL_SOLID:   return this.colors.solid;
    }
  }
}
<|endoftext|>


<commit_before>const moment = require('moment')
const { compact, mapValues, get, isPlainObject, isNull } = require('lodash')
const { buildCompanyUrl } = require('../../companies/services/data')
const metadataRepository = require('../../../lib/metadata')

function formatCurrency (number) {
  if (isNull(number)) { return null }

  return new Intl.NumberFormat('en-GB', {
    style: 'currency',
    currency: 'GBP',
    minimumFractionDigits: 0,
  }).format(number)
}

function transformToApi (body) {
  if (!isPlainObject(body)) { return }

  const schema = {
    'client_relationship_manager': Object,
    'referral_source_adviser': Object,
    'referral_source_activity': Object,
    'referral_source_activity_marketing': Object,
    'referral_source_activity_website': Object,
    'investor_company': Object,
    'investment_type': Object,
    'fdi_type': Object,
    'non_fdi_type': Object,
    'sector': Object,
    'client_contacts': Array,
    'business_activities': Array,
  }

  const relationshipMgr = body['is-relationship-manager']
  if (relationshipMgr !== 'No') {
    body.client_relationship_manager = relationshipMgr
  }

  const referralSource = body['is-referral-source']
  if (referralSource !== 'No') {
    body.referral_source_adviser = referralSource
  }

  const formatted = mapValues(schema, (type, key) => {
    const value = body[key]

    if (!value) {
      return
    }

    if (type === Array) {
      return [{ id: value }]
    }

    return { id: value }
  })

  formatted['estimated_land_date'] = `${body['land-date_year']}-${body['land-date_month']}-01`

  return Object.assign({}, body, formatted)
}

function transformFromApi (body) {
  if (!isPlainObject(body)) { return }

  const schema = {
    'client_relationship_manager': String,
    'referral_source_adviser': String,
    'referral_source_activity': String,
    'referral_source_activity_marketing': String,
    'referral_source_activity_website': String,
    'investor_company': String,
    'investment_type': String,
    'fdi_type': String,
    'non_fdi_type': String,
    'sector': String,
    'client_contacts': Array,
    'business_activities': Array,
  }

  const formatted = mapValues(schema, (type, key) => {
    if (type === Array) {
      return get(body, `${key}[0].id`, '')
    }
    return get(body, `${key}.id`)
  })

  const date = new Date(body['estimated_land_date'])
  if (date) {
    formatted['land-date_year'] = date.getFullYear()
    formatted['land-date_month'] = date.getMonth() + 1 // month is zero based index
  }

  return Object.assign({}, body, formatted)
}

function transformInvestmentDataForView (data) {
  if (!isPlainObject(data)) { return }

  function getInvestmentTypeDetails () {
    const types = [
      data.investment_type.name,
      get(data, 'fdi_type.name'),
      get(data, 'non_fdi_type.name'),
    ]
    return compact(types).join(', ')
  }

  return Object.assign({}, data, {
    investor_company: {
      name: data.investor_company.name,
      url: buildCompanyUrl(data.investor_company),
    },
    investment_type: getInvestmentTypeDetails(),
    sector: get(data, 'sector.name', null),
    business_activities: data.business_activities.map(i => i.name).join(', '),
    nda_signed: data.nda_signed ? 'Signed' : 'Not signed',
    estimated_land_date: data.estimated_land_date ? moment(data.estimated_land_date).format('MMMM YYYY') : null,
  })
}

function transformInvestmentValueForView (data) {
  if (!isPlainObject(data)) { return }

  function formatBoolean (boolean, { suffix = '', pos = 'Yes', neg = 'No' }) {
    if (isNull(boolean)) { return null }
    return (data.government_assistance ? pos : neg) + suffix
  }

  return Object.assign({}, data, {
    total_investment: formatCurrency(data.total_investment),
    foreign_equity_investment: formatCurrency(data.foreign_equity_investment),
    number_new_jobs: data.number_new_jobs && `${data.number_new_jobs} new jobs`,
    number_safeguarded_jobs: data.number_safeguarded_jobs && `${data.number_safeguarded_jobs} safeguarded jobs`,
    government_assistance: formatBoolean(data.government_assistance, { pos: 'Has', suffix: ' government assistance' }),
    r_and_d_budget: formatBoolean(data.r_and_d_budget, { pos: 'Has', suffix: ' R&D budget' }),
    average_salary: get(data, 'average_salary.name'),
    non_fdi_r_and_d_budget: formatBoolean(data.non_fdi_r_and_d_budget, {
      pos: 'Has',
      suffix: ' linked non-FDI R&D projects',
    }),
    new_tech_to_uk: formatBoolean(data.new_tech_to_uk, {
      pos: 'Has',
      suffix: ' new-to-world tech, business model or IP',
    }),
    export_revenue: formatBoolean(data.export_revenue, {
      pos: 'Yes, will',
      neg: 'No, will not',
      suffix: ' create significant export revenue',
    }),
    sector_name: get(data, 'sector.name'),
    account_tier: get(data, 'investor_company.classification.name'),
    business_activities: data.business_activities.filter((activity) => {
      return /^(european|global) headquarters$/i.test(activity.name)
    }).length ? 'Yes' : 'No',
  })
}

function transformInvestmentRequirementsForView (data) {
  if (!isPlainObject(data)) { return }

  const strategicDrivers = get(data, 'strategic_drivers', [])
  const competitorCountries = get(data, 'competitor_countries', [])
  const regionLocations = get(data, 'uk_region_locations', [])

  return Object.assign({}, data, {
    strategic_drivers: strategicDrivers.map(driver => driver.name).join(', '),
    competitor_countries: competitorCountries.map(country => country.name).join(', '),
    uk_region_locations: regionLocations.map(region => region.name).join(', '),
  })
}

function transformInvestmentFDIForView (data) {
  if (!isPlainObject(data)) {
    return
  }

  const [
    { name: commitmentToInvestName },
    { name: fdiName },
    { name: nonFdiName },
  ] = metadataRepository.investmentTypeOptions

  function approvedInvestmentText (investments, defaultText) {
    return investments.reduce((displayText, investmentDetail) => {
      return investmentDetail.isApproved ? investmentDetail.displayText : displayText
    }, defaultText)
  }

  return {
    type_of_investment: approvedInvestmentText([
      { displayText: commitmentToInvestName, isApproved: data.approved_commitment_to_invest },
      { displayText: fdiName, isApproved: data.approved_fdi },
      { displayText: nonFdiName, isApproved: data.approved_non_fdi },
    ], 'Does not apply'),
    foreign_investor: {
      name: data.investor_company.name,
      url: buildCompanyUrl(data.investor_company),
    },
    foreign_country: get(data, 'investor_company.registered_address_country.name'),
    uk_company: data.uk_company ? {
      name: data.uk_company.name,
      url: buildCompanyUrl(data.uk_company),
    } : null,
    investor_retain_voting_power: data.uk_company ? 'Yes' : 'No',
  }
}

function transformInvestmentLandingForView (data) {
  if (!isPlainObject(data)) {
    return
  }

  return Object.assign({}, {
    uk_company: data.uk_company ? { name: data.uk_company.name, url: buildCompanyUrl(data.uk_company) } : null,
    company_number: get(data, 'uk_company.company_number'),
    registered_address: data.uk_company ? [
      data.uk_company.registered_address_1,
      data.uk_company.registered_address_2,
      data.uk_company.registered_address_town,
      data.uk_company.registered_address_country.name,
      data.uk_company.registered_address_county,
      data.uk_company.registered_address_postcode,
    ].filter((address) => address) : null,
    investment_land_date: data.actual_land_date ? moment(data.actual_land_date).format('Do MMMM YYYY') : null,
  })
}

function transformBriefInvestmentSummary (data) {
  if (!isPlainObject(data)) { return }

  const investorCompany = data.investor_company
  const competitorCountries = data.competitor_countries || []
  const regionLocations = data.uk_region_locations || []

  return {
    sector: get(data, 'sector.name', null),
    investor_company: {
      name: investorCompany.name,
      url: buildCompanyUrl(investorCompany),
    },
    website: (investorCompany.website) ? `<a href="${investorCompany.website}">${investorCompany.website}</a>` : '',
    account_tier: (investorCompany.classification && investorCompany.classification !== null && investorCompany.classification.name) ? investorCompany.classification.name : 'None',
    uk_region_locations: regionLocations.map(region => region.name).join(', '),
    competitor_countries: competitorCountries.map(country => country.name).join(', '),
    estimated_land_date: data.estimated_land_date ? moment(data.estimated_land_date).format('MMMM YYYY') : null,
    total_investment: formatCurrency(data.total_investment),
  }
}

function getAdviserName (investmentData, key) {
  if (!get(investmentData, key)) {
    return 'To do'
  }

  const adviserName = get(investmentData, `${key}.first_name`, '') + ' ' + get(investmentData, `${key}.last_name`, '')
  return adviserName.trim()
}

function transformProjectManagementForView (investmentData) {
  if (investmentData.project_manager || investmentData.project_assurance_adviser) {
    return [{
      role: 'Project assuranace adviser',
      adviser: getAdviserName(investmentData, 'project_assurance_adviser'),
      team: get(investmentData, 'project_assurance_team.name', null),
    }, {
      role: 'Project manager',
      adviser: getAdviserName(investmentData, 'project_manager'),
      team: get(investmentData, 'project_manager_team.name', null),
    }]
  }

  return null
}

module.exports = {
  transformInvestmentDataForView,
  transformInvestmentValueForView,
  transformInvestmentRequirementsForView,
  transformInvestmentFDIForView,
  transformInvestmentLandingForView,
  transformToApi,
  transformFromApi,
  transformBriefInvestmentSummary,
  transformProjectManagementForView,
}
<commit_msg>Show company name instead of stringified object<commit_after>const moment = require('moment')
const { compact, mapValues, get, isPlainObject, isNull } = require('lodash')
const { buildCompanyUrl } = require('../../companies/services/data')
const metadataRepository = require('../../../lib/metadata')

function formatCurrency (number) {
  if (isNull(number)) { return null }

  return new Intl.NumberFormat('en-GB', {
    style: 'currency',
    currency: 'GBP',
    minimumFractionDigits: 0,
  }).format(number)
}

function transformToApi (body) {
  if (!isPlainObject(body)) { return }

  const schema = {
    'client_relationship_manager': Object,
    'referral_source_adviser': Object,
    'referral_source_activity': Object,
    'referral_source_activity_marketing': Object,
    'referral_source_activity_website': Object,
    'investor_company': Object,
    'investment_type': Object,
    'fdi_type': Object,
    'non_fdi_type': Object,
    'sector': Object,
    'client_contacts': Array,
    'business_activities': Array,
  }

  const relationshipMgr = body['is-relationship-manager']
  if (relationshipMgr !== 'No') {
    body.client_relationship_manager = relationshipMgr
  }

  const referralSource = body['is-referral-source']
  if (referralSource !== 'No') {
    body.referral_source_adviser = referralSource
  }

  const formatted = mapValues(schema, (type, key) => {
    const value = body[key]

    if (!value) {
      return
    }

    if (type === Array) {
      return [{ id: value }]
    }

    return { id: value }
  })

  formatted['estimated_land_date'] = `${body['land-date_year']}-${body['land-date_month']}-01`

  return Object.assign({}, body, formatted)
}

function transformFromApi (body) {
  if (!isPlainObject(body)) { return }

  const schema = {
    'client_relationship_manager': String,
    'referral_source_adviser': String,
    'referral_source_activity': String,
    'referral_source_activity_marketing': String,
    'referral_source_activity_website': String,
    'investor_company': String,
    'investment_type': String,
    'fdi_type': String,
    'non_fdi_type': String,
    'sector': String,
    'client_contacts': Array,
    'business_activities': Array,
  }

  const formatted = mapValues(schema, (type, key) => {
    if (type === Array) {
      return get(body, `${key}[0].id`, '')
    }
    return get(body, `${key}.id`)
  })

  const date = new Date(body['estimated_land_date'])
  if (date) {
    formatted['land-date_year'] = date.getFullYear()
    formatted['land-date_month'] = date.getMonth() + 1 // month is zero based index
  }

  return Object.assign({}, body, formatted)
}

function transformInvestmentDataForView (data) {
  if (!isPlainObject(data)) { return }

  function getInvestmentTypeDetails () {
    const types = [
      data.investment_type.name,
      get(data, 'fdi_type.name'),
      get(data, 'non_fdi_type.name'),
    ]
    return compact(types).join(', ')
  }

  return Object.assign({}, data, {
    investor_company: {
      name: data.investor_company.name,
      url: buildCompanyUrl(data.investor_company),
    },
    investment_type: getInvestmentTypeDetails(),
    sector: get(data, 'sector.name', null),
    business_activities: data.business_activities.map(i => i.name).join(', '),
    nda_signed: data.nda_signed ? 'Signed' : 'Not signed',
    estimated_land_date: data.estimated_land_date ? moment(data.estimated_land_date).format('MMMM YYYY') : null,
  })
}

function transformInvestmentValueForView (data) {
  if (!isPlainObject(data)) { return }

  function formatBoolean (boolean, { suffix = '', pos = 'Yes', neg = 'No' }) {
    if (isNull(boolean)) { return null }
    return (data.government_assistance ? pos : neg) + suffix
  }

  return Object.assign({}, data, {
    total_investment: formatCurrency(data.total_investment),
    foreign_equity_investment: formatCurrency(data.foreign_equity_investment),
    number_new_jobs: data.number_new_jobs && `${data.number_new_jobs} new jobs`,
    number_safeguarded_jobs: data.number_safeguarded_jobs && `${data.number_safeguarded_jobs} safeguarded jobs`,
    government_assistance: formatBoolean(data.government_assistance, { pos: 'Has', suffix: ' government assistance' }),
    r_and_d_budget: formatBoolean(data.r_and_d_budget, { pos: 'Has', suffix: ' R&D budget' }),
    average_salary: get(data, 'average_salary.name'),
    non_fdi_r_and_d_budget: formatBoolean(data.non_fdi_r_and_d_budget, {
      pos: 'Has',
      suffix: ' linked non-FDI R&D projects',
    }),
    new_tech_to_uk: formatBoolean(data.new_tech_to_uk, {
      pos: 'Has',
      suffix: ' new-to-world tech, business model or IP',
    }),
    export_revenue: formatBoolean(data.export_revenue, {
      pos: 'Yes, will',
      neg: 'No, will not',
      suffix: ' create significant export revenue',
    }),
    sector_name: get(data, 'sector.name'),
    account_tier: get(data, 'investor_company.classification.name'),
    business_activities: data.business_activities.filter((activity) => {
      return /^(european|global) headquarters$/i.test(activity.name)
    }).length ? 'Yes' : 'No',
  })
}

function transformInvestmentRequirementsForView (data) {
  if (!isPlainObject(data)) { return }

  const strategicDrivers = get(data, 'strategic_drivers', [])
  const competitorCountries = get(data, 'competitor_countries', [])
  const regionLocations = get(data, 'uk_region_locations', [])

  return Object.assign({}, data, {
    strategic_drivers: strategicDrivers.map(driver => driver.name).join(', '),
    competitor_countries: competitorCountries.map(country => country.name).join(', '),
    uk_region_locations: regionLocations.map(region => region.name).join(', '),
    uk_company: get(data, 'uk_company.name'),
  })
}

function transformInvestmentFDIForView (data) {
  if (!isPlainObject(data)) {
    return
  }

  const [
    { name: commitmentToInvestName },
    { name: fdiName },
    { name: nonFdiName },
  ] = metadataRepository.investmentTypeOptions

  function approvedInvestmentText (investments, defaultText) {
    return investments.reduce((displayText, investmentDetail) => {
      return investmentDetail.isApproved ? investmentDetail.displayText : displayText
    }, defaultText)
  }

  return {
    type_of_investment: approvedInvestmentText([
      { displayText: commitmentToInvestName, isApproved: data.approved_commitment_to_invest },
      { displayText: fdiName, isApproved: data.approved_fdi },
      { displayText: nonFdiName, isApproved: data.approved_non_fdi },
    ], 'Does not apply'),
    foreign_investor: {
      name: data.investor_company.name,
      url: buildCompanyUrl(data.investor_company),
    },
    foreign_country: get(data, 'investor_company.registered_address_country.name'),
    uk_company: data.uk_company ? {
      name: data.uk_company.name,
      url: buildCompanyUrl(data.uk_company),
    } : null,
    investor_retain_voting_power: data.uk_company ? 'Yes' : 'No',
  }
}

function transformInvestmentLandingForView (data) {
  if (!isPlainObject(data)) {
    return
  }

  return Object.assign({}, {
    uk_company: data.uk_company ? { name: data.uk_company.name, url: buildCompanyUrl(data.uk_company) } : null,
    company_number: get(data, 'uk_company.company_number'),
    registered_address: data.uk_company ? [
      data.uk_company.registered_address_1,
      data.uk_company.registered_address_2,
      data.uk_company.registered_address_town,
      data.uk_company.registered_address_country.name,
      data.uk_company.registered_address_county,
      data.uk_company.registered_address_postcode,
    ].filter((address) => address) : null,
    investment_land_date: data.actual_land_date ? moment(data.actual_land_date).format('Do MMMM YYYY') : null,
  })
}

function transformBriefInvestmentSummary (data) {
  if (!isPlainObject(data)) { return }

  const investorCompany = data.investor_company
  const competitorCountries = data.competitor_countries || []
  const regionLocations = data.uk_region_locations || []

  return {
    sector: get(data, 'sector.name', null),
    investor_company: {
      name: investorCompany.name,
      url: buildCompanyUrl(investorCompany),
    },
    website: (investorCompany.website) ? `<a href="${investorCompany.website}">${investorCompany.website}</a>` : '',
    account_tier: (investorCompany.classification && investorCompany.classification !== null && investorCompany.classification.name) ? investorCompany.classification.name : 'None',
    uk_region_locations: regionLocations.map(region => region.name).join(', '),
    competitor_countries: competitorCountries.map(country => country.name).join(', '),
    estimated_land_date: data.estimated_land_date ? moment(data.estimated_land_date).format('MMMM YYYY') : null,
    total_investment: formatCurrency(data.total_investment),
  }
}

function getAdviserName (investmentData, key) {
  if (!get(investmentData, key)) {
    return 'To do'
  }

  const adviserName = get(investmentData, `${key}.first_name`, '') + ' ' + get(investmentData, `${key}.last_name`, '')
  return adviserName.trim()
}

function transformProjectManagementForView (investmentData) {
  if (investmentData.project_manager || investmentData.project_assurance_adviser) {
    return [{
      role: 'Project assuranace adviser',
      adviser: getAdviserName(investmentData, 'project_assurance_adviser'),
      team: get(investmentData, 'project_assurance_team.name', null),
    }, {
      role: 'Project manager',
      adviser: getAdviserName(investmentData, 'project_manager'),
      team: get(investmentData, 'project_manager_team.name', null),
    }]
  }

  return null
}

module.exports = {
  transformInvestmentDataForView,
  transformInvestmentValueForView,
  transformInvestmentRequirementsForView,
  transformInvestmentFDIForView,
  transformInvestmentLandingForView,
  transformToApi,
  transformFromApi,
  transformBriefInvestmentSummary,
  transformProjectManagementForView,
}
<|endoftext|>


<commit_before>const Player = React.createClass({
  onStateChange: function (event) {
    switch (event.data) {
      case YT.PlayerState.PLAYING:
        Socket.emit('video/start', this.state.player.getVideoData()['video_id']);
        break;
      case YT.PlayerState.PAUSED:
        Socket.emit('video/pause', this.state.player.getVideoData()['video_id']);
        break;
      case YT.PlayerState.BUFFERING:
        Socket.emit('video/buffer', this.state.player.getVideoData()['video_id']);
        break;
      case YT.PlayerState.ENDED:
        Socket.emit('video/end', this.state.player.getVideoData()['video_id']);
        break;
    };
  },
  updateVideo: function (id) {
    this.setState((state) => {
      return {
        id: id,
        player: state.player
      };
    });

    this.state.player.cueVideoById(id);
  },
  playVideo: function (id) {
    this.setState((state) => {
      return {
        id: id,
        player: state.player
      };
    });

    this.state.player.loadVideoById(id);
  },
  componentDidMount: function () {
    this.setState({
      id: null,
      // YT may not be loaded at this time, need to find a solution...
      // That's probably why I can't put this in a getInitialState method
      player: new YT.Player('player', {
          events: {
            onStateChange: this.onStateChange
          }
        })
    });

    Socket.on('video/cue', this.updateVideo);
    Socket.on('video/play', this.playVideo);
  },
  render: function () {
    return

;
  }
});

const PlaylistItem = React.createClass({
  playVideo: function () {
    if (this.props.id) {
      Socket.emit('video/play', this.props);
    }
  },
  render: function () {
    return (

              {this.props.title}

{this.props.channel}

    );
  }
});

const Playlist = React.createClass({
  getInitialState: function () {
    return { videos: [] };
  },
  componentDidMount: function () {
    Socket.on('playlist/update', (playlist) => {
      this.setState({ videos: playlist });
    });
  },
  render: function () {
    let videos = [];
    for (var index in this.state.videos) {
      videos.push(
        <PlaylistItem
          key={this.state.videos[index].id}
          id={this.state.videos[index].id}
          thumbnail={this.state.videos[index].thumbnail}
          title={this.state.videos[index].title}
          channel={this.state.videos[index].channel} />
        );
    }

    return (

        {videos}

    );
  }
});

const CurrentPlaylist = React.createClass({
  render: function () {
    return (

        <Playlist />
        <Player />

    );
  }
});

const Video = React.createClass({
  cueVideo: function () {
    if (this.props.id) {
      Socket.emit('video/cue', this.props);
    }
  },
  setNextVideo: function () {
    if (this.props.id) {
      Socket.emit('video/next', this.props);
    }
  },
  render: function () {
    return (

        {this.props.duration}

          <button className="btn btn-secondary btn-sm cue"
                  onClick={this.cueVideo}
                  title="Cue this video">+</button>

              {this.props.title}

{this.props.channel}

    );
  }
});

const VideoGrid = React.createClass({
  render: function () {
    if (this.props.videos.length) {
      let videoNodes = this.props.videos.map((video) => {
        return (
          <Video
            key={video.id}
            id={video.id}
            duration={video.duration}
            thumbnail={video.thumbnail}
            title={video.title}
            channel={video.channel} />
        )
      });

      return (

          {videoNodes}

      );
    }

    return
Nothing to show at the moment
;
  }
});

const SubscriptionsPage = React.createClass({
  getInitialState: function () { return { loading: true, videos: null }; },
  componentDidMount: function () {
    Socket.emit('subscriptions/list');
    Socket.on('subscriptions/list', (subscriptions) => {
      this.setState({ loading: false, videos: subscriptions });
      window.addEventListener('paste', this.onPaste);
    });
  },
  componentWillUnmount: function () {
    Socket.removeAllListeners('subscriptions/list');
    window.removeEventListener('paste', this.onPaste);
  },
  onPaste: function (event) {
    if (!event.clipboardData.getData('text/plain')) return;

    Socket.emit('video/paste', event.clipboardData.getData('text/plain'));
  },
  render: function () {
    if (this.state.loading) {
      return (

Let us load your data

You are connected to the YouTube API

It may take a while

      );
    }

    return (

        <VideoGrid videos={this.state.videos} />
        <CurrentPlaylist />

    );
  }
});
<commit_msg>Improve the subscriptions grid layout<commit_after>const Player = React.createClass({
  onStateChange: function (event) {
    switch (event.data) {
      case YT.PlayerState.PLAYING:
        Socket.emit('video/start', this.state.player.getVideoData()['video_id']);
        break;
      case YT.PlayerState.PAUSED:
        Socket.emit('video/pause', this.state.player.getVideoData()['video_id']);
        break;
      case YT.PlayerState.BUFFERING:
        Socket.emit('video/buffer', this.state.player.getVideoData()['video_id']);
        break;
      case YT.PlayerState.ENDED:
        Socket.emit('video/end', this.state.player.getVideoData()['video_id']);
        break;
    };
  },
  updateVideo: function (id) {
    this.setState((state) => {
      return {
        id: id,
        player: state.player
      };
    });

    this.state.player.cueVideoById(id);
  },
  playVideo: function (id) {
    this.setState((state) => {
      return {
        id: id,
        player: state.player
      };
    });

    this.state.player.loadVideoById(id);
  },
  componentDidMount: function () {
    this.setState({
      id: null,
      // YT may not be loaded at this time, need to find a solution...
      // That's probably why I can't put this in a getInitialState method
      player: new YT.Player('player', {
          events: {
            onStateChange: this.onStateChange
          }
        })
    });

    Socket.on('video/cue', this.updateVideo);
    Socket.on('video/play', this.playVideo);
  },
  render: function () {
    return

;
  }
});

const PlaylistItem = React.createClass({
  playVideo: function () {
    if (this.props.id) {
      Socket.emit('video/play', this.props);
    }
  },
  render: function () {
    return (

              {this.props.title}

{this.props.channel}

    );
  }
});

const Playlist = React.createClass({
  getInitialState: function () {
    return { videos: [] };
  },
  componentDidMount: function () {
    Socket.on('playlist/update', (playlist) => {
      this.setState({ videos: playlist });
    });
  },
  render: function () {
    let videos = [];
    for (var index in this.state.videos) {
      videos.push(
        <PlaylistItem
          key={this.state.videos[index].id}
          id={this.state.videos[index].id}
          thumbnail={this.state.videos[index].thumbnail}
          title={this.state.videos[index].title}
          channel={this.state.videos[index].channel} />
        );
    }

    return (

        {videos}

    );
  }
});

const CurrentPlaylist = React.createClass({
  render: function () {
    return (

        <Playlist />
        <Player />

    );
  }
});

const Video = React.createClass({
  cueVideo: function () {
    if (this.props.id) {
      Socket.emit('video/cue', this.props);
    }
  },
  setNextVideo: function () {
    if (this.props.id) {
      Socket.emit('video/next', this.props);
    }
  },
  render: function () {
    return (

        {this.props.duration}

          <button className="btn btn-secondary btn-sm cue"
                  onClick={this.cueVideo}
                  title="Cue this video">+</button>

              {this.props.title}

{this.props.channel}

    );
  }
});

const VideoGrid = React.createClass({
  render: function () {
    if (this.props.videos.length) {
      let videoNodes = this.props.videos.map((video) => {
        return (
          <Video
            key={video.id}
            id={video.id}
            duration={video.duration}
            thumbnail={video.thumbnail}
            title={video.title}
            channel={video.channel} />
        )
      });

      return (

          {videoNodes}

      );
    }

    return
Nothing to show at the moment
;
  }
});

const SubscriptionsPage = React.createClass({
  getInitialState: function () { return { loading: true, videos: null }; },
  componentDidMount: function () {
    Socket.emit('subscriptions/list');
    Socket.on('subscriptions/list', (subscriptions) => {
      this.setState({ loading: false, videos: subscriptions });
      window.addEventListener('paste', this.onPaste);
    });
  },
  componentWillUnmount: function () {
    Socket.removeAllListeners('subscriptions/list');
    window.removeEventListener('paste', this.onPaste);
  },
  onPaste: function (event) {
    if (!event.clipboardData.getData('text/plain')) return;

    Socket.emit('video/paste', event.clipboardData.getData('text/plain'));
  },
  render: function () {
    if (this.state.loading) {
      return (

Let us load your data

You are connected to the YouTube API

It may take a while

      );
    }

    return (

        <VideoGrid videos={this.state.videos} />
        <CurrentPlaylist />

    );
  }
});
<|endoftext|>


<commit_before>/**
 * @file Require javascript resource handling
 * @since 0.2.2
 */
/*#ifndef(UMD)*/
"use strict";
/*global _GPF_HOST*/ // Host types
/*global _gpfErrorDeclare*/ // Declare new gpf.Error names
/*global _gpfFunc*/ // Create a new function using the source
/*global _gpfHost*/ // Host type
/*global _gpfIgnore*/ // Helper to remove unused parameter warning
/*global _gpfPathJoin*/ // Join all arguments together and normalize the resulting path
/*global _gpfPathParent*/ // Get the parent of a path
/*global _gpfRegExpForEach*/ // Executes the callback for each match of the regular expression
/*global _gpfRequireProcessor*/ // Mapping of resource extension to processor function
/*global _gpfRequireWrapGpf*/ // Wrap gpf to fit the new context and give access to gpf.require.define promise
/*#endif*/

_gpfErrorDeclare("require/javascript", {

    /**
     * ### Summary
     *
     * Dynamic require not supported
     *
     * ### Description
     *
     * When loading a [CommonJS](http://www.commonjs.org/) module, a first pass is done to extract all requires being
     * called. If the require is based on a complex parameter (variable or string manipulation), the loader won't be
     * able to understand the require. No fallback mechanism is implemented yet
     * @since 0.2.2
     */
    noCommonJSDynamicRequire:
        "Dynamic require not supported"

});

var _gpfRequireJsModuleRegEx = /[^.]\brequire\b\s*\(\s*(?:['|"]([^"']+)['|"]|[^)]+)\s*\)/g;

function _gpfRequireJSGetStaticDependencies (resourceName, content) {
    /*jshint validthis:true*/
    var requires = _gpfRegExpForEach(_gpfRequireJsModuleRegEx, content);
    if (requires.length) {
        return _gpfRequireWrapGpf(this, resourceName).gpf.require.define(requires  //eslint-disable-line no-invalid-this
            .map(function (match) {
                return match[1]; // may be undefined if dynamic
            })
            .filter(function (require) {
                return require;
            })
            .reduce(function (dictionary, name) {
                dictionary[name] = name;
                return dictionary;
            }, {}),
        function (require) {
            return require;
        });
    }
    return Promise.resolve({}); // No static dependencies
}

//region AMD define wrapper

function _gpfRequireAmdDefineParamsFactoryOnly (params) {
    return {
        dependencies: [],
        factory: params[0]
    };
}

function _gpfRequireAmdDefineParamsDependenciesAndFactory (params) {
    return {
        dependencies: params[0],
        factory: params[1]
    };
}

function _gpfRequireAmdDefineParamsAll (params) {
    return {
        dependencies: params[1],
        factory: params[2]
    };
}

var
    /**
     * Mapping of define parameter count to dependencies / factory
     *
     * @type {Function[]}
     * @since 0.2.2
     */
    _gpfRequireAmdDefineParamsMapping = [
        null,
        _gpfRequireAmdDefineParamsFactoryOnly,
        _gpfRequireAmdDefineParamsDependenciesAndFactory,
        _gpfRequireAmdDefineParamsAll
    ];

function _gpfRequireAmdDefine (name, dependencies, factory) {
    /*jshint validthis:true*/
    _gpfIgnore(name, dependencies, factory);
    var myGpf = this, //eslint-disable-line
        params = _gpfRequireAmdDefineParamsMapping[arguments.length](arguments);
    myGpf.require.define(params.dependencies, function (require) {
        require.length = params.dependencies.length;
        return params.factory.apply(null, [].slice.call(require));
    });
}

function _gpfRequireJS (myGpf, content, staticDependencies) {
    var module = {};
    _gpfFunc(["gpf", "define", "module", "require"], content)(
        myGpf,
        _gpfRequireAmdDefine.bind(myGpf),
        module,
        function (name) {
            return staticDependencies[name] || gpf.Error.noCommonJSDynamicRequire();
        }
    );
    return module.exports;
}

/*global location*/

function _gpfRequireSourceMapBrowswer (name, content) {
    var parentPath = location.pathname.toString();
    /* istanbul ignore else */ // sourceURL.1
    if (!parentPath.endsWith("/")) {
        parentPath = _gpfPathParent(parentPath);
    }
    return "//# sourceURL=" + location.origin + _gpfPathJoin(parentPath, name) + "?gpf.require\n" + content;
}

function _gpfRequireSourceMapNone (name, content) {
    return content;
}

var _gpfRequireSourceMapImpl;
if (_GPF_HOST.BROWSER === _gpfHost) {
    _gpfRequireSourceMapImpl = _gpfRequireSourceMapBrowswer;

} else {
    _gpfRequireSourceMapImpl = _gpfRequireSourceMapNone;

}

_gpfRequireProcessor[".js"] = function (resourceName, content) {
    var wrapper = _gpfRequireWrapGpf(this, resourceName);
    return _gpfRequireJSGetStaticDependencies.call(this, resourceName, content)
        .then(function (staticDependencies) {
            var exports = _gpfRequireJS(wrapper.gpf, _gpfRequireSourceMapImpl(resourceName, content),
                staticDependencies);
            if (undefined === exports) {
                return wrapper.promise;
            }
            return exports;
        });
};
<commit_msg>ESLint fixes (#280)<commit_after>/**
 * @file Require javascript resource handling
 * @since 0.2.2
 */
/*#ifndef(UMD)*/
"use strict";
/*global _GPF_HOST*/ // Host types
/*global _gpfErrorDeclare*/ // Declare new gpf.Error names
/*global _gpfFunc*/ // Create a new function using the source
/*global _gpfHost*/ // Host type
/*global _gpfIgnore*/ // Helper to remove unused parameter warning
/*global _gpfPathJoin*/ // Join all arguments together and normalize the resulting path
/*global _gpfPathParent*/ // Get the parent of a path
/*global _gpfRegExpForEach*/ // Executes the callback for each match of the regular expression
/*global _gpfRequireProcessor*/ // Mapping of resource extension to processor function
/*global _gpfRequireWrapGpf*/ // Wrap gpf to fit the new context and give access to gpf.require.define promise
/*#endif*/

_gpfErrorDeclare("require/javascript", {

    /**
     * ### Summary
     *
     * Dynamic require not supported
     *
     * ### Description
     *
     * When loading a [CommonJS](http://www.commonjs.org/) module, a first pass is done to extract all requires being
     * called. If the require is based on a complex parameter (variable or string manipulation), the loader won't be
     * able to understand the require. No fallback mechanism is implemented yet
     * @since 0.2.2
     */
    noCommonJSDynamicRequire:
        "Dynamic require not supported"

});

var _gpfRequireJsModuleRegEx = /[^.]\brequire\b\s*\(\s*(?:['|"]([^"']+)['|"]|[^)]+)\s*\)/g;

function _gpfRequireJSGetStaticDependencies (resourceName, content) {
    /*jshint validthis:true*/
    var requires = _gpfRegExpForEach(_gpfRequireJsModuleRegEx, content);
    if (requires.length) {
        return _gpfRequireWrapGpf(this, resourceName).gpf.require.define(requires //eslint-disable-line no-invalid-this
            .map(function (match) {
                return match[1]; // may be undefined if dynamic
            })
            .filter(function (require) {
                return require;
            })
            .reduce(function (dictionary, name) {
                dictionary[name] = name;
                return dictionary;
            }, {}),
        function (require) {
            return require;
        });
    }
    return Promise.resolve({}); // No static dependencies
}

//region AMD define wrapper

function _gpfRequireAmdDefineParamsFactoryOnly (params) {
    return {
        dependencies: [],
        factory: params[0]
    };
}

function _gpfRequireAmdDefineParamsDependenciesAndFactory (params) {
    return {
        dependencies: params[0],
        factory: params[1]
    };
}

function _gpfRequireAmdDefineParamsAll (params) {
    return {
        dependencies: params[1],
        factory: params[2]
    };
}

var
    /**
     * Mapping of define parameter count to dependencies / factory
     *
     * @type {Function[]}
     * @since 0.2.2
     */
    _gpfRequireAmdDefineParamsMapping = [
        null,
        _gpfRequireAmdDefineParamsFactoryOnly,
        _gpfRequireAmdDefineParamsDependenciesAndFactory,
        _gpfRequireAmdDefineParamsAll
    ];

function _gpfRequireAmdDefine (name, dependencies, factory) {
    /*jshint validthis:true*/
    _gpfIgnore(name, dependencies, factory);
    var myGpf = this, //eslint-disable-line
        params = _gpfRequireAmdDefineParamsMapping[arguments.length](arguments);
    myGpf.require.define(params.dependencies, function (require) {
        require.length = params.dependencies.length;
        return params.factory.apply(null, [].slice.call(require));
    });
}

function _gpfRequireJS (myGpf, content, staticDependencies) {
    var module = {};
    _gpfFunc(["gpf", "define", "module", "require"], content)(
        myGpf,
        _gpfRequireAmdDefine.bind(myGpf),
        module,
        function (name) {
            return staticDependencies[name] || gpf.Error.noCommonJSDynamicRequire();
        }
    );
    return module.exports;
}

/*global location*/

function _gpfRequireSourceMapBrowswer (name, content) {
    var parentPath = location.pathname.toString();
    /* istanbul ignore else */ // sourceURL.1
    if (!parentPath.endsWith("/")) {
        parentPath = _gpfPathParent(parentPath);
    }
    return "//# sourceURL=" + location.origin + _gpfPathJoin(parentPath, name) + "?gpf.require\n" + content;
}

function _gpfRequireSourceMapNone (name, content) {
    return content;
}

var _gpfRequireSourceMapImpl;
if (_GPF_HOST.BROWSER === _gpfHost) {
    _gpfRequireSourceMapImpl = _gpfRequireSourceMapBrowswer;

} else {
    _gpfRequireSourceMapImpl = _gpfRequireSourceMapNone;

}

_gpfRequireProcessor[".js"] = function (resourceName, content) {
    var wrapper = _gpfRequireWrapGpf(this, resourceName);
    return _gpfRequireJSGetStaticDependencies.call(this, resourceName, content)
        .then(function (staticDependencies) {
            var exports = _gpfRequireJS(wrapper.gpf, _gpfRequireSourceMapImpl(resourceName, content),
                staticDependencies);
            if (undefined === exports) {
                return wrapper.promise;
            }
            return exports;
        });
};
<|endoftext|>


<commit_before>'use strict'

// Foundation for Apps
//
// We use this Gulpfile to assemble the documentation, run unit tests,
// and deploy changes to the live documentation and CDN.
//
// The tasks are grouped into these categories:
//   1. Libraries
//   2. Variables
//   3. Cleaning files
//   4. Copying files
//   5. Stylesheets
//   6. JavaScript
//   7. Testing
//   8. Server
//   9. Deployment
//  10. Default tasks

// 1. LIBRARIES
// - - - - - - - - - - - - - - -

var gulp           = require('gulp'),
    $              = require('gulp-load-plugins')(),
    rimraf         = require('rimraf'),
    runSequence    = require('run-sequence'),
    modRewrite     = require('connect-modrewrite'),
    routes         = require('./bin/gulp-dynamic-routing'),
    merge          = require('merge-stream'),
    settingsParser = require('settings-parser')
;

// 2. VARIABLES
// - - - - - - - - - - - - - - -

var foundationJS = [
  'js/vendor/**/*.js',
  'js/angular/**/*.js',
  '!js/angular/app.js'
];
var dependenciesJS = [
  'bower_components/fastclick/lib/fastclick.js',
  'bower_components/viewport-units-buggyfill/viewport-units-buggyfill.js',
  'bower_components/tether/tether.js',
  'bower_components/angular/angular.js',
  'bower_components/angular-animate/angular-animate.js',
  'bower_components/angular-ui-router/release/angular-ui-router.js',
  'bower_components/hammerjs/hammer.js'
];
var docsJS = [
  'bower_components/marked/lib/marked.js',
  'bower_components/angular-highlightjs/angular-highlightjs.js',
  'bower_components/highlightjs/highlight.pack.js',
  'bower_components/allmighty-autocomplete/script/autocomplete.js',
  'docs/assets/js/app.js'
];

// 3. CLEANIN' FILES
// - - - - - - - - - - - - - - -

// Clean build directory
gulp.task('clean', function(cb) {
  rimraf('./build', cb);
});

// Clean the partials directory
gulp.task('clean:partials', function(cb) {
  rimraf('./build/partials', cb);
});

// 4. COPYING FILES
// - - - - - - - - - - - - - - -

// Copy static files (but not the Angular templates, Sass, or JS)
gulp.task('copy', function() {
  var dirs = [
    './docs/**/*.*',
    '!./docs/templates/**/*.*',
    '!./docs/assets/{scss,js}/**/*.*'
  ];
  gulp.src(dirs, {
    base: './docs/'
  })
    .pipe(gulp.dest('build'));

  return gulp.src('./iconic/**/*')
    .pipe(gulp.dest('build/assets/img/iconic/'));
});

// Copy page templates and generate routes
gulp.task('copy:templates', ['copy'], function() {
  var config = [];

  return gulp.src('./docs/templates/**/*.html')
    .pipe(routes({
      path: 'build/assets/js/routes.js',
      root: 'docs'
    }))
    .pipe(gulp.dest('./build/templates'))
  ;
});

// Copy Foundation directive partials
gulp.task('copy:partials', ['clean:partials'], function() {
  return gulp.src(['js/angular/components/**/*.html'])
    .pipe(gulp.dest('./build/components/'));
});

// 5. STYLESHEETS
// - - - - - - - - - - - - - - -

// Inject styles for docs-specific libraries
gulp.task('css', ['sass'], function() {
  var dirs = [
    'bower_components/allmighty-autocomplete/style/autocomplete.css',
    'build/assets/css/app.css'
  ];
  return gulp.src(dirs)
    .pipe($.concat('app.css'))
    .pipe(gulp.dest('build/assets/css'))
  ;
});

// Compile stylesheets with Ruby Sass
gulp.task('sass', function() {
  var filter = $.filter(['*.map']);

  return $.rubySass('docs/assets/scss/', {
      loadPath: ['scss'],
      style: 'nested',
      bundleExec: true
    })
    .on('error', function(err) {
      console.log(err.message);
    })
    .pipe(filter)
      .pipe($.autoprefixer({
        browsers: ['last 2 versions', 'ie 10']
      }))
    .pipe(filter.restore())
    .pipe(gulp.dest('./build/assets/css/'));
});

// Compile stylesheets with node-sass
gulp.task('node-sass', function() {
  return gulp.src('docs/assets/scss/app.scss')
    .pipe($.sass({
      includePaths: ['scss'],
      outputStyle: 'nested',
      errLogToConsole: true
    }))
    .pipe(autoprefixer({
      browsers: ['last 2 versions', 'ie 10']
    }))
    .pipe(concat('app_node.css'))
    .pipe(gulp.dest('./build/assets/css/'));
});

// Generate Sass settings file
gulp.task('settings', function() {
  return settingsParser([
    'scss/_includes.scss',
    'scss/_global.scss',
    'scss/helpers/_breakpoints.scss',
    'scss/components/_typography.scss',
    'scss/components/_grid.scss',
    'scss/components/*.scss'
  ], {
    title: 'Foundation for Apps Settings'.toUpperCase(),
    partialsPath: 'build/partials/scss',
    settingsPath: 'scss'
  });
});

// 6. JAVASCRIPT
// - - - - - - - - - - - - - - -

// Compile Foundation JavaScript
gulp.task('javascript', function() {
  return gulp.src(foundationJS)
    .pipe($.uglify({
      beautify: true,
      mangle: false
    }).on('error', function(e) {
      console.log(e);
    }))
    .pipe($.concat('foundation.js'))
    .pipe(gulp.dest('./build/assets/js/'))
  ;
});

// Compile JavaScript dependencies
gulp.task('javascript:deps', function() {
  return gulp.src(dependenciesJS)
    .pipe($.uglify({
      beautify: true,
      mangle: false
    }).on('error', function(e) {
      console.log(e);
    }))
    .pipe($.concat('dependencies.js'))
    .pipe(gulp.dest('./build/assets/js/'))
  ;
});

// Compile documentation-specific JavaScript
gulp.task('javascript:docs', function() {
  return gulp.src(docsJS)
    .pipe($.uglify({
      beautify: true,
      mangle: false
    }))
    .pipe($.concat('app.js'))
    .pipe(gulp.dest('./build/assets/js/'))
  ;

});

// 7. SERVER
// - - - - - - - - - - - - - - -

gulp.task('server:start', function() {
  $.connect.server({
    root: './build',
    middleware: function() {
      return [
        modRewrite(['^[^\\.]*$ /index.html [L]'])
      ];
    },
  });
});

// gulp.task('minify-css', function() {
//   gulp.src('./build/assets/css/app.css')
//     .pipe(minify({keepBreaks:true}))
//     .pipe(concat('app.min.css'))
//     .pipe(gulp.dest('./build/assets/css/'))
// });

// 8. TESTING
// - - - - - - - - - - - - - - -

gulp.task('karma:test', ['build', 'node-sass'], function() {
  var testFiles = [
    'build/assets/js/foundation.js',
    'build/assets/js/dependencies.js',
    'build/assets/js/app.js',
    'bower_components/angular-mocks/angular-mocks.js',
    'bower_components/jsdiff/diff.js',
    'build/assets/css/app.css',
    'build/assets/css/app_node.css',
    'tests/unit/common/*Spec.js'
  ];

  return gulp.src(testFiles)
    .pipe($.karma({
      configFile: 'karma.conf.js',
      action: 'run'
    }))
    .on('error', function(err) {
      throw err;
    })
  ;

});

gulp.task('sass:test', function() {
  $.rubySass('./tests/unit/scss/tests.scss', {
    loadPath: ['scss', 'docs/assets/scss', 'bower_components/bootcamp/dist'],
    style: 'nested',
    bundleExec: true
  })
    .on('data', function(data) {
      console.log(data.contents.toString());
    });
});

gulp.task('test', ['karma:test', 'sass:test'], function() {
  console.log('Tests finished.');
});

// 9. DEPLOYMENT
// - - - - - - - - - - - - - - -

// Deploy distribution files
gulp.task('deploy:dist', function() {
  var pkg = require('./package.json');
  var filter = $.filter(['*.map']);

  var css = $.rubySass('docs/assets/scss/', {
      loadPath: ['scss'],
      style: 'nested',
      bundleExec: true
    })
    .pipe(filter)
      .pipe($.autoprefixer({
        browsers: ['last 2 versions', 'ie 10']
      }))
    .pipe(filter.restore())
    .pipe($.rename('foundation-apps.css'))
    .pipe(gulp.dest('./dist/css'))
    .pipe($.minifyCss())
    .pipe($.rename('foundation-apps.min.css'))
    .pipe(gulp.dest('./dist/css'));

  var js = gulp.src(foundationJS)
    .pipe($.concat('foundation-apps.js'))
    .pipe(gulp.dest('./dist/js'))
    .pipe($.uglify())
    .pipe($.rename('foundation-apps.min.js'))
    .pipe(gulp.dest('./dist/js'));

  return;
});

// Deploy documentation
gulp.task('deploy:docs', ['build', 'settings'], function() {
  return gulp.src('build/**')
    .pipe($.rsync({
      root: 'build',
      hostname: 'deployer@72.32.134.77',
      destination: '/home/deployer/sites/foundation-apps/current'
    }));
});

// Deploy to CDN
gulp.task('deploy:cdn', ['deploy:dist'], function() {
  var pkg = require('./package.json');

  return gulp.src('./dist/**/*', {base:'./dist/'})
    .pipe($.filter(['**/*.css', '**/*.js']))
    .pipe($.rename(function(path) {
      // Inject the version number into the filename
      var base = path.basename.split('.');
      if (base.length === 1) {
        base = base + '-' + pkg.version;
      }
      else {
        base = base.slice(0, -1).join('') + '-' + pkg.version + '.' + base[base.length - 1];
      }
      path.basename = base;
      path.dirname = '';
    }))
    .pipe($.rsync({
      hostname: 'deployer@72.32.134.77',
      destination: '/home/deployer/sites/foundation-apps-cdn/current',
      relative: false
    }));
});

// 10. NOW BRING IT TOGETHER
// - - - - - - - - - - - - - - -

// Build the documentation once
gulp.task('build', function(cb) {
  runSequence('clean', ['copy', 'copy:partials', 'css', 'javascript', 'javascript:deps', 'javascript:docs'], 'copy:templates', function() {
    console.log('Successfully built.');
    cb();
  });
});

// Build the documentation, start a test server, and re-compile when files change
gulp.task('default', ['build', 'server:start'], function() {

  // Watch static files
  gulp.watch(['./docs/**/*.*', '!./docs/templates/**/*.*', '!./docs/assets/{scss,js}/**/*.*'], ['copy']);

  // Watch Angular templates
  gulp.watch(['docs/templates/**/*.html'], ['copy:templates']);

  // Watch Angular partials
  gulp.watch(['js/angular/components/**/**.html'], ['copy:partials']);

  // Watch Sass
  gulp.watch(['./docs/assets/scss/**/*', './scss/**/*'], ['css']);

  // Watch JavaScript
  gulp.watch(['./docs/assets/js/**/*', './js/**/*'], ['javascript', 'javascript:deps']);
});
<commit_msg>Remove javascript-deps from gulp watch<commit_after>'use strict'

// Foundation for Apps
//
// We use this Gulpfile to assemble the documentation, run unit tests,
// and deploy changes to the live documentation and CDN.
//
// The tasks are grouped into these categories:
//   1. Libraries
//   2. Variables
//   3. Cleaning files
//   4. Copying files
//   5. Stylesheets
//   6. JavaScript
//   7. Testing
//   8. Server
//   9. Deployment
//  10. Default tasks

// 1. LIBRARIES
// - - - - - - - - - - - - - - -

var gulp           = require('gulp'),
    $              = require('gulp-load-plugins')(),
    rimraf         = require('rimraf'),
    runSequence    = require('run-sequence'),
    modRewrite     = require('connect-modrewrite'),
    routes         = require('./bin/gulp-dynamic-routing'),
    merge          = require('merge-stream'),
    settingsParser = require('settings-parser')
;

// 2. VARIABLES
// - - - - - - - - - - - - - - -

var foundationJS = [
  'js/vendor/**/*.js',
  'js/angular/**/*.js',
  '!js/angular/app.js'
];
var dependenciesJS = [
  'bower_components/fastclick/lib/fastclick.js',
  'bower_components/viewport-units-buggyfill/viewport-units-buggyfill.js',
  'bower_components/tether/tether.js',
  'bower_components/angular/angular.js',
  'bower_components/angular-animate/angular-animate.js',
  'bower_components/angular-ui-router/release/angular-ui-router.js',
  'bower_components/hammerjs/hammer.js'
];
var docsJS = [
  'bower_components/marked/lib/marked.js',
  'bower_components/angular-highlightjs/angular-highlightjs.js',
  'bower_components/highlightjs/highlight.pack.js',
  'bower_components/allmighty-autocomplete/script/autocomplete.js',
  'docs/assets/js/app.js'
];

// 3. CLEANIN' FILES
// - - - - - - - - - - - - - - -

// Clean build directory
gulp.task('clean', function(cb) {
  rimraf('./build', cb);
});

// Clean the partials directory
gulp.task('clean:partials', function(cb) {
  rimraf('./build/partials', cb);
});

// 4. COPYING FILES
// - - - - - - - - - - - - - - -

// Copy static files (but not the Angular templates, Sass, or JS)
gulp.task('copy', function() {
  var dirs = [
    './docs/**/*.*',
    '!./docs/templates/**/*.*',
    '!./docs/assets/{scss,js}/**/*.*'
  ];
  gulp.src(dirs, {
    base: './docs/'
  })
    .pipe(gulp.dest('build'));

  return gulp.src('./iconic/**/*')
    .pipe(gulp.dest('build/assets/img/iconic/'));
});

// Copy page templates and generate routes
gulp.task('copy:templates', ['copy'], function() {
  var config = [];

  return gulp.src('./docs/templates/**/*.html')
    .pipe(routes({
      path: 'build/assets/js/routes.js',
      root: 'docs'
    }))
    .pipe(gulp.dest('./build/templates'))
  ;
});

// Copy Foundation directive partials
gulp.task('copy:partials', ['clean:partials'], function() {
  return gulp.src(['js/angular/components/**/*.html'])
    .pipe(gulp.dest('./build/components/'));
});

// 5. STYLESHEETS
// - - - - - - - - - - - - - - -

// Inject styles for docs-specific libraries
gulp.task('css', ['sass'], function() {
  var dirs = [
    'bower_components/allmighty-autocomplete/style/autocomplete.css',
    'build/assets/css/app.css'
  ];
  return gulp.src(dirs)
    .pipe($.concat('app.css'))
    .pipe(gulp.dest('build/assets/css'))
  ;
});

// Compile stylesheets with Ruby Sass
gulp.task('sass', function() {
  var filter = $.filter(['*.map']);

  return $.rubySass('docs/assets/scss/', {
      loadPath: ['scss'],
      style: 'nested',
      bundleExec: true
    })
    .on('error', function(err) {
      console.log(err.message);
    })
    .pipe(filter)
      .pipe($.autoprefixer({
        browsers: ['last 2 versions', 'ie 10']
      }))
    .pipe(filter.restore())
    .pipe(gulp.dest('./build/assets/css/'));
});

// Compile stylesheets with node-sass
gulp.task('node-sass', function() {
  return gulp.src('docs/assets/scss/app.scss')
    .pipe($.sass({
      includePaths: ['scss'],
      outputStyle: 'nested',
      errLogToConsole: true
    }))
    .pipe(autoprefixer({
      browsers: ['last 2 versions', 'ie 10']
    }))
    .pipe(concat('app_node.css'))
    .pipe(gulp.dest('./build/assets/css/'));
});

// Generate Sass settings file
gulp.task('settings', function() {
  return settingsParser([
    'scss/_includes.scss',
    'scss/_global.scss',
    'scss/helpers/_breakpoints.scss',
    'scss/components/_typography.scss',
    'scss/components/_grid.scss',
    'scss/components/*.scss'
  ], {
    title: 'Foundation for Apps Settings'.toUpperCase(),
    partialsPath: 'build/partials/scss',
    settingsPath: 'scss'
  });
});

// 6. JAVASCRIPT
// - - - - - - - - - - - - - - -

// Compile Foundation JavaScript
gulp.task('javascript', function() {
  return gulp.src(foundationJS)
    .pipe($.uglify({
      beautify: true,
      mangle: false
    }).on('error', function(e) {
      console.log(e);
    }))
    .pipe($.concat('foundation.js'))
    .pipe(gulp.dest('./build/assets/js/'))
  ;
});

// Compile JavaScript dependencies
gulp.task('javascript:deps', function() {
  return gulp.src(dependenciesJS)
    .pipe($.uglify({
      beautify: true,
      mangle: false
    }).on('error', function(e) {
      console.log(e);
    }))
    .pipe($.concat('dependencies.js'))
    .pipe(gulp.dest('./build/assets/js/'))
  ;
});

// Compile documentation-specific JavaScript
gulp.task('javascript:docs', function() {
  return gulp.src(docsJS)
    .pipe($.uglify({
      beautify: true,
      mangle: false
    }))
    .pipe($.concat('app.js'))
    .pipe(gulp.dest('./build/assets/js/'))
  ;

});

// 7. SERVER
// - - - - - - - - - - - - - - -

gulp.task('server:start', function() {
  $.connect.server({
    root: './build',
    middleware: function() {
      return [
        modRewrite(['^[^\\.]*$ /index.html [L]'])
      ];
    },
  });
});

// gulp.task('minify-css', function() {
//   gulp.src('./build/assets/css/app.css')
//     .pipe(minify({keepBreaks:true}))
//     .pipe(concat('app.min.css'))
//     .pipe(gulp.dest('./build/assets/css/'))
// });

// 8. TESTING
// - - - - - - - - - - - - - - -

gulp.task('karma:test', ['build', 'node-sass'], function() {
  var testFiles = [
    'build/assets/js/foundation.js',
    'build/assets/js/dependencies.js',
    'build/assets/js/app.js',
    'bower_components/angular-mocks/angular-mocks.js',
    'bower_components/jsdiff/diff.js',
    'build/assets/css/app.css',
    'build/assets/css/app_node.css',
    'tests/unit/common/*Spec.js'
  ];

  return gulp.src(testFiles)
    .pipe($.karma({
      configFile: 'karma.conf.js',
      action: 'run'
    }))
    .on('error', function(err) {
      throw err;
    })
  ;

});

gulp.task('sass:test', function() {
  $.rubySass('./tests/unit/scss/tests.scss', {
    loadPath: ['scss', 'docs/assets/scss', 'bower_components/bootcamp/dist'],
    style: 'nested',
    bundleExec: true
  })
    .on('data', function(data) {
      console.log(data.contents.toString());
    });
});

gulp.task('test', ['karma:test', 'sass:test'], function() {
  console.log('Tests finished.');
});

// 9. DEPLOYMENT
// - - - - - - - - - - - - - - -

// Deploy distribution files
gulp.task('deploy:dist', function() {
  var pkg = require('./package.json');
  var filter = $.filter(['*.map']);

  var css = $.rubySass('docs/assets/scss/', {
      loadPath: ['scss'],
      style: 'nested',
      bundleExec: true
    })
    .pipe(filter)
      .pipe($.autoprefixer({
        browsers: ['last 2 versions', 'ie 10']
      }))
    .pipe(filter.restore())
    .pipe($.rename('foundation-apps.css'))
    .pipe(gulp.dest('./dist/css'))
    .pipe($.minifyCss())
    .pipe($.rename('foundation-apps.min.css'))
    .pipe(gulp.dest('./dist/css'));

  var js = gulp.src(foundationJS)
    .pipe($.concat('foundation-apps.js'))
    .pipe(gulp.dest('./dist/js'))
    .pipe($.uglify())
    .pipe($.rename('foundation-apps.min.js'))
    .pipe(gulp.dest('./dist/js'));

  return;
});

// Deploy documentation
gulp.task('deploy:docs', ['build', 'settings'], function() {
  return gulp.src('build/**')
    .pipe($.rsync({
      root: 'build',
      hostname: 'deployer@72.32.134.77',
      destination: '/home/deployer/sites/foundation-apps/current'
    }));
});

// Deploy to CDN
gulp.task('deploy:cdn', ['deploy:dist'], function() {
  var pkg = require('./package.json');

  return gulp.src('./dist/**/*', {base:'./dist/'})
    .pipe($.filter(['**/*.css', '**/*.js']))
    .pipe($.rename(function(path) {
      // Inject the version number into the filename
      var base = path.basename.split('.');
      if (base.length === 1) {
        base = base + '-' + pkg.version;
      }
      else {
        base = base.slice(0, -1).join('') + '-' + pkg.version + '.' + base[base.length - 1];
      }
      path.basename = base;
      path.dirname = '';
    }))
    .pipe($.rsync({
      hostname: 'deployer@72.32.134.77',
      destination: '/home/deployer/sites/foundation-apps-cdn/current',
      relative: false
    }));
});

// 10. NOW BRING IT TOGETHER
// - - - - - - - - - - - - - - -

// Build the documentation once
gulp.task('build', function(cb) {
  runSequence('clean', ['copy', 'copy:partials', 'css', 'javascript', 'javascript:deps', 'javascript:docs'], 'copy:templates', function() {
    console.log('Successfully built.');
    cb();
  });
});

// Build the documentation, start a test server, and re-compile when files change
gulp.task('default', ['build', 'server:start'], function() {

  // Watch static files
  gulp.watch(['./docs/**/*.*', '!./docs/templates/**/*.*', '!./docs/assets/{scss,js}/**/*.*'], ['copy']);

  // Watch Angular templates
  gulp.watch(['docs/templates/**/*.html'], ['copy:templates']);

  // Watch Angular partials
  gulp.watch(['js/angular/components/**/**.html'], ['copy:partials']);

  // Watch Sass
  gulp.watch(['./docs/assets/scss/**/*', './scss/**/*'], ['css']);

  // Watch JavaScript
  gulp.watch(['./docs/assets/js/**/*', './js/**/*'], ['javascript']);
});
<|endoftext|>


<commit_before>/**
 * Created by user on 2016/12/16.
 */
export default (store) => ({
    path : 'email',
    /*  Async getComponent is only invoked when route matches   */
    getComponent (nextState, cb) {
    /*  Webpack - use 'require.ensure' to create a split point
     and embed an async module loader (jsonp) when bundling   */
    require.ensure([], (require) => {
        /*  Webpack - use require callback to define
         dependencies for bundling   */
        const About = require('./components/EmailMenu').default
        // const reducer = require('./modules/counter').default

        /*  Add the reducer to the store on key 'counter'  */
        // injectReducer(store, { key: 'about', null })

        /*  Return getComponent   */
        cb(null, About)

        /* Webpack named bundle   */
    }, 'counter')
}
})
<commit_msg>Update index.js<commit_after>/**
 * Created by user on 2016/12/16.
 */
export default (store) => ({
    path : 'email',
    /*  Async getComponent is only invoked when route matches   */
    getComponent (nextState, cb) {
    /*  Webpack - use 'require.ensure' to create a split point
     and embed an async module loader (jsonp) when bundling   */
    require.ensure([], (require) => {
        /*  Webpack - use require callback to define
         dependencies for bundling   */
        const About = require('./components/EmailCont').default
        // const reducer = require('./modules/counter').default

        /*  Add the reducer to the store on key 'counter'  */
        // injectReducer(store, { key: 'about', null })

        /*  Return getComponent   */
        cb(null, About)

        /* Webpack named bundle   */
    }, 'counter')
}
})
<|endoftext|>


<commit_before>import Component from '@ember/component';
import { get, set, computed, observer, setProperties } from '@ember/object';
import { inject as service } from '@ember/service';
import ViewNewEdit from 'shared/mixins/view-new-edit';
import ChildHook from 'shared/mixins/child-hook';
import { alias } from '@ember/object/computed';
import { loadStylesheet, proxifyUrl } from 'shared/utils/load-script';
import layout from './template';
import { isEmpty } from '@ember/utils';

const MEMBER_CONFIG = {
  type: 'clusterRoleTemplateBinding',
};

export default Component.extend(ViewNewEdit, ChildHook, {
  layout,
  globalStore:      service(),
  intl:             service(),
  access:           service(),

  cluster:          alias('model.cluster'),
  originalCluster:  alias('model.originalCluster'),
  primaryResource:  alias('model.cluster'),

  step:             1,
  initialProvider:  null,
  memberConfig:     MEMBER_CONFIG,
  newCluster:       false,
  needReloadSchema: false,
  reloadingSchema:  false,
  schemaReloaded:   false,

  init() {
    this._super(...arguments);

    // On edit pass in initialProvider, for create just set provider directly
    const initialProvider = get(this, 'initialProvider');

    if ( initialProvider ) {
      set(this, 'provider', initialProvider);
    }

    if ( isEmpty(get(this, 'cluster.id')) ){
      set(this, 'newCluster', true);
    }

  },

  actions: {
    clickNext() {
      this.$('BUTTON[type="submit"]').click();
    },

    close() {
      this.sendAction('close');
    },
  },

  providerChoices: computed(
  'isEdit',
  'cluster.rancherKubernetesEngineConfig',
  'nodeDrivers.[]',
  'schemaReloaded',
  'intl.locale',
  function() {
    const intl = get(this, 'intl');

    let out = [
      {name: 'googlegke', driver: 'googlegke'},
      {name: 'amazoneks', driver: 'amazoneks'},
      {name: 'azureaks',  driver: 'azureaks'},
    ];

    get(this, 'model.nodeDrivers').filterBy('state','active').sortBy('name').forEach((driver) => {

      const name         = get(driver, 'name');
      const hasUi        = get(driver, 'hasUi');
      const hasIcon      = get(driver, 'hasBuiltinIconOnly');
      const uiUrl        = get(driver, 'uiUrl');
      const configName   = `${name}Config`;
      const driverSchema = get(this, 'globalStore').getById('schema', configName.toLowerCase());

      if( uiUrl ) {

        const cssUrl = proxifyUrl(uiUrl.replace(/\.js$/,'.css'), get(this, 'app.proxyEndpoint'));

        loadStylesheet(cssUrl, `driver-ui-css-${name}`);
      }

      if ( driverSchema ) {

        out.push({
          name:          name,
          driver:        'rke',
          genericIcon:   !hasUi && !hasIcon,
          nodeComponent: hasUi ? name : 'generic',
          nodeWhich:     name,
        });

      } else {

        set(this, 'needReloadSchema', true);

      }

    }),

    out.push({
      name:      'custom',
      driver:    'rke',
      nodeWhich: 'custom',
      preSave:   true
    });

    out.push({
      name:    'import',
      driver:  'import',
      preSave: true
    });

    out.forEach((driver) => {

      const key = `clusterNew.${driver.name}.label`;

      if ( !get(driver,'displayName') && intl.exists(key) ) {
        set(driver, 'displayName', intl.t(key));
      }

    });

    if ( get(this, 'isEdit') && get(this, 'cluster.rancherKubernetesEngineConfig') ) {
      out = out.filterBy('driver','rke');
    }

    return out;
  }),

  reloadSchema: observer('needReloadSchema', function() {

    if ( !get(this, 'reloadingSchema') && get(this, 'needReloadSchema') ) {

      set(this, 'reloadingSchema', true);

      get(this, 'globalStore').findAll('schema', {
        url: '/v3/schemas',
        forceReload: true
      }).then(() => {

        setProperties(this, {
          schemaReloaded: true,
          reloadingSchema: false
        });

      });
    }
  }),

  providerGroups: computed('providerChoices.@each.{name,driver,nodeComponent,nodeWhich,preSave}', function() {

    const choices     = get(this, 'providerChoices');
    const rkeGroup    = [];
    const cloudGroup  = [];
    const customGroup = [];
    const importGroup = [];

    choices.forEach((item) => {

      if (get(item, 'driver') === 'rke' && get(item, 'name') !== 'custom') {

        rkeGroup.pushObject(item);

      } else if (get(item, 'driver') === 'import' && get(item, 'name') !== 'custom') {

        importGroup.pushObject(item);

      } else if (get(item, 'name') === 'custom') {

        customGroup.pushObject(item);

      } else {

        cloudGroup.pushObject(item);

      }

    });

    return {
      rkeGroup,
      cloudGroup,
      customGroup,
      importGroup
    };

  }),

  driverInfo: computed('provider', function() {

    const name    = get(this, 'provider');
    const choices = get(this, 'providerChoices');
    const entry   = choices.findBy('name', name);

    if ( entry ) {

      return {
        name:            entry.name,
        driverComponent: `cluster-driver/driver-${entry.driver}`,
        nodeWhich:       entry.nodeWhich,
        preSave:         !!entry.preSave,
      };

    }

  }),

  didSave() {

    const originalCluster = get(this, 'cluster');

    return originalCluster.waitForCondition('InitialRolesPopulated').then(() => {

      return this.applyHooks().then(() => {

        const clone = originalCluster.clone();

        setProperties({
          cluster: clone,
          originalCluster: originalCluster,
        });

        return clone;

      });

    });

  },

  doneSaving() {

    if ( get(this, 'step') === 1 && get(this, 'driverInfo.preSave') ) {

      setProperties(this, {
        step: 2,
        initialProvider: get(this, 'provider')
      });

    } else {

      this.sendAction('close');

    }
  },
});
<commit_msg>Fix the import cluster issue<commit_after>import Component from '@ember/component';
import { get, set, computed, observer, setProperties } from '@ember/object';
import { inject as service } from '@ember/service';
import ViewNewEdit from 'shared/mixins/view-new-edit';
import ChildHook from 'shared/mixins/child-hook';
import { alias } from '@ember/object/computed';
import { loadStylesheet, proxifyUrl } from 'shared/utils/load-script';
import layout from './template';
import { isEmpty } from '@ember/utils';

const MEMBER_CONFIG = {
  type: 'clusterRoleTemplateBinding',
};

export default Component.extend(ViewNewEdit, ChildHook, {
  layout,
  globalStore:      service(),
  intl:             service(),
  access:           service(),

  cluster:          alias('model.cluster'),
  originalCluster:  alias('model.originalCluster'),
  primaryResource:  alias('model.cluster'),

  step:             1,
  initialProvider:  null,
  memberConfig:     MEMBER_CONFIG,
  newCluster:       false,
  needReloadSchema: false,
  reloadingSchema:  false,
  schemaReloaded:   false,

  init() {
    this._super(...arguments);

    // On edit pass in initialProvider, for create just set provider directly
    const initialProvider = get(this, 'initialProvider');

    if ( initialProvider ) {
      set(this, 'provider', initialProvider);
    }

    if ( isEmpty(get(this, 'cluster.id')) ){
      set(this, 'newCluster', true);
    }

  },

  actions: {
    clickNext() {
      this.$('BUTTON[type="submit"]').click();
    },

    close() {
      this.sendAction('close');
    },
  },

  providerChoices: computed(
  'isEdit',
  'cluster.rancherKubernetesEngineConfig',
  'nodeDrivers.[]',
  'schemaReloaded',
  'intl.locale',
  function() {
    const intl = get(this, 'intl');

    let out = [
      {name: 'googlegke', driver: 'googlegke'},
      {name: 'amazoneks', driver: 'amazoneks'},
      {name: 'azureaks',  driver: 'azureaks'},
    ];

    get(this, 'model.nodeDrivers').filterBy('state','active').sortBy('name').forEach((driver) => {

      const name         = get(driver, 'name');
      const hasUi        = get(driver, 'hasUi');
      const hasIcon      = get(driver, 'hasBuiltinIconOnly');
      const uiUrl        = get(driver, 'uiUrl');
      const configName   = `${name}Config`;
      const driverSchema = get(this, 'globalStore').getById('schema', configName.toLowerCase());

      if( uiUrl ) {

        const cssUrl = proxifyUrl(uiUrl.replace(/\.js$/,'.css'), get(this, 'app.proxyEndpoint'));

        loadStylesheet(cssUrl, `driver-ui-css-${name}`);
      }

      if ( driverSchema ) {

        out.push({
          name:          name,
          driver:        'rke',
          genericIcon:   !hasUi && !hasIcon,
          nodeComponent: hasUi ? name : 'generic',
          nodeWhich:     name,
        });

      } else {

        set(this, 'needReloadSchema', true);

      }

    }),

    out.push({
      name:      'custom',
      driver:    'rke',
      nodeWhich: 'custom',
      preSave:   true
    });

    out.push({
      name:    'import',
      driver:  'import',
      preSave: true
    });

    out.forEach((driver) => {

      const key = `clusterNew.${driver.name}.label`;

      if ( !get(driver,'displayName') && intl.exists(key) ) {
        set(driver, 'displayName', intl.t(key));
      }

    });

    if ( get(this, 'isEdit') && get(this, 'cluster.rancherKubernetesEngineConfig') ) {
      out = out.filterBy('driver','rke');
    }

    return out;
  }),

  reloadSchema: observer('needReloadSchema', function() {

    if ( !get(this, 'reloadingSchema') && get(this, 'needReloadSchema') ) {

      set(this, 'reloadingSchema', true);

      get(this, 'globalStore').findAll('schema', {
        url: '/v3/schemas',
        forceReload: true
      }).then(() => {

        setProperties(this, {
          schemaReloaded: true,
          reloadingSchema: false
        });

      });
    }
  }),

  providerGroups: computed('providerChoices.@each.{name,driver,nodeComponent,nodeWhich,preSave}', function() {

    const choices     = get(this, 'providerChoices');
    const rkeGroup    = [];
    const cloudGroup  = [];
    const customGroup = [];
    const importGroup = [];

    choices.forEach((item) => {

      if (get(item, 'driver') === 'rke' && get(item, 'name') !== 'custom') {

        rkeGroup.pushObject(item);

      } else if (get(item, 'driver') === 'import' && get(item, 'name') !== 'custom') {

        importGroup.pushObject(item);

      } else if (get(item, 'name') === 'custom') {

        customGroup.pushObject(item);

      } else {

        cloudGroup.pushObject(item);

      }

    });

    return {
      rkeGroup,
      cloudGroup,
      customGroup,
      importGroup
    };

  }),

  driverInfo: computed('provider', function() {

    const name    = get(this, 'provider');
    const choices = get(this, 'providerChoices');
    const entry   = choices.findBy('name', name);

    if ( entry ) {

      return {
        name:            entry.name,
        driverComponent: `cluster-driver/driver-${entry.driver}`,
        nodeWhich:       entry.nodeWhich,
        preSave:         !!entry.preSave,
      };

    }

  }),

  didSave() {

    const originalCluster = get(this, 'cluster');

    return originalCluster.waitForCondition('InitialRolesPopulated').then(() => {

      return this.applyHooks().then(() => {

        const clone = originalCluster.clone();

        setProperties(this, {
          cluster: clone,
          originalCluster: originalCluster,
        });

        return clone;

      });

    });

  },

  doneSaving() {

    if ( get(this, 'step') === 1 && get(this, 'driverInfo.preSave') ) {

      setProperties(this, {
        step: 2,
        initialProvider: get(this, 'provider')
      });

    } else {

      this.sendAction('close');

    }
  },
});
<|endoftext|>