<commit_before>"use strict";
const express = require("express");
const cache = require("apicache");
const equals = require("deep-equal");
const fs = require("fs");

const {
  db,
  as,
  CASES_BY_COUNTRY,
  CREATE_CASE,
  CASE_BY_ID,
  INSERT_AUTHOR,
  INSERT_LOCALIZED_TEXT,
  UPDATE_CASE,
  UPDATE_AUTHOR_FIRST,
  UPDATE_AUTHOR_LAST,
  listUsers,
  listCases,
  listMethods,
  listOrganizations,
  refreshSearch,
  ErrorReporter,
} = require("../helpers/db");

const {
  setConditional,
  maybeUpdateUserText,
  parseGetParams,
  validateUrl,
  verifyOrUpdateUrl,
  returnByType,
  fixUpURLs,
  getCollections
} = require("../helpers/things");

const logError = require("../helpers/log-error.js");

const requireAuthenticatedUser = require("../middleware/requireAuthenticatedUser.js");
const CASE_STRUCTURE = JSON.parse(
  fs.readFileSync("api/helpers/data/case-structure.json", "utf8")
);
const sharedFieldOptions = require("../helpers/shared-field-options.js");

/**
 * @api {post} /case/new Create new case
 * @apiGroup Cases
 * @apiVersion 0.1.0
 * @apiName newCase
 *
 * @apiSuccess {Boolean} OK true if call was successful
 * @apiSuccess {String[]} errors List of error strings (when `OK` is false)
 * @apiSuccess {Object} data case data
 *
 * @apiSuccessExample Success-Response:
 *     HTTP/1.1 200 OK
 *     {
 *       "OK": true,
 *       "data": {
 *         "ID": 3,
 *         "Description": 'foo'
 *        }
 *     }
 *
 * @apiError NotAuthenticated The user is not authenticated
 * @apiError NotAuthorized The user doesn't have permission to perform this operation.
 *
 */

async function postCaseNewHttp(req, res) {
  // create new `case` in db
  try {
    cache.clear();
    let title = req.body.title;
    let body = req.body.body || req.body.summary || "";
    let description = req.body.description;
    let original_language = req.body.original_language || "en";
    let links = req.body.links;

    if (!title) {
      return res.status(400).json({
        OK: false,
        errors: ["Cannot create a case without at least a title."],
      });
    }

    const user_id = req.user.id;
    const thing = await db.one(CREATE_CASE, {
      title,
      body,
      description,
      original_language,
    });
    req.params.thingid = thing.thingid;
    await postCaseUpdateHttp(req, res);
  } catch (error) {
    logError(error);
    res.status(400).json({ OK: false, error: error });
  }
}

/**
 * @api {put} /case/:caseId  Submit a new version of a case
 * @apiGroup Cases
 * @apiVersion 0.1.0
 * @apiName editCase
 * @apiParam {Number} caseId Case ID
 *
 * @apiSuccess {Boolean} OK true if call was successful
 * @apiSuccess {String[]} errors List of error strings (when `OK` is false)
 * @apiSuccess {Object} data case data
 *
 * @apiSuccessExample Success-Response:
 *     HTTP/1.1 200 OK
 *     {
 *       "OK": true,
 *       "data": {
 *         "ID": 3,
 *         "Description": 'foo'
 *        }
 *     }
 *
 * @apiError NotAuthenticated The user is not authenticated
 * @apiError NotAuthorized The user doesn't have permission to perform this operation.
 *
 */

function getUpdatedCase(user, params, newCase, oldCase) {
  const updatedCase = Object.assign({}, oldCase);
  const er = new ErrorReporter();
  const cond = (key, fn) => setConditional(updatedCase, newCase, er, fn, key);
  // admin-only
  if (user.isadmin) {
    cond("featured", as.boolean);
    cond("hidden", as.boolean);
    cond("completeness", as.text);
    cond("original_language", as.text);
    cond("post_date", as.date);
    cond("updated_date", as.date);
  }

  // media lists
  ["links", "videos", "audio", "evaluation_links"].map(key =>
    cond(key, as.media)
  );
  // photos and files are slightly different from other media as they have a source url too
  ["photos", "files", "evaluation_reports"].map(key =>
    cond(key, as.sourcedMedia)
  );
  // boolean (would include "published" but we don't really support it)
  ["ongoing", "staff", "volunteers"].map(key => cond(key, as.selectBoolean));
  // yes/no (convert to boolean)
  ["impact_evidence", "formal_evaluation"].map(key => cond(key, as.yesno));
  // integer
  ["number_of_participants"].map(key => cond(key, as.integer));
  // float
  ["latitude", "longitude"].map(key => cond(key, as.float));
  // plain text
  [
    "location_name",
    "address1",
    "address2",
    "city",
    "province",
    "postal_code",
    "country",
    "funder",
  ].map(key => cond(key, as.text));
  // date
  ["start_date", "end_date"].map(key => cond(key, as.date));
  // id
  ["is_component_of", "primary_organizer"].map(key => cond(key, as.id));
  // list of ids
  ["specific_methods_tools_techniques"].map(key => cond(key, as.ids));
  // key
  [
    "scope_of_influence",
    "public_spectrum",
    "legality",
    "facilitators",
    "facilitator_training",
    "facetoface_online_or_both",
    "open_limited",
    "recruitment_method",
    "time_limited",
  ].map(key => cond(key, as.casekeyflat));
  // list of keys
  [
    "general_issues",
    "specific_topics",
    "collections",
    "purposes",
    "approaches",
    "targeted_participants",
    "method_types",
    "participants_interactions",
    "learning_resources",
    "decision_methods",
    "if_voting",
    "insights_outcomes",
    "organizer_types",
    "funder_types",
    "change_types",
    "implementers_of_change",
    "tools_techniques_types",
  ].map(key => cond(key, as.casekeys));
  // TODO save bookmarked on user
  return [updatedCase, er];
}

// Only changes to title, description, and/or body trigger a new author and version

async function postCaseUpdateHttp(req, res) {
  // cache.clear();
  const params = parseGetParams(req, "case");
  const user = req.user;
  const { articleid, type, view, userid, lang, returns } = params;
  const newCase = req.body;
  const links = req.body.links;

  //validate url

  if (links) {
    for (let key in links) {
      let url = links[key].url;
      if (url.length > 0) {
        newCase.links = verifyOrUpdateUrl(newCase.links);
        const isUrlValid = validateUrl(newCase);
        if (!isUrlValid) {
          return res.status(400).json({
            OK: false,
            errors: ["Invalid link url."],
          });
        }
      }
    }
  }

  // if this is a new case, we don't have a post_date yet, so we set it here
  if (!newCase.post_date) {
    newCase.post_date = Date.now();
  }

  // if this is a new case, we don't have a updated_date yet, so we set it here
  if (!newCase.updated_date) {
    newCase.updated_date = Date.now();
  }

  // save any changes to the user-submitted text
  const {
    updatedText,
    author,
    oldArticle: oldCase,
  } = await maybeUpdateUserText(req, res, "case");
  const [updatedCase, er] = getUpdatedCase(user, params, newCase, oldCase);

  //get current date when user.isAdmin is false;
  updatedCase.updated_date = !user.isadmin ? "now" : updatedCase.updated_date;

  if (!er.hasErrors()) {
    if (updatedText) {
      await db.tx("update-case", async t => {
        await t.none(INSERT_AUTHOR, author);
        await t.none(INSERT_LOCALIZED_TEXT, updatedText);
        await t.none(UPDATE_CASE, updatedCase);
      });
      //if this is a new case, set creator id to userid and isAdmin
      if (user.isadmin) {
        const creator = {
          user_id: newCase.creator ? newCase.creator : params.userid,
          thingid: params.articleid,
        };
        const updatedBy = {
          user_id: newCase.last_updated_by
            ? newCase.last_updated_by
            : params.userid,
          thingid: params.articleid,
          updated_date: newCase.updated_date || "now",
        };
        await db.tx("update-case", async t => {
          await t.none(UPDATE_AUTHOR_FIRST, creator);
          await t.none(UPDATE_AUTHOR_LAST, updatedBy);
        });
      }
    } else {
      await db.tx("update-case", async t => {
        await t.none(INSERT_AUTHOR, author);
        await t.none(UPDATE_CASE, updatedCase);
      });
    }
    // the client expects this request to respond with json
    // save successful response
    const freshArticle = await getCase(params, res);
    res.status(200).json({
      OK: true,
      article: freshArticle,
    });
    refreshSearch();
  } else {
    logError(`400 with errors: ${er.errors.join(", ")}`);
    res.status(400).json({
      OK: false,
      errors: er.errors,
    });
  }
}

/**
 * @api {get} /case/:thingid Get the last version of a case
 * @apiGroup Cases
 * @apiVersion 0.1.0
 * @apiName returnCaseById
 * @apiParam {Number} thingid Case ID
 *
 * @apiSuccess {Boolean} OK true if call was successful
 * @apiSuccess {String[]} errors List of error strings (when `OK` is false)
 * @apiSuccess {Object} data case data
 *
 * @apiSuccessExample Success-Response:
 *     HTTP/1.1 200 OK
 *     {
 *       "OK": true,
 *       "data": {
 *         "ID": 3,
 *         "Description": 'foo'
 *        }
 *     }
 *
 * @apiError NotAuthenticated The user is not authenticated
 * @apiError NotAuthorized The user doesn't have permission to perform this operation.
 *
 */

async function getCase(params, res) {
  try {
    if (Number.isNaN(params.articleid)) {
      return null;
    }
    const articleRow = await db.one(CASE_BY_ID, params);
    const article = articleRow.results;
    fixUpURLs(article);
    return article;
  } catch (error) {
    // only log actual excaptional results, not just data not found
    if (error.message !== "No data returned from the query.") {
      logError(error);
    }
    // if no entry is found, render the 404 page
    return null;
  }
}

async function getCaseHttp(req, res) {
  /* This is the entry point for getting an article */
  const params = parseGetParams(req, "case");
  const article = await getCase(params, res);
  if (!article) {
    res.status(404).render("404");
    return null;
  }
  const staticText = await getEditStaticText(params);
  returnByType(res, params, article, staticText, req.user);
}

async function getEditStaticText(params) {
  const lang = params.lang;
  let staticText = Object.assign({}, sharedFieldOptions);
  staticText.collections = await getCollections(params.lang);
  staticText.authors = listUsers();
  staticText.cases = listCases(lang).filter(article => !article.hidden);
  staticText.methods = listMethods(lang).filter(article => !article.hidden);
  staticText.organizations = listOrganizations(lang).filter(
    article => !article.hidden
  );
  return staticText;
}

async function getCaseEditHttp(req, res) {
  let startTime = new Date();
  const params = parseGetParams(req, "case");
  params.view = "edit";
  const article = await getCase(params, res);
  if (!article) {
    res.status(404).render("404");
    return null;
  }
  const staticText = await getEditStaticText(params);
  returnByType(res, params, article, staticText, req.user);
}

async function getCaseNewHttp(req, res) {
  const params = parseGetParams(req, "case");
  params.view = "edit";
  const article = CASE_STRUCTURE;
  const staticText = await getEditStaticText(params);
  returnByType(res, params, article, staticText, req.user);
}

const router = express.Router(); // eslint-disable-line new-cap
router.get("/:thingid/edit", requireAuthenticatedUser(), getCaseEditHttp);
router.get("/new", requireAuthenticatedUser(), getCaseNewHttp);
router.post("/new", requireAuthenticatedUser(), postCaseNewHttp);
router.get("/:thingid", getCaseHttp);
router.post("/:thingid", requireAuthenticatedUser(), postCaseUpdateHttp);

module.exports = {
  case_: router,
  getCaseEditHttp,
  getCaseNewHttp,
  postCaseNewHttp,
  getCaseHttp,
  postCaseUpdateHttp,
};
<commit_msg>refactor getCollections method language parameter in case controller<commit_after>"use strict";
const express = require("express");
const cache = require("apicache");
const equals = require("deep-equal");
const fs = require("fs");

const {
  db,
  as,
  CASES_BY_COUNTRY,
  CREATE_CASE,
  CASE_BY_ID,
  INSERT_AUTHOR,
  INSERT_LOCALIZED_TEXT,
  UPDATE_CASE,
  UPDATE_AUTHOR_FIRST,
  UPDATE_AUTHOR_LAST,
  listUsers,
  listCases,
  listMethods,
  listOrganizations,
  refreshSearch,
  ErrorReporter,
} = require("../helpers/db");

const {
  setConditional,
  maybeUpdateUserText,
  parseGetParams,
  validateUrl,
  verifyOrUpdateUrl,
  returnByType,
  fixUpURLs,
  getCollections
} = require("../helpers/things");

const logError = require("../helpers/log-error.js");

const requireAuthenticatedUser = require("../middleware/requireAuthenticatedUser.js");
const CASE_STRUCTURE = JSON.parse(
  fs.readFileSync("api/helpers/data/case-structure.json", "utf8")
);
const sharedFieldOptions = require("../helpers/shared-field-options.js");

/**
 * @api {post} /case/new Create new case
 * @apiGroup Cases
 * @apiVersion 0.1.0
 * @apiName newCase
 *
 * @apiSuccess {Boolean} OK true if call was successful
 * @apiSuccess {String[]} errors List of error strings (when `OK` is false)
 * @apiSuccess {Object} data case data
 *
 * @apiSuccessExample Success-Response:
 *     HTTP/1.1 200 OK
 *     {
 *       "OK": true,
 *       "data": {
 *         "ID": 3,
 *         "Description": 'foo'
 *        }
 *     }
 *
 * @apiError NotAuthenticated The user is not authenticated
 * @apiError NotAuthorized The user doesn't have permission to perform this operation.
 *
 */

async function postCaseNewHttp(req, res) {
  // create new `case` in db
  try {
    cache.clear();
    let title = req.body.title;
    let body = req.body.body || req.body.summary || "";
    let description = req.body.description;
    let original_language = req.body.original_language || "en";
    let links = req.body.links;

    if (!title) {
      return res.status(400).json({
        OK: false,
        errors: ["Cannot create a case without at least a title."],
      });
    }

    const user_id = req.user.id;
    const thing = await db.one(CREATE_CASE, {
      title,
      body,
      description,
      original_language,
    });
    req.params.thingid = thing.thingid;
    await postCaseUpdateHttp(req, res);
  } catch (error) {
    logError(error);
    res.status(400).json({ OK: false, error: error });
  }
}

/**
 * @api {put} /case/:caseId  Submit a new version of a case
 * @apiGroup Cases
 * @apiVersion 0.1.0
 * @apiName editCase
 * @apiParam {Number} caseId Case ID
 *
 * @apiSuccess {Boolean} OK true if call was successful
 * @apiSuccess {String[]} errors List of error strings (when `OK` is false)
 * @apiSuccess {Object} data case data
 *
 * @apiSuccessExample Success-Response:
 *     HTTP/1.1 200 OK
 *     {
 *       "OK": true,
 *       "data": {
 *         "ID": 3,
 *         "Description": 'foo'
 *        }
 *     }
 *
 * @apiError NotAuthenticated The user is not authenticated
 * @apiError NotAuthorized The user doesn't have permission to perform this operation.
 *
 */

function getUpdatedCase(user, params, newCase, oldCase) {
  const updatedCase = Object.assign({}, oldCase);
  const er = new ErrorReporter();
  const cond = (key, fn) => setConditional(updatedCase, newCase, er, fn, key);
  // admin-only
  if (user.isadmin) {
    cond("featured", as.boolean);
    cond("hidden", as.boolean);
    cond("completeness", as.text);
    cond("original_language", as.text);
    cond("post_date", as.date);
    cond("updated_date", as.date);
  }

  // media lists
  ["links", "videos", "audio", "evaluation_links"].map(key =>
    cond(key, as.media)
  );
  // photos and files are slightly different from other media as they have a source url too
  ["photos", "files", "evaluation_reports"].map(key =>
    cond(key, as.sourcedMedia)
  );
  // boolean (would include "published" but we don't really support it)
  ["ongoing", "staff", "volunteers"].map(key => cond(key, as.selectBoolean));
  // yes/no (convert to boolean)
  ["impact_evidence", "formal_evaluation"].map(key => cond(key, as.yesno));
  // integer
  ["number_of_participants"].map(key => cond(key, as.integer));
  // float
  ["latitude", "longitude"].map(key => cond(key, as.float));
  // plain text
  [
    "location_name",
    "address1",
    "address2",
    "city",
    "province",
    "postal_code",
    "country",
    "funder",
  ].map(key => cond(key, as.text));
  // date
  ["start_date", "end_date"].map(key => cond(key, as.date));
  // id
  ["is_component_of", "primary_organizer"].map(key => cond(key, as.id));
  // list of ids
  ["specific_methods_tools_techniques"].map(key => cond(key, as.ids));
  // key
  [
    "scope_of_influence",
    "public_spectrum",
    "legality",
    "facilitators",
    "facilitator_training",
    "facetoface_online_or_both",
    "open_limited",
    "recruitment_method",
    "time_limited",
  ].map(key => cond(key, as.casekeyflat));
  // list of keys
  [
    "general_issues",
    "specific_topics",
    "collections",
    "purposes",
    "approaches",
    "targeted_participants",
    "method_types",
    "participants_interactions",
    "learning_resources",
    "decision_methods",
    "if_voting",
    "insights_outcomes",
    "organizer_types",
    "funder_types",
    "change_types",
    "implementers_of_change",
    "tools_techniques_types",
  ].map(key => cond(key, as.casekeys));
  // TODO save bookmarked on user
  return [updatedCase, er];
}

// Only changes to title, description, and/or body trigger a new author and version

async function postCaseUpdateHttp(req, res) {
  // cache.clear();
  const params = parseGetParams(req, "case");
  const user = req.user;
  const { articleid, type, view, userid, lang, returns } = params;
  const newCase = req.body;
  const links = req.body.links;

  //validate url

  if (links) {
    for (let key in links) {
      let url = links[key].url;
      if (url.length > 0) {
        newCase.links = verifyOrUpdateUrl(newCase.links);
        const isUrlValid = validateUrl(newCase);
        if (!isUrlValid) {
          return res.status(400).json({
            OK: false,
            errors: ["Invalid link url."],
          });
        }
      }
    }
  }

  // if this is a new case, we don't have a post_date yet, so we set it here
  if (!newCase.post_date) {
    newCase.post_date = Date.now();
  }

  // if this is a new case, we don't have a updated_date yet, so we set it here
  if (!newCase.updated_date) {
    newCase.updated_date = Date.now();
  }

  // save any changes to the user-submitted text
  const {
    updatedText,
    author,
    oldArticle: oldCase,
  } = await maybeUpdateUserText(req, res, "case");
  const [updatedCase, er] = getUpdatedCase(user, params, newCase, oldCase);

  //get current date when user.isAdmin is false;
  updatedCase.updated_date = !user.isadmin ? "now" : updatedCase.updated_date;

  if (!er.hasErrors()) {
    if (updatedText) {
      await db.tx("update-case", async t => {
        await t.none(INSERT_AUTHOR, author);
        await t.none(INSERT_LOCALIZED_TEXT, updatedText);
        await t.none(UPDATE_CASE, updatedCase);
      });
      //if this is a new case, set creator id to userid and isAdmin
      if (user.isadmin) {
        const creator = {
          user_id: newCase.creator ? newCase.creator : params.userid,
          thingid: params.articleid,
        };
        const updatedBy = {
          user_id: newCase.last_updated_by
            ? newCase.last_updated_by
            : params.userid,
          thingid: params.articleid,
          updated_date: newCase.updated_date || "now",
        };
        await db.tx("update-case", async t => {
          await t.none(UPDATE_AUTHOR_FIRST, creator);
          await t.none(UPDATE_AUTHOR_LAST, updatedBy);
        });
      }
    } else {
      await db.tx("update-case", async t => {
        await t.none(INSERT_AUTHOR, author);
        await t.none(UPDATE_CASE, updatedCase);
      });
    }
    // the client expects this request to respond with json
    // save successful response
    const freshArticle = await getCase(params, res);
    res.status(200).json({
      OK: true,
      article: freshArticle,
    });
    refreshSearch();
  } else {
    logError(`400 with errors: ${er.errors.join(", ")}`);
    res.status(400).json({
      OK: false,
      errors: er.errors,
    });
  }
}

/**
 * @api {get} /case/:thingid Get the last version of a case
 * @apiGroup Cases
 * @apiVersion 0.1.0
 * @apiName returnCaseById
 * @apiParam {Number} thingid Case ID
 *
 * @apiSuccess {Boolean} OK true if call was successful
 * @apiSuccess {String[]} errors List of error strings (when `OK` is false)
 * @apiSuccess {Object} data case data
 *
 * @apiSuccessExample Success-Response:
 *     HTTP/1.1 200 OK
 *     {
 *       "OK": true,
 *       "data": {
 *         "ID": 3,
 *         "Description": 'foo'
 *        }
 *     }
 *
 * @apiError NotAuthenticated The user is not authenticated
 * @apiError NotAuthorized The user doesn't have permission to perform this operation.
 *
 */

async function getCase(params, res) {
  try {
    if (Number.isNaN(params.articleid)) {
      return null;
    }
    const articleRow = await db.one(CASE_BY_ID, params);
    const article = articleRow.results;
    fixUpURLs(article);
    return article;
  } catch (error) {
    // only log actual excaptional results, not just data not found
    if (error.message !== "No data returned from the query.") {
      logError(error);
    }
    // if no entry is found, render the 404 page
    return null;
  }
}

async function getCaseHttp(req, res) {
  /* This is the entry point for getting an article */
  const params = parseGetParams(req, "case");
  const article = await getCase(params, res);
  if (!article) {
    res.status(404).render("404");
    return null;
  }
  const staticText = await getEditStaticText(params);
  returnByType(res, params, article, staticText, req.user);
}

async function getEditStaticText(params) {
  const lang = params.lang;
  let staticText = Object.assign({}, sharedFieldOptions);
  staticText.collections = await getCollections(lang);
  staticText.authors = listUsers();
  staticText.cases = listCases(lang).filter(article => !article.hidden);
  staticText.methods = listMethods(lang).filter(article => !article.hidden);
  staticText.organizations = listOrganizations(lang).filter(
    article => !article.hidden
  );
  return staticText;
}

async function getCaseEditHttp(req, res) {
  let startTime = new Date();
  const params = parseGetParams(req, "case");
  params.view = "edit";
  const article = await getCase(params, res);
  if (!article) {
    res.status(404).render("404");
    return null;
  }
  const staticText = await getEditStaticText(params);
  returnByType(res, params, article, staticText, req.user);
}

async function getCaseNewHttp(req, res) {
  const params = parseGetParams(req, "case");
  params.view = "edit";
  const article = CASE_STRUCTURE;
  const staticText = await getEditStaticText(params);
  returnByType(res, params, article, staticText, req.user);
}

const router = express.Router(); // eslint-disable-line new-cap
router.get("/:thingid/edit", requireAuthenticatedUser(), getCaseEditHttp);
router.get("/new", requireAuthenticatedUser(), getCaseNewHttp);
router.post("/new", requireAuthenticatedUser(), postCaseNewHttp);
router.get("/:thingid", getCaseHttp);
router.post("/:thingid", requireAuthenticatedUser(), postCaseUpdateHttp);

module.exports = {
  case_: router,
  getCaseEditHttp,
  getCaseNewHttp,
  postCaseNewHttp,
  getCaseHttp,
  postCaseUpdateHttp,
};
<|endoftext|>


<commit_before>/*
  Copyright 2019 Google LLC

  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

      https://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.
*/

//useTargetServers
//|   |:white_medium_square:| TD002 | Use Target Server |  Discourage use of direct URLs in Target Server. |

const xpath = require("xpath"),
      ruleId = require("../myUtil.js").getRuleId(),
      debug = require("debug")("apigeelint:" + ruleId);

var plugin = {
    ruleId,
    name: "Discourage use of direct URLs in Target Server.",
    message: "Using a Target Server simplifies CI/CD.",
    fatal: false,
    severity: 1, //warn
    nodeType: "TargetEndpoint",
    enabled: true
    };

var onTargetEndpoint = function(target, cb) {
  //get /TargetEndpoint/HTTPTargetConnection/URL
  var hadWarnErr = false;
  var url = xpath.select(
      "/TargetEndpoint/HTTPTargetConnection/URL/text()",
      target.getElement()
    );

  if (url && url[0] !== undefined ) {
    let name = target.getName();
    target.addMessage({
      plugin,
      message: `TargetEndpoint (${name}) is using URL (${url}), using a Target Server simplifies CI/CD.`
    });
    hadWarnErr=true;
  }

  if (typeof cb == "function") {
    cb(null,hadWarnErr);
  }
  return hadWarnErr;
};

module.exports = {
  plugin,
  onTargetEndpoint
};
<commit_msg>Fix Issue232, avoid TD002 for EMG<commit_after>/*
  Copyright 2019 Google LLC

  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

      https://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.
*/

//useTargetServers
//|   |:white_medium_square:| TD002 | Use Target Server |  Discourage use of direct URLs in Target Server. |

const xpath = require("xpath"),
      ruleId = require("../myUtil.js").getRuleId(),
      debug = require("debug")("apigeelint:" + ruleId);

var plugin = {
    ruleId,
    name: "Discourage use of direct URLs in Target Server.",
    message: "Using a Target Server simplifies CI/CD.",
    fatal: false,
    severity: 1, //warn
    nodeType: "TargetEndpoint",
    enabled: true
    };

let emg = false;

const onBundle = function (b, cb) {
  debug( "onBundle: " + b.getName());
  if( b.getName().startsWith("edgemicro_") ) {
    emg = true;
  }
  if (typeof cb == "function") {
    cb(null, false);
  }
};

const onTargetEndpoint = function(target, cb) {
  debug( "onTargetEndpoint emg: " + emg );
  var hadWarnErr = false;

  if( !emg ) {
    var url = xpath.select(
        "/TargetEndpoint/HTTPTargetConnection/URL/text()",
        target.getElement()
      );

    if (url && url[0] !== undefined ) {
      let name = target.getName();
      target.addMessage({
        plugin,
        message: `TargetEndpoint (${name}) is using URL (${url}), using a Target Server simplifies CI/CD.`
      });
      hadWarnErr=true;
    }
  }

  if (typeof cb == "function") {
    cb(null,hadWarnErr);
  }
  return hadWarnErr;
};

module.exports = {
  plugin,
  onBundle,
  onTargetEndpoint
};
<|endoftext|>


<commit_before>// (C) Copyright 2014-2016 Hewlett Packard Enterprise Development LP

import React, { Component } from 'react';
import Search from 'grommet/components/Search';
import InteractiveExample from '../../../components/InteractiveExample';

Search.displayName = 'Search';

const PROPS_SCHEMA = {
  placeHolder: { value: 'Search', initial: true },
  inline: { value: true, initial: true },
  responsive: { value: true },
  iconAlign: { options: ['start', 'end'] },
  size: { options: ['small', 'medium', 'large'] },
  suggestions: { value: ['first', 'second', 'third', 'fourth'] }
};

export default class SearchExamplesDoc extends Component {

  constructor () {
    super();
    this.state = { elementProps: {} };
  }

  render () {
    const { elementProps } = this.state;
    const element = <Search {...elementProps} />;
    return (
      <InteractiveExample contextLabel='Search' contextPath='/docs/search'
        preamble={`import Search from 'grommet/components/Search';`}
        propsSchema={PROPS_SCHEMA}
        element={element}
        onChange={elementProps => this.setState({ elementProps })} />
    );
  }
};
<commit_msg>Enhanced Search examples to show setting value.<commit_after>// (C) Copyright 2014-2016 Hewlett Packard Enterprise Development LP

import React, { Component } from 'react';
import Search from 'grommet/components/Search';
import InteractiveExample from '../../../components/InteractiveExample';

Search.displayName = 'Search';

const PROPS_SCHEMA = {
  placeHolder: { value: 'Search', initial: true },
  inline: { value: true, initial: true },
  responsive: { value: true },
  iconAlign: { options: ['start', 'end'] },
  size: { options: ['small', 'medium', 'large'] },
  suggestions: { value: ['first', 'second', 'third', 'fourth'] }
};

export default class SearchExamplesDoc extends Component {

  constructor () {
    super();
    this._onDOMChange = this._onDOMChange.bind(this);
    this._onSelect = this._onSelect.bind(this);
    this.state = { elementProps: {}, value: '' };
  }

  _onDOMChange (event) {
    this.setState({ value: event.target.value });
  }

  _onSelect (event) {
    this.setState({ value: event.suggestion });
  }

  render () {
    const { elementProps, value } = this.state;
    const props = { value };
    if (elementProps.suggestions) {
      props.onSelect = this._onSelect;
    }
    const element = (
      <Search {...elementProps} {...props}
        onDOMChange={this._onDOMChange}/>
    );
    return (
      <InteractiveExample contextLabel='Search' contextPath='/docs/search'
        preamble={`import Search from 'grommet/components/Search';`}
        propsSchema={PROPS_SCHEMA}
        element={element}
        onChange={elementProps => this.setState({ elementProps })} />
    );
  }
};
<|endoftext|>


<commit_before>module.exports = {
	description: 'handles naked return value from top-level arrow function expression (#403)'
};
<commit_msg>argh, node 0.12<commit_after>module.exports = {
	description: 'handles naked return value from top-level arrow function expression (#403)',
	babel: true
};
<|endoftext|>


<commit_before>/* @flow weak */

/**
 * mSupply Mobile
 * Sustainable Solutions (NZ) Ltd. 2016
 */

import React from 'react';
import { StyleSheet, View } from 'react-native';
import globalStyles, {
  SUSSOL_ORANGE,
  WARM_GREY,
  LIGHT_GREY,
  COMPONENT_HEIGHT,
} from '../globalStyles';

import {
  Cell,
  CheckableCell,
  DataTable,
  EditableCell,
  Header,
  HeaderCell,
  Row,
} from '../widgets/DataTable';

import Icon from 'react-native-vector-icons/Ionicons';
import { ListView } from 'realm/react-native';
import { SearchBar } from '../widgets';

/**
 * Provides a generic implementation of a standard page in mSupply Mobile, which
 * contains a searchable table. Should always be overridden, in particular the
 * following methods and instance variables (fields):
 * @method getUpdatedData(searchTerm, sortBy, isAscending) Should return updated data
 * @method renderCell(key, record) Should define what to render in a cell with the
 *         											 given column key and database record
 * @method onRowPress(key, rowData) Should define behaviour when a row is pressed,
 *         											 don't override if row should not be pressable
 * @method onEndEditing(key, rowData, newValue) Handles user input to an editable cell
 *         											 don't override if row should not be pressable
 * @const  {array}  cellRefsMap  Stores references to TextInputs in editableCells so next button
 *                               on native keyboard focuses the next cell. Order is left to
 *                               right within a row, then next row.
 * @field  {array}  columns      An array of objects defining each of the columns.
 *         											 Each column must contain: key, width, title. Each
 *         											 may optionally also contain a boolean 'sortable'.
 * @state  {ListView.DataSource} dataSource    DataTable input, used to update rows
 *         																		 being rendered
 * @state  {string}              searchTerm    Current term user has entered in search bar
 * @state  {string}              sortBy        The property to sort by (is selected
 *                                             by column press).
 * @state  {boolean}             isAscending   Direction sortBy should sort
 *                                             (ascending/descending:true/false).
 * N.B. Take care to call parent method if overriding any of the react life cycle methods.
 */
export class GenericTablePage extends React.Component {
  constructor(props) {
    super(props);
    const dataSource = new ListView.DataSource({
      rowHasChanged: (row1, row2) => row1 !== row2,
    });
    this.state = {
      dataSource: dataSource,
      searchTerm: '',
      sortBy: '',
      isAscending: true,
      selection: [],
      expandedRows: [],
      modalKey: null,
      pageContentModalIsOpen: false,
    };
    this.cellRefsMap = {}; // { rowId: reference, rowId: reference, ...}
    this.columns = null;
    this.dataTableRef = null;
    this.dataTypesDisplayed = [];
    this.databaseListenerId = null;
    this.onSearchChange = this.onSearchChange.bind(this);
    this.onColumnSort = this.onColumnSort.bind(this);
    this.onDatabaseEvent = this.onDatabaseEvent.bind(this);
    this.openModal = this.openModal.bind(this);
    this.closeModal = this.closeModal.bind(this);
    this.focusNextField = this.focusNextField.bind(this);
    this.renderHeader = this.renderHeader.bind(this);
    this.renderRow = this.renderRow.bind(this);
    this.renderCell = this.renderCell.bind(this);
    this.refreshData = this.refreshData.bind(this);
  }

  /**
   * If overridden, first line of this method should be duplicated. May need to be overridden to
   * populate selection in state if CheckableCells are used and need to
   * remember their selected state.
   */
  componentWillMount() {
    this.databaseListenerId = this.props.database.addListener(this.onDatabaseEvent);
    this.refreshData();
  }

  componentWillUnmount() {
    this.props.database.removeListener(this.databaseListenerId);
  }

  onDatabaseEvent(changeType, recordType) {
    if (this.dataTypesDisplayed.indexOf(recordType) >= 0) this.refreshData();
  }

  onSearchChange(event) {
    const term = event.nativeEvent.text;
    this.setState({ searchTerm: term }, () => {
      this.refreshData();
      if (this.dataTableRef) this.dataTableRef.scrollTo({ y: 0, animated: false });
    });
  }

  onColumnSort(sortBy) {
    if (this.state.sortBy === sortBy) { // Changed column sort direction
      this.setState({ isAscending: !this.state.isAscending }, this.refreshData);
    } else { // Changed sorting column
      this.setState({
        sortBy: sortBy,
        isAscending: true,
      }, this.refreshData);
    }
  }

  /**
   * Adds/removes rowData.id to/from the selection array in state. Must call this within any
   * overrides. i.e. super.onCheckablePress(rowData);
   */
  onCheckablePress(rowData) {
    const newSelection = [...this.state.selection];
    if (newSelection.indexOf(rowData.id) >= 0) {
      newSelection.splice(newSelection.indexOf(rowData.id), 1);
    } else {
      newSelection.push(rowData.id);
    }
    this.setState({ selection: newSelection });
  }

  /**
   * Adds/removes rowData.id to/from the expandedRows array in state. Must call this within any
   * overrides i.e. super.onExpandablePress(rowData);
   */
  onExpandablePress(rowData) {
    const newExpandedRows = [...this.state.expandedRows];
    if (newExpandedRows.indexOf(rowData.id) >= 0) {
      newExpandedRows.splice(newExpandedRows.indexOf(rowData.id), 1);
    } else {
      newExpandedRows.push(rowData.id);
    }
    this.setState({ expandedRows: newExpandedRows });
  }

  openModal(key) {
    this.setState({ modalKey: key, pageContentModalIsOpen: true });
  }

  closeModal() {
    this.setState({ pageContentModalIsOpen: false });
  }

  scrollTableToRow(rowId) {
    // Scrolls to row of rowId with a couple rows above it, unless the rowId is of the top 3 rows,
    // where it just scrolls to the top.
    const yValue = Math.max((rowId - 2) * COMPONENT_HEIGHT, 0);
    if (this.dataTableRef) this.dataTableRef.scrollTo({ y: yValue });
  }

  focusNextField(currentCellRef) {
    const nextCellRef = currentCellRef + 1;
    if (this.cellRefsMap[nextCellRef]) {
      this.scrollTableToRow(nextCellRef);
      this.cellRefsMap[nextCellRef].focus();
    } else {
      // Protect against crash from null being in the Map.
      if (this.cellRefsMap[currentCellRef]) this.cellRefsMap[currentCellRef].blur();
    }
  }

  refreshData() {
    this.cellRefsMap = {};
    const { dataSource, searchTerm, sortBy, isAscending } = this.state;
    const data = this.getUpdatedData(searchTerm, sortBy, isAscending);
    this.setState({ dataSource: dataSource.cloneWithRows(data) });
  }

/**
 * Accepted Cell formats:
 * 1. <Cell style={styles.cell} width={3}/> // Or any other react component. Must be styled within
 *                                          // the extending class.
 * 2. item.name;
 * 3. {
 *      type: 'text',
 *      cellContents: item.name,
 *    };
 * 4. {
 *      type: 'editable',
 *      cellContents: transactionItem.totalQuantity,
 *    };
 * 4. {
 *      type: 'editable',
 *      cellContents: item.countedTotalQuantity,
 *      keyboardType: numeric,
 *      returnKeyType: 'next',
 *    };
 * 6. {
 *      type: 'checkable',
 *      isDisabled: false,
 *    };
 * 7. {
 *      type: 'checkable',
 *      icon: 'md-remove-circle', // will use for both Checked and NotChecked, only colour changes
 *      isDisabled: false,
 *    };
 * 8. {
 *      type: 'checkable',
 *      iconChecked: 'md-radio-button-on',
 *      iconNotChecked: 'md-radio-button-off',
 *      isDisabled: false,
 *    };
 */
  renderCell() {
    return 'DEFAULT CELL';
  }

  renderHeader() {
    const headerCells = [];
    this.columns.forEach((column, index, columns) => {
      let textStyle;
      let cellStyle = index !== columns.length - 1 ?
        globalStyles.dataTableHeaderCell :
        [globalStyles.dataTableHeaderCell, globalStyles.dataTableRightMostCell];

      switch (column.alignText) {
        case 'left':
        default:
          textStyle = [globalStyles.dataTableText, localStyles.alignTextLeft];
          break;
        case 'center':
          textStyle = [globalStyles.dataTableText, localStyles.alignTextCenter];
          cellStyle = [cellStyle, { justifyContent: 'center' }];
          break;
        case 'right':
          textStyle = [globalStyles.dataTableText, localStyles.alignTextRight];
          cellStyle = [cellStyle, { justifyContent: 'flex-end' }];
          break;
      }

      const sortFunction = column.sortable ? () => this.onColumnSort(column.key) : null;
      headerCells.push(
        <HeaderCell
          key={column.key}
          style={cellStyle}
          textStyle={textStyle}
          width={column.width}
          onPress={sortFunction}
          isAscending={this.state.isAscending}
          isSelected={this.state.sortBy === column.key}
          text={column.title}
        />
      );
    });
    return (
      <Header style={globalStyles.header}>
        {headerCells}
      </Header>
    );
  }

  renderRow(rowData, sectionId, rowId) {
    const cells = [];
    const isExpanded = this.state.expandedRows.includes(rowData.id);
    // Make rows alternate background colour
    const rowStyle = rowId % 2 === 1 ?
      globalStyles.dataTableRow : [globalStyles.dataTableRow, { backgroundColor: 'white' }];

    this.columns.forEach((column, index, columns) => {
      let textStyle;
      switch (column.alignText) {
        case 'left':
        default:
          textStyle = [globalStyles.dataTableText, localStyles.alignTextLeft];
          break;
        case 'center':
          textStyle = [globalStyles.dataTableText, localStyles.alignTextCenter];
          break;
        case 'right':
          textStyle = [globalStyles.dataTableText, localStyles.alignTextRight];
          break;
      }

      const cellStyle = index !== columns.length - 1 ?
        globalStyles.dataTableCell :
        [globalStyles.dataTableCell, globalStyles.dataTableRightMostCell];
      const renderedCell = this.renderCell(column.key, rowData);

      let cell;
      switch (renderedCell.type) {
        case 'custom':
          cell = renderedCell.cell;
          break;
        case 'checkable': {
          // if provided, use isChecked prop, else set isChecked according to rowData.id
          // being in selection array.
          const isChecked = renderedCell.isChecked ?
            renderedCell.isChecked : this.state.selection.indexOf(rowData.id) >= 0;
          let iconChecked;
          let iconNotChecked;
          if (renderedCell.iconChecked && renderedCell.iconNotChecked) {
            iconChecked = renderedCell.iconChecked;
            iconNotChecked = renderedCell.iconNotChecked;
          } else if (renderedCell.icon) {
            iconChecked = renderedCell.icon;
            iconNotChecked = renderedCell.icon;
          } else {
            iconChecked = 'md-radio-button-on';
            iconNotChecked = 'md-radio-button-off';
          }
          cell = (
            <CheckableCell
              key={column.key}
              style={[
                cellStyle,
                globalStyles.dataTableCheckableCell,
              ]}
              width={column.width}
              onPress={() => this.onCheckablePress(rowData)}
              renderDisabled={() => <Icon name={iconNotChecked} size={15} color={LIGHT_GREY} />}
              renderIsChecked={() => <Icon name={iconChecked} size={15} color={SUSSOL_ORANGE} />}
              renderIsNotChecked={() => <Icon name={iconNotChecked} size={15} color={WARM_GREY} />}
              isChecked={isChecked}
              isDisabled={renderedCell.isDisabled}
            />
          );
          break;
        }
        case 'editable':
          cell = (
            <EditableCell
              key={column.key}
              refCallback={(reference) => { this.cellRefsMap[rowId] = reference; }}
              style={cellStyle}
              textStyle={textStyle}
              width={column.width}
              returnKeyType={renderedCell.returnKeyType || 'next'}
              selectTextOnFocus={true}
              keyboardType={renderedCell.keyboardType || 'numeric'}
              onEndEditing={this.onEndEditing &&
                            ((target, value) => this.onEndEditing(column.key, target, value))}
              onSubmitEditing={() => this.focusNextField(parseInt(rowId, 10))}
              target={rowData}
              value={renderedCell.cellContents}
            />
          );
          break;
        case 'text':
        default:
          cell = (
            <Cell
              key={column.key}
              style={cellStyle}
              textStyle={textStyle}
              width={column.width}
              numberOfLines={renderedCell.lines}
            >
              {renderedCell.hasOwnProperty('cellContents') ?
                renderedCell.cellContents :
                renderedCell}
            </Cell>
          );
      }
      cells.push(cell);
    });
    return (
      <Row
        style={rowStyle}
        renderExpansion={this.renderExpansion && (() => this.renderExpansion(rowData))}
        isExpanded={isExpanded}
        onPress={
          this.renderExpansion && (() => this.onExpandablePress(rowData))
            || this.onRowPress && (() => this.onRowPress(rowData))
        }
      >
        {cells}
      </Row>
    );
  }

  renderSearchBar() {
    return (
      <SearchBar
        onChange={(event) => this.onSearchChange(event)}
      />);
  }

  renderDataTable() {
    return (
      <DataTable
        refCallback={(reference) => (this.dataTableRef = reference)}
        style={globalStyles.dataTable}
        listViewStyle={localStyles.listView}
        dataSource={this.state.dataSource}
        renderRow={this.renderRow}
        renderHeader={this.renderHeader}
      />);
  }

  render() {
    return (
      <View style={globalStyles.pageContentContainer}>
        <View style={globalStyles.container}>
          <View style={globalStyles.pageTopSectionContainer}>
            <View style={globalStyles.pageTopLeftSectionContainer}>
              {this.renderSearchBar()}
            </View>
          </View>
          {this.renderDataTable()}
        </View>
      </View>
    );
  }
}

GenericTablePage.propTypes = {
  database: React.PropTypes.object,
};

const localStyles = StyleSheet.create({
  listView: {
    flex: 1,
  },
  alignTextLeft: {
    marginLeft: 20,
    textAlign: 'left',
  },
  alignTextCenter: {
    textAlign: 'center',
  },
  alignTextRight: {
    marginRight: 20,
    textAlign: 'right',
  },
});
<commit_msg>Only refreshes data on sync<commit_after>/* @flow weak */

/**
 * mSupply Mobile
 * Sustainable Solutions (NZ) Ltd. 2016
 */

import React from 'react';
import { StyleSheet, View } from 'react-native';
import globalStyles, {
  SUSSOL_ORANGE,
  WARM_GREY,
  LIGHT_GREY,
  COMPONENT_HEIGHT,
} from '../globalStyles';

import {
  Cell,
  CheckableCell,
  DataTable,
  EditableCell,
  Header,
  HeaderCell,
  Row,
} from '../widgets/DataTable';

import Icon from 'react-native-vector-icons/Ionicons';
import { ListView } from 'realm/react-native';
import { SearchBar } from '../widgets';

/**
 * Provides a generic implementation of a standard page in mSupply Mobile, which
 * contains a searchable table. Should always be overridden, in particular the
 * following methods and instance variables (fields):
 * @method getUpdatedData(searchTerm, sortBy, isAscending) Should return updated data
 * @method renderCell(key, record) Should define what to render in a cell with the
 *         											 given column key and database record
 * @method onRowPress(key, rowData) Should define behaviour when a row is pressed,
 *         											 don't override if row should not be pressable
 * @method onEndEditing(key, rowData, newValue) Handles user input to an editable cell
 *         											 don't override if row should not be pressable
 * @const  {array}  cellRefsMap  Stores references to TextInputs in editableCells so next button
 *                               on native keyboard focuses the next cell. Order is left to
 *                               right within a row, then next row.
 * @field  {array}  columns      An array of objects defining each of the columns.
 *         											 Each column must contain: key, width, title. Each
 *         											 may optionally also contain a boolean 'sortable'.
 * @state  {ListView.DataSource} dataSource    DataTable input, used to update rows
 *         																		 being rendered
 * @state  {string}              searchTerm    Current term user has entered in search bar
 * @state  {string}              sortBy        The property to sort by (is selected
 *                                             by column press).
 * @state  {boolean}             isAscending   Direction sortBy should sort
 *                                             (ascending/descending:true/false).
 * N.B. Take care to call parent method if overriding any of the react life cycle methods.
 */
export class GenericTablePage extends React.Component {
  constructor(props) {
    super(props);
    const dataSource = new ListView.DataSource({
      rowHasChanged: (row1, row2) => row1 !== row2,
    });
    this.state = {
      dataSource: dataSource,
      searchTerm: '',
      sortBy: '',
      isAscending: true,
      selection: [],
      expandedRows: [],
      modalKey: null,
      pageContentModalIsOpen: false,
    };
    this.cellRefsMap = {}; // { rowId: reference, rowId: reference, ...}
    this.columns = null;
    this.dataTableRef = null;
    this.dataTypesDisplayed = [];
    this.databaseListenerId = null;
    this.onSearchChange = this.onSearchChange.bind(this);
    this.onColumnSort = this.onColumnSort.bind(this);
    this.onDatabaseEvent = this.onDatabaseEvent.bind(this);
    this.openModal = this.openModal.bind(this);
    this.closeModal = this.closeModal.bind(this);
    this.focusNextField = this.focusNextField.bind(this);
    this.renderHeader = this.renderHeader.bind(this);
    this.renderRow = this.renderRow.bind(this);
    this.renderCell = this.renderCell.bind(this);
    this.refreshData = this.refreshData.bind(this);
  }

  /**
   * If overridden, first line of this method should be duplicated. May need to be overridden to
   * populate selection in state if CheckableCells are used and need to
   * remember their selected state.
   */
  componentWillMount() {
    this.databaseListenerId = this.props.database.addListener(this.onDatabaseEvent);
    this.refreshData();
  }

  componentWillUnmount() {
    this.props.database.removeListener(this.databaseListenerId);
  }

  // Refetch data and render the list any time sync changes data displayed on this page
  onDatabaseEvent(changeType, recordType, record, causedBy) {
    if (causedBy === 'sync' && this.dataTypesDisplayed.indexOf(recordType) >= 0) this.refreshData();
  }

  onSearchChange(event) {
    const term = event.nativeEvent.text;
    this.setState({ searchTerm: term }, () => {
      this.refreshData();
      if (this.dataTableRef) this.dataTableRef.scrollTo({ y: 0, animated: false });
    });
  }

  onColumnSort(sortBy) {
    if (this.state.sortBy === sortBy) { // Changed column sort direction
      this.setState({ isAscending: !this.state.isAscending }, this.refreshData);
    } else { // Changed sorting column
      this.setState({
        sortBy: sortBy,
        isAscending: true,
      }, this.refreshData);
    }
  }

  /**
   * Adds/removes rowData.id to/from the selection array in state. Must call this within any
   * overrides. i.e. super.onCheckablePress(rowData);
   */
  onCheckablePress(rowData) {
    const newSelection = [...this.state.selection];
    if (newSelection.indexOf(rowData.id) >= 0) {
      newSelection.splice(newSelection.indexOf(rowData.id), 1);
    } else {
      newSelection.push(rowData.id);
    }
    this.setState({ selection: newSelection });
  }

  /**
   * Adds/removes rowData.id to/from the expandedRows array in state. Must call this within any
   * overrides i.e. super.onExpandablePress(rowData);
   */
  onExpandablePress(rowData) {
    const newExpandedRows = [...this.state.expandedRows];
    if (newExpandedRows.indexOf(rowData.id) >= 0) {
      newExpandedRows.splice(newExpandedRows.indexOf(rowData.id), 1);
    } else {
      newExpandedRows.push(rowData.id);
    }
    this.setState({ expandedRows: newExpandedRows });
  }

  openModal(key) {
    this.setState({ modalKey: key, pageContentModalIsOpen: true });
  }

  closeModal() {
    this.setState({ pageContentModalIsOpen: false });
  }

  scrollTableToRow(rowId) {
    // Scrolls to row of rowId with a couple rows above it, unless the rowId is of the top 3 rows,
    // where it just scrolls to the top.
    const yValue = Math.max((rowId - 2) * COMPONENT_HEIGHT, 0);
    if (this.dataTableRef) this.dataTableRef.scrollTo({ y: yValue });
  }

  focusNextField(currentCellRef) {
    const nextCellRef = currentCellRef + 1;
    if (this.cellRefsMap[nextCellRef]) {
      this.scrollTableToRow(nextCellRef);
      this.cellRefsMap[nextCellRef].focus();
    } else {
      // Protect against crash from null being in the Map.
      if (this.cellRefsMap[currentCellRef]) this.cellRefsMap[currentCellRef].blur();
    }
  }

  refreshData() {
    this.cellRefsMap = {};
    const { dataSource, searchTerm, sortBy, isAscending } = this.state;
    const data = this.getUpdatedData(searchTerm, sortBy, isAscending);
    this.setState({ dataSource: dataSource.cloneWithRows(data) });
  }

/**
 * Accepted Cell formats:
 * 1. <Cell style={styles.cell} width={3}/> // Or any other react component. Must be styled within
 *                                          // the extending class.
 * 2. item.name;
 * 3. {
 *      type: 'text',
 *      cellContents: item.name,
 *    };
 * 4. {
 *      type: 'editable',
 *      cellContents: transactionItem.totalQuantity,
 *    };
 * 4. {
 *      type: 'editable',
 *      cellContents: item.countedTotalQuantity,
 *      keyboardType: numeric,
 *      returnKeyType: 'next',
 *    };
 * 6. {
 *      type: 'checkable',
 *      isDisabled: false,
 *    };
 * 7. {
 *      type: 'checkable',
 *      icon: 'md-remove-circle', // will use for both Checked and NotChecked, only colour changes
 *      isDisabled: false,
 *    };
 * 8. {
 *      type: 'checkable',
 *      iconChecked: 'md-radio-button-on',
 *      iconNotChecked: 'md-radio-button-off',
 *      isDisabled: false,
 *    };
 */
  renderCell() {
    return 'DEFAULT CELL';
  }

  renderHeader() {
    const headerCells = [];
    this.columns.forEach((column, index, columns) => {
      let textStyle;
      let cellStyle = index !== columns.length - 1 ?
        globalStyles.dataTableHeaderCell :
        [globalStyles.dataTableHeaderCell, globalStyles.dataTableRightMostCell];

      switch (column.alignText) {
        case 'left':
        default:
          textStyle = [globalStyles.dataTableText, localStyles.alignTextLeft];
          break;
        case 'center':
          textStyle = [globalStyles.dataTableText, localStyles.alignTextCenter];
          cellStyle = [cellStyle, { justifyContent: 'center' }];
          break;
        case 'right':
          textStyle = [globalStyles.dataTableText, localStyles.alignTextRight];
          cellStyle = [cellStyle, { justifyContent: 'flex-end' }];
          break;
      }

      const sortFunction = column.sortable ? () => this.onColumnSort(column.key) : null;
      headerCells.push(
        <HeaderCell
          key={column.key}
          style={cellStyle}
          textStyle={textStyle}
          width={column.width}
          onPress={sortFunction}
          isAscending={this.state.isAscending}
          isSelected={this.state.sortBy === column.key}
          text={column.title}
        />
      );
    });
    return (
      <Header style={globalStyles.header}>
        {headerCells}
      </Header>
    );
  }

  renderRow(rowData, sectionId, rowId) {
    const cells = [];
    const isExpanded = this.state.expandedRows.includes(rowData.id);
    // Make rows alternate background colour
    const rowStyle = rowId % 2 === 1 ?
      globalStyles.dataTableRow : [globalStyles.dataTableRow, { backgroundColor: 'white' }];

    this.columns.forEach((column, index, columns) => {
      let textStyle;
      switch (column.alignText) {
        case 'left':
        default:
          textStyle = [globalStyles.dataTableText, localStyles.alignTextLeft];
          break;
        case 'center':
          textStyle = [globalStyles.dataTableText, localStyles.alignTextCenter];
          break;
        case 'right':
          textStyle = [globalStyles.dataTableText, localStyles.alignTextRight];
          break;
      }

      const cellStyle = index !== columns.length - 1 ?
        globalStyles.dataTableCell :
        [globalStyles.dataTableCell, globalStyles.dataTableRightMostCell];
      const renderedCell = this.renderCell(column.key, rowData);

      let cell;
      switch (renderedCell.type) {
        case 'custom':
          cell = renderedCell.cell;
          break;
        case 'checkable': {
          // if provided, use isChecked prop, else set isChecked according to rowData.id
          // being in selection array.
          const isChecked = renderedCell.isChecked ?
            renderedCell.isChecked : this.state.selection.indexOf(rowData.id) >= 0;
          let iconChecked;
          let iconNotChecked;
          if (renderedCell.iconChecked && renderedCell.iconNotChecked) {
            iconChecked = renderedCell.iconChecked;
            iconNotChecked = renderedCell.iconNotChecked;
          } else if (renderedCell.icon) {
            iconChecked = renderedCell.icon;
            iconNotChecked = renderedCell.icon;
          } else {
            iconChecked = 'md-radio-button-on';
            iconNotChecked = 'md-radio-button-off';
          }
          cell = (
            <CheckableCell
              key={column.key}
              style={[
                cellStyle,
                globalStyles.dataTableCheckableCell,
              ]}
              width={column.width}
              onPress={() => this.onCheckablePress(rowData)}
              renderDisabled={() => <Icon name={iconNotChecked} size={15} color={LIGHT_GREY} />}
              renderIsChecked={() => <Icon name={iconChecked} size={15} color={SUSSOL_ORANGE} />}
              renderIsNotChecked={() => <Icon name={iconNotChecked} size={15} color={WARM_GREY} />}
              isChecked={isChecked}
              isDisabled={renderedCell.isDisabled}
            />
          );
          break;
        }
        case 'editable':
          cell = (
            <EditableCell
              key={column.key}
              refCallback={(reference) => { this.cellRefsMap[rowId] = reference; }}
              style={cellStyle}
              textStyle={textStyle}
              width={column.width}
              returnKeyType={renderedCell.returnKeyType || 'next'}
              selectTextOnFocus={true}
              keyboardType={renderedCell.keyboardType || 'numeric'}
              onEndEditing={this.onEndEditing &&
                            ((target, value) => this.onEndEditing(column.key, target, value))}
              onSubmitEditing={() => this.focusNextField(parseInt(rowId, 10))}
              target={rowData}
              value={renderedCell.cellContents}
            />
          );
          break;
        case 'text':
        default:
          cell = (
            <Cell
              key={column.key}
              style={cellStyle}
              textStyle={textStyle}
              width={column.width}
              numberOfLines={renderedCell.lines}
            >
              {renderedCell.hasOwnProperty('cellContents') ?
                renderedCell.cellContents :
                renderedCell}
            </Cell>
          );
      }
      cells.push(cell);
    });
    return (
      <Row
        style={rowStyle}
        renderExpansion={this.renderExpansion && (() => this.renderExpansion(rowData))}
        isExpanded={isExpanded}
        onPress={
          this.renderExpansion && (() => this.onExpandablePress(rowData))
            || this.onRowPress && (() => this.onRowPress(rowData))
        }
      >
        {cells}
      </Row>
    );
  }

  renderSearchBar() {
    return (
      <SearchBar
        onChange={(event) => this.onSearchChange(event)}
      />);
  }

  renderDataTable() {
    return (
      <DataTable
        refCallback={(reference) => (this.dataTableRef = reference)}
        style={globalStyles.dataTable}
        listViewStyle={localStyles.listView}
        dataSource={this.state.dataSource}
        renderRow={this.renderRow}
        renderHeader={this.renderHeader}
      />);
  }

  render() {
    return (
      <View style={globalStyles.pageContentContainer}>
        <View style={globalStyles.container}>
          <View style={globalStyles.pageTopSectionContainer}>
            <View style={globalStyles.pageTopLeftSectionContainer}>
              {this.renderSearchBar()}
            </View>
          </View>
          {this.renderDataTable()}
        </View>
      </View>
    );
  }
}

GenericTablePage.propTypes = {
  database: React.PropTypes.object,
};

const localStyles = StyleSheet.create({
  listView: {
    flex: 1,
  },
  alignTextLeft: {
    marginLeft: 20,
    textAlign: 'left',
  },
  alignTextCenter: {
    textAlign: 'center',
  },
  alignTextRight: {
    marginRight: 20,
    textAlign: 'right',
  },
});
<|endoftext|>


<commit_before>module.exports = require('../../');<commit_msg>just a note for why test/node_modules/keydb<commit_after>// This module exists so tests can always require keydb as 'keydb'.

module.exports = require('../../');<|endoftext|>


<commit_before>var sbot = require('scuttlebot')
var fs = require('fs')
var path = require('path')
var pull = require('pull-stream')
var paramap = require('pull-paramap')
var Blather = require('blather')

function markov (name) {
  var m = new Blather()
  var text = fs.readFileSync(path.join(__dirname, 'text', name+'.txt'), 'utf8')
  console.log(text.length)
  m.addText(text)
  return m
}

//some text sources from the front pages of project gutenburg
var markovs = {
  melville: markov('moby-dick'),
  twain   : markov('a-tale-of-two-cities'),
  wilde   : markov('picture-of-dorian-grey'),
  kafka   : markov('metamorphosis'),
  grim    : markov('grims-fairy-tales')
}

var keys = Object.keys(markovs)

var crypto = require('crypto')
var ssbKeys = require('ssb-keys')

function hash (s) {
  return crypto.createHash('sha256').update(s).digest()
}

var names = require('random-name')

function randomName(feed) {
  return names.first() + '_' + names.last()
}

function randA(feeds) {
  return feeds[~~(Math.random()*feeds.length)]
}

function addNames () {

  return paramap(function (feed, cb) {
    feed.name = randomName()
    feed.voice = keys.shift()
    keys.push(feed.voice)

    feed.add({
      type: 'contact',
      contact: {feed: feed.id},
      follow: true,
      name: feed.name, voice: feed.voice
    }, function () { cb(null, feed) })
  })

}

function addMessage (feeds) {

  return paramap(function (feed, cb) {
    var random = Math.random()
    var f = randA(feeds)

    if(random < 0.5) //say something
      feed.add({
        type: 'post',
        text: markovs[feed.voice].paragraph()
      }, function (_, msg) {
        //track the latest message
        feed.msg = msg
        cb(null, msg)
      })
    if(random < 0.7) { //follow someone
      feed.add({
        type: 'contact',
        contact: {feed: f.id},
        name: f.name
      }, cb)
    }
    else { //reply to some one
      feed.add({
        type: 'post',
        repliesTo: f.msg ? {msg: f.msg.key} : undefined,
        text: markovs[feed.voice].sentence() + ' @' + f.id,
        mentions: [{feed: f.id}],
      }, function (_, msg) {
        //track the latest message
        feed.msg = msg
        cb(null, msg)
      })

    }
  })
}

var config = {
  feeds: 1000,
  messages: 100000,
  seed: 'generate test networks key, [add your own entropy here]'
}

module.exports = function (ssb, main, cb) {

  var seed = config, count = 0, key = 0

  var root = hash(seed)

  var last = ''

  var feeds = []

  pull(
    pull.count(1000), //config.feeds),
    pull.map(function () {
      var feed = ssb.createFeed(ssbKeys.generate('ed25519', hash(seed + ++key))
      feeds.push(feed)
      last = feed.id
      return feed
    }),
    addNames(),
    pull.collect(function (err, feeds) {
      if(err) throw err

      pull(
        pull.count(config.messages),
        pull.map(function (n) {
          return randA(feeds)
        }),
        addMessage(feeds),
        pull.drain(function () {
          console.log(++count)
        }, cb)
      )

    })
  )

}

sbot.init(require('./config'), function (err, sbot) {
  module.exports(sbot.ssb, sbot.feed, function () {
    console.log('generated!')
  })
})
<commit_msg>fix bugs, plus log progress better<commit_after>var sbot = require('scuttlebot')
var fs = require('fs')
var path = require('path')
var pull = require('pull-stream')
var paramap = require('pull-paramap')
var Blather = require('blather')

function markov (name) {
  var m = new Blather()
  var text = fs.readFileSync(path.join(__dirname, 'text', name+'.txt'), 'utf8')
  console.log(text.length)
  m.addText(text)
  return m
}

//some text sources from the front pages of project gutenburg
var markovs = {
  melville: markov('moby-dick'),
  twain   : markov('a-tale-of-two-cities'),
  wilde   : markov('picture-of-dorian-grey'),
  kafka   : markov('metamorphosis'),
  grim    : markov('grims-fairy-tales')
}

var keys = Object.keys(markovs)

var crypto = require('crypto')
var ssbKeys = require('ssb-keys')

function hash (s) {
  return crypto.createHash('sha256').update(s).digest()
}

var names = require('random-name')

function randomName(feed) {
  return names.first() + '_' + names.last()
}

function randA(feeds) {
  return feeds[~~(Math.random()*feeds.length)]
}

function addNames () {

  return paramap(function (feed, cb) {
    feed.name = randomName()
    feed.voice = keys.shift()
    keys.push(feed.voice)

    feed.add({
      type: 'contact',
      contact: {feed: feed.id},
      follow: true,
      name: feed.name, voice: feed.voice
    }, function () { cb(null, feed) })
  })

}

function addMessage (feeds) {

  return paramap(function (feed, cb) {
    var random = Math.random()
    var f = randA(feeds)

    if(random < 0.5) //say something
      feed.add({
        type: 'post',
        text: markovs[feed.voice].paragraph()
      }, function (_, msg) {
        //track the latest message
        feed.msg = msg
        cb(null, msg)
      })
    if(random < 0.7) { //follow someone
      feed.add({
        type: 'contact',
        contact: {feed: f.id},
        name: f.name
      }, cb)
    }
    else { //reply to some one
      feed.add({
        type: 'post',
        repliesTo: f.msg ? {msg: f.msg.key} : undefined,
        text: markovs[feed.voice].sentence() + ' @' + f.id,
        mentions: [{feed: f.id}],
      }, function (_, msg) {
        //track the latest message
        feed.msg = msg
        cb(null, msg)
      })

    }
  })
}

var config = {
  feeds: 1500,
  messages: 200000,
  seed: 'generate test networks key, [add your own entropy here]'
}

function flowMeter (log, slice) {
  var count = 0, slice_count = 0, ts
  return pull.through(function (data) {
    count ++; slice_count++
    if(!ts) ts = Date.now()
    if(Date.now() > ts + slice) {
      log(count, slice_count, slice_count/slice)
      ts = Date.now(); slice_count = 0
    }
  })

}

module.exports = function (ssb, main, cb) {

  var count = 0, key = 0

  var root = hash(config.seed)

  var last = ''

  var feeds = []

  pull(
    pull.count(config.feeds),
    pull.map(function () {
      var feed = ssb.createFeed(ssbKeys.generate('ed25519', hash(config.seed + ++key)))
      feeds.push(feed)
      last = feed.id
      return feed
    }),
    addNames(),
    pull.collect(function (err, feeds) {
      if(err) throw err
      if(!feeds.length) throw new Error('feed generation failed')
      pull(
        pull.count(config.messages),
        pull.map(function (n) {
          return randA(feeds)
        }),
        addMessage(feeds),
        flowMeter(console.log, 1000),
        pull.drain(null, cb)
      )

    })
  )

}

sbot.init(require('./config'), function (err, sbot) {
  module.exports(sbot.ssb, sbot.feed, function () {
    console.log('generated!')
    sbot.close()
  })
})
<|endoftext|>


<commit_before>// Copyright 2014-2015, University of Colorado Boulder

/**
 * View for the 'Energy Systems' screen of the Energy Forms And Changes simulation.
 *
 * @author  John Blanco
 * @author  Martin Veillette (Berea College)
 * @author  Jesse Greenberg
 * @author  Andrew Adare
 */
define( function( require ) {
  'use strict';

  // Modules
  var Bounds2 = require( 'DOT/Bounds2' );
  var CheckBox = require( 'SUN/CheckBox' );
  var EFACConstants = require( 'ENERGY_FORMS_AND_CHANGES/common/EFACConstants' );
  var EnergyChunkLegend = require( 'ENERGY_FORMS_AND_CHANGES/energy-systems/view/EnergyChunkLegend' );
  var energyFormsAndChanges = require( 'ENERGY_FORMS_AND_CHANGES/energyFormsAndChanges' );
  var EnergySystemElementSelector = require( 'ENERGY_FORMS_AND_CHANGES/energy-systems/view/EnergySystemElementSelector' );
  var EnergyChunkNode = require( 'ENERGY_FORMS_AND_CHANGES/common/view/EnergyChunkNode' );
  var EnergyType = require( 'ENERGY_FORMS_AND_CHANGES/common/model/EnergyType' );
  var HSlider = require( 'SUN/HSlider' );
  var Image = require( 'SCENERY/nodes/Image' );
  var inherit = require( 'PHET_CORE/inherit' );
  var LayoutBox = require( 'SCENERY/nodes/LayoutBox' );
  var ModelViewTransform2 = require( 'PHETCOMMON/view/ModelViewTransform2' );
  var Panel = require( 'SUN/Panel' );
  var PhetFont = require( 'SCENERY_PHET/PhetFont' );
  var Property = require( 'AXON/Property' );
  var Rectangle = require( 'SCENERY/nodes/Rectangle' );
  var ResetAllButton = require( 'SCENERY_PHET/buttons/ResetAllButton' );
  var ScreenView = require( 'JOIST/ScreenView' );
  var SunNode = require( 'ENERGY_FORMS_AND_CHANGES/energy-systems/view/SunNode' );
  var Text = require( 'SCENERY/nodes/Text' );
  var Vector2 = require( 'DOT/Vector2' );

  // Images
  var mockupImage = require( 'image!ENERGY_FORMS_AND_CHANGES/mockup_energy_systems.png' );

  // Strings
  var energySymbolsString = require( 'string!ENERGY_FORMS_AND_CHANGES/energySymbols' );

  // Constants
  var EDGE_INSET = 10;

  /**
   * @param {EnergySystemsModel} model
   * @constructor
   */
  function EnergySystemsScreenView( model ) {

    ScreenView.call( this, {
      layoutBounds: new Bounds2( 0, 0, 1008, 679 )
    } );

    var thisScreenView = this;

    // Create the model-view transform.  The primary units used in the model are
    // meters, so significant zoom is used. The multipliers for the 2nd parameter
    // can be used to adjust where the point (0, 0) in the model, which is on the
    // middle of the screen above the counter as located in the view.
    // Final arg is zoom factor - smaller zooms out, larger zooms in.
    var mvtOriginX = Math.round( thisScreenView.layoutBounds.width * 0.5 );
    var mvtOriginY = Math.round( thisScreenView.layoutBounds.height * 0.475 );
    var modelViewTransform = ModelViewTransform2.createSinglePointScaleInvertedYMapping(
      Vector2.ZERO, new Vector2( mvtOriginX, mvtOriginY ), 2200 );

    //Show the mock-up and a slider to change its transparency
    function addMockupImage() {
      var opacity = new Property( 0.8 );
      var image = new Image( mockupImage, {
        pickable: false
      } );
      image.scale( thisScreenView.layoutBounds.width / image.width );
      opacity.linkAttribute( image, 'opacity' );
      thisScreenView.addChild( image );
      thisScreenView.addChild( new HSlider( opacity, {
        min: 0,
        max: 1
      }, {
        top: 10,
        left: 10
      } ) );
    }

    // Create the legend for energy chunk types
    function addEnergyChunkLegend() {
      var legend = new EnergyChunkLegend();
      var x = 0.9 * thisScreenView.layoutBounds.width;
      var y = 0.5 * thisScreenView.layoutBounds.height;
      legend.center = new Vector2( x, y );
      thisScreenView.addChild( legend );
    }

    // Check box panel to display energy chunks
    function addCheckBoxPanel() {
      var label = new Text( energySymbolsString, {
        font: new PhetFont( 20 )
      } );

      var energyChunkNode = EnergyChunkNode.createEnergyChunkNode( EnergyType.THERMAL );
      energyChunkNode.scale( 1.0 );
      energyChunkNode.pickable = false;

      var checkBox = new CheckBox( new LayoutBox( {
        children: [ label, energyChunkNode ],
        orientation: 'horizontal',
        spacing: 5
      } ), model.energyChunksVisibleProperty );

      var panel = new Panel( checkBox, {
        fill: EFACConstants.CONTROL_PANEL_BACKGROUND_COLOR,
        stroke: EFACConstants.CONTROL_PANEL_OUTLINE_STROKE,
        lineWidth: EFACConstants.CONTROL_PANEL_OUTLINE_LINE_WIDTH
      } );
      panel.rightTop = new Vector2( thisScreenView.layoutBounds.width - EDGE_INSET, EDGE_INSET );
      thisScreenView.addChild( panel );
    }

    // Create and add the Reset All Button in the bottom right, which resets the model
    function addResetButton() {
      var resetAllButton = new ResetAllButton( {
        listener: function() {
          model.reset();
        },
        right: thisScreenView.layoutBounds.maxX - 10,
        bottom: thisScreenView.layoutBounds.maxY - 10
      } );
      thisScreenView.addChild( resetAllButton );
    }

    function addSun() {
      var sun = new SunNode( model.sun, model.energyChunksVisibleProperty, modelViewTransform );
      thisScreenView.addChild( sun );
    }

    function addPlayControls() {

      // Create a background rectangle for the play/pause controls.
      var bounds = thisScreenView.layoutBounds;
      var w = bounds.width;
      var h = bounds.height;
      var x = bounds.width / 2 - w / 2;
      var y = bounds.maxY - 114; // Offset chosen to match mockup image

      var bottomPanel = new Rectangle( x, y, w, h, 0, 0, {
        fill: EFACConstants.CLOCK_CONTROL_BACKGROUND_COLOR,
        stroke: 'black'
      } );
      thisScreenView.addChild( bottomPanel );
    }

    // Create the carousel control nodes.
    function addCarousels() {
      var sourcesCarousel = new EnergySystemElementSelector( model.energySourcesCarousel );
      // var convertersCarousel = new EnergySystemElementSelector( model.energyConvertersCarousel );
      // var usersCarousel = new EnergySystemElementSelector( model.energyUsersCarousel );

      thisScreenView.addChild( sourcesCarousel );
      // thisScreenView.addChild( convertersCarousel );
      // thisScreenView.addChild( usersCarousel );
    }

    // Add beige background rectangle
    this.addChild( new Rectangle( this.layoutBounds, {
      fill: EFACConstants.SECOND_TAB_BACKGROUND_COLOR
    } ) );

    addPlayControls();
    addMockupImage();
    addEnergyChunkLegend();
    addCheckBoxPanel();
    addResetButton();
    addSun();
    addCarousels();
  }

  energyFormsAndChanges.register( 'EnergySystemsScreenView', EnergySystemsScreenView );

  return inherit( ScreenView, EnergySystemsScreenView );
} );
<commit_msg>Reorganization and cleanup<commit_after>// Copyright 2014-2015, University of Colorado Boulder

/**
 * View for the 'Energy Systems' screen of the Energy Forms And Changes simulation.
 *
 * @author  John Blanco
 * @author  Martin Veillette (Berea College)
 * @author  Jesse Greenberg
 * @author  Andrew Adare
 */
define( function( require ) {
  'use strict';

  // Modules
  var Bounds2 = require( 'DOT/Bounds2' );
  var CheckBox = require( 'SUN/CheckBox' );
  var EFACConstants = require( 'ENERGY_FORMS_AND_CHANGES/common/EFACConstants' );
  var EnergyChunkLegend = require( 'ENERGY_FORMS_AND_CHANGES/energy-systems/view/EnergyChunkLegend' );
  var energyFormsAndChanges = require( 'ENERGY_FORMS_AND_CHANGES/energyFormsAndChanges' );
  var EnergySystemElementSelector = require( 'ENERGY_FORMS_AND_CHANGES/energy-systems/view/EnergySystemElementSelector' );
  var EnergyChunkNode = require( 'ENERGY_FORMS_AND_CHANGES/common/view/EnergyChunkNode' );
  var EnergyType = require( 'ENERGY_FORMS_AND_CHANGES/common/model/EnergyType' );
  var HSlider = require( 'SUN/HSlider' );
  var Image = require( 'SCENERY/nodes/Image' );
  var inherit = require( 'PHET_CORE/inherit' );
  var LayoutBox = require( 'SCENERY/nodes/LayoutBox' );
  var ModelViewTransform2 = require( 'PHETCOMMON/view/ModelViewTransform2' );
  var Node = require( 'SCENERY/nodes/Node' );
  var Panel = require( 'SUN/Panel' );
  var PhetFont = require( 'SCENERY_PHET/PhetFont' );
  var Property = require( 'AXON/Property' );
  var Rectangle = require( 'SCENERY/nodes/Rectangle' );
  var ResetAllButton = require( 'SCENERY_PHET/buttons/ResetAllButton' );
  var ScreenView = require( 'JOIST/ScreenView' );
  var SunNode = require( 'ENERGY_FORMS_AND_CHANGES/energy-systems/view/SunNode' );
  var Text = require( 'SCENERY/nodes/Text' );
  var Vector2 = require( 'DOT/Vector2' );

  // Images
  var mockupImage = require( 'image!ENERGY_FORMS_AND_CHANGES/mockup_energy_systems.png' );

  // Strings
  var energySymbolsString = require( 'string!ENERGY_FORMS_AND_CHANGES/energySymbols' );

  // Constants
  var EDGE_INSET = 10;

  /**
   * @param {EnergySystemsModel} model
   * @constructor
   */
  function EnergySystemsScreenView( model ) {

    ScreenView.call( this, {
      layoutBounds: new Bounds2( 0, 0, 1008, 679 )
    } );

    // Bounds2 object for use as primary geometric reference
    var stage = this.layoutBounds;

    // Node for back-most layer
    var backLayer = new Node();
    this.addChild( backLayer );

    // ScreenView handle for use inside functions
    var thisScreenView = this;

    // Create the model-view transform.  The primary units used in the model are
    // meters, so significant zoom is used. The multipliers for the 2nd parameter
    // can be used to adjust where the point (0, 0) in the model, which is on the
    // middle of the screen above the counter as located in the view.
    // Final arg is zoom factor - smaller zooms out, larger zooms in.
    var mvtOriginX = Math.round( stage.width * 0.5 );
    var mvtOriginY = Math.round( stage.height * 0.475 );
    var modelViewTransform = ModelViewTransform2.createSinglePointScaleInvertedYMapping(
      Vector2.ZERO, new Vector2( mvtOriginX, mvtOriginY ), 2200 );

    // Add beige background rectangle
    function addBackground() {
      backLayer.addChild( new Rectangle( stage, {
        fill: EFACConstants.SECOND_TAB_BACKGROUND_COLOR
      } ) );
    }

    // Create a background rectangle for the play/pause controls.
    function addPlayControls() {
      var bottomPanel = new Rectangle( 0, stage.maxY - 114, stage.width, stage.height, 0, 0, {
        fill: EFACConstants.CLOCK_CONTROL_BACKGROUND_COLOR,
        stroke: 'black'
      } );
      backLayer.addChild( bottomPanel );
    }

    //Show the mock-up and a slider to change its transparency
    function addMockupImage() {
      var opacity = new Property( 0.8 );
      var image = new Image( mockupImage, {
        pickable: false
      } );
      image.scale( stage.width / image.width );
      opacity.linkAttribute( image, 'opacity' );
      thisScreenView.addChild( image );
      thisScreenView.addChild( new HSlider( opacity, {
        min: 0,
        max: 1
      }, {
        top: 10,
        left: 10
      } ) );
    }

    // Create the legend for energy chunk types
    function addEnergyChunkLegend() {
      var legend = new EnergyChunkLegend();
      legend.center = new Vector2( 0.9 * stage.width;, 0.5 * stage.height );
      thisScreenView.addChild( legend );
    }

    // Check box panel to display energy chunks
    function addCheckBoxPanel() {
      var label = new Text( energySymbolsString, {
        font: new PhetFont( 20 )
      } );

      var energyChunkNode = EnergyChunkNode.createEnergyChunkNode( EnergyType.THERMAL );
      energyChunkNode.scale( 1.0 );
      energyChunkNode.pickable = false;

      var checkBox = new CheckBox( new LayoutBox( {
        children: [ label, energyChunkNode ],
        orientation: 'horizontal',
        spacing: 5
      } ), model.energyChunksVisibleProperty );

      var panel = new Panel( checkBox, {
        fill: EFACConstants.CONTROL_PANEL_BACKGROUND_COLOR,
        stroke: EFACConstants.CONTROL_PANEL_OUTLINE_STROKE,
        lineWidth: EFACConstants.CONTROL_PANEL_OUTLINE_LINE_WIDTH
      } );
      panel.rightTop = new Vector2( stage.width - EDGE_INSET, EDGE_INSET );
      thisScreenView.addChild( panel );
    }

    // Create and add the Reset All Button in the bottom right, which resets the model
    function addResetButton() {
      var resetAllButton = new ResetAllButton( {
        listener: function() {
          model.reset();
        },
        right: stage.maxX - 10,
        bottom: stage.maxY - 10
      } );
      thisScreenView.addChild( resetAllButton );
    }

    function addSun() {
      var sun = new SunNode( model.sun, model.energyChunksVisibleProperty, modelViewTransform );
      thisScreenView.addChild( sun );
    }

    // Create the carousel control nodes.
    function addCarousels() {
      var sourcesCarousel = new EnergySystemElementSelector( model.energySourcesCarousel );
      // var convertersCarousel = new EnergySystemElementSelector( model.energyConvertersCarousel );
      // var usersCarousel = new EnergySystemElementSelector( model.energyUsersCarousel );

      thisScreenView.addChild( sourcesCarousel );
      // thisScreenView.addChild( convertersCarousel );
      // thisScreenView.addChild( usersCarousel );
    }

    addBackground();
    addPlayControls();
    addMockupImage();
    addEnergyChunkLegend();
    addCheckBoxPanel();
    addResetButton();
    addSun();
    addCarousels();
  }

  energyFormsAndChanges.register( 'EnergySystemsScreenView', EnergySystemsScreenView );

  return inherit( ScreenView, EnergySystemsScreenView );
} );
<|endoftext|>


<commit_before>Clazz.load (["java.io.Serializable", "java.lang.Comparable"], "java.lang.Enum", ["java.lang.ClassCastException", "$.CloneNotSupportedException", "$.IllegalArgumentException", "$.NullPointerException"], function () {
c$ = java.lang.Enum = Enum = function () {
this.$name = null;
this.$ordinal = 0;
Clazz.instantialize (this, arguments);
};
Clazz.decorateAsType (c$, "Enum", null, [Comparable, java.io.Serializable]);
Clazz.defineMethod (c$, "name",
function () {
return this.$name;
});
Clazz.defineMethod (c$, "ordinal",
function () {
return this.$ordinal;
});
Clazz.makeConstructor (c$,
function (name, ordinal) {
this.$name = name;
this.$ordinal = ordinal;
}, "String, Number");
Clazz.defineMethod (c$, "toString",
function () {
return this.$name;
});
Clazz.defineMethod (c$, "equals",
function (other) {
return this == other;
}, "Object");
Clazz.defineMethod (c$, "hashCode",
function () {
return System.identityHashCode (this);
});
Clazz.defineMethod (c$, "clone",
function () {
throw  new CloneNotSupportedException ();
});
Clazz.defineMethod (c$, "compareTo",
function (o) {
var other = o;
var self = this;
if (self.getClass () != other.getClass () && self.getDeclaringClass () != other.getDeclaringClass ()) throw  new ClassCastException ();
return self.ordinal - other.ordinal;
}, "E");
Clazz.defineMethod (c$, "getDeclaringClass",
function () {
var clazz = this.getClass ();
var zuper = clazz.getSuperclass ();
return (zuper == Enum) ? clazz : zuper;
});
Clazz.defineMethod (Enum, "$valueOf",
function (enumType, name) {
	return enumType.$valueOf (name);
}, "Object, String"); /* "Class, String" */
Clazz.defineMethod (Enum, "$valueOf",
function (name) {
if (name == null) throw  new NullPointerException ("Name is null");
var vals = this.values ();
for (var i = 0; i < vals.length; i++) {
	if (name == vals[i].name ()) {
		return vals[i];
	}
}
throw  new IllegalArgumentException ("No enum const " + enumType + "." + name);
}, "String");
Enum.$valueOf = Enum.prototype.$valueOf;
Clazz.defineMethod (Enum, "values",
function () {
	if (this.$ALL$ENUMS != null) {
		return this.$ALL$ENUMS;
	}
	this.$ALL$ENUMS = new Array ();
	var clazzThis = this.getClass ();
	for (var e in clazzThis) {
		if (clazzThis[e] != null && clazzThis[e].__CLASS_NAME__ != null
				&& e != "prototype"
				&& Clazz.instanceOf (clazzThis[e], clazzThis)) {
			this.$ALL$ENUMS[this.$ALL$ENUMS.length] = clazzThis[e];
		}
	}
	return this.$ALL$ENUMS;
});
Enum.values = Enum.prototype.values;
});<commit_msg>fix part of bug 1272 testcases test_compareToLjava_lang_Enum and test_valueOfLjava_lang_String in EnumTest will failed<commit_after>Clazz.load (["java.io.Serializable", "java.lang.Comparable"], "java.lang.Enum", ["java.lang.ClassCastException", "$.CloneNotSupportedException", "$.IllegalArgumentException", "$.NullPointerException"], function () {
c$ = java.lang.Enum = Enum = function () {
this.$name = null;
this.$ordinal = 0;
Clazz.instantialize (this, arguments);
};
Clazz.decorateAsType (c$, "Enum", null, [Comparable, java.io.Serializable]);
Clazz.defineMethod (c$, "name",
function () {
return this.$name;
});
Clazz.defineMethod (c$, "ordinal",
function () {
return this.$ordinal;
});
Clazz.makeConstructor (c$,
function (name, ordinal) {
this.$name = name;
this.$ordinal = ordinal;
}, "String, Number");
Clazz.defineMethod (c$, "toString",
function () {
return this.$name;
});
Clazz.defineMethod (c$, "equals",
function (other) {
return this == other;
}, "Object");
Clazz.defineMethod (c$, "hashCode",
function () {
return System.identityHashCode (this);
});
Clazz.defineMethod (c$, "clone",
function () {
throw  new CloneNotSupportedException ();
});
Clazz.defineMethod (c$, "compareTo",
function (o) {
if (o == null) {
    throw new NullPointerException ();
}
var other = o;
var self = this;
if (self.getClass () != other.getClass () && self.getDeclaringClass () != other.getDeclaringClass ()) throw  new ClassCastException ();
return self.$ordinal - other.$ordinal;
}, "E");
Clazz.defineMethod (c$, "getDeclaringClass",
function () {
var clazz = this.getClass ();
var zuper = clazz.getSuperclass ();
return (zuper == Enum) ? clazz : zuper;
});
Clazz.defineMethod (Enum, "$valueOf",
function (enumType, name) {
	return enumType.$valueOf (name);
}, "Object, String"); /* "Class, String" */
Clazz.defineMethod (Enum, "$valueOf",
function (name) {
if (name == null) throw  new NullPointerException ("Name is null");
var vals = this.values ();
for (var i = 0; i < vals.length; i++) {
	if (name == vals[i].name ()) {
		return vals[i];
	}
}
throw  new IllegalArgumentException ("No enum const " + this.__CLASS_NAME__ + "." + name);
}, "String");
Enum.$valueOf = Enum.prototype.$valueOf;
Clazz.defineMethod (Enum, "values",
function () {
	if (this.$ALL$ENUMS != null) {
		return this.$ALL$ENUMS;
	}
	this.$ALL$ENUMS = new Array ();
	var clazzThis = this.getClass ();
	for (var e in clazzThis) {
		if (clazzThis[e] != null && clazzThis[e].__CLASS_NAME__ != null
				&& e != "prototype"
				&& Clazz.instanceOf (clazzThis[e], clazzThis)) {
			this.$ALL$ENUMS[this.$ALL$ENUMS.length] = clazzThis[e];
		}
	}
	return this.$ALL$ENUMS;
});
Enum.values = Enum.prototype.values;
});<|endoftext|>


<commit_before>(function (global, factory) {
    if (typeof define === "function" && define.amd) {
        define(['exports', 'react', 'react-dom', './lib/ScriptCache', './lib/GoogleApi'], factory);
    } else if (typeof exports !== "undefined") {
        factory(exports, require('react'), require('react-dom'), require('./lib/ScriptCache'), require('./lib/GoogleApi'));
    } else {
        var mod = {
            exports: {}
        };
        factory(mod.exports, global.react, global.reactDom, global.ScriptCache, global.GoogleApi);
        global.GoogleApiComponent = mod.exports;
    }
})(this, function (exports, _react, _reactDom, _ScriptCache, _GoogleApi) {
    'use strict';

    Object.defineProperty(exports, "__esModule", {
        value: true
    });
    exports.wrapper = undefined;

    var _react2 = _interopRequireDefault(_react);

    var _reactDom2 = _interopRequireDefault(_reactDom);

    var _GoogleApi2 = _interopRequireDefault(_GoogleApi);

    function _interopRequireDefault(obj) {
        return obj && obj.__esModule ? obj : {
            default: obj
        };
    }

    function _classCallCheck(instance, Constructor) {
        if (!(instance instanceof Constructor)) {
            throw new TypeError("Cannot call a class as a function");
        }
    }

    var _createClass = function () {
        function defineProperties(target, props) {
            for (var i = 0; i < props.length; i++) {
                var descriptor = props[i];
                descriptor.enumerable = descriptor.enumerable || false;
                descriptor.configurable = true;
                if ("value" in descriptor) descriptor.writable = true;
                Object.defineProperty(target, descriptor.key, descriptor);
            }
        }

        return function (Constructor, protoProps, staticProps) {
            if (protoProps) defineProperties(Constructor.prototype, protoProps);
            if (staticProps) defineProperties(Constructor, staticProps);
            return Constructor;
        };
    }();

    function _possibleConstructorReturn(self, call) {
        if (!self) {
            throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
        }

        return call && (typeof call === "object" || typeof call === "function") ? call : self;
    }

    function _inherits(subClass, superClass) {
        if (typeof superClass !== "function" && superClass !== null) {
            throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
        }

        subClass.prototype = Object.create(superClass && superClass.prototype, {
            constructor: {
                value: subClass,
                enumerable: false,
                writable: true,
                configurable: true
            }
        });
        if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
    }

    var defaultMapConfig = {};
    var defaultCreateCache = function defaultCreateCache(options) {
        options = options || {};
        var apiKey = options.apiKey;
        var libraries = options.libraries || ['places'];
        var version = options.version || '3.24';
        var language = options.language || 'en';

        return (0, _ScriptCache.ScriptCache)({
            google: (0, _GoogleApi2.default)({
                apiKey: apiKey,
                language: language,
                libraries: libraries,
                version: version
            })
        });
    };

    var wrapper = exports.wrapper = function wrapper(options) {
        return function (WrappedComponent) {
            var apiKey = options.apiKey;
            var libraries = options.libraries || ['places'];
            var version = options.version || '3';
            var createCache = options.createCache || defaultCreateCache;

            var Wrapper = function (_React$Component) {
                _inherits(Wrapper, _React$Component);

                function Wrapper(props, context) {
                    _classCallCheck(this, Wrapper);

                    var _this = _possibleConstructorReturn(this, (Wrapper.__proto__ || Object.getPrototypeOf(Wrapper)).call(this, props, context));

                    _this.scriptCache = createCache(options);
                    _this.scriptCache.google.onLoad(_this.onLoad.bind(_this));

                    _this.state = {
                        loaded: false,
                        map: null,
                        google: null
                    };
                    return _this;
                }

                _createClass(Wrapper, [{
                    key: 'onLoad',
                    value: function onLoad(err, tag) {
                        this._gapi = window.google;

                        this.setState({ loaded: true, google: this._gapi });
                    }
                }, {
                    key: 'render',
                    value: function render() {
                        var props = Object.assign({}, this.props, {
                            loaded: this.state.loaded,
                            google: window.google
                        });

                        return _react2.default.createElement(
                            'div',
                            null,
                            _react2.default.createElement(WrappedComponent, props),
                            _react2.default.createElement('div', { ref: 'map' })
                        );
                    }
                }]);

                return Wrapper;
            }(_react2.default.Component);

            return Wrapper;
        };
    };

    exports.default = wrapper;
});<commit_msg>Update GoogleApiComponent.js<commit_after>(function (global, factory) {
    if (typeof define === "function" && define.amd) {
        define(['exports', 'react', 'react-dom', './lib/ScriptCache', './lib/GoogleApi'], factory);
    } else if (typeof exports !== "undefined") {
        factory(exports, require('react'), require('react-dom'), require('./lib/ScriptCache'), require('./lib/GoogleApi'));
    } else {
        var mod = {
            exports: {}
        };
        factory(mod.exports, global.react, global.reactDom, global.ScriptCache, global.GoogleApi);
        global.GoogleApiComponent = mod.exports;
    }
})(this, function (exports, _react, _reactDom, _ScriptCache, _GoogleApi) {
    'use strict';

    Object.defineProperty(exports, "__esModule", {
        value: true
    });
    exports.wrapper = undefined;

    var _react2 = _interopRequireDefault(_react);

    var _reactDom2 = _interopRequireDefault(_reactDom);

    var _GoogleApi2 = _interopRequireDefault(_GoogleApi);

    function _interopRequireDefault(obj) {
        return obj && obj.__esModule ? obj : {
            default: obj
        };
    }

    function _classCallCheck(instance, Constructor) {
        if (!(instance instanceof Constructor)) {
            throw new TypeError("Cannot call a class as a function");
        }
    }

    var _createClass = function () {
        function defineProperties(target, props) {
            for (var i = 0; i < props.length; i++) {
                var descriptor = props[i];
                descriptor.enumerable = descriptor.enumerable || false;
                descriptor.configurable = true;
                if ("value" in descriptor) descriptor.writable = true;
                Object.defineProperty(target, descriptor.key, descriptor);
            }
        }

        return function (Constructor, protoProps, staticProps) {
            if (protoProps) defineProperties(Constructor.prototype, protoProps);
            if (staticProps) defineProperties(Constructor, staticProps);
            return Constructor;
        };
    }();

    function _possibleConstructorReturn(self, call) {
        if (!self) {
            throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
        }

        return call && (typeof call === "object" || typeof call === "function") ? call : self;
    }

    function _inherits(subClass, superClass) {
        if (typeof superClass !== "function" && superClass !== null) {
            throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
        }

        subClass.prototype = Object.create(superClass && superClass.prototype, {
            constructor: {
                value: subClass,
                enumerable: false,
                writable: true,
                configurable: true
            }
        });
        if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
    }

    var defaultMapConfig = {};
    var defaultCreateCache = function defaultCreateCache(options) {
        options = options || {};
        var apiKey = options.apiKey;
        var libraries = options.libraries || ['places'];
        var version = options.version || '3.28';
        var language = options.language || 'en';

        return (0, _ScriptCache.ScriptCache)({
            google: (0, _GoogleApi2.default)({
                apiKey: apiKey,
                language: language,
                libraries: libraries,
                version: version
            })
        });
    };

    var wrapper = exports.wrapper = function wrapper(options) {
        return function (WrappedComponent) {
            var apiKey = options.apiKey;
            var libraries = options.libraries || ['places'];
            var version = options.version || '3';
            var createCache = options.createCache || defaultCreateCache;

            var Wrapper = function (_React$Component) {
                _inherits(Wrapper, _React$Component);

                function Wrapper(props, context) {
                    _classCallCheck(this, Wrapper);

                    var _this = _possibleConstructorReturn(this, (Wrapper.__proto__ || Object.getPrototypeOf(Wrapper)).call(this, props, context));

                    _this.scriptCache = createCache(options);
                    _this.scriptCache.google.onLoad(_this.onLoad.bind(_this));

                    _this.state = {
                        loaded: false,
                        map: null,
                        google: null
                    };
                    return _this;
                }

                _createClass(Wrapper, [{
                    key: 'onLoad',
                    value: function onLoad(err, tag) {
                        this._gapi = window.google;

                        this.setState({ loaded: true, google: this._gapi });
                    }
                }, {
                    key: 'render',
                    value: function render() {
                        var props = Object.assign({}, this.props, {
                            loaded: this.state.loaded,
                            google: window.google
                        });

                        return _react2.default.createElement(
                            'div',
                            null,
                            _react2.default.createElement(WrappedComponent, props),
                            _react2.default.createElement('div', { ref: 'map' })
                        );
                    }
                }]);

                return Wrapper;
            }(_react2.default.Component);

            return Wrapper;
        };
    };

    exports.default = wrapper;
});
<|endoftext|>