<commit_before>fallback.ready(['jQuery', 'SockJS', 'EventBus'], function () {
    var eventbus = new EventBus("/eventbus");
    eventbus.onopen = function () {
        var lang;
        eventbus.send("translations", getCookie("lang"), function (error, reply) {
            lang = reply.body;
            console.log(lang);
            eventbus.send("database_get_wishlist",
                {}, function (error, reply) {
                    var data = reply.body['rows'];
                    console.log(data);
                    addTableHead(lang);
                    addTableData(data, lang);
                });
        });
    };
});

function addTableHead(lang) {
    $("#wishlist-table").empty().append(
        '
' +
        '' + lang['HISTORY_TITLE'] + '	' +
        '' + lang['HISTORY_DATE'] + '	' +
        '
');
}

function addTableData(data, lang) {
    $.each(data, function (i) {
        $("#wishlist-table").append(
            $.parseHTML('
' +
                '' + data[i]['Title'] + '	' +
                //'' + getMonth(data[i]['Time'], lang) + '	' +
                '' + data[i]['Time'] + '	' +
                '
')
        );
    });
}<commit_msg>wishlist timeout<commit_after>fallback.ready(['jQuery', 'SockJS', 'EventBus'], function () {
    var eventbus = new EventBus("/eventbus");
    eventbus.onopen = function () {
        var lang;
        eventbus.send("translations", getCookie("lang"), function (error, reply) {
            lang = reply.body;
            console.log(lang);
            eventbus.send("database_get_wishlist",
                {}, function (error, reply) {
                    var data = reply.body['rows'];
                    console.log(data);
                    addTableHead(lang);
                    addTableData(data, lang);
                });
        });
    };
});

function addTableHead(lang) {
    $("#wishlist-table").empty().append(
        '
' +
        '' + lang['HISTORY_TITLE'] + '	' +
        '' + lang['HISTORY_DATE'] + '	' +
        '
');
}

function addTableData(data, lang) {
    var timeout = 100;
    $.each(data, function (i) {
        setTimeout(function () {
            $("#wishlist-table").append(
                $.parseHTML('
' +
                    '' + data[i]['Title'] + '	' +
                    //'' + getMonth(data[i]['Time'], lang) + '	' +
                    '' + data[i]['Time'] + '	' +
                    '
')
            );
        }, timeout += 25);
    });
}<|endoftext|>


<commit_before>var request = require('supertest')
  , sinon = require('sinon')
  , should = require('chai').should()
  , expect = require('chai').expect
  , mongoose = require('mongoose')
  , MockToken = require('../mockToken')
  , TokenModel = mongoose.model('Token');

require('chai').should();
require('sinon-mongoose');

require('../../models/team');
var TeamModel = mongoose.model('Team');

require('../../models/event');
var EventModel = mongoose.model('Event');

const SecurePropertyAppender = require('../../security/utilities/secure-property-appender');
const AuthenticationConfiguration = require('../../models/authenticationconfiguration');

describe("event read tests", function() {

  let app;

  beforeEach(function() {
    const configs = [];
    const config = {
      name: 'local',
      type: 'local'
    };
    configs.push(config);

    sinon.mock(AuthenticationConfiguration)
      .expects('getAllConfigurations')
      .resolves(configs);

    sinon.mock(SecurePropertyAppender)
      .expects('appendToConfig')
      .resolves(config);

    app = require('../../express');
  });

  afterEach(function() {
    sinon.restore();
  });

  var userId = mongoose.Types.ObjectId();
  function mockTokenWithPermission(permission) {
    sinon.mock(TokenModel)
      .expects('findOne')
      .withArgs({token: "12345"})
      .chain('populate', 'userId')
      .chain('exec')
      .yields(null, MockToken(userId, [permission]));
  }

  it("should read active events", function(done) {
    mockTokenWithPermission('READ_EVENT_ALL');

    var eventId = 1;
    var mockEvent = new EventModel({
      _id: eventId,
      name: 'Mock Event'
    });
    sinon.mock(EventModel)
      .expects('find')
      .withArgs({ complete: { $ne: true } })
      .yields(null, [mockEvent]);

    request(app)
      .get('/api/events')
      .set('Accept', 'application/json')
      .set('Authorization', 'Bearer 12345')
      .expect(200)
      .end(done);
  });

  it("should read active events if user has read permission in acl", function(done) {
    mockTokenWithPermission('');

    var mockEvent1 = {
      _id: 1,
      name: 'Mock Event',
      acl: {
        userId: userId,
        role: 'GUEST'
      }
    };
    mockEvent1.acl[userId] = 'GUEST';

    var mockEvent2 = {
      _id: 2,
      name: 'Mock Event',
      acl: {}
    };

    var mockCursor = {
      toArray: function(callback) {
        callback(null, [mockEvent1, mockEvent2]);
      }
    };

    sinon.mock(EventModel.collection)
      .expects('find')
      .withArgs({ complete: { $ne: true } })
      .yields(null, mockCursor);

    request(app)
      .get('/api/events')
      .set('Accept', 'application/json')
      .set('Authorization', 'Bearer 12345')
      .expect(200)
      .expect(function(res) {
        should.exist(res.body);
        res.body.should.be.an('array');
        expect(res.body).to.have.lengthOf(1);
      })
      .end(done);
  });

  it("should read active events if user is part of a team in event", function(done) {
    mockTokenWithPermission('');

    var eventId = 1;

    var mockEvent1 = new EventModel({
      _id: eventId,
      name: 'Mock Event 123',
      teamIds: [],
      acl: {
        1: 'NONE'
      }
    });
    mockEvent1.teamIds[0] = {
      userIds: [userId]
    };

    var mockEvent2 = new EventModel({
      _id: eventId,
      name: 'Mock Event 267',
      acl: {}
    });

    sinon.mock(EventModel)
      .expects('populate')
      .yields(null, [mockEvent1, mockEvent2]);

    sinon.mock(EventModel)
      .expects('find')
      .withArgs({ complete: { $ne: true } })
      .yields(null);

    request(app)
      .get('/api/events?populate=false')
      .set('Accept', 'application/json')
      .set('Authorization', 'Bearer 12345')
      .expect(200)
      .expect(function(res) {
        should.exist(res.body);
        res.body.should.be.an('array');
        expect(res.body).to.have.lengthOf(1);
      })
      .end(done);
  });

  it("should not read events if user is not part of a team in event or in acl", function(done) {
    mockTokenWithPermission('');

    var eventId = 1;

    var mockEvent1 = new EventModel({
      _id: eventId,
      name: 'Mock Event 1',
      acl: {}
    });

    var mockEvent2 = new EventModel({
      _id: eventId,
      name: 'Mock Event 2',
      acl: {}
    });

    sinon.mock(EventModel)
      .expects('populate')
      .yields(null, [mockEvent1, mockEvent2]);

    sinon.mock(EventModel)
      .expects('find')
      .withArgs({ complete: { $ne: true } })
      .yields(null);

    request(app)
      .get('/api/events?populate=false')
      .set('Accept', 'application/json')
      .set('Authorization', 'Bearer 12345')
      .expect(200)
      .expect(function(res) {
        console.log('res.body', res.body);
        should.exist(res.body);
        res.body.should.be.an('array');
        expect(res.body).to.have.lengthOf(0);
      })
      .end(done);
  });

  it("should read complete events", function(done) {
    mockTokenWithPermission('READ_EVENT_ALL');

    var eventId = 1;
    var mockEvent = new EventModel({
      _id: eventId,
      name: 'Mock Event'
    });
    sinon.mock(EventModel)
      .expects('find')
      .withArgs({ complete: true })
      .yields(null, [mockEvent]);

    sinon.mock(EventModel)
      .expects('populate')
      .yields(null, [mockEvent]);

    request(app)
      .get('/api/events')
      .query({state: 'complete'})
      .set('Accept', 'application/json')
      .set('Authorization', 'Bearer 12345')
      .expect(200)
      .end(done);
  });

  it("should read all events", function(done) {
    mockTokenWithPermission('READ_EVENT_ALL');

    var eventId = 1;
    var mockEvent = new EventModel({
      _id: eventId,
      name: 'Mock Event'
    });
    sinon.mock(EventModel)
      .expects('find')
      .withArgs({})
      .yields(null, [mockEvent]);

    sinon.mock(EventModel)
      .expects('populate')
      .yields(null, [mockEvent]);

    request(app)
      .get('/api/events')
      .query({state: 'all'})
      .set('Accept', 'application/json')
      .set('Authorization', 'Bearer 12345')
      .expect(200)
      .end(done);
  });

  it("should read event by id", function(done) {
    mockTokenWithPermission('READ_EVENT_ALL');

    var eventId = 1;
    var mockEvent = new EventModel({
      _id: eventId,
      name: 'Mock Event'
    });

    sinon.mock(EventModel)
      .expects('findById')
      .twice()
      .onFirstCall()
      .yields(null, mockEvent)
      .onSecondCall()
      .yields(null, mockEvent);

    request(app)
      .get('/api/events/1')
      .query({state: 'all'})
      .set('Accept', 'application/json')
      .set('Authorization', 'Bearer 12345')
      .expect(200)
      .end(done);
  });

  it("should fail to read event by id if event does not exist", function(done) {
    mockTokenWithPermission('READ_EVENT_ALL');

    var eventId = 1;
    var mockEvent = new EventModel({
      _id: eventId,
      name: 'Mock Event'
    });

    sinon.mock(EventModel)
      .expects('findById')
      .twice()
      .onFirstCall()
      .yields(null, mockEvent)
      .onSecondCall()
      .yields(null, null);

    request(app)
      .get('/api/events/2')
      .query({state: 'all'})
      .set('Accept', 'application/json')
      .set('Authorization', 'Bearer 12345')
      .expect(404)
      .end(done);
  });

  it("should read teams in event", function(done) {
    mockTokenWithPermission('READ_EVENT_ALL');

    var eventId = 1;
    var mockEvent = new EventModel({
      _id: eventId,
      name: 'Mock Event'
    });

    var eventMock = sinon.mock(EventModel);

    eventMock.expects('findOne')
      .resolves(mockEvent);

    var mockTeam = new TeamModel({
      _id: 1,
      name: 'Mock Team'
    });

    var mockCursor = {
      toArray: function (callback) {
        callback(null, [mockTeam]);
      }
    };

    sinon.mock(TeamModel.collection)
      .expects('find')
      .yields(null, mockCursor);

    sinon.mock(TeamModel)
      .expects('count')
      .resolves(1);

    request(app)
      .get('/api/events/1/teams')
      .set('Accept', 'application/json')
      .set('Authorization', 'Bearer 12345')
      .expect(200)
      .end(done);
  });

  it("should read users in event", function(done) {
    mockTokenWithPermission('READ_EVENT_ALL');

    var eventId = 1;
    var mockEvent = new EventModel({
      _id: eventId,
      name: 'Mock Event'
    });

    var eventMock = sinon.mock(EventModel);

    eventMock.expects('findById')
      .withArgs("1")
      .yields(null, mockEvent);

    eventMock.expects('findById')
      .chain('populate')
      .withArgs({path: 'teamIds', populate: { path: 'userIds' }})
      .chain('exec')
      .yields(null, mockEvent);

    request(app)
      .get('/api/events/1/users')
      .set('Accept', 'application/json')
      .set('Authorization', 'Bearer 12345')
      .expect(200)
      .end(done);
  });

  it("should read users in event with team access", function(done) {
    mockTokenWithPermission('');

    var eventId = 1;

    var mockTeam = new TeamModel({
      userIds: [userId],
      acl: {}
    });

    var mockEvent = new EventModel({
      _id: eventId,
      name: 'Mock Event 123',
      teamIds: [],
      acl: {
        1: 'NONE'
      }
    });
    mockEvent.teamIds[0] = mockTeam;

    var eventMock = sinon.mock(EventModel);

    eventMock.expects('findById')
      .withArgs("1")
      .yields(null, mockEvent);

    sinon.mock(EventModel)
      .expects('populate')
      .yields(null, mockEvent);

    eventMock.expects('findById')
      .chain('populate')
      .withArgs({
        path: 'teamIds',
        populate: {
          path: 'userIds'
        }
      })
      .chain('exec')
      .yields(null, mockEvent);

    request(app)
      .get('/api/events/1/users')
      .set('Accept', 'application/json')
      .set('Authorization', 'Bearer 12345')
      .query({populate: 'users'})
      .expect(200)
      .end(done);
  });

  it("should read teams in event with team access", function(done) {
    mockTokenWithPermission('');

    var eventId = 1;

    var mockTeam = new TeamModel({
      _id: mongoose.Types.ObjectId(),
      userIds: [userId],
      acl: {}
    });

    var mockEvent = new EventModel({
      _id: eventId,
      name: 'Mock Event 123',
      teamIds: [],
      acl: {
        1: 'NONE'
      }
    });
    mockEvent.teamIds[0] = mockTeam._id;

    var eventMock = sinon.mock(EventModel);

    eventMock.expects('findOne')
      .resolves(mockEvent);

    var mockCursor = {
      toArray: function (callback) {
        callback(null, [mockTeam]);
      }
    };

    sinon.mock(TeamModel.collection)
      .expects('find')
      .yields(null, mockCursor);

    sinon.mock(TeamModel)
      .expects('count')
      .resolves(1);

    request(app)
      .get('/api/events/1/teams')
      .set('Accept', 'application/json')
      .set('Authorization', 'Bearer 12345')
      .query({populate: 'users'})
      .expect(200)
      .end(done);
  });
});
<commit_msg>Fix event tests<commit_after>var request = require('supertest')
  , sinon = require('sinon')
  , should = require('chai').should()
  , expect = require('chai').expect
  , mongoose = require('mongoose')
  , MockToken = require('../mockToken')
  , TokenModel = mongoose.model('Token');

require('chai').should();
require('sinon-mongoose');

require('../../models/team');
var TeamModel = mongoose.model('Team');

require('../../models/event');
var EventModel = mongoose.model('Event');

const SecurePropertyAppender = require('../../security/utilities/secure-property-appender');
const AuthenticationConfiguration = require('../../models/authenticationconfiguration');

describe("event read tests", function() {

  let app;

  beforeEach(function() {
    const configs = [];
    const config = {
      name: 'local',
      type: 'local'
    };
    configs.push(config);

    sinon.mock(AuthenticationConfiguration)
      .expects('getAllConfigurations')
      .resolves(configs);

    sinon.mock(SecurePropertyAppender)
      .expects('appendToConfig')
      .resolves(config);

    app = require('../../express');
  });

  afterEach(function() {
    sinon.restore();
  });

  var userId = mongoose.Types.ObjectId();
  function mockTokenWithPermission(permission) {
    sinon.mock(TokenModel)
      .expects('findOne')
      .withArgs({token: "12345"})
      .chain('populate', 'userId')
      .chain('exec')
      .yields(null, MockToken(userId, [permission]));
  }

  it("should read active events", function(done) {
    mockTokenWithPermission('READ_EVENT_ALL');

    var eventId = 1;
    var mockEvent = new EventModel({
      _id: eventId,
      name: 'Mock Event'
    });
    sinon.mock(EventModel)
      .expects('find')
      .withArgs({ complete: { $ne: true } })
      .yields(null, [mockEvent]);

    request(app)
      .get('/api/events')
      .set('Accept', 'application/json')
      .set('Authorization', 'Bearer 12345')
      .expect(200)
      .end(done);
  });

  it("should read active events if user has read permission in acl", function(done) {
    mockTokenWithPermission('');

    var mockEvent1 = {
      _id: 1,
      name: 'Mock Event',
      acl: {
        userId: userId,
        role: 'GUEST'
      }
    };
    mockEvent1.acl[userId] = 'GUEST';

    var mockEvent2 = {
      _id: 2,
      name: 'Mock Event',
      acl: {}
    };

    var mockCursor = {
      toArray: function(callback) {
        callback(null, [mockEvent1, mockEvent2]);
      }
    };

    sinon.mock(EventModel.collection)
      .expects('find')
      .withArgs({ complete: { $ne: true } })
      .yields(null, mockCursor);

    request(app)
      .get('/api/events')
      .set('Accept', 'application/json')
      .set('Authorization', 'Bearer 12345')
      .expect(200)
      .expect(function(res) {
        should.exist(res.body);
        res.body.should.be.an('array');
        expect(res.body).to.have.lengthOf(1);
      })
      .end(done);
  });

  it("should read active events if user is part of a team in event", function(done) {
    mockTokenWithPermission('');

    var eventId = 1;

    var mockEvent1 = new EventModel({
      _id: eventId,
      name: 'Mock Event 123',
      teamIds: [],
      acl: {
        1: 'NONE'
      }
    });
    mockEvent1.teamIds[0] = {
      userIds: [userId]
    };

    var mockEvent2 = new EventModel({
      _id: eventId,
      name: 'Mock Event 267',
      acl: {}
    });

    sinon.mock(EventModel)
      .expects('populate')
      .yields(null, [mockEvent1, mockEvent2]);

    sinon.mock(EventModel)
      .expects('find')
      .withArgs({ complete: { $ne: true } })
      .yields(null);

    request(app)
      .get('/api/events?populate=false')
      .set('Accept', 'application/json')
      .set('Authorization', 'Bearer 12345')
      .expect(200)
      .expect(function(res) {
        should.exist(res.body);
        res.body.should.be.an('array');
        expect(res.body).to.have.lengthOf(1);
      })
      .end(done);
  });

  it("should not read events if user is not part of a team in event or in acl", function(done) {
    mockTokenWithPermission('');

    var eventId = 1;

    var mockEvent1 = new EventModel({
      _id: eventId,
      name: 'Mock Event 1',
      acl: {}
    });

    var mockEvent2 = new EventModel({
      _id: eventId,
      name: 'Mock Event 2',
      acl: {}
    });

    sinon.mock(EventModel)
      .expects('populate')
      .yields(null, [mockEvent1, mockEvent2]);

    sinon.mock(EventModel)
      .expects('find')
      .withArgs({ complete: { $ne: true } })
      .yields(null);

    request(app)
      .get('/api/events?populate=false')
      .set('Accept', 'application/json')
      .set('Authorization', 'Bearer 12345')
      .expect(200)
      .expect(function(res) {
        console.log('res.body', res.body);
        should.exist(res.body);
        res.body.should.be.an('array');
        expect(res.body).to.have.lengthOf(0);
      })
      .end(done);
  });

  it("should read complete events", function(done) {
    mockTokenWithPermission('READ_EVENT_ALL');

    var eventId = 1;
    var mockEvent = new EventModel({
      _id: eventId,
      name: 'Mock Event'
    });
    sinon.mock(EventModel)
      .expects('find')
      .withArgs({ complete: true })
      .yields(null, [mockEvent]);

    sinon.mock(EventModel)
      .expects('populate')
      .yields(null, [mockEvent]);

    request(app)
      .get('/api/events')
      .query({state: 'complete'})
      .set('Accept', 'application/json')
      .set('Authorization', 'Bearer 12345')
      .expect(200)
      .end(done);
  });

  it("should read all events", function(done) {
    mockTokenWithPermission('READ_EVENT_ALL');

    var eventId = 1;
    var mockEvent = new EventModel({
      _id: eventId,
      name: 'Mock Event'
    });
    sinon.mock(EventModel)
      .expects('find')
      .withArgs({})
      .yields(null, [mockEvent]);

    sinon.mock(EventModel)
      .expects('populate')
      .yields(null, [mockEvent]);

    request(app)
      .get('/api/events')
      .query({state: 'all'})
      .set('Accept', 'application/json')
      .set('Authorization', 'Bearer 12345')
      .expect(200)
      .end(done);
  });

  it("should read event by id", function(done) {
    mockTokenWithPermission('READ_EVENT_ALL');

    var eventId = 1;
    var mockEvent = new EventModel({
      _id: eventId,
      name: 'Mock Event'
    });

    sinon.mock(EventModel)
      .expects('findById')
      .twice()
      .onFirstCall()
      .yields(null, mockEvent)
      .onSecondCall()
      .yields(null, mockEvent);

    request(app)
      .get('/api/events/1')
      .query({state: 'all'})
      .set('Accept', 'application/json')
      .set('Authorization', 'Bearer 12345')
      .expect(200)
      .end(done);
  });

  it("should fail to read event by id if event does not exist", function(done) {
    mockTokenWithPermission('READ_EVENT_ALL');

    var eventId = 1;
    var mockEvent = new EventModel({
      _id: eventId,
      name: 'Mock Event'
    });

    sinon.mock(EventModel)
      .expects('findById')
      .twice()
      .onFirstCall()
      .yields(null, mockEvent)
      .onSecondCall()
      .yields(null, null);

    request(app)
      .get('/api/events/2')
      .query({state: 'all'})
      .set('Accept', 'application/json')
      .set('Authorization', 'Bearer 12345')
      .expect(404)
      .end(done);
  });

  it("should read teams page in event", function(done) {
    mockTokenWithPermission('READ_EVENT_ALL');

    var eventId = 1;
    var mockEvent = new EventModel({
      _id: eventId,
      name: 'Mock Event'
    });

    var eventMock = sinon.mock(EventModel);

    eventMock.expects('findOne')
      .resolves(mockEvent);

    var mockTeam = new TeamModel({
      _id: 1,
      name: 'Mock Team'
    });

    var mockCursor = {
      toArray: function (callback) {
        callback(null, [mockTeam]);
      }
    };

    sinon.mock(TeamModel.collection)
      .expects('find')
      .yields(null, mockCursor);

    sinon.mock(TeamModel)
      .expects('count')
      .resolves(1);

    request(app)
      .get('/api/events/1/teams?page=0')
      .set('Accept', 'application/json')
      .set('Authorization', 'Bearer 12345')
      .expect(200)
      .end(done);
  });

  it("should read users in event", function(done) {
    mockTokenWithPermission('READ_EVENT_ALL');

    var eventId = 1;
    var mockEvent = new EventModel({
      _id: eventId,
      name: 'Mock Event'
    });

    var eventMock = sinon.mock(EventModel);

    eventMock.expects('findById')
      .withArgs("1")
      .yields(null, mockEvent);

    eventMock.expects('findById')
      .chain('populate')
      .withArgs({path: 'teamIds', populate: { path: 'userIds' }})
      .chain('exec')
      .yields(null, mockEvent);

    request(app)
      .get('/api/events/1/users')
      .set('Accept', 'application/json')
      .set('Authorization', 'Bearer 12345')
      .expect(200)
      .end(done);
  });

  it("should read users in event with team access", function(done) {
    mockTokenWithPermission('');

    var eventId = 1;

    var mockTeam = new TeamModel({
      userIds: [userId],
      acl: {}
    });

    var mockEvent = new EventModel({
      _id: eventId,
      name: 'Mock Event 123',
      teamIds: [],
      acl: {
        1: 'NONE'
      }
    });
    mockEvent.teamIds[0] = mockTeam;

    var eventMock = sinon.mock(EventModel);

    eventMock.expects('findById')
      .withArgs("1")
      .yields(null, mockEvent);

    sinon.mock(EventModel)
      .expects('populate')
      .yields(null, mockEvent);

    eventMock.expects('findById')
      .chain('populate')
      .withArgs({
        path: 'teamIds',
        populate: {
          path: 'userIds'
        }
      })
      .chain('exec')
      .yields(null, mockEvent);

    request(app)
      .get('/api/events/1/users')
      .set('Accept', 'application/json')
      .set('Authorization', 'Bearer 12345')
      .query({populate: 'users'})
      .expect(200)
      .end(done);
  });

  it("should read teams page in event with team access", function(done) {
    mockTokenWithPermission('');

    var eventId = 1;

    var mockTeam = new TeamModel({
      _id: mongoose.Types.ObjectId(),
      userIds: [userId],
      acl: {}
    });

    var mockEvent = new EventModel({
      _id: eventId,
      name: 'Mock Event 123',
      teamIds: [],
      acl: {
        1: 'NONE'
      }
    });
    mockEvent.teamIds[0] = mockTeam._id;

    var eventMock = sinon.mock(EventModel);

    eventMock.expects('findOne')
      .resolves(mockEvent);

    var mockCursor = {
      toArray: function (callback) {
        callback(null, [mockTeam]);
      }
    };

    sinon.mock(TeamModel.collection)
      .expects('find')
      .yields(null, mockCursor);

    sinon.mock(TeamModel)
      .expects('count')
      .resolves(1);

    request(app)
      .get('/api/events/1/teams?page=0')
      .set('Accept', 'application/json')
      .set('Authorization', 'Bearer 12345')
      .query({populate: 'users'})
      .expect(200)
      .end(done);
  });
});
<|endoftext|>


<commit_before>import React from 'react';

//import Web3 from "web3"
import BLOCKCHAIN_INFO from "../../../../../env"
import * as constants from "../../constants"

import {isUserLogin} from "../../../utils/common"

export default class CachedServerProvider extends React.Component {
    constructor(props) {
        super(props)
        this.rpcUrl = props.url
        this.maxRequestTime = constants.CONNECTION_TIMEOUT
    }

    getGasPrice() {
        return new Promise((resolve, rejected) => {
            this.timeout(this.maxRequestTime, fetch(this.rpcUrl + '/gasPrice'))
            .then((response) => {
                return response.json()
            }).then((result) => {
                if (result.success) {
                    resolve(result.data)
                } else {
                    rejected(new Error("Cannot get gas price from server"))
                }
            })
                .catch((err) => {
                    console.log(err.message)
                    rejected(new Error("Cannot get gas price from server"))
                })
        })
    }

    // getGasFromEthgasstation() {
    //     return new Promise((resolve, rejected) => {
    //         fetch(BLOCKCHAIN_INFO.gasstation_endpoint)
    //             .then((response) => {
    //                 return response.json()
    //             })
    //             .then((data) => {
    //                 resolve(data)
    //             })
    //             .catch((err) => {
    //                 rejected(err)
    //             })
    //     })
    // }

    checkKyberEnable() {
        return new Promise((resolve, rejected) => {
            this.timeout(this.maxRequestTime, fetch(this.rpcUrl + '/kyberEnabled'))
            .then((response) => {
                return response.json()
            }).then((result) => {
                if (result.success) {
                    resolve(result.data)
                } else {
                    rejected(new Error("Cannot check kyber enable from server"))
                }
            })
                .catch((err) => {
                    console.log(err.message)
                    rejected(new Error("Cannot check kyber enable from server"))
                })
        })
    }

    getMaxGasPrice() {
        return new Promise((resolve, rejected) => {
            this.timeout(this.maxRequestTime, fetch(this.rpcUrl + '/maxGasPrice'))
            .then((response) => {
                return response.json()
            }).then((result) => {
                if (result.success) {
                    resolve(result.data)
                } else {
                    rejected(new Error("Cannot get max gas price from server"))
                }
            })
                .catch((err) => {
                    console.log(err.message)
                    rejected(new Error("Cannot get max gas price from server"))
                })
        })
    }

    getLatestBlock() {
        return new Promise((resolve, rejected) => {
            this.timeout(this.maxRequestTime, fetch(this.rpcUrl + '/latestBlock'))
            .then((response) => {
                return response.json()
            }).then((result) => {
                if (result.success) {
                    resolve(result.data)
                } else {
                    rejected(new Error("Cannot get latest block from server"))
                }
            })
                .catch((err) => {
                    rejected(new Error("Cannot get latest block from server"))
                })
        })
    }

    getAllRates(tokensObj) {
        return new Promise((resolve, rejected) => {
            this.timeout(this.maxRequestTime, fetch(this.rpcUrl + '/rate'))

                .then((response) => {
                    return response.json()
                })
                .then(result => {
                    if (result.success) {
                        resolve(result.data)
                    } else {
                        rejected(new Error("Rate server is not fetching"))
                    }
                })
                .catch((err) => {
                    rejected(err)
                })
        })
    }

    getSourceAmount(sourceTokenSymbol, destTokenSymbol, destAmount) {
        return new Promise((resolve, reject) => {
            this.timeout(this.maxRequestTime, fetch(`${this.rpcUrl}/sourceAmount?source=${sourceTokenSymbol}&dest=${destTokenSymbol}&destAmount=${destAmount}`))
                .then((response) => {
                    return response.json();
                })
                .then((result) => {
                    if (result.success) {
                        resolve(result.value);
                    } else {
                        reject(new Error("Cannot get source amount"));
                    }
                })
                .catch((err) => {
                    reject(err);
                });
        })
    }

    getAllRatesUSD() {
        return new Promise((resolve, rejected) => {
            this.timeout(this.maxRequestTime, fetch(this.rpcUrl + '/rateUSD'))
            .then((response) => {
                return response.json()
            })
                .then((result) => {
                    if (result.success) {
                        resolve(result.data)
                    } else {
                        rejected(new Error("RateUSD server is not fetching"))
                    }
                })
                .catch((err) => {
                    rejected(err)
                })
        })
    }

    getRateETH() {
        return new Promise((resolve, rejected) => {
            this.timeout(this.maxRequestTime, fetch(this.rpcUrl + '/rateETH'))
            .then((response) => {
                return response.json()
            })
                .then((result) => {
                    if (result.success) {
                        resolve(result.data)
                    } else {
                        rejected(new Error("RateETHs server is not fetching"))
                    }
                })
                .catch((err) => {
                    rejected(err)
                })
        })
    }

    getLanguagePack(lang) {
        return new Promise((resolve, rejected) => {
            rejected(new Error("This api /getLanguagePack will comming soon"))
        })
    }

    getInfo(infoObj) {
        if(isUserLogin()){
            var params = {tx_hash: infoObj.hash}
            fetch("/api/transactions", {
                method: 'POST',
                headers: {
                    Accept: 'application/json',
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify(params)
            })
        }else{
            fetch(BLOCKCHAIN_INFO.broadcastTx + 'broadcast/' + infoObj.hash, {
                method: 'GET',
                headers: {
                    Accept: 'application/json',
                    'Content-Type': 'application/json',
                },
            })
        }

        return new Promise((resolve, rejected) => {
            resolve("get_info_successfully")
        })
    }

    // getExchangeEnable(address) {
    //     if (isUserLogin()){
    //         return new Promise((resolve, rejected) => {
    //             this.timeout(this.maxRequestTime, fetch("/api/user_stats"))
    //                 .then((response) => {
    //                     return response.json()
    //                 })
    //                 .then((result) => {
    //                     resolve(result)
    //                 })
    //                 .catch((err) => {
    //                     console.log(err)
    //                     rejected(err)
    //                 })
    //         })
    //     }else{
    //         return new Promise((resolve, rejected) => {
    //             this.timeout(this.maxRequestTime, fetch(this.rpcUrl + '/users?address=' + address))
    //                 .then((response) => {
    //                     return response.json()
    //                 })
    //                 .then((result) => {
    //                     resolve(result)
    //                 })
    //                 .catch((err) => {
    //                     console.log(err)
    //                     rejected(err)
    //                 })
    //         })
    //     }
    // }

    getMarketData() {
        return new Promise((resolve, rejected) => {
            this.timeout(this.maxRequestTime, fetch(this.rpcUrl + '/getMarketData'))
            .then((response) => {
                return response.json()
            })
                .then((result) => {
                    if (result.success) {
                        resolve(result.data)
                    } else {
                        rejected(new Error("Market data is not fetching"))
                    }
                })
                .catch((err) => {
                    rejected(err)
                })
        })
    }

    getGeneralTokenInfo() {
        return new Promise((resolve, rejected) => {
            this.timeout(this.maxRequestTime, fetch(this.rpcUrl + '/getTokenInfo'))
            .then((response) => {
                return response.json()
            })
                .then((result) => {
                    if (result.success) {
                        resolve(result.data)
                    } else {
                        rejected(new Error("Market data is not fetching"))
                    }
                })
                .catch((err) => {
                    rejected(err)
                })
        })
    }

    getVolumnChart() {
        return new Promise((resolve, rejected) => {
            this.timeout(this.maxRequestTime, fetch(BLOCKCHAIN_INFO.tracker + '/api/tokens/rates'))
            //fetch(BLOCKCHAIN_INFO.tracker + '/api/tokens/rates', {
            .then((response) => {
                return response.json()
            })
                .then((result) => {
                    resolve(result)
                })
                .catch((err) => {
                    console.log(err)
                    rejected(err)
                })
        })
    }

    getMarketInfo(queryString) {
        return new Promise((resolve, rejected) => {
            this.timeout(this.maxRequestTime, fetch(this.rpcUrl + '/marketInfoByTokens' + '?listToken=' + queryString))
            //fetch(this.rpcUrl + '/getMarketInfoByTokens' + '?listToken=' + queryString, {
            .then((response) => {
                return response.json()
            })
                .then((result) => {
                    resolve(result)
                })
                .catch((err) => {
                    console.log(err)
                    rejected(err)
                })
        })
    }

    getRightMarketInfo() {
        return new Promise((resolve, rejected) => {
            this.timeout(this.maxRequestTime,  fetch(this.rpcUrl + '/marketInfo'))
            .then((response) => {
                return response.json()
            })
                .then((result) => {
                    resolve(result)
                })
                .catch((err) => {
                    console.log(err)
                    rejected(err)
                })
        })
    }

    getLast7D(queryString) {
        return new Promise((resolve, rejected) => {
            this.timeout(this.maxRequestTime, fetch(this.rpcUrl + '/getLast7D' + '?listToken=' + queryString))
            //fetch(this.rpcUrl + '/getLast7D' + '?listToken=' + queryString, {
            .then((response) => {
                return response.json()
            })
                .then((result) => {
                    resolve(result)
                })
                .catch((err) => {
                    console.log(err)
                    rejected(err)
                })
        })
    }

    getUserMaxCap(address) {
        if (isUserLogin()){
            return new Promise((resolve, rejected) => {
                this.timeout(this.maxRequestTime, fetch("/api/user_stats"))
                    .then((response) => {
                        return response.json()
                    })
                    .then((result) => {
                        resolve(result)
                    })
                    .catch((err) => {
                        console.log(err)
                        // resolve({
                        //     cap: 100000000000000000,
                        //     rich: false
                        // })
                        rejected(err)
                    })
            })
        }else{
            return new Promise((resolve, rejected) => {
                this.timeout(this.maxRequestTime, fetch(this.rpcUrl + '/users?address=' + address))
                    .then((response) => {
                        return response.json()
                    })
                    .then((result) => {
                        resolve(result)
                    })
                    .catch((err) => {
                        console.log(err)
                        rejected(err)
                    })
            })
        }

    }

    timeout(ms, promise) {
        return new Promise(function (resolve, reject) {
            setTimeout(function () {
                reject(new Error("timeout"))
            }, ms)
            promise.then(resolve, reject)
        })
    }
}
<commit_msg>fix broadcast tx<commit_after>import React from 'react';

//import Web3 from "web3"
import BLOCKCHAIN_INFO from "../../../../../env"
import * as constants from "../../constants"

import {isUserLogin} from "../../../utils/common"

export default class CachedServerProvider extends React.Component {
    constructor(props) {
        super(props)
        this.rpcUrl = props.url
        this.maxRequestTime = constants.CONNECTION_TIMEOUT
    }

    getGasPrice() {
        return new Promise((resolve, rejected) => {
            this.timeout(this.maxRequestTime, fetch(this.rpcUrl + '/gasPrice'))
            .then((response) => {
                return response.json()
            }).then((result) => {
                if (result.success) {
                    resolve(result.data)
                } else {
                    rejected(new Error("Cannot get gas price from server"))
                }
            })
                .catch((err) => {
                    console.log(err.message)
                    rejected(new Error("Cannot get gas price from server"))
                })
        })
    }

    // getGasFromEthgasstation() {
    //     return new Promise((resolve, rejected) => {
    //         fetch(BLOCKCHAIN_INFO.gasstation_endpoint)
    //             .then((response) => {
    //                 return response.json()
    //             })
    //             .then((data) => {
    //                 resolve(data)
    //             })
    //             .catch((err) => {
    //                 rejected(err)
    //             })
    //     })
    // }

    checkKyberEnable() {
        return new Promise((resolve, rejected) => {
            this.timeout(this.maxRequestTime, fetch(this.rpcUrl + '/kyberEnabled'))
            .then((response) => {
                return response.json()
            }).then((result) => {
                if (result.success) {
                    resolve(result.data)
                } else {
                    rejected(new Error("Cannot check kyber enable from server"))
                }
            })
                .catch((err) => {
                    console.log(err.message)
                    rejected(new Error("Cannot check kyber enable from server"))
                })
        })
    }

    getMaxGasPrice() {
        return new Promise((resolve, rejected) => {
            this.timeout(this.maxRequestTime, fetch(this.rpcUrl + '/maxGasPrice'))
            .then((response) => {
                return response.json()
            }).then((result) => {
                if (result.success) {
                    resolve(result.data)
                } else {
                    rejected(new Error("Cannot get max gas price from server"))
                }
            })
                .catch((err) => {
                    console.log(err.message)
                    rejected(new Error("Cannot get max gas price from server"))
                })
        })
    }

    getLatestBlock() {
        return new Promise((resolve, rejected) => {
            this.timeout(this.maxRequestTime, fetch(this.rpcUrl + '/latestBlock'))
            .then((response) => {
                return response.json()
            }).then((result) => {
                if (result.success) {
                    resolve(result.data)
                } else {
                    rejected(new Error("Cannot get latest block from server"))
                }
            })
                .catch((err) => {
                    rejected(new Error("Cannot get latest block from server"))
                })
        })
    }

    getAllRates(tokensObj) {
        return new Promise((resolve, rejected) => {
            this.timeout(this.maxRequestTime, fetch(this.rpcUrl + '/rate'))

                .then((response) => {
                    return response.json()
                })
                .then(result => {
                    if (result.success) {
                        resolve(result.data)
                    } else {
                        rejected(new Error("Rate server is not fetching"))
                    }
                })
                .catch((err) => {
                    rejected(err)
                })
        })
    }

    getSourceAmount(sourceTokenSymbol, destTokenSymbol, destAmount) {
        return new Promise((resolve, reject) => {
            this.timeout(this.maxRequestTime, fetch(`${this.rpcUrl}/sourceAmount?source=${sourceTokenSymbol}&dest=${destTokenSymbol}&destAmount=${destAmount}`))
                .then((response) => {
                    return response.json();
                })
                .then((result) => {
                    if (result.success) {
                        resolve(result.value);
                    } else {
                        reject(new Error("Cannot get source amount"));
                    }
                })
                .catch((err) => {
                    reject(err);
                });
        })
    }

    getAllRatesUSD() {
        return new Promise((resolve, rejected) => {
            this.timeout(this.maxRequestTime, fetch(this.rpcUrl + '/rateUSD'))
            .then((response) => {
                return response.json()
            })
                .then((result) => {
                    if (result.success) {
                        resolve(result.data)
                    } else {
                        rejected(new Error("RateUSD server is not fetching"))
                    }
                })
                .catch((err) => {
                    rejected(err)
                })
        })
    }

    getRateETH() {
        return new Promise((resolve, rejected) => {
            this.timeout(this.maxRequestTime, fetch(this.rpcUrl + '/rateETH'))
            .then((response) => {
                return response.json()
            })
                .then((result) => {
                    if (result.success) {
                        resolve(result.data)
                    } else {
                        rejected(new Error("RateETHs server is not fetching"))
                    }
                })
                .catch((err) => {
                    rejected(err)
                })
        })
    }

    getLanguagePack(lang) {
        return new Promise((resolve, rejected) => {
            rejected(new Error("This api /getLanguagePack will comming soon"))
        })
    }

    getInfo(infoObj) {
        if(isUserLogin()){
            var params = {tx_hash: infoObj.txHash}
            fetch("/api/transactions", {
                method: 'POST',
                headers: {
                    Accept: 'application/json',
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify(params)
            })
        }else{
            fetch(BLOCKCHAIN_INFO.broadcastTx + 'broadcast/' + infoObj.txHash, {
                method: 'GET',
                headers: {
                    Accept: 'application/json',
                    'Content-Type': 'application/json',
                },
            })
        }

        return new Promise((resolve, rejected) => {
            resolve("get_info_successfully")
        })
    }

    // getExchangeEnable(address) {
    //     if (isUserLogin()){
    //         return new Promise((resolve, rejected) => {
    //             this.timeout(this.maxRequestTime, fetch("/api/user_stats"))
    //                 .then((response) => {
    //                     return response.json()
    //                 })
    //                 .then((result) => {
    //                     resolve(result)
    //                 })
    //                 .catch((err) => {
    //                     console.log(err)
    //                     rejected(err)
    //                 })
    //         })
    //     }else{
    //         return new Promise((resolve, rejected) => {
    //             this.timeout(this.maxRequestTime, fetch(this.rpcUrl + '/users?address=' + address))
    //                 .then((response) => {
    //                     return response.json()
    //                 })
    //                 .then((result) => {
    //                     resolve(result)
    //                 })
    //                 .catch((err) => {
    //                     console.log(err)
    //                     rejected(err)
    //                 })
    //         })
    //     }
    // }

    getMarketData() {
        return new Promise((resolve, rejected) => {
            this.timeout(this.maxRequestTime, fetch(this.rpcUrl + '/getMarketData'))
            .then((response) => {
                return response.json()
            })
                .then((result) => {
                    if (result.success) {
                        resolve(result.data)
                    } else {
                        rejected(new Error("Market data is not fetching"))
                    }
                })
                .catch((err) => {
                    rejected(err)
                })
        })
    }

    getGeneralTokenInfo() {
        return new Promise((resolve, rejected) => {
            this.timeout(this.maxRequestTime, fetch(this.rpcUrl + '/getTokenInfo'))
            .then((response) => {
                return response.json()
            })
                .then((result) => {
                    if (result.success) {
                        resolve(result.data)
                    } else {
                        rejected(new Error("Market data is not fetching"))
                    }
                })
                .catch((err) => {
                    rejected(err)
                })
        })
    }

    getVolumnChart() {
        return new Promise((resolve, rejected) => {
            this.timeout(this.maxRequestTime, fetch(BLOCKCHAIN_INFO.tracker + '/api/tokens/rates'))
            //fetch(BLOCKCHAIN_INFO.tracker + '/api/tokens/rates', {
            .then((response) => {
                return response.json()
            })
                .then((result) => {
                    resolve(result)
                })
                .catch((err) => {
                    console.log(err)
                    rejected(err)
                })
        })
    }

    getMarketInfo(queryString) {
        return new Promise((resolve, rejected) => {
            this.timeout(this.maxRequestTime, fetch(this.rpcUrl + '/marketInfoByTokens' + '?listToken=' + queryString))
            //fetch(this.rpcUrl + '/getMarketInfoByTokens' + '?listToken=' + queryString, {
            .then((response) => {
                return response.json()
            })
                .then((result) => {
                    resolve(result)
                })
                .catch((err) => {
                    console.log(err)
                    rejected(err)
                })
        })
    }

    getRightMarketInfo() {
        return new Promise((resolve, rejected) => {
            this.timeout(this.maxRequestTime,  fetch(this.rpcUrl + '/marketInfo'))
            .then((response) => {
                return response.json()
            })
                .then((result) => {
                    resolve(result)
                })
                .catch((err) => {
                    console.log(err)
                    rejected(err)
                })
        })
    }

    getLast7D(queryString) {
        return new Promise((resolve, rejected) => {
            this.timeout(this.maxRequestTime, fetch(this.rpcUrl + '/getLast7D' + '?listToken=' + queryString))
            //fetch(this.rpcUrl + '/getLast7D' + '?listToken=' + queryString, {
            .then((response) => {
                return response.json()
            })
                .then((result) => {
                    resolve(result)
                })
                .catch((err) => {
                    console.log(err)
                    rejected(err)
                })
        })
    }

    getUserMaxCap(address) {
        if (isUserLogin()){
            return new Promise((resolve, rejected) => {
                this.timeout(this.maxRequestTime, fetch("/api/user_stats"))
                    .then((response) => {
                        return response.json()
                    })
                    .then((result) => {
                        resolve(result)
                    })
                    .catch((err) => {
                        console.log(err)
                        // resolve({
                        //     cap: 100000000000000000,
                        //     rich: false
                        // })
                        rejected(err)
                    })
            })
        }else{
            return new Promise((resolve, rejected) => {
                this.timeout(this.maxRequestTime, fetch(this.rpcUrl + '/users?address=' + address))
                    .then((response) => {
                        return response.json()
                    })
                    .then((result) => {
                        resolve(result)
                    })
                    .catch((err) => {
                        console.log(err)
                        rejected(err)
                    })
            })
        }

    }

    timeout(ms, promise) {
        return new Promise(function (resolve, reject) {
            setTimeout(function () {
                reject(new Error("timeout"))
            }, ms)
            promise.then(resolve, reject)
        })
    }
}
<|endoftext|>


<commit_before>function setupParser() {
    // prepare *Marked* (a Markdown parser) library; see https://github.com/chjj/marked
    marked.setOptions({
        renderer: new marked.Renderer(),
        gfm: true,
        tables: true,
        breaks: false,
        pedantic: false,
        sanitize: true,
        smartLists: true,
        smartypants: false,
    });
}

function translateFragments() {
    var fg = $("#fragment-group");

    // highlight any search keyword contained in fragment titles;
    fg.find(".fragment-title").each(function() {
        var $this = $(this);
        $this.html(translateSearchKeywordCommands($this.html()));
    });

    // translate Markdown formatted fragment contents into HTML format
    fg.find(".fragment-content").each(function() {
        var $this = $(this);
        $this.html(translateFragmentContent($this.text()));
        postprocessFragmentContent($this);
    });

    // add a tooltip message of updated and created time
    fg.find(".fragment-header .fa-clock-o, .fragment-header .fa-birthday-cake").each(function() {
        var $this = $(this);
        $this[0].title = formatDatetime($this.prev("span").text());
    });

    fg.find(".each-tag").each(function() {
        formatTagsOnFragmentHeader($(this));
    });
}

function populateFragmentOverlay(data) {
    // show the fragment overlay as a popup
    var overlayFrame = $("#fragment-overlay");
    overlayFrame.lightbox_me({
        centered:false
        , showOverlay:false
        , lightboxSpeed:"fast"
        , closeSelector:"#fragment-overlay-close-button"
        , closeEsc:true
        , modalCSS:{ position:"fixed", bottom: '34px', right: '2%' }
    });

    var titleBar = $("#fragment-overlay-title-bar");
    if (titleBar.next().is(":visible") == false) {
        toggleWindow(overlayFrame, titleBar);
    }

    $("#fragment-overlay-title").text("");

    // Set up a link to the previous fragment if any.
    var overlayContent = $("#fragment-overlay-content");
    var prevHdr = overlayContent.find(".fragment-header");
    var backBtn = $("#fragmen-overlay-back-button");
    if (prevHdr.length > 0) {
        backBtn.show().attr("href", "fragment/"+prevHdr.attr("_fid"))
            .addClass("-cvz-frgm");
    }
    else {
        backBtn.hide();
    }

    overlayContent.html(data);

    $("#fragment-overlay-content .fragment-header .fa-clock-o, #fragment-overlay-content .fragment-header .fa-birthday-cake")
    .each(function() {
        var $this = $(this);
        $this[0].title = formatDatetime($this.prev("span").text());
    });

    // translate Markdown formatted fragment contents into HTML format
    overlayContent.find(".fragment-content").each(function(){
        var $this = $(this);
        $this.html(translateFragmentContent($this.text()));
        postprocessFragmentContent($this);
    });

    // make titles on the overlay window also draggable/droppable
    setupDraggableForFragmentTitle();

    setupDndForRelatingFragments();

    setContextMenuForFragments();

    setContextMenuForTags();

    overlayContent.find(".each-tag").draggable(baseDraggableSettings)
    .each(function() {formatTagsOnFragmentHeader($(this))});

    overlayFrame.off("click.cvz_frg_overlay").on("click.cvz_frg_overlay", ".-cvz-frgm", triggerFragmentOverlay);
    setupClickHandlerForTags(overlayContent);

    setupQuickFragmentEditing(overlayContent.find(".fragment-header"));
}

function translateSearchKeywordCommands(html) {
    return html
        // {([keyword] ... text ... )} --- translated to a ;
        // used for one special purpose; highlighting search phrase
        .replace(/\{\(\[(.+?)\] /g, function(match, p1, pos, originalText) {
            return "";
        })
        .replace(/ \)\}/g, function(match, pos, originalText) {
            return "";
        })
        ;
}

function translateCustomMarkupCommands(html) {
    return translateSearchKeywordCommands(html)
        // {{{[keyword] ... text ... }}} --- translated to a
 block
        .replace(/\{\{\{\[(.+?)({.*})?\]/g, function(match, p1, p2, pos, originalText) {
            var output = "
";
        })
        .replace(/\}\}\}/g, function(match, pos, originalText) {
            return "
";
        })
        // {{[keyword] ... text ... }} --- translated to a
        .replace(/\{\{\[([^,]+?)\]/g, function(match, p1, pos, originalText) {
            return "";
        })
        .replace(/\}\}/g, function(match, pos, originalText) {
            return "";
        })
        ;
}

function translateFragmentContent(content) {
    // translate Markdown text into HTML;
    var outputHtml = parseMarkdown(content);

    // take care of custom markup commands
    return translateCustomMarkupCommands(outputHtml);
}

function setupFragmentLinks(content) {
    content.find("span.-cvz-frgm").each(function() {
        var $this = $(this);
        var txt = $this.text();
        var patt = /\s*(\d+)\s+(.*)/g;
        if (txt.match(patt)) {
            var newTag = $("" + RegExp.$2 + "");
            $this.replaceWith(newTag);
        }
    });
}

function processFoldings(content) {
    content.find(".-cvz-fold").each(function() {
        var $this = $(this);
        var args = parseJsonArgs($this);
        $this.wrapInner("
");
        var link = addToggler($this, "fold-toggle-icon", function() {
            showOrHide($this);
        });
        if (args.title) {
            var title = $(""+args.title+"")
            .click(function (e) {
                link.click();
            });
            $this.before(title);
        }
        if (args.hide == "true") {
            link.click();
            // with the only above code, the target element would be hidden.
            // but it doesn't work on Safari, so make sure it becomes hidden.
            $this.hide();
        }
    });
}

function processEmbeddedFragments(content) {
    content.find(".-cvz-frgm-embed").each(function() {
        var $this = $(this);
        $.get("fragment/"+$this.text().trim(), "", function(data) {
            var content = $(data).find(".fragment-content").text();
            $this.html(translateFragmentContent(content));
            postprocessFragmentContent($this);
        });
    })
}

function unsanitizeHtml(content) {
    content.find(".-cvz-html").each(function() {
        var $this = $(this);
        var res = $this.text()
            .replace(/<(\/?)(.+)>/g, function(match, cg1, cg2, pos, originalText) {
//                var cg1 = RegExp.$1;
//                var cg2 = RegExp.$2;
                if (cg2.indexOf("html") == 0
                   || cg2.indexOf("head") == 0
                   || cg2.indexOf("body") == 0
                   || cg2.indexOf("link") == 0
                   || cg2.indexOf("script") == 0
                   )
                    // these tags should be sanitized for safety
                    return "<"+cg1+cg2+"&gt";
                return match;
            });
        $this.text(null).html(res);
    });
}

function embedYoutubeVideo(content) {
    function kickYoutubeVideo() {
        var $this = $(this);
        var iframe = $("");
        $this.replaceWith(iframe);
        return false;
    }

    content.find("iframe[src*='www.youtube.com/embed/'], a[href*='youtu.be/'], a[href*='www.youtube.com/watch?']")
    .each(function() {
        var $this = $(this), videoId;
        if ($this.is("iframe"))
            videoId = suffix($this.attr("src"), "/", true);
        else if ($this.is("a[href*='youtu.be/']"))
            videoId = suffix($this.attr("href"), "/", true);
        else if ($this.is("a[href*='www.youtube.com/watch?']"))
            videoId = inbetween($this.attr("href"), "v=", "&")
                || suffix($this.attr("href"), "v=", true);
        var div = $("
" +
            '

')
            .click(kickYoutubeVideo);
        $this.replaceWith(div);
    });
}

function postprocessFragmentContent(content) {
    // translate foldings
    // Rule - {{{[fold]...}}}
    processFoldings(content);

    // translate embedded fragemnts
    // Rule - {{[frgm-embed]...}}
    processEmbeddedFragments(content);

    // translate fragemnt links
    // Rule - {{[frgm]...}}
    setupFragmentLinks(content);

    // translate tag links
    // Rule - {{[tag]...}}
    setupTagLinks(content);

    // convert links to images into  tags
    content.find("a").each(function() {
        var $this = $(this);
        var href = $this.attr("href");
        if (isImage(suffix(href, ".")))
            $this.replaceWith("");
    });

    // translate file box elements into HTML links
    // Rule - {{[file]...}}
    processFileClasses(content);

    // unsanitize HTML code if any
    // Rule - {{[html]...}}
    unsanitizeHtml(content);

    embedYoutubeVideo(content);
}
<commit_msg>[bug fix] highlighting search keywords would break some layouts (e.g., folding);<commit_after>function setupParser() {
    // prepare *Marked* (a Markdown parser) library; see https://github.com/chjj/marked
    marked.setOptions({
        renderer: new marked.Renderer(),
        gfm: true,
        tables: true,
        breaks: false,
        pedantic: false,
        sanitize: true,
        smartLists: true,
        smartypants: false,
    });
}

function translateFragments() {
    var fg = $("#fragment-group");

    // highlight any search keyword contained in fragment titles;
    fg.find(".fragment-title").each(function() {
        var $this = $(this);
        $this.html(translateSearchKeywordCommands($this.html()));
    });

    // translate Markdown formatted fragment contents into HTML format
    fg.find(".fragment-content").each(function() {
        var $this = $(this);
        var text = $this.text();
        $this.html(translateFragmentContent(text));
        postprocessFragmentContent($this);
        if ($this.hasClass("fp-search")) {
            // Highlight search keywords
            $this.find("*").each(function() {
               var elem = $(this), attrs = this.attributes;
               // Remove any of search keyword markups from HTML attributes
               for (var i=0; i<attrs.length; ++i) {
                   var attr = attrs[i];
                   attr.value = removeSearchKeywordCommands(attr.value);
                   elem.attr(attr.name, attr.value);
               }
               // Translate search keyword markups inside HTML text
               elem.html(translateSearchKeywordCommands(elem.html()));
            });
        }
    });

    // add a tooltip message of updated and created time
    fg.find(".fragment-header .fa-clock-o, .fragment-header .fa-birthday-cake").each(function() {
        var $this = $(this);
        $this[0].title = formatDatetime($this.prev("span").text());
    });

    fg.find(".each-tag").each(function() {
        formatTagsOnFragmentHeader($(this));
    });
}

function populateFragmentOverlay(data) {
    // show the fragment overlay as a popup
    var overlayFrame = $("#fragment-overlay");
    overlayFrame.lightbox_me({
        centered:false
        , showOverlay:false
        , lightboxSpeed:"fast"
        , closeSelector:"#fragment-overlay-close-button"
        , closeEsc:true
        , modalCSS:{ position:"fixed", bottom: '34px', right: '2%' }
    });

    var titleBar = $("#fragment-overlay-title-bar");
    if (titleBar.next().is(":visible") == false) {
        toggleWindow(overlayFrame, titleBar);
    }

    $("#fragment-overlay-title").text("");

    // Set up a link to the previous fragment if any.
    var overlayContent = $("#fragment-overlay-content");
    var prevHdr = overlayContent.find(".fragment-header");
    var backBtn = $("#fragmen-overlay-back-button");
    if (prevHdr.length > 0) {
        backBtn.show().attr("href", "fragment/"+prevHdr.attr("_fid"))
            .addClass("-cvz-frgm");
    }
    else {
        backBtn.hide();
    }

    overlayContent.html(data);

    $("#fragment-overlay-content .fragment-header .fa-clock-o, #fragment-overlay-content .fragment-header .fa-birthday-cake")
    .each(function() {
        var $this = $(this);
        $this[0].title = formatDatetime($this.prev("span").text());
    });

    // translate Markdown formatted fragment contents into HTML format
    overlayContent.find(".fragment-content").each(function(){
        var $this = $(this);
        $this.html(translateFragmentContent($this.text()));
        postprocessFragmentContent($this);
    });

    // make titles on the overlay window also draggable/droppable
    setupDraggableForFragmentTitle();

    setupDndForRelatingFragments();

    setContextMenuForFragments();

    setContextMenuForTags();

    overlayContent.find(".each-tag").draggable(baseDraggableSettings)
    .each(function() {formatTagsOnFragmentHeader($(this))});

    overlayFrame.off("click.cvz_frg_overlay").on("click.cvz_frg_overlay", ".-cvz-frgm", triggerFragmentOverlay);
    setupClickHandlerForTags(overlayContent);

    setupQuickFragmentEditing(overlayContent.find(".fragment-header"));
}

function translateSearchKeywordCommands(html) {
    return html
        // {([keyword] ... text ... )} --- translated to a ;
        // used for one special purpose; highlighting search phrase
        .replace(/\{\(\[(.+?)\] /g, function(match, p1, pos, originalText) {
            return "";
        })
        .replace(/ \)\}/g, function(match, pos, originalText) {
            return "";
        })
        ;
}

function removeSearchKeywordCommands(html) {
    return html
        .replace(/\{\(\[(.+?)\] /g, function(match, p1, pos, originalText) {
            return "";
        })
        .replace(/ \)\}/g, function(match, pos, originalText) {
            return "";
        })
        ;
}

function translateCustomMarkupCommands(html) {
//    return translateSearchKeywordCommands(html)
    return html
    // {{{[keyword] ... text ... }}} --- translated to a
 block
    .replace(/\{\{\{\[(.+?)({.*})?\]/g, function(match, p1, p2, pos, originalText) {
        var output = "
";
    })
    .replace(/\}\}\}/g, function(match, pos, originalText) {
        return "
";
    })
    // {{[keyword] ... text ... }} --- translated to a
    .replace(/\{\{\[([^,]+?)\]/g, function(match, p1, pos, originalText) {
        return "";
    })
    .replace(/\}\}/g, function(match, pos, originalText) {
        return "";
    })
    ;
}

function translateFragmentContent(content) {
    // translate Markdown text into HTML;
    var outputHtml = parseMarkdown(content);

    // take care of custom markup commands
    return translateCustomMarkupCommands(outputHtml);
}

function setupFragmentLinks(content) {
    content.find("span.-cvz-frgm").each(function() {
        var $this = $(this);
        var txt = $this.text();
        var patt = /\s*(\d+)\s+(.*)/g;
        if (txt.match(patt)) {
            var newTag = $("" + RegExp.$2 + "");
            $this.replaceWith(newTag);
        }
    });
}

function processFoldings(content) {
    content.find(".-cvz-fold").each(function() {
        var $this = $(this);
        var args = parseJsonArgs($this);
        $this.wrapInner("
");
        var link = addToggler($this, "fold-toggle-icon", function() {
            showOrHide($this);
        });
        if (args.title) {
            var title = $(""+args.title+"")
            .click(function (e) {
                link.click();
            });
            $this.before(title);
        }
        if (args.hide == "true") {
            link.click();
            // with the only above code, the target element would be hidden.
            // but it doesn't work on Safari, so make sure it becomes hidden.
            $this.hide();
        }
    });
}

function processEmbeddedFragments(content) {
    content.find(".-cvz-frgm-embed").each(function() {
        var $this = $(this);
        $.get("fragment/"+$this.text().trim(), "", function(data) {
            var content = $(data).find(".fragment-content").text();
            $this.html(translateFragmentContent(content));
            postprocessFragmentContent($this);
        });
    })
}

function unsanitizeHtml(content) {
    content.find(".-cvz-html").each(function() {
        var $this = $(this);
        var res = $this.text()
            .replace(/<(\/?)(.+)>/g, function(match, cg1, cg2, pos, originalText) {
//                var cg1 = RegExp.$1;
//                var cg2 = RegExp.$2;
                if (cg2.indexOf("html") == 0
                   || cg2.indexOf("head") == 0
                   || cg2.indexOf("body") == 0
                   || cg2.indexOf("link") == 0
                   || cg2.indexOf("script") == 0
                   )
                    // these tags should be sanitized for safety
                    return "<"+cg1+cg2+"&gt";
                return match;
            });
        $this.text(null).html(res);
    });
}

function embedYoutubeVideo(content) {
    function kickYoutubeVideo() {
        var $this = $(this);
        var iframe = $("");
        $this.replaceWith(iframe);
        return false;
    }

    content.find("iframe[src*='www.youtube.com/embed/'], a[href*='youtu.be/'], a[href*='www.youtube.com/watch?']")
    .each(function() {
        var $this = $(this), videoId;
        if ($this.is("iframe"))
            videoId = suffix($this.attr("src"), "/", true);
        else if ($this.is("a[href*='youtu.be/']"))
            videoId = suffix($this.attr("href"), "/", true);
        else if ($this.is("a[href*='www.youtube.com/watch?']"))
            videoId = inbetween($this.attr("href"), "v=", "&")
                || suffix($this.attr("href"), "v=", true);
        var div = $("
" +
            '

')
            .click(kickYoutubeVideo);
        $this.replaceWith(div);
    });
}

function postprocessFragmentContent(content) {
    // translate foldings
    // Rule - {{{[fold]...}}}
    processFoldings(content);

    // translate embedded fragemnts
    // Rule - {{[frgm-embed]...}}
    processEmbeddedFragments(content);

    // translate fragemnt links
    // Rule - {{[frgm]...}}
    setupFragmentLinks(content);

    // translate tag links
    // Rule - {{[tag]...}}
    setupTagLinks(content);

    // convert links to images into  tags
    content.find("a").each(function() {
        var $this = $(this);
        var href = $this.attr("href");
        if (isImage(suffix(href, ".")))
            $this.replaceWith("");
    });

    // translate file box elements into HTML links
    // Rule - {{[file]...}}
    processFileClasses(content);

    // unsanitize HTML code if any
    // Rule - {{[html]...}}
    unsanitizeHtml(content);

    embedYoutubeVideo(content);
}
<|endoftext|>


<commit_before>angular.module('demo', ['demo.controllers', 'demo.services', 'demo.directives', 'ui.router', 'satellizer', 'ngResource'])
    .config(['$resourceProvider', '$authProvider', '$stateProvider', '$urlRouterProvider', function($resourceProvider, $authProvider, $stateProvider, $urlRouterProvider) {
        $resourceProvider.defaults.stripTrailingSlashes = false;

        $authProvider.facebook({
            clientId: '439130886253368',
            redirectUri: window.location.origin + '/auth/facebook',
        });
        $authProvider.google({
            clientId: '388525728293-bu96shbpa47dpc92efgsemsd6ftu7gj7.apps.googleusercontent.com',
            redirectUri: window.location.origin + '/auth/google',
        });
        $authProvider.loginRedirect = '/dashboard';
        $authProvider.loginUrl = '/login';

        $stateProvider
        .state('home', {
            url:'/',
            templateUrl: 'static/ui/home.html',
            controller: 'HomeCtrl'
        })
        // Login & logout
        .state('login', {
            url:'/login',
            templateUrl: 'static/ui/login.html',
            controller: 'LoginCtrl'
        })
        .state('logout', {
            url:'/logout',
            template: null,
            controller: 'LogoutCtrl'
        })
        // Dashboard (private)
        .state('dashboard', {
            url:'/dashboard',
            templateUrl: 'static/ui/dashboard/index.html',
            controller: 'DashboardCtrl'
        });
        $urlRouterProvider.otherwise('/');
    }]);<commit_msg>UI Router authentication fix, redirecting to login<commit_after>angular.module('demo', ['demo.controllers', 'demo.services', 'demo.directives', 'ui.router', 'satellizer', 'ngResource'])
    .config(['$resourceProvider', '$authProvider', '$stateProvider', '$urlRouterProvider', function($resourceProvider, $authProvider, $stateProvider, $urlRouterProvider) {
        $resourceProvider.defaults.stripTrailingSlashes = false;

        $authProvider.facebook({
            clientId: '439130886253368',
            redirectUri: window.location.origin + '/auth/facebook',
        });
        $authProvider.google({
            clientId: '388525728293-bu96shbpa47dpc92efgsemsd6ftu7gj7.apps.googleusercontent.com',
            redirectUri: window.location.origin + '/auth/google',
        });
        $authProvider.loginRedirect = '/dashboard';
        $authProvider.loginUrl = '/login';

        $stateProvider
        .state('home', {
            url:'/',
            templateUrl: 'static/ui/home.html',
            controller: 'HomeCtrl'
        })
        // Login & logout
        .state('login', {
            url:'/login',
            templateUrl: 'static/ui/login.html',
            controller: 'LoginCtrl'
        })
        .state('logout', {
            url:'/logout',
            template: null,
            controller: 'LogoutCtrl'
        })
        // Dashboard (private)
        .state('dashboard', {
            url:'/dashboard',
            templateUrl: 'static/ui/dashboard/index.html',
            controller: 'DashboardCtrl',
            authenticate: true
        });
        $urlRouterProvider.otherwise('/');
    }])
    .run(['$rootScope', '$state', '$auth', function ($rootScope, $state, $auth) {
        $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
            if (toState.authenticate && !$auth.isAuthenticated()) {
                $state.transitionTo('login');
                event.preventDefault();
            }
        })
    }]);<|endoftext|>


<commit_before>import {LightningElement, api, track} from 'lwc';
import {fireEvent, registerListener} from 'c/pubsubNoPageRef';
import GeLabelService from 'c/geLabelService';
import {isEmpty, isNotEmpty, isNumeric} from 'c/utilCommon';
import ALLOCATION_OBJECT from '@salesforce/schema/Allocation__c';
import AMOUNT_FIELD from '@salesforce/schema/Allocation__c.Amount__c';
import PERCENT_FIELD from '@salesforce/schema/Allocation__c.Percent__c';
import GAU_FIELD from '@salesforce/schema/Allocation__c.General_Accounting_Unit__c';
const ALLOCATION_AMOUNT = `${ALLOCATION_OBJECT.objectApiName}.${AMOUNT_FIELD.fieldApiName}`;
const ALLOCATION_PERCENT = `${ALLOCATION_OBJECT.objectApiName}.${PERCENT_FIELD.fieldApiName}`;
const ALLOCATION_GAU = `${ALLOCATION_OBJECT.objectApiName}.${GAU_FIELD.fieldApiName}`;

export default class GeFormWidgetRowAllocation extends LightningElement {
    @api rowIndex;
    @api rowRecord;
    @api fieldList;
    @api disabled;
    @api totalAmount;
    @api remainingAmount;

    CUSTOM_LABELS = GeLabelService.CUSTOM_LABELS;

    @api
    getValues() {
        const fields = this.template.querySelectorAll('c-ge-form-field');
        let widgetFieldAndValues = {};
        if(fields !== null && typeof fields !== 'undefined') {
            fields.forEach(field => {
                const { fieldAndValue } = field;
                // convert full field names to local field names for processing
                Object.entries(fieldAndValue).forEach(([fieldName,fieldValue]) => {
                    const localFieldName = this.getLocalFieldName(fieldName);
                    widgetFieldAndValues = { ...widgetFieldAndValues, ...{[localFieldName]: fieldValue}};
                });
            });
        }
        return widgetFieldAndValues;
    }

    /**
     * Given a field, set a value on that ge-form-field by calling ge-form-field.setFieldValue
     * @param field Field name to set the value for
     * @param value Value ot set
     */
    @api
    setFieldValue(field, value) {
        const element = this.getFieldByName(field);
        if(element) {
            element.setValue(value);
        }
    }

    /**
     * If the total amount is changed, any GAU allocated by percent must be re-allocated to match the total value.
     * Call this method from the parent component on every allocation.
     */
    @api
    reallocateByPercent(totalDonation) {
        const percent = this.rowRecord[ALLOCATION_PERCENT];
        if(isNumeric(percent) && percent >= 0) {
            const detail = {
                targetFieldName: ALLOCATION_PERCENT,
                value: percent
            };
            this.handleChange({ detail }, totalDonation);
        }
    }

    @api
    isValid() {
        const gauField = this.getFieldByName(ALLOCATION_GAU);
        return gauField.isValid();
    }

    /**
     * Calculate what amount is X percent of the total donation amount, rounded down to two decimal places.
     * @param percentValue
     * @param total
     * @return {Number}
     */
    calculateAmount(percentValue, total) {
        const factor = +percentValue / 100;
        const amountInCents = Math.round((total * factor) * 100);
        return (amountInCents / 100);
    }

    /**
     * Handle a change in the percent amount of an Allocation
     * In some cases, we're not changing the percent, but the total donation amount was updated and we need to update it.
     * @param detail    Event Detail
     * @param total  New total to calculate against. Only needed when the total is updating.
     * @returns {{}}
     */
    handlePercentChange(detail, total) {
        const { targetFieldName, value } = detail;
        let payload = { [targetFieldName]: value };
        if(isNumeric(value) && value > 0 && !this.isFieldDisabled(ALLOCATION_AMOUNT)) {
            // if a percent is entered, the amount field should be disabled
            this.disableField(ALLOCATION_AMOUNT);
        } else if(isEmpty(value) || value === 0) {
            if(this.isFieldDisabled(ALLOCATION_AMOUNT)) {
                this.enableField(ALLOCATION_AMOUNT);
            }
        }

        // calculate what percent of the total we should set this row's allocation to
        const amount = this.calculateAmount(value, total);
        this.setFieldValue(ALLOCATION_AMOUNT, amount);
        // add the allocation amount to the update event
        payload[ALLOCATION_AMOUNT] = amount;
        return payload;
    }

    /**
     * When the amount in a GAU Allocation is updated, the percent field should be disabled.
     * @param detail    Detail parameter from the change event in the ge-form-field
     * @returns Object where keys are field names, and values are field values
     */
    handleAmountChange(detail) {
        const { targetFieldName, value } = detail;
        let payload = { [targetFieldName]: value };
        if(isNumeric(value) && value > 0 && !this.isFieldDisabled(ALLOCATION_PERCENT)) {
            this.disableField(ALLOCATION_PERCENT);
        } else if(isEmpty(value) || value === 0) {
            this.enableField(ALLOCATION_PERCENT);
        }

        return payload;
    }

    /**
     * Handle field updates inside this allocation row.
     * @param event
     * @param total Optional total amount parameter for when we're reacting to the total donation amount changing
     */
    handleChange(event, total) {
        let payload;
        // if a total was passed in, use it for calculating percent allocations, otherwise use this.totalAmount
        const totalForCalculation = isNumeric(total) ? total : this.totalAmount;
        if(event.detail.targetFieldName === ALLOCATION_PERCENT) {
            // handle the percent field being updated
            payload = this.handlePercentChange(event.detail, totalForCalculation);
        } else if(event.detail.targetFieldName === ALLOCATION_AMOUNT) {
            // handle the Amount field being updated
            payload = this.handleAmountChange(event.detail);
        }

        if(isNotEmpty(payload)) {
            // notify listeners of the new allocation values
            fireEvent(null, 'allocationValueChange', {rowIndex: this.rowIndex, payload});
        }
    }

    getFieldByName(fieldName) {
        return this.template.querySelector(`[data-fieldname='${fieldName}']`);
    }

    isFieldDisabled(fieldName) {
        const field = this.getFieldByName(fieldName);
        return field.element.disabled === true;
    }

    disableField(fieldName) {
        const field = this.getFieldByName(fieldName);
        field.element =  {...field.element, disabled: true};
    }

    enableField(fieldName) {
        const field = this.getFieldByName(fieldName);
        field.element =  {...field.element, disabled: false};
    }

    remove() {
        const { rowIndex, rowRecord } = this;
        this.dispatchEvent(new CustomEvent('remove', { detail: { rowIndex, rowRecord } }));
    }

    get isRemovable() {
        return this.disabled !== true;
    }

    /**
     * If a value is populated for the field in this.rowRecord, return it.
     * @param fullFieldName e.g. Allocation__c.General_Accounting_Unit__c
     */
    getDefaultForField(fullFieldName) {
        const localFieldName = this.getLocalFieldName(fullFieldName);
        if (localFieldName) {
            return this.rowRecord[localFieldName];
        }
    }

    /**
     * Extract the local field name from a full field name
     * @param fullFieldName example: 'Allocation__c.General_Accounting_Unit__c'
     * @return {*|string}   example: 'General_Accounting_Unit__c'
     */
    getLocalFieldName(fullFieldName) {
        const parts = fullFieldName.split('.');
        if(parts && parts.length === 2) {
            return parts[1];
        }
    }

    /**
     * Merge row-level properties with field level properties.
     * If the whole row is disabled (default GAU) then all fields in the row should be disabled
     */
    get mergedFieldList() {
        if(this.disabled) {
            return this.fieldList.map(f => {
                const { element } = f;
                return {
                    ...f,
                    element: {
                        ...element,
                        disabled: true,
                        defaultValue: this.getDefaultForField(f.mappedField) // only needed for default GAU for now
                    }
                };
            });
        }

        return this.fieldList;
    }

}<commit_msg>Fix empty percent value bug<commit_after>import {LightningElement, api, track} from 'lwc';
import {fireEvent, registerListener} from 'c/pubsubNoPageRef';
import GeLabelService from 'c/geLabelService';
import {isEmpty, isNotEmpty, isNumeric} from 'c/utilCommon';
import ALLOCATION_OBJECT from '@salesforce/schema/Allocation__c';
import AMOUNT_FIELD from '@salesforce/schema/Allocation__c.Amount__c';
import PERCENT_FIELD from '@salesforce/schema/Allocation__c.Percent__c';
import GAU_FIELD from '@salesforce/schema/Allocation__c.General_Accounting_Unit__c';
const ALLOCATION_AMOUNT = `${ALLOCATION_OBJECT.objectApiName}.${AMOUNT_FIELD.fieldApiName}`;
const ALLOCATION_PERCENT = `${ALLOCATION_OBJECT.objectApiName}.${PERCENT_FIELD.fieldApiName}`;
const ALLOCATION_GAU = `${ALLOCATION_OBJECT.objectApiName}.${GAU_FIELD.fieldApiName}`;

export default class GeFormWidgetRowAllocation extends LightningElement {
    @api rowIndex;
    @api rowRecord;
    @api fieldList;
    @api disabled;
    @api totalAmount;
    @api remainingAmount;

    CUSTOM_LABELS = GeLabelService.CUSTOM_LABELS;

    @api
    getValues() {
        const fields = this.template.querySelectorAll('c-ge-form-field');
        let widgetFieldAndValues = {};
        if(fields !== null && typeof fields !== 'undefined') {
            fields.forEach(field => {
                const { fieldAndValue } = field;
                // convert full field names to local field names for processing
                Object.entries(fieldAndValue).forEach(([fieldName,fieldValue]) => {
                    const localFieldName = this.getLocalFieldName(fieldName);
                    if(isNotEmpty(fieldValue)) {
                        // no need to populate fields with values that are blank / empty
                        widgetFieldAndValues = {...widgetFieldAndValues, ...{[localFieldName]: fieldValue}};
                    }
                });
            });
        }
        return widgetFieldAndValues;
    }

    /**
     * Given a field, set a value on that ge-form-field by calling ge-form-field.setFieldValue
     * @param field Field name to set the value for
     * @param value Value ot set
     */
    @api
    setFieldValue(field, value) {
        const element = this.getFieldByName(field);
        if(element) {
            element.setValue(value);
        }
    }

    /**
     * If the total amount is changed, any GAU allocated by percent must be re-allocated to match the total value.
     * Call this method from the parent component on every allocation.
     */
    @api
    reallocateByPercent(totalDonation) {
        const percent = this.rowRecord[ALLOCATION_PERCENT];
        if(isNumeric(percent) && percent >= 0) {
            const detail = {
                targetFieldName: ALLOCATION_PERCENT,
                value: percent
            };
            this.handleChange({ detail }, totalDonation);
        }
    }

    @api
    isValid() {
        const gauField = this.getFieldByName(ALLOCATION_GAU);
        return gauField.isValid();
    }

    /**
     * Calculate what amount is X percent of the total donation amount, rounded down to two decimal places.
     * @param percentValue
     * @param total
     * @return {Number}
     */
    calculateAmount(percentValue, total) {
        const factor = +percentValue / 100;
        const amountInCents = Math.round((total * factor) * 100);
        return (amountInCents / 100);
    }

    /**
     * Handle a change in the percent amount of an Allocation
     * In some cases, we're not changing the percent, but the total donation amount was updated and we need to update it.
     * @param detail    Event Detail
     * @param total  New total to calculate against. Only needed when the total is updating.
     * @returns {{}}
     */
    handlePercentChange(detail, total) {
        const { targetFieldName, value } = detail;
        let payload = { [targetFieldName]: value };
        if(isNumeric(value) && value > 0 && !this.isFieldDisabled(ALLOCATION_AMOUNT)) {
            // if a percent is entered, the amount field should be disabled
            this.disableField(ALLOCATION_AMOUNT);
        } else if(isEmpty(value) || value === 0) {
            if(this.isFieldDisabled(ALLOCATION_AMOUNT)) {
                this.enableField(ALLOCATION_AMOUNT);
            }
        }

        // calculate what percent of the total we should set this row's allocation to
        const amount = this.calculateAmount(value, total);
        this.setFieldValue(ALLOCATION_AMOUNT, amount);
        // add the allocation amount to the update event
        payload[ALLOCATION_AMOUNT] = amount;
        return payload;
    }

    /**
     * When the amount in a GAU Allocation is updated, the percent field should be disabled.
     * @param detail    Detail parameter from the change event in the ge-form-field
     * @returns Object where keys are field names, and values are field values
     */
    handleAmountChange(detail) {
        const { targetFieldName, value } = detail;
        let payload = { [targetFieldName]: value };
        if(isNumeric(value) && value > 0 && !this.isFieldDisabled(ALLOCATION_PERCENT)) {
            this.disableField(ALLOCATION_PERCENT);
        } else if(isEmpty(value) || value === 0) {
            this.enableField(ALLOCATION_PERCENT);
        }

        return payload;
    }

    /**
     * Handle field updates inside this allocation row.
     * @param event
     * @param total Optional total amount parameter for when we're reacting to the total donation amount changing
     */
    handleChange(event, total) {
        let payload;
        // if a total was passed in, use it for calculating percent allocations, otherwise use this.totalAmount
        const totalForCalculation = isNumeric(total) ? total : this.totalAmount;
        if(event.detail.targetFieldName === ALLOCATION_PERCENT) {
            // handle the percent field being updated
            payload = this.handlePercentChange(event.detail, totalForCalculation);
        } else if(event.detail.targetFieldName === ALLOCATION_AMOUNT) {
            // handle the Amount field being updated
            payload = this.handleAmountChange(event.detail);
        }

        if(isNotEmpty(payload)) {
            // notify listeners of the new allocation values
            fireEvent(null, 'allocationValueChange', {rowIndex: this.rowIndex, payload});
        }
    }

    getFieldByName(fieldName) {
        return this.template.querySelector(`[data-fieldname='${fieldName}']`);
    }

    isFieldDisabled(fieldName) {
        const field = this.getFieldByName(fieldName);
        return field.element.disabled === true;
    }

    disableField(fieldName) {
        const field = this.getFieldByName(fieldName);
        field.element =  {...field.element, disabled: true};
    }

    enableField(fieldName) {
        const field = this.getFieldByName(fieldName);
        field.element =  {...field.element, disabled: false};
    }

    remove() {
        const { rowIndex, rowRecord } = this;
        this.dispatchEvent(new CustomEvent('remove', { detail: { rowIndex, rowRecord } }));
    }

    get isRemovable() {
        return this.disabled !== true;
    }

    /**
     * If a value is populated for the field in this.rowRecord, return it.
     * @param fullFieldName e.g. Allocation__c.General_Accounting_Unit__c
     */
    getDefaultForField(fullFieldName) {
        const localFieldName = this.getLocalFieldName(fullFieldName);
        if (localFieldName) {
            return this.rowRecord[localFieldName];
        }
    }

    /**
     * Extract the local field name from a full field name
     * @param fullFieldName example: 'Allocation__c.General_Accounting_Unit__c'
     * @return {*|string}   example: 'General_Accounting_Unit__c'
     */
    getLocalFieldName(fullFieldName) {
        const parts = fullFieldName.split('.');
        if(parts && parts.length === 2) {
            return parts[1];
        }
    }

    /**
     * Merge row-level properties with field level properties.
     * If the whole row is disabled (default GAU) then all fields in the row should be disabled
     */
    get mergedFieldList() {
        if(this.disabled) {
            return this.fieldList.map(f => {
                const { element } = f;
                return {
                    ...f,
                    element: {
                        ...element,
                        disabled: true,
                        defaultValue: this.getDefaultForField(f.mappedField) // only needed for default GAU for now
                    }
                };
            });
        }

        return this.fieldList;
    }

}<|endoftext|>