<commit_before>const _ = require('lodash');

const ConfigurationWrapper = require('../components/Configuration/ConfigurationWrapper');
const constants = require('../components/constants');
const EmailClient = require('../components/Email');
const logger = require('../components/Logger');
const Volunteer = require('../components/Volunteer');

const config = new ConfigurationWrapper('mercury', 'mercury.json');
const emailClient = new EmailClient(config.getKey('email'));
/**
 * This will Validate that the email service is currently up and running and call next otherwise
 * send a 500 internal server that the service is currently not working but they can still login
 * and a validation email will be sent out as soon as the service is running again.
 */
function validateConnectionStatus(req, res, next) {
  if (emailClient.getStatus()) {
    next();
  } else {
    res.status(503).send({ error: 'Email Service', description: constants.EMAIL_UNAVAILABLE });
  }
}

/**
 * Will send a validation email to the new volunteer via there email, allowing them
 * to confirm there current email address.
 */
function sendVerificationEmail(req, res) {
  const { volunteer } = req;
  const code = req.verificationCode;
  let verificationLink;

  if (config.getKey('online')) {
    verificationLink = `${config.getKey('online_address')}/verify/${volunteer.username}/${code}`;
  } else {
    verificationLink = `http://localhost:8080/verify/${volunteer.username}/${code}`;
  }

  // This is currently here because we have no email service
  logger.debug('link for user', volunteer.username, verificationLink);

  const to = req.volunteer.email;
  const from = config.getKey(['email']).email;
  const subject = '[CodeDoesGood] Verification Email';
  const text = verificationLink;

  emailClient.send(from, to, subject, text, text)
    .then(() => {
      res.status(200).send({ message: `Account ${volunteer.username} created, you will soon get a verification email` });
    })
    .catch((error) => {
      logger.error(`Error attempting to send a email. to=${to} from=${from}, error=${error}`);
      res.status(503).send({ error: 'Unavailable Service', description: constants.EMAIL_UNAVAILABLE });
    });
}

/**
 * Resend the verification code to user,
 */
function resendVerificationEmail(req, res) {
  const volunteerId = req.id;
  const volunteer = new Volunteer(volunteerId);

  volunteer.exists()
    .then(() => {
      if (!volunteer.getVerification()) {
        return volunteer.createVerificationCode();
      }
      return res.status(400).send({ error: 'Verification', description: constants.VOLUNTEER_IS_VERIFIED(volunteer.username) });
    })
    .then((code) => {
      req.volunteer = volunteer;
      req.verificationCode = code;
      sendVerificationEmail(req, res);
    })
    .catch(error => res.status(500).send({ error: 'Authentication', description: constants.FAILED_VOLUNTEER_GET(error) }));
}

/**
 * Generates and emails a link to the user for resetting the users password.
 * The front end will then route to a functional page that will post back
 * to reset the users password.
 */
function sendPasswordResetLinkToRequestingEmail(req, res) {
  const { volunteer } = req.volunteer;
  const { username, email } = volunteer;

  const code = req.resetPasswordCode;

  let link;

  if (config.getKey('online')) {
    link = `${config.getKey('online_address')}/reset/${username}/${code}`;
  } else {
    link = `http://localhost:8080/reset/${username}/${code}`;
  }

  const content = `A password reset has been requested for the Volunteer: ${username}. If you did not make this request you ` +
    `can safely ignore this email.\\n\\nIf you do actually want to reset your password, visit this link: ${link}`;

  logger.info(`Created password reset link for user=${username}, link=${link}`);

  const to = email;
  const from = config.getKey(['email']).email;
  const subject = '[CodeDoesGood] Password Reset Email';
  const text = content;

  emailClient.send(from, to, subject, text, text)
    .then(() => {
      res.status(200).send({ message: constants.EMAIL_RESET_SENT });
    })
    .catch((error) => {
      logger.error(`Error attempting to send a email. to=${to} from=${from}, error=${error}`);
      res.status(503).send({ error: 'Unavailable Service', description: constants.EMAIL_UNAVAILABLE });
    });
}

/**
 * Validates the users name, email and text that as been sent.
 */
function validateContactUsRequestInformation(req, res, next) {
  const senderName = req.body.name;
  const senderEmail = req.body.email;
  const senderSubject = req.body.subject;
  const senderText = req.body.text;

  let valid = true;

  const sender = {
    name: senderName, email: senderEmail, subject: senderSubject, text: senderText,
  };

  _.forEach(sender, (item) => { if (_.isNil(item)) { valid = false; } });

  if (!valid) {
    return res.status(400).send({ error: 'Invalid fields', description: constants.EMAIL_FIELDS_REQUIRED });
  } else if (sender.name.length > constants.EMAIL_MAX_LENGTH ||
    sender.email.length > constants.EMAIL_MAX_LENGTH ||
    sender.subject.length > constants.EMAIL_MAX_LENGTH) {
    return res.status(400).send({ error: 'Invalid length', description: constants.EMAIL_AND_NAME_LENGTH });
  } else if (sender.text.length > constants.EMAIL_BODY_MAX_LENGTH ||
    sender.text.length < constants.EMAIL_BODY_MIN_LENGTH) {
    return res.status(400).send({ error: 'Invalid length', description: constants.EMAIL_BODY_LENGTH });
  }

  // Bind the sender to the request data to be accessed later
  req.sender = sender;
  return next();
}

/**
 * Rejects any invalid domain names or banned domain names from being sent.
 */
function DenyInvalidAndBlockedDomains(req, res, next) {
  return next();
}

/**
 * After validation of the name, email and senderText then send the email to the
 * email to the default CodeDoesGood inbox.
 */
function sendContactUsRequestInbox(req, res) {
  const { sender } = req;

  emailClient.send(sender.email, config.getKey(['email']).email, sender.subject, sender.text, sender.text)
    .then(() => {
      res.sendStatus(200);
    })
    .catch((error) => {
      logger.error(`Error attempting to send a email. to=${config.getKey(['email']).email} from=${sender.email}, error=${error}`);
      res.status(503).send({ error: 'Unavailable Service', description: constants.EMAIL_UNAVAILABLE });
    });
}

/**
 * Sends OK or Internal Server Error based on the true / false email status.
 */
function sendContactUsEmailStatus(req, res) {
  if (emailClient.getStatus()) { res.sendStatus(200); } else { res.status(503).send({ error: 'Unavailable Service', description: constants.EMAIL_UNAVAILABLE }); }
}

module.exports = {
  validateConnectionStatus,
  sendVerificationEmail,
  sendPasswordResetLinkToRequestingEmail,
  resendVerificationEmail,
  sendContactUsEmailStatus,
  sendContactUsRequestInbox,
  DenyInvalidAndBlockedDomains,
  validateContactUsRequestInformation,
};
<commit_msg>hot fix reset<commit_after>const _ = require('lodash');

const ConfigurationWrapper = require('../components/Configuration/ConfigurationWrapper');
const constants = require('../components/constants');
const EmailClient = require('../components/Email');
const logger = require('../components/Logger');
const Volunteer = require('../components/Volunteer');

const config = new ConfigurationWrapper('mercury', 'mercury.json');
const emailClient = new EmailClient(config.getKey('email'));
/**
 * This will Validate that the email service is currently up and running and call next otherwise
 * send a 500 internal server that the service is currently not working but they can still login
 * and a validation email will be sent out as soon as the service is running again.
 */
function validateConnectionStatus(req, res, next) {
  if (emailClient.getStatus()) {
    next();
  } else {
    res.status(503).send({ error: 'Email Service', description: constants.EMAIL_UNAVAILABLE });
  }
}

/**
 * Will send a validation email to the new volunteer via there email, allowing them
 * to confirm there current email address.
 */
function sendVerificationEmail(req, res) {
  const { volunteer } = req;
  const code = req.verificationCode;
  let verificationLink;

  if (config.getKey('online')) {
    verificationLink = `${config.getKey('online_address')}/verify/${volunteer.username}/${code}`;
  } else {
    verificationLink = `http://localhost:8080/verify/${volunteer.username}/${code}`;
  }

  // This is currently here because we have no email service
  logger.debug('link for user', volunteer.username, verificationLink);

  const to = req.volunteer.email;
  const from = config.getKey(['email']).email;
  const subject = '[CodeDoesGood] Verification Email';
  const text = verificationLink;

  emailClient.send(from, to, subject, text, text)
    .then(() => {
      res.status(200).send({ message: `Account ${volunteer.username} created, you will soon get a verification email` });
    })
    .catch((error) => {
      logger.error(`Error attempting to send a email. to=${to} from=${from}, error=${error}`);
      res.status(503).send({ error: 'Unavailable Service', description: constants.EMAIL_UNAVAILABLE });
    });
}

/**
 * Resend the verification code to user,
 */
function resendVerificationEmail(req, res) {
  const volunteerId = req.id;
  const volunteer = new Volunteer(volunteerId);

  volunteer.exists()
    .then(() => {
      if (!volunteer.getVerification()) {
        return volunteer.createVerificationCode();
      }
      return res.status(400).send({ error: 'Verification', description: constants.VOLUNTEER_IS_VERIFIED(volunteer.username) });
    })
    .then((code) => {
      req.volunteer = volunteer;
      req.verificationCode = code;
      sendVerificationEmail(req, res);
    })
    .catch(error => res.status(500).send({ error: 'Authentication', description: constants.FAILED_VOLUNTEER_GET(error) }));
}

/**
 * Generates and emails a link to the user for resetting the users password.
 * The front end will then route to a functional page that will post back
 * to reset the users password.
 */
function sendPasswordResetLinkToRequestingEmail(req, res) {
  const { volunteer } = req;
  const { username, email } = volunteer;

  const code = req.resetPasswordCode;

  let link;

  if (config.getKey('online')) {
    link = `${config.getKey('online_address')}/reset/${username}/${code}`;
  } else {
    link = `http://localhost:8080/reset/${username}/${code}`;
  }

  const content = `A password reset has been requested for the Volunteer: ${username}. If you did not make this request you ` +
    `can safely ignore this email.\\n\\nIf you do actually want to reset your password, visit this link: ${link}`;

  logger.info(`Created password reset link for user=${username}, link=${link}`);

  const to = email;
  const from = config.getKey(['email']).email;
  const subject = '[CodeDoesGood] Password Reset Email';
  const text = content;

  emailClient.send(from, to, subject, text, text)
    .then(() => {
      res.status(200).send({ message: constants.EMAIL_RESET_SENT });
    })
    .catch((error) => {
      logger.error(`Error attempting to send a email. to=${to} from=${from}, error=${error}`);
      res.status(503).send({ error: 'Unavailable Service', description: constants.EMAIL_UNAVAILABLE });
    });
}

/**
 * Validates the users name, email and text that as been sent.
 */
function validateContactUsRequestInformation(req, res, next) {
  const senderName = req.body.name;
  const senderEmail = req.body.email;
  const senderSubject = req.body.subject;
  const senderText = req.body.text;

  let valid = true;

  const sender = {
    name: senderName, email: senderEmail, subject: senderSubject, text: senderText,
  };

  _.forEach(sender, (item) => { if (_.isNil(item)) { valid = false; } });

  if (!valid) {
    return res.status(400).send({ error: 'Invalid fields', description: constants.EMAIL_FIELDS_REQUIRED });
  } else if (sender.name.length > constants.EMAIL_MAX_LENGTH ||
    sender.email.length > constants.EMAIL_MAX_LENGTH ||
    sender.subject.length > constants.EMAIL_MAX_LENGTH) {
    return res.status(400).send({ error: 'Invalid length', description: constants.EMAIL_AND_NAME_LENGTH });
  } else if (sender.text.length > constants.EMAIL_BODY_MAX_LENGTH ||
    sender.text.length < constants.EMAIL_BODY_MIN_LENGTH) {
    return res.status(400).send({ error: 'Invalid length', description: constants.EMAIL_BODY_LENGTH });
  }

  // Bind the sender to the request data to be accessed later
  req.sender = sender;
  return next();
}

/**
 * Rejects any invalid domain names or banned domain names from being sent.
 */
function DenyInvalidAndBlockedDomains(req, res, next) {
  return next();
}

/**
 * After validation of the name, email and senderText then send the email to the
 * email to the default CodeDoesGood inbox.
 */
function sendContactUsRequestInbox(req, res) {
  const { sender } = req;

  emailClient.send(sender.email, config.getKey(['email']).email, sender.subject, sender.text, sender.text)
    .then(() => {
      res.sendStatus(200);
    })
    .catch((error) => {
      logger.error(`Error attempting to send a email. to=${config.getKey(['email']).email} from=${sender.email}, error=${error}`);
      res.status(503).send({ error: 'Unavailable Service', description: constants.EMAIL_UNAVAILABLE });
    });
}

/**
 * Sends OK or Internal Server Error based on the true / false email status.
 */
function sendContactUsEmailStatus(req, res) {
  if (emailClient.getStatus()) { res.sendStatus(200); } else { res.status(503).send({ error: 'Unavailable Service', description: constants.EMAIL_UNAVAILABLE }); }
}

module.exports = {
  validateConnectionStatus,
  sendVerificationEmail,
  sendPasswordResetLinkToRequestingEmail,
  resendVerificationEmail,
  sendContactUsEmailStatus,
  sendContactUsRequestInbox,
  DenyInvalidAndBlockedDomains,
  validateContactUsRequestInformation,
};
<|endoftext|>


<commit_before>'use strict';

angular.module('angular-client-side-auth')
.factory('Auth', function($http, $cookieStore){

    var accessLevels = routingConfig.accessLevels
        , userRoles = routingConfig.userRoles
        , currentUser = $cookieStore.get('user') || { username: '', role: userRoles.public };

    $cookieStore.remove('user');

    function changeUser(user) {
        angular.extend(currentUser, user);
    }

    return {
        authorize: function(accessLevel, role) {
            if(role === undefined) {
                role = currentUser.role;
            }

            return accessLevel.bitMask & role.bitMask;
        },
        isLoggedIn: function(user) {
            if(user === undefined) {
                user = currentUser;
            }
            return user.role.title === userRoles.user.title || user.role.title === userRoles.admin.title;
        },
        register: function(user, success, error) {
            $http.post('/register', user).success(function(res) {
                changeUser(res);
                success();
            }).error(error);
        },
        login: function(user, success, error) {
            $http.post('/login', user).success(function(user){
                changeUser(user);
                success(user);
            }).error(error);
        },
        logout: function(success, error) {
            $http.post('/logout').success(function(){
                changeUser({
                    username: '',
                    role: userRoles.public
                });
                success();
            }).error(error);
        },
        accessLevels: accessLevels,
        userRoles: userRoles,
        user: currentUser
    };
});

angular.module('angular-client-side-auth')
.factory('Users', function($http) {
    return {
        getAll: function(success, error) {
            $http.get('/users').success(success).error(error);
        }
    };
});
<commit_msg>Testing transaction button<commit_after>'use strict';

angular.module('angular-client-side-auth')
.factory('Auth', function($http, $cookieStore){

    var accessLevels = routingConfig.accessLevels
        , userRoles = routingConfig.userRoles
        , currentUser = $cookieStore.get('user') || { username: '', role: userRoles.public };

    $cookieStore.remove('user');

    function changeUser(user) {
        angular.extend(currentUser, user);
    }

    return {
        authorize: function(accessLevel, role) {
            if(role === undefined) {
                role = currentUser.role;
            }

            return accessLevel.bitMask & role.bitMask;
        },
        isLoggedIn: function(user) {
            if(user === undefined) {
                user = currentUser;
            }
            return user.role.title === userRoles.user.title || user.role.title === userRoles.admin.title;
        },
        register: function(user, success, error) {
            $http.post('/register', user).success(function(res) {
                changeUser(res);
                success();
            }).error(error);
        },
        login: function(user, success, error) {
            $http.post('/login', user).success(function(user){
                changeUser(user);
                success(user);
            }).error(error);
        },
        newTransaction: function(user, success, error) {
            /*$http.post('/login', user).success(function(user){
                changeUser(user);
                success(user);
            }).error(error);
            */
            alert('test!');
            console.log('test');
        },
        logout: function(success, error) {
            $http.post('/logout').success(function(){
                changeUser({
                    username: '',
                    role: userRoles.public
                });
                success();
            }).error(error);
        },
        accessLevels: accessLevels,
        userRoles: userRoles,
        user: currentUser
    };
});

angular.module('angular-client-side-auth')
.factory('Users', function($http) {
    return {
        getAll: function(success, error) {
            $http.get('/users').success(success).error(error);
        }
    };
});
<|endoftext|>


<commit_before>/**
 * Parses the JSON returned by a network request
 *
 * @param  {object} response A response from a network request
 * @return {object}          The parsed JSON from the request
 */
function parseJSON(response) {
  return response.json();
}

/**
 * Checks if a network request came back fine, and throws an error if not
 *
 * @param  {objct} response   A response from a network request
 * @return {object|undefined} Returns either the response, or throws an error
 */
function checkStatus(response) {
  if (response.status >= 200 && response.status < 300) {
    return response;
  }

  return response.json().then((repsonseJSON) => {
    const error = new Error(response.statusText);
    error.response = repsonseJSON;
    throw error;
  });
}

/**
 * Requests a URL, returning a promise
 *
 * @param  {string} url       The URL we want to request
 * @param  {object} [options] The options we want to pass to "fetch"
 *
 * @return {object}
 */
function Request(url, options = {}) {
  const opts = options;
  const { headers = {} } = options;

  opts.headers = new Headers(headers);

  if (/api\.syncano/.test(url)) {
    if (!opts.headers.has('Content-type')) {
      opts.headers.append('Content-type', 'application/json');
    }
  }

  return fetch(url, opts)
    .then(checkStatus)
    .then(parseJSON)
    .then(data => data);
}

Request.get = (url, options) => new Request(url, {
  method: 'GET',
  ...options,
});

Request.post = (url, data, options) => new Request(url, {
  body: JSON.stringify(data),
  method: 'POST',
  ...options,
});

Request.patch = (url, data, options) => new Request(url, {
  body: JSON.stringify(data),
  method: 'PATCH',
  ...options,
});

Request.put = (url, data, options) => new Request(url, {
  body: JSON.stringify(data),
  method: 'PUT',
  ...options,
});

Request.delete = (url, data, options) => new Request(url, {
  body: JSON.stringify(data),
  method: 'DELETE',
  ...options,
});

export default Request;
<commit_msg>fix: apply proper request content type<commit_after>/**
 * Parses the JSON returned by a network request
 *
 * @param  {object} response A response from a network request
 * @return {object}          The parsed JSON from the request
 */
function parseJSON(response) {
  return response.json();
}

/**
 * Checks if a network request came back fine, and throws an error if not
 *
 * @param  {objct} response   A response from a network request
 * @return {object|undefined} Returns either the response, or throws an error
 */
function checkStatus(response) {
  if (response.status >= 200 && response.status < 300) {
    return response;
  }

  return response.json().then((repsonseJSON) => {
    const error = new Error(response.statusText);
    error.response = repsonseJSON;
    throw error;
  });
}

/**
 * Requests a URL, returning a promise
 *
 * @param  {string} url       The URL we want to request
 * @param  {object} [options] The options we want to pass to "fetch"
 *
 * @return {object}
 */
function Request(url, options = {}) {
  const opts = options;
  const { headers = {} } = options;

  opts.headers = new Headers(headers);

  if (!opts.headers.has('Content-type')) {
    opts.headers.append('Content-type', 'application/json');
  }

  return fetch(url, opts)
    .then(checkStatus)
    .then(parseJSON)
    .then(data => data);
}

Request.get = (url, options) => new Request(url, {
  method: 'GET',
  ...options,
});

Request.post = (url, data, options) => new Request(url, {
  body: JSON.stringify(data),
  method: 'POST',
  ...options,
});

Request.patch = (url, data, options) => new Request(url, {
  body: JSON.stringify(data),
  method: 'PATCH',
  ...options,
});

Request.put = (url, data, options) => new Request(url, {
  body: JSON.stringify(data),
  method: 'PUT',
  ...options,
});

Request.delete = (url, data, options) => new Request(url, {
  body: JSON.stringify(data),
  method: 'DELETE',
  ...options,
});

export default Request;
<|endoftext|>


<commit_before>import { constants } from "../common/constants.js";
import { kinveyRequester } from "../common/kinvey-requester.js";
import { templateLoader as tl } from "../common/template-loader.js";
import * as models from "../models/models.js";
import * as imageTools from "../common/image-tools.js";

let vehicleController = (function() {

    let allVehicles = [];
    let userAds = [];

    function all(context) {
        $("#vehiclesForSale").removeClass("open");

        document.getElementById('sortOptions').style.display = 'block';
        let sortOrder = document.getElementById('sortOrder').value;
        // console.log(sortOrder);
        let itemsPerPage = document.getElementById('itemsPerPage').value;
        // console.log(itemsPerPage);
        let pageNumber = 1; // to be fixed with pagination

        Promise.all([kinveyRequester.findAllVehicles(sortOrder, itemsPerPage, pageNumber), tl.get("vehicles")])
            .then(([data, template]) => {
                //dont touch the code because "maikata si ebalo"
                let currentUser = sessionStorage.getItem("userID");
                for (let vehicle of data) {
                    if (currentUser === vehicle._acl.creator) {
                        userAds.push(vehicle);
                        vehicle.currentUser = currentUser;
                    }
                }

                $("#content").html(template(data));
                // context.$element().html(template(data));
                allVehicles = data.slice();
            })
            .then((options) => {
                toastr.success(constants.VEHICLES_LOADED);
            })
            .then(() => {
                $(".caption").on("click", function(ev) {
                    const selectedVehicleId = $(this).attr("id");
                    if ($(ev.target).hasClass("editLink")) {
                        document.location = "#/Edit/?id=" + selectedVehicleId;
                    }

                    if ($(ev.target).hasClass("wishList")) {
                        addToWishList(selectedVehicleId);
                    }

                    if ($(ev.target).hasClass("deleteLink")) {
                        document.location = "#/Delete/?id=" + selectedVehicleId;
                    }

                    if ($(ev.target).hasClass("vehicleDetails")) {
                        document.location = "#/VehicleDetails/?id=" + selectedVehicleId;
                    }
                });
            });

        $("#content").on("click", function(ev) {
            //TODO need to find a way to make width bigger cause currently it is limited to div width
            if (ev.target.nodeName === "IMG") {
                let target = $(ev.target);
                target.animate({ height: "300px", opacity: "0.8" }, "slow");
                target.animate({ width: "300px", opacity: "0.8" }, "slow");
                target.animate({ height: "100px", opacity: "0.8" }, "slow");
                target.animate({ width: "100px", opacity: "0.8" }, "slow");
            }
            if (ev.target.nodeName === "A") {
                let elem = $(ev.target);
                let hiddenElem = elem.next();
                $(elem).click(function() {
                    elem.hide();
                    $(hiddenElem).slideToggle("slow");
                });
            }
        });

        let search = $('#vehicleSearch');
        search.keyup(function(ev) {
            let text = search.val();
            let searchedVehicles = [];
            $("#vehiclesForSale").removeClass("open");
            tl.get("vehicles")
                .then((template) => {
                    for (let vehicle of allVehicles) {
                        let match = vehicle.make.indexOf(text) >= 0 || vehicle.model.indexOf(text) >= 0;
                        if (match) {
                            searchedVehicles.push(vehicle);
                        }
                    }

                    $("#content").html(template(searchedVehicles))
                });
        });
    }

    function seeYourAds(context) {
        $("#vehiclesForSale").removeClass("open");

        const userId = sessionStorage.getItem("userID");

        Promise.all([kinveyRequester.findVehiclesByOwnerId(userId), tl.get("your-ads")])
            .then(([data, template]) => {
                context.$element().html(template(data));

                $(".caption").on("click", function(ev) {
                    const selectedVehicleId = $(this).attr("id");
                    if ($(ev.target).hasClass("editLink")) {
                        document.location = "#/Edit/?id=" + selectedVehicleId;
                    }

                    if ($(ev.target).hasClass("wishList")) {
                        addToWishList(selectedVehicleId);
                    }

                    if ($(ev.target).hasClass("deleteLink")) {
                        document.location = "#/Delete/?id=" + selectedVehicleId;
                    }

                    if ($(ev.target).hasClass("vehicleDetails")) {
                        document.location = "#/VehicleDetails/?id=" + selectedVehicleId;
                    }
                });
            })
            .catch((err) => toastr.error(err.responseText));
    }

    function addToWishList(vehicleId) {
        kinveyRequester.addToWishList(vehicleId)
            .then(() => toastr.success(constants.SUCCESS_ADD_TO_WISHLIST))
            .catch((err) => toastr.error(err.responseText));
    }

    function userWishList(context) {
        $('#sortOptions').hide();

        kinveyRequester.getUserWishList()
            .then((data) => {
                Promise.all([kinveyRequester.findVehiclesById(data), tl.get("wish-list")])
                    .then(([vehicles, template]) => {
                        context.$element().html(template(vehicles));
                    })
                    .then(() => {
                        $("#btn-Back").on("click", function(ev) {
                            document.location = ("#/Shop")
                        });

                        $(".remove-wish").on("click", function(ev) {
                            const userId = sessionStorage.getItem("userID");
                            const vehicleId = $(ev.target).parents(".container").attr("id");
                            kinveyRequester.getFullUserWishList()
                                .then((wishes) => {
                                    for (let wish of wishes) {
                                        if (wish.userId === userId && wish.vehicleId === vehicleId) {
                                            kinveyRequester.deleteVehicleFromWishList(wish._id)
                                                .then(() => toastr.success(constants.SUCCESS_DELETE))
                                                .then(() => document.location = ("#/UserChoise"))
                                                .catch((err) => toastr.error(err.responseText));
                                        }
                                    };
                                })
                                .catch((err) => toastr.error(err.responseText));
                        });
                    })
                    .catch((err) => toastr.error(err.responseText));
            })
            .catch((err) => toastr.error(err.responseText));
    }

    function vehicleDetails(context) {
        document.getElementById('sortOptions').style.display = 'none';

        const id = context.params["id"];

        kinveyRequester.findVehicleById(id)
            .then((vehicle) => {
                const ownerId = vehicle._acl.creator;
                Promise.all([tl.get("vehicle-details"), kinveyRequester.getUser(ownerId)])
                    .then(([template, user]) => {
                        const data = { vehicle, user };
                        context.$element().html(template(data));
                    })
                    .then(() => {
                        $("#btn-Back").on("click", function(ev) {
                            document.location = ("#/Shop")
                        });
                    })
                    .catch((err) => toastr.error(err.responseText));
            })
            .catch((err) => toastr.error(err.responseText));
    }

    function addVehicle(context) {
        document.getElementById('sortOptions').style.display = 'none';

        $("#vehiclesForSale").removeClass("open");

        tl.get("add-vehicle")
            .then(template => context.$element().html(template(constants.VEHICLE_TYPES)))
            .then(() => {
                $("#new-vehicle-type").on("change", function() {
                    const selected = $(this).val();
                    const motorcycleType = $("#motorcycleType");
                    const truckAxes = $("#truckAxes");
                    const busSeats = $("#busSeats");

                    switch (selected) {
                        case "Car":
                            motorcycleType.addClass("hidden");
                            truckAxes.addClass("hidden");
                            busSeats.addClass("hidden");
                            break;
                        case "Motorcycle":
                            motorcycleType.removeClass("hidden");
                            truckAxes.addClass("hidden");
                            busSeats.addClass("hidden");
                            break;
                        case "Truck":
                            motorcycleType.addClass("hidden");
                            truckAxes.removeClass("hidden");
                            busSeats.addClass("hidden");
                            break;
                        case "Bus":
                            motorcycleType.addClass("hidden");
                            truckAxes.addClass("hidden");
                            busSeats.removeClass("hidden");
                            break;
                        default:
                            break;
                    }

                });

                $("#btnAddVehicle").on("click", () => {
                    const make = $("#new-vehicle-make").val();
                    const model = $("#new-vehicle-model").val();
                    const firstRegistration = $("#new-vehicle-year").val();
                    const fuelType = $("#new-vehicle-fuel-type").val();
                    const hp = $("#new-vehicle-hp").val();
                    const price = $("#new-vehicle-price").val();
                    const info = $("#new-vehicle-info").val();
                    const image = $("#new-vehicle-image-file")[0].files[0];

                    const vehicleType = $("#new-vehicle-type").val();

                    let newVehicle = {};

                    try {
                        switch (vehicleType) {
                            case "Car":
                                return models.getCar(make, model, firstRegistration, fuelType, hp, price, info);
                            case "Motorcycle":
                                const type = $("#motorcycleType").val();
                                return models.getMotorcycle(make, model, firstRegistration, fuelType, hp, price, info, type);
                            case "Truck":
                                const axes = $("#truckAxes").val();
                                return models.getTruck(make, model, firstRegistration, fuelType, hp, price, info, axes);
                            case "Bus":
                                const seats = $("#busSeats").val();
                                return models.getBus(make, model, firstRegistration, fuelType, hp, price, info, seats);
                            default:
                                break;
                        }
                    } catch (ex) {
                        toastr.error(ex.message);
                        return;
                    }

                    newVehicle["_vehicleType"] = vehicleType;
                    newVehicle["_imageUrl"] = "";

                    kinveyRequester.createVehicle(newVehicle)
                        .then(() => {
                            if (image) {
                                const currentUserId = sessionStorage.getItem("userID");
                                kinveyRequester.findLastVehicleIdByOwnerId(currentUserId)
                                    .then((data) => {
                                        const metadata = {
                                            vehicleId: data._id,
                                            mimeType: image.type,
                                            _public: true
                                        };

                                        imageTools.default.resize(image, {
                                            width: constants.MAX_IMAGE_WIDTH,
                                            height: constants.MAX_IMAGE_HEIGHT
                                        }, function(blob) {
                                            kinveyRequester.uploadImage(blob, metadata);
                                        });

                                    });
                            }
                        })
                        .then(() => {
                            toastr.success(constants.SUCCESS_ADD_VEHICLE);
                            document.location = "#/Shop";
                        })
                        .catch((err) => {
                            toastr.error(err.responseText);
                        });
                });
            });
    }

    function editVehicle(context) {
        document.getElementById('sortOptions').style.display = 'none';

        const id = context.params["id"];
        let vehicle = {};
        Promise.all([kinveyRequester.findVehicleById(id), tl.get("edit-vehicle")])
            .then(([data, template]) => {
                context.$element().html(template(data));
                toastr.success(`${data._make} ${data._model} preparing for edit`);
            })
            .then(() => {
                $("#btn-Back").on("click", function(ev) {
                    document.location = ("#/Shop")
                });

                $("#btn-Edit").on("click", function(ev) {
                    const make = $("#vehicle-make").val();
                    const model = $("#vehicle-model").val();
                    const firstRegistration = $("#vehicle-year").val();
                    const hp = $("#vehicle-hp").val();
                    const price = $("#vehicle-price").val();
                    const info = $("#vehicle-info").val();
                    const fuelType = $("#vehicle-fuel-type").val();

                    const vehicleType = $("#vehicle-v-type").val();
                    const imageUrl = $("#vehicle-image-url").val();

                    let newVehicle = {};

                    try {
                        switch (vehicleType) {
                            case "Car":
                                return models.getCar(make, model, firstRegistration, fuelType, hp, price, info);
                            case "Motorcycle":
                                const type = $("#vehicle-type").val();
                                return models.getMotorcycle(make, model, firstRegistration, fuelType, hp, price, info, type);
                            case "Truck":
                                const axes = $("#vehicle-axes")[0].val();
                                return models.getTruck(make, model, firstRegistration, fuelType, hp, price, info, axes);
                            case "Bus":
                                const seats = $("#vehicle-seats").val();
                                return models.getBus(make, model, firstRegistration, fuelType, hp, price, info, seats);
                            default:
                                break;
                        }
                    } catch (ex) {
                        toastr.error(ex.message);
                        return;
                    }

                    newVehicle["_vehicleType"] = vehicleType;
                    newVehicle["_imageUrl"] = imageUrl;

                    kinveyRequester.editVehicle(id, newVehicle)
                        .then(() => {
                            toastr.success(constants.SUCCESS_EDITED)
                            document.location = ("#/Shop");
                        });
                });
            })
            .catch((err) => toastr.error(err));
    }

    function deleteVehicle(context) {
        document.getElementById('sortOptions').style.display = 'none';

        const id = context.params["id"];
        Promise.all([kinveyRequester.findVehicleById(id), tl.get("delete-vehicle")])
            .then(([data, template]) => {
                context.$element().html(template(data))
                toastr.success(`${data._make} ${data._model} preparing for delete`);
            })
            .then(() => {
                $("#btn-goBack").on("click", function(ev) {
                    document.location = ("#/Shop");
                });

                $("#btn-Delete").on("click", function(ev) {
                    kinveyRequester.deleteImageByVehicleId(id);
                    kinveyRequester.deleteVehicle(id)
                        .then(() => {
                            toastr.success(constants.SUCCESS_DELETE);
                            document.location = ("#/Shop");
                        })
                        .catch(() => toastr.error(err.responseText));
                });
            });
    }

    return {
        all,
        vehicleDetails,
        addVehicle,
        editVehicle,
        deleteVehicle,
        seeYourAds,
        userWishList
    }

})();

export { vehicleController };<commit_msg>fixed search, but still searches only in current page, because "all" ;-)<commit_after>import { constants } from "../common/constants.js";
import { kinveyRequester } from "../common/kinvey-requester.js";
import { templateLoader as tl } from "../common/template-loader.js";
import * as models from "../models/models.js";
import * as imageTools from "../common/image-tools.js";

let vehicleController = (function() {

    let allVehicles = [];
    let userAds = [];

    function all(context) {
        $("#vehiclesForSale").removeClass("open");

        document.getElementById('sortOptions').style.display = 'block';
        let sortOrder = document.getElementById('sortOrder').value;
        // console.log(sortOrder);
        let itemsPerPage = document.getElementById('itemsPerPage').value;
        // console.log(itemsPerPage);
        let pageNumber = 1; // to be fixed with pagination

        Promise.all([kinveyRequester.findAllVehicles(sortOrder, itemsPerPage, pageNumber), tl.get("vehicles")])
            .then(([data, template]) => {
                //dont touch the code because "maikata si ebalo"
                let currentUser = sessionStorage.getItem("userID");
                for (let vehicle of data) {
                    if (currentUser === vehicle._acl.creator) {
                        userAds.push(vehicle);
                        vehicle.currentUser = currentUser;
                    }
                }

                $("#content").html(template(data));
                // context.$element().html(template(data));
                allVehicles = data.slice();
            })
            .then((options) => {
                toastr.success(constants.VEHICLES_LOADED);
            })
            .then(() => {
                $(".caption").on("click", function(ev) {
                    const selectedVehicleId = $(this).attr("id");
                    if ($(ev.target).hasClass("editLink")) {
                        document.location = "#/Edit/?id=" + selectedVehicleId;
                    }

                    if ($(ev.target).hasClass("wishList")) {
                        addToWishList(selectedVehicleId);
                    }

                    if ($(ev.target).hasClass("deleteLink")) {
                        document.location = "#/Delete/?id=" + selectedVehicleId;
                    }

                    if ($(ev.target).hasClass("vehicleDetails")) {
                        document.location = "#/VehicleDetails/?id=" + selectedVehicleId;
                    }
                });
            });

        $("#content").on("click", function(ev) {
            //TODO need to find a way to make width bigger cause currently it is limited to div width
            if (ev.target.nodeName === "IMG") {
                let target = $(ev.target);
                target.animate({ height: "300px", opacity: "0.8" }, "slow");
                target.animate({ width: "300px", opacity: "0.8" }, "slow");
                target.animate({ height: "100px", opacity: "0.8" }, "slow");
                target.animate({ width: "100px", opacity: "0.8" }, "slow");
            }
            if (ev.target.nodeName === "A") {
                let elem = $(ev.target);
                let hiddenElem = elem.next();
                $(elem).click(function() {
                    elem.hide();
                    $(hiddenElem).slideToggle("slow");
                });
            }
        });

        let search = $('#vehicleSearch');
        search.keyup(function(ev) {
            let text = search.val().toLowerCase();
            let searchedVehicles = [];
            $("#vehiclesForSale").removeClass("open");
            tl.get("vehicles")
                .then((template) => {
                    for (let vehicle of allVehicles) {
                        let match = vehicle._make.toLowerCase().indexOf(text) >= 0 ||
                            vehicle._model.toLowerCase().indexOf(text) >= 0;
                        if (match) {
                            searchedVehicles.push(vehicle);
                        }
                    }

                    $("#content").html(template(searchedVehicles))
                });
        });
    }

    function seeYourAds(context) {
        $("#vehiclesForSale").removeClass("open");

        const userId = sessionStorage.getItem("userID");

        Promise.all([kinveyRequester.findVehiclesByOwnerId(userId), tl.get("your-ads")])
            .then(([data, template]) => {
                context.$element().html(template(data));

                $(".caption").on("click", function(ev) {
                    const selectedVehicleId = $(this).attr("id");
                    if ($(ev.target).hasClass("editLink")) {
                        document.location = "#/Edit/?id=" + selectedVehicleId;
                    }

                    if ($(ev.target).hasClass("wishList")) {
                        addToWishList(selectedVehicleId);
                    }

                    if ($(ev.target).hasClass("deleteLink")) {
                        document.location = "#/Delete/?id=" + selectedVehicleId;
                    }

                    if ($(ev.target).hasClass("vehicleDetails")) {
                        document.location = "#/VehicleDetails/?id=" + selectedVehicleId;
                    }
                });
            })
            .catch((err) => toastr.error(err.responseText));
    }

    function addToWishList(vehicleId) {
        kinveyRequester.addToWishList(vehicleId)
            .then(() => toastr.success(constants.SUCCESS_ADD_TO_WISHLIST))
            .catch((err) => toastr.error(err.responseText));
    }

    function userWishList(context) {
        $('#sortOptions').hide();

        kinveyRequester.getUserWishList()
            .then((data) => {
                Promise.all([kinveyRequester.findVehiclesById(data), tl.get("wish-list")])
                    .then(([vehicles, template]) => {
                        context.$element().html(template(vehicles));
                    })
                    .then(() => {
                        $("#btn-Back").on("click", function(ev) {
                            document.location = ("#/Shop")
                        });

                        $(".remove-wish").on("click", function(ev) {
                            const userId = sessionStorage.getItem("userID");
                            const vehicleId = $(ev.target).parents(".container").attr("id");
                            kinveyRequester.getFullUserWishList()
                                .then((wishes) => {
                                    for (let wish of wishes) {
                                        if (wish.userId === userId && wish.vehicleId === vehicleId) {
                                            kinveyRequester.deleteVehicleFromWishList(wish._id)
                                                .then(() => toastr.success(constants.SUCCESS_DELETE))
                                                .then(() => document.location = ("#/UserChoise"))
                                                .catch((err) => toastr.error(err.responseText));
                                        }
                                    };
                                })
                                .catch((err) => toastr.error(err.responseText));
                        });
                    })
                    .catch((err) => toastr.error(err.responseText));
            })
            .catch((err) => toastr.error(err.responseText));
    }

    function vehicleDetails(context) {
        document.getElementById('sortOptions').style.display = 'none';

        const id = context.params["id"];

        kinveyRequester.findVehicleById(id)
            .then((vehicle) => {
                const ownerId = vehicle._acl.creator;
                Promise.all([tl.get("vehicle-details"), kinveyRequester.getUser(ownerId)])
                    .then(([template, user]) => {
                        const data = { vehicle, user };
                        context.$element().html(template(data));
                    })
                    .then(() => {
                        $("#btn-Back").on("click", function(ev) {
                            document.location = ("#/Shop")
                        });
                    })
                    .catch((err) => toastr.error(err.responseText));
            })
            .catch((err) => toastr.error(err.responseText));
    }

    function addVehicle(context) {
        document.getElementById('sortOptions').style.display = 'none';

        $("#vehiclesForSale").removeClass("open");

        tl.get("add-vehicle")
            .then(template => context.$element().html(template(constants.VEHICLE_TYPES)))
            .then(() => {
                $("#new-vehicle-type").on("change", function() {
                    const selected = $(this).val();
                    const motorcycleType = $("#motorcycleType");
                    const truckAxes = $("#truckAxes");
                    const busSeats = $("#busSeats");

                    switch (selected) {
                        case "Car":
                            motorcycleType.addClass("hidden");
                            truckAxes.addClass("hidden");
                            busSeats.addClass("hidden");
                            break;
                        case "Motorcycle":
                            motorcycleType.removeClass("hidden");
                            truckAxes.addClass("hidden");
                            busSeats.addClass("hidden");
                            break;
                        case "Truck":
                            motorcycleType.addClass("hidden");
                            truckAxes.removeClass("hidden");
                            busSeats.addClass("hidden");
                            break;
                        case "Bus":
                            motorcycleType.addClass("hidden");
                            truckAxes.addClass("hidden");
                            busSeats.removeClass("hidden");
                            break;
                        default:
                            break;
                    }

                });

                $("#btnAddVehicle").on("click", () => {
                    const make = $("#new-vehicle-make").val();
                    const model = $("#new-vehicle-model").val();
                    const firstRegistration = $("#new-vehicle-year").val();
                    const fuelType = $("#new-vehicle-fuel-type").val();
                    const hp = $("#new-vehicle-hp").val();
                    const price = $("#new-vehicle-price").val();
                    const info = $("#new-vehicle-info").val();
                    const image = $("#new-vehicle-image-file")[0].files[0];

                    const vehicleType = $("#new-vehicle-type").val();

                    let newVehicle = {};

                    try {
                        switch (vehicleType) {
                            case "Car":
                                return models.getCar(make, model, firstRegistration, fuelType, hp, price, info);
                            case "Motorcycle":
                                const type = $("#motorcycleType").val();
                                return models.getMotorcycle(make, model, firstRegistration, fuelType, hp, price, info, type);
                            case "Truck":
                                const axes = $("#truckAxes").val();
                                return models.getTruck(make, model, firstRegistration, fuelType, hp, price, info, axes);
                            case "Bus":
                                const seats = $("#busSeats").val();
                                return models.getBus(make, model, firstRegistration, fuelType, hp, price, info, seats);
                            default:
                                break;
                        }
                    } catch (ex) {
                        toastr.error(ex.message);
                        return;
                    }

                    newVehicle["_vehicleType"] = vehicleType;
                    newVehicle["_imageUrl"] = "";

                    kinveyRequester.createVehicle(newVehicle)
                        .then(() => {
                            if (image) {
                                const currentUserId = sessionStorage.getItem("userID");
                                kinveyRequester.findLastVehicleIdByOwnerId(currentUserId)
                                    .then((data) => {
                                        const metadata = {
                                            vehicleId: data._id,
                                            mimeType: image.type,
                                            _public: true
                                        };

                                        imageTools.default.resize(image, {
                                            width: constants.MAX_IMAGE_WIDTH,
                                            height: constants.MAX_IMAGE_HEIGHT
                                        }, function(blob) {
                                            kinveyRequester.uploadImage(blob, metadata);
                                        });

                                    });
                            }
                        })
                        .then(() => {
                            toastr.success(constants.SUCCESS_ADD_VEHICLE);
                            document.location = "#/Shop";
                        })
                        .catch((err) => {
                            toastr.error(err.responseText);
                        });
                });
            });
    }

    function editVehicle(context) {
        document.getElementById('sortOptions').style.display = 'none';

        const id = context.params["id"];
        let vehicle = {};
        Promise.all([kinveyRequester.findVehicleById(id), tl.get("edit-vehicle")])
            .then(([data, template]) => {
                context.$element().html(template(data));
                toastr.success(`${data._make} ${data._model} preparing for edit`);
            })
            .then(() => {
                $("#btn-Back").on("click", function(ev) {
                    document.location = ("#/Shop")
                });

                $("#btn-Edit").on("click", function(ev) {
                    const make = $("#vehicle-make").val();
                    const model = $("#vehicle-model").val();
                    const firstRegistration = $("#vehicle-year").val();
                    const hp = $("#vehicle-hp").val();
                    const price = $("#vehicle-price").val();
                    const info = $("#vehicle-info").val();
                    const fuelType = $("#vehicle-fuel-type").val();

                    const vehicleType = $("#vehicle-v-type").val();
                    const imageUrl = $("#vehicle-image-url").val();

                    let newVehicle = {};

                    try {
                        switch (vehicleType) {
                            case "Car":
                                return models.getCar(make, model, firstRegistration, fuelType, hp, price, info);
                            case "Motorcycle":
                                const type = $("#vehicle-type").val();
                                return models.getMotorcycle(make, model, firstRegistration, fuelType, hp, price, info, type);
                            case "Truck":
                                const axes = $("#vehicle-axes")[0].val();
                                return models.getTruck(make, model, firstRegistration, fuelType, hp, price, info, axes);
                            case "Bus":
                                const seats = $("#vehicle-seats").val();
                                return models.getBus(make, model, firstRegistration, fuelType, hp, price, info, seats);
                            default:
                                break;
                        }
                    } catch (ex) {
                        toastr.error(ex.message);
                        return;
                    }

                    newVehicle["_vehicleType"] = vehicleType;
                    newVehicle["_imageUrl"] = imageUrl;

                    kinveyRequester.editVehicle(id, newVehicle)
                        .then(() => {
                            toastr.success(constants.SUCCESS_EDITED)
                            document.location = ("#/Shop");
                        });
                });
            })
            .catch((err) => toastr.error(err));
    }

    function deleteVehicle(context) {
        document.getElementById('sortOptions').style.display = 'none';

        const id = context.params["id"];
        Promise.all([kinveyRequester.findVehicleById(id), tl.get("delete-vehicle")])
            .then(([data, template]) => {
                context.$element().html(template(data))
                toastr.success(`${data._make} ${data._model} preparing for delete`);
            })
            .then(() => {
                $("#btn-goBack").on("click", function(ev) {
                    document.location = ("#/Shop");
                });

                $("#btn-Delete").on("click", function(ev) {
                    kinveyRequester.deleteImageByVehicleId(id);
                    kinveyRequester.deleteVehicle(id)
                        .then(() => {
                            toastr.success(constants.SUCCESS_DELETE);
                            document.location = ("#/Shop");
                        })
                        .catch(() => toastr.error(err.responseText));
                });
            });
    }

    return {
        all,
        vehicleDetails,
        addVehicle,
        editVehicle,
        deleteVehicle,
        seeYourAds,
        userWishList
    }

})();

export { vehicleController };<|endoftext|>


<commit_before>import React from 'react';
import { connect } from 'react-redux';
import Node from './vEBNode';
import {store} from './main.js';
const NODE_RADIUS = 10;
import {ADD_POINT, INSERT_NODE, SET_ROOT, CLEAR_POINTS} from './constants';

function vEBReducer (state, action) {
  if (state === undefined) {
    return {root: null,};
  }

  switch (action.type) {
    case SET_ROOT:
      return Object.assign({}, state, {
        root: action.root,
      });
    case INSERT_NODE:
      let newElement = isNaN(action.newElement) ? parseInt(action.newElement.split('').map(x => x.charCodeAt(0)).reduce(x, y) => x+y, '') : parseFloat(action.newElement);
      if (state.root === null) {
        return Object.assign({}, state, {
          root: new Node(newElement),
        });
      }
      state.root.insert(newElement);
    default:
      return state;
  }
}

class vEBGraph extends React.Component {
  constructor () {
    super();
    this.state = {
      simulation: d3.forceSimulation(),
      newElement: '',
    };
    this.insertElement = this.insertElement.bind(this);
    this.changeElement = this.changeElement.bind(this);
    this.makevEBTree = this.makevEBTree.bind(this);
  }

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

  insertElement (event) {
    let newElement = this.state.newElement;

    event.preventDefault();
    store.dispatch({type: INSERT_NODE, newElement});
    this.setState({newElement: ''});
  }

  makevEBTree () {
    store.dispatch({type: CLEAR_POINTS});
    // figure out how this works TODO
  }

  render () {
    return (

        <form onSubmit={this.insertElement}>
          Insert an element
          <input value={this.state.newElement} onChange={this.changeElement}></input>
          <button type="submit">Insert</button>
        </form>
        <button onClick={this.makeGeometricBST}>Make Geometric BST</button>
        <svg id="standard" className="graph">
          <g id="links"/>
          <g id="nodes"/>
        </svg>

    );
  }

  componentDidMount () {
    // TODO
  }

  componentDidUpdate () {
    // TODO
  }
}

export default connect(function (state, ownProps) {
  return {root: state.vEBTree.root,};
})(vEBGraph);

export {vEBReducer};
<commit_msg>just adding this for now to see updates<commit_after>import React from 'react';
import { connect } from 'react-redux';
import Node from './vEBNode';
import {store} from './main.js';
const NODE_RADIUS = 10;
import {ADD_POINT, INSERT_NODE, SET_ROOT, CLEAR_POINTS} from './constants';

function vEBReducer (state, action) {
  if (state === undefined) {
    return {root: null,};
  }

  switch (action.type) {
    case SET_ROOT:
      return Object.assign({}, state, {
        root: action.root,
      });
    case INSERT_NODE:
      let newElement = isNaN(action.newElement) ? parseInt(action.newElement.split('').map(x => x.charCodeAt(0)).reduce(x, y) => x+y, '') : parseFloat(action.newElement);
      if (state.root === null) {
        return Object.assign({}, state, {
          root: new Node(newElement),
        });
      }
      state.root.insert(newElement);
    default:
      return state;
  }
}

class vEBGraph extends React.Component {
  constructor () {
    super();
    this.state = {
      simulation: d3.forceSimulation(),
      newElement: '',
    };
    this.insertElement = this.insertElement.bind(this);
    this.changeElement = this.changeElement.bind(this);
    this.makevEBTree = this.makevEBTree.bind(this);
  }

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

  insertElement (event) {
    let newElement = this.state.newElement;

    event.preventDefault();
    store.dispatch({type: INSERT_NODE, newElement});
    this.setState({newElement: ''});
  }

  makevEBTree () {
    store.dispatch({type: CLEAR_POINTS});
    let nodes = null; // TODO: make this actually something
    nodes.forEach((node, i) => {
      let point = new Point(node.key, node.value, i+1);
      store.dispatch({type: ADD_POINT, point});
      node.getAncestors().forEach(ancestor => {
        point = new Point(ancestor.key, ancestor.value, i+1);
        point.isSatisfier = true;
        store.dispatch({type: ADD_POINT, point});
      });
    });
  }

  render () {
    return (

        <form onSubmit={this.insertElement}>
          Insert an element
          <input value={this.state.newElement} onChange={this.changeElement}></input>
          <button type="submit">Insert</button>
        </form>
        <button onClick={this.makeGeometricBST}>Make Geometric BST</button>
        <svg id="standard" className="graph">
          <g id="links"/>
          <g id="nodes"/>
        </svg>

    );
  }

  componentDidMount () {
    let standard = d3.select('#standard');
    this.state.simulation
      .force('collision', d3.forceCollide().radius(NODE_RADIUS + 5))
      .force('manyBody', d3.forceManyBody().strength(1))
      .on('tick', () => {
        standard.selectAll('svg.node').transition()
          .ease(v => d3.easeSinIn(v))
          .duration(100)
          .attr('x', (d) => {
            if(d.parent !== null && d.parent.x !== null) {
              let delta = NODE_RADIUS;
              delta *= Math.pow(2, d.parent.height);
              d.x = d == d.parent.left ? d.parent.x - delta : d.parent.x + delta;
            }
            return d.x;
          })
          .attr('y', (d) => {
            if(d.parent !== null && d.parent.y !== null) {
              d.y = d.parent.y + 50; // TODO: note position with relation to parents
            }
            return d.y;
          });

        if(this.props.root !== null) {
          this.props.root.fx = standard.node().getBoundingClientRect().width / 2;
          this.props.root.fy = standard.node().getBoundingClientRect().height / 3;
        }

        standard.selectAll('text.node')
          .text((d) => d.key);

        standard.selectAll('line.link').transition()
          .duration(100)
          .ease(v => d3.easeSinIn(v)) // TODO: note animations here
          .attr('x1', d => d.source.x + NODE_RADIUS * 2)
          .attr('y1', d => d.source.y + NODE_RADIUS * 2)
          .attr('x2', d => d.target.x + NODE_RADIUS * 2)
          .attr('y2', d => d.target.y + NODE_RADIUS * 2);
      });
    this.componentDidUpdate();
  }

  componentDidUpdate () {
    if(this.props.root === null)return;

    let standard = d3.select('#standard');

    function linkChildren (parent) {
      let linkList = [];
      if(parent.left !== null) {
        linkList.push({source: parent, target: parent.left});
        linkList.push(...linkChildren(parent.left));
      }
      if(parent.right !== null) {
        linkList.push({source: parent, target: parent.right});
        linkList.push(...linkChildren(parent.right));
      }
      return linkList;
    }

    let linkList = linkChildren(this.props.root);
    let link = standard.select('#links').selectAll('line.link').data(linkList, d => {
      return d.target.id;
    });
    link
      .enter().append('line')
      .attr('class', 'link')
      .attr('stroke', '#ddd')
      .attr('stroke-width', 5);
    link.exit().remove();

    let nodes = this.props.root.traversal();
    let node = standard.select('#nodes').selectAll('svg.node')
      .data(nodes, d => d.id);

    let nodeG = node.enter()
      .append('svg')
      .attr('class', 'node')
      .attr('width', '40')
      .attr('height', '40');

    nodeG
      .append('circle')
      .attr('class', 'node')
      .attr('stroke', 'white')
      .attr('cx', '50%')
      .attr('cy', '50%')
      .attr('r', 20)
      .text((d) => d.key);

    nodeG.exit().remove();

    nodeG
      .append('text')
      .attr('class', 'node')
      .attr('fill', 'white')
      .attr('x', '50%')
      .attr('y', '50%')
      .attr('text-anchor', 'middle')
      .attr('alignment-baseline', 'middle')
      .text((d) => d.key);

    nodeG.exit().remove();

    this.state.simulation.nodes(nodes)
      .force('link', d3.forceLink(linkList).strength(0.5).distance(100))
      .alpha(1)
      .restart();
  }
}

export default connect(function (state, ownProps) {
  return {root: state.vEBTree.root,};
})(vEBGraph);

export {vEBReducer};
<|endoftext|>


<commit_before>// Full Calendar
$(document).ready(function () {

  //Initialize Datepicker
  $('[data-toggle="datepicker"]').datepicker({
    language: 'pt-BR',
    format: 'dd/mm/yyyy',
    autoHide: true,
    zIndex: 100000,
    startView: 1,
  });

  //Initialize Clockpicker
  $('#timeSchedule').timepicker();
  $('#info-time-edit').timepicker();

  //Setup Fullcalendar
  $('#calendar').fullCalendar({
    locale: 'pt-BR',
    header: {
      left: 'today prev,next title',
      center: '',
      right: ''
    },
    defaultView: 'agendaWeek',
    allDaySlot: false,
    titleFormat: 'MMMM YYYY',
    themeSystem: 'bootstrap4',
    height: 525,
    events: 'https://api-agenda-rafaeel16.c9users.io/api/schedules',
    dayClick: function (date, jsEvent, view) {
      //reset input
      $('#titleSchedule').val('');
      $('#patientSchedule').val(0);
      $('#timeSchedule').val(date.format('LT'));
      $('#modalSchedule #dateSchedule').val(date.format('l'));

      // show modal schedule
      $('#modalSchedule').modal();
    },
    eventRender: function (event, element) {
      $(element)[0].setAttribute('data-id', event.id);
      $(element)[0].setAttribute('data-title', event.title);
      $(element)[0].setAttribute('data-start', event.start);
      $(element)[0].setAttribute('data-patient', event.patient);
      $(element)[0].setAttribute('onclick', 'scheduleInfos(this)');
    }
  });

  //Close modal Schedule
  $('#modalSchedule .bg-overlay, #modalSchedule .btn-close').click(function () {
    $('#modalSchedule').hide();
  });

  //Close modal Schedule Infos
  $('#modalScheduleInfos .bg-overlay, #modalScheduleInfos .btn-close').click(function () {
    $('#modalScheduleInfos').hide();
  });

  //Save Schedule
  $('#saveSchedule').click(function () {
    var title = $('#titleSchedule').val();
    var date = $('#dateSchedule').val();
    var patient = $('#patientSchedule option:selected').text();
    var time = $('#timeSchedule').val();

    var start = formatToPatternFullcalendar(date, time);

    if(title == '' || patient == '' || start == '') {
      mensagemAlerta('Mensagem genérica!!', 'primary');
    } else {
      $.ajax({
        url: 'https://api-agenda-rafaeel16.c9users.io/api/schedules',
        type: "POST",
        data: {
          'title': title,
          'start': start,
          'time': time,
          'patient': patient
        },
        success: function (data) {
          $('#calendar').fullCalendar('renderEvent', {
            id: data.last_insert_id,
            title: title,
            start: start,
            patient: patient,
            time: time
          });
          $('#modalSchedule').modal('hide');
          mensagemAlerta('Agendamento criado com sucesso!', 'primary');
        },
        error: function (e) {
          console.log("Erro: " + e);
        }
      });
    }

  });
});

// Schedule infos
function scheduleInfos(element) {

  var id = $(element).data('id');
  var title = $(element).data('title');
  var patient = $(element).data('patient');
  var start = $(element).data('start');

  $('#info-id').val(id);
  $('#info-title').text(title);
  $('#info-patient').text(patient);
  $('#info-date').text(moment(start).format('l'));
  $('#info-time').text(moment(start).format('LT'));

  // show modal schedule
  $('#modalScheduleInfos').modal();

  // when opening the modal returns to the default
  $('#modalScheduleInfos .wrapper-infos').show();
  $('#modalScheduleInfos .btn-edit-event').show();
  $('#modalScheduleInfos .btn-remove-event').show();

  $('#modalScheduleInfos .wrapper-infos-edit').hide();
  $('#modalScheduleInfos .btn-update-event').hide();
}

function removeEvent() {
  var id = $('#info-id').val();
  $.ajax({
    type: "DELETE",
    url: 'https://api-agenda-rafaeel16.c9users.io/api/schedules/' + id,
    success: function (data) {
      var element = '[data-id="' + $('#info-id').val() + '"]';
      $(element).remove();
      $('#modalScheduleInfos').modal('hide');
      mensagemAlerta('Agendamento deletado com sucesso!', 'danger');
    },
    error: function (e) {
      console.log("Erro: " + e);
    }
  });
}

function changeContentModalUpdate() {
  var id = '[data-id="' + $('#info-id').val() + '"]';

  var title = $('#info-title').text();
  var date = $('#info-date').text();
  var time = $('#info-time').text();

  $('#info-title-edit').val(title);
  $('#info-date-edit').val(date);
  $('#info-time-edit').val(time);

  $('#modalScheduleInfos .wrapper-infos').hide();
  $('#modalScheduleInfos .btn-edit-event').hide();
  $('#modalScheduleInfos .btn-remove-event').hide();

  $('#modalScheduleInfos .wrapper-infos-edit').fadeIn(400);
  $('#modalScheduleInfos .btn-update-event').fadeIn(400);

  $.fn.setCursorPosition = function (pos) {
    this.each(function (index, elem) {
      if (elem.setSelectionRange) {
        elem.setSelectionRange(pos, pos);
      } else if (elem.createTextRange) {
        var range = elem.createTextRange();
        range.collapse(true);
        range.moveEnd('character', pos);
        range.moveStart('character', pos);
        range.select();
      }
    });
    return this;
  };

  $('#info-title-edit').focus().setCursorPosition(0);
}

function updateEvent() {
  var id = $('#info-id').val();
  var title = $('#info-title-edit').val();
  var date = $('#info-date-edit').val();
  var time = $('#info-time-edit').val();

  start = formatToPatternFullcalendar(date, time);

  $.ajax({
    type: "PUT",
    url: 'https://api-agenda-rafaeel16.c9users.io/api/schedules/' + id,
    data: {
      'title': title,
      'start': start
    },
    success: function () {
      //reset calendar after update
      $('#calendar').fullCalendar('refetchEvents');
      $("#modalScheduleInfos").modal('hide');
      mensagemAlerta('Agendamento atualizado com sucesso!', 'primary');
    },
    error: function (e) {
      console.log("Erro: " + e);
    }
  });
}

function formatToPatternFullcalendar(date, time) {
  // Formatting to the fullcalendar pattern
  var formattedDate = moment(moment(date, ['DD-MM-YYYY', 'MM-DD-YYYY'])).format('YYYY-MM-DD');

  // Concatenate to date and time formdateat fullcalendar
  var start = formattedDate + 'T' + time + '-03:00';

  return start;
}

function mensagemAlerta(mensagem, colorClass) {
  $('body').append(`

  ${mensagem}

`);

  var widthScreen = $(document).width();

  if(widthScreen > 567) {
    $('.alert-message').css({
      'position':'fixed',
      'right': '5px',
      'top': '10px',
    }).fadeIn(400);
  } else {
    $('.alert-message').css({
      'position':'fixed',
      'right': '0',
      'left': '0',
      'top': '0',
      'border-radius': '0',
      'opacity': '.95'
    }).fadeIn(400);
  }

  setTimeout(function() {
    $('.alert-message').fadeOut(400,function(){
      $('.alert-message').remove();
    });
  }, 3000);
}<commit_msg>Solução manual para o hoário de verão<commit_after>// Full Calendar
$(document).ready(function () {

  //Initialize Datepicker
  $('[data-toggle="datepicker"]').datepicker({
    language: 'pt-BR',
    format: 'dd/mm/yyyy',
    autoHide: true,
    zIndex: 100000,
    startView: 1,
  });

  //Initialize Clockpicker
  $('#timeSchedule').timepicker();
  $('#info-time-edit').timepicker();

  //Setup Fullcalendar
  $('#calendar').fullCalendar({
    locale: 'pt-BR',
    header: {
      left: 'today prev,next title',
      center: '',
      right: ''
    },
    defaultView: 'agendaWeek',
    allDaySlot: false,
    titleFormat: 'MMMM YYYY',
    themeSystem: 'bootstrap4',
    height: 525,
    events: 'https://api-agenda-rafaeel16.c9users.io/api/schedules',
    dayClick: function (date, jsEvent, view) {
      //reset input
      $('#titleSchedule').val('');
      $('#patientSchedule').val(0);
      $('#timeSchedule').val(date.format('LT'));
      $('#modalSchedule #dateSchedule').val(date.format('l'));

      // show modal schedule
      $('#modalSchedule').modal();
    },
    eventRender: function (event, element) {
      $(element)[0].setAttribute('data-id', event.id);
      $(element)[0].setAttribute('data-title', event.title);
      $(element)[0].setAttribute('data-start', event.start);
      $(element)[0].setAttribute('data-patient', event.patient);
      $(element)[0].setAttribute('onclick', 'scheduleInfos(this)');
    }
  });

  //Close modal Schedule
  $('#modalSchedule .bg-overlay, #modalSchedule .btn-close').click(function () {
    $('#modalSchedule').hide();
  });

  //Close modal Schedule Infos
  $('#modalScheduleInfos .bg-overlay, #modalScheduleInfos .btn-close').click(function () {
    $('#modalScheduleInfos').hide();
  });

  //Save Schedule
  $('#saveSchedule').click(function () {
    var title = $('#titleSchedule').val();
    var date = $('#dateSchedule').val();
    var patient = $('#patientSchedule option:selected').text();
    var time = $('#timeSchedule').val();

    var start = formatToPatternFullcalendar(date, time);

    if(title == '' || patient == '' || start == '') {
      mensagemAlerta('Mensagem genérica!!', 'primary');
    } else {
      $.ajax({
        url: 'https://api-agenda-rafaeel16.c9users.io/api/schedules',
        type: "POST",
        data: {
          'title': title,
          'start': start,
          'time': time,
          'patient': patient
        },
        success: function (data) {
          $('#calendar').fullCalendar('renderEvent', {
            id: data.last_insert_id,
            title: title,
            start: start,
            patient: patient,
            time: time
          });
          $('#modalSchedule').modal('hide');
          mensagemAlerta('Agendamento criado com sucesso!', 'primary');
        },
        error: function (e) {
          console.log("Erro: " + e);
        }
      });
    }

  });
});

// Schedule infos
function scheduleInfos(element) {

  var id = $(element).data('id');
  var title = $(element).data('title');
  var patient = $(element).data('patient');
  var start = $(element).data('start');

  $('#info-id').val(id);
  $('#info-title').text(title);
  $('#info-patient').text(patient);
  $('#info-date').text(moment(start).format('l'));
  $('#info-time').text(moment(start).format('LT'));

  // show modal schedule
  $('#modalScheduleInfos').modal();

  // when opening the modal returns to the default
  $('#modalScheduleInfos .wrapper-infos').show();
  $('#modalScheduleInfos .btn-edit-event').show();
  $('#modalScheduleInfos .btn-remove-event').show();

  $('#modalScheduleInfos .wrapper-infos-edit').hide();
  $('#modalScheduleInfos .btn-update-event').hide();
}

function removeEvent() {
  var id = $('#info-id').val();
  $.ajax({
    type: "DELETE",
    url: 'https://api-agenda-rafaeel16.c9users.io/api/schedules/' + id,
    success: function (data) {
      var element = '[data-id="' + $('#info-id').val() + '"]';
      $(element).remove();
      $('#modalScheduleInfos').modal('hide');
      mensagemAlerta('Agendamento deletado com sucesso!', 'danger');
    },
    error: function (e) {
      console.log("Erro: " + e);
    }
  });
}

function changeContentModalUpdate() {
  var id = '[data-id="' + $('#info-id').val() + '"]';

  var title = $('#info-title').text();
  var date = $('#info-date').text();
  var time = $('#info-time').text();

  $('#info-title-edit').val(title);
  $('#info-date-edit').val(date);
  $('#info-time-edit').val(time);

  $('#modalScheduleInfos .wrapper-infos').hide();
  $('#modalScheduleInfos .btn-edit-event').hide();
  $('#modalScheduleInfos .btn-remove-event').hide();

  $('#modalScheduleInfos .wrapper-infos-edit').fadeIn(400);
  $('#modalScheduleInfos .btn-update-event').fadeIn(400);

  $.fn.setCursorPosition = function (pos) {
    this.each(function (index, elem) {
      if (elem.setSelectionRange) {
        elem.setSelectionRange(pos, pos);
      } else if (elem.createTextRange) {
        var range = elem.createTextRange();
        range.collapse(true);
        range.moveEnd('character', pos);
        range.moveStart('character', pos);
        range.select();
      }
    });
    return this;
  };

  $('#info-title-edit').focus().setCursorPosition(0);
}

function updateEvent() {
  var id = $('#info-id').val();
  var title = $('#info-title-edit').val();
  var date = $('#info-date-edit').val();
  var time = $('#info-time-edit').val();

  start = formatToPatternFullcalendar(date, time);

  $.ajax({
    type: "PUT",
    url: 'https://api-agenda-rafaeel16.c9users.io/api/schedules/' + id,
    data: {
      'title': title,
      'start': start
    },
    success: function () {
      //reset calendar after update
      $('#calendar').fullCalendar('refetchEvents');
      $("#modalScheduleInfos").modal('hide');
      mensagemAlerta('Agendamento atualizado com sucesso!', 'primary');
    },
    error: function (e) {
      console.log("Erro: " + e);
    }
  });
}

function formatToPatternFullcalendar(date, time) {
  // Formatting to the fullcalendar pattern
  var formattedDate = moment(moment(date, ['DD-MM-YYYY', 'MM-DD-YYYY'])).format('YYYY-MM-DD');

  // Concatenate to date and time formdateat fullcalendar
  var start = formattedDate + 'T' + time + '-02:00';

  return start;
}

function mensagemAlerta(mensagem, colorClass) {
  $('body').append(`

  ${mensagem}

`);

  var widthScreen = $(document).width();

  if(widthScreen > 567) {
    $('.alert-message').css({
      'position':'fixed',
      'right': '5px',
      'top': '10px',
    }).fadeIn(400);
  } else {
    $('.alert-message').css({
      'position':'fixed',
      'right': '0',
      'left': '0',
      'top': '0',
      'border-radius': '0',
      'opacity': '.95'
    }).fadeIn(400);
  }

  setTimeout(function() {
    $('.alert-message').fadeOut(400,function(){
      $('.alert-message').remove();
    });
  }, 3000);
}<|endoftext|>


<commit_before>
// TODO - Remove this from here
// Couldn't find your standard state and action management

import Promise from 'bluebird';
import assert from 'assert';
import request from 'superagent';
import SteemConnect from 'sc2-sdk';
import { push } from 'react-router-redux';
import { createAction } from 'redux-actions';
import { jsonParse } from '../../helpers/formatter';
import { createPermlink, getBodyPatchIfSmaller } from '../../helpers/steemitHelpers';

Promise.promisifyAll(request.Request.prototype);

export const CREATE_POST = '@editor/CREATE_POST';
export const CREATE_POST_START = '@editor/CREATE_POST_START';
export const CREATE_POST_SUCCESS = '@editor/CREATE_POST_SUCCESS';
export const CREATE_POST_ERROR = '@editor/CREATE_POST_ERROR';

export const NEW_POST = '@editor/NEW_POST';
export const newPost = createAction(NEW_POST);

export const SAVE_DRAFT = '@editor/SAVE_DRAFT';
export const saveDraft = createAction(SAVE_DRAFT);

export const DELETE_DRAFT = '@editor/DELETE_DRAFT';
export const deleteDraft = createAction(DELETE_DRAFT);

export const editPost = post =>
  (dispatch) => {
    const jsonMetadata = jsonParse(post.json_metadata);
    const draft = {
      ...post,
      originalBody: post.body,
      isUpdating: true,
      jsonMetadata,
      parentAuthor: post.parent_author,
      parentPermlink: post.parent_permlink,
    };
    dispatch(saveDraft({ postData: draft, id: post.id }));
    dispatch(push(`/write?draft=${post.id}`));
  };

const requiredFields = 'parentAuthor,parentPermlink,author,permlink,title,body,jsonMetadata'.split(',');

export function createPost(postData) {
  requiredFields.forEach((field) => {
    assert(postData[field] != null, `Developer Error: Missing required field ${field}`);
  });

  return (dispatch) => {
    const { parentAuthor, parentPermlink, author, title, jsonMetadata, draftId, isUpdating } = postData;
    const getPremLink = isUpdating ?
      Promise.resolve(postData.permlink) :
      createPermlink(title, author, parentAuthor, parentPermlink);

    const body = isUpdating ? getBodyPatchIfSmaller(postData.originalBody, postData.body) : postData.body;

    dispatch({
      type: CREATE_POST,
      payload: {
        promise: getPremLink
          .then(permlink =>
            SteemConnect
              .comment(parentAuthor, parentPermlink, author, permlink, title, body, jsonMetadata)
              .then(({ result }) => {
                if (draftId) { dispatch(deleteDraft(draftId)); }
                dispatch(push(`/${parentPermlink}/@${author}/${permlink}`));
                return result;
              })
          ),
      },
    });
  };
}
<commit_msg>Redirect to draft<commit_after>
// TODO - Remove this from here
// Couldn't find your standard state and action management

import Promise from 'bluebird';
import assert from 'assert';
import request from 'superagent';
import SteemConnect from 'sc2-sdk';
import { push } from 'react-router-redux';
import { createAction } from 'redux-actions';
import { jsonParse } from '../../helpers/formatter';
import { createPermlink, getBodyPatchIfSmaller } from '../../helpers/steemitHelpers';

Promise.promisifyAll(request.Request.prototype);

export const CREATE_POST = '@editor/CREATE_POST';
export const CREATE_POST_START = '@editor/CREATE_POST_START';
export const CREATE_POST_SUCCESS = '@editor/CREATE_POST_SUCCESS';
export const CREATE_POST_ERROR = '@editor/CREATE_POST_ERROR';

export const NEW_POST = '@editor/NEW_POST';
export const newPost = createAction(NEW_POST);

export const SAVE_DRAFT = '@editor/SAVE_DRAFT';

export const DELETE_DRAFT = '@editor/DELETE_DRAFT';
export const deleteDraft = createAction(DELETE_DRAFT);

export const saveDraft = post =>
  (dispatch) => {
    dispatch(push(`/write?draft=${post.id}`));
    dispatch({
      type: SAVE_DRAFT,
      payload: {
        ...post,
      },
    });
  };

export const editPost = post =>
  (dispatch) => {
    const jsonMetadata = jsonParse(post.json_metadata);
    const draft = {
      ...post,
      originalBody: post.body,
      isUpdating: true,
      jsonMetadata,
      parentAuthor: post.parent_author,
      parentPermlink: post.parent_permlink,
    };
    dispatch(saveDraft({ postData: draft, id: post.id }));
    dispatch(push(`/write?draft=${post.id}`));
  };

const requiredFields = 'parentAuthor,parentPermlink,author,permlink,title,body,jsonMetadata'.split(',');

export function createPost(postData) {
  requiredFields.forEach((field) => {
    assert(postData[field] != null, `Developer Error: Missing required field ${field}`);
  });

  return (dispatch) => {
    const { parentAuthor, parentPermlink, author, title, jsonMetadata, draftId, isUpdating } = postData;
    const getPremLink = isUpdating ?
      Promise.resolve(postData.permlink) :
      createPermlink(title, author, parentAuthor, parentPermlink);

    const body = isUpdating ? getBodyPatchIfSmaller(postData.originalBody, postData.body) : postData.body;

    dispatch({
      type: CREATE_POST,
      payload: {
        promise: getPremLink
          .then(permlink =>
            SteemConnect
              .comment(parentAuthor, parentPermlink, author, permlink, title, body, jsonMetadata)
              .then(({ result }) => {
                if (draftId) { dispatch(deleteDraft(draftId)); }
                dispatch(push(`/${parentPermlink}/@${author}/${permlink}`));
                return result;
              })
          ),
      },
    });
  };
}
<|endoftext|>


<commit_before>// https://stackoverflow.com/a/25359264
$.urlParam = function(name){
    var results = new RegExp('[\?&]' + name + '=([^&#]*)').exec(window.location.href);
    if (results==null) {
        return null;
    }
    return decodeURI(results[1]) || 0;
}

// https://stackoverflow.com/a/3291856
String.prototype.capitalize = function() {
    return this.charAt(0).toUpperCase() + this.slice(1);
}

// fetch ticket status from REST API
var endpoint_ticket_list = 'https://www.ebi.ac.uk/panda/jira/rest/api/2/search/?jql=project=ENSCOMPARASW+AND+issuetype=Task+AND+fixVersion+IN+("Ensembl+__RELEASE__",+"Release+__RELEASE__")+AND+component="Relco+tasks"+AND+cf[11130]=__DIVISION__+ORDER+BY+created+ASC,id+ASC&maxResults=500';
var endpoint_ticket_subtasks = 'https://www.ebi.ac.uk/panda/jira/rest/api/2/search/?jql=project=ENSCOMPARASW+AND+parent="__PARENT__"+ORDER+BY+created+ASC,id+ASC&maxResults=500';

var endpoint_ticket_query = 'https://www.ebi.ac.uk/panda/jira/rest/api/2/issue';
var url_jira_issue = 'https://www.ebi.ac.uk/panda/jira/browse/';
var release = $.urlParam("release");
var all_divisions = [ 'empty', 'Vertebrates', 'GRCh37', 'Metazoa', 'Plants', 'Protists', 'Fungi', 'Pan', 'Bacteria' ];

$('body').append('
Release ' + release + ' dashboard
');

function process_division(division) { return function(json) {
    //console.log('json: ', json);
    var n_tickets = json.issues.length;
    console.log(n_tickets);
    if (n_tickets == 0) {
        return;
    }
    if (division.toLowerCase() != "empty") {
        $('#' + division).prepend('
' + division + '
');
    }
    var table = $('

').appendTo('#' + division);
    for(var i =0; i<n_tickets; i++) {
        var ticket = json.issues[i];
        var summary = ticket.fields.summary;
        summary = summary.replace('Release ' + release, '');
        summary = summary.replace(division, '');
        table.append( '
' + summary.trim().capitalize() + '	' + ticket.key + '
' );
        var endpoint = endpoint_ticket_subtasks.replace('__PARENT__', ticket.key);
        console.log(endpoint);
        $.ajax(endpoint, {
            success: process_task(ticket.key),
            error: function(jqXHR, status, error) {
                console.log('Error: ' + (error || jqXHR.crossDomain && 'Cross-Origin Request Blocked' || 'Network issues'));
                window.alert('Having trouble contacting Jira - please check that you are logged in');
            },
            crossDomain: true,
        })
    }

} }

function process_task(task) { return function(json) {
    console.log('json: ', json);
    var n_tickets = json.issues.length;
    //$('#' + task).append('' + json.issues.length + '	');
    var n_done = 0;
    var n_in_progress = 0;
    var n_to_do = 0;
    for(var i =0; i<n_tickets; i++) {
        var ticket = json.issues[i];
        switch (ticket.fields.status.name) {
            case 'Resolved':    n_done ++; break;
            case 'Closed':      n_done ++; break;
            case 'In Progress': n_in_progress ++; break;
            default:            n_to_do ++; break;
        }
    }
    var prog = '';
    if (n_done) {
        prog += '

';
    }
    if (n_in_progress) {
        prog += '

';
    }
    if (n_to_do) {
        prog += '

';
    }
    $('#' + task).append('
' + prog + '
	');
    $('#' + task).append('' + n_done + ' done,	');
    $('#' + task).append('' + n_in_progress + ' in progress,	');
    $('#' + task).append('' + n_to_do + ' to do	');
} }

for(var j = 0; j < all_divisions.length; j++){
    var division = all_divisions[j];
    var endpoint = endpoint_ticket_list.replace(/__RELEASE__/g, release).replace('__DIVISION__', division);
    console.log(endpoint);
    $('body').append('

');
    $.ajax(endpoint, {
        success: process_division(division),
        error: function(jqXHR, status, error) {
            console.log('Error: ' + (error || jqXHR.crossDomain && 'Cross-Origin Request Blocked' || 'Network issues'));
            window.alert('Having trouble contacting Jira - please check that you are logged in');
        },
        crossDomain: true,
    })
}
<commit_msg>Works for tasks that don't have sub-tasks too<commit_after>// https://stackoverflow.com/a/25359264
$.urlParam = function(name){
    var results = new RegExp('[\?&]' + name + '=([^&#]*)').exec(window.location.href);
    if (results==null) {
        return null;
    }
    return decodeURI(results[1]) || 0;
}

// https://stackoverflow.com/a/3291856
String.prototype.capitalize = function() {
    return this.charAt(0).toUpperCase() + this.slice(1);
}

// fetch ticket status from REST API
var endpoint_ticket_list = 'https://www.ebi.ac.uk/panda/jira/rest/api/2/search/?jql=project=ENSCOMPARASW+AND+issuetype=Task+AND+fixVersion+IN+("Ensembl+__RELEASE__",+"Release+__RELEASE__")+AND+component="Relco+tasks"+AND+cf[11130]=__DIVISION__+ORDER+BY+created+ASC,id+ASC&maxResults=500';
var endpoint_ticket_subtasks = 'https://www.ebi.ac.uk/panda/jira/rest/api/2/search/?jql=project=ENSCOMPARASW+AND+parent="__PARENT__"+ORDER+BY+created+ASC,id+ASC&maxResults=500';

var endpoint_ticket_query = 'https://www.ebi.ac.uk/panda/jira/rest/api/2/issue';
var url_jira_issue = 'https://www.ebi.ac.uk/panda/jira/browse/';
var release = $.urlParam("release");
var all_divisions = [ 'empty', 'Vertebrates', 'GRCh37', 'Metazoa', 'Plants', 'Protists', 'Fungi', 'Pan', 'Bacteria' ];

$('body').append('
Release ' + release + ' dashboard
');

function process_division(division) { return function(json) {
    //console.log('json: ', json);
    var n_tickets = json.issues.length;
    console.log(n_tickets);
    if (n_tickets == 0) {
        return;
    }
    if (division.toLowerCase() != "empty") {
        $('#' + division).prepend('
' + division + '
');
    }
    var table = $('

').appendTo('#' + division);
    for(var i =0; i<n_tickets; i++) {
        var ticket = json.issues[i];
        var summary = ticket.fields.summary;
        summary = summary.replace('Release ' + release, '');
        summary = summary.replace(division, '');
        table.append( '
' + summary.trim().capitalize() + '	' + ticket.key + '
' );
        var endpoint = endpoint_ticket_subtasks.replace('__PARENT__', ticket.key);
        console.log(endpoint);
        $.ajax(endpoint, {
            success: process_task(ticket),
            error: function(jqXHR, status, error) {
                console.log('Error: ' + (error || jqXHR.crossDomain && 'Cross-Origin Request Blocked' || 'Network issues'));
                window.alert('Having trouble contacting Jira - please check that you are logged in');
            },
            crossDomain: true,
        })
    }

} }

function process_task(task) { return function(json) {
    console.log('json: ', json);
    var n_tickets = json.issues.length;
    //$('#' + task).append('' + json.issues.length + '	');
    var n_done = 0;
    var n_in_progress = 0;
    var n_to_do = 0;
    for(var i =0; i<n_tickets; i++) {
        var ticket = json.issues[i];
        switch (ticket.fields.status.name) {
            case 'Resolved':    n_done ++; break;
            case 'Closed':      n_done ++; break;
            case 'In Progress': n_in_progress ++; break;
            default:            n_to_do ++; break;
        }
    }
    var task_key = task.key;
    if (n_tickets) {
        var prog = '';
        if (n_done) {
            prog += '

';
        }
        if (n_in_progress) {
            prog += '

';
        }
        if (n_to_do) {
            prog += '

';
        }
        $('#' + task_key).append('
' + prog + '
	');
        $('#' + task_key).append('' + n_done + ' done,	');
        $('#' + task_key).append('' + n_in_progress + ' in progress,	');
        $('#' + task_key).append('' + n_to_do + ' to do	');
    } else {
        var task_status;
        var colour;
        switch (task.fields.status.name) {
            case 'Resolved':    task_status = 'Done';        colour = 'green';  break;
            case 'Closed':      task_status = 'Done';        colour = 'green';  break;
            case 'In Progress': task_status = 'In progress'; colour = 'yellow'; break;
            default:            task_status = 'To do';       colour = 'blue';   break;
        }
        var prog = '

';
        $('#' + task_key).append('
' + prog + '
	');
        $('#' + task_key).append('' + task_status + '	');
    }
} }

for(var j = 0; j < all_divisions.length; j++){
    var division = all_divisions[j];
    var endpoint = endpoint_ticket_list.replace(/__RELEASE__/g, release).replace('__DIVISION__', division);
    console.log(endpoint);
    $('body').append('

');
    $.ajax(endpoint, {
        success: process_division(division),
        error: function(jqXHR, status, error) {
            console.log('Error: ' + (error || jqXHR.crossDomain && 'Cross-Origin Request Blocked' || 'Network issues'));
            window.alert('Having trouble contacting Jira - please check that you are logged in');
        },
        crossDomain: true,
    })
}
<|endoftext|>