<commit_before>const typeConverter = require('../utils/typeConverter');
const utils = require('../utils/utils');
const logger = require('../logger');

module.exports = class MysqlSchemaPreprocessor {

  /**
   * Normalize the table schema.
   *
   * @param tableSchema
   * @returns {{}}
   */
  convertToStandardSchema(tableSchema) {
    const schema = {};
    schema.name = tableSchema['COLUMN_NAME'] ? tableSchema['COLUMN_NAME'] : null;
    schema.primary = !!(tableSchema['COLUMN_KEY'] && tableSchema['COLUMN_KEY'] === 'PRI');
    schema.unique = !!(tableSchema['COLUMN_KEY'] && (tableSchema['COLUMN_KEY'] === 'PRI' || tableSchema['COLUMN_KEY'] === 'UNI'));
    schema.foreignKey = !!(tableSchema['COLUMN_KEY'] && tableSchema['COLUMN_KEY'] === 'MUL');
    schema.allowNull = !!(tableSchema['IS_NULLABLE'] && tableSchema['IS_NULLABLE'] === 'YES');
    schema.dataType = {
      type: typeConverter.convertSqlType(tableSchema['DATA_TYPE']),
      size: tableSchema['CHARACTER_MAXIMUM_LENGTH'] ? parseInt(tableSchema['CHARACTER_MAXIMUM_LENGTH']) : null,
    };
    return schema;
  }

  /**
   * Normalizes all foreign key relations, by creating the respective columns in the target tables.
   *
   * @param schema
   * @returns {*}
   */
  normalizeSchemaRelations(schema) {
    schema = this.sortSchema(schema);
    schema = this.normalizeOneToOneRelations(schema);
    schema = this.normalizeOneToManyRelations(schema);
    schema = this.normalizeManyToManyRelations(schema);
    schema = this.cleanupUnusedPropertiesFromColumns(schema);
    schema = this.stripEmptyTables(schema);
    logger.info(JSON.stringify(schema));
    console.log(JSON.stringify(schema));
    return schema;
  }

  /**
   * Normalizes one to one relations.
   * Parses the table list and checks for tables
   * which have unique foreign keys, are not CrossReferenceTables(many to many)
   * and adds the foreign column on both sides of the relation.
   *
   * @param schema
   * @returns {*}
   */
  normalizeOneToOneRelations(schema) {
    let updatedSchema = schema;
    schema.forEach(table => {
      if (!this.tableHasForeignKeys(table) || this.tableIsCrossReferenceTable(table)) {
        return table;
      }
      table.columns.forEach(column => {
        if (column.foreignKey && column.unique) {
          const targetColumn = {
            name: utils.singular(table.name),
            primary: column.primary,
            unique: true,
            allowNull: false,
            dataType: {
              type: utils.toTitleCase(table.name),
              isArray: false
            }
          };

          updatedSchema = this.addColumnToTable(updatedSchema, column.dataType.references.table, targetColumn);
          updatedSchema = this.removeColumnFromTable(updatedSchema, table.name, column.name);
        }
      });
    });

    return updatedSchema;
  }

  /**
   * Normalizes one to many relations.
   * Parses the table list and checks for tables
   * which have foreign keys, are not CrossReferenceTables(many to many)
   * and adds the foreign column on the holder.
   *
   * @param schema
   * @returns {*}
   */
  normalizeOneToManyRelations(schema) {
    let updatedSchema = schema;
    schema.forEach(table => {
      if (!this.tableHasForeignKeys(table) || this.tableIsCrossReferenceTable(table)) {
        return table;
      }
      table.columns.forEach(column => {
        if (column.foreignKey) {
          const targetColumn = {
            name: table.name,
            primary: column.primary,
            unique: false,
            allowNull: true,
            dataType: {
              type: utils.toTitleCase(table.name),
              isArray: true
            }
          };
          updatedSchema = this.addColumnToTable(updatedSchema, column.dataType.references.table, targetColumn);
          updatedSchema = this.removeColumnFromTable(updatedSchema, table.name, column.name);
        }
      });
    });

    return updatedSchema;
  }

  /**
   * Normalizes many to many relations.
   * Parses the table list and checks for tables
   * which are CrossReferenceTables(many to many)
   * and adds the foreign columns to the source and target tables.
   *
   * @param schema
   * @returns {*}
   */
  normalizeManyToManyRelations(schema) {
    let updatedSchema = schema;
    schema.forEach(table => {
      if (!this.tableIsCrossReferenceTable(table) || table.columns.length !== 2) {
        return table;
      }
      const source = table.columns[0];
      const target = table.columns[1];

      const sourceColumn = {
        name: source.dataType.references.table,
        primary: source.primary,
        unique: false,
        allowNull: true,
        dataType: {
          type: utils.toTitleCase(source.dataType.type),
          isArray: true
        }
      };

      const targetColumn = {
        name: target.dataType.references.table,
        primary: target.primary,
        unique: false,
        allowNull: true,
        dataType: {
          type: utils.toTitleCase(target.dataType.type),
          isArray: true
        }
      };

      updatedSchema = this.addColumnToTable(updatedSchema, source.dataType.references.table, targetColumn);
      updatedSchema = this.addColumnToTable(updatedSchema, target.dataType.references.table, sourceColumn);
      updatedSchema = this.removeColumnFromTable(updatedSchema, table.name, source.name);
      updatedSchema = this.removeColumnFromTable(updatedSchema, table.name, target.name);

    });

    return updatedSchema;
  }

  /**
   * Strips tables with no columns from schema.
   *
   * @param schema
   * @returns {Array<*>}
   */
  stripEmptyTables(schema) {
    return schema.filter(table => !!Object.keys(table.columns).length);
  }

  /**
   * Checks if the table has any foreign key columns.
   *
   * @param table
   * @returns {boolean}
   */
  tableHasForeignKeys(table) {
    return !!table.columns.filter(column => column.foreignKey).length;
  }

  /**
   * Checks if the table is a cross reference map(association table for many to many relations).
   *
   * @param table
   * @returns {boolean}
   */
  tableIsCrossReferenceTable(table) {
    return table.columns.filter(column => column.foreignKey).length === table.columns.length;
  }

  /**
   * Adds a column to a table in the schema.
   *
   * @param schema
   * @param tableName
   * @param column
   * @returns {Array|*}
   */
  addColumnToTable(schema, tableName, column) {
    return this.removeColumnFromTable(schema, tableName, column.name).map(table => {
      if (table.name !== tableName) {
        return table;
      }
      table.columns.push(column);

      return table;
    });
  }

  /**
   * Removes a column from a table in the schema.
   *
   * @param schema
   * @param tableName
   * @param columnName
   * @returns {Array|*}
   */
  removeColumnFromTable(schema, tableName, columnName) {
    return schema.map(table => {
      if (table.name !== tableName) {
        return table;
      }
      table.columns = table.columns.filter(column => {
        return column.name !== columnName;
      });

      return table;
    });
  }

  /**
   * Remove unused properties from schema.
   *
   * @param schema
   * @returns {Array|*}
   */
  cleanupUnusedPropertiesFromColumns(schema) {
    return schema.map(table => {
      table.columns.map(column => {
        delete column.foreignKey;
        return column;
      });
      return table;
    });
  }

  /**
   * Sort schema so tables without foreign keys are first.
   *
   * @param schema
   * @returns {Array|*}
   */
  sortSchema(schema) {
    return schema.sort((a, b) => {
      return  Number(this.tableHasForeignKeys(b)) - Number(this.tableHasForeignKeys(a));
    });
  }
};
<commit_msg>fix sorting schema<commit_after>const typeConverter = require('../utils/typeConverter');
const utils = require('../utils/utils');
const logger = require('../logger');

module.exports = class MysqlSchemaPreprocessor {

  /**
   * Normalize the table schema.
   *
   * @param tableSchema
   * @returns {{}}
   */
  convertToStandardSchema(tableSchema) {
    const schema = {};
    schema.name = tableSchema['COLUMN_NAME'] ? tableSchema['COLUMN_NAME'] : null;
    schema.primary = !!(tableSchema['COLUMN_KEY'] && tableSchema['COLUMN_KEY'] === 'PRI');
    schema.unique = !!(tableSchema['COLUMN_KEY'] && (tableSchema['COLUMN_KEY'] === 'PRI' || tableSchema['COLUMN_KEY'] === 'UNI'));
    schema.foreignKey = !!(tableSchema['COLUMN_KEY'] && tableSchema['COLUMN_KEY'] === 'MUL');
    schema.allowNull = !!(tableSchema['IS_NULLABLE'] && tableSchema['IS_NULLABLE'] === 'YES');
    schema.dataType = {
      type: typeConverter.convertSqlType(tableSchema['DATA_TYPE']),
      size: tableSchema['CHARACTER_MAXIMUM_LENGTH'] ? parseInt(tableSchema['CHARACTER_MAXIMUM_LENGTH']) : null,
    };
    return schema;
  }

  /**
   * Normalizes all foreign key relations, by creating the respective columns in the target tables.
   *
   * @param schema
   * @returns {*}
   */
  normalizeSchemaRelations(schema) {
    schema = this.normalizeOneToOneRelations(schema);
    schema = this.normalizeOneToManyRelations(schema);
    schema = this.normalizeManyToManyRelations(schema);
    schema = this.cleanupUnusedPropertiesFromColumns(schema);
    schema = this.stripEmptyTables(schema);
    schema = this.sortSchema(schema);

    logger.info(JSON.stringify(schema));
    console.log(JSON.stringify(schema));
    return schema;
  }

  /**
   * Normalizes one to one relations.
   * Parses the table list and checks for tables
   * which have unique foreign keys, are not CrossReferenceTables(many to many)
   * and adds the foreign column on both sides of the relation.
   *
   * @param schema
   * @returns {*}
   */
  normalizeOneToOneRelations(schema) {
    let updatedSchema = schema;
    schema.forEach(table => {
      if (!this.tableHasForeignKeys(table) || this.tableIsCrossReferenceTable(table)) {
        return table;
      }
      table.columns.forEach(column => {
        if (column.foreignKey && column.unique) {
          const targetColumn = {
            name: utils.singular(table.name),
            primary: column.primary,
            unique: true,
            allowNull: false,
            dataType: {
              type: utils.toTitleCase(table.name),
              isArray: false
            }
          };

          updatedSchema = this.addColumnToTable(updatedSchema, column.dataType.references.table, targetColumn);
          updatedSchema = this.removeColumnFromTable(updatedSchema, table.name, column.name);
        }
      });
    });

    return updatedSchema;
  }

  /**
   * Normalizes one to many relations.
   * Parses the table list and checks for tables
   * which have foreign keys, are not CrossReferenceTables(many to many)
   * and adds the foreign column on the holder.
   *
   * @param schema
   * @returns {*}
   */
  normalizeOneToManyRelations(schema) {
    let updatedSchema = schema;
    schema.forEach(table => {
      if (!this.tableHasForeignKeys(table) || this.tableIsCrossReferenceTable(table)) {
        return table;
      }
      table.columns.forEach(column => {
        if (column.foreignKey) {
          const targetColumn = {
            name: table.name,
            primary: column.primary,
            unique: false,
            allowNull: true,
            dataType: {
              type: utils.toTitleCase(table.name),
              isArray: true
            }
          };
          updatedSchema = this.addColumnToTable(updatedSchema, column.dataType.references.table, targetColumn);
          updatedSchema = this.removeColumnFromTable(updatedSchema, table.name, column.name);
        }
      });
    });

    return updatedSchema;
  }

  /**
   * Normalizes many to many relations.
   * Parses the table list and checks for tables
   * which are CrossReferenceTables(many to many)
   * and adds the foreign columns to the source and target tables.
   *
   * @param schema
   * @returns {*}
   */
  normalizeManyToManyRelations(schema) {
    let updatedSchema = schema;
    schema.forEach(table => {
      if (!this.tableIsCrossReferenceTable(table) || table.columns.length !== 2) {
        return table;
      }
      const source = table.columns[0];
      const target = table.columns[1];

      const sourceColumn = {
        name: source.dataType.references.table,
        primary: source.primary,
        unique: false,
        allowNull: true,
        dataType: {
          type: utils.toTitleCase(source.dataType.type),
          isArray: true
        }
      };

      const targetColumn = {
        name: target.dataType.references.table,
        primary: target.primary,
        unique: false,
        allowNull: true,
        dataType: {
          type: utils.toTitleCase(target.dataType.type),
          isArray: true
        }
      };

      updatedSchema = this.addColumnToTable(updatedSchema, source.dataType.references.table, targetColumn);
      updatedSchema = this.addColumnToTable(updatedSchema, target.dataType.references.table, sourceColumn);
      updatedSchema = this.removeColumnFromTable(updatedSchema, table.name, source.name);
      updatedSchema = this.removeColumnFromTable(updatedSchema, table.name, target.name);

    });

    return updatedSchema;
  }

  /**
   * Strips tables with no columns from schema.
   *
   * @param schema
   * @returns {Array<*>}
   */
  stripEmptyTables(schema) {
    return schema.filter(table => !!Object.keys(table.columns).length);
  }

  /**
   * Checks if the table has any foreign key columns.
   *
   * @param table
   * @returns {boolean}
   */
  tableHasForeignKeys(table) {
    return !!table.columns.filter(column => column.foreignKey).length;
  }

  /**
   * Checks if the table is a cross reference map(association table for many to many relations).
   *
   * @param table
   * @returns {boolean}
   */
  tableIsCrossReferenceTable(table) {
    return table.columns.filter(column => column.foreignKey).length === table.columns.length;
  }

  /**
   * Adds a column to a table in the schema.
   *
   * @param schema
   * @param tableName
   * @param column
   * @returns {Array|*}
   */
  addColumnToTable(schema, tableName, column) {
    return this.removeColumnFromTable(schema, tableName, column.name).map(table => {
      if (table.name !== tableName) {
        return table;
      }
      table.columns.push(column);

      return table;
    });
  }

  /**
   * Removes a column from a table in the schema.
   *
   * @param schema
   * @param tableName
   * @param columnName
   * @returns {Array|*}
   */
  removeColumnFromTable(schema, tableName, columnName) {
    return schema.map(table => {
      if (table.name !== tableName) {
        return table;
      }
      table.columns = table.columns.filter(column => {
        return column.name !== columnName;
      });

      return table;
    });
  }

  /**
   * Remove unused properties from schema.
   *
   * @param schema
   * @returns {Array|*}
   */
  cleanupUnusedPropertiesFromColumns(schema) {
    return schema.map(table => {
      table.columns.map(column => {
        delete column.foreignKey;
        return column;
      });
      return table;
    });
  }

  /**
   * Sort schema so tables without foreign keys are first.
   *
   * @param schema
   * @returns {Array|*}
   */
  sortSchema(schema) {
    return schema.sort((a, b) => {

      return  Number(
        Boolean(
          b.columns.filter((column) => {
            column.dataType.hasOwnProperty('isArray')
          }).length)
        ) - Number(
          Boolean(a.columns.filter((column) => {
            column.dataType.hasOwnProperty('isArray')
          }).length)
        );
    });
  }
};
<|endoftext|>


<commit_before>// Copyright 2015, EMC, Inc.

'use strict';

var di = require('di'),
    express = require('express');

module.exports = workflowsRouterFactory;

di.annotate(workflowsRouterFactory, new di.Provide('Http.Api.Workflows'));
di.annotate(workflowsRouterFactory,
    new di.Inject(
        'Protocol.TaskGraphRunner',
        'Http.Services.RestApi',
        'Services.Waterline',
        '_'
    )
);

function workflowsRouterFactory (taskgraphRunner, rest, waterline, _) {
    var router = express.Router();

    /**
     * @api {get} /api/1.1/workflows GET /
     * @apiVersion 1.1.0
     * @apiDescription get list of active and past run workflow instances
     * or an empty object if there are none
     * @apiName workflows-get
     * @apiGroup workflows
     * @apiSuccess {json} workflows List of all workflows or if there are none an empty object.
     */

    router.get('/workflows/', rest(function (req) {
        return waterline.graphobjects.find(req.query);
    }));

    /**
     * @api {put} /api/1.1/workflows PUT /
     * @apiVersion 1.1.0
     * @apiDescription define a new workflow
     * @apiName workflows-define
     * @apiGroup workflows
     * @apiError Error problem was encountered, workflow was not written.
     * @apiErrorExample Error-Response:
     *     HTTP/1.1 500 Error
     *     {
     *       "error": "upload failed."
     *     }
     */

    router.put('/workflows/', rest(function (req) {
        return taskgraphRunner.defineTaskGraph(req.body);
    }));

    /**
     * @api {put} /api/1.1/workflows/tasks PUT /tasks
     * @apiVersion 1.1.0
     * @apiDescription add a task to the tasks library
     * @apiName workflowTasks-define
     * @apiGroup workflowTasks
     * @apiParam {json} task The task to be added to the library
     * @apiSuccess {string} injectableName The value of the injectableName of the task
     */

    router.put('/workflows/tasks', rest(function (req) {
        return taskgraphRunner.defineTask(req.body);
    }));

    /**
     * @api {get} /api/1.1/workflows/tasks/library GET /tasks/library
     * @apiVersion 1.1.0
     * @apiDescription get list of tasks possible to run in workflows
     * @apiName tasks-library
     * @apiSuccess {json} tasks List of all tasks possible to run in workflows.
     * @apiGroup workflowTasks
     */

    router.get('/workflows/tasks/library', rest(function (req) {
        //TODO(heckj): verify that the filter object matches this
        // and that models are relevant here.
        var filter = _.merge(
            req.query || {}
        );
        return taskgraphRunner.getTaskLibrary(filter);
    }));

    /**
     * @api {get} /api/1.1/workflows/library GET /library
     * @apiVersion 1.1.0
     * @apiDescription get list of workflows possible to run
     * @apiName workflows-library
     * @apiSuccess {json} workflows list of workflows that are possible to run
     * @apiGroup workflows
     */

    router.get('/workflows/library', rest(function () {
        //TODO(heckj): library function on protocol takes a filter,
        // check to see what options are supported, and if this should pass any
        return taskgraphRunner.getTaskGraphLibrary();
    }));

    /**
     * @api {get} /api/1.1/workflows/library/:identifier GET /library/:identifier
     * @apiVersion 1.1.0
     * @apiDescription get a specific workflow from the library
     * @apiParam {String} identifier of workflow, must cast to ObjectId
     * @apiName workflows-library-item
     * @apiSuccess {json} workflow the specific workflow from the library that have the identifier
     * @apiGroup workflows
     */

    router.get('/workflows/library/:identifier', rest(function (req) {
        //TODO(heckj): verify format of filter for library call
        var filter = { injectableName: req.params.identifier };
        return taskgraphRunner.getTaskGraphLibrary(filter);
    }));

    /**
     * @api {get} /api/1.1/workflows/:identifier GET /:id
     * @apiVersion 1.1.0
     * @apiDescription get a specific workflow
     * @apiName workflow-get
     * @apiGroup workflows
     * @apiParam {String} identifier of workflow, must cast to ObjectId
     * @apiSuccess {json} workflow the workflow that have the identifier
     * @apiError NotFound There is no workflow with identifier
     * @apiErrorExample Error-Response:
     *     HTTP/1.1 404 Not Found
     *     {
     *       "error": "Not Found"
     *     }
     */

    router.get('/workflows/:identifier', rest(function (req) {
        return waterline.graphobjects.needByIdentifier(req.params.identifier);
    }));

    return router;
}
<commit_msg>Fix a "Line too long" violation<commit_after>// Copyright 2015, EMC, Inc.

'use strict';

var di = require('di'),
    express = require('express');

module.exports = workflowsRouterFactory;

di.annotate(workflowsRouterFactory, new di.Provide('Http.Api.Workflows'));
di.annotate(workflowsRouterFactory,
    new di.Inject(
        'Protocol.TaskGraphRunner',
        'Http.Services.RestApi',
        'Services.Waterline',
        '_'
    )
);

function workflowsRouterFactory (taskgraphRunner, rest, waterline, _) {
    var router = express.Router();

    /**
     * @api {get} /api/1.1/workflows GET /
     * @apiVersion 1.1.0
     * @apiDescription get list of active and past run workflow instances
     * or an empty object if there are none
     * @apiName workflows-get
     * @apiGroup workflows
     * @apiSuccess {json} workflows List of all workflows or if there are none an empty object.
     */

    router.get('/workflows/', rest(function (req) {
        return waterline.graphobjects.find(req.query);
    }));

    /**
     * @api {put} /api/1.1/workflows PUT /
     * @apiVersion 1.1.0
     * @apiDescription define a new workflow
     * @apiName workflows-define
     * @apiGroup workflows
     * @apiError Error problem was encountered, workflow was not written.
     * @apiErrorExample Error-Response:
     *     HTTP/1.1 500 Error
     *     {
     *       "error": "upload failed."
     *     }
     */

    router.put('/workflows/', rest(function (req) {
        return taskgraphRunner.defineTaskGraph(req.body);
    }));

    /**
     * @api {put} /api/1.1/workflows/tasks PUT /tasks
     * @apiVersion 1.1.0
     * @apiDescription add a task to the tasks library
     * @apiName workflowTasks-define
     * @apiGroup workflowTasks
     * @apiParam {json} task The task to be added to the library
     * @apiSuccess {string} injectableName The value of the injectableName of the task
     */

    router.put('/workflows/tasks', rest(function (req) {
        return taskgraphRunner.defineTask(req.body);
    }));

    /**
     * @api {get} /api/1.1/workflows/tasks/library GET /tasks/library
     * @apiVersion 1.1.0
     * @apiDescription get list of tasks possible to run in workflows
     * @apiName tasks-library
     * @apiSuccess {json} tasks List of all tasks possible to run in workflows.
     * @apiGroup workflowTasks
     */

    router.get('/workflows/tasks/library', rest(function (req) {
        //TODO(heckj): verify that the filter object matches this
        // and that models are relevant here.
        var filter = _.merge(
            req.query || {}
        );
        return taskgraphRunner.getTaskLibrary(filter);
    }));

    /**
     * @api {get} /api/1.1/workflows/library GET /library
     * @apiVersion 1.1.0
     * @apiDescription get list of workflows possible to run
     * @apiName workflows-library
     * @apiSuccess {json} workflows list of workflows that are possible to run
     * @apiGroup workflows
     */

    router.get('/workflows/library', rest(function () {
        //TODO(heckj): library function on protocol takes a filter,
        // check to see what options are supported, and if this should pass any
        return taskgraphRunner.getTaskGraphLibrary();
    }));

    /**
     * @api {get} /api/1.1/workflows/library/:identifier GET /library/:identifier
     * @apiVersion 1.1.0
     * @apiDescription get a specific workflow from the library
     * @apiParam {String} identifier of workflow, must cast to ObjectId
     * @apiName workflows-library-item
     * @apiSuccess {json} workflow the workflow that have the identifier
     * @apiGroup workflows
     */

    router.get('/workflows/library/:identifier', rest(function (req) {
        //TODO(heckj): verify format of filter for library call
        var filter = { injectableName: req.params.identifier };
        return taskgraphRunner.getTaskGraphLibrary(filter);
    }));

    /**
     * @api {get} /api/1.1/workflows/:identifier GET /:id
     * @apiVersion 1.1.0
     * @apiDescription get a specific workflow
     * @apiName workflow-get
     * @apiGroup workflows
     * @apiParam {String} identifier of workflow, must cast to ObjectId
     * @apiSuccess {json} workflow the workflow that have the identifier
     * @apiError NotFound There is no workflow with identifier
     * @apiErrorExample Error-Response:
     *     HTTP/1.1 404 Not Found
     *     {
     *       "error": "Not Found"
     *     }
     */

    router.get('/workflows/:identifier', rest(function (req) {
        return waterline.graphobjects.needByIdentifier(req.params.identifier);
    }));

    return router;
}
<|endoftext|>


<commit_before>'use strict';

/**
 * Module dependencies.
 */

var integration = require('analytics.js-integration');
var each = require('each');

/**
 * Expose `Pinterest`.
 */

var Pinterest = module.exports = integration('Pinterest')
  .tag('')
  .mapping('events');

/**
 * Initialize.
 *
 * @api public
 */

Pinterest.prototype.initialize = function() {
  this.ready();
};

/**
 * Track.
 *
 * @api public
 * @param {Track} track
 */

Pinterest.prototype.track = function(track) {
  var events = this.events(track.event());
  var self = this;
  each(events, function(tid) {
    self.load({
      tid: tid
    });
  });
};
<commit_msg>Building out custom img insert<commit_after>'use strict';

/**
 * Module dependencies.
 */

var integration = require('analytics.js-integration');
var each = require('each');

/**
 * Expose `Pinterest`.
 */

var Pinterest = module.exports = integration('Pinterest')
  .tag('')
  .mapping('events');

/**
 * Initialize.
 *
 * @api public
 */

Pinterest.prototype.initialize = function() {
  this.ready();
};

Pinterest.prototype.loaded = function() {
  return true;
};

/**
 * Track.
 *
 * @api public
 * @param {Track} track
 */

Pinterest.prototype.track = function(track) {
  var events = this.events(track.event());
  var self = this;
  each(events, function(tid) {
    self.fire(tid);
  });
};

/**
 * Fire Pixel
*/

Pinterest.prototype.fire = function(tid){
  var src = 'https://ct.pinterest.com/?tid=' + tid + '&value=0.00&quantity=1';
  var pixel = document.createElement('img');
  pixel.setAttribute('height', 1);
  pixel.setAttribute('width', 1);
  pixel.style.display = 'none';
  pixel.setAttribute('alt', '');
  pixel.setAttribute('src', src);
  document.body.appendChild(pixel);
};
<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
import { Field } from 'react-final-form';
import setFieldData from 'final-form-set-field-data';
import {
  isEqual,
  toNumber,
} from 'lodash';

import stripesFinalForm from '@folio/stripes/final-form';
import {
  Paneset,
  Pane,
  PaneMenu,
  TextArea,
  Button,
  Row,
  Col,
  Checkbox,
} from '@folio/stripes/components';

import UserInfo from './UserInfo';
import FeeFineInfo from './FeeFineInfo';
import ItemInfo from './ItemInfo';

function showValidationErrors({ feeFineId, ownerId, amount }) {
  const errors = {};
  if (!feeFineId) {
    errors.feeFineId = <FormattedMessage id="ui-users.feefines.modal.error" />;
  }
  if (!ownerId) {
    errors.ownerId = <FormattedMessage id="ui-users.feefines.modal.error" />;
  }
  if (toNumber(amount) <= 0) {
    errors.amount = <FormattedMessage id="ui-users.accounts.error.message" />;
  }
  if (!amount) {
    errors.amount = <FormattedMessage id="ui-users.errors.missingRequiredField" />;
  }
  if (Number.isNaN(toNumber(amount)) && amount) {
    errors.amount = <FormattedMessage id="ui-users.charge.errors.amount" />;
  }

  return errors;
}

class ChargeForm extends React.Component {
  static propTypes = {
    user: PropTypes.object,
    item: PropTypes.object,
    stripes: PropTypes.object,
    ownerId: PropTypes.string,
    owners: PropTypes.arrayOf(PropTypes.object),
    ownerList: PropTypes.arrayOf(PropTypes.object),
    feefines: PropTypes.arrayOf(PropTypes.object),
    form: PropTypes.object.isRequired,
    onClickCancel: PropTypes.func,
    onChangeOwner: PropTypes.func.isRequired,
    onChangeFeeFine: PropTypes.func.isRequired,
    handleSubmit: PropTypes.func.isRequired,
    onClickSelectItem: PropTypes.func.isRequired,
    onFindShared: PropTypes.func.isRequired,
    pristine: PropTypes.bool,
    submitting: PropTypes.bool,
    invalid: PropTypes.bool,
    selectedLoan: PropTypes.object,
    isPending: PropTypes.object,
    onSubmit: PropTypes.func,
    servicePointsIds: PropTypes.arrayOf(PropTypes.string),
    defaultServicePointId: PropTypes.string,
    location: PropTypes.object,
    history: PropTypes.object,
    initialValues: PropTypes.object,
    match: PropTypes.object,
    feeFineTypeOptions: PropTypes.arrayOf(PropTypes.object).isRequired,
  }

  constructor(props) {
    super(props);

    this.onChangeFeeFine = this.onChangeFeeFine.bind(this);
    this.onChangeOwner = this.onChangeOwner.bind(this);
    this.query = 0;
    this.feeFineId = null;
  }

  componentDidUpdate(prevProps) {
    const {
      owners,
      onFindShared,
    } = this.props;
    const { owners: prevOwners } = prevProps;

    if (prevOwners !== owners) {
      const shared = (owners.find(o => o.owner === 'Shared') || {}).id;
      onFindShared(shared);
    }
  }

  async onChangeFeeFine(e) {
    const {
      feefines,
      form: { change },
    } = this.props;

    if (e?.target?.value) {
      const feeFineId = e.target.value;
      await this.props.onChangeFeeFine(e);
      const feefine = feefines.find(f => f.id === feeFineId) || {};
      change('feeFineId', feefine.id);
      this.amount = feefine.defaultAmount || 0;
      this.amount = parseFloat(this.amount).toFixed(2);
      const defaultAmount = parseFloat(feefine.defaultAmount || 0).toFixed(2);
      change('amount', defaultAmount);
    }
  }

  onChangeOwner(e) {
    const { form: { change, reset } } = this.props;
    reset();
    const ownerId = e.target.value;

    this.props.onChangeOwner(e);
    change('ownerId', ownerId);
  }

  goToAccounts = () => {
    const {
      history,
      match: {
        params: { id },
      },
    } = this.props;

    history.push(`/users/${id}/accounts/open`);
  }

  render() {
    const {
      user,
      selectedLoan: selectedLoanProp,
      onSubmit,
      handleSubmit,
      initialValues,
      feeFineTypeOptions,
      form,
      form : {
        getState,
        change,
      },
      submitting,
      pristine,
      isPending,
      stripes,
    } = this.props;
    const {
      valid,
      values: {
        feeFineId,
        ownerId,
        notify,
      }
    } = getState();

    const selectedLoan = selectedLoanProp || {};
    const editable = !(selectedLoan.id);
    const itemLoan = {
      id: selectedLoan.itemId,
      instance: (selectedLoan.item || {}).title,
      barcode: (selectedLoan.item || {}).barcode,
      itemStatus: ((selectedLoan.item || {}).status || {}).name,
      callNumber: (selectedLoan.item || {}).callNumber,
      location: selectedLoan?.item?.effectiveLocation?.name,
      type: ((selectedLoan.item || {}).materialType || {}).name
    };
    const item = (editable) ? this.props.item : itemLoan;
    const feefineList = [];
    const ownerOptions = [];

    this.props.owners.forEach((own = {}) => {
      if (own.owner !== 'Shared') ownerOptions.push({ label: own.owner, value: own.id });
    });

    feeFineTypeOptions.forEach((feefineItem) => {
      const fee = {};
      fee.label = feefineItem.feeFineType;
      fee.value = feefineItem.id;
      feefineList.push(fee);
    });

    let showNotify = false;
    const feefine = this.props.feefines.find(f => f.id === feeFineId) || {};
    const owner = this.props.owners.find(o => o.id === ownerId) || {};
    if (feefine?.chargeNoticeId || owner?.defaultChargeNoticeId) {
      showNotify = true;
    }

    const lastMenu = (
      <PaneMenu>
        <Button
          id="cancelCharge"
          onClick={this.goToAccounts}
          marginBottom0
        >
          <FormattedMessage id="ui-users.feefines.modal.cancel" />
        </Button>
        <Button
          id="chargeAndPay"
          // disabled={pristine || submitting || !valid}
          disabled={true}
          onClick={() => {
            change('pay', true);
            handleSubmit(data => onSubmit(data));
          }}
          marginBottom0
        >
          <FormattedMessage id="ui-users.charge.Pay" />
        </Button>
        <Button
          id="chargeOnly"
          disabled={pristine || submitting || !valid}
          onClick={() => {
            change('pay', false);
            handleSubmit(data => onSubmit(data));
          }}
          marginBottom0
        >
          <FormattedMessage id="ui-users.charge.onlyCharge" />
        </Button>
      </PaneMenu>);

    return (
      <Paneset data-test-charge-form>
        <Pane
          defaultWidth="100%"
          dismissible
          onClose={this.goToAccounts}
          paneTitle={(
            <FormattedMessage id="ui-users.charge.title" />
          )}
          lastMenu={lastMenu}
        >
          <UserInfo user={user} />

          <form
            onSubmit={handleSubmit}
            id="feeFineChargeForm"
          >
            <FeeFineInfo
              form={form}
              stripes={stripes}
              initialValues={initialValues}
              ownerOptions={ownerOptions}
              isPending={isPending}
              onChangeOwner={this.onChangeOwner}
              onChangeFeeFine={this.onChangeFeeFine}
              feefineList={feefineList}
            />

            <ItemInfo {...this.props} item={item} onClickSelectItem={this.props.onClickSelectItem} editable={editable} />

<FormattedMessage id="ui-users.charge.comment" />

            <Row>
              <Col xs={12} sm={10} md={7} lg={5}>
                <Field
                  id="comments"
                  name="comments"
                  component={TextArea}
                  fullWidth
                />
              </Col>
            </Row>
            {showNotify &&

                <Row>
                  <Col xs>
                    <Field
                      name="notify"
                      component={Checkbox}
                      type="checkbox"
                      inline
                      label={<FormattedMessage id="ui-users.accounts.notifyPatron" />}
                    />
                  </Col>
                </Row>

            }

            {notify && showNotify &&

                <Row>
                  <Col xs>

<FormattedMessage id="ui-users.accounts.infoPatron" />

                  </Col>
                </Row>
                <Row>
                  <Col xs={12} sm={10} md={7} lg={5}>
                    <Field
                      name="patronInfo"
                      component={TextArea}
                    />
                  </Col>
                </Row>

            }
          </form>
        </Pane>
      </Paneset>
    );
  }
}

export default stripesFinalForm({
  initialValuesEqual: (a, b) => isEqual(a, b),
  navigationCheck: true,
  subscription: { values: true },
  mutators: { setFieldData },
  validate: showValidationErrors,
})(ChargeForm);
<commit_msg>UIU-1980: Clean up<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
import { Field } from 'react-final-form';
import setFieldData from 'final-form-set-field-data';
import {
  isEqual,
  toNumber,
} from 'lodash';

import stripesFinalForm from '@folio/stripes/final-form';
import {
  Paneset,
  Pane,
  PaneMenu,
  TextArea,
  Button,
  Row,
  Col,
  Checkbox,
} from '@folio/stripes/components';

import UserInfo from './UserInfo';
import FeeFineInfo from './FeeFineInfo';
import ItemInfo from './ItemInfo';

function showValidationErrors({ feeFineId, ownerId, amount }) {
  const errors = {};
  if (!feeFineId) {
    errors.feeFineId = <FormattedMessage id="ui-users.feefines.modal.error" />;
  }
  if (!ownerId) {
    errors.ownerId = <FormattedMessage id="ui-users.feefines.modal.error" />;
  }
  if (toNumber(amount) <= 0) {
    errors.amount = <FormattedMessage id="ui-users.accounts.error.message" />;
  }
  if (!amount) {
    errors.amount = <FormattedMessage id="ui-users.errors.missingRequiredField" />;
  }
  if (Number.isNaN(toNumber(amount)) && amount) {
    errors.amount = <FormattedMessage id="ui-users.charge.errors.amount" />;
  }

  return errors;
}

class ChargeForm extends React.Component {
  static propTypes = {
    user: PropTypes.object,
    item: PropTypes.object,
    stripes: PropTypes.object,
    ownerId: PropTypes.string,
    owners: PropTypes.arrayOf(PropTypes.object),
    ownerList: PropTypes.arrayOf(PropTypes.object),
    feefines: PropTypes.arrayOf(PropTypes.object),
    form: PropTypes.object.isRequired,
    onClickCancel: PropTypes.func,
    onChangeOwner: PropTypes.func.isRequired,
    onChangeFeeFine: PropTypes.func.isRequired,
    handleSubmit: PropTypes.func.isRequired,
    onClickSelectItem: PropTypes.func.isRequired,
    onFindShared: PropTypes.func.isRequired,
    pristine: PropTypes.bool,
    submitting: PropTypes.bool,
    invalid: PropTypes.bool,
    selectedLoan: PropTypes.object,
    isPending: PropTypes.object,
    onSubmit: PropTypes.func,
    servicePointsIds: PropTypes.arrayOf(PropTypes.string),
    defaultServicePointId: PropTypes.string,
    location: PropTypes.object,
    history: PropTypes.object,
    initialValues: PropTypes.object,
    match: PropTypes.object,
    feeFineTypeOptions: PropTypes.arrayOf(PropTypes.object).isRequired,
  }

  constructor(props) {
    super(props);

    this.onChangeFeeFine = this.onChangeFeeFine.bind(this);
    this.onChangeOwner = this.onChangeOwner.bind(this);
    this.query = 0;
    this.feeFineId = null;
  }

  componentDidUpdate(prevProps) {
    const {
      owners,
      onFindShared,
    } = this.props;
    const { owners: prevOwners } = prevProps;

    if (prevOwners !== owners) {
      const shared = (owners.find(o => o.owner === 'Shared') || {}).id;
      onFindShared(shared);
    }
  }

  async onChangeFeeFine(e) {
    const {
      feefines,
      form: { change },
    } = this.props;

    if (e?.target?.value) {
      const feeFineId = e.target.value;
      await this.props.onChangeFeeFine(e);
      const feefine = feefines.find(f => f.id === feeFineId) || {};
      change('feeFineId', feefine.id);
      this.amount = feefine.defaultAmount || 0;
      this.amount = parseFloat(this.amount).toFixed(2);
      const defaultAmount = parseFloat(feefine.defaultAmount || 0).toFixed(2);
      change('amount', defaultAmount);
    }
  }

  onChangeOwner(e) {
    const { form: { change, reset } } = this.props;
    reset();
    const ownerId = e.target.value;

    this.props.onChangeOwner(e);
    change('ownerId', ownerId);
  }

  goToAccounts = () => {
    const {
      history,
      match: {
        params: { id },
      },
    } = this.props;

    history.push(`/users/${id}/accounts/open`);
  }

  render() {
    const {
      user,
      selectedLoan: selectedLoanProp,
      onSubmit,
      handleSubmit,
      initialValues,
      feeFineTypeOptions,
      form,
      form : {
        getState,
        change,
      },
      submitting,
      pristine,
      isPending,
      stripes,
    } = this.props;
    const {
      valid,
      values: {
        feeFineId,
        ownerId,
        notify,
      }
    } = getState();

    const selectedLoan = selectedLoanProp || {};
    const editable = !(selectedLoan.id);
    const itemLoan = {
      id: selectedLoan.itemId,
      instance: (selectedLoan.item || {}).title,
      barcode: (selectedLoan.item || {}).barcode,
      itemStatus: ((selectedLoan.item || {}).status || {}).name,
      callNumber: (selectedLoan.item || {}).callNumber,
      location: selectedLoan?.item?.effectiveLocation?.name,
      type: ((selectedLoan.item || {}).materialType || {}).name
    };
    const item = (editable) ? this.props.item : itemLoan;
    const feefineList = [];
    const ownerOptions = [];

    this.props.owners.forEach((own = {}) => {
      if (own.owner !== 'Shared') ownerOptions.push({ label: own.owner, value: own.id });
    });

    feeFineTypeOptions.forEach((feefineItem) => {
      const fee = {};
      fee.label = feefineItem.feeFineType;
      fee.value = feefineItem.id;
      feefineList.push(fee);
    });

    let showNotify = false;
    const feefine = this.props.feefines.find(f => f.id === feeFineId) || {};
    const owner = this.props.owners.find(o => o.id === ownerId) || {};
    if (feefine?.chargeNoticeId || owner?.defaultChargeNoticeId) {
      showNotify = true;
    }

    const lastMenu = (
      <PaneMenu>
        <Button
          id="cancelCharge"
          onClick={this.goToAccounts}
          marginBottom0
        >
          <FormattedMessage id="ui-users.feefines.modal.cancel" />
        </Button>
        <Button
          id="chargeAndPay"
          disabled
          // disabled={pristine || submitting || !valid}
          onClick={() => {
            change('pay', true);
            handleSubmit(data => onSubmit(data));
          }}
          marginBottom0
        >
          <FormattedMessage id="ui-users.charge.Pay" />
        </Button>
        <Button
          id="chargeOnly"
          disabled={pristine || submitting || !valid}
          onClick={() => {
            change('pay', false);
            handleSubmit(data => onSubmit(data));
          }}
          marginBottom0
        >
          <FormattedMessage id="ui-users.charge.onlyCharge" />
        </Button>
      </PaneMenu>);

    return (
      <Paneset data-test-charge-form>
        <Pane
          defaultWidth="100%"
          dismissible
          onClose={this.goToAccounts}
          paneTitle={(
            <FormattedMessage id="ui-users.charge.title" />
          )}
          lastMenu={lastMenu}
        >
          <UserInfo user={user} />

          <form
            onSubmit={handleSubmit}
            id="feeFineChargeForm"
          >
            <FeeFineInfo
              form={form}
              stripes={stripes}
              initialValues={initialValues}
              ownerOptions={ownerOptions}
              isPending={isPending}
              onChangeOwner={this.onChangeOwner}
              onChangeFeeFine={this.onChangeFeeFine}
              feefineList={feefineList}
            />

            <ItemInfo {...this.props} item={item} onClickSelectItem={this.props.onClickSelectItem} editable={editable} />

<FormattedMessage id="ui-users.charge.comment" />

            <Row>
              <Col xs={12} sm={10} md={7} lg={5}>
                <Field
                  id="comments"
                  name="comments"
                  component={TextArea}
                  fullWidth
                />
              </Col>
            </Row>
            {showNotify &&

                <Row>
                  <Col xs>
                    <Field
                      name="notify"
                      component={Checkbox}
                      type="checkbox"
                      inline
                      label={<FormattedMessage id="ui-users.accounts.notifyPatron" />}
                    />
                  </Col>
                </Row>

            }

            {notify && showNotify &&

                <Row>
                  <Col xs>

<FormattedMessage id="ui-users.accounts.infoPatron" />

                  </Col>
                </Row>
                <Row>
                  <Col xs={12} sm={10} md={7} lg={5}>
                    <Field
                      name="patronInfo"
                      component={TextArea}
                    />
                  </Col>
                </Row>

            }
          </form>
        </Pane>
      </Paneset>
    );
  }
}

export default stripesFinalForm({
  initialValuesEqual: (a, b) => isEqual(a, b),
  navigationCheck: true,
  subscription: { values: true },
  mutators: { setFieldData },
  validate: showValidationErrors,
})(ChargeForm);
<|endoftext|>


<commit_before>(function(){
    var app = angular.module('coala', ['ngSanitize','btford.markdown', 'ngRoute']);

    app.factory('Languages', function ($location) {
        langs = [{
            'name' : 'English',
            'code' : 'en'
        },
        {
            'name' : 'Bahasa',
            'code' : 'id'
        },
        {
            'name' : 'हिन्दी',
            'code' : 'hi'
        },
            'name' : 'Romanian',
            'code' : 'ro'
        }];
        selected_language = JSON.parse(window.localStorage.getItem('lang')) || langs[0];
        return {
            setData: function (val) {
                angular.forEach(langs, function(v, k){
                    if (v.code == val){
                        window.localStorage.setItem('lang', JSON.stringify(v));
                        selected_language = v;
                    }
                });
            },
            getData: function () {
                return selected_language['code'];

            },
            getAllLanguages: function () {
                return langs;
            },
            getLanguageObject: function () {
                return selected_language;
            }
        }
    });

    app.config(['$routeProvider',
        function($routeProvider) {
            $routeProvider.
            when('/projects', {
                template: '<projects></projects>',
                reloadOnSearch: false
            }).
            when('/mentors', {
                template: '<mentors></mentors>'
            }).
            when('/faq', {
                template: '<faq></faq>'
            }).
            otherwise({
                redirectTo: '/projects'
            });
    }]);

    app.controller('LanguageController', function ($scope, Languages) {
        $scope.langs = Languages.getAllLanguages();
        $scope.update = function () {
            Languages.setData($scope.language.code);
        }
        $scope.init_language = Languages.getLanguageObject();
        $scope.getLanguage = function () {
            $scope.init_language = Languages.getLanguageObject();
            $(document).ready(function(){
                $('select').material_select();
            })
            $scope.$evalAsync();
            return $scope.init_language;
        }
    })

    app.controller('TabController', function ($location) {
        this.tab = $location.path()
        this.setTab = function (stab) {
            this.tab = stab
            $location.path(stab);
        }
        this.isSet = function (stab) {
            return $location.path() == stab
        }
    })

    app.directive('projects',  ['$http',  '$timeout', '$location', 'Languages', function ($http, $timeout, $location, Languages) {
        return {
            restrict: 'E',
            templateUrl: '/partials/tabs/projects.html',
            controller: function ($scope, $location, Languages) {
                self = this

                $scope.getDefaultProjectsMetadata = function () {
                    $http.get('data/projects.liquid')
                        .then(function (res) {
                            $scope.projectList = res.data;
                        })
                }

                $scope.lang = Languages.getData();

                $scope.getDefaultProjectsMetadata();

                $scope.$watch( function () {
                    return Languages.getData();
                }, function () {
                    $scope.setLanguage(Languages.getData());
                }, true);

                $scope.setLanguage = function (val) {
                    $scope.lang = val;
                    $scope.updateProjects();
                }

                $scope.updateProjects = function () {
                    if ($scope.lang != 'en') {
                        $http.get('data/locale/'+$scope.lang+'/projects.json')
                            .then(function (res) {
                                $scope.projectList.map(function (project) {
                                    if (res.data[project.markdown]) {
                                        Object.keys(project).map(function (key) {
                                            if (res.data[project.markdown][key]) {
                                                project[key] = res.data[project.markdown][key]
                                            }
                                        });
                                    }
                                });

                                $scope.projectRequest();
                            });
                    } else {
                        $scope.getDefaultProjectsMetadata();
                        $scope.projectRequest();
                    }
                }

                function generateMarkdown() {

                    function setFromDefault() {
                        $http.get($scope.currentProject.content_url)
                            .then(function (res) {
                                $scope.currentProject.content = res.data
                            }, function() {
                                $scope.currentProject.content = 'No content'
                            });
                    }

                    if ($scope.lang != 'en') {
                        $http.get('data/locale/' + $scope.lang + '/projects/' + $scope.currentProject.markdown).then(function (res) {
                            $scope.currentProject.content = res.data
                        }, function () {
                            setFromDefault()
                        });
                    } else {
                        setFromDefault()
                    }
                }

                self.showProject = function (project) {

                    $scope.currentProject = project

                    $(document).ready(function () {
                        $('.modal').modal('open');
                    });

                    mval = encodeURIComponent(project["name"].split(' ').join('_').toLowerCase());
                    $location.url('?project=' + mval + ( $scope.lang ? '&lang=' + $scope.lang : '' ))
                    $scope.$evalAsync();

                    generateMarkdown()
                }

                self.showProjectOnArrowClick = function (project) {

                    $scope.currentProject = project
                    mval = encodeURIComponent(project["name"].split(' ').join('_').toLowerCase());
                    $location.url('?project=' + mval + ( $scope.lang ? '&lang=' + $scope.lang : '' ))
                                        $scope.$evalAsync();
                    generateMarkdown()
                }

                $scope.search = function (arg) {
                    $scope.searchText = arg
                }

                $scope.redirect = function (arg) {
                    window.open(arg, '_blank');
                }

                $scope.updateLink = function () {
                    $scope.currentProject = null;
                    $location.url($location.path());
                }

                $scope.encode_URI = function (project_name) {
                    return encodeURIComponent(project_name.split(' ').join('_').toLowerCase());
                }

                $scope.arrowPressed = function (e) {
                    if(e.keyCode == 37){
                        keyPressed = "left"
                                    $scope.moveToNext(keyPressed);
                    }
                    else if(e.keyCode == 39){
                        keyPressed = "right"
                                    $scope.moveToNext(keyPressed);
                    }

                }

                $scope.moveToNext = function (keyPressed) {
                    if($scope.currentProject){

                        total_projects = $scope.projectList.length
                        angular.forEach($scope.projectList, function(value, key){
                            if($scope.currentProject.name == value["name"]){
                                current_project_index = key
                            }
                        });

                        if(keyPressed == "left"){
                            if(current_project_index == 0){
                                self.showProjectOnArrowClick($scope.projectList[total_projects-1])
                            }else{
                                self.showProjectOnArrowClick($scope.projectList[--current_project_index])
                            }
                        }
                        if(keyPressed == "right"){
                            if(current_project_index == total_projects-1){
                                self.showProjectOnArrowClick($scope.projectList[0])
                            }else{
                                self.showProjectOnArrowClick($scope.projectList[++current_project_index])
                            }
                        }
                    }
                }

                $scope.projectRequest = function () {
                    $scope.projects_url_dict = {}
                    $scope.projects_url_list = Object.keys($scope.projects_url_dict);
                    angular.forEach($scope.projectList, function(value, key){
                        value["url"] = encodeURIComponent(value["name"].split(' ').join('_').toLowerCase());
                        $scope.projects_url_dict[value["url"]] = key
                    });

                    var project_requested = encodeURIComponent($location.search().project);
                    if(project_requested){
                        if(Object.keys($scope.projects_url_dict).indexOf(project_requested) > -1){
                            self.showProject($scope.projectList[$scope.projects_url_dict[project_requested]])
                        }
                    }
                }

                var search_requested = $location.search().q;
                if(search_requested){
                    $scope.searchText = search_requested
                }

            },
            controllerAs: 'lc'
        }
    }]);

    app.directive('faq',[ '$http', '$templateCache', function ($http, $templateCache, Languages) {
        return {
            restrict: 'E',
            templateUrl: '/partials/tabs/faq.html',
            controller: function ($scope, Languages) {
                $scope.lang = Languages.getData();

                $scope.getDefaultFAQMetadata = function () {
                    $http.get('data/faq.liquid')
                        .then(function (res) {
                            $scope.faqs = res.data;
                            $scope.generateMarkdown();
                        })
                }

                $scope.lang = Languages.getData();

                $scope.getDefaultFAQMetadata();

                $scope.$watch( function () {
                    return Languages.getData();
                }, function () {
                    $scope.setLanguage(Languages.getData());
                }, true);

                $scope.setLanguage = function (val) {
                    $scope.lang = val;
                    $scope.updateFAQ();
                }

                $scope.updateFAQ = function () {
                    if ($scope.lang != 'en') {

                        $http.get('data/locale/'+$scope.lang+'/faq.json')
                            .then(function (res) {
                                $scope.faqs.map(function (faq) {
                                    if (res.data[faq.markdown]) {
                                        Object.keys(faq).map(function (key) {
                                            if (res.data[faq.markdown]) {
                                                faq['question'] = res.data[faq.markdown]

                                            }
                                        });
                                    }
                                });
                                $scope.generateMarkdown();
                            });
                    } else {
                        $scope.getDefaultFAQMetadata();
                    }
                }

                $scope.generateMarkdown = function() {

                    if ($scope.lang != 'en') {
                        $scope.faqs.forEach(function (faq, key) {
                            $http.get('data/locale/' + $scope.lang + '/faq/' + faq.markdown)
                                .then(function (res) {
                                    $scope.faqs[key].answer = res.data
                                }, function (error) {
                                    $http.get($scope.faqs[key].url)
                                        .then(function (res) {
                                            $scope.faqs[key].answer = res.data;
                                        })
                                });
                        })
                    } else {
                        $scope.faqs.forEach(function (f, k) {
                            $http.get($scope.faqs[k].url)
                                .then(function (res) {
                                    $scope.faqs[k].answer = res.data
                                });
                        })
                    }
                }

            },
            controllerAs: 'toc'
        }
    }]);

    app.filter('format_issue', function () {
        return function (value) {
            if (!value) return '';
            res = value.split('/')
            res = res[3] + '/' + res[4] + '#' + res[6]
            return res;
        };
    });

    app.directive('mentors', ['$http', function ($http) {
        return {
            restrict: 'E',
            templateUrl: '/partials/tabs/mentors.html',
            controller: function ($scope, $rootScope) {
                self = this
                self.mentorsList = {}
                self.adminsList = {}

                $http.get('data/projects.liquid')
                    .then(function (res) {
                        $scope.projects = res.data
                        angular.forEach($scope.projects, function(value, key){
                            angular.forEach(value.mentors, function(value, key){
                                self.mentorsList[value] =  {
                                    "github_handle" : value,
                                    "github_avatar_url": "https://avatars.githubusercontent.com/" +value
                                }
                            });
                        });
                    })

                $http.get('data/admins.json')
                    .then(function (res) {
                        admins = res.data
                        angular.forEach(admins, function(value, key){
                            self.adminsList[value] = {
                                "github_handle" : value,
                                "github_avatar_url": "https://avatars.githubusercontent.com/" +value

                            }
                        });
                    })

            },
            controllerAs: "gic"
        }
    }]);

})();
<commit_msg>app.js: Add missing open braces<commit_after>(function(){
    var app = angular.module('coala', ['ngSanitize','btford.markdown', 'ngRoute']);

    app.factory('Languages', function ($location) {
        langs = [{
            'name' : 'English',
            'code' : 'en'
        },
        {
            'name' : 'Bahasa',
            'code' : 'id'
        },
        {
            'name' : 'हिन्दी',
            'code' : 'hi'
        },
        {
            'name' : 'Romanian',
            'code' : 'ro'
        }];
        selected_language = JSON.parse(window.localStorage.getItem('lang')) || langs[0];
        return {
            setData: function (val) {
                angular.forEach(langs, function(v, k){
                    if (v.code == val){
                        window.localStorage.setItem('lang', JSON.stringify(v));
                        selected_language = v;
                    }
                });
            },
            getData: function () {
                return selected_language['code'];

            },
            getAllLanguages: function () {
                return langs;
            },
            getLanguageObject: function () {
                return selected_language;
            }
        }
    });

    app.config(['$routeProvider',
        function($routeProvider) {
            $routeProvider.
            when('/projects', {
                template: '<projects></projects>',
                reloadOnSearch: false
            }).
            when('/mentors', {
                template: '<mentors></mentors>'
            }).
            when('/faq', {
                template: '<faq></faq>'
            }).
            otherwise({
                redirectTo: '/projects'
            });
    }]);

    app.controller('LanguageController', function ($scope, Languages) {
        $scope.langs = Languages.getAllLanguages();
        $scope.update = function () {
            Languages.setData($scope.language.code);
        }
        $scope.init_language = Languages.getLanguageObject();
        $scope.getLanguage = function () {
            $scope.init_language = Languages.getLanguageObject();
            $(document).ready(function(){
                $('select').material_select();
            })
            $scope.$evalAsync();
            return $scope.init_language;
        }
    })

    app.controller('TabController', function ($location) {
        this.tab = $location.path()
        this.setTab = function (stab) {
            this.tab = stab
            $location.path(stab);
        }
        this.isSet = function (stab) {
            return $location.path() == stab
        }
    })

    app.directive('projects',  ['$http',  '$timeout', '$location', 'Languages', function ($http, $timeout, $location, Languages) {
        return {
            restrict: 'E',
            templateUrl: '/partials/tabs/projects.html',
            controller: function ($scope, $location, Languages) {
                self = this

                $scope.getDefaultProjectsMetadata = function () {
                    $http.get('data/projects.liquid')
                        .then(function (res) {
                            $scope.projectList = res.data;
                        })
                }

                $scope.lang = Languages.getData();

                $scope.getDefaultProjectsMetadata();

                $scope.$watch( function () {
                    return Languages.getData();
                }, function () {
                    $scope.setLanguage(Languages.getData());
                }, true);

                $scope.setLanguage = function (val) {
                    $scope.lang = val;
                    $scope.updateProjects();
                }

                $scope.updateProjects = function () {
                    if ($scope.lang != 'en') {
                        $http.get('data/locale/'+$scope.lang+'/projects.json')
                            .then(function (res) {
                                $scope.projectList.map(function (project) {
                                    if (res.data[project.markdown]) {
                                        Object.keys(project).map(function (key) {
                                            if (res.data[project.markdown][key]) {
                                                project[key] = res.data[project.markdown][key]
                                            }
                                        });
                                    }
                                });

                                $scope.projectRequest();
                            });
                    } else {
                        $scope.getDefaultProjectsMetadata();
                        $scope.projectRequest();
                    }
                }

                function generateMarkdown() {

                    function setFromDefault() {
                        $http.get($scope.currentProject.content_url)
                            .then(function (res) {
                                $scope.currentProject.content = res.data
                            }, function() {
                                $scope.currentProject.content = 'No content'
                            });
                    }

                    if ($scope.lang != 'en') {
                        $http.get('data/locale/' + $scope.lang + '/projects/' + $scope.currentProject.markdown).then(function (res) {
                            $scope.currentProject.content = res.data
                        }, function () {
                            setFromDefault()
                        });
                    } else {
                        setFromDefault()
                    }
                }

                self.showProject = function (project) {

                    $scope.currentProject = project

                    $(document).ready(function () {
                        $('.modal').modal('open');
                    });

                    mval = encodeURIComponent(project["name"].split(' ').join('_').toLowerCase());
                    $location.url('?project=' + mval + ( $scope.lang ? '&lang=' + $scope.lang : '' ))
                    $scope.$evalAsync();

                    generateMarkdown()
                }

                self.showProjectOnArrowClick = function (project) {

                    $scope.currentProject = project
                    mval = encodeURIComponent(project["name"].split(' ').join('_').toLowerCase());
                    $location.url('?project=' + mval + ( $scope.lang ? '&lang=' + $scope.lang : '' ))
                                        $scope.$evalAsync();
                    generateMarkdown()
                }

                $scope.search = function (arg) {
                    $scope.searchText = arg
                }

                $scope.redirect = function (arg) {
                    window.open(arg, '_blank');
                }

                $scope.updateLink = function () {
                    $scope.currentProject = null;
                    $location.url($location.path());
                }

                $scope.encode_URI = function (project_name) {
                    return encodeURIComponent(project_name.split(' ').join('_').toLowerCase());
                }

                $scope.arrowPressed = function (e) {
                    if(e.keyCode == 37){
                        keyPressed = "left"
                                    $scope.moveToNext(keyPressed);
                    }
                    else if(e.keyCode == 39){
                        keyPressed = "right"
                                    $scope.moveToNext(keyPressed);
                    }

                }

                $scope.moveToNext = function (keyPressed) {
                    if($scope.currentProject){

                        total_projects = $scope.projectList.length
                        angular.forEach($scope.projectList, function(value, key){
                            if($scope.currentProject.name == value["name"]){
                                current_project_index = key
                            }
                        });

                        if(keyPressed == "left"){
                            if(current_project_index == 0){
                                self.showProjectOnArrowClick($scope.projectList[total_projects-1])
                            }else{
                                self.showProjectOnArrowClick($scope.projectList[--current_project_index])
                            }
                        }
                        if(keyPressed == "right"){
                            if(current_project_index == total_projects-1){
                                self.showProjectOnArrowClick($scope.projectList[0])
                            }else{
                                self.showProjectOnArrowClick($scope.projectList[++current_project_index])
                            }
                        }
                    }
                }

                $scope.projectRequest = function () {
                    $scope.projects_url_dict = {}
                    $scope.projects_url_list = Object.keys($scope.projects_url_dict);
                    angular.forEach($scope.projectList, function(value, key){
                        value["url"] = encodeURIComponent(value["name"].split(' ').join('_').toLowerCase());
                        $scope.projects_url_dict[value["url"]] = key
                    });

                    var project_requested = encodeURIComponent($location.search().project);
                    if(project_requested){
                        if(Object.keys($scope.projects_url_dict).indexOf(project_requested) > -1){
                            self.showProject($scope.projectList[$scope.projects_url_dict[project_requested]])
                        }
                    }
                }

                var search_requested = $location.search().q;
                if(search_requested){
                    $scope.searchText = search_requested
                }

            },
            controllerAs: 'lc'
        }
    }]);

    app.directive('faq',[ '$http', '$templateCache', function ($http, $templateCache, Languages) {
        return {
            restrict: 'E',
            templateUrl: '/partials/tabs/faq.html',
            controller: function ($scope, Languages) {
                $scope.lang = Languages.getData();

                $scope.getDefaultFAQMetadata = function () {
                    $http.get('data/faq.liquid')
                        .then(function (res) {
                            $scope.faqs = res.data;
                            $scope.generateMarkdown();
                        })
                }

                $scope.lang = Languages.getData();

                $scope.getDefaultFAQMetadata();

                $scope.$watch( function () {
                    return Languages.getData();
                }, function () {
                    $scope.setLanguage(Languages.getData());
                }, true);

                $scope.setLanguage = function (val) {
                    $scope.lang = val;
                    $scope.updateFAQ();
                }

                $scope.updateFAQ = function () {
                    if ($scope.lang != 'en') {

                        $http.get('data/locale/'+$scope.lang+'/faq.json')
                            .then(function (res) {
                                $scope.faqs.map(function (faq) {
                                    if (res.data[faq.markdown]) {
                                        Object.keys(faq).map(function (key) {
                                            if (res.data[faq.markdown]) {
                                                faq['question'] = res.data[faq.markdown]

                                            }
                                        });
                                    }
                                });
                                $scope.generateMarkdown();
                            });
                    } else {
                        $scope.getDefaultFAQMetadata();
                    }
                }

                $scope.generateMarkdown = function() {

                    if ($scope.lang != 'en') {
                        $scope.faqs.forEach(function (faq, key) {
                            $http.get('data/locale/' + $scope.lang + '/faq/' + faq.markdown)
                                .then(function (res) {
                                    $scope.faqs[key].answer = res.data
                                }, function (error) {
                                    $http.get($scope.faqs[key].url)
                                        .then(function (res) {
                                            $scope.faqs[key].answer = res.data;
                                        })
                                });
                        })
                    } else {
                        $scope.faqs.forEach(function (f, k) {
                            $http.get($scope.faqs[k].url)
                                .then(function (res) {
                                    $scope.faqs[k].answer = res.data
                                });
                        })
                    }
                }

            },
            controllerAs: 'toc'
        }
    }]);

    app.filter('format_issue', function () {
        return function (value) {
            if (!value) return '';
            res = value.split('/')
            res = res[3] + '/' + res[4] + '#' + res[6]
            return res;
        };
    });

    app.directive('mentors', ['$http', function ($http) {
        return {
            restrict: 'E',
            templateUrl: '/partials/tabs/mentors.html',
            controller: function ($scope, $rootScope) {
                self = this
                self.mentorsList = {}
                self.adminsList = {}

                $http.get('data/projects.liquid')
                    .then(function (res) {
                        $scope.projects = res.data
                        angular.forEach($scope.projects, function(value, key){
                            angular.forEach(value.mentors, function(value, key){
                                self.mentorsList[value] =  {
                                    "github_handle" : value,
                                    "github_avatar_url": "https://avatars.githubusercontent.com/" +value
                                }
                            });
                        });
                    })

                $http.get('data/admins.json')
                    .then(function (res) {
                        admins = res.data
                        angular.forEach(admins, function(value, key){
                            self.adminsList[value] = {
                                "github_handle" : value,
                                "github_avatar_url": "https://avatars.githubusercontent.com/" +value

                            }
                        });
                    })

            },
            controllerAs: "gic"
        }
    }]);

})();
<|endoftext|>


<commit_before>require('./scroll/whenScrolled');

module.exports = require('an').controller(

// todo: refactor this. It's too big, violates srp
['$scope', '$http', function AppController($scope, $http) {
  $scope.initialized = false;
  var graphController;
  var page = require('./scroll/page');

  var nodeIdxToNodeId = {};
  $http.get('/data/npmgraph.json').then(function (res) {
    res.data.forEach(function (node, idx) {
      nodeIdxToNodeId[idx] = node.id;
    });
    graphController = require('./graphController.js')(res.data);
    graphController.on('mouseEnterNode', onMouseEnter);
    graphController.on('mouseLeaveNode', onMouseLeave);
    $scope.initialized = true;
  });

  var testData;
  $scope.toggleTests = function () {
    if (!testData) {
      $http.get('/data/withtests.json').then(function (res) {
        testData = transformToTestData(res.data);
        toggleTests($scope.showTests);
      });
    } else {
      toggleTests($scope.showTests);
    }
  };

  function toggleTests(show) {
    var allMatches = graphController.highlightRules(function (node) {
      if (show && testData[node.id]) {
        return {
          size: 10,
          color: 0xFF4500ff
        };
      }
    });
    showInSearch(allMatches);
  }

  function transformToTestData(data) {
    var nodeIdHasTest = {};
    for (var i = 0; i < data.length; ++i) {
      nodeIdHasTest[nodeIdxToNodeId[data[i]]] = true;
    }

    return nodeIdHasTest;
  }

  $scope.highlightPackages = function () {
    var searchTerm = $scope.search,
        rNameMatch = new RegExp(searchTerm, 'ig'),
        rExactMatch = new RegExp('^' + searchTerm + '$', 'ig');

    var allMatches = graphController.highlightRules(function (node) {
      if (searchTerm && node.id.match(rExactMatch)) {
        return 0xE28100ff;
      } else if (searchTerm && node.id.match(rNameMatch)) {
        return 0xD61D73ff;
      }
    });

    showInSearch(allMatches);
  };

  function showInSearch(allMatches) {
    allMatches = allMatches.map(function (match) { return match.id; });
    $scope.totalFound = allMatches.length;
    $scope.searchResults = null;
    var pageResults = page(allMatches, function (currentPage) {
      if (!$scope.searchResults) {
        $scope.searchResults = [];
      }
      $scope.searchResults = $scope.searchResults.concat(currentPage);
    });
    $scope.loadMore = pageResults.loadMore;
    $scope.loadMore();
  }

  $scope.loadMore = function() {
    var totalItems = allSearchResults.length;
    if (totalItems === 0) return;

    var from = itemsPerPage * lastPage;
    var to = Math.min((lastPage + 1) * itemsPerPage, totalItems);
    if (to - from <= 0) return;

    if (!$scope.searchResults) {
      $scope.searchResults = [];
    }
    $scope.searchResults = $scope.searchResults.concat(allSearchResults.slice(from, to));
    lastPage += 1;
  };

  var countNodeStats = require('./graph/countNodeStats');
  function onMouseEnter(node) {
    $scope.$apply(function () {
      $scope.name = node.id;
      $scope.author = node.data.a || '';
      $scope.license = node.data.l || '';
      $scope.stats = countNodeStats(node.id, node.links);
    });
  }

  function onMouseLeave(node) {
    $scope.$apply(function () {
      $scope.node = null;
    });
  }
}]
);
<commit_msg>Changed to relative links<commit_after>require('./scroll/whenScrolled');

module.exports = require('an').controller(

// todo: refactor this. It's too big, violates srp
['$scope', '$http', function AppController($scope, $http) {
  $scope.initialized = false;
  var graphController;
  var page = require('./scroll/page');

  var nodeIdxToNodeId = {};
  $http.get('data/npmgraph.json').then(function (res) {
    res.data.forEach(function (node, idx) {
      nodeIdxToNodeId[idx] = node.id;
    });
    graphController = require('./graphController.js')(res.data);
    graphController.on('mouseEnterNode', onMouseEnter);
    graphController.on('mouseLeaveNode', onMouseLeave);
    $scope.initialized = true;
  });

  var testData;
  $scope.toggleTests = function () {
    if (!testData) {
      $http.get('data/withtests.json').then(function (res) {
        testData = transformToTestData(res.data);
        toggleTests($scope.showTests);
      });
    } else {
      toggleTests($scope.showTests);
    }
  };

  function toggleTests(show) {
    var allMatches = graphController.highlightRules(function (node) {
      if (show && testData[node.id]) {
        return {
          size: 10,
          color: 0xFF4500ff
        };
      }
    });
    showInSearch(allMatches);
  }

  function transformToTestData(data) {
    var nodeIdHasTest = {};
    for (var i = 0; i < data.length; ++i) {
      nodeIdHasTest[nodeIdxToNodeId[data[i]]] = true;
    }

    return nodeIdHasTest;
  }

  $scope.highlightPackages = function () {
    var searchTerm = $scope.search,
        rNameMatch = new RegExp(searchTerm, 'ig'),
        rExactMatch = new RegExp('^' + searchTerm + '$', 'ig');

    var allMatches = graphController.highlightRules(function (node) {
      if (searchTerm && node.id.match(rExactMatch)) {
        return 0xE28100ff;
      } else if (searchTerm && node.id.match(rNameMatch)) {
        return 0xD61D73ff;
      }
    });

    showInSearch(allMatches);
  };

  function showInSearch(allMatches) {
    allMatches = allMatches.map(function (match) { return match.id; });
    $scope.totalFound = allMatches.length;
    $scope.searchResults = null;
    var pageResults = page(allMatches, function (currentPage) {
      if (!$scope.searchResults) {
        $scope.searchResults = [];
      }
      $scope.searchResults = $scope.searchResults.concat(currentPage);
    });
    $scope.loadMore = pageResults.loadMore;
    $scope.loadMore();
  }

  $scope.loadMore = function() {
    var totalItems = allSearchResults.length;
    if (totalItems === 0) return;

    var from = itemsPerPage * lastPage;
    var to = Math.min((lastPage + 1) * itemsPerPage, totalItems);
    if (to - from <= 0) return;

    if (!$scope.searchResults) {
      $scope.searchResults = [];
    }
    $scope.searchResults = $scope.searchResults.concat(allSearchResults.slice(from, to));
    lastPage += 1;
  };

  var countNodeStats = require('./graph/countNodeStats');
  function onMouseEnter(node) {
    $scope.$apply(function () {
      $scope.name = node.id;
      $scope.author = node.data.a || '';
      $scope.license = node.data.l || '';
      $scope.stats = countNodeStats(node.id, node.links);
    });
  }

  function onMouseLeave(node) {
    $scope.$apply(function () {
      $scope.node = null;
    });
  }
}]
);
<|endoftext|>


<commit_before>/*
Copyright 2019 The Matrix.org Foundation C.I.C.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

import React from 'react';
import PropTypes from 'prop-types';
import * as HtmlUtils from '../../../HtmlUtils';
import {formatTime} from '../../../DateUtils';
import {MatrixEvent} from 'matrix-js-sdk';
import {pillifyLinks} from '../../../utils/pillify';
import { _t } from '../../../languageHandler';
import sdk from '../../../index';
import MatrixClientPeg from '../../../MatrixClientPeg';
import Modal from '../../../Modal';
import classNames from 'classnames';

export default class EditHistoryMessage extends React.PureComponent {
    static propTypes = {
        // the message event being edited
        mxEvent: PropTypes.instanceOf(MatrixEvent).isRequired,
    };

    constructor(props) {
        super(props);
        const cli = MatrixClientPeg.get();
        const {userId} = cli.credentials;
        const event = this.props.mxEvent;
        const room = cli.getRoom(event.getRoomId());
        if (event.localRedactionEvent()) {
            event.localRedactionEvent().on("status", this._onAssociatedStatusChanged);
        }
        const canRedact = room.currentState.maySendRedactionForEvent(event, userId);
        this.state = {canRedact, sendStatus: event.getAssociatedStatus()};
    }

    _onAssociatedStatusChanged = () => {
        this.setState({sendStatus: this.props.mxEvent.getAssociatedStatus()});
    };

    _onRedactClick = async () => {
        const event = this.props.mxEvent;
        const cli = MatrixClientPeg.get();
        const ConfirmAndWaitRedactDialog = sdk.getComponent("dialogs.ConfirmAndWaitRedactDialog");

        Modal.createTrackedDialog('Confirm Redact Dialog from edit history', '', ConfirmAndWaitRedactDialog, {
            redact: () => cli.redactEvent(event.getRoomId(), event.getId()),
        }, 'mx_Dialog_confirmredact');
    };

    pillifyLinks() {
        // not present for redacted events
        if (this.refs.content) {
            pillifyLinks(this.refs.content.children, this.props.mxEvent);
        }
    }

    componentDidMount() {
        this.pillifyLinks();
    }

    componentWillUnmount() {
        const event = this.props.mxEvent;
        if (event.localRedactionEvent()) {
            event.localRedactionEvent().off("status", this._onAssociatedStatusChanged);
        }
    }

    componentDidUpdate() {
        this.pillifyLinks();
    }

    _renderActionBar() {
        const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
        // hide the button when already redacted
        if (this.props.mxEvent.isRedacted()) {
            return null;
        }
        // disabled remove button when not allowed
        return (

            <AccessibleButton onClick={this._onRedactClick} disabled={!this.state.canRedact}>{_t("Remove")}</AccessibleButton>

);
    }

    render() {
        const {mxEvent} = this.props;
        const originalContent = mxEvent.getOriginalContent();
        const content = originalContent["m.new_content"] || originalContent;
        const contentElements = HtmlUtils.bodyToHtml(content);
        let contentContainer;
        if (mxEvent.isRedacted()) {
            const UnknownBody = sdk.getComponent('messages.UnknownBody');
            contentContainer = (<UnknownBody mxEvent={this.props.mxEvent} />);
        } else if (mxEvent.getContent().msgtype === "m.emote") {
            const name = mxEvent.sender ? mxEvent.sender.name : mxEvent.getSender();
            contentContainer = (
*
                { name }
                 {contentElements}

);
        } else {
            contentContainer = (
{contentElements}
);
        }
        const timestamp = formatTime(new Date(mxEvent.getTs()), this.props.isTwelveHour);
        const isSending = (['sending', 'queued', 'encrypting'].indexOf(this.state.sendStatus) !== -1);
        const classes = classNames({
            "mx_EventTile": true,
            "mx_EventTile_redacted": mxEvent.isRedacted(),
            "mx_EventTile_sending": isSending,
            "mx_EventTile_notSent": this.state.sendStatus === 'not_sent',
        });
        return

                    {timestamp}
                    { contentContainer }
                    { this._renderActionBar() }

;
    }
}
<commit_msg>implement view source for edits<commit_after>/*
Copyright 2019 The Matrix.org Foundation C.I.C.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

import React from 'react';
import PropTypes from 'prop-types';
import * as HtmlUtils from '../../../HtmlUtils';
import {formatTime} from '../../../DateUtils';
import {MatrixEvent} from 'matrix-js-sdk';
import {pillifyLinks} from '../../../utils/pillify';
import { _t } from '../../../languageHandler';
import sdk from '../../../index';
import MatrixClientPeg from '../../../MatrixClientPeg';
import Modal from '../../../Modal';
import classNames from 'classnames';

export default class EditHistoryMessage extends React.PureComponent {
    static propTypes = {
        // the message event being edited
        mxEvent: PropTypes.instanceOf(MatrixEvent).isRequired,
    };

    constructor(props) {
        super(props);
        const cli = MatrixClientPeg.get();
        const {userId} = cli.credentials;
        const event = this.props.mxEvent;
        const room = cli.getRoom(event.getRoomId());
        if (event.localRedactionEvent()) {
            event.localRedactionEvent().on("status", this._onAssociatedStatusChanged);
        }
        const canRedact = room.currentState.maySendRedactionForEvent(event, userId);
        this.state = {canRedact, sendStatus: event.getAssociatedStatus()};
    }

    _onAssociatedStatusChanged = () => {
        this.setState({sendStatus: this.props.mxEvent.getAssociatedStatus()});
    };

    _onRedactClick = async () => {
        const event = this.props.mxEvent;
        const cli = MatrixClientPeg.get();
        const ConfirmAndWaitRedactDialog = sdk.getComponent("dialogs.ConfirmAndWaitRedactDialog");

        Modal.createTrackedDialog('Confirm Redact Dialog from edit history', '', ConfirmAndWaitRedactDialog, {
            redact: () => cli.redactEvent(event.getRoomId(), event.getId()),
        }, 'mx_Dialog_confirmredact');
    };

    _onViewSourceClick = () => {
        const ViewSource = sdk.getComponent('structures.ViewSource');
        Modal.createTrackedDialog('View Event Source', '', ViewSource, {
            roomId: this.props.mxEvent.getRoomId(),
            eventId: this.props.mxEvent.getId(),
            content: this.props.mxEvent.event,
        }, 'mx_Dialog_viewsource');
    };

    pillifyLinks() {
        // not present for redacted events
        if (this.refs.content) {
            pillifyLinks(this.refs.content.children, this.props.mxEvent);
        }
    }

    componentDidMount() {
        this.pillifyLinks();
    }

    componentWillUnmount() {
        const event = this.props.mxEvent;
        if (event.localRedactionEvent()) {
            event.localRedactionEvent().off("status", this._onAssociatedStatusChanged);
        }
    }

    componentDidUpdate() {
        this.pillifyLinks();
    }

    _renderActionBar() {
        const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
        // hide the button when already redacted
        let redactButton;
        if (!this.props.mxEvent.isRedacted()) {
            redactButton = (<AccessibleButton onClick={this._onRedactClick} disabled={!this.state.canRedact}>
                {_t("Remove")}
            </AccessibleButton>);
        }
        const viewSourceButton = (<AccessibleButton onClick={this._onViewSourceClick}>
                {_t("View Source")}
            </AccessibleButton>);
        // disabled remove button when not allowed
        return (

            {redactButton}
            {viewSourceButton}

);
    }

    render() {
        const {mxEvent} = this.props;
        const originalContent = mxEvent.getOriginalContent();
        const content = originalContent["m.new_content"] || originalContent;
        const contentElements = HtmlUtils.bodyToHtml(content);
        let contentContainer;
        if (mxEvent.isRedacted()) {
            const UnknownBody = sdk.getComponent('messages.UnknownBody');
            contentContainer = (<UnknownBody mxEvent={this.props.mxEvent} />);
        } else if (mxEvent.getContent().msgtype === "m.emote") {
            const name = mxEvent.sender ? mxEvent.sender.name : mxEvent.getSender();
            contentContainer = (
*
                { name }
                 {contentElements}

);
        } else {
            contentContainer = (
{contentElements}
);
        }
        const timestamp = formatTime(new Date(mxEvent.getTs()), this.props.isTwelveHour);
        const isSending = (['sending', 'queued', 'encrypting'].indexOf(this.state.sendStatus) !== -1);
        const classes = classNames({
            "mx_EventTile": true,
            "mx_EventTile_redacted": mxEvent.isRedacted(),
            "mx_EventTile_sending": isSending,
            "mx_EventTile_notSent": this.state.sendStatus === 'not_sent',
        });
        return

                    {timestamp}
                    { contentContainer }
                    { this._renderActionBar() }

;
    }
}
<|endoftext|>


<commit_before><commit_msg>interface font size<commit_after><|endoftext|>