<commit_before>import { createElement } from 'lwc';
import GeBatchGiftEntryHeader from 'c/geBatchGiftEntryHeader';
import { getRecord } from 'lightning/uiRecordApi';
import { registerLdsTestWireAdapter, registerApexTestWireAdapter } from '@salesforce/sfdx-lwc-jest';

import getGiftBatchTotalsBy from '@salesforce/apex/GE_GiftEntryController.getGiftBatchTotalsBy';
import isElevateCustomer from '@salesforce/apex/GE_GiftEntryController.isElevateCustomer';

const mockGetRecord = require('./data/getRecord.json');
const getRecordAdapter = registerLdsTestWireAdapter(getRecord);
const isElevateCustomerAdapter = registerApexTestWireAdapter(isElevateCustomer);

const APEX_GIFT_BATCH_TOTALS_BY_SUCCESS = {
    'PROCESSED': 10,
    'FAILED': 5,
    'TOTAL': 20
};

const APEX_GIFT_BATCH_TOTALS_WITHOUT_ROWS = {
    'PROCESSED': 0,
    'FAILED': 0,
    'TOTAL': 0
};

jest.mock(
    "@salesforce/apex/GE_GiftEntryController.getGiftBatchTotalsBy",
    () => {
        return {
            default: jest.fn()
        };
    },
    { virtual: true }
);

describe('c-ge-batch-gift-entry-header', () => {
    afterEach(() => {
        clearDOM();
        jest.clearAllMocks();
    });

    function flushPromises() {
        return new Promise((resolve) => setImmediate(resolve));
    }

    const setup = () => {
        const element = createElement('c-ge-batch-gift-entry-header', {
            is: GeBatchGiftEntryHeader
        });
        document.body.appendChild(element);
        getRecordAdapter.emit(mockGetRecord);
        return element;
    }

    describe('getRecord @wire data', () => {
        it('renders user record details', async () => {
            getGiftBatchTotalsBy.mockResolvedValue(APEX_GIFT_BATCH_TOTALS_BY_SUCCESS);
            const element = setup();

            await flushPromises();
            const headerElement = element.shadowRoot.querySelectorAll('c-util-page-header');
            const headerElements = headerElement[0].shadowRoot.querySelectorAll('h1');
            const text = headerElements[0].querySelectorAll('.uiOutputText');
            expect(text[0].innerHTML).toBe(mockGetRecord.fields.Name.value);
        });
    });

    describe('gift entry batch header elements', () => {
        it('should render three action buttons', async () => {
            getGiftBatchTotalsBy.mockResolvedValue(APEX_GIFT_BATCH_TOTALS_BY_SUCCESS);
            const element = setup();

            await flushPromises();
            const buttons = element.shadowRoot.querySelectorAll('lightning-button');
            expect(buttons.length).toBe(3);
        });

        it('renders detail row', async () => {
            getGiftBatchTotalsBy.mockResolvedValue(APEX_GIFT_BATCH_TOTALS_BY_SUCCESS);
            const element = setup();

            await flushPromises();
            const headerDetailRows = element.shadowRoot.querySelectorAll('c-util-page-header-detail-row');
            expect(headerDetailRows.length).toBe(1);
        });

        it('does not render detail row', async () => {
            getGiftBatchTotalsBy.mockResolvedValue(APEX_GIFT_BATCH_TOTALS_WITHOUT_ROWS);
            const element = setup();

            await flushPromises();
            const headerDetailRows = element.shadowRoot.querySelectorAll('c-util-page-header-detail-row');
            expect(headerDetailRows.length).toBe(0);
        });

        it('renders detail blocks for records processed and records failed with correct record counts on load', async () => {
            getGiftBatchTotalsBy.mockResolvedValue(APEX_GIFT_BATCH_TOTALS_BY_SUCCESS);
            let element = setup();

            isElevateCustomerAdapter.emit(true);

            await flushPromises();

            const detailBlocks = element.shadowRoot.querySelectorAll('c-util-page-header-detail-block');
            expect(detailBlocks.length).toBe(2);

            const processedGifts = detailBlocks[0].querySelectorAll('p')[1].innerHTML;
            expect(processedGifts).toBe('10 / 20');

            const failedGifts = detailBlocks[1].querySelectorAll('p')[1].innerHTML;
            expect(failedGifts).toBe('5');
        });
    });
});<commit_msg>Add checks for is elevate customer to JEST<commit_after>import { createElement } from 'lwc';
import GeBatchGiftEntryHeader from 'c/geBatchGiftEntryHeader';
import { getRecord } from 'lightning/uiRecordApi';
import { registerLdsTestWireAdapter, registerApexTestWireAdapter } from '@salesforce/sfdx-lwc-jest';

import getGiftBatchTotalsBy from '@salesforce/apex/GE_GiftEntryController.getGiftBatchTotalsBy';
import isElevateCustomer from '@salesforce/apex/GE_GiftEntryController.isElevateCustomer';

const mockGetRecord = require('./data/getRecord.json');
const getRecordAdapter = registerLdsTestWireAdapter(getRecord);
const isElevateCustomerAdapter = registerApexTestWireAdapter(isElevateCustomer);

const APEX_GIFT_BATCH_TOTALS_BY_SUCCESS = {
    'PROCESSED': 10,
    'FAILED': 5,
    'TOTAL': 20
};

const APEX_GIFT_BATCH_TOTALS_WITHOUT_ROWS = {
    'PROCESSED': 0,
    'FAILED': 0,
    'TOTAL': 0
};

jest.mock(
    "@salesforce/apex/GE_GiftEntryController.getGiftBatchTotalsBy",
    () => {
        return {
            default: jest.fn()
        };
    },
    { virtual: true }
);

describe('c-ge-batch-gift-entry-header', () => {
    afterEach(() => {
        clearDOM();
        jest.clearAllMocks();
    });

    function flushPromises() {
        return new Promise((resolve) => setImmediate(resolve));
    }

    const setup = () => {
        const element = createElement('c-ge-batch-gift-entry-header', {
            is: GeBatchGiftEntryHeader
        });
        document.body.appendChild(element);
        getRecordAdapter.emit(mockGetRecord);
        return element;
    }

    describe('getRecord @wire data', () => {
        it('renders user record details', async () => {
            getGiftBatchTotalsBy.mockResolvedValue(APEX_GIFT_BATCH_TOTALS_BY_SUCCESS);
            const element = setup();

            await flushPromises();
            const headerElement = element.shadowRoot.querySelectorAll('c-util-page-header');
            const headerElements = headerElement[0].shadowRoot.querySelectorAll('h1');
            const text = headerElements[0].querySelectorAll('.uiOutputText');
            expect(text[0].innerHTML).toBe(mockGetRecord.fields.Name.value);
        });
    });

    describe('gift entry batch header elements', () => {
        it('should render three action buttons', async () => {
            getGiftBatchTotalsBy.mockResolvedValue(APEX_GIFT_BATCH_TOTALS_BY_SUCCESS);
            const element = setup();

            await flushPromises();
            const buttons = element.shadowRoot.querySelectorAll('lightning-button');
            expect(buttons.length).toBe(3);
        });

        it('renders detail row', async () => {
            getGiftBatchTotalsBy.mockResolvedValue(APEX_GIFT_BATCH_TOTALS_BY_SUCCESS);
            const element = setup();

            isElevateCustomerAdapter.emit(false);

            await flushPromises();
            const headerDetailRows = element.shadowRoot.querySelectorAll('c-util-page-header-detail-row');
            expect(headerDetailRows.length).toBe(1);
        });

        it('does not render detail row', async () => {
            getGiftBatchTotalsBy.mockResolvedValue(APEX_GIFT_BATCH_TOTALS_WITHOUT_ROWS);
            const element = setup();

            await flushPromises();
            const headerDetailRows = element.shadowRoot.querySelectorAll('c-util-page-header-detail-row');
            expect(headerDetailRows.length).toBe(0);
        });

        it('renders detail blocks for records processed and records failed with correct record counts on load', async () => {
            getGiftBatchTotalsBy.mockResolvedValue(APEX_GIFT_BATCH_TOTALS_BY_SUCCESS);
            let element = setup();

            isElevateCustomerAdapter.emit(true);

            await flushPromises();

            const detailBlocks = element.shadowRoot.querySelectorAll('c-util-page-header-detail-block');
            expect(detailBlocks.length).toBe(2);

            const processedGifts = detailBlocks[0].querySelectorAll('p')[1].innerHTML;
            expect(processedGifts).toBe('10 / 20');

            const failedGifts = detailBlocks[1].querySelectorAll('p')[1].innerHTML;
            expect(failedGifts).toBe('5');
        });
    });
});<|endoftext|>


<commit_before>function WalletBuyAssetsController($modal, $scope, $http, $q, userService, walletTransactionService) {
    // [ Template Initialization ]

  $scope.currencyList.forEach(function(e, i) {
    if (e.symbol == "BTC"){
      $scope.addressList = userService.getAddressesWithPrivkey(e.tradableAddresses);
      $scope.$parent.$parent.selectedAddress = $scope.addressList[0];
    }
  });

  // OInitialize values.
  var transaction = $scope.global['buyOffer'];
  $http.get('/v1/transaction/tx/' + transaction.tx_hash + '.json').success(function(data) {
    var tx = data[0];
    $scope.selectedCoin=tx.currency_str;

    if(parseInt(tx.currencyId) <3) {
      $scope.sendPlaceholderValue = '1.00000000';
      $scope.sendPlaceholderStep = $scope.sendPlaceholderMin = '0.00000001';
      $scope.displayedAbbreviation = tx.currency_str;
    } else {
      $http.get("/v1/property/"+tx.currencyId.replace(new RegExp("^0+"), "") +".json", function(data) {
        var property = data[0];
        if(property.propertyType == "0001")
          $scope.sendPlaceholderValue = $scope.sendPlaceholderStep = $scope.sendPlaceholderMin = '1';
        else  {
          $scope.sendPlaceholderValue = '1.00000000';
          $scope.sendPlaceholderStep = $scope.sendPlaceholderMin = '0.00000001';
        }

        $scope.displayedAbbreviation = property.propertyName + " #" + property.currencyId;
      });
    }
  });
  // [ Buy Form Helpers ]

  function getUnsignedBuyTransaction(buyerAddress, pubKey, buyAmount, fee, saleTransactionHash) {
    var deferred = $q.defer();

    var url = '/v1/exchange/accept/';
    $http.post(url, {
        buyer: buyerAddress,
        pubKey: pubKey,
        amount: buyAmount,
        fee: fee,
        tx_hash: saleTransactionHash
      }).success(function(data) {
        return deferred.resolve(data);
      }).error(function(data) {
      return deferred.reject(data);
    });

    return deferred.promise;
  }

  function prepareBuyTransaction(buyer, amt, hash, fee, privkeyphrase, $modalScope) {
    var addressData = userService.getAddress(buyer);
    var privKey = new Bitcoin.ECKey.decodeEncryptedFormat(addressData.privkey, addressData.address); // Using address as temporary password
    var pubKey = privKey.getPubKeyHex();

    $scope.sendTxPromise = getUnsignedBuyTransaction(buyer, pubKey, amt, fee, hash);
    $scope.sendTxPromise.then(function(successData) {
      if (successData.status != 'OK') {
        $modalScope.waiting = false;
        $modalScope.sendError = true;
        $modalScope.error = 'Error preparing buy transaction: ' + successData.data.error;
      } else {
        //var successData = successData.data ??
        var sourceScript = successData.sourceScript;
        var unsignedTransaction = successData.transaction;

        try {

          var bytes = Bitcoin.Util.hexToBytes(unsignedTransaction);
          var transaction = Bitcoin.Transaction.deserialize(bytes);
          var script = parseScript(successData.sourceScript);

          transaction.ins[0].script = script;

          //DEBUG console.log('before',transaction, Bitcoin.Util.bytesToHex(transaction.serialize()))
          var signedSuccess = transaction.signWithKey(privKey);

          var finalTransaction = Bitcoin.Util.bytesToHex(transaction.serialize());

          //Showing the user the transaction hash doesn't work right now
          //var transactionHash = Bitcoin.Util.bytesToHex(transaction.getHash().reverse())

          walletTransactionService.pushSignedTransaction(finalTransaction).then(function(successData) {
            var successData = successData.data;
            if (successData.pushed.match(/submitted|success/gi) != null) {
              $modalScope.waiting = false;
              $modalScope.sendSuccess = true;
              $modalScope.url = 'http://blockchain.info/address/' + buyer + '?sort=0';
            } else {
              $modalScope.waiting = false;
              $modalScope.sendError = true;
              $modalScope.error = successData.pushed; //Unspecified error, show user
            }
            console.log('server response: ', successData);
          }, function(errorData) {
            $modalScope.waiting = false;
            $modalScope.sendError = true;
            if (errorData.message)
              $modalScope.error = 'Server error: ' + errorData.message;
            else
              if (errorData.data)
                $modalScope.error = 'Server error: ' + errorData.data;
              else
                $modalScope.error = 'Unknown Server Error';
            console.log('server error: ', errorData);
          });

          //DEBUG console.log(addressData, privKey, bytes, transaction, script, signedSuccess, finalTransaction );
          function parseScript(script) {
            var newScript = new Bitcoin.Script();
            var s = script.split(" ");
            for (var i = 0; i < s.length; i++) {
              if (Bitcoin.Opcode.map.hasOwnProperty(s[i])) {
                newScript.writeOp(Bitcoin.Opcode.map[s[i]]);
              } else {
                newScript.writeBytes(Bitcoin.Util.hexToBytes(s[i]));
              }
            }
            return newScript;
          }
        } catch (e) {
          $modalScope.sendError = true;
          if (e.message)
            $modalScope.error = 'Error sending transaction: ' + e.message;
          else
            if (e.data)
              $modalScope.error = 'Error sending transaction: ' + e.data;
            else
              $modalScope.error = 'Unknown error sending transaction';
          console.log('Error sending transaction', e);
        }
      }
    }, function(errorData) {
      $modalScope.sendError = true;
      if (errorData.message)
        $modalScope.error = 'Server error: ' + errorData.message;
      else
        if (errorData.data)
          $modalScope.error = 'Server error: ' + errorData.data;
        else
          $modalScope.error = 'Unknown Server Error';
      console.log('server error: ', errorData);
    });
  }

  $scope.validateBuyForm = function() {
    var dustValue = 5430;
    var minerMinimum = 10000;
    var nonZeroValue = 1;
    var divisible = $scope.selectedCoin.divisible;

    var convertToSatoshi = [
        $scope.minerFees,
        $scope.buyAmount,
        $scope.balanceData[0],
        $scope.balanceData[1]
      ];

    if (!divisible) {
      delete convertToSatoshi[ convertToSatoshi.indexOf( $scope.saleAmount ) ];
      delete convertToSatoshi[ convertToSatoshi.indexOf( $scope.balanceData[0] ) ];
    }

    var convertedValues = $scope.convertDisplayedValue( convertToSatoshi );

    var minerFees = +convertedValues[0];
    var buyAmount = divisible ? +convertedValues[1] : +$scope.buyAmount;

    var balance = divisible ? +convertedValues[2] : +$scope.balanceData[0];
    var btcbalance = +convertedValues[3];

    var coin = $scope.selectedCoin.symbol;
    var address = $scope.selectedAddress;
    var saleHash = $scope.buySaleID;

    var required = [coin, address, buyAmount, minerFees, balance, btcbalance, $scope.buyForm.$valid];
    console.log(required);
    var error = 'Please ';
    if ($scope.buyForm.$valid == false) {
      error += 'make sure all fields are completely filled, ';
    }
    //should be valid hash
    //if( walletTransactionService.validAddress(sendTo) == false) {
    //   error += 'make sure you are sending to a valid MSC/BTC address, '
    //}
    if (coin == 'BTC') {
      error += 'make sure your sale is for MSC or TMSC, ';
    }
    if( ((coin == 'MSC') || (coin == 'TMSC')) ) {
      if (buyAmount < nonZeroValue)
        error += 'make sure your send amount is non-zero, ';
      if (minerFees < minerMinimum)
        error += 'make sure your fee entry is at least 0.0001 BTC, ';
      if ((minerFees <= btcbalance) == false)
        error += 'make sure you have enough Bitcoin to cover your fees, ';
    }
    if (error.length < 8) {
      $scope.$parent.showErrors = false;

      // open modal
      var modalInstance = $modal.open({
        templateUrl: '/partials/wallet_buy_modal.html',
        controller: function($scope, $rootScope, userService, data, prepareBuyTransaction, getUnsignedBuyTransaction, convertSatoshiToDisplayedValue) {
          $scope.sendSuccess = false, $scope.sendError = false, $scope.waiting = false, $scope.privKeyPass = {};
          $scope.convertSatoshiToDisplayedValue=convertSatoshiToDisplayedValue,
          $scope.displayedAbbreviation=data.displayedAbbreviation,
          $scope.buyAmount=data.amt,
          $scope.minerFees= data.fee,
          $scope.selectedCoin= data.selectedCoin;

          $scope.ok = function() {
            $scope.clicked = true;
            $scope.waiting = true;
            prepareBuyTransaction(data.buyer, data.amt, data.hash, data.fee, $scope.privKeyPass, $scope);
          };
        },
        resolve: {
          data: function() {
            return {
              buyer: address,
              amt: buyAmount,
              hash: saleHash,
              fee: minerFees,
              selectedCoin: $scope.selectedCoin,
              displayedAbbreviation: $scope.displayedAbbreviation
            };
          },
          prepareBuyTransaction: function() {
            return prepareBuyTransaction;
          },
          getUnsignedBuyTransaction: function() {
            return getUnsignedBuyTransaction;
          },
          pushSignedTransaction: function() {
            return walletTransactionService.pushSignedTransaction;
          },
          convertSatoshiToDisplayedValue: function() {
            return $scope.convertSatoshiToDisplayedValue;
          }
        }
      });
    } else {
      error += 'and try again.';
      $scope.error = error;
      $scope.$parent.showErrors = true;
    }
  };

}
<commit_msg>Fixed divisible value that caused errors. Updated dust value.<commit_after>function WalletBuyAssetsController($modal, $scope, $http, $q, userService, walletTransactionService) {
    // [ Template Initialization ]

  $scope.currencyList.forEach(function(e, i) {
    if (e.symbol == "BTC"){
      $scope.addressList = userService.getAddressesWithPrivkey(e.tradableAddresses);
      $scope.$parent.$parent.selectedAddress = $scope.addressList[0];
    }
  });

  // OInitialize values.
  var transaction = $scope.global['buyOffer'];
  $http.get('/v1/transaction/tx/' + transaction.tx_hash + '.json').success(function(data) {
    var tx = data[0];
    $scope.selectedCoin=tx.currency_str;

    if(parseInt(tx.currencyId) <3) {
      $scope.divisible = true;
      $scope.sendPlaceholderValue = '1.00000000';
      $scope.sendPlaceholderStep = $scope.sendPlaceholderMin = '0.00000001';
      $scope.displayedAbbreviation = tx.currency_str;
    } else {
      $http.get("/v1/property/"+tx.currencyId.replace(new RegExp("^0+"), "") +".json", function(data) {
        var property = data[0];
        if(property.propertyType == "0001"){
          $scope.divisible =false;
          $scope.sendPlaceholderValue = $scope.sendPlaceholderStep = $scope.sendPlaceholderMin = '1';
        } else  {
          $scope.divisible = true;
          $scope.sendPlaceholderValue = '1.00000000';
          $scope.sendPlaceholderStep = $scope.sendPlaceholderMin = '0.00000001';
        }

        $scope.displayedAbbreviation = property.propertyName + " #" + property.currencyId;
      });
    }
  });
  // [ Buy Form Helpers ]

  function getUnsignedBuyTransaction(buyerAddress, pubKey, buyAmount, fee, saleTransactionHash) {
    var deferred = $q.defer();

    var url = '/v1/exchange/accept/';
    $http.post(url, {
        buyer: buyerAddress,
        pubKey: pubKey,
        amount: buyAmount,
        fee: fee,
        tx_hash: saleTransactionHash
      }).success(function(data) {
        return deferred.resolve(data);
      }).error(function(data) {
      return deferred.reject(data);
    });

    return deferred.promise;
  }

  function prepareBuyTransaction(buyer, amt, hash, fee, privkeyphrase, $modalScope) {
    var addressData = userService.getAddress(buyer);
    var privKey = new Bitcoin.ECKey.decodeEncryptedFormat(addressData.privkey, addressData.address); // Using address as temporary password
    var pubKey = privKey.getPubKeyHex();

    $scope.sendTxPromise = getUnsignedBuyTransaction(buyer, pubKey, amt, fee, hash);
    $scope.sendTxPromise.then(function(successData) {
      if (successData.status != 'OK') {
        $modalScope.waiting = false;
        $modalScope.sendError = true;
        $modalScope.error = 'Error preparing buy transaction: ' + successData.data.error;
      } else {
        //var successData = successData.data ??
        var sourceScript = successData.sourceScript;
        var unsignedTransaction = successData.transaction;

        try {

          var bytes = Bitcoin.Util.hexToBytes(unsignedTransaction);
          var transaction = Bitcoin.Transaction.deserialize(bytes);
          var script = parseScript(successData.sourceScript);

          transaction.ins[0].script = script;

          //DEBUG console.log('before',transaction, Bitcoin.Util.bytesToHex(transaction.serialize()))
          var signedSuccess = transaction.signWithKey(privKey);

          var finalTransaction = Bitcoin.Util.bytesToHex(transaction.serialize());

          //Showing the user the transaction hash doesn't work right now
          //var transactionHash = Bitcoin.Util.bytesToHex(transaction.getHash().reverse())

          walletTransactionService.pushSignedTransaction(finalTransaction).then(function(successData) {
            var successData = successData.data;
            if (successData.pushed.match(/submitted|success/gi) != null) {
              $modalScope.waiting = false;
              $modalScope.sendSuccess = true;
              $modalScope.url = 'http://blockchain.info/address/' + buyer + '?sort=0';
            } else {
              $modalScope.waiting = false;
              $modalScope.sendError = true;
              $modalScope.error = successData.pushed; //Unspecified error, show user
            }
            console.log('server response: ', successData);
          }, function(errorData) {
            $modalScope.waiting = false;
            $modalScope.sendError = true;
            if (errorData.message)
              $modalScope.error = 'Server error: ' + errorData.message;
            else
              if (errorData.data)
                $modalScope.error = 'Server error: ' + errorData.data;
              else
                $modalScope.error = 'Unknown Server Error';
            console.log('server error: ', errorData);
          });

          //DEBUG console.log(addressData, privKey, bytes, transaction, script, signedSuccess, finalTransaction );
          function parseScript(script) {
            var newScript = new Bitcoin.Script();
            var s = script.split(" ");
            for (var i = 0; i < s.length; i++) {
              if (Bitcoin.Opcode.map.hasOwnProperty(s[i])) {
                newScript.writeOp(Bitcoin.Opcode.map[s[i]]);
              } else {
                newScript.writeBytes(Bitcoin.Util.hexToBytes(s[i]));
              }
            }
            return newScript;
          }
        } catch (e) {
          $modalScope.sendError = true;
          if (e.message)
            $modalScope.error = 'Error sending transaction: ' + e.message;
          else
            if (e.data)
              $modalScope.error = 'Error sending transaction: ' + e.data;
            else
              $modalScope.error = 'Unknown error sending transaction';
          console.log('Error sending transaction', e);
        }
      }
    }, function(errorData) {
      $modalScope.sendError = true;
      if (errorData.message)
        $modalScope.error = 'Server error: ' + errorData.message;
      else
        if (errorData.data)
          $modalScope.error = 'Server error: ' + errorData.data;
        else
          $modalScope.error = 'Unknown Server Error';
      console.log('server error: ', errorData);
    });
  }

  $scope.validateBuyForm = function() {
    var dustValue = 5757;
    var minerMinimum = 10000;
    var nonZeroValue = 1;
    var divisible = $scope.divisible;

    var convertToSatoshi = [
        $scope.minerFees,
        $scope.buyAmount,
        $scope.balanceData[0],
        $scope.balanceData[1]
      ];

    if (!divisible) {
      delete convertToSatoshi[ convertToSatoshi.indexOf( $scope.saleAmount ) ];
      delete convertToSatoshi[ convertToSatoshi.indexOf( $scope.balanceData[0] ) ];
    }

    var convertedValues = $scope.convertDisplayedValue( convertToSatoshi );

    var minerFees = +convertedValues[0];
    var buyAmount = divisible ? +convertedValues[1] : +$scope.buyAmount;

    var balance = divisible ? +convertedValues[2] : +$scope.balanceData[0];
    var btcbalance = +convertedValues[3];

    var coin = $scope.selectedCoin.symbol;
    var address = $scope.selectedAddress;
    var saleHash = $scope.buySaleID;

    var required = [coin, address, buyAmount, minerFees, balance, btcbalance, $scope.buyForm.$valid];
    console.log(required);
    var error = 'Please ';
    if ($scope.buyForm.$valid == false) {
      error += 'make sure all fields are completely filled, ';
    }
    //should be valid hash
    //if( walletTransactionService.validAddress(sendTo) == false) {
    //   error += 'make sure you are sending to a valid MSC/BTC address, '
    //}
    if (coin == 'BTC') {
      error += 'make sure your sale is for MSC or TMSC, ';
    }
    if( ((coin == 'MSC') || (coin == 'TMSC')) ) {
      if (buyAmount < nonZeroValue)
        error += 'make sure your send amount is non-zero, ';
      if (minerFees < minerMinimum)
        error += 'make sure your fee entry is at least 0.0001 BTC, ';
      if ((minerFees <= btcbalance) == false)
        error += 'make sure you have enough Bitcoin to cover your fees, ';
    }
    if (error.length < 8) {
      $scope.$parent.showErrors = false;

      // open modal
      var modalInstance = $modal.open({
        templateUrl: '/partials/wallet_buy_modal.html',
        controller: function($scope, $rootScope, userService, data, prepareBuyTransaction, getUnsignedBuyTransaction, convertSatoshiToDisplayedValue) {
          $scope.sendSuccess = false, $scope.sendError = false, $scope.waiting = false, $scope.privKeyPass = {};
          $scope.convertSatoshiToDisplayedValue=convertSatoshiToDisplayedValue,
          $scope.displayedAbbreviation=data.displayedAbbreviation,
          $scope.buyAmount=data.amt,
          $scope.minerFees= data.fee,
          $scope.selectedCoin= data.selectedCoin;

          $scope.ok = function() {
            $scope.clicked = true;
            $scope.waiting = true;
            prepareBuyTransaction(data.buyer, data.amt, data.hash, data.fee, $scope.privKeyPass, $scope);
          };
        },
        resolve: {
          data: function() {
            return {
              buyer: address,
              amt: buyAmount,
              hash: saleHash,
              fee: minerFees,
              selectedCoin: $scope.selectedCoin,
              displayedAbbreviation: $scope.displayedAbbreviation
            };
          },
          prepareBuyTransaction: function() {
            return prepareBuyTransaction;
          },
          getUnsignedBuyTransaction: function() {
            return getUnsignedBuyTransaction;
          },
          pushSignedTransaction: function() {
            return walletTransactionService.pushSignedTransaction;
          },
          convertSatoshiToDisplayedValue: function() {
            return $scope.convertSatoshiToDisplayedValue;
          }
        }
      });
    } else {
      error += 'and try again.';
      $scope.error = error;
      $scope.$parent.showErrors = true;
    }
  };

}
<|endoftext|>


<commit_before>function WalletBuyAssetsController($modal, $scope, $http, $q, userService, walletTransactionService) {
    // [ Template Initialization ]

  $scope.currencyList.forEach(function(e, i) {
    if (e.symbol == "BTC"){
      $scope.addressList = userService.getAddressesWithPrivkey(e.tradableAddresses);
      $scope.$parent.$parent.selectedAddress = $scope.addressList[0];
    }
  });

  // OInitialize values.
  var transaction = $scope.global['buyOffer'];
  $http.get('/v1/transaction/tx/' + transaction.tx_hash + '.json').success(function(data) {
    var tx = data[0];
    $scope.selectedCoin=tx.currency_str;

    if(parseInt(tx.currencyId) <3) {
      $scope.divisible = true;
      $scope.sendPlaceholderValue = '1.00000000';
      $scope.sendPlaceholderStep = $scope.sendPlaceholderMin = '0.00000001';
      $scope.displayedAbbreviation = tx.currency_str;
    } else {
      $http.get("/v1/property/"+tx.currencyId.replace(new RegExp("^0+"), "") +".json", function(data) {
        var property = data[0];
        if(property.propertyType == "0001"){
          $scope.divisible =false;
          $scope.sendPlaceholderValue = $scope.sendPlaceholderStep = $scope.sendPlaceholderMin = '1';
        } else  {
          $scope.divisible = true;
          $scope.sendPlaceholderValue = '1.00000000';
          $scope.sendPlaceholderStep = $scope.sendPlaceholderMin = '0.00000001';
        }

        $scope.displayedAbbreviation = property.propertyName + " #" + property.currencyId;
      });
    }
  });
  // [ Buy Form Helpers ]

  function getUnsignedBuyTransaction(buyerAddress, pubKey, buyAmount, fee, saleTransactionHash) {
    var deferred = $q.defer();

    var url = '/v1/exchange/accept/';
    $http.post(url, {
        buyer: buyerAddress,
        pubKey: pubKey,
        amount: buyAmount,
        fee: fee,
        tx_hash: saleTransactionHash
      }).success(function(data) {
        return deferred.resolve(data);
      }).error(function(data) {
      return deferred.reject(data);
    });

    return deferred.promise;
  }

  function prepareBuyTransaction(buyer, amt, hash, fee, privkeyphrase, $modalScope) {
    var addressData = userService.getAddress(buyer);
    var privKey = new Bitcoin.ECKey.decodeEncryptedFormat(addressData.privkey, addressData.address); // Using address as temporary password
    var pubKey = privKey.getPubKeyHex();

    $scope.sendTxPromise = getUnsignedBuyTransaction(buyer, pubKey, amt, fee, hash);
    $scope.sendTxPromise.then(function(successData) {
      if (successData.status != 'OK') {
        $modalScope.waiting = false;
        $modalScope.sendError = true;
        $modalScope.error = 'Error preparing buy transaction: ' + successData.data.error;
      } else {
        //var successData = successData.data ??
        var sourceScript = successData.sourceScript;
        var unsignedTransaction = successData.transaction;

        try {

          var bytes = Bitcoin.Util.hexToBytes(unsignedTransaction);
          var transaction = Bitcoin.Transaction.deserialize(bytes);
          var script = parseScript(successData.sourceScript);

          transaction.ins[0].script = script;

          //DEBUG console.log('before',transaction, Bitcoin.Util.bytesToHex(transaction.serialize()))
          var signedSuccess = transaction.signWithKey(privKey);

          var finalTransaction = Bitcoin.Util.bytesToHex(transaction.serialize());

          //Showing the user the transaction hash doesn't work right now
          //var transactionHash = Bitcoin.Util.bytesToHex(transaction.getHash().reverse())

          walletTransactionService.pushSignedTransaction(finalTransaction).then(function(successData) {
            var successData = successData.data;
            if (successData.pushed.match(/submitted|success/gi) != null) {
              $modalScope.waiting = false;
              $modalScope.sendSuccess = true;
              $modalScope.url = 'http://blockchain.info/address/' + buyer + '?sort=0';
            } else {
              $modalScope.waiting = false;
              $modalScope.sendError = true;
              $modalScope.error = successData.pushed; //Unspecified error, show user
            }
            console.log('server response: ', successData);
          }, function(errorData) {
            $modalScope.waiting = false;
            $modalScope.sendError = true;
            if (errorData.message)
              $modalScope.error = 'Server error: ' + errorData.message;
            else
              if (errorData.data)
                $modalScope.error = 'Server error: ' + errorData.data;
              else
                $modalScope.error = 'Unknown Server Error';
            console.log('server error: ', errorData);
          });

          //DEBUG console.log(addressData, privKey, bytes, transaction, script, signedSuccess, finalTransaction );
          function parseScript(script) {
            var newScript = new Bitcoin.Script();
            var s = script.split(" ");
            for (var i = 0; i < s.length; i++) {
              if (Bitcoin.Opcode.map.hasOwnProperty(s[i])) {
                newScript.writeOp(Bitcoin.Opcode.map[s[i]]);
              } else {
                newScript.writeBytes(Bitcoin.Util.hexToBytes(s[i]));
              }
            }
            return newScript;
          }
        } catch (e) {
          $modalScope.sendError = true;
          if (e.message)
            $modalScope.error = 'Error sending transaction: ' + e.message;
          else
            if (e.data)
              $modalScope.error = 'Error sending transaction: ' + e.data;
            else
              $modalScope.error = 'Unknown error sending transaction';
          console.log('Error sending transaction', e);
        }
      }
    }, function(errorData) {
      $modalScope.sendError = true;
      if (errorData.message)
        $modalScope.error = 'Server error: ' + errorData.message;
      else
        if (errorData.data)
          $modalScope.error = 'Server error: ' + errorData.data;
        else
          $modalScope.error = 'Unknown Server Error';
      console.log('server error: ', errorData);
    });
  }

  $scope.validateBuyForm = function() {
    var dustValue = 5757;
    var minerMinimum = 10000;
    var nonZeroValue = 1;
    var divisible = $scope.divisible;

    var convertToSatoshi = [
        $scope.minerFees,
        $scope.buyAmount,
        $scope.balanceData[0],
        $scope.balanceData[1]
      ];

    if (!divisible) {
      delete convertToSatoshi[ convertToSatoshi.indexOf( $scope.buyAmount ) ];
      delete convertToSatoshi[ convertToSatoshi.indexOf( $scope.balanceData[0] ) ];
    }

    var convertedValues = $scope.convertDisplayedValue( convertToSatoshi );

    var minerFees = +convertedValues[0];
    var buyAmount = divisible ? +convertedValues[1] : +$scope.buyAmount;

    var balance = divisible ? +convertedValues[2] : +$scope.balanceData[0];
    var btcbalance = +convertedValues[3];

    var coin = $scope.selectedCoin;
    var address = $scope.selectedAddress;
    var saleHash = $scope.buySaleID;

    var required = [coin, address, buyAmount, minerFees, balance, btcbalance, $scope.buyForm.$valid];
    console.log(required);
    var error = 'Please ';
    if ($scope.buyForm.$valid == false) {
      error += 'make sure all fields are completely filled, ';
    }
    //should be valid hash
    //if( walletTransactionService.validAddress(sendTo) == false) {
    //   error += 'make sure you are sending to a valid MSC/BTC address, '
    //}
    if (coin == 'Bitcoin') {
      error += 'make sure your sale is for MSC or TMSC, ';
    }
    if( ((coin == 'Mastercoin') || (coin == 'Test Mastercoin')) ) {
      if (buyAmount < nonZeroValue)
        error += 'make sure your send amount is non-zero, ';
      if (minerFees < minerMinimum)
        error += 'make sure your fee entry is at least 0.0001 BTC, ';
      if ((minerFees <= btcbalance) == false)
        error += 'make sure you have enough Bitcoin to cover your fees, ';
    }
    if (error.length < 8) {
      $scope.$parent.showErrors = false;

      // open modal
      var modalInstance = $modal.open({
        templateUrl: '/partials/wallet_buy_modal.html',
        controller: function($scope, $rootScope, userService, data, prepareBuyTransaction, getUnsignedBuyTransaction, convertSatoshiToDisplayedValue) {
          $scope.sendSuccess = false, $scope.sendError = false, $scope.waiting = false, $scope.privKeyPass = {};
          $scope.convertSatoshiToDisplayedValue=convertSatoshiToDisplayedValue,
          $scope.displayedAbbreviation=data.displayedAbbreviation,
          $scope.buyAmount=data.amt,
          $scope.minerFees= data.fee,
          $scope.selectedCoin= data.selectedCoin;

          $scope.ok = function() {
            $scope.clicked = true;
            $scope.waiting = true;
            prepareBuyTransaction(data.buyer, data.amt, data.hash, data.fee, $scope.privKeyPass, $scope);
          };
        },
        resolve: {
          data: function() {
            return {
              buyer: address,
              amt: buyAmount,
              hash: saleHash,
              fee: minerFees,
              selectedCoin: $scope.selectedCoin,
              displayedAbbreviation: $scope.displayedAbbreviation
            };
          },
          prepareBuyTransaction: function() {
            return prepareBuyTransaction;
          },
          getUnsignedBuyTransaction: function() {
            return getUnsignedBuyTransaction;
          },
          pushSignedTransaction: function() {
            return walletTransactionService.pushSignedTransaction;
          },
          convertSatoshiToDisplayedValue: function() {
            return $scope.convertSatoshiToDisplayedValue;
          }
        }
      });
    } else {
      error += 'and try again.';
      $scope.error = error;
      $scope.$parent.showErrors = true;
    }
  };

}
<commit_msg>Fixed sale hash asignment.<commit_after>function WalletBuyAssetsController($modal, $scope, $http, $q, userService, walletTransactionService) {
    // [ Template Initialization ]

  $scope.currencyList.forEach(function(e, i) {
    if (e.symbol == "BTC"){
      $scope.addressList = userService.getAddressesWithPrivkey(e.tradableAddresses);
      $scope.$parent.$parent.selectedAddress = $scope.addressList[0];
    }
  });

  // OInitialize values.
  var transaction = $scope.global['buyOffer'];
  $scope.buySaleID = transaction.tx_hash;
  $http.get('/v1/transaction/tx/' + transaction.tx_hash + '.json').success(function(data) {
    var tx = data[0];
    $scope.selectedCoin=tx.currency_str;

    if(parseInt(tx.currencyId) <3) {
      $scope.divisible = true;
      $scope.sendPlaceholderValue = '1.00000000';
      $scope.sendPlaceholderStep = $scope.sendPlaceholderMin = '0.00000001';
      $scope.displayedAbbreviation = tx.currency_str;
    } else {
      $http.get("/v1/property/"+tx.currencyId.replace(new RegExp("^0+"), "") +".json", function(data) {
        var property = data[0];
        if(property.propertyType == "0001"){
          $scope.divisible =false;
          $scope.sendPlaceholderValue = $scope.sendPlaceholderStep = $scope.sendPlaceholderMin = '1';
        } else  {
          $scope.divisible = true;
          $scope.sendPlaceholderValue = '1.00000000';
          $scope.sendPlaceholderStep = $scope.sendPlaceholderMin = '0.00000001';
        }

        $scope.displayedAbbreviation = property.propertyName + " #" + property.currencyId;
      });
    }
  });
  // [ Buy Form Helpers ]

  function getUnsignedBuyTransaction(buyerAddress, pubKey, buyAmount, fee, saleTransactionHash) {
    var deferred = $q.defer();

    var url = '/v1/exchange/accept/';
    $http.post(url, {
        buyer: buyerAddress,
        pubKey: pubKey,
        amount: buyAmount,
        fee: fee,
        tx_hash: saleTransactionHash
      }).success(function(data) {
        return deferred.resolve(data);
      }).error(function(data) {
      return deferred.reject(data);
    });

    return deferred.promise;
  }

  function prepareBuyTransaction(buyer, amt, hash, fee, privkeyphrase, $modalScope) {
    var addressData = userService.getAddress(buyer);
    var privKey = new Bitcoin.ECKey.decodeEncryptedFormat(addressData.privkey, addressData.address); // Using address as temporary password
    var pubKey = privKey.getPubKeyHex();

    $scope.sendTxPromise = getUnsignedBuyTransaction(buyer, pubKey, amt, fee, hash);
    $scope.sendTxPromise.then(function(successData) {
      if (successData.status != 'OK') {
        $modalScope.waiting = false;
        $modalScope.sendError = true;
        $modalScope.error = 'Error preparing buy transaction: ' + successData.data.error;
      } else {
        //var successData = successData.data ??
        var sourceScript = successData.sourceScript;
        var unsignedTransaction = successData.transaction;

        try {

          var bytes = Bitcoin.Util.hexToBytes(unsignedTransaction);
          var transaction = Bitcoin.Transaction.deserialize(bytes);
          var script = parseScript(successData.sourceScript);

          transaction.ins[0].script = script;

          //DEBUG console.log('before',transaction, Bitcoin.Util.bytesToHex(transaction.serialize()))
          var signedSuccess = transaction.signWithKey(privKey);

          var finalTransaction = Bitcoin.Util.bytesToHex(transaction.serialize());

          //Showing the user the transaction hash doesn't work right now
          //var transactionHash = Bitcoin.Util.bytesToHex(transaction.getHash().reverse())

          walletTransactionService.pushSignedTransaction(finalTransaction).then(function(successData) {
            var successData = successData.data;
            if (successData.pushed.match(/submitted|success/gi) != null) {
              $modalScope.waiting = false;
              $modalScope.sendSuccess = true;
              $modalScope.url = 'http://blockchain.info/address/' + buyer + '?sort=0';
            } else {
              $modalScope.waiting = false;
              $modalScope.sendError = true;
              $modalScope.error = successData.pushed; //Unspecified error, show user
            }
            console.log('server response: ', successData);
          }, function(errorData) {
            $modalScope.waiting = false;
            $modalScope.sendError = true;
            if (errorData.message)
              $modalScope.error = 'Server error: ' + errorData.message;
            else
              if (errorData.data)
                $modalScope.error = 'Server error: ' + errorData.data;
              else
                $modalScope.error = 'Unknown Server Error';
            console.log('server error: ', errorData);
          });

          //DEBUG console.log(addressData, privKey, bytes, transaction, script, signedSuccess, finalTransaction );
          function parseScript(script) {
            var newScript = new Bitcoin.Script();
            var s = script.split(" ");
            for (var i = 0; i < s.length; i++) {
              if (Bitcoin.Opcode.map.hasOwnProperty(s[i])) {
                newScript.writeOp(Bitcoin.Opcode.map[s[i]]);
              } else {
                newScript.writeBytes(Bitcoin.Util.hexToBytes(s[i]));
              }
            }
            return newScript;
          }
        } catch (e) {
          $modalScope.sendError = true;
          if (e.message)
            $modalScope.error = 'Error sending transaction: ' + e.message;
          else
            if (e.data)
              $modalScope.error = 'Error sending transaction: ' + e.data;
            else
              $modalScope.error = 'Unknown error sending transaction';
          console.log('Error sending transaction', e);
        }
      }
    }, function(errorData) {
      $modalScope.sendError = true;
      if (errorData.message)
        $modalScope.error = 'Server error: ' + errorData.message;
      else
        if (errorData.data)
          $modalScope.error = 'Server error: ' + errorData.data;
        else
          $modalScope.error = 'Unknown Server Error';
      console.log('server error: ', errorData);
    });
  }

  $scope.validateBuyForm = function() {
    var dustValue = 5757;
    var minerMinimum = 10000;
    var nonZeroValue = 1;
    var divisible = $scope.divisible;

    var convertToSatoshi = [
        $scope.minerFees,
        $scope.buyAmount,
        $scope.balanceData[0],
        $scope.balanceData[1]
      ];

    if (!divisible) {
      delete convertToSatoshi[ convertToSatoshi.indexOf( $scope.buyAmount ) ];
      delete convertToSatoshi[ convertToSatoshi.indexOf( $scope.balanceData[0] ) ];
    }

    var convertedValues = $scope.convertDisplayedValue( convertToSatoshi );

    var minerFees = +convertedValues[0];
    var buyAmount = divisible ? +convertedValues[1] : +$scope.buyAmount;

    var balance = divisible ? +convertedValues[2] : +$scope.balanceData[0];
    var btcbalance = +convertedValues[3];

    var coin = $scope.selectedCoin;
    var address = $scope.selectedAddress;
    var saleHash = $scope.buySaleID;

    var required = [coin, address, buyAmount, minerFees, balance, btcbalance, $scope.buyForm.$valid];
    console.log(required);
    var error = 'Please ';
    if ($scope.buyForm.$valid == false) {
      error += 'make sure all fields are completely filled, ';
    }
    //should be valid hash
    //if( walletTransactionService.validAddress(sendTo) == false) {
    //   error += 'make sure you are sending to a valid MSC/BTC address, '
    //}
    if (coin == 'Bitcoin') {
      error += 'make sure your sale is for MSC or TMSC, ';
    }
    if( ((coin == 'Mastercoin') || (coin == 'Test Mastercoin')) ) {
      if (buyAmount < nonZeroValue)
        error += 'make sure your send amount is non-zero, ';
      if (minerFees < minerMinimum)
        error += 'make sure your fee entry is at least 0.0001 BTC, ';
      if ((minerFees <= btcbalance) == false)
        error += 'make sure you have enough Bitcoin to cover your fees, ';
    }
    if (error.length < 8) {
      $scope.$parent.showErrors = false;

      // open modal
      var modalInstance = $modal.open({
        templateUrl: '/partials/wallet_buy_modal.html',
        controller: function($scope, $rootScope, userService, data, prepareBuyTransaction, getUnsignedBuyTransaction, convertSatoshiToDisplayedValue) {
          $scope.sendSuccess = false, $scope.sendError = false, $scope.waiting = false, $scope.privKeyPass = {};
          $scope.convertSatoshiToDisplayedValue=convertSatoshiToDisplayedValue,
          $scope.displayedAbbreviation=data.displayedAbbreviation,
          $scope.buyAmount=data.amt,
          $scope.minerFees= data.fee,
          $scope.selectedCoin= data.selectedCoin;

          $scope.ok = function() {
            $scope.clicked = true;
            $scope.waiting = true;
            prepareBuyTransaction(data.buyer, data.amt, data.hash, data.fee, $scope.privKeyPass, $scope);
          };
        },
        resolve: {
          data: function() {
            return {
              buyer: address,
              amt: buyAmount,
              hash: saleHash,
              fee: minerFees,
              selectedCoin: $scope.selectedCoin,
              displayedAbbreviation: $scope.displayedAbbreviation
            };
          },
          prepareBuyTransaction: function() {
            return prepareBuyTransaction;
          },
          getUnsignedBuyTransaction: function() {
            return getUnsignedBuyTransaction;
          },
          pushSignedTransaction: function() {
            return walletTransactionService.pushSignedTransaction;
          },
          convertSatoshiToDisplayedValue: function() {
            return $scope.convertSatoshiToDisplayedValue;
          }
        }
      });
    } else {
      error += 'and try again.';
      $scope.error = error;
      $scope.$parent.showErrors = true;
    }
  };

}
<|endoftext|>


<commit_before>var controllers;

controllers = angular.module("proBebe.controllers");

controllers.controller("MessagesCtrl", function($ionicPlatform, $scope, $state, $rootScope, $ionicPopup, $ionicModal, $cordovaToast, $window, Child, Profile, Constants, Microdonation) {
  $rootScope.$on('networkOffline', function(event, networkState) {
    $cordovaToast.showLongBottom('Sem conexão');
  });

  function init() {
    Profile.get()
    .then(function(response) {
      $scope.profile = response.data
      if (!$scope.selectedChild) {
        $scope.selectedChild = $scope.profile.children[0];
        initDonationProcess();
      }
    }).catch(function(err) {
      console.log(err);
      $cordovaToast.showLongBottom('Não foi possível carregar as mensagens');
    });
  }

  function initDonationProcess() {
    Microdonation.setProfileType($scope.profile.profile_type);
    if(Microdonation.isProfileDonor()){
      Microdonation.sendMessages(function(){

      });
    }
  }

  $scope.selectChild = function(child) {
    $scope.selectedChild = child;
    $rootScope.$emit('childSelected', child);
    $state.go('messages');
  };

  $scope.openInBrowser = function(url) {
    $window.open(url, '_system');
  }

  $scope.$on('childSelected', function(child) {
    $scope.selectedChild = child;
  });

  $scope.$on('pushMessageReceived', init);
  init();
});
<commit_msg>Fixing bug list child menu<commit_after>var controllers;

controllers = angular.module("proBebe.controllers");

controllers.controller("MessagesCtrl", function($ionicPlatform, $scope, $state, $rootScope, $ionicPopup, $ionicModal, $cordovaToast, $window, Child, Profile, Constants, Microdonation) {
  $rootScope.$on('networkOffline', function(event, networkState) {
    $cordovaToast.showLongBottom('Sem conexão');
  });

  function init() {
    Profile.get()
    .then(function(response) {
      $scope.profile = response.data
        $scope.children = $scope.profile.children;
      if (!$scope.selectedChild) {
        $scope.selectedChild = $scope.profile.children[0];
        initDonationProcess();
      }
    }).catch(function(err) {
      console.log(err);
      $cordovaToast.showLongBottom('Não foi possível carregar as mensagens');
    });
  }

  function initDonationProcess() {
    Microdonation.setProfileType($scope.profile.profile_type);
    if(Microdonation.isProfileDonor()){
      Microdonation.sendMessages(function(){

      });
    }
  }

  $scope.selectChild = function(child) {
    $scope.selectedChild = child;
    $rootScope.$emit('childSelected', child);
    $state.go('messages');
  };

  $scope.openInBrowser = function(url) {
    $window.open(url, '_system');
  }

  $scope.$on('childSelected', function(child) {
    $scope.selectedChild = child;
  });

  $scope.$on('pushMessageReceived', init);
  init();
});
<|endoftext|>


<commit_before>
define([
    './visualize/highlight',
    './visualize/options',
    './visualize/themes',
    './visualize/checkChartHeight',
    './visualize/loadVisDeferred',
    './visualize/initTabNav',
    './visualize/enableInlineEditing',
    './visualize/liveUpdate',
    './visualize/updateSize',
    'js/misc/classify',
    './visualize/colorpicker',
    'js/misc/jquery.easing'],

function(initHighlightSeries, visOptions, themes, checkChartHeight, loadVisDfd,
    initTabNav, enableInlineEditing, liveUpdate, updateSize, classify) {

    var _typeHasChanged = false,
        _themeHasChanged = false,
        _axesHaveChanged = false,
        _transposed = false,
        __thumbTimer,
        __updateSizeTimer,
        chart = dw.backend.currentChart,
        visMetas = {},
        iframe = $('#iframe-vis');

    function init(themesJSON, _visMetas, visJSON) {

        themes.init(themesJSON);

        visMetas = _visMetas;

        dw.backend.__currentVisLoaded = loadVisDfd.promise();

        chart.onSave(onChartSave);

        syncUI();

        chart.load().done(onDatasetLoaded);

        iframe.load(iframeLoaded);
        iframe.ready(iframeReady);

        // initialize some UI actions
        initTabNav();
        initTransposeLink();
        initVisSelector();
        initResizeChart();

        //
        initChartSize();

        // init visualization options
        require(['dw/chart/visualize/options'], function(options) {
            options.init(chart, visJSON);
        });

    }

    function onChartSave(chart) {
        if (_themeHasChanged) {
            iframe.one('load', updateVisBackground);
            _.some(themes.all(), function(theme) {
                if (theme.id == chart.get('theme')) {
                    var w = theme.default_width || chart.get('metadata.publish.embed-width'),
                        h = theme.default_height || chart.get('metadata.publish.embed-height');
                    updateSize(w, h);
                    return true;
                }
            });
        }

        if (_typeHasChanged) {
            // remove all notifications
            $("#notifications .notification").fadeOutAndRemove();
            loadOptions().done(function() {
                loadVis();
            });
        }

        if (_themeHasChanged) {
            // load new visualization options
            themes.load().done(function() {
                loadOptions().done(function() {
                    loadVis();
                    themes.updateUI();
                });
            });
        }

        if (_axesHaveChanged || _transposed) {
            loadOptions().done(function() {
                loadVis();
            });
        }

        _themeHasChanged = false;
        _typeHasChanged = false;
        _axesHaveChanged = false;
        _transposed = false;

        var iframeWin = iframe.get(0).contentWindow;
        if (iframeWin.__dw && iframeWin.__dw.saved) {
            iframeWin.__dw.saved();
        }
        scheduleThumbnail();
        checkChartHeight();
    }

    function syncUI() {
        chart.sync('#select-theme', 'theme');
        chart.sync('#text-title', 'title');
        chart.sync('#text-intro', 'metadata.describe.intro');
        chart.sync('#describe-source-name', 'metadata.describe.source-name');
        chart.sync('#describe-source-url', 'metadata.describe.source-url');

        chart.onChange(function(chart, key, value) {
            if (key == 'type') _typeHasChanged = true;
            if (key == 'theme') _themeHasChanged = true;
            if (key.substr(0, 13) == 'metadata.axes') _axesHaveChanged = true;
            if (key == 'metadata.data.transpose') _transposed = true;
            liveUpdate.update(iframe, chart.attributes());
        });
    }

    function iframeLoaded() {
        updateVisBackground();
        var win = $('#iframe-vis').get(0).contentWindow,
            chk;

        chk = setInterval(function() {  // wait a little more
            if (win.__dw.vis) {
                clearInterval(chk);
                liveUpdate.init(iframe);
                win.__dw.vis.rendered().done(function() {
                    checkChartHeight();
                });
            }
        }, 100);

        $(win).unload(function() {
            iframe.ready(iframeReady);
        });
    }

    function iframeReady() {
        var iframe_window = $('#iframe-vis').get(0).contentWindow;
        $(window).on('message', function(evt) {
            evt = evt.originalEvent;
            if (evt.source == iframe_window) {
                if (evt.data == 'datawrapper:vis:init') {
                    iframe_window.dw_alert = dw.backend.alert;
                    iframe_window.__dw.backend = dw.backend;
                }
                if (evt.data == 'datawrapper:vis:rendered') {
                    enableInlineEditing($('#iframe-vis'), chart);
                    if (initHighlightSeries) initHighlightSeries();
                }
                if (evt.data.slice(0, 7) == 'notify:') {
                    dw.backend.notify(evt.data.slice(7));
                }
            }
        });
    }

    function loadOptions() {
        var loaded = $.Deferred();
        $('#vis-options').load(
            '/xhr/'+chart.get('id')+'/vis-options?nocache='+Math.random(),
            function() {
                setTimeout(function() {
                    loaded.resolve();
                    // trigger event in order to resync options
                    loadVisDfd.resolve();
                    themes.updateUI();
                }, 500);
            }
        );
        return loaded.promise();
    }

    function initTransposeLink() {
        $('#btn-transpose').click(function(e) {
            e.preventDefault();
            chart.set('metadata.data.transpose', !chart.get('metadata.data.transpose'));
            chart.load().done(onDatasetLoaded);
            setTimeout(function() {
                loadOptions();
            }, 2000);
        });
    }

    function initVisSelector() {
        // graphical vis selector
        var unfolded = $('.vis-selector-unfolded'),
            folded = $('.vis-selector-folded'),
            thumbs = $('.vis-thumb'),
            selVis = $('.vis-selected');
        unfolded.show().data('h', unfolded.height()).hide();
        thumbs.click(function(e) {
            var thumb = $(e.target);
            if (!thumb.hasClass('vis-thumb')) thumb = thumb.parents('.vis-thumb');
            thumbs.removeClass('active');
            thumb.addClass('active');
            selVis.html('' + thumb.data('title'));
            setTimeout(function() {
                /*folded.show();
                unfolded.animate({ height: 0 }, 300, 'easeOutExpo', function() {
                    unfolded.hide();
                });*/
                chart.set('type', thumb.data('id'));
            }, 100);
        });

        folded.click(function() {
            folded.hide();
            unfolded.height(0).show().animate({ height: unfolded.data('h') }, 300);
        });

        unfolded.show();
        folded.hide();
    }

    function initResizeChart() {
        $('.resize-chart a').click(function(e) {
            e.preventDefault();
            var dim = $(e.target).html().split('×');
            $('#resize-w').val(dim[0]);
            $('#resize-h').val(dim[1]);
            updateSize();
        });
    }

    function initChartSize() {
        var cw = chart.get('metadata.publish.embed-width', $('#iframe-wrapper').width()),
            ch = chart.get('metadata.publish.embed-height', $('#iframe-wrapper').height());
        $('#resize-w').val(cw);
        $('#resize-h').val(ch);
        $('.resize-chart input').change(_updateSize);
        $('#iframe-wrapper').width(cw);
        $('#iframe-wrapper').height(ch);
    }

    /** Set into `dw.backend.currentVis` the edited visualization (editor side) */
    function loadVis() {
        dw.backend.currentVis = dw.visualization(chart.get('type'));
        dw.backend.currentVis.chart(chart);
        dw.backend.currentVis.dataset = chart.dataset().reset();
        dw.backend.currentVis.meta = visMetas[chart.get('type')];
        loadVisDfd.resolve();
    }

    function scheduleThumbnail() {
        clearTimeout(__thumbTimer);
        __thumbTimer = setTimeout(function() {
            dw.backend.snapshot(iframe, dw.backend.currentChart.get('id'), 'm', 260, 160);
        }, 500);
    }

    function onDatasetLoaded() {
        loadVis();
        if (initHighlightSeries) initHighlightSeries();
        _.each(themes.all(), function(theme) {
            if (theme.id == chart.get('theme')) {
                var w = chart.get('metadata.publish.embed-width', theme.default_width || 560),
                    h = chart.get('metadata.publish.embed-height', theme.default_height || 400);
                updateSize(w, h);
                return false;
            }
        });
        themes.load();
    }

    function updateVisBackground() {  // and show msg if chart needs more space
        var iframe = $('#iframe-vis').contents(),
            bgcol =  $('body', iframe).css('background-color'),
            white = bgcol == 'rgb(255, 255, 255)' || bgcol == '#ffffff' || bgcol == 'white' || bgcol == 'transparent',
            border = white ? '#ffffff' : '#bbb';

        bgcol = dw.backend.currentChart.get('metadata.publish.contextBg') || dw.backend.currentChart.get('metadata.publish.background');

        $('#iframe-wrapper').css({
            'background-color': white ? '#ffffff' : bgcol,
            'border-color': border
        });
    }

    // chart resizing
    function _updateSize() {
        clearTimeout(__updateSizeTimer);
        __updateSizeTimer = setTimeout(updateSize, 300);
    }

    return {
        init: init
    };

});<commit_msg>refactoring, removing inline require call<commit_after>
define([
    './visualize/highlight',
    './visualize/options',
    './visualize/themes',
    './visualize/checkChartHeight',
    './visualize/loadVisDeferred',
    './visualize/initTabNav',
    './visualize/enableInlineEditing',
    './visualize/liveUpdate',
    './visualize/updateSize',
    './visualize/options',
    'js/misc/classify',
    './visualize/colorpicker',
    'js/misc/jquery.easing'],

function(initHighlightSeries, visOptions, themes, checkChartHeight, loadVisDfd,
    initTabNav, enableInlineEditing, liveUpdate, updateSize, options, classify) {

    var _typeHasChanged = false,
        _themeHasChanged = false,
        _axesHaveChanged = false,
        _transposed = false,
        __thumbTimer,
        __updateSizeTimer,
        chart = dw.backend.currentChart,
        visMetas = {},
        iframe = $('#iframe-vis');

    function init(themesJSON, _visMetas, visJSON) {

        themes.init(themesJSON);

        visMetas = _visMetas;

        dw.backend.__currentVisLoaded = loadVisDfd.promise();

        chart.onSave(onChartSave);

        syncUI();

        chart.load().done(onDatasetLoaded);

        iframe.load(iframeLoaded);
        iframe.ready(iframeReady);

        // initialize some UI actions
        initTabNav();
        initTransposeLink();
        initVisSelector();
        initResizeChart();

        //
        initChartSize();

        options.init(chart, visJSON);
    }

    function onChartSave(chart) {
        if (_themeHasChanged) {
            iframe.one('load', updateVisBackground);
            _.some(themes.all(), function(theme) {
                if (theme.id == chart.get('theme')) {
                    var w = theme.default_width || chart.get('metadata.publish.embed-width'),
                        h = theme.default_height || chart.get('metadata.publish.embed-height');
                    updateSize(w, h);
                    return true;
                }
            });
        }

        if (_typeHasChanged) {
            // remove all notifications
            $("#notifications .notification").fadeOutAndRemove();
            loadOptions().done(function() {
                loadVis();
            });
        }

        if (_themeHasChanged) {
            // load new visualization options
            themes.load().done(function() {
                loadOptions().done(function() {
                    loadVis();
                    themes.updateUI();
                });
            });
        }

        if (_axesHaveChanged || _transposed) {
            loadOptions().done(function() {
                loadVis();
            });
        }

        _themeHasChanged = false;
        _typeHasChanged = false;
        _axesHaveChanged = false;
        _transposed = false;

        var iframeWin = iframe.get(0).contentWindow;
        if (iframeWin.__dw && iframeWin.__dw.saved) {
            iframeWin.__dw.saved();
        }
        scheduleThumbnail();
        checkChartHeight();
    }

    function syncUI() {
        chart.sync('#select-theme', 'theme');
        chart.sync('#text-title', 'title');
        chart.sync('#text-intro', 'metadata.describe.intro');
        chart.sync('#describe-source-name', 'metadata.describe.source-name');
        chart.sync('#describe-source-url', 'metadata.describe.source-url');

        chart.onChange(function(chart, key, value) {
            if (key == 'type') _typeHasChanged = true;
            if (key == 'theme') _themeHasChanged = true;
            if (key.substr(0, 13) == 'metadata.axes') _axesHaveChanged = true;
            if (key == 'metadata.data.transpose') _transposed = true;
            liveUpdate.update(iframe, chart.attributes());
        });
    }

    function iframeLoaded() {
        updateVisBackground();
        var win = $('#iframe-vis').get(0).contentWindow,
            chk;

        chk = setInterval(function() {  // wait a little more
            if (win.__dw.vis) {
                clearInterval(chk);
                liveUpdate.init(iframe);
                win.__dw.vis.rendered().done(function() {
                    checkChartHeight();
                });
            }
        }, 100);

        $(win).unload(function() {
            iframe.ready(iframeReady);
        });
    }

    function iframeReady() {
        var iframe_window = $('#iframe-vis').get(0).contentWindow;
        $(window).on('message', function(evt) {
            evt = evt.originalEvent;
            if (evt.source == iframe_window) {
                if (evt.data == 'datawrapper:vis:init') {
                    iframe_window.dw_alert = dw.backend.alert;
                    iframe_window.__dw.backend = dw.backend;
                }
                if (evt.data == 'datawrapper:vis:rendered') {
                    enableInlineEditing($('#iframe-vis'), chart);
                    if (initHighlightSeries) initHighlightSeries();
                }
                if (evt.data.slice(0, 7) == 'notify:') {
                    dw.backend.notify(evt.data.slice(7));
                }
            }
        });
    }

    function loadOptions() {
        var loaded = $.Deferred();
        $('#vis-options').load(
            '/xhr/'+chart.get('id')+'/vis-options?nocache='+Math.random(),
            function() {
                setTimeout(function() {
                    loaded.resolve();
                    // trigger event in order to resync options
                    loadVisDfd.resolve();
                    themes.updateUI();
                }, 500);
            }
        );
        return loaded.promise();
    }

    function initTransposeLink() {
        $('#btn-transpose').click(function(e) {
            e.preventDefault();
            chart.set('metadata.data.transpose', !chart.get('metadata.data.transpose'));
            chart.load().done(onDatasetLoaded);
            setTimeout(function() {
                loadOptions();
            }, 2000);
        });
    }

    function initVisSelector() {
        // graphical vis selector
        var unfolded = $('.vis-selector-unfolded'),
            folded = $('.vis-selector-folded'),
            thumbs = $('.vis-thumb'),
            selVis = $('.vis-selected');
        unfolded.show().data('h', unfolded.height()).hide();
        thumbs.click(function(e) {
            var thumb = $(e.target);
            if (!thumb.hasClass('vis-thumb')) thumb = thumb.parents('.vis-thumb');
            thumbs.removeClass('active');
            thumb.addClass('active');
            selVis.html('' + thumb.data('title'));
            setTimeout(function() {
                /*folded.show();
                unfolded.animate({ height: 0 }, 300, 'easeOutExpo', function() {
                    unfolded.hide();
                });*/
                chart.set('type', thumb.data('id'));
            }, 100);
        });

        folded.click(function() {
            folded.hide();
            unfolded.height(0).show().animate({ height: unfolded.data('h') }, 300);
        });

        unfolded.show();
        folded.hide();
    }

    function initResizeChart() {
        $('.resize-chart a').click(function(e) {
            e.preventDefault();
            var dim = $(e.target).html().split('×');
            $('#resize-w').val(dim[0]);
            $('#resize-h').val(dim[1]);
            updateSize();
        });
    }

    function initChartSize() {
        var cw = chart.get('metadata.publish.embed-width', $('#iframe-wrapper').width()),
            ch = chart.get('metadata.publish.embed-height', $('#iframe-wrapper').height());
        $('#resize-w').val(cw);
        $('#resize-h').val(ch);
        $('.resize-chart input').change(_updateSize);
        $('#iframe-wrapper').width(cw);
        $('#iframe-wrapper').height(ch);
    }

    /** Set into `dw.backend.currentVis` the edited visualization (editor side) */
    function loadVis() {
        dw.backend.currentVis = dw.visualization(chart.get('type'));
        dw.backend.currentVis.chart(chart);
        dw.backend.currentVis.dataset = chart.dataset().reset();
        dw.backend.currentVis.meta = visMetas[chart.get('type')];
        loadVisDfd.resolve();
    }

    function scheduleThumbnail() {
        clearTimeout(__thumbTimer);
        __thumbTimer = setTimeout(function() {
            dw.backend.snapshot(iframe, dw.backend.currentChart.get('id'), 'm', 260, 160);
        }, 500);
    }

    function onDatasetLoaded() {
        loadVis();
        if (initHighlightSeries) initHighlightSeries();
        _.each(themes.all(), function(theme) {
            if (theme.id == chart.get('theme')) {
                var w = chart.get('metadata.publish.embed-width', theme.default_width || 560),
                    h = chart.get('metadata.publish.embed-height', theme.default_height || 400);
                updateSize(w, h);
                return false;
            }
        });
        themes.load();
    }

    function updateVisBackground() {  // and show msg if chart needs more space
        var iframe = $('#iframe-vis').contents(),
            bgcol =  $('body', iframe).css('background-color'),
            white = bgcol == 'rgb(255, 255, 255)' || bgcol == '#ffffff' || bgcol == 'white' || bgcol == 'transparent',
            border = white ? '#ffffff' : '#bbb';

        bgcol = dw.backend.currentChart.get('metadata.publish.contextBg') || dw.backend.currentChart.get('metadata.publish.background');

        $('#iframe-wrapper').css({
            'background-color': white ? '#ffffff' : bgcol,
            'border-color': border
        });
    }

    // chart resizing
    function _updateSize() {
        clearTimeout(__updateSizeTimer);
        __updateSizeTimer = setTimeout(updateSize, 300);
    }

    return {
        init: init
    };

});<|endoftext|>


<commit_before>/* FTUI Plugin
 * Copyright (c) 2015-2016 Mario Stephan <mstephan@shared-files.de>
 * Under MIT License (http://www.opensource.org/licenses/mit-license.php)
 */

/* global ftui:true, Modul_widget:true */

"use strict";

var Modul_simplechart = function () {

    function createElem(elem) {
        return $(document.createElementNS('http://www.w3.org/2000/svg', elem));
    }

    function getSvgPoints(arg) {
        var res = [];
        for (var i = 0, l = arg.length; i < l; i++) {
            if (arg[i])
                res.push(arg[i].join(','));
        }
        return res.join(' ');
    }

    function init_attr(elem) {

        elem.initData('minvalue', 10);
        elem.initData('maxvalue', 30);
        elem.initData('xticks', 360);
        elem.initData('yticks', 5);
        elem.initData('yunit', '');
        elem.initData('get', 'STATE');

        me.addReading(elem, 'get');
    }

    function init_ui(elem) {

        var defaultHeight = elem.hasClass('fullsize') ? '85%' : '';
        var svgElement = $('<svg>' +
            '<svg class="chart" x="0%" width="91%" preserveAspectRatio="none">' +
            '<g transform="scale(1, -1)">' +
            '<polyline points=""/>' +
            '</g></svg>' +
            '</svg>');
        svgElement.appendTo(elem)
            .css("width", elem.data('width') || '93%')
            .css("height", elem.data('height') || defaultHeight);

    }

    function refresh(elem) {
        var minarray = elem.data('minvalue');
        var maxarray = elem.data('maxvalue');
        var min = parseFloat($.isArray(minarray) ? minarray[0] : minarray);
        var max = parseFloat($.isArray(maxarray) ? maxarray[maxarray.length-1] : maxarray);
        var xticks = parseFloat(elem.data('xticks'));
        var yticks = parseFloat(elem.data('yticks'));
        var fix = ftui.precision(elem.data('yticks'));
        var unit = elem.data('yunit');
        var caption = elem.data('caption');
        var noticks = (elem.data('width') <= 100) ? true : elem.hasClass('noticks');
        var days = parseFloat(elem.attr('data-daysago') || 0);
        var now = new Date();
        var ago = new Date();
        var vals = [];
        var mindate = now;
        var maxdate = now;
        if (days > 0 && days < 1) {
            ago.setTime(now.getTime() - (days * 24 * 60 * 60 * 1000));
            mindate = ago.yyyymmdd() + '_' + ago.hhmmss();
        } else {
            ago.setDate(now.getDate() - days);
            mindate = ago.yyyymmdd() + '_00:00:00';
        }
        //var maxdate= now.yyyymmdd() + '_23:59:59';
        maxdate.setDate(now.getDate() + 1);
        maxdate = maxdate.yyyymmdd() + '_00:00:00';

        //console.log( "mindate: " + mindate);
        //console.log( "maxdate: " + maxdate);

        var column_spec;
        if (elem.attr("data-columnspec")) {
            column_spec = elem.attr("data-columnspec");
        } else {
            var device = elem.attr('data-device') || '';
            var reading = elem.attr('data-get') || '';
            column_spec = device + ':' + reading;
        }
        if (!column_spec.match(/.+:.+/)) {
            console.log('columnspec ' + column_spec + ' is not ok in simplechart' + (elem.attr('data-device') ? ' for device ' + elem.attr('data-device') : ''));
            return;
        }

        var logdevice = elem.attr("data-logdevice");
        var logfile = elem.attr("data-logfile") || "-";

        var cmd = ['get', logdevice, logfile, '-', mindate, maxdate, column_spec ].join(' ');

        ftui.sendFhemCommand(cmd)
            .done(function (data) {
                var points = [];
                var lines = data.split('\n');
                var point = [];
                var i = 0;
                var tstart = ftui.dateFromString(mindate);
                $.each(lines, function (index, value) {
                    if (value) {
                        var val = ftui.getPart(value.replace('\r\n', ''), 2);
                        var minutes = ftui.diffMinutes(tstart, ftui.dateFromString(value));
                        if (val && minutes && $.isNumeric(val)) {
                            point = [minutes, val];
                            vals.push(val);
                            i++;
                            points[index] = point;
                            var j = 0,
                                len = 0;
                            if (val > max && $.isArray(maxarray)) {
                                for (j = maxarray.length-1; j > 0; j--) {
                                    console.log('------------------------j:',j);
                                    if (maxarray[j] > val) {
                                        max = maxarray[j];
                                        break;
                                    }
                                }
                            }
                            if (val < min && $.isArray(minarray)) {
                                for (j = 0, len = minarray.length; j < len; j++) {
                                    if (minarray[j] < val) {
                                        min = minarray[j];
                                        break;
                                    }
                                }
                            }
                        }
                    }
                });

                //add last know point
                points[i] = point;

                var xrange = parseInt(ftui.diffMinutes(tstart, ftui.dateFromString(maxdate)));
                var strokeWidth = (document.documentElement.style.vectorEffect === undefined) ? (max - min) / 150 : 1;
                var strokeWidthDashed = (strokeWidth == 1) ? 1.2 : 10;

                var svg = elem.find('svg.chart');
                if (svg) {
                    //clear previous content
                    svg.parent().find('text').remove();
                    svg.find('line').remove();
                    var polyline = svg.find('polyline');
                    if (polyline) {
                        var graph = polyline.parent();
                        //y-axis
                        var yaxis = createElem('line');
                        yaxis.attr({
                            'id': 'yaxis',
                            'x1': '3',
                            'y1': min,
                            'x2': '3',
                            'y2': max,
                            'style': 'stroke:#555;stroke-width:' + strokeWidth + 'px',
                            'vector-effect': 'non-scaling-stroke',
                        });
                        polyline.parent().append(yaxis);

                        if (!noticks) {
                            //y-ticks
                            for (var y = min; y <= max; y += yticks) {
                                var line = createElem('line');
                                line.attr({
                                    'x1': '0',
                                    'y1': y,
                                    'x2': xrange,
                                    'y2': y,
                                    'style': 'stroke:#555;stroke-width:' + strokeWidth + 'px',
                                    'vector-effect': 'non-scaling-stroke',
                                });
                                graph.prepend(line);
                                var text = createElem('text');
                                var textY = (caption) ? (((max - y) * 100) / (max - min) * 0.8 + 12) : (((max - y) * 100) / (max - min) * 0.87 + 5);

                                text.attr({
                                    'x': '99%',
                                    'y': textY + '%',
                                    'style': 'font-size:9px',
                                    'text-anchor': "end",
                                    'fill': '#ddd',
                                });
                                text.text(((fix > -1 && fix <= 20) ? y.toFixed(fix) : y) + unit);
                                svg.parent().append(text);
                            }

                            //x-axis
                            var textX1 = createElem('text');
                            textX1.attr({
                                'x': '0',
                                'y': '100%',
                                'fill': '#ddd',
                                'style': 'font-size:9px',
                            });
                            textX1.text(tstart.ddmm());
                            svg.parent().append(textX1);

                            for (var x = xticks; x <= xrange; x += xticks) {

                                var tx = new Date(tstart);
                                var textX2 = createElem('text');
                                textX2.attr({
                                    'x': 93 * x / xrange + '%',
                                    'y': '100%',
                                    'text-anchor': "middle",
                                    'fill': '#ddd',
                                    'style': 'font-size:9px',
                                });
                                tx.setMinutes(tstart.getMinutes() + x);
                                //console.log(tx);
                                var textX2Value = (tx.hhmm() == "00:00") ? tx.ddmm() : tx.hhmm();
                                textX2.text(textX2Value);
                                svg.parent().append(textX2);

                                var xtick1 = createElem('line');
                                xtick1.attr({
                                    'x1': 100 * x / xrange + '%',
                                    'y1': min,
                                    'x2': 100 * x / xrange + '%',
                                    'y2': max,
                                    'stroke-dasharray': strokeWidth * 2 + ',' + strokeWidth * 2,
                                    'style': 'stroke:#555;stroke-width:' + strokeWidthDashed + 'px',
                                    'vector-effect': 'non-scaling-stroke',
                                });
                                graph.append(xtick1);
                            }

                        } else {
                            var elmLine = createElem('line');
                            elmLine.attr({
                                'x1': '0',
                                'y1': min,
                                'x2': xrange,
                                'y2': min,
                                'style': 'stroke:#555;stroke-width:' + strokeWidth + 'px',
                                'vector-effect': 'non-scaling-stroke',
                            });
                            graph.prepend(elmLine);

                        }

                        //show chart caption if set
                        if (caption) {
                            var textCaption = createElem('text');
                            textCaption.attr({
                                'x': '50%',
                                'y': '8',
                                'fill': '#ddd',
                                'text-anchor': "middle",
                                'style': 'font-size:10px;font-weight:bold',
                            });
                            caption = caption.replace('$min', Math.min.apply(null, vals))
                                .replace('$max', Math.max.apply(null, vals))
                                .replace('$cur', vals[vals.length - 1]);
                            textCaption.text(caption);
                            svg.parent().append(textCaption);
                        }
                        //The graph it self
                        polyline.attr({
                            'points': getSvgPoints(points),
                            'style': 'fill:none;stroke:orange;stroke-width:' + strokeWidth * 2 + 'px',
                            'vector-effect': 'non-scaling-stroke'
                        });
                    }
                    //Viewbox (autoscaler)
                    var graphHeight = (caption) ? 80 : 87;
                    var graphTop = (caption) ? 10 : 2;
                    svg.attr({
                        "height": graphHeight + "%",
                        y: graphTop + "%"
                    });
                    svg[0].setAttribute('viewBox', [0, -max, xrange, max - min].join(' '));
                }
            });
    }

    function update(dev, par) {
        me.elements.filterDeviceReading('get', dev, par)
            .each(function (index) {
                refresh($(this));
            });
    }

    // public
    // inherit all public members from base class
    var me = $.extend(new Modul_widget(), {
        //override or own public members
        widgetname: 'simplechart',
        init_attr: init_attr,
        init_ui: init_ui,
        update: update,
    });

    return me;
};<commit_msg>add data-endplotnow to  have the most current value rightaligned<commit_after>/* FTUI Plugin
 * Copyright (c) 2015-2016 Mario Stephan <mstephan@shared-files.de>
 * Under MIT License (http://www.opensource.org/licenses/mit-license.php)
 */

/* global ftui:true, Modul_widget:true */

"use strict";

var Modul_simplechart = function () {

    function createElem(elem) {
        return $(document.createElementNS('http://www.w3.org/2000/svg', elem));
    }

    function getSvgPoints(arg) {
        var res = [];
        for (var i = 0, l = arg.length; i < l; i++) {
            if (arg[i])
                res.push(arg[i].join(','));
        }
        return res.join(' ');
    }

    function init_attr(elem) {

        elem.initData('minvalue', 10);
        elem.initData('maxvalue', 30);
        elem.initData('xticks', 360);
        elem.initData('yticks', 5);
        elem.initData('yunit', '');
        elem.initData('get', 'STATE');

        me.addReading(elem, 'get');
    }

    function init_ui(elem) {

        var defaultHeight = elem.hasClass('fullsize') ? '85%' : '';
        var svgElement = $('<svg>' +
            '<svg class="chart" x="0%" width="91%" preserveAspectRatio="none">' +
            '<g transform="scale(1, -1)">' +
            '<polyline points=""/>' +
            '</g></svg>' +
            '</svg>');
        svgElement.appendTo(elem)
            .css("width", elem.data('width') || '93%')
            .css("height", elem.data('height') || defaultHeight);

    }

    function refresh(elem) {
        var minarray = elem.data('minvalue');
        var maxarray = elem.data('maxvalue');
        var min = parseFloat($.isArray(minarray) ? minarray[0] : minarray);
        var max = parseFloat($.isArray(maxarray) ? maxarray[maxarray.length-1] : maxarray);
        var xticks = parseFloat(elem.data('xticks'));
        var yticks = parseFloat(elem.data('yticks'));
        var fix = ftui.precision(elem.data('yticks'));
        var unit = elem.data('yunit');
        var caption = elem.data('caption');
        var noticks = (elem.data('width') <= 100) ? true : elem.hasClass('noticks');
        var days = parseFloat(elem.attr('data-daysago') || 0);
        var endnow = elem.data('endplotnow');
        var now = new Date();
        var ago = new Date();
        var vals = [];
        var mindate = now;
        var maxdate = now;
        if (days > 0 && days < 1) {
            ago.setTime(now.getTime() - (days * 24 * 60 * 60 * 1000));
            mindate = ago.yyyymmdd() + '_' + ago.hhmmss();
        } else if (endnow) {
            ago.setDate(now.getDate() - days);
            //align to hours if span is larger than 12h
            if (days > 0.5) {
                mindate = ago.yyyymmdd() + '_' + ago.getHours() + ':00:00';
            } else {
                mindate = ago.yyyymmdd() + '_' + ago.hhmm() + ':00';
            }
        } else {
            ago.setDate(now.getDate() - days);
            mindate = ago.yyyymmdd() + '_00:00:00';
        }
        //var maxdate= now.yyyymmdd() + '_23:59:59';
        if (!endnow) {
            maxdate.setDate(now.getDate() + 1);
            maxdate = maxdate.yyyymmdd() + '_00:00:00';
        }
        else if (days > 0.5) {
            maxdate.setHours(maxdate.getHours() + 1);
            maxdate = maxdate.yyyymmdd() + '_' + maxdate.getHours() + ':00:00';
        } else {
            maxdate.setMinutes(maxdate.getMinutes() + 1);
            maxdate = nextmin.yyyymmdd() + '_' + nextmin.hhmm() + ':00';
        }

        //console.log( "mindate: " + mindate);
        //console.log( "maxdate: " + maxdate);

        var column_spec;
        if (elem.attr("data-columnspec")) {
            column_spec = elem.attr("data-columnspec");
        } else {
            var device = elem.attr('data-device') || '';
            var reading = elem.attr('data-get') || '';
            column_spec = device + ':' + reading;
        }
        if (!column_spec.match(/.+:.+/)) {
            console.log('columnspec ' + column_spec + ' is not ok in simplechart' + (elem.attr('data-device') ? ' for device ' + elem.attr('data-device') : ''));
            return;
        }

        var logdevice = elem.attr("data-logdevice");
        var logfile = elem.attr("data-logfile") || "-";

        var cmd = ['get', logdevice, logfile, '-', mindate, maxdate, column_spec ].join(' ');

        ftui.sendFhemCommand(cmd)
            .done(function (data) {
                var points = [];
                var lines = data.split('\n');
                var point = [];
                var i = 0;
                var tstart = ftui.dateFromString(mindate);
                $.each(lines, function (index, value) {
                    if (value) {
                        var val = ftui.getPart(value.replace('\r\n', ''), 2);
                        var minutes = ftui.diffMinutes(tstart, ftui.dateFromString(value));
                        if (val && minutes && $.isNumeric(val)) {
                            point = [minutes, val];
                            vals.push(val);
                            i++;
                            points[index] = point;
                            var j = 0,
                                len = 0;
                            if (val > max && $.isArray(maxarray)) {
                                for (j = maxarray.length-1; j > 0; j--) {
                                    console.log('------------------------j:',j);
                                    if (maxarray[j] > val) {
                                        max = maxarray[j];
                                        break;
                                    }
                                }
                            }
                            if (val < min && $.isArray(minarray)) {
                                for (j = 0, len = minarray.length; j < len; j++) {
                                    if (minarray[j] < val) {
                                        min = minarray[j];
                                        break;
                                    }
                                }
                            }
                        }
                    }
                });

                //add last know point
                points[i] = point;

                var xrange = parseInt(ftui.diffMinutes(tstart, ftui.dateFromString(maxdate)));
                var strokeWidth = (document.documentElement.style.vectorEffect === undefined) ? (max - min) / 150 : 1;
                var strokeWidthDashed = (strokeWidth == 1) ? 1.2 : 10;

                var svg = elem.find('svg.chart');
                if (svg) {
                    //clear previous content
                    svg.parent().find('text').remove();
                    svg.find('line').remove();
                    var polyline = svg.find('polyline');
                    if (polyline) {
                        var graph = polyline.parent();
                        //y-axis
                        var yaxis = createElem('line');
                        yaxis.attr({
                            'id': 'yaxis',
                            'x1': '3',
                            'y1': min,
                            'x2': '3',
                            'y2': max,
                            'style': 'stroke:#555;stroke-width:' + strokeWidth + 'px',
                            'vector-effect': 'non-scaling-stroke',
                        });
                        polyline.parent().append(yaxis);

                        if (!noticks) {
                            //y-ticks
                            for (var y = min; y <= max; y += yticks) {
                                var line = createElem('line');
                                line.attr({
                                    'x1': '0',
                                    'y1': y,
                                    'x2': xrange,
                                    'y2': y,
                                    'style': 'stroke:#555;stroke-width:' + strokeWidth + 'px',
                                    'vector-effect': 'non-scaling-stroke',
                                });
                                graph.prepend(line);
                                var text = createElem('text');
                                var textY = (caption) ? (((max - y) * 100) / (max - min) * 0.8 + 12) : (((max - y) * 100) / (max - min) * 0.87 + 5);

                                text.attr({
                                    'x': '99%',
                                    'y': textY + '%',
                                    'style': 'font-size:9px',
                                    'text-anchor': "end",
                                    'fill': '#ddd',
                                });
                                text.text(((fix > -1 && fix <= 20) ? y.toFixed(fix) : y) + unit);
                                svg.parent().append(text);
                            }

                            //x-axis
                            var textX1 = createElem('text');
                            textX1.attr({
                                'x': '0',
                                'y': '100%',
                                'fill': '#ddd',
                                'style': 'font-size:9px',
                            });
                            textX1.text(tstart.ddmm());
                            svg.parent().append(textX1);

                            for (var x = xticks; x <= xrange; x += xticks) {

                                var tx = new Date(tstart);
                                var textX2 = createElem('text');
                                textX2.attr({
                                    'x': 93 * x / xrange + '%',
                                    'y': '100%',
                                    'text-anchor': "middle",
                                    'fill': '#ddd',
                                    'style': 'font-size:9px',
                                });
                                tx.setMinutes(tstart.getMinutes() + x);
                                //console.log(tx);
                                var textX2Value = (tx.hhmm() == "00:00") ? tx.ddmm() : tx.hhmm();
                                textX2.text(textX2Value);
                                svg.parent().append(textX2);

                                var xtick1 = createElem('line');
                                xtick1.attr({
                                    'x1': 100 * x / xrange + '%',
                                    'y1': min,
                                    'x2': 100 * x / xrange + '%',
                                    'y2': max,
                                    'stroke-dasharray': strokeWidth * 2 + ',' + strokeWidth * 2,
                                    'style': 'stroke:#555;stroke-width:' + strokeWidthDashed + 'px',
                                    'vector-effect': 'non-scaling-stroke',
                                });
                                graph.append(xtick1);
                            }

                        } else {
                            var elmLine = createElem('line');
                            elmLine.attr({
                                'x1': '0',
                                'y1': min,
                                'x2': xrange,
                                'y2': min,
                                'style': 'stroke:#555;stroke-width:' + strokeWidth + 'px',
                                'vector-effect': 'non-scaling-stroke',
                            });
                            graph.prepend(elmLine);

                        }

                        //show chart caption if set
                        if (caption) {
                            var textCaption = createElem('text');
                            textCaption.attr({
                                'x': '50%',
                                'y': '8',
                                'fill': '#ddd',
                                'text-anchor': "middle",
                                'style': 'font-size:10px;font-weight:bold',
                            });
                            caption = caption.replace('$min', Math.min.apply(null, vals))
                                .replace('$max', Math.max.apply(null, vals))
                                .replace('$cur', vals[vals.length - 1]);
                            textCaption.text(caption);
                            svg.parent().append(textCaption);
                        }
                        //The graph it self
                        polyline.attr({
                            'points': getSvgPoints(points),
                            'style': 'fill:none;stroke:orange;stroke-width:' + strokeWidth * 2 + 'px',
                            'vector-effect': 'non-scaling-stroke'
                        });
                    }
                    //Viewbox (autoscaler)
                    var graphHeight = (caption) ? 80 : 87;
                    var graphTop = (caption) ? 10 : 2;
                    svg.attr({
                        "height": graphHeight + "%",
                        y: graphTop + "%"
                    });
                    svg[0].setAttribute('viewBox', [0, -max, xrange, max - min].join(' '));
                }
            });
    }

    function update(dev, par) {
        me.elements.filterDeviceReading('get', dev, par)
            .each(function (index) {
                refresh($(this));
            });
    }

    // public
    // inherit all public members from base class
    var me = $.extend(new Modul_widget(), {
        //override or own public members
        widgetname: 'simplechart',
        init_attr: init_attr,
        init_ui: init_ui,
        update: update,
    });

    return me;
};<|endoftext|>