<commit_before>(function () {
  "use strict";

  angular
    .module("mnDocuments")
    .controller("mnDocumentsEditingController", mnDocumentsEditingController);

  function mnDocumentsEditingController($scope, $state, $uibModal, mnDocumentsEditingService, mnPromiseHelper) {
    var vm = this;
    var editorOptions = {
      lineNumbers: true,
      matchBrackets: false,
      tabSize: 2,
      mode: {
        name: "javascript",
        json: true
      },
      theme: 'default',
      readOnly: 'nocursor',
      onLoad: codemirrorLoaded
    };
    vm.editorOptions = editorOptions;
    vm.isDeleteDisabled = isDeleteDisabled;
    vm.isSaveAsDisabled = isSaveAsDisabled;
    vm.isSaveDisabled = isSaveDisabled;
    vm.isEditorDisabled = isEditorDisabled;
    vm.areThereWarnings = areThereWarnings;
    vm.saveAsDialog = saveAsDialog;
    vm.deleteDocument = deleteDocument;
    vm.save = save;

    function save() {
      mnPromiseHelper(vm, mnDocumentsEditingService.createDocument($state.params, vm.state.doc))
        .cancelOnScopeDestroy($scope)
        .showSpinner()
        .catchErrors();
    }
    function codemirrorLoaded(cm) {
      activate().then(function (resp) {
        if (resp.doc) {
          cm.on("change", function (doc) {
            vm.isDocumentChanged = !documentIsNotChanged(doc.historySize());
            onDocValueUpdate(doc.getValue());
          });
        }
      });
    }
    function deleteDocument(documentId) {
      return $uibModal.open({
        controller: 'mnDocumentsDeleteDialogController as documentsDeleteDialogCtl',
        templateUrl: 'app/mn_admin/mn_documents/delete_dialog/mn_documents_delete_dialog.html',
        resolve: {
          documentId: function () {
            return vm.state.title;
          }
        }
      }).result.then(function () {
        $state.go("app.admin.documents.list");
      });
    }
    function saveAsDialog() {
      return $uibModal.open({
        controller: 'mnDocumentsCreateDialogController as documentsCreateDialogCtl',
        templateUrl: 'app/mn_admin/mn_documents/create_dialog/mn_documents_create_dialog.html',
        resolve: {
          doc: function () {
            return vm.state.doc;
          }
        }
      }).result.then(function (resp) {
        $state.go("app.admin.documents.editing", {
          documentId: resp.documentId
        });
      })
    }
    function documentIsNotChanged(history) {
      return history.redo == 0 && history.undo == 1;
    }
    function areThereWarnings() {
      return vm.state && _.chain(vm.state.editorWarnings).values().some().value();
    }
    function areThereErrors() {
      return !!vm.state.errors || areThereWarnings();
    }
    function isEditorDisabled() {
      return !vm.state ||
             (vm.state.editorWarnings &&
             (vm.state.editorWarnings.notFound ||
              vm.state.editorWarnings.documentIsBase64 ||
              vm.state.editorWarnings.documentLimitError));

    }
    function isDeleteDisabled() {
      return !vm.state ||
              vm.viewLoading ||
             (vm.state.editorWarnings && vm.state.editorWarnings.notFound);
    }
    function isSaveAsDisabled() {
      return !vm.state ||
              vm.viewLoading ||
              areThereErrors();
    }
    function isSaveDisabled() {
      return !vm.state ||
              vm.viewLoading ||
             !vm.isDocumentChanged ||
             areThereErrors();
    }
    function onDocValueUpdate(json) {
      vm.state.errors = null;
      vm.state.editorWarnings = {
        documentLimitError: mnDocumentsEditingService.isJsonOverLimited(json)
      };

      if (!vm.state.editorWarnings.documentLimitError) {
        try {
          var parsedJSON = JSON.parse(json);
        } catch (error) {
          vm.state.errors = {
            reason: error.message,
            error: "Invalid document"
          };
          return false;
        }
        vm.state.editorWarnings["shouldNotBeNull"] = _.isNull(parsedJSON);
        vm.state.editorWarnings["shouldBeAnObject"] = !_.isObject(parsedJSON);
        vm.state.editorWarnings["shouldNotBeAnArray"] = _.isArray(parsedJSON);
      }

      return areThereWarnings() ? false : parsedJSON;
    }
    function activate() {
      $scope.$watch(isEditorDisabled, function (isDisabled) {
        editorOptions.readOnly = isDisabled ? 'nocursor' : false;
        editorOptions.matchBrackets = !isDisabled;
        vm.editorOptions = editorOptions;
      });
      return mnPromiseHelper(vm, mnDocumentsEditingService.getDocumentsEditingState($state.params))
        .applyToScope("state")
        .cancelOnScopeDestroy($scope)
        .getPromise();
    }
  }
})();
<commit_msg>MB-16953: disable save button after saving the document<commit_after>(function () {
  "use strict";

  angular
    .module("mnDocuments")
    .controller("mnDocumentsEditingController", mnDocumentsEditingController);

  function mnDocumentsEditingController($scope, $state, $uibModal, mnDocumentsEditingService, mnPromiseHelper) {
    var vm = this;
    var editorOptions = {
      lineNumbers: true,
      matchBrackets: false,
      tabSize: 2,
      mode: {
        name: "javascript",
        json: true
      },
      theme: 'default',
      readOnly: 'nocursor',
      onLoad: codemirrorLoaded
    };
    vm.editorOptions = editorOptions;
    vm.isDeleteDisabled = isDeleteDisabled;
    vm.isSaveAsDisabled = isSaveAsDisabled;
    vm.isSaveDisabled = isSaveDisabled;
    vm.isEditorDisabled = isEditorDisabled;
    vm.areThereWarnings = areThereWarnings;
    vm.saveAsDialog = saveAsDialog;
    vm.deleteDocument = deleteDocument;
    vm.save = save;

    function save() {
      mnPromiseHelper(vm, mnDocumentsEditingService.createDocument($state.params, vm.state.doc))
        .cancelOnScopeDestroy($scope)
        .showSpinner()
        .catchErrors()
        .onSuccess(function () {
          vm.isDocumentChanged = false;
        });
    }
    function codemirrorLoaded(cm) {
      activate().then(function (resp) {
        if (resp.doc) {
          cm.on("change", function (doc) {
            vm.isDocumentChanged = !documentIsNotChanged(doc.historySize());
            onDocValueUpdate(doc.getValue());
          });
        }
      });
    }
    function deleteDocument(documentId) {
      return $uibModal.open({
        controller: 'mnDocumentsDeleteDialogController as documentsDeleteDialogCtl',
        templateUrl: 'app/mn_admin/mn_documents/delete_dialog/mn_documents_delete_dialog.html',
        resolve: {
          documentId: function () {
            return vm.state.title;
          }
        }
      }).result.then(function () {
        $state.go("app.admin.documents.list");
      });
    }
    function saveAsDialog() {
      return $uibModal.open({
        controller: 'mnDocumentsCreateDialogController as documentsCreateDialogCtl',
        templateUrl: 'app/mn_admin/mn_documents/create_dialog/mn_documents_create_dialog.html',
        resolve: {
          doc: function () {
            return vm.state.doc;
          }
        }
      }).result.then(function (resp) {
        $state.go("app.admin.documents.editing", {
          documentId: resp.documentId
        });
      })
    }
    function documentIsNotChanged(history) {
      return history.redo == 0 && history.undo == 1;
    }
    function areThereWarnings() {
      return vm.state && _.chain(vm.state.editorWarnings).values().some().value();
    }
    function areThereErrors() {
      return !!vm.state.errors || areThereWarnings();
    }
    function isEditorDisabled() {
      return !vm.state ||
             (vm.state.editorWarnings &&
             (vm.state.editorWarnings.notFound ||
              vm.state.editorWarnings.documentIsBase64 ||
              vm.state.editorWarnings.documentLimitError));

    }
    function isDeleteDisabled() {
      return !vm.state ||
              vm.viewLoading ||
             (vm.state.editorWarnings && vm.state.editorWarnings.notFound);
    }
    function isSaveAsDisabled() {
      return !vm.state ||
              vm.viewLoading ||
              areThereErrors();
    }
    function isSaveDisabled() {
      return !vm.state ||
              vm.viewLoading ||
             !vm.isDocumentChanged ||
             areThereErrors();
    }
    function onDocValueUpdate(json) {
      vm.state.errors = null;
      vm.state.editorWarnings = {
        documentLimitError: mnDocumentsEditingService.isJsonOverLimited(json)
      };

      if (!vm.state.editorWarnings.documentLimitError) {
        try {
          var parsedJSON = JSON.parse(json);
        } catch (error) {
          vm.state.errors = {
            reason: error.message,
            error: "Invalid document"
          };
          return false;
        }
        vm.state.editorWarnings["shouldNotBeNull"] = _.isNull(parsedJSON);
        vm.state.editorWarnings["shouldBeAnObject"] = !_.isObject(parsedJSON);
        vm.state.editorWarnings["shouldNotBeAnArray"] = _.isArray(parsedJSON);
      }

      return areThereWarnings() ? false : parsedJSON;
    }
    function activate() {
      $scope.$watch(isEditorDisabled, function (isDisabled) {
        editorOptions.readOnly = isDisabled ? 'nocursor' : false;
        editorOptions.matchBrackets = !isDisabled;
        vm.editorOptions = editorOptions;
      });
      return mnPromiseHelper(vm, mnDocumentsEditingService.getDocumentsEditingState($state.params))
        .applyToScope("state")
        .cancelOnScopeDestroy($scope)
        .getPromise();
    }
  }
})();
<|endoftext|>


<commit_before>import { SpriteWidth, SpriteHeight, SpriteRatioX, SpriteRatioY, Bounds } from "../Constants.js";
import { Wall } from "../SpriteConstants";

const MaxX = 1;
const MaxY = 0;

class Room extends Phaser.Group {

  constructor(game, parent, name) {
    super(game, parent, name, false, false, Phaser.Physics.ARCADE);
  }

  createRandomLine(x1, y1, x2, y2, division = 1, varX = 0, varY = 0) {
    const middleX = (x1 + x2) / 2 + (varX * SpriteWidth);
    const middleY = (y1 + y2) / 2 + (varY * SpriteHeight);

    const middleXBefore = middleX - (middleX % SpriteWidth);
    const middleXAfter =  middleX + (middleX % SpriteWidth);
    const middleYBefore = middleY - (middleY % SpriteHeight);
    const middleYAfter = middleY + (middleY % SpriteHeight);
    if(division > 1) {
      this.createRandomLine(x1, y1, middleXBefore, middleYBefore, division - 1, varX, varY);
      this.createRandomLine(middleXAfter, middleYAfter, x2, y2, division - 1, varX, varY);
    } else {
      this.createLine(x1,y1, middleXBefore, middleYBefore);
      this.createLine(middleXAfter, middleYAfter, x2, y2);
    }
  }

  createLineByTile(x1, y1, nbTilesX, nbTilesY, division, varX, varY) {
    if(nbTilesX < 0 ) {
      throw `createLineByTile ${nbTilesX} is negative`;
    }
    if(nbTilesY < 0 ) {
      throw `createLineByTile ${nbTilesY} is negative`;
    }
    this.createRandomLine(x1, y1, (nbTilesX-1) * SpriteWidth + x1 , (nbTilesY-1) * SpriteHeight + y1, division, varX, varY);
  }

  // //Brasenhem algorithm
  createLine(x1,y1, x2, y2) {
    const dx = Math.abs(x2 - x1);
    const sx = x1 < x2 ? SpriteWidth : -SpriteWidth;
    const dy = Math.abs(y2 - y1);
    const sy = y1 < y2 ? SpriteHeight : -SpriteHeight;
    var err = (dx > dy ? dx : -dy) / 2;

    let x = x1;
    let y = y1;
    while (true) {
      this.createSprite(x,y);
      if (x >= x2 && y >= y2) break;
      if(x < 0 || y < 0 || x > Bounds || y > Bounds) break;
      let e2 = err;
      if (e2 > - dx) {
        err -= dy;
        x += sx;
      }
      if (e2 < dy) {
        err += dx;
        y += sy;
      }
    }
  }

  createSprite(x,y) {
    let sprite = this.create(x, y, Wall);
    sprite.scale.setTo(SpriteRatioX, SpriteRatioY);
  }

  ////
  // (x,y) ####
  //       #  #
  //       #  #
  //       #  #
  //       ####
  //
  ///
  createSquare(x, y, nbTilesBySide) {
    this.createRandomSquare(x, y, nbTilesBySide, 1, 0, 0);
  }

  // const division = 3;
  // const varX = -1;
  // const varY = 1;
  createRandomSquare(x, y, nbTilesBySide, division = 3, varX = -1, varY = 1) {
    this.createLineByTile(x, y, nbTilesBySide, 1, division, varX, varY);
    this.createLineByTile(x, y + (nbTilesBySide-1) * SpriteHeight, nbTilesBySide, 1, division, varX, varY);

    //nbtiles - 2 because corner  was drawn  by vertical line
    this.createLineByTile(x, y + SpriteHeight, 1, nbTilesBySide - 2, division, varX, varY);
    this.createLineByTile(x + (nbTilesBySide-1) * SpriteWidth, y + SpriteHeight, 1, nbTilesBySide - 2, division, varX, varY);
  }
}

export default Room;<commit_msg>make sprite immovable<commit_after>import { SpriteWidth, SpriteHeight, SpriteRatioX, SpriteRatioY, Bounds } from "../Constants.js";
import { Wall } from "../SpriteConstants";

const MaxX = 1;
const MaxY = 0;

class Room extends Phaser.Group {

  constructor(game, parent, name) {
    super(game, parent, name, false, true, Phaser.Physics.ARCADE);
  }

  createRandomLine(x1, y1, x2, y2, division = 1, varX = 0, varY = 0) {
    const middleX = (x1 + x2) / 2 + (varX * SpriteWidth);
    const middleY = (y1 + y2) / 2 + (varY * SpriteHeight);

    const middleXBefore = middleX - (middleX % SpriteWidth);
    const middleXAfter =  middleX + (middleX % SpriteWidth);
    const middleYBefore = middleY - (middleY % SpriteHeight);
    const middleYAfter = middleY + (middleY % SpriteHeight);
    if(division > 1) {
      this.createRandomLine(x1, y1, middleXBefore, middleYBefore, division - 1, varX, varY);
      this.createRandomLine(middleXAfter, middleYAfter, x2, y2, division - 1, varX, varY);
    } else {
      this.createLine(x1,y1, middleXBefore, middleYBefore);
      this.createLine(middleXAfter, middleYAfter, x2, y2);
    }
  }

  createLineByTile(x1, y1, nbTilesX, nbTilesY, division, varX, varY) {
    if(nbTilesX < 0 ) {
      throw `createLineByTile ${nbTilesX} is negative`;
    }
    if(nbTilesY < 0 ) {
      throw `createLineByTile ${nbTilesY} is negative`;
    }
    this.createRandomLine(x1, y1, (nbTilesX-1) * SpriteWidth + x1 , (nbTilesY-1) * SpriteHeight + y1, division, varX, varY);
  }

  // //Brasenhem algorithm
  createLine(x1,y1, x2, y2) {
    const dx = Math.abs(x2 - x1);
    const sx = x1 < x2 ? SpriteWidth : -SpriteWidth;
    const dy = Math.abs(y2 - y1);
    const sy = y1 < y2 ? SpriteHeight : -SpriteHeight;
    var err = (dx > dy ? dx : -dy) / 2;

    let x = x1;
    let y = y1;
    while (true) {
      this.createSprite(x,y);
      if (x >= x2 && y >= y2) break;
      if(x < 0 || y < 0 || x > Bounds || y > Bounds) break;
      let e2 = err;
      if (e2 > - dx) {
        err -= dy;
        x += sx;
      }
      if (e2 < dy) {
        err += dx;
        y += sy;
      }
    }
  }

  createSprite(x,y) {
    let sprite = this.create(x, y, Wall);
    sprite.scale.setTo(SpriteRatioX, SpriteRatioY);
    sprite.body.immovable = true;
  }

  ////
  // (x,y) ####
  //       #  #
  //       #  #
  //       #  #
  //       ####
  //
  ///
  createSquare(x, y, nbTilesBySide) {
    this.createRandomSquare(x, y, nbTilesBySide, 1, 0, 0);
  }

  // const division = 3;
  // const varX = -1;
  // const varY = 1;
  createRandomSquare(x, y, nbTilesBySide, division = 3, varX = -1, varY = 1) {
    this.createLineByTile(x, y, nbTilesBySide, 1, division, varX, varY);
    this.createLineByTile(x, y + (nbTilesBySide-1) * SpriteHeight, nbTilesBySide, 1, division, varX, varY);

    //nbtiles - 2 because corner  was drawn  by vertical line
    this.createLineByTile(x, y + SpriteHeight, 1, nbTilesBySide - 2, division, varX, varY);
    this.createLineByTile(x + (nbTilesBySide-1) * SpriteWidth, y + SpriteHeight, 1, nbTilesBySide - 2, division, varX, varY);
  }
}

export default Room;<|endoftext|>


<commit_before>/*
---

script: Script/Interpolation.js

description: Tools to find and evaluate interpolated strings in text content and attributes

license: Public domain (http://unlicense.org).

authors: Yaroslaff Fedin

requires:
  - LSD.Script.Function
  - LSD.Script.Scope

provides:
  - LSD.Script.Interpolation

...
*/

LSD.Script.Interpolation = function(object, source) {
  if (object.nodeType) {
    if (object.nodeType == 3)
      return LSD.Script.Interpolation.Textnode(object, source)
  } else if (Type.isEnumerable(object)) {
    for (var i = 0, attribute; attribute = object[i++];)
      LSD.Script.Interpolation.Attribute(attribute.name, attribute.value, source, attribute)
  } else if (type.toObject) {
    for (var name in type) {
      if (type.hasProperty(type))
        LSD.Script.Interpolation.Attribute(name, type[name], source)
    }
  }
};

LSD.Script.Interpolation.Attribute = function(name, value, source, attribute, forgiving) {
  var count = 0, last = 0, index, args;
  var regex = forgiving ? LSD.Layout.Interpolation.rForgivingBoundaries : LSD.Script.Interpolation.rBoundaries;
  for (var match, compiled; match = regex.exec(value);) {
    index = match.index;
    if (!args) args = [];
    if (index > last) args.push(value.substring(last, index));
    if (match[2] == "}") {
      args.push(LSD.Script({
        input: match[1],
        source: source,
        placeholder: match[0]
      }));
    }
    last = index + match[0].length;
  }
  if (args && last < value.length) args.push(value.substring(last, value.length));
  if (args) {
    if (!attribute) attribute = source.getAttributeNode(name);
    return new LSD.Script.Function(args, source, attribute, 'concat')
  }
};

LSD.Script.Interpolation.Textnode = function(node, source, forgiving) {
  var content = node.textContent, finder, length = content.length;
  var regex = forgiving ? LSD.Layout.Interpolation.rForgivingBoundaries : LSD.Script.Interpolation.rBoundaries;
  for (var match, index, last, next, compiled; match = regex.exec(content);) {
    last = index || 0
    var index = match.index + match[0].length;
    expression = node;
    var cut = index - last;
    if (cut < node.textContent.length) node = node.splitText(index - last);
    if ((cut = (match.index - last))) expression = expression.splitText(cut);
    compiled = LSD.Script({
      input: match[1],
      source: source,
      output: expression,
      placeholder: match[0]
    });
    Element.store(expression, 'interpolation', compiled);
    last = index;
  }
}
// Find {interpolated} expressions in a string
LSD.Script.Interpolation.rBoundaries = /\\?\{([^{}]+)\}/g;
// Find {interpolated} expressions and tolerate {unclosed expressions
LSD.Script.Interpolation.rForgivingBoundaries = /\\?\{([^{}]+)(\}|$)/g;<commit_msg>Attach attribute interpolations from the start<commit_after>/*
---

script: Script/Interpolation.js

description: Tools to find and evaluate interpolated strings in text content and attributes

license: Public domain (http://unlicense.org).

authors: Yaroslaff Fedin

requires:
  - LSD.Script.Function
  - LSD.Script.Scope

provides:
  - LSD.Script.Interpolation

...
*/

LSD.Script.Interpolation = function(object, source) {
  if (object.nodeType) {
    if (object.nodeType == 3)
      return LSD.Script.Interpolation.Textnode(object, source)
  } else if (Type.isEnumerable(object)) {
    for (var i = 0, attribute; attribute = object[i++];)
      LSD.Script.Interpolation.Attribute(attribute.name, attribute.value, source, attribute)
  } else if (type.toObject) {
    for (var name in type) {
      if (type.hasProperty(type))
        LSD.Script.Interpolation.Attribute(name, type[name], source)
    }
  }
};

LSD.Script.Interpolation.Attribute = function(name, value, source, attribute, forgiving) {
  var count = 0, last = 0, index, args;
  var regex = forgiving ? LSD.Layout.Interpolation.rForgivingBoundaries : LSD.Script.Interpolation.rBoundaries;
  for (var match, compiled; match = regex.exec(value);) {
    index = match.index;
    if (!args) args = [];
    if (index > last) args.push(value.substring(last, index));
    if (match[2] == "}" || match[2] == null) {
      args.push(LSD.Script({
        input: match[1],
        source: source,
        placeholder: match[0]
      }));
    }
    last = index + match[0].length;
  }
  if (args && last < value.length) args.push(value.substring(last, value.length));
  if (args) {
    if (!attribute) attribute = source.getAttributeNode(name);
    return new LSD.Script.Function(args, source, attribute, 'concat').attach();
  }
};

LSD.Script.Interpolation.Textnode = function(node, source, forgiving) {
  var content = node.textContent, finder, length = content.length;
  var regex = forgiving ? LSD.Layout.Interpolation.rForgivingBoundaries : LSD.Script.Interpolation.rBoundaries;
  for (var match, index, last, next, compiled; match = regex.exec(content);) {
    last = index || 0
    var index = match.index + match[0].length;
    expression = node;
    var cut = index - last;
    if (cut < node.textContent.length) node = node.splitText(index - last);
    if ((cut = (match.index - last))) expression = expression.splitText(cut);
    compiled = LSD.Script({
      input: match[1],
      source: source,
      output: expression,
      placeholder: match[0]
    });
    Element.store(expression, 'interpolation', compiled);
    last = index;
  }
}
// Find {interpolated} expressions in a string
LSD.Script.Interpolation.rBoundaries = /\\?\{([^{}]+)\}/g;
// Find {interpolated} expressions and tolerate {unclosed expressions
LSD.Script.Interpolation.rForgivingBoundaries = /\\?\{([^{}]+)(\}|$)/g;<|endoftext|>


<commit_before>/**
 * 字典数据源
 */
define( function ( require ) {
    "use strict";
    var DataSource,
        $ = require( "jquery" )
    ;

    DataSource = {
        // 在 _pkui.js 注册组件时，再设置
        timestamp: undefined
    };

    DataSource.init = function () {
        this.timestamp = window.PKUI.timestamp;
    };

    // 缓存
    DataSource.cache = {
        "list": {}, // { DIC_GENDER: [ { code:'',text:'',spell:'',aspell:'' }, ... ], ... }
        "set": {},  // { DIC_GENDER: { 'code1':'text1', 'code2':'text2', ... }, ... }
        "ext": { // 扩展的缓存，专门存放非标准的list或set
            "select2": {}
        }
    };

    // 提供的API
    DataSource = $.extend( DataSource, {
        /**
         * 根据指定字典名称获取dataList，步骤：
         * 1. 从缓存中取指定url的dataList，取到则返回，否则，进行下一步；
         * 2. 根据url发送请求，将获取到的xml文档对象转换成dataList，并缓存；
         * @param dicName: 字典文件的url
         * @returns {*}: 返回的格式
         * [
         *      { code: "", text: "", spell: "", aspell: "" },
         *      { code: "", text: "", spell: "", aspell: "" },
         *      ...
         * ]
         */
        getDataList: function ( dicName ) {
            var listCache,
                dataList
                ;
            // 1. 从listCache中取
            listCache = this.cache[ "list" ];
            dataList = listCache[ dicName ];

            // 2. 取到了，则直接返回
            if ( dataList ) {
                return dataList;
            }

            // 3. 没取到，请求字典文件
            this.request.getXmlAndCache( dicName );

            return listCache[ dicName ];
        },
        /**
         * 根据指定字典名称获取dataSet，步骤：
         * 1. 从缓存中取，取到了则返回，取不到则进行下一步；
         * 2. 调用 getDataList() 方法获取 dataList，将 dataList 转换成 dataSet，缓存并返回
         * @param dicName 字典文件的url
         * @returns {*}: 返回的格式
         * {
         *      code1: text1,
         *      code2: text2,
         *      ...
         * }
         */
        getDataSet: function ( dicName ) {
            var setCache,
                dataSet,
                dataList
            ;

            setCache = this.cache[ "set" ];

            // 1. 从 setCache 中取，取到则返回
            dataSet = setCache[ dicName ];

            if( dataSet ) {
                return dataSet;
            }

            // 2. 取不到，则从 listCache 中取（没有则请求并转换）
            dataList = this.getDataList( dicName );

            // 3. 将list转换为set
            dataSet = this.utils.convertDataListToDataSet( dataList );

            // 4. 缓存 dataSet
            setCache[ dicName ] = dataSet;

            return dataSet;
        },
        /**
         * 获取扩展的dataList
         * @param dicName 字典文件的url
         * @param extType 扩展类型，一般是插件名称
         * @param extConverter 有预定义好的转换器，也可以用自定义的
         * @returns {*}
         */
        getExtDataList: function ( dicName, extType, extConverter ) {
            var dataList,
                extDataList,
                extCache
            ;
            extCache = this.cache[ "ext" ];

            // 1. 从extCache缓存中取，取到了则直接返回
            if ( ! extCache[ extType ] ) { // 如果没有对应的扩展类缓存，则创建
                extCache[ extType ] = {};
            }
            extDataList = extCache[ extType ][ dicName ];

            if ( extDataList ) {
                return extDataList;
            }

            // 2. 取不到，则获取dataList
            dataList = this.getDataList( dicName );

            // 3. 将 dataList 转化为 extType类型 的数据格式
            extDataList = this.utils.convertDataListToExtDataList( dataList, extType, extConverter );

            // 4. 缓存，并返回
            extCache[ extType ][ dicName ] = extDataList;

            return extDataList;
        },
        /**
         * 通过字典名称和code获取value
         * @param dicName
         * @param code
         * @returns {*}
         */
        getDicValue: function( dicName, code ) {
            return this.getDataSet(dicName)[ code ];
        },
        /**
         * 清空缓存。
         * 如果指定了字典名称则删除指定的字典，否则删除所有。
         * 通常用于字典内容变化后，进行数据源的刷新
         * @param dicName {Array|String}
         */
        clearCache: function ( dicName ) {
            var cache = DataSource.cache
            ;

            // 更新时间戳，避免使用缓存字典文件
            this.timestamp = "v=" + ( new Date() ).getTime();

            // dicName没有指定 或 数组长度为0，则直接清空所有缓存
            if ( ! dicName || ( $.isArray( dicName ) && dicName.length === 0 ) ) {
                cache = {
                    "list": {},
                    "set": {}
                };
                return;
            }
            // 如果指定了字典名称，则删除指定的字典
            if ( typeof dicName === "string" ) {
                dicName = [ dicName ];
            }
            $.each( dicName, function ( index, dicname ) {
                if ( cache[ "list" ].hasOwnProperty( dicname ) ) {
                    delete cache[ "list" ][ dicname ];
                }
                if ( cache[ "set" ].hasOwnProperty( dicname ) ) {
                    delete cache[ "set" ][ dicname ];
                }
            } );
        }

    } );

    // 请求
    DataSource.request = {
        /**
         * 同步请求指定url的字典文件
         * @param url: 请求的字典文件url
         * @param doSuccess: 请求成功后的回调函数
         * @param doError: 请求出错后的回调函数
         * @param method: 请求方式，"GET"（默认） 或 "POST"
         * @returns {DataSource}: 链式调用
         */
        syncAjax: function ( url, doSuccess, doError, method  ) {
            method = method || "GET";
            $.ajax( {
                type: method,
                url: url,
                async: false, // 同步请求
                timeout: 30000, // 设置请求超时时间（毫秒）
                contentType: "application/x-www-form-urlencoded; charset=utf-8",
                cache: true, // 缓存此页面
                dataType: "xml", // 预期服务器返回的数据类型。
                success: function ( data ) {
                    doSuccess( data );
                },
                error: function () {
                    doError( );
                }
            } );
        },
        /**
         * 请求指定名称的字典文件，并转换成dataList缓存起来。
         * @param dicNames: 可以是单个url字符串，也可以是 url字符串数组
         * @returns {DataSource}: 链式调用
         */
        getXmlAndCache: function ( dicNames ) {
            var _this
                ;

            _this = this;

            if ( typeof dicNames === "string" ) {
                dicNames = [ dicNames ];
            }

            $.unique( dicNames ); // 去重

            // Ajax同步请求每个 dic ，并将请求返回的xml文档对象缓存起来
            $.each( dicNames, function ( index, dicName ) {
                var dicUrl = DataSource.utils.getDicUrl( dicName )
                ;
                _this.syncAjax(
                    dicUrl,
                    function ( xmlDoc ) {
                        _this.handleRequestDicSuccess( dicName, xmlDoc );
                    },
                    function () {
                        _this.handleRequestDicError( dicName );
                    }
                );
            } );

            return this;
        },
        handleRequestDicSuccess: function ( dicName, xmlDoc ) {
            var isSuccess,
                listCache,
                _this,
                dicUrl = DataSource.utils.getDicUrl( dicName )
                ;
            _this = this;
            isSuccess = xmlDoc && ( xmlDoc.getElementsByTagName( "row" ).length > 0 );
            listCache = DataSource.cache[ "list" ];
            if ( isSuccess ) {
                console.info( dicUrl, "\t字典获取成功。" );
            } else {
                if ( listCache[ dicName ] == "isRepeated" ) {
                    console.info( dicUrl, "\t字典获取失败: 第二次获取失败。" );
                }
                console.info( dicUrl, "\t字典获取失败: 进行第二次获取。" );
                // 尝试再次获取，通过POST请求
                listCache[ dicName ] = "isRepeated";
                DataSource.request(
                    dicUrl,
                    function ( data ) {
                        _this.handleRequestDicSuccess( dicName, data );
                    },
                    function () {
                        _this.handleRequestDicError( dicName );
                    },
                    "POST"
                );
            }
            // 缓存数据
            listCache[ dicName ] = DataSource.utils.convertXmlDocToDataList( xmlDoc );
        },
        handleRequestDicError: function ( dicName ) {
            console.info( dicName, "\t字典获取失败: 网络原因/路径错误。" );
        }
    };

    // 工具
    DataSource.utils = {
        /**
         * 根据字典文件名获取其URL，如果不是"DIC_"的格式，则直接当做URL来处理
         * @param dicName 字典文件名，如 DIC_GENDER
         * @returns {*}
         */
        getDicUrl: function ( dicName ) {
            // 不以"DIC_"打头的字典，不添加时间戳
            if ( dicName.indexOf( "DIC_" ) !== 0 ){
                return dicName;
            }
            return window.PKUI.dicPath + dicName + ".xml?" + DataSource.timestamp;
        },
        /**
         * 将xml文档对象转换成标准的dataList
         * @param xmlDoc xml文档对象
         * @returns {Array}
         */
        convertXmlDocToDataList: function ( xmlDoc ) {
            var dataList,
                rowElts
                ;

            dataList = [];
            rowElts = xmlDoc.getElementsByTagName( "row" );

            $.each( rowElts, function ( index, rowElt ) {
                dataList.push( {
                    "code": rowElt.getAttribute( "DIC_CODE" ),
                    "text": rowElt.getAttribute( "DIC_TEXT" ),
                    "spell": rowElt.getAttribute( "DIC_SPELL" ),
                    "aspell": rowElt.getAttribute( "DIC_ASPELL" )
                } );
            } );

            return dataList;
        },
        convertDataListToDataSet: function ( dataList ) {
            var dataSet
                ;
            dataSet = {};
            $.each( dataList, function ( index, dicData ) {
                dataSet[ dicData[ "code" ] ] = dicData[ "text" ];
            } );
            return dataSet;
        },
        convertDataListToExtDataList: function ( dataList, extType, extConverter ) {
            var extDataList
                ;

            // 如果传了自定义的extConverter，则调用自定义的extConverter
            if ( extConverter ) {
                return extConverter( dataList );
            }

            switch ( extType ) {
                case "select2": { // 预定义的 extConverter
                    extDataList = DataSource.converter.get( "select2" )( dataList );
                    break;
                }
            }
            return extDataList;
        }
    };

    // 转换器
    DataSource.converter = {
        get: function ( type ) {
            return this[ type ];
        },
        select2 : function ( dataList ) {
            var extDataList
                ;
            extDataList = [];
            $.each( dataList, function ( index, data ) {
                extDataList.push( {
                    "id": data[ "code" ],
                    "text": data[ "text" ],
                    "spell": data[ "spell" ] + data[ "code" ]
                } );
            } );
            return extDataList;
        }
    };

    //window.PKUI.component.DataSource = DataSource;

    return DataSource;
} );
<commit_msg>【PKUI】dataSource：优化getDicValue()方法<commit_after>/**
 * 字典数据源
 */
define( function ( require ) {
    "use strict";
    var DataSource,
        $ = require( "jquery" )
    ;

    DataSource = {
        // 在 _pkui.js 注册组件时，再设置
        timestamp: undefined
    };

    DataSource.init = function () {
        this.timestamp = window.PKUI.timestamp;
    };

    // 缓存
    DataSource.cache = {
        "list": {}, // { DIC_GENDER: [ { code:'',text:'',spell:'',aspell:'' }, ... ], ... }
        "set": {},  // { DIC_GENDER: { 'code1':'text1', 'code2':'text2', ... }, ... }
        "ext": { // 扩展的缓存，专门存放非标准的list或set
            "select2": {}
        }
    };

    // 提供的API
    DataSource = $.extend( DataSource, {
        /**
         * 根据指定字典名称获取dataList，步骤：
         * 1. 从缓存中取指定url的dataList，取到则返回，否则，进行下一步；
         * 2. 根据url发送请求，将获取到的xml文档对象转换成dataList，并缓存；
         * @param dicName: 字典文件的url
         * @returns {*}: 返回的格式
         * [
         *      { code: "", text: "", spell: "", aspell: "" },
         *      { code: "", text: "", spell: "", aspell: "" },
         *      ...
         * ]
         */
        getDataList: function ( dicName ) {
            var listCache,
                dataList
                ;
            // 1. 从listCache中取
            listCache = this.cache[ "list" ];
            dataList = listCache[ dicName ];

            // 2. 取到了，则直接返回
            if ( dataList ) {
                return dataList;
            }

            // 3. 没取到，请求字典文件
            this.request.getXmlAndCache( dicName );

            return listCache[ dicName ];
        },
        /**
         * 根据指定字典名称获取dataSet，步骤：
         * 1. 从缓存中取，取到了则返回，取不到则进行下一步；
         * 2. 调用 getDataList() 方法获取 dataList，将 dataList 转换成 dataSet，缓存并返回
         * @param dicName 字典文件的url
         * @returns {*}: 返回的格式
         * {
         *      code1: text1,
         *      code2: text2,
         *      ...
         * }
         */
        getDataSet: function ( dicName ) {
            var setCache,
                dataSet,
                dataList
            ;

            setCache = this.cache[ "set" ];

            // 1. 从 setCache 中取，取到则返回
            dataSet = setCache[ dicName ];

            if( dataSet ) {
                return dataSet;
            }

            // 2. 取不到，则从 listCache 中取（没有则请求并转换）
            dataList = this.getDataList( dicName );

            // 3. 将list转换为set
            dataSet = this.utils.convertDataListToDataSet( dataList );

            // 4. 缓存 dataSet
            setCache[ dicName ] = dataSet;

            return dataSet;
        },
        /**
         * 获取扩展的dataList
         * @param dicName 字典文件的url
         * @param extType 扩展类型，一般是插件名称
         * @param extConverter 有预定义好的转换器，也可以用自定义的
         * @returns {*}
         */
        getExtDataList: function ( dicName, extType, extConverter ) {
            var dataList,
                extDataList,
                extCache
            ;
            extCache = this.cache[ "ext" ];

            // 1. 从extCache缓存中取，取到了则直接返回
            if ( ! extCache[ extType ] ) { // 如果没有对应的扩展类缓存，则创建
                extCache[ extType ] = {};
            }
            extDataList = extCache[ extType ][ dicName ];

            if ( extDataList ) {
                return extDataList;
            }

            // 2. 取不到，则获取dataList
            dataList = this.getDataList( dicName );

            // 3. 将 dataList 转化为 extType类型 的数据格式
            extDataList = this.utils.convertDataListToExtDataList( dataList, extType, extConverter );

            // 4. 缓存，并返回
            extCache[ extType ][ dicName ] = extDataList;

            return extDataList;
        },
        /**
         * 通过字典名称和code获取value
         * @param dicName
         * @param code
         * @returns {*}
         */
        getDicValue: function( dicName, code ) {
            var value = code;
            try {
                value = this.getDataSet(dicName)[ code ];
            } catch ( e ) {
                console.info( e );
            }
            return value;
        },
        /**
         * 清空缓存。
         * 如果指定了字典名称则删除指定的字典，否则删除所有。
         * 通常用于字典内容变化后，进行数据源的刷新
         * @param dicName {Array|String}
         */
        clearCache: function ( dicName ) {
            var cache = DataSource.cache
            ;

            // 更新时间戳，避免使用缓存字典文件
            this.timestamp = "v=" + ( new Date() ).getTime();

            // dicName没有指定 或 数组长度为0，则直接清空所有缓存
            if ( ! dicName || ( $.isArray( dicName ) && dicName.length === 0 ) ) {
                cache = {
                    "list": {},
                    "set": {}
                };
                return;
            }
            // 如果指定了字典名称，则删除指定的字典
            if ( typeof dicName === "string" ) {
                dicName = [ dicName ];
            }
            $.each( dicName, function ( index, dicname ) {
                if ( cache[ "list" ].hasOwnProperty( dicname ) ) {
                    delete cache[ "list" ][ dicname ];
                }
                if ( cache[ "set" ].hasOwnProperty( dicname ) ) {
                    delete cache[ "set" ][ dicname ];
                }
            } );
        }

    } );

    // 请求
    DataSource.request = {
        /**
         * 同步请求指定url的字典文件
         * @param url: 请求的字典文件url
         * @param doSuccess: 请求成功后的回调函数
         * @param doError: 请求出错后的回调函数
         * @param method: 请求方式，"GET"（默认） 或 "POST"
         * @returns {DataSource}: 链式调用
         */
        syncAjax: function ( url, doSuccess, doError, method  ) {
            method = method || "GET";
            $.ajax( {
                type: method,
                url: url,
                async: false, // 同步请求
                timeout: 30000, // 设置请求超时时间（毫秒）
                contentType: "application/x-www-form-urlencoded; charset=utf-8",
                cache: true, // 缓存此页面
                dataType: "xml", // 预期服务器返回的数据类型。
                success: function ( data ) {
                    doSuccess( data );
                },
                error: function () {
                    doError( );
                }
            } );
        },
        /**
         * 请求指定名称的字典文件，并转换成dataList缓存起来。
         * @param dicNames: 可以是单个url字符串，也可以是 url字符串数组
         * @returns {DataSource}: 链式调用
         */
        getXmlAndCache: function ( dicNames ) {
            var _this
                ;

            _this = this;

            if ( typeof dicNames === "string" ) {
                dicNames = [ dicNames ];
            }

            $.unique( dicNames ); // 去重

            // Ajax同步请求每个 dic ，并将请求返回的xml文档对象缓存起来
            $.each( dicNames, function ( index, dicName ) {
                var dicUrl = DataSource.utils.getDicUrl( dicName )
                ;
                _this.syncAjax(
                    dicUrl,
                    function ( xmlDoc ) {
                        _this.handleRequestDicSuccess( dicName, xmlDoc );
                    },
                    function () {
                        _this.handleRequestDicError( dicName );
                    }
                );
            } );

            return this;
        },
        handleRequestDicSuccess: function ( dicName, xmlDoc ) {
            var isSuccess,
                listCache,
                _this,
                dicUrl = DataSource.utils.getDicUrl( dicName )
                ;
            _this = this;
            isSuccess = xmlDoc && ( xmlDoc.getElementsByTagName( "row" ).length > 0 );
            listCache = DataSource.cache[ "list" ];
            if ( isSuccess ) {
                console.info( dicUrl, "\t字典获取成功。" );
            } else {
                if ( listCache[ dicName ] == "isRepeated" ) {
                    console.info( dicUrl, "\t字典获取失败: 第二次获取失败。" );
                }
                console.info( dicUrl, "\t字典获取失败: 进行第二次获取。" );
                // 尝试再次获取，通过POST请求
                listCache[ dicName ] = "isRepeated";
                DataSource.request(
                    dicUrl,
                    function ( data ) {
                        _this.handleRequestDicSuccess( dicName, data );
                    },
                    function () {
                        _this.handleRequestDicError( dicName );
                    },
                    "POST"
                );
            }
            // 缓存数据
            listCache[ dicName ] = DataSource.utils.convertXmlDocToDataList( xmlDoc );
        },
        handleRequestDicError: function ( dicName ) {
            console.info( dicName, "\t字典获取失败: 网络原因/路径错误。" );
        }
    };

    // 工具
    DataSource.utils = {
        /**
         * 根据字典文件名获取其URL，如果不是"DIC_"的格式，则直接当做URL来处理
         * @param dicName 字典文件名，如 DIC_GENDER
         * @returns {*}
         */
        getDicUrl: function ( dicName ) {
            // 不以"DIC_"打头的字典，不添加时间戳
            if ( dicName.indexOf( "DIC_" ) !== 0 ){
                return dicName;
            }
            return window.PKUI.dicPath + dicName + ".xml?" + DataSource.timestamp;
        },
        /**
         * 将xml文档对象转换成标准的dataList
         * @param xmlDoc xml文档对象
         * @returns {Array}
         */
        convertXmlDocToDataList: function ( xmlDoc ) {
            var dataList,
                rowElts
                ;

            dataList = [];
            rowElts = xmlDoc.getElementsByTagName( "row" );

            $.each( rowElts, function ( index, rowElt ) {
                dataList.push( {
                    "code": rowElt.getAttribute( "DIC_CODE" ),
                    "text": rowElt.getAttribute( "DIC_TEXT" ),
                    "spell": rowElt.getAttribute( "DIC_SPELL" ),
                    "aspell": rowElt.getAttribute( "DIC_ASPELL" )
                } );
            } );

            return dataList;
        },
        convertDataListToDataSet: function ( dataList ) {
            var dataSet
                ;
            dataSet = {};
            $.each( dataList, function ( index, dicData ) {
                dataSet[ dicData[ "code" ] ] = dicData[ "text" ];
            } );
            return dataSet;
        },
        convertDataListToExtDataList: function ( dataList, extType, extConverter ) {
            var extDataList
                ;

            // 如果传了自定义的extConverter，则调用自定义的extConverter
            if ( extConverter ) {
                return extConverter( dataList );
            }

            switch ( extType ) {
                case "select2": { // 预定义的 extConverter
                    extDataList = DataSource.converter.get( "select2" )( dataList );
                    break;
                }
            }
            return extDataList;
        }
    };

    // 转换器
    DataSource.converter = {
        get: function ( type ) {
            return this[ type ];
        },
        select2 : function ( dataList ) {
            var extDataList
                ;
            extDataList = [];
            $.each( dataList, function ( index, data ) {
                extDataList.push( {
                    "id": data[ "code" ],
                    "text": data[ "text" ],
                    "spell": data[ "spell" ] + data[ "code" ]
                } );
            } );
            return extDataList;
        }
    };

    //window.PKUI.component.DataSource = DataSource;

    return DataSource;
} );
<|endoftext|>


<commit_before>import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
import {
  Link
} from 'react-router-dom'

import block from '../../../helpers/bem-cn'

import PaginatedList from '../../PaginatedList/PaginatedList'
import Button from '../../../components/Button/Button'
import Icon from '../../../components/Icon/Icon'
import Control from '../../../components/Control/Control'
import Preloader from '../../../components/Preloader/Preloader'
import NoSearchResults from '../../../components/NoSearchResults/NoSearchResults'

import JSONmodal from '../../modals/JSONmodal/JSONmodal'

import '../../Layout/Table/Table.css'

const propTypes = {
  apiList: PropTypes.arrayOf(PropTypes.object.isRequired).isRequired,
  currentPageIndex: PropTypes.number.isRequired,
  isAdmin: PropTypes.bool.isRequired,
  setCurrentPageIndex: PropTypes.func.isRequired,
  fetchEndpoints: PropTypes.func.isRequired,
  refreshEndpoints: PropTypes.func.isRequired,
  setSortingFilter: PropTypes.func.isRequired,
  searchQuery: PropTypes.string.isRequired,
  confirmAction: PropTypes.func.isRequired
}

const table = block('j-table')

class ApiList extends PureComponent {
  state = {
    showJSONmodal: false,
    JSONmodalContent: {}
  }

  componentDidMount () {
    this.props.fetchEndpoints()
  }

    isOauthEnabled = (plugins) => {
    // @TODO: find why
    // if (typeof this.isProtected !== 'undefined') {
    //   return this.isProtected;
    // }
      const oauth = plugins.find(plugin => plugin.name.indexOf('oauth2') > -1)

      return !!oauth && !!oauth.enabled
    }

    handleDelete = api => {
      this.props.confirmAction('delete', 'endpoint', api.name)
    };

    handleCloseModal = () => this.setState({
      showJSONmodal: false,
      JSONmodalContent: {}
    })

    handleCopyAsJSON = api => this.setState({
      showJSONmodal: true,
      JSONmodalContent: api
    })

    renderRows = list => list.map((api, index) => (
      <div className={table('row')()} key={`${index}-${api.name}`}>

{api.name}

{api.proxy.listen_path}

          {api.active ? <Icon type='checked' /> : null}

          <Link to={`/preview/${api.name}`} className={table('controls-item')()}>
            <Icon type='view' ariaLabel='View' />
          </Link>
          <Link to={`/${api.name}`} className={table('controls-item')()}>
            <Icon type='edit' ariaLabel='Edit' />
          </Link>
          <Link
            to={{
              pathname: '/new',
              state: {
                clone: api
              }
            }}
            className={table('controls-item')()}
          >
            <Icon type='copy' ariaLabel='Copy' />
          </Link>
          <Button
            mod='primary'
            type='button'
            size='small'
            onClick={() => {
              this.handleCopyAsJSON(api)
            }}
          >
            Copy as JSON
          </Button>
          {
            this.props.isAdmin &&
            <Control
              className={table('controls-item')()}
              icon='delete'
              onClick={() => {
                this.handleDelete(api)
              }}
            />
          }

    ))

    sortList = filter => {
      this.props.setSortingFilter(filter)
      this.props.setAscendingFilter()
    }

    renderTable = list => (

 this.sortList('name')}
            >

Api Name

Listen Path

 this.sortList('active')}
            >

Active

          { this.renderRows(list) }

        <JSONmodal
          show={this.state.showJSONmodal}
          message={this.state.JSONmodalContent}
          closeModal={this.handleCloseModal}
        />

    )

    render () {
      if (this.props.apiList.length > 0) {
        return (
          <PaginatedList
            list={this.props.apiList}
            currentPageIndex={this.props.currentPageIndex}
            changePageIndex={this.props.setCurrentPageIndex}
            renderChildren={this.renderTable}
          />
        )
      }

      if (this.props.apiList.isFetching) {
        return <Preloader />
      } else {
        return <NoSearchResults />
      }
    }
}

ApiList.propTypes = propTypes

export default ApiList
<commit_msg>Remove else block<commit_after>import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
import {
  Link
} from 'react-router-dom'

import block from '../../../helpers/bem-cn'

import PaginatedList from '../../PaginatedList/PaginatedList'
import Button from '../../../components/Button/Button'
import Icon from '../../../components/Icon/Icon'
import Control from '../../../components/Control/Control'
import Preloader from '../../../components/Preloader/Preloader'
import NoSearchResults from '../../../components/NoSearchResults/NoSearchResults'

import JSONmodal from '../../modals/JSONmodal/JSONmodal'

import '../../Layout/Table/Table.css'

const propTypes = {
  apiList: PropTypes.arrayOf(PropTypes.object.isRequired).isRequired,
  currentPageIndex: PropTypes.number.isRequired,
  isAdmin: PropTypes.bool.isRequired,
  setCurrentPageIndex: PropTypes.func.isRequired,
  fetchEndpoints: PropTypes.func.isRequired,
  refreshEndpoints: PropTypes.func.isRequired,
  setSortingFilter: PropTypes.func.isRequired,
  searchQuery: PropTypes.string.isRequired,
  confirmAction: PropTypes.func.isRequired
}

const table = block('j-table')

class ApiList extends PureComponent {
  state = {
    showJSONmodal: false,
    JSONmodalContent: {}
  }

  componentDidMount () {
    this.props.fetchEndpoints()
  }

    isOauthEnabled = (plugins) => {
    // @TODO: find why
    // if (typeof this.isProtected !== 'undefined') {
    //   return this.isProtected;
    // }
      const oauth = plugins.find(plugin => plugin.name.indexOf('oauth2') > -1)

      return !!oauth && !!oauth.enabled
    }

    handleDelete = api => {
      this.props.confirmAction('delete', 'endpoint', api.name)
    };

    handleCloseModal = () => this.setState({
      showJSONmodal: false,
      JSONmodalContent: {}
    })

    handleCopyAsJSON = api => this.setState({
      showJSONmodal: true,
      JSONmodalContent: api
    })

    renderRows = list => list.map((api, index) => (
      <div className={table('row')()} key={`${index}-${api.name}`}>

{api.name}

{api.proxy.listen_path}

          {api.active ? <Icon type='checked' /> : null}

          <Link to={`/preview/${api.name}`} className={table('controls-item')()}>
            <Icon type='view' ariaLabel='View' />
          </Link>
          <Link to={`/${api.name}`} className={table('controls-item')()}>
            <Icon type='edit' ariaLabel='Edit' />
          </Link>
          <Link
            to={{
              pathname: '/new',
              state: {
                clone: api
              }
            }}
            className={table('controls-item')()}
          >
            <Icon type='copy' ariaLabel='Copy' />
          </Link>
          <Button
            mod='primary'
            type='button'
            size='small'
            onClick={() => {
              this.handleCopyAsJSON(api)
            }}
          >
            Copy as JSON
          </Button>
          {
            this.props.isAdmin &&
            <Control
              className={table('controls-item')()}
              icon='delete'
              onClick={() => {
                this.handleDelete(api)
              }}
            />
          }

    ))

    sortList = filter => {
      this.props.setSortingFilter(filter)
      this.props.setAscendingFilter()
    }

    renderTable = list => (

 this.sortList('name')}
            >

Api Name

Listen Path

 this.sortList('active')}
            >

Active

          { this.renderRows(list) }

        <JSONmodal
          show={this.state.showJSONmodal}
          message={this.state.JSONmodalContent}
          closeModal={this.handleCloseModal}
        />

    )

    render () {
      if (this.props.apiList.length > 0) {
        return (
          <PaginatedList
            list={this.props.apiList}
            currentPageIndex={this.props.currentPageIndex}
            changePageIndex={this.props.setCurrentPageIndex}
            renderChildren={this.renderTable}
          />
        )
      }

      if (this.props.apiList.isFetching) {
        return <Preloader />
      }

      return <NoSearchResults />
    }
}

ApiList.propTypes = propTypes

export default ApiList
<|endoftext|>


<commit_before>frappe.ui.FilterGroup = class {
	constructor(opts) {
		$.extend(this, opts);
		this.wrapper = this.parent;
		this.filters = [];
		this.make();
		window.fltr = this;
	}

	make() {
		this.wrapper.append(this.get_container_template());
		this.set_events();
	}

	toggle_clear_filter() {
		let clear_filter_button = this.wrapper.find('.clear-filters');

		if (this.filters.length == 0) {
			clear_filter_button.hide();
		} else {
			clear_filter_button.show();
		}
	}
	set_events() {
		this.wrapper.find('.add-filter').on('click', () => {
			this.add_filter(this.doctype, 'name')
				.then(this.toggle_clear_filter());

		});
		this.wrapper.find('.clear-filters').on('click', () => {
			this.clear_filters();
		});
	}

	add_filters(filters) {
		let promises = [];

		for (const filter of filters) {
			promises.push(() => this.add_filter(...filter));
		}

		promises.push(() => this.toggle_clear_filter());

		return frappe.run_serially(promises);
	}

	add_filter(doctype, fieldname, condition, value, hidden) {
		if (!fieldname) return Promise.resolve();
		// adds a new filter, returns true if filter has been added

		// {}: Add in page filter by fieldname if exists ('=' => 'like')

		if(!this.validate_args(doctype, fieldname)) return false;
		const is_new_filter = arguments.length < 2;
		if (is_new_filter && this.wrapper.find(".new-filter:visible").length) {
			// only allow 1 new filter at a time!
			return Promise.resolve();
		} else {
			let args = [doctype, fieldname, condition, value, hidden];
			const promise = this.push_new_filter(args, is_new_filter);
			return (promise && promise.then) ? promise : Promise.resolve();
		}
	}

	validate_args(doctype, fieldname) {
		if(doctype && fieldname
			&& !frappe.meta.has_field(doctype, fieldname)
			&& !frappe.model.std_fields_list.includes(fieldname)) {

			frappe.throw(__(`Invalid filter: "${[fieldname.bold()]}"`));
			return false;
		}
		return true;
	}

	push_new_filter(args, is_new_filter=false) {
		// args: [doctype, fieldname, condition, value]
		if(this.filter_exists(args)) return;

		// {}: Clear page filter fieldname field

		let filter = this._push_new_filter(...args);

		if (filter && filter.value) {
			filter.setup_state(is_new_filter);
			return filter._filter_value_set; // internal promise
		}
	}

	_push_new_filter(doctype, fieldname, condition, value, hidden = false) {
		let args = {
			parent: this.wrapper,
			parent_doctype: this.doctype,
			doctype: doctype,
			fieldname: fieldname,
			condition: condition,
			value: value,
			hidden: hidden,
			on_change: (update) => {
				if(update) this.update_filters();
				this.on_change();
			},
			filter_items: (doctype, fieldname) => {
				return !this.filter_exists([doctype, fieldname]);
			}
		};
		let filter = new frappe.ui.Filter(args);
		this.filters.push(filter);
		return filter;
	}

	filter_exists(filter_value) {
		// filter_value of form: [doctype, fieldname, condition, value]
		let exists = false;
		this.filters.filter(f => f.field).map(f => {
			let f_value = f.get_value();
			if (filter_value.length === 2) {
				exists = filter_value[0] === f_value[0] && filter_value[1] === f_value[1];
				return;
			}

			let value = filter_value[3];
			let equal = frappe.utils.arrays_equal;

			if(equal(f_value.slice(0, 4), filter_value.slice(0, 4)) || (Array.isArray(value) && equal(value, f_value[3]))) {
				exists = true;
			}
		});
		return exists;
	}

	get_filters() {
		return this.filters.filter(f => f.field).map(f => {
			f.freeze();
			return f.get_value();
		});
		// {}: this.list.update_standard_filters(values);
	}

	update_filters() {
		this.filters = this.filters.filter(f => f.field); // remove hidden filters
		this.toggle_clear_filter();
	}

	clear_filters() {
		this.filters.map(f => f.remove(true));
		// {}: Clear page filters, .date-range-picker (called list run())
		this.filters = [];
	}

	get_filter(fieldname) {
		return this.filters.filter(f => {
			return (f.field && f.field.df.fieldname==fieldname);
		})[0];
	}

	get_container_template() {
		return $(`

				<button class="btn btn-default btn-xs filter-button text-muted add-filter">
					${__("Add Filter")}
				</button><button class="btn btn-default btn-xs filter-button text-muted clear-filters">
					${__("Clear Filters")}
				</button>

`);
	}
};
<commit_msg>fix: hide clear-filter by default<commit_after>frappe.ui.FilterGroup = class {
	constructor(opts) {
		$.extend(this, opts);
		this.wrapper = this.parent;
		this.filters = [];
		this.make();
		window.fltr = this;
	}

	make() {
		this.wrapper.append(this.get_container_template());
		this.set_events();
	}

	toggle_clear_filter() {
		let clear_filter_button = this.wrapper.find('.clear-filters');

		if (this.filters.length == 0) {
			clear_filter_button.hide();
		} else {
			clear_filter_button.show();
		}
	}
	set_events() {
		this.wrapper.find('.add-filter').on('click', () => {
			this.add_filter(this.doctype, 'name')
				.then(this.toggle_clear_filter());

		});
		this.wrapper.find('.clear-filters').on('click', () => {
			this.clear_filters();
		});
	}

	add_filters(filters) {
		let promises = [];

		for (const filter of filters) {
			promises.push(() => this.add_filter(...filter));
		}

		promises.push(() => this.toggle_clear_filter());

		return frappe.run_serially(promises);
	}

	add_filter(doctype, fieldname, condition, value, hidden) {
		if (!fieldname) return Promise.resolve();
		// adds a new filter, returns true if filter has been added

		// {}: Add in page filter by fieldname if exists ('=' => 'like')

		if(!this.validate_args(doctype, fieldname)) return false;
		const is_new_filter = arguments.length < 2;
		if (is_new_filter && this.wrapper.find(".new-filter:visible").length) {
			// only allow 1 new filter at a time!
			return Promise.resolve();
		} else {
			let args = [doctype, fieldname, condition, value, hidden];
			const promise = this.push_new_filter(args, is_new_filter);
			return (promise && promise.then) ? promise : Promise.resolve();
		}
	}

	validate_args(doctype, fieldname) {
		if(doctype && fieldname
			&& !frappe.meta.has_field(doctype, fieldname)
			&& !frappe.model.std_fields_list.includes(fieldname)) {

			frappe.throw(__(`Invalid filter: "${[fieldname.bold()]}"`));
			return false;
		}
		return true;
	}

	push_new_filter(args, is_new_filter=false) {
		// args: [doctype, fieldname, condition, value]
		if(this.filter_exists(args)) return;

		// {}: Clear page filter fieldname field

		let filter = this._push_new_filter(...args);

		if (filter && filter.value) {
			filter.setup_state(is_new_filter);
			return filter._filter_value_set; // internal promise
		}
	}

	_push_new_filter(doctype, fieldname, condition, value, hidden = false) {
		let args = {
			parent: this.wrapper,
			parent_doctype: this.doctype,
			doctype: doctype,
			fieldname: fieldname,
			condition: condition,
			value: value,
			hidden: hidden,
			on_change: (update) => {
				if(update) this.update_filters();
				this.on_change();
			},
			filter_items: (doctype, fieldname) => {
				return !this.filter_exists([doctype, fieldname]);
			}
		};
		let filter = new frappe.ui.Filter(args);
		this.filters.push(filter);
		return filter;
	}

	filter_exists(filter_value) {
		// filter_value of form: [doctype, fieldname, condition, value]
		let exists = false;
		this.filters.filter(f => f.field).map(f => {
			let f_value = f.get_value();
			if (filter_value.length === 2) {
				exists = filter_value[0] === f_value[0] && filter_value[1] === f_value[1];
				return;
			}

			let value = filter_value[3];
			let equal = frappe.utils.arrays_equal;

			if(equal(f_value.slice(0, 4), filter_value.slice(0, 4)) || (Array.isArray(value) && equal(value, f_value[3]))) {
				exists = true;
			}
		});
		return exists;
	}

	get_filters() {
		return this.filters.filter(f => f.field).map(f => {
			f.freeze();
			return f.get_value();
		});
		// {}: this.list.update_standard_filters(values);
	}

	update_filters() {
		this.filters = this.filters.filter(f => f.field); // remove hidden filters
		this.toggle_clear_filter();
	}

	clear_filters() {
		this.filters.map(f => f.remove(true));
		// {}: Clear page filters, .date-range-picker (called list run())
		this.filters = [];
	}

	get_filter(fieldname) {
		return this.filters.filter(f => {
			return (f.field && f.field.df.fieldname==fieldname);
		})[0];
	}

	get_container_template() {
		return $(`

				<button class="btn btn-default btn-xs filter-button text-muted add-filter">
					${__("Add Filter")}
				</button><button class="btn btn-default btn-xs filter-button text-muted clear-filters" style="display: none;">
					${__("Clear Filters")}
				</button>

`);
	}
};
<|endoftext|>


<commit_before>import _ from 'lodash';
import React from 'react';
import PropTypes from 'prop-types';

import {
  Accordion,
  ExpandAllButton,
  Pane,
  Row,
  Col,
  PaneMenu,
  Button,
  IconButton,
  TextArea,
  Checkbox,
  Datepicker,
  AppIcon
} from '@folio/stripes/components';
import { TitleManager } from '@folio/stripes/core';
import { Field } from 'redux-form';
import stripesForm from '@folio/stripes/form';
import { ViewMetaData } from '@folio/stripes/smart-components';
import moment from 'moment';
import {
  FormattedMessage,
  intlShape,
} from 'react-intl';
import { getFullName } from '../../util';
import UserDetails from '../Accounts/ChargeFeeFine/UserDetails';

const validate = (item) => {
  const errors = {};
  if (!item.desc) {
    errors.desc = <FormattedMessage id="ui-users.blocks.form.validate.desc" />;
  }
  if (!item.borrowing && !item.renewals && !item.requests) {
    errors.borrowing = <FormattedMessage id="ui-users.blocks.form.validate.any" />;
    errors.renewals = <FormattedMessage id="ui-users.blocks.form.validate.any" />;
    errors.requests = <FormattedMessage id="ui-users.blocks.form.validate.any" />;
  }
  if (!item.expirationDate) {
    errors.expirationDate = <FormattedMessage id="ui-users.blocks.form.validate.date" />;
  }
  if (moment(moment(item.expirationDate).format()).isBefore(moment().format())) {
    errors.expirationDate = <FormattedMessage id="ui-users.blocks.form.validate.future" />;
  }
  return errors;
};

class PatronBlockForm extends React.Component {
  static propTypes = {
    user: PropTypes.object,
    pristine: PropTypes.bool,
    submitting: PropTypes.bool,
    invalid: PropTypes.bool,
    selectedItem: PropTypes.object,
    query: PropTypes.object,
    onDeleteItem: PropTypes.func,
    onClose: PropTypes.func,
    initialize: PropTypes.func,
    handleSubmit: PropTypes.func.isRequired,
    connect: PropTypes.func,
    intl: intlShape.isRequired,
    readOnly: PropTypes.bool,
    stripes: PropTypes.object,
  };

  constructor(props) {
    super(props);

    this.handleExpandAll = this.handleExpandAll.bind(this);
    this.handleSectionToggle = this.handleSectionToggle.bind(this);

    this.connectedViewMetaData = props.stripes.connect(ViewMetaData);

    this.state = {
      sections: {
        blockInformationSection: true,
        blockActionsSection: true,
        prueba: true,
      },
      borrowing: false,
      renewals: false,
      requests: false,
      checkedBlocks: {},
    };
  }

  componentDidMount() {
    const item = this.props.selectedItem || {};
    const state = {
      borrowing: (item.id) ? item.borrowing : true,
      renewals: (item.id) ? item.renewals : true,
      requests: (item.id) ? item.requests : true,
    };
    this.setState(state);
    this.props.initialize(state);

    if (item.id) {
      this.props.initialize(item);
    }
  }

  componentDidUpdate(prevProps) {
    if (JSON.stringify(prevProps.selectedItem) !== JSON.stringify(this.props.selectedItem)) {
      const item = this.props.selectedItem || {};
      // eslint-disable-next-line react/no-did-update-set-state
      this.setState({
        borrowing: item.borrowing,
        renewals: item.renewals,
        requests: item.requests,
      });
      this.props.initialize(item);
    }
  }

  handleSectionToggle({ id }) {
    this.setState((curState) => {
      const newState = _.cloneDeep(curState);
      newState.sections[id] = !newState.sections[id];
      return newState;
    });
  }

  handleExpandAll(obj) {
    this.setState((curState) => {
      const newState = _.cloneDeep(curState);
      newState.sections = obj;
      return newState;
    });
  }

  renderFirstMenu = () => (
    <PaneMenu>
      <IconButton
        id="close-patron-block"
        onClick={this.props.onClose}
        title="Close"
        icon="closeX"
      />
    </PaneMenu>
  );

  renderLastMenu = () => {
    const {
      pristine,
      submitting,
      invalid,
      query,
    } = this.props;

    const submit =
      <Button buttonStyle="primary" onClick={this.props.handleSubmit} disabled={pristine || submitting || invalid}>
        {(query.layer === 'edit-block') ? <FormattedMessage id="ui-users.blocks.form.button.save" /> : <FormattedMessage id="ui-users.blocks.form.button.create" />}
      </Button>;
    const del = (query.layer === 'edit-block') ? <Button buttonStyle="danger" onClick={this.props.onDeleteItem}><FormattedMessage id="ui-users.blocks.form.button.delete" /></Button> : '';

    return (
      <PaneMenu>
        {del}
        {submit}
      </PaneMenu>
    );
  }

  onToggleActions = (action) => {
    const { readOnly } = this.props;

    return (e) => {
      if (readOnly) {
        e.preventDefault();
      }
      this.setState(prevState => ({
        [action]: !prevState[action],
      }));
    };
  }

  render() {
    const user = this.props.user || {};
    const { intl } = this.props;
    const title = this.props.query.layer === 'edit-block' ?

        {' '}
        <AppIcon app="users" size="small" />
        {getFullName(user)}
        {' '}

 : 'New Block';
    const userD = this.props.query.layer !== 'edit-block' ? <UserDetails user={user} /> : '';

    return (
      <Pane
        defaultWidth="20%"
        firstMenu={this.renderFirstMenu()}
        paneTitle={title}
        lastMenu={this.renderLastMenu()}
      >
        <TitleManager />
        {userD}
        <Row end="xs">
          <Col xs>
            <ExpandAllButton accordionStatus={this.state.sections} onToggle={this.handleExpandAll} />
          </Col>
        </Row>
        <Row>
          <Col xs>
            <Accordion
              label={<FormattedMessage id="ui-users.blocks.form.label.information" />}
              id="blockInformationSection"
              onToggle={this.handleSectionToggle}
              open={this.state.sections.blockInformationSection}
            >
              {(this.props.selectedItem.metadata) ?
                <Row>
                  <Col xs={12} sm={10} md={7} lg={5}>
                    <this.connectedViewMetaData metadata={this.props.selectedItem.metadata} />
                  </Col>
                </Row> : ''
              }
              <form>
                <Row>
                  <Col xs={12} sm={10} md={7} lg={5}>
                    <Field
                      name="desc"
                      label={<FormattedMessage id="ui-users.blocks.form.label.display" />}
                      component={TextArea}
                      placeholder={intl.formatMessage({ id: 'ui-users.blocks.form.placeholder.desc' })}
                      fullWidth
                    />
                  </Col>
                </Row>
                <Row>
                  <Col xs={12} sm={10} md={7} lg={5}>
                    <Field
                      name="staffInformation"
                      label={<FormattedMessage id="ui-users.blocks.form.label.staff" />}
                      component={TextArea}
                      placeholder={intl.formatMessage({ id: 'ui-users.blocks.form.placeholder.information' })}
                      fullWidth
                    />
                  </Col>
                </Row>
                <Row>
                  <Col xs={12} sm={10} md={7} lg={5}>
                    <Field
                      label={<FormattedMessage id="ui-users.blocks.form.label.message" />}
                      name="patronMessage"
                      component={TextArea}
                      placeholder={intl.formatMessage({ id: 'ui-users.blocks.form.placeholder.message' })}
                      fullWidth
                    />
                  </Col>
                </Row>
                <Row>
                  <Col xs={12} sm={10} md={7} lg={5}>
                    <Field
                      component={Datepicker}
                      dateFormat="YYYY/MM/DD"
                      name="expirationDate"
                      label={<FormattedMessage id="ui-users.blocks.form.label.date" />}
                      backendDateStandard="YYYY/MM/DD"
                      useFocus
                    />
                  </Col>
                </Row>
                <Row>
                  <Col><FormattedMessage id="ui-users.blocks.form.label.block" /></Col>
                </Row>
                <Row>
                  <Col xs={12} sm={10} md={7} lg={5}>
                    <Field
                      name="borrowing"
                      id="borrowing"
                      label={<FormattedMessage id="ui-users.blocks.form.label.borrowing" />}
                      checked={this.state.borrowing}
                      value={this.state.borrowing}
                      onChange={this.onToggleActions('borrowing')}
                      component={Checkbox}
                    />
                  </Col>
                </Row>
                <Row>
                  <Col xs={12} sm={10} md={7} lg={5}>
                    <Field
                      name="renewals"
                      id="renewals"
                      label={<FormattedMessage id="ui-users.blocks.form.label.renewals" />}
                      checked={this.state.renewals}
                      onChange={this.onToggleActions('renewals')}
                      value={this.state.renewals}
                      component={Checkbox}
                    />
                  </Col>
                </Row>
                <Row>
                  <Col xs={12} sm={10} md={7} lg={5}>
                    <Field
                      name="requests"
                      id="requests"
                      label={<FormattedMessage id="ui-users.blocks.form.label.request" />}
                      component={Checkbox}
                      checked={this.state.requests}
                      onChange={this.onToggleActions('requests')}
                      value={this.state.requests}
                    />
                  </Col>
                </Row>
              </form>
            </Accordion>
          </Col>
        </Row>
      </Pane>
    );
  }
}

export default stripesForm({
  form: 'patron-block-form',
  validate,
  fields: [],
})(PatronBlockForm);
<commit_msg>Add timeZone<commit_after>import _ from 'lodash';
import React from 'react';
import PropTypes from 'prop-types';

import {
  Accordion,
  ExpandAllButton,
  Pane,
  Row,
  Col,
  PaneMenu,
  Button,
  IconButton,
  TextArea,
  Checkbox,
  Datepicker,
  AppIcon
} from '@folio/stripes/components';
import { TitleManager } from '@folio/stripes/core';
import { Field } from 'redux-form';
import stripesForm from '@folio/stripes/form';
import { ViewMetaData } from '@folio/stripes/smart-components';
import moment from 'moment';
import {
  FormattedMessage,
  intlShape,
} from 'react-intl';
import { getFullName } from '../../util';
import UserDetails from '../Accounts/ChargeFeeFine/UserDetails';

const validate = (item) => {
  const errors = {};
  if (!item.desc) {
    errors.desc = <FormattedMessage id="ui-users.blocks.form.validate.desc" />;
  }
  if (!item.borrowing && !item.renewals && !item.requests) {
    errors.borrowing = <FormattedMessage id="ui-users.blocks.form.validate.any" />;
    errors.renewals = <FormattedMessage id="ui-users.blocks.form.validate.any" />;
    errors.requests = <FormattedMessage id="ui-users.blocks.form.validate.any" />;
  }
  if (!item.expirationDate) {
    errors.expirationDate = <FormattedMessage id="ui-users.blocks.form.validate.date" />;
  }
  if (moment(moment(item.expirationDate).format()).isBefore(moment().format())) {
    errors.expirationDate = <FormattedMessage id="ui-users.blocks.form.validate.future" />;
  }
  return errors;
};

class PatronBlockForm extends React.Component {
  static propTypes = {
    user: PropTypes.object,
    pristine: PropTypes.bool,
    submitting: PropTypes.bool,
    invalid: PropTypes.bool,
    selectedItem: PropTypes.object,
    query: PropTypes.object,
    onDeleteItem: PropTypes.func,
    onClose: PropTypes.func,
    initialize: PropTypes.func,
    handleSubmit: PropTypes.func.isRequired,
    connect: PropTypes.func,
    intl: intlShape.isRequired,
    readOnly: PropTypes.bool,
    stripes: PropTypes.object,
  };

  constructor(props) {
    super(props);

    this.handleExpandAll = this.handleExpandAll.bind(this);
    this.handleSectionToggle = this.handleSectionToggle.bind(this);

    this.connectedViewMetaData = props.stripes.connect(ViewMetaData);

    this.state = {
      sections: {
        blockInformationSection: true,
        blockActionsSection: true,
        prueba: true,
      },
      borrowing: false,
      renewals: false,
      requests: false,
      checkedBlocks: {},
    };
  }

  componentDidMount() {
    const item = this.props.selectedItem || {};
    const state = {
      borrowing: (item.id) ? item.borrowing : true,
      renewals: (item.id) ? item.renewals : true,
      requests: (item.id) ? item.requests : true,
    };
    this.setState(state);
    this.props.initialize(state);

    if (item.id) {
      this.props.initialize(item);
    }
  }

  componentDidUpdate(prevProps) {
    if (JSON.stringify(prevProps.selectedItem) !== JSON.stringify(this.props.selectedItem)) {
      const item = this.props.selectedItem || {};
      // eslint-disable-next-line react/no-did-update-set-state
      this.setState({
        borrowing: item.borrowing,
        renewals: item.renewals,
        requests: item.requests,
      });
      this.props.initialize(item);
    }
  }

  handleSectionToggle({ id }) {
    this.setState((curState) => {
      const newState = _.cloneDeep(curState);
      newState.sections[id] = !newState.sections[id];
      return newState;
    });
  }

  handleExpandAll(obj) {
    this.setState((curState) => {
      const newState = _.cloneDeep(curState);
      newState.sections = obj;
      return newState;
    });
  }

  renderFirstMenu = () => (
    <PaneMenu>
      <IconButton
        id="close-patron-block"
        onClick={this.props.onClose}
        title="Close"
        icon="closeX"
      />
    </PaneMenu>
  );

  renderLastMenu = () => {
    const {
      pristine,
      submitting,
      invalid,
      query,
    } = this.props;

    const submit =
      <Button buttonStyle="primary" onClick={this.props.handleSubmit} disabled={pristine || submitting || invalid}>
        {(query.layer === 'edit-block') ? <FormattedMessage id="ui-users.blocks.form.button.save" /> : <FormattedMessage id="ui-users.blocks.form.button.create" />}
      </Button>;
    const del = (query.layer === 'edit-block') ? <Button buttonStyle="danger" onClick={this.props.onDeleteItem}><FormattedMessage id="ui-users.blocks.form.button.delete" /></Button> : '';

    return (
      <PaneMenu>
        {del}
        {submit}
      </PaneMenu>
    );
  }

  onToggleActions = (action) => {
    const { readOnly } = this.props;

    return (e) => {
      if (readOnly) {
        e.preventDefault();
      }
      this.setState(prevState => ({
        [action]: !prevState[action],
      }));
    };
  }

  render() {
    const user = this.props.user || {};
    const { intl } = this.props;
    const title = this.props.query.layer === 'edit-block' ?

        {' '}
        <AppIcon app="users" size="small" />
        {getFullName(user)}
        {' '}

 : 'New Block';
    const userD = this.props.query.layer !== 'edit-block' ? <UserDetails user={user} /> : '';

    return (
      <Pane
        defaultWidth="20%"
        firstMenu={this.renderFirstMenu()}
        paneTitle={title}
        lastMenu={this.renderLastMenu()}
      >
        <TitleManager />
        {userD}
        <Row end="xs">
          <Col xs>
            <ExpandAllButton accordionStatus={this.state.sections} onToggle={this.handleExpandAll} />
          </Col>
        </Row>
        <Row>
          <Col xs>
            <Accordion
              label={<FormattedMessage id="ui-users.blocks.form.label.information" />}
              id="blockInformationSection"
              onToggle={this.handleSectionToggle}
              open={this.state.sections.blockInformationSection}
            >
              {(this.props.selectedItem.metadata) ?
                <Row>
                  <Col xs={12} sm={10} md={7} lg={5}>
                    <this.connectedViewMetaData metadata={this.props.selectedItem.metadata} />
                  </Col>
                </Row> : ''
              }
              <form>
                <Row>
                  <Col xs={12} sm={10} md={7} lg={5}>
                    <Field
                      name="desc"
                      label={<FormattedMessage id="ui-users.blocks.form.label.display" />}
                      component={TextArea}
                      placeholder={intl.formatMessage({ id: 'ui-users.blocks.form.placeholder.desc' })}
                      fullWidth
                    />
                  </Col>
                </Row>
                <Row>
                  <Col xs={12} sm={10} md={7} lg={5}>
                    <Field
                      name="staffInformation"
                      label={<FormattedMessage id="ui-users.blocks.form.label.staff" />}
                      component={TextArea}
                      placeholder={intl.formatMessage({ id: 'ui-users.blocks.form.placeholder.information' })}
                      fullWidth
                    />
                  </Col>
                </Row>
                <Row>
                  <Col xs={12} sm={10} md={7} lg={5}>
                    <Field
                      label={<FormattedMessage id="ui-users.blocks.form.label.message" />}
                      name="patronMessage"
                      component={TextArea}
                      placeholder={intl.formatMessage({ id: 'ui-users.blocks.form.placeholder.message' })}
                      fullWidth
                    />
                  </Col>
                </Row>
                <Row>
                  <Col xs={12} sm={10} md={7} lg={5}>
                    <Field
                      component={Datepicker}
                      dateFormat="YYYY/MM/DD"
                      name="expirationDate"
                      label={<FormattedMessage id="ui-users.blocks.form.label.date" />}
                      backendDateStandard="YYYY/MM/DD"
                      timeZone="UTC"
                      useFocus
                    />
                  </Col>
                </Row>
                <Row>
                  <Col><FormattedMessage id="ui-users.blocks.form.label.block" /></Col>
                </Row>
                <Row>
                  <Col xs={12} sm={10} md={7} lg={5}>
                    <Field
                      name="borrowing"
                      id="borrowing"
                      label={<FormattedMessage id="ui-users.blocks.form.label.borrowing" />}
                      checked={this.state.borrowing}
                      value={this.state.borrowing}
                      onChange={this.onToggleActions('borrowing')}
                      component={Checkbox}
                    />
                  </Col>
                </Row>
                <Row>
                  <Col xs={12} sm={10} md={7} lg={5}>
                    <Field
                      name="renewals"
                      id="renewals"
                      label={<FormattedMessage id="ui-users.blocks.form.label.renewals" />}
                      checked={this.state.renewals}
                      onChange={this.onToggleActions('renewals')}
                      value={this.state.renewals}
                      component={Checkbox}
                    />
                  </Col>
                </Row>
                <Row>
                  <Col xs={12} sm={10} md={7} lg={5}>
                    <Field
                      name="requests"
                      id="requests"
                      label={<FormattedMessage id="ui-users.blocks.form.label.request" />}
                      component={Checkbox}
                      checked={this.state.requests}
                      onChange={this.onToggleActions('requests')}
                      value={this.state.requests}
                    />
                  </Col>
                </Row>
              </form>
            </Accordion>
          </Col>
        </Row>
      </Pane>
    );
  }
}

export default stripesForm({
  form: 'patron-block-form',
  validate,
  fields: [],
})(PatronBlockForm);
<|endoftext|>


<commit_before>// ***********************************************//
//                 models and stores
// ***********************************************//
require('akvo-flow/core');
require('akvo-flow/models/store_def');

FLOW.SurveyGroup = DS.Model.extend({
    didDelete: function() {FLOW.surveyGroupControl.populate();},
    didUpdate: function() {FLOW.surveyGroupControl.populate();},
    didCreate: function() {FLOW.surveyGroupControl.populate();},

	description: DS.attr('string',{defaultValue: ""}),
	name: DS.attr('string',{defaultValue: ""}),
	createdDateTime: DS.attr('string',{defaultValue: ""}),
	lastUpdateDateTime: DS.attr('string',{defaultValue: ""}),
	// the code field is used as name
	code: DS.attr('string',{defaultValue: ""}),
	keyId: DS.attr('number'),
	primaryKey: 'keyId'
});

FLOW.Survey = DS.Model.extend({
	didDelete: function() {FLOW.surveyControl.populate();},
    didUpdate: function() {FLOW.surveyControl.populate();},
    didCreate: function() {FLOW.surveyControl.populate();},

	defaultLanguageCode: DS.attr('string'),
	status: DS.attr('string'),
	code: DS.attr('string'),
	requireApproval: DS.attr('string'),
	version: DS.attr('string'),
	description: DS.attr('string'),
	name: DS.attr('string'),
	displayName: DS.attr('string'),
	keyId: DS.attr('number'),
	pointType: DS.attr('string'),
	surveyGroupId: DS.attr('number'),
	createdDateTime:DS.attr('number'),
	lastUpdateDateTime:DS.attr('number'),
	primaryKey: 'keyId'

});

FLOW.QuestionGroup = DS.Model.extend({
	didDelete: function() {if (FLOW.questionGroupControl.get('allRecordsSaved')) FLOW.questionGroupControl.populate();},
    didUpdate: function() {if (FLOW.questionGroupControl.get('allRecordsSaved')) FLOW.questionGroupControl.populate();},
    didCreate: function() {if (FLOW.questionGroupControl.get('allRecordsSaved')) FLOW.questionGroupControl.populate();},

	order: DS.attr('number'),
	description: DS.attr('string'),
	name: DS.attr('string'),
	path: DS.attr('string'),
	code: DS.attr('string'),
	surveyId: DS.attr('number'),
	displayName: DS.attr('string'),
	keyId: DS.attr('number'),
	isOpen: DS.attr('boolean', {
		defaultValue: 0
	}),
	primaryKey: 'keyId'
});

FLOW.Question = DS.Model.extend({
	allowDecimal: DS.attr('boolean', {defaultValue: 0}),
	allowMultipleFlag: DS.attr('boolean', {defaultValue: 0}),
	allowOtherFlag: DS.attr('boolean', {defaultValue: 0}),
	allowSign: DS.attr('boolean', {defaultValue: 0}),
	collabseable: DS.attr('boolean', {defaultValue: 0}),
	displayName: DS.attr('string'),
	immutable: DS.attr('boolean', {defaultValue: 0}),
	isName: DS.attr('boolean', {defaultValue: 0}),
	keyId: DS.attr('number'),
	mandatoryFlag: DS.attr('boolean', {defaultValue: 0}),
	maxVal: DS.attr('number'),
	minVal: DS.attr('number'),
	optionContainerDto: DS.attr('string'),
	order: DS.attr('number'),
	path: DS.attr('string'),
	questionDependency: DS.attr('string'),
	questionGroupId: DS.attr('number'),
	questionTypeString: DS.attr('string',{defaultValue:"freeText"}),
	surveyId: DS.attr('number'),
	text: DS.attr('string'),
	tip: DS.attr('string'),
	type: DS.attr('string'),
});

FLOW.QuestionOption = DS.Model.extend({
	questionId: DS.attr('number'),
	text: DS.attr('string'),
	keyId: DS.attr('number')
});

FLOW.QuestionOption.FIXTURES = [{
	keyId: 1,
	text: 'teacher',
	questionId: 1
}, {
	keyId: 2,
	text: 'cook',
	questionId: 1
},{
	keyId: 3,
	text: 'minister',
	questionId: 1
},{
	keyId: 4,
	text: 'programmer',
	questionId: 1
}];

FLOW.SurveyAssignment = DS.Model.extend({

});

FLOW.DeviceGroup = DS.Model.extend({
	displayName: DS.attr('string',{defaultValue: ""}),
	code: DS.attr('string',{defaultValue: ""})
});

FLOW.Device = DS.Model.extend({
	deviceType: DS.attr('string',{defaultValue: ""}),
	phoneNumber: DS.attr('string',{defaultValue: ""}),
	esn: DS.attr('string',{defaultValue: ""}),
	deviceIdentifier: DS.attr('string',{defaultValue: ""}),
	inServiceDate: DS.attr('date'),
	outServiceDate: DS.attr('date'),
	lastUpdate: DS.attr('date', {defaultValue: ""}),
	osVersion: DS.attr('string', {defaultValue: ""}),
	lastKnownLat: DS.attr('number', {defaultValue: 0}),
	lastKnownLong:DS.attr('number', {defaultValue: 0}),
	lastKnownAccuracy: DS.attr('number',{defaultValue:0}),
	lastLocationBeaconTime: DS.attr('date', {defaultValue: ""}),
	deviceGroup: DS.attr('string',{defaultValue: ""}),
	keyId: DS.attr('number'),
	primaryKey:'keyId',
	isSelected: DS.attr('boolean', {defaultValue: false})
});

FLOW.SurveyedLocale = DS.Model.extend({
  description:  DS.attr("string", {defaultValue: ""}),
  keyId:        DS.attr("number"),
  latitude:     DS.attr("number"),
  longitude:    DS.attr("number"),
  primaryKey:   "keyId",
  typeMark:     DS.attr("string", {defaultValue: "WATER_POINT"})
});

FLOW.Placemark = DS.Model.extend({
  keyId: DS.attr("number"),
  latitude: DS.attr("number"),
  longitude: DS.attr("number"),
  collectionDate: DS.attr("date"),
  markType: DS.attr("string", {defaultValue: "WATER_POINT"}),
  primaryKey: "keyId"
});<commit_msg>remove displayName from survey model in Ember<commit_after>// ***********************************************//
//                 models and stores
// ***********************************************//
require('akvo-flow/core');
require('akvo-flow/models/store_def');

FLOW.SurveyGroup = DS.Model.extend({
    didDelete: function() {FLOW.surveyGroupControl.populate();},
    didUpdate: function() {FLOW.surveyGroupControl.populate();},
    didCreate: function() {FLOW.surveyGroupControl.populate();},

	description: DS.attr('string',{defaultValue: ""}),
	name: DS.attr('string',{defaultValue: ""}),
	createdDateTime: DS.attr('string',{defaultValue: ""}),
	lastUpdateDateTime: DS.attr('string',{defaultValue: ""}),
	// the code field is used as name
	code: DS.attr('string',{defaultValue: ""}),
	keyId: DS.attr('number'),
	primaryKey: 'keyId'
});

FLOW.Survey = DS.Model.extend({
	didDelete: function() {FLOW.surveyControl.populate();},
    didUpdate: function() {FLOW.surveyControl.populate();},
    didCreate: function() {FLOW.surveyControl.populate();},

	defaultLanguageCode: DS.attr('string'),
	status: DS.attr('string'),
	code: DS.attr('string'),
	requireApproval: DS.attr('string'),
	version: DS.attr('string'),
	description: DS.attr('string'),
	name: DS.attr('string'),
	keyId: DS.attr('number'),
	pointType: DS.attr('string'),
	surveyGroupId: DS.attr('number'),
	createdDateTime:DS.attr('number'),
	lastUpdateDateTime:DS.attr('number'),
	primaryKey: 'keyId'

});

FLOW.QuestionGroup = DS.Model.extend({
	didDelete: function() {if (FLOW.questionGroupControl.get('allRecordsSaved')) FLOW.questionGroupControl.populate();},
    didUpdate: function() {if (FLOW.questionGroupControl.get('allRecordsSaved')) FLOW.questionGroupControl.populate();},
    didCreate: function() {if (FLOW.questionGroupControl.get('allRecordsSaved')) FLOW.questionGroupControl.populate();},

	order: DS.attr('number'),
	description: DS.attr('string'),
	name: DS.attr('string'),
	path: DS.attr('string'),
	code: DS.attr('string'),
	surveyId: DS.attr('number'),
	displayName: DS.attr('string'),
	keyId: DS.attr('number'),
	isOpen: DS.attr('boolean', {
		defaultValue: 0
	}),
	primaryKey: 'keyId'
});

FLOW.Question = DS.Model.extend({
	allowDecimal: DS.attr('boolean', {defaultValue: 0}),
	allowMultipleFlag: DS.attr('boolean', {defaultValue: 0}),
	allowOtherFlag: DS.attr('boolean', {defaultValue: 0}),
	allowSign: DS.attr('boolean', {defaultValue: 0}),
	collabseable: DS.attr('boolean', {defaultValue: 0}),
	displayName: DS.attr('string'),
	immutable: DS.attr('boolean', {defaultValue: 0}),
	isName: DS.attr('boolean', {defaultValue: 0}),
	keyId: DS.attr('number'),
	mandatoryFlag: DS.attr('boolean', {defaultValue: 0}),
	maxVal: DS.attr('number'),
	minVal: DS.attr('number'),
	optionContainerDto: DS.attr('string'),
	order: DS.attr('number'),
	path: DS.attr('string'),
	questionDependency: DS.attr('string'),
	questionGroupId: DS.attr('number'),
	questionTypeString: DS.attr('string',{defaultValue:"freeText"}),
	surveyId: DS.attr('number'),
	text: DS.attr('string'),
	tip: DS.attr('string'),
	type: DS.attr('string'),
});

FLOW.QuestionOption = DS.Model.extend({
	questionId: DS.attr('number'),
	text: DS.attr('string'),
	keyId: DS.attr('number')
});

FLOW.SurveyAssignment = DS.Model.extend({

});

FLOW.DeviceGroup = DS.Model.extend({
	displayName: DS.attr('string',{defaultValue: ""}),
	code: DS.attr('string',{defaultValue: ""})
});

FLOW.Device = DS.Model.extend({
	deviceType: DS.attr('string',{defaultValue: ""}),
	phoneNumber: DS.attr('string',{defaultValue: ""}),
	esn: DS.attr('string',{defaultValue: ""}),
	deviceIdentifier: DS.attr('string',{defaultValue: ""}),
	inServiceDate: DS.attr('date'),
	outServiceDate: DS.attr('date'),
	lastUpdate: DS.attr('date', {defaultValue: ""}),
	osVersion: DS.attr('string', {defaultValue: ""}),
	lastKnownLat: DS.attr('number', {defaultValue: 0}),
	lastKnownLong:DS.attr('number', {defaultValue: 0}),
	lastKnownAccuracy: DS.attr('number',{defaultValue:0}),
	lastLocationBeaconTime: DS.attr('date', {defaultValue: ""}),
	deviceGroup: DS.attr('string',{defaultValue: ""}),
	keyId: DS.attr('number'),
	primaryKey:'keyId',
	isSelected: DS.attr('boolean', {defaultValue: false})
});

FLOW.SurveyedLocale = DS.Model.extend({
  description:  DS.attr("string", {defaultValue: ""}),
  keyId:        DS.attr("number"),
  latitude:     DS.attr("number"),
  longitude:    DS.attr("number"),
  primaryKey:   "keyId",
  typeMark:     DS.attr("string", {defaultValue: "WATER_POINT"})
});

FLOW.Placemark = DS.Model.extend({
  keyId: DS.attr("number"),
  latitude: DS.attr("number"),
  longitude: DS.attr("number"),
  collectionDate: DS.attr("date"),
  markType: DS.attr("string", {defaultValue: "WATER_POINT"}),
  primaryKey: "keyId"
});<|endoftext|>


<commit_before>import m from 'mithril';
import h from '../h';
import facebookButton from './facebook-button';
import projectVM from '../vms/project-vm';

const projectShareBox = {
    controller() {
        return {
            displayEmbed: h.toggleProp(false, true)
        };
    },
    view(ctrl, args) {
        return m('.pop-share.fontcolor-primary', {
            style: 'display: block;'
        }, [
            m('.w-hidden-main.w-hidden-medium.w-clearfix', [
                m('a.btn.btn-small.btn-terciary.btn-inline.u-right', {
                    onclick: args.displayShareBox.toggle
                }, 'Fechar'),
                m('.fontsize-small.fontweight-semibold.u-marginbottom-30', 'Compartilhe este projeto')
            ]),
            m('.w-widget.w-widget-twitter.w-hidden-small.w-hidden-tiny.share-block', [
                m(`iframe[allowtransparency="true"][width="120px"][height="22px"][frameborder="0"][scrolling="no"][src="//platform.twitter.com/widgets/tweet_button.8d007ddfc184e6776be76fe9e5e52d69.en.html#_=1442425984936&count=horizontal&dnt=false&id=twitter-widget-1&lang=en&original_referer=https%3A%2F%2Fwww.catarse.me%2Fpt%2F${args.project().permalink}&size=m&text=Confira%20o%20projeto%20${args.project().name}%20no%20%40catarse&type=share&url=https%3A%2F%2Fwww.catarse.me%2Fpt%2F${args.project().permalink}%3Fref%3Dtwitter%26utm_source%3Dtwitter.com%26utm_medium%3Dsocial%26utm_campaign%3Dproject_share&via=catarse"]`)
            ]),
            projectVM.isSubscription(args.project) ? null : m('a.w-hidden-small.widget-embed.w-hidden-tiny.fontsize-small.link-hidden.fontcolor-secondary[href="javascript:void(0);"]', {
                onclick: ctrl.displayEmbed.toggle
            }, '< embed >'), (ctrl.displayEmbed() ? m('.embed-expanded.u-margintop-30', [
                m('.fontsize-small.fontweight-semibold.u-marginbottom-20', 'Insira um widget em seu site'),
                m('.w-form', [
                    m(`input.w-input[type="text"][value="<iframe frameborder="0" height="340px" src="https://www.catarse.me/pt/projects/${args.project().project_id}/embed" width="300px" scrolling="no"></iframe>"]`)
                ]),
                m('.card-embed', [
                    m(`iframe[frameborder="0"][height="350px"][src="/projects/${args.project().project_id}/embed"][width="300px"][scrolling="no"]`)
                ])
            ]) : ''),
            args.project().permalink ? m.component(facebookButton, {
                mobile: true,
                url: `https://www.catarse.me/${args.project().permalink}?ref=facebook&utm_source=facebook.com&utm_medium=social&utm_campaign=project_share`
            }) : '',
            m(`a.w-hidden-main.w-hidden-medium.btn.btn-medium.btn-tweet.u-marginbottom-20[href="https://twitter.com/intent/tweet?text=Acabei%20de%20apoiar%20o%20projeto%20${encodeURIComponent(args.project().name)}%20https://www.catarse.me/${args.project().permalink}%3Fref%3Dtwitter%26utm_source%3Dtwitter.com%26utm_medium%3Dsocial%26utm_campaign%3Dproject_share"][target="_blank"]`, [
                m('span.fa.fa-twitter'), ' Tweet'
            ]),
            m('a.w-hidden-main.w-hidden-medium.btn.btn-medium[data-action="share/whatsapp/share"]', {
                href: `whatsapp://send?text=${encodeURIComponent(`https://www.catarse.me/${args.project().permalink}/?ref=whatsapp&utm_source=whatsapp&utm_medium=social&utm_campaign=project_share`)}`
            }, [m('span.fa.fa-whatsapp'), ' Whatsapp'])
        ]);
    }
};

export default projectShareBox;
<commit_msg>show widget on sub projects<commit_after>import m from 'mithril';
import h from '../h';
import facebookButton from './facebook-button';

const projectShareBox = {
    controller() {
        return {
            displayEmbed: h.toggleProp(false, true)
        };
    },
    view(ctrl, args) {
        return m('.pop-share.fontcolor-primary', {
            style: 'display: block;'
        }, [
            m('.w-hidden-main.w-hidden-medium.w-clearfix', [
                m('a.btn.btn-small.btn-terciary.btn-inline.u-right', {
                    onclick: args.displayShareBox.toggle
                }, 'Fechar'),
                m('.fontsize-small.fontweight-semibold.u-marginbottom-30', 'Compartilhe este projeto')
            ]),
            m('.w-widget.w-widget-twitter.w-hidden-small.w-hidden-tiny.share-block', [
                m(`iframe[allowtransparency="true"][width="120px"][height="22px"][frameborder="0"][scrolling="no"][src="//platform.twitter.com/widgets/tweet_button.8d007ddfc184e6776be76fe9e5e52d69.en.html#_=1442425984936&count=horizontal&dnt=false&id=twitter-widget-1&lang=en&original_referer=https%3A%2F%2Fwww.catarse.me%2Fpt%2F${args.project().permalink}&size=m&text=Confira%20o%20projeto%20${args.project().name}%20no%20%40catarse&type=share&url=https%3A%2F%2Fwww.catarse.me%2Fpt%2F${args.project().permalink}%3Fref%3Dtwitter%26utm_source%3Dtwitter.com%26utm_medium%3Dsocial%26utm_campaign%3Dproject_share&via=catarse"]`)
            ]),
            m('a.w-hidden-small.widget-embed.w-hidden-tiny.fontsize-small.link-hidden.fontcolor-secondary[href="javascript:void(0);"]', {
                onclick: ctrl.displayEmbed.toggle
            }, '< embed >'), (ctrl.displayEmbed() ? m('.embed-expanded.u-margintop-30', [
                m('.fontsize-small.fontweight-semibold.u-marginbottom-20', 'Insira um widget em seu site'),
                m('.w-form', [
                    m(`input.w-input[type="text"][value="<iframe frameborder="0" height="340px" src="https://www.catarse.me/pt/projects/${args.project().project_id}/embed" width="300px" scrolling="no"></iframe>"]`)
                ]),
                m('.card-embed', [
                    m(`iframe[frameborder="0"][height="350px"][src="/projects/${args.project().project_id}/embed"][width="300px"][scrolling="no"]`)
                ])
            ]) : ''),
            args.project().permalink ? m.component(facebookButton, {
                mobile: true,
                url: `https://www.catarse.me/${args.project().permalink}?ref=facebook&utm_source=facebook.com&utm_medium=social&utm_campaign=project_share`
            }) : '',
            m(`a.w-hidden-main.w-hidden-medium.btn.btn-medium.btn-tweet.u-marginbottom-20[href="https://twitter.com/intent/tweet?text=Acabei%20de%20apoiar%20o%20projeto%20${encodeURIComponent(args.project().name)}%20https://www.catarse.me/${args.project().permalink}%3Fref%3Dtwitter%26utm_source%3Dtwitter.com%26utm_medium%3Dsocial%26utm_campaign%3Dproject_share"][target="_blank"]`, [
                m('span.fa.fa-twitter'), ' Tweet'
            ]),
            m('a.w-hidden-main.w-hidden-medium.btn.btn-medium[data-action="share/whatsapp/share"]', {
                href: `whatsapp://send?text=${encodeURIComponent(`https://www.catarse.me/${args.project().permalink}/?ref=whatsapp&utm_source=whatsapp&utm_medium=social&utm_campaign=project_share`)}`
            }, [m('span.fa.fa-whatsapp'), ' Whatsapp'])
        ]);
    }
};

export default projectShareBox;
<|endoftext|>