<commit_before>const asyncFn = (response) => () => jest.fn(() => Promise.resolve(response));
const syncFn = (response) => () => jest.fn(() => response);
const makeFns = (response) => [asyncFn(response), syncFn(response)];

const [stringFnAsync, stringFnSync] = makeFns('unknown');
const [numberFnAsync, numberFnSync] = makeFns(-1);
const [arrayFnAsync, arrayFnSync] = makeFns([]);
const [booleanFnAsync, booleanFnSync] = makeFns(false);
const [objectFnAsync, objectFnSync] = makeFns({});

const numberAsyncHookResultHook = () => jest.fn(() => ({ loading: false, result: -1 }));
const booleanAsyncHookResultHook = () => jest.fn(() => ({ loading: false, result: false }));
const stringAsyncHookResultHook = () => jest.fn(() => ({ loading: false, result: 'unknown' }));

const diMock = {
  getAndroidId: stringFnAsync(),
  getAndroidIdSync: stringFnSync(),
  getApiLevel: numberFnAsync(),
  getApiLevelSync: numberFnSync(),
  getAvailableLocationProviders: objectFnAsync(),
  getAvailableLocationProvidersSync: objectFnSync(),
  getBaseOs: stringFnAsync(),
  getBaseOsSync: stringFnSync(),
  getBatteryLevel: numberFnAsync(),
  getBatteryLevelSync: numberFnSync(),
  getBootloader: stringFnAsync(),
  getBootloaderSync: stringFnSync(),
  getBuildId: stringFnAsync(),
  getBuildIdSync: stringFnSync(),
  getCarrier: stringFnAsync(),
  getCarrierSync: stringFnSync(),
  getCodename: stringFnAsync(),
  getCodenameSync: stringFnSync(),
  getDevice: stringFnAsync(),
  getDeviceSync: stringFnSync(),
  getDeviceName: stringFnAsync(),
  getDeviceNameSync: stringFnSync(),
  getDeviceToken: stringFnAsync(),
  getDisplay: stringFnAsync(),
  getDisplaySync: stringFnSync(),
  getFingerprint: stringFnAsync(),
  getFingerprintSync: stringFnSync(),
  getFirstInstallTime: numberFnAsync(),
  getFirstInstallTimeSync: numberFnSync(),
  getFontScale: numberFnAsync(),
  getFontScaleSync: numberFnSync(),
  getFreeDiskStorage: numberFnAsync(),
  getFreeDiskStorageOld: numberFnAsync(),
  getFreeDiskStorageSync: numberFnSync(),
  getFreeDiskStorageOldSync: numberFnSync(),
  getHardware: stringFnAsync(),
  getHardwareSync: stringFnSync(),
  getHost: stringFnAsync(),
  getHostSync: stringFnSync(),
  getIncremental: stringFnAsync(),
  getIncrementalSync: stringFnSync(),
  getInstallerPackageName: stringFnAsync(),
  getInstallerPackageNameSync: stringFnSync(),
  getInstallReferrer: stringFnAsync(),
  getInstallReferrerSync: stringFnSync(),
  getInstanceId: stringFnAsync(),
  getInstanceIdSync: stringFnSync(),
  getIpAddress: stringFnAsync(),
  getIpAddressSync: stringFnSync(),
  getLastUpdateTime: numberFnAsync(),
  getLastUpdateTimeSync: numberFnSync(),
  getMacAddress: stringFnAsync(),
  getMacAddressSync: stringFnSync(),
  getMaxMemory: numberFnAsync(),
  getMaxMemorySync: numberFnSync(),
  getPhoneNumber: stringFnAsync(),
  getPhoneNumberSync: stringFnSync(),
  getPreviewSdkInt: numberFnAsync(),
  getPreviewSdkIntSync: numberFnSync(),
  getProduct: stringFnAsync(),
  getProductSync: stringFnSync(),
  getSecurityPatch: stringFnAsync(),
  getSecurityPatchSync: stringFnSync(),
  getSerialNumber: stringFnAsync(),
  getSerialNumberSync: stringFnSync(),
  getSystemAvailableFeatures: arrayFnAsync(),
  getSystemAvailableFeaturesSync: arrayFnSync(),
  getTags: stringFnAsync(),
  getTagsSync: stringFnSync(),
  getTotalDiskCapacity: numberFnAsync(),
  getTotalDiskCapacityOld: numberFnAsync(),
  getTotalDiskCapacitySync: numberFnSync(),
  getTotalDiskCapacityOldSync: numberFnSync(),
  getTotalMemory: numberFnAsync(),
  getTotalMemorySync: numberFnSync(),
  getType: stringFnAsync(),
  getTypeSync: stringFnSync(),
  getUsedMemory: numberFnAsync(),
  getUsedMemorySync: numberFnSync(),
  getUserAgent: stringFnAsync(),
  getUserAgentSync: stringFnSync(),
  hasSystemFeature: booleanFnAsync(),
  hasSystemFeatureSync: booleanFnSync(),
  hasGms: booleanFnAsync(),
  hasGmsSync: booleanFnSync(),
  hasHms: booleanFnAsync(),
  hasHmsSync: booleanFnSync(),
  isAirplaneMode: booleanFnAsync(),
  isAirplaneModeSync: booleanFnSync(),
  isBatteryCharging: booleanFnAsync(),,
  isBatteryChargingSync: booleanFnSync(),
  isCameraPresent: booleanFnSync(),
  isCameraPresentSync: booleanFnSync(),
  isEmulator: booleanFnAsync(),
  isEmulatorSync: booleanFnSync(),
  isHeadphonesConnected: booleanFnAsync(),
  isHeadphonesConnectedSync: booleanFnSync(),
  isLocationEnabled: booleanFnAsync(),
  isLocationEnabledSync: booleanFnSync(),
  isPinOrFingerprintSet: booleanFnAsync(),
  isPinOrFingerprintSetSync: booleanFnSync(),
  syncUniqueId: stringFnAsync(),
  getApplicationName: stringFnSync(),
  getBrand: stringFnSync(),
  getBuildNumber: stringFnSync(),
  getBundleId: stringFnSync(),
  getDeviceId: stringFnSync(),
  getDeviceType: stringFnSync(),
  getManufacturer: stringFnAsync(),
  getManufacturerSync: stringFnSync(),
  getModel: stringFnSync(),
  getPowerState: objectFnAsync(),
  getPowerStateSync: objectFnSync(),
  getReadableVersion: stringFnSync(),
  getSystemName: stringFnSync(),
  getSystemVersion: stringFnSync(),
  getUniqueId: stringFnSync(),
  getVersion: stringFnSync(),
  hasNotch: booleanFnSync(),
  isLandscape: booleanFnAsync(),
  isLandscapeSync: booleanFnSync(),
  isTablet: booleanFnSync(),
  supported32BitAbis: arrayFnAsync(),
  supported32BitAbisSync: arrayFnSync(),
  supported64BitAbis: arrayFnAsync(),
  supported64BitAbisSync: arrayFnSync(),
  supportedAbis: arrayFnAsync(),
  supportedAbisSync: arrayFnSync(),
  useBatteryLevel: numberFnSync(),
  useBatteryLevelIsLow: numberFnSync(),
  usePowerState: objectFnSync(),
  useIsHeadphonesConnected: booleanAsyncHookResultHook(),
  useFirstInstallTime: numberAsyncHookResultHook(),
  useDeviceName: stringAsyncHookResultHook(),
  useHasSystemFeature: booleanAsyncHookResultHook(),
  useIsEmulator: booleanAsyncHookResultHook(),
  useManufacturer: stringAsyncHookResultHook(),
};

module.exports = diMock;
<commit_msg>fix(test, mocks): extra comma syntax error in mock definition (#1134)<commit_after>const asyncFn = (response) => () => jest.fn(() => Promise.resolve(response));
const syncFn = (response) => () => jest.fn(() => response);
const makeFns = (response) => [asyncFn(response), syncFn(response)];

const [stringFnAsync, stringFnSync] = makeFns('unknown');
const [numberFnAsync, numberFnSync] = makeFns(-1);
const [arrayFnAsync, arrayFnSync] = makeFns([]);
const [booleanFnAsync, booleanFnSync] = makeFns(false);
const [objectFnAsync, objectFnSync] = makeFns({});

const numberAsyncHookResultHook = () => jest.fn(() => ({ loading: false, result: -1 }));
const booleanAsyncHookResultHook = () => jest.fn(() => ({ loading: false, result: false }));
const stringAsyncHookResultHook = () => jest.fn(() => ({ loading: false, result: 'unknown' }));

const diMock = {
  getAndroidId: stringFnAsync(),
  getAndroidIdSync: stringFnSync(),
  getApiLevel: numberFnAsync(),
  getApiLevelSync: numberFnSync(),
  getAvailableLocationProviders: objectFnAsync(),
  getAvailableLocationProvidersSync: objectFnSync(),
  getBaseOs: stringFnAsync(),
  getBaseOsSync: stringFnSync(),
  getBatteryLevel: numberFnAsync(),
  getBatteryLevelSync: numberFnSync(),
  getBootloader: stringFnAsync(),
  getBootloaderSync: stringFnSync(),
  getBuildId: stringFnAsync(),
  getBuildIdSync: stringFnSync(),
  getCarrier: stringFnAsync(),
  getCarrierSync: stringFnSync(),
  getCodename: stringFnAsync(),
  getCodenameSync: stringFnSync(),
  getDevice: stringFnAsync(),
  getDeviceSync: stringFnSync(),
  getDeviceName: stringFnAsync(),
  getDeviceNameSync: stringFnSync(),
  getDeviceToken: stringFnAsync(),
  getDisplay: stringFnAsync(),
  getDisplaySync: stringFnSync(),
  getFingerprint: stringFnAsync(),
  getFingerprintSync: stringFnSync(),
  getFirstInstallTime: numberFnAsync(),
  getFirstInstallTimeSync: numberFnSync(),
  getFontScale: numberFnAsync(),
  getFontScaleSync: numberFnSync(),
  getFreeDiskStorage: numberFnAsync(),
  getFreeDiskStorageOld: numberFnAsync(),
  getFreeDiskStorageSync: numberFnSync(),
  getFreeDiskStorageOldSync: numberFnSync(),
  getHardware: stringFnAsync(),
  getHardwareSync: stringFnSync(),
  getHost: stringFnAsync(),
  getHostSync: stringFnSync(),
  getIncremental: stringFnAsync(),
  getIncrementalSync: stringFnSync(),
  getInstallerPackageName: stringFnAsync(),
  getInstallerPackageNameSync: stringFnSync(),
  getInstallReferrer: stringFnAsync(),
  getInstallReferrerSync: stringFnSync(),
  getInstanceId: stringFnAsync(),
  getInstanceIdSync: stringFnSync(),
  getIpAddress: stringFnAsync(),
  getIpAddressSync: stringFnSync(),
  getLastUpdateTime: numberFnAsync(),
  getLastUpdateTimeSync: numberFnSync(),
  getMacAddress: stringFnAsync(),
  getMacAddressSync: stringFnSync(),
  getMaxMemory: numberFnAsync(),
  getMaxMemorySync: numberFnSync(),
  getPhoneNumber: stringFnAsync(),
  getPhoneNumberSync: stringFnSync(),
  getPreviewSdkInt: numberFnAsync(),
  getPreviewSdkIntSync: numberFnSync(),
  getProduct: stringFnAsync(),
  getProductSync: stringFnSync(),
  getSecurityPatch: stringFnAsync(),
  getSecurityPatchSync: stringFnSync(),
  getSerialNumber: stringFnAsync(),
  getSerialNumberSync: stringFnSync(),
  getSystemAvailableFeatures: arrayFnAsync(),
  getSystemAvailableFeaturesSync: arrayFnSync(),
  getTags: stringFnAsync(),
  getTagsSync: stringFnSync(),
  getTotalDiskCapacity: numberFnAsync(),
  getTotalDiskCapacityOld: numberFnAsync(),
  getTotalDiskCapacitySync: numberFnSync(),
  getTotalDiskCapacityOldSync: numberFnSync(),
  getTotalMemory: numberFnAsync(),
  getTotalMemorySync: numberFnSync(),
  getType: stringFnAsync(),
  getTypeSync: stringFnSync(),
  getUsedMemory: numberFnAsync(),
  getUsedMemorySync: numberFnSync(),
  getUserAgent: stringFnAsync(),
  getUserAgentSync: stringFnSync(),
  hasSystemFeature: booleanFnAsync(),
  hasSystemFeatureSync: booleanFnSync(),
  hasGms: booleanFnAsync(),
  hasGmsSync: booleanFnSync(),
  hasHms: booleanFnAsync(),
  hasHmsSync: booleanFnSync(),
  isAirplaneMode: booleanFnAsync(),
  isAirplaneModeSync: booleanFnSync(),
  isBatteryCharging: booleanFnAsync(),
  isBatteryChargingSync: booleanFnSync(),
  isCameraPresent: booleanFnSync(),
  isCameraPresentSync: booleanFnSync(),
  isEmulator: booleanFnAsync(),
  isEmulatorSync: booleanFnSync(),
  isHeadphonesConnected: booleanFnAsync(),
  isHeadphonesConnectedSync: booleanFnSync(),
  isLocationEnabled: booleanFnAsync(),
  isLocationEnabledSync: booleanFnSync(),
  isPinOrFingerprintSet: booleanFnAsync(),
  isPinOrFingerprintSetSync: booleanFnSync(),
  syncUniqueId: stringFnAsync(),
  getApplicationName: stringFnSync(),
  getBrand: stringFnSync(),
  getBuildNumber: stringFnSync(),
  getBundleId: stringFnSync(),
  getDeviceId: stringFnSync(),
  getDeviceType: stringFnSync(),
  getManufacturer: stringFnAsync(),
  getManufacturerSync: stringFnSync(),
  getModel: stringFnSync(),
  getPowerState: objectFnAsync(),
  getPowerStateSync: objectFnSync(),
  getReadableVersion: stringFnSync(),
  getSystemName: stringFnSync(),
  getSystemVersion: stringFnSync(),
  getUniqueId: stringFnSync(),
  getVersion: stringFnSync(),
  hasNotch: booleanFnSync(),
  isLandscape: booleanFnAsync(),
  isLandscapeSync: booleanFnSync(),
  isTablet: booleanFnSync(),
  supported32BitAbis: arrayFnAsync(),
  supported32BitAbisSync: arrayFnSync(),
  supported64BitAbis: arrayFnAsync(),
  supported64BitAbisSync: arrayFnSync(),
  supportedAbis: arrayFnAsync(),
  supportedAbisSync: arrayFnSync(),
  useBatteryLevel: numberFnSync(),
  useBatteryLevelIsLow: numberFnSync(),
  usePowerState: objectFnSync(),
  useIsHeadphonesConnected: booleanAsyncHookResultHook(),
  useFirstInstallTime: numberAsyncHookResultHook(),
  useDeviceName: stringAsyncHookResultHook(),
  useHasSystemFeature: booleanAsyncHookResultHook(),
  useIsEmulator: booleanAsyncHookResultHook(),
  useManufacturer: stringAsyncHookResultHook(),
};

module.exports = diMock;
<|endoftext|>


<commit_before>const PROMISES = new Set();

export default class Loader {
  static get onLoad() {
    return Promise.all(PROMISES);
  }

  static get promises() {
    return PROMISES;
  }

  static load(values) {
    if(!(values instanceof Array)) {
      values = [values];
    }

    let promises = [];

    for (let value of values) {
      promises.push(new Promise(function(resolve, reject) {
        let onLoad = () => {
          PROMISES.delete(promise);
          value.removeEventListener("load", onLoad);
          value.removeEventListener("canplaythrough", onLoad);
          resolve(value);
        };

        if(typeof value === "string") {
          let tagName;
          if(/\.(png|jpg|gif)$/.test(value)) {
            tagName = "img";
          } else if(/\.(mp4|webm)$/.test(value)) {
            tagName = "video";
          } else if(/\.(mp3|ogg)$/.test(value)) {
            tagName = "audio";
          }
          if(tag) {
            let element = document.createElement(tagName);
            element.src = value;
            value = element;
          }
        }

        if(value instanceof HTMLMediaElement) {
          if(value instanceof HTMLMediaElement) {
            value.addEventListener("canplaythrough", onLoad);
          } else {
            value.addEventListener("load", onLoad);
          };
        } else {
          // TODO: fetch
        }
      }));
    }

    PROMISES.add(promises);

    return Promise.all(promises);
  }
}
<commit_msg>add fetch to loader<commit_after>const PROMISES = new Set();

export default class Loader {
  static get onLoad() {
    return Promise.all(PROMISES);
  }

  static get promises() {
    return PROMISES;
  }

  static load(values) {
    if(!(values instanceof Array)) {
      values = [values];
    }

    let promises = [];

    for (let value of values) {
      promises.push(new Promise(function(resolve, reject) {
        let onLoad = (response) => {
          PROMISES.delete(promises);
          if(value instanceof HTMLMediaElement) {
            value.removeEventListener("load", onLoad);
            value.removeEventListener("canplaythrough", onLoad);
            resolve(value);
          } else {
            resolve(response);
          }
        };

        if(typeof value === "string") {
          let tagName;
          if(/\.(png|jpg|gif)$/.test(value)) {
            tagName = "img";
          } else if(/\.(mp4|webm)$/.test(value)) {
            tagName = "video";
          } else if(/\.(mp3|ogg)$/.test(value)) {
            tagName = "audio";
          }
          if(tagName) {
            let element = document.createElement(tagName);
            element.src = value;
            value = element;
          }
        }

        if(value instanceof HTMLMediaElement) {
          if(value instanceof HTMLMediaElement) {
            value.addEventListener("canplaythrough", onLoad);
          } else {
            value.addEventListener("load", onLoad);
          };
        } else {
          fetch(value).then((response) => {
            return response.text();
          }).then(onLoad);
        }
      }));
    }

    PROMISES.add(promises);

    return promises.length > 1 ? Promise.all(promises) : promises[0];
  }
}
<|endoftext|>


<commit_before>var modWidget = require('../modWidget.js');
var util = require('../../utils/MyUtil');
module.exports = {

	process : function(ctx, step, next) {
		var paramField = {};
		var showItemWebform = ctx.showItemWebform;
		var wv = ctx.wv;
		var item = ctx.item;
		var params = ctx.params;
		var endpoint = item.endpoint;
		var submitBtnCallback = function() {
			for(var i = 0; i < params.length; i++) {
				var param = params[i];
				if(typeof param == 'object') {
					// search available widget
					var value = modWidget.parseValue(param, {wv:wv})
					if(value != null)
						paramField[param.name] = {value:value};
				}
				else {
					var value = wv.ios.stringByEvaluatingJavaScriptFromString('document.getElementById("' + param + '").value');
					paramField[param] = {value:value};
				}
			}
		}
		var url = endpoint;
		var formParams = {};
		for(var key in paramField) {
			formParams[key] = paramField[key].value;
		}

		var method = 'POST';
		if(item.method) method = item.method;
		util.frequest({
			url : url,
			method : method,
			params : formParams,

			callbackJSON : function(json) {

				if(json.message) {
					alert(json.message);
				}
				if(json.refresh) {
					if(opts.refresh) opts.refresh();
				}
				if(json.webform) {
					showItemWebform(json.webform, {
						refresh:function() {
							if(opts.refresh) opts.refresh();
						}
					});
				}
				if(json.redirectUrl) {
					ctx.showCategory(json.redirectUrl);
				}
				if(json.closewin) {
					//helper.back();
				}

				//#47 submit callback level

				if(typeof json.flows != 'undefined') {
					for(var i in json.flows) {
						ctx.flows[i] = json.flows[i];
					}
				}

				var flow = json.flow;
				ctx.createFlowEngine(flow).execute(function() {});
			}
		});
		setTimeout(next, 1);
	}
}
<commit_msg>fix path to MyUtil from submitForm<commit_after>var modWidget = require('../modWidget.js');
var util = require('../../../utils/MyUtil');
module.exports = {

	process : function(ctx, step, next) {
		var paramField = {};
		var showItemWebform = ctx.showItemWebform;
		var wv = ctx.wv;
		var item = ctx.item;
		var params = ctx.params;
		var endpoint = item.endpoint;
		var submitBtnCallback = function() {
			for(var i = 0; i < params.length; i++) {
				var param = params[i];
				if(typeof param == 'object') {
					// search available widget
					var value = modWidget.parseValue(param, {wv:wv})
					if(value != null)
						paramField[param.name] = {value:value};
				}
				else {
					var value = wv.ios.stringByEvaluatingJavaScriptFromString('document.getElementById("' + param + '").value');
					paramField[param] = {value:value};
				}
			}
		}
		var url = endpoint;
		var formParams = {};
		for(var key in paramField) {
			formParams[key] = paramField[key].value;
		}

		var method = 'POST';
		if(item.method) method = item.method;
		util.frequest({
			url : url,
			method : method,
			params : formParams,

			callbackJSON : function(json) {

				if(json.message) {
					alert(json.message);
				}
				if(json.refresh) {
					if(opts.refresh) opts.refresh();
				}
				if(json.webform) {
					showItemWebform(json.webform, {
						refresh:function() {
							if(opts.refresh) opts.refresh();
						}
					});
				}
				if(json.redirectUrl) {
					ctx.showCategory(json.redirectUrl);
				}
				if(json.closewin) {
					//helper.back();
				}

				//#47 submit callback level

				if(typeof json.flows != 'undefined') {
					for(var i in json.flows) {
						ctx.flows[i] = json.flows[i];
					}
				}

				var flow = json.flow;
				ctx.createFlowEngine(flow).execute(function() {});
			}
		});
		setTimeout(next, 1);
	}
}
<|endoftext|>


<commit_before>define([], function() {

    'use strict';

	return [
        '$scope',
        '$location',
        '$routeParams',
        'Rest',
        '$modal',
        'catchOutcome',
        'gettext',
        'Beneficiary',
        function($scope, $location, $routeParams, Rest, $modal, catchOutcome, gettext, Beneficiary) {

        var userResource = Rest.admin.users.getResource();
        var accountbeneficiaryResource = Rest.admin.accountbeneficiaries.getResource();
        var adjustmentResource = Rest.admin.adjustments.getResource();
        var requestResource = Rest.admin.requests.getResource();

        if (!$location.search().user) {
            throw new Error('The user parameter is mandatory');
        }

        var requests = requestResource.query({
            'user.id': $location.search().user,
            absence: true,
            time_saving_deposit: true
        });

        $scope.user = userResource.get({id: $location.search().user});

        $scope.user.$promise.then(function() {
            var beneficiaryContainer = accountbeneficiaryResource.get({
                id: $routeParams.id,
                account: $scope.user.roles.account._id
            });

            Beneficiary.processBeneficiary($scope, beneficiaryContainer, requests, function(renewalId, callback) {
                return adjustmentResource.query({ rightRenewal: renewalId, user: $scope.user._id }, callback);
            });
        });

        $scope.xAxisTickFormat_Date_Format = Beneficiary.xAxisTickFormat_Date_Format;

		$scope.back = function back() {
			$location.path('/admin/users/'+$scope.user._id);
		};

        $scope.addAdjustment = function addAdjustment(renewal) {
            var modalscope = $scope.$new();

            modalscope.renewal = renewal;

            modalscope.adjustment = new adjustmentResource();

            modalscope.adjustment.rightRenewal = renewal._id;
            modalscope.adjustment.user = $scope.user._id;
            modalscope.adjustment.quantity = 0;
            modalscope.adjustment.comment = '';

            modalscope.adjustment.available_quantity = renewal.available_quantity;

            modalscope.setAdjustmentQuantity = function setAdjustmentQuantity() {
                modalscope.adjustment.available_quantity = renewal.available_quantity + modalscope.adjustment.quantity;
            };

            modalscope.setAvailableQuantity = function setAvailableQuantity() {
                modalscope.adjustment.quantity = modalscope.adjustment.available_quantity - renewal.available_quantity;
            };

            var modal = $modal({
                scope: modalscope,
                templateUrl: 'partials/admin/adjustment-edit.html',
                show: true
            });

            modalscope.cancel = function() {
                modal.hide();
            };

            modalscope.save = function() {
                catchOutcome(modalscope.adjustment.$create()).then(modal.hide);
            };
        };

	}];
});
<commit_msg>Fix save new adjustment<commit_after>define([], function() {

    'use strict';

	return [
        '$scope',
        '$location',
        '$routeParams',
        'Rest',
        '$modal',
        'catchOutcome',
        'gettext',
        'Beneficiary',
        function($scope, $location, $routeParams, Rest, $modal, catchOutcome, gettext, Beneficiary) {

        var userResource = Rest.admin.users.getResource();
        var accountbeneficiaryResource = Rest.admin.accountbeneficiaries.getResource();
        var adjustmentResource = Rest.admin.adjustments.getResource();
        var requestResource = Rest.admin.requests.getResource();

        if (!$location.search().user) {
            throw new Error('The user parameter is mandatory');
        }

        var requests = requestResource.query({
            'user.id': $location.search().user,
            absence: true,
            time_saving_deposit: true
        });

        $scope.user = userResource.get({id: $location.search().user});

        $scope.user.$promise.then(function() {
            var beneficiaryContainer = accountbeneficiaryResource.get({
                id: $routeParams.id,
                account: $scope.user.roles.account._id
            });

            Beneficiary.processBeneficiary($scope, beneficiaryContainer, requests, function(renewalId, callback) {
                return adjustmentResource.query({ rightRenewal: renewalId, user: $scope.user._id }, callback);
            });
        });

        $scope.xAxisTickFormat_Date_Format = Beneficiary.xAxisTickFormat_Date_Format;

		$scope.back = function back() {
			$location.path('/admin/users/'+$scope.user._id);
		};

        $scope.addAdjustment = function addAdjustment(renewal) {
            var modalscope = $scope.$new();

            modalscope.renewal = renewal;

            modalscope.adjustment = new adjustmentResource();

            modalscope.adjustment.beneficiary = $routeParams.id;
            modalscope.adjustment.rightRenewal = renewal._id;
            modalscope.adjustment.user = $scope.user._id;
            modalscope.adjustment.quantity = 0;
            modalscope.adjustment.comment = '';

            modalscope.adjustment.available_quantity = renewal.available_quantity;

            modalscope.setAdjustmentQuantity = function setAdjustmentQuantity() {
                modalscope.adjustment.available_quantity = renewal.available_quantity + modalscope.adjustment.quantity;
            };

            modalscope.setAvailableQuantity = function setAvailableQuantity() {
                modalscope.adjustment.quantity = modalscope.adjustment.available_quantity - renewal.available_quantity;
            };

            var modal = $modal({
                scope: modalscope,
                templateUrl: 'partials/admin/adjustment-edit.html',
                show: true
            });

            modalscope.cancel = function() {
                modal.hide();
            };

            modalscope.save = function() {
                catchOutcome(modalscope.adjustment.$create()).then(modal.hide);
            };
        };

	}];
});
<|endoftext|>


<commit_before>var _ = require('underscore');
var createDashboard = require('./create-dashboard');
var cdb = require('cartodb.js');

function Dashboard (dashboard) {
  this.dashboard = dashboard;

  // bind widget related methods
  var ws = dashboard.widgets;
  this.createCategory = ws.createCategoryModel.bind(ws);
  this.createHistogram = ws.createHistogramModel.bind(ws);
  this.createFormula = ws.createFormulaModel.bind(ws);
  this.createTimeSeries = ws.createTimeSeriesModel.bind(ws);
  this.getWidget = ws.get.bind(ws);
  this.getWidgets = ws.getList.bind(ws);
}

Dashboard.prototype = {
  getMap: function () {
    return this.dashboard.vis;
  }
};

module.exports = function (selector, vizJSON, opts, callback) {
  var args = arguments;
  var fn = args[args.length - 1];

  if (_.isFunction(fn)) {
    callback = fn;
  }

  function _load (vizJSON) {
    var dashboard = createDashboard(selector, vizJSON, opts);
    dashboard.vis.done(function () {
      callback(null, new Dashboard(dashboard));
    });
  }

  if (typeof vizJSON === 'string') {
    cdb.core.Loader.get(vizJSON, function (data) {
      if (data) {
        _load(data, opts);
      } else {
        callback(new Error('error fetching viz.json file'));
      }
    });
  }
};

<commit_msg>changed api methods<commit_after>var _ = require('underscore');
var createDashboard = require('./create-dashboard');
var cdb = require('cartodb.js');

function Dashboard (dashboard) {
  this.dashboard = dashboard;
}

Dashboard.prototype = {

  /**
   * @return {Map} the map used in the dashboard
   */
  getMap: function () {
    return this.dashboard.vis;
  },

  /**
   * @return {Array} of widgets in the dashboard
   */
  getWidgets: function () {
    return this._dashboard.widgets.getList.call(this);
  },

  /**
   * @param {Integer} id - widget id
   * @return a widget object
   */
  getWidget: function (id) {
    return this._dashboard.widgets.getWidget.call(this, id);
  },

  /**
   * Create a category widget.
   * @param {Object} widgetAttrs - attributes for the new widget
   * @param {string} widgetAttrs.id - id (required)
   * @param {string} widgetAttrs.title - title (required)
   * @param {number} widgetAttrs.order - index of the widget (optional)
   * @param ...
   * @return {CategoryWidget} The new widget
   */
  createCategoryWidget: function (widgetAttrs) {
    this._dashboard.widgets.createCategoryModel.call(this, widgetAttrs);
  },

  /**
   * Create a histogram widget
   * @param {Object} widgetAttrs - attributes for the new widget
   * @param {string} widgetAttrs.id - id (required)
   * @param {string} widgetAttrs.title - title (required)
   * @param {number} widgetAttrs.order - index of the widget (optional)
   * @param ...
   * @return {HistogramWidget} The new widget
   */
  createHistogramWidget: function (widgetAttrs) {
    this._dashboard.widgets.createHistogramModel.call(this, widgetAttrs);
  },

  /**
   * Create a formula widget
   * @param {Object} widgetAttrs - attributes for the new widget
   * @param {string} widgetAttrs.id - id (required)
   * @param {string} widgetAttrs.title - title (required)
   * @param {number} widgetAttrs.order - index of the widget (optional)
   * @param ...
   * @return {FormulaWidget} The new widget
   */
  createFormulaWidget: function (widgetAttrs) {
    this._dashboard.widgets.createFormulaModel.call(this, widgetAttrs);
  },

  /**
   * Create a timesier es widget
   * @param {Object} widgetAttrs - attributes for the new widget
   * @param {string} widgetAttrs.id - id (required)
   * @param {string} widgetAttrs.title - title (required)
   * @param {number} widgetAttrs.order - index of the widget (optional)
   * @param ...
   * @return {TimeSeriesWidget} The new widget
   */
  createTimeSeriesWidget: function (widgetAttrs) {
    this._dashboard.widgets.createTimeSeriesModel.call(this, widgetAttrs);
  }

};

module.exports = function (selector, vizJSON, opts, callback) {
  var args = arguments;
  var fn = args[args.length - 1];

  if (_.isFunction(fn)) {
    callback = fn;
  }

  function _load (vizJSON) {
    var dashboard = createDashboard(selector, vizJSON, opts);
    dashboard.vis.done(function () {
      callback(null, new Dashboard(dashboard));
    });
  }

  if (typeof vizJSON === 'string') {
    cdb.core.Loader.get(vizJSON, function (data) {
      if (data) {
        _load(data, opts);
      } else {
        callback(new Error('error fetching viz.json file'));
      }
    });
  } else {
     _load(vizJSON, opts);
  }
};

<|endoftext|>


<commit_before>const routes = [
  {
    index: true,
    label: 'Ishwar Sawale',
    path: '/',
  },
  {
    label: 'About',
    path: '/about',
  },
  {
    label: 'Résumé',
    path: '/resume',
  },
  {
    label: 'Projects',
    path: '/projects',
  },
  {
    label: 'Certifications',
    path: '/mooc',
  },
  {
    label: 'Stats',
    path: '/stats',
  },
  {
    label: 'Contact',
    path: '/contact',
  },
];

export default routes;
<commit_msg>fix(projects): removed project path<commit_after>const routes = [
  {
    index: true,
    label: 'Ishwar Sawale',
    path: '/',
  },
  {
    label: 'About',
    path: '/about',
  },
  {
    label: 'Résumé',
    path: '/resume',
  },
  /*{
    label: 'Projects',
    path: '/projects',
  },*/
  {
    label: 'Certifications',
    path: '/mooc',
  },
  {
    label: 'Stats',
    path: '/stats',
  },
  {
    label: 'Contact',
    path: '/contact',
  },
];

export default routes;
<|endoftext|>


<commit_before><commit_msg>Reset text inputs on page load for filter form Fixes #162 by letting textbox inputs be set by checkboxes as expected<commit_after><|endoftext|>


<commit_before>'use strict';

function usage() {
  console.log(`This script updates the dependencies / devDependencies in the main addon and app blueprints along with their corresponding test fixtures.

Options:

  - '--ember-source' (required) - The dist-tag to use for ember-source
  - '--ember-data' (required) - The dist-tag to use for ember-data
  - '--filter' (optional) - A RegExp to filter the packages to update by

Example:

node dev/update-blueprint-dependencies.js --ember-source=beta --ember-data=beta

node dev/update-blueprint-dependencies.js --filter eslint
`);
}

const fs = require('fs');
const path = require('path');
const util = require('util');
const nopt = require('nopt');
const _latestVersion = require('latest-version');

nopt.typeDefs['regexp'] = {
  type: RegExp,
  validate(data, key, value) {
    let regexp = new RegExp(value);

    data[key] = regexp;
  },
};

const OPTIONS = nopt({
  'ember-source': String,
  'ember-data': String,
  filter: RegExp,
});

const PACKAGE_FILES = [
  '../blueprints/app/files/package.json',
  '../blueprints/addon/additional-dev-dependencies.json',
  '../tests/fixtures/app/defaults/package.json',
  '../tests/fixtures/app/npm/package.json',
  '../tests/fixtures/app/yarn/package.json',
  '../tests/fixtures/app/embroider/package.json',
  '../tests/fixtures/app/embroider-no-welcome/package.json',
  '../tests/fixtures/addon/defaults/package.json',
  '../tests/fixtures/addon/yarn/package.json',
];

function shouldCheckDependency(dependency) {
  if (OPTIONS.filter) {
    return OPTIONS.filter.test(dependency);
  }

  return true;
}

const LATEST = new Map();
async function latestVersion(packageName) {
  let result = LATEST.get(packageName);

  if (result === undefined) {
    let options = {
      version: 'latest',
    };

    if (OPTIONS[packageName]) {
      options.version = OPTIONS[packageName];
    }

    result = _latestVersion(packageName, options);
    LATEST.set(packageName, result);
  }

  return result;
}

async function updateDependencies(dependencies) {
  for (let dependency in dependencies) {
    if (!shouldCheckDependency(dependency)) {
      continue;
    }

    let previousValue = dependencies[dependency];

    // grab the first char (~ or ^)
    let prefix = previousValue[0];
    let isValidPrefix = prefix === '~' || prefix === '^';

    // handle things from blueprints/app/files/package.json like `^2.4.0<% if (welcome) { %>`
    let templateSuffix = previousValue.includes('<') ? previousValue.slice(previousValue.indexOf('<')) : '';

    // check if we are dealing with `~<%= emberCLIVersion %>`
    let hasVersion = previousValue[1] !== '<';

    if (hasVersion && isValidPrefix) {
      dependencies[dependency] = `${prefix}${await latestVersion(dependency)}${templateSuffix}`;
    }
  }
}

async function main() {
  for (let packageFile of PACKAGE_FILES) {
    let filePath = path.join(__dirname, packageFile);
    let pkg = JSON.parse(fs.readFileSync(filePath, { encoding: 'utf8' }));

    await updateDependencies(pkg.dependencies);
    await updateDependencies(pkg.devDependencies);

    let output = `${JSON.stringify(pkg, null, 2)}\n`;

    fs.writeFileSync(filePath, output, { encoding: 'utf8' });
  }
}

if (module === require.main) {
  // ensure promise rejection is a failure
  process.on('unhandledRejection', (error) => {
    if (!(error instanceof Error)) {
      error = new Error(`Promise rejected with value: ${util.inspect(error)}`);
    }

    console.error(error.stack);

    /* eslint-disable-next-line no-process-exit */
    process.exit(1);
  });

  if (OPTIONS.filter || (OPTIONS['ember-source'] && OPTIONS['ember-data'])) {
    main();
  } else {
    usage();
    process.exitCode = 1;
    return;
  }
}
<commit_msg>Update dependency update script to allow finer grained control<commit_after>'use strict';

function usage() {
  console.log(`This script updates the dependencies / devDependencies in the main addon and app blueprints along with their corresponding test fixtures.

Options:

  - '--ember-source' (required) - The dist-tag to use for ember-source
  - '--ember-data' (required) - The dist-tag to use for ember-data
  - '--filter' (optional) - A RegExp to filter the packages to update by

Example:

node dev/update-blueprint-dependencies.js --ember-source=beta --ember-data=beta

node dev/update-blueprint-dependencies.js --filter /eslint/

node dev/update-blueprint-dependencies.js --filter some-package@beta
`);
}

const fs = require('fs');
const path = require('path');
const util = require('util');
const nopt = require('nopt');
const npmPackageArg = require('npm-package-arg');
const _latestVersion = require('latest-version');

nopt.typeDefs['regexp'] = {
  type: RegExp,
  validate(data, key, value) {
    let regexp = new RegExp(value);

    data[key] = regexp;
  },
};

const OPTIONS = nopt({
  'ember-source': String,
  'ember-data': String,
  filter: String,
});

const PACKAGE_FILES = [
  '../blueprints/app/files/package.json',
  '../blueprints/addon/additional-dev-dependencies.json',
  '../tests/fixtures/app/defaults/package.json',
  '../tests/fixtures/app/npm/package.json',
  '../tests/fixtures/app/yarn/package.json',
  '../tests/fixtures/app/embroider/package.json',
  '../tests/fixtures/app/embroider-no-welcome/package.json',
  '../tests/fixtures/addon/defaults/package.json',
  '../tests/fixtures/addon/yarn/package.json',
];

let filter = {
  nameRegexp: null,
  fetchSpec: null,
};

if (OPTIONS.filter) {
  if (OPTIONS.filter.startsWith('/')) {
    filter.nameRegexp = new RegExp(OPTIONS.filter);
    // can only use latest when using a regexp style
    filter.fetchSpec = 'latest';
  } else {
    let packageArgResult = npmPackageArg(OPTIONS.filter);
    filter.nameRegexp = packageArgResult.name;
    filter.fetchSpec = packageArgResult.fetchSpec;
  }
}

function shouldCheckDependency(dependency) {
  if (OPTIONS.filter) {
    if (OPTIONS.filter.startsWith('/')) {
      return OPTIONS.filter.test(dependency);
    }
  }

  return true;
}

const LATEST = new Map();
async function latestVersion(packageName) {
  let result = LATEST.get(packageName);

  if (result === undefined) {
    let options = {
      version: 'latest',
    };

    if (OPTIONS[packageName]) {
      options.version = OPTIONS[packageName];
    }

    result = _latestVersion(packageName, options);
    LATEST.set(packageName, result);
  }

  return result;
}

async function updateDependencies(dependencies) {
  for (let dependency in dependencies) {
    if (!shouldCheckDependency(dependency)) {
      continue;
    }

    let previousValue = dependencies[dependency];

    // grab the first char (~ or ^)
    let prefix = previousValue[0];
    let isValidPrefix = prefix === '~' || prefix === '^';

    // handle things from blueprints/app/files/package.json like `^2.4.0<% if (welcome) { %>`
    let templateSuffix = previousValue.includes('<') ? previousValue.slice(previousValue.indexOf('<')) : '';

    // check if we are dealing with `~<%= emberCLIVersion %>`
    let hasVersion = previousValue[1] !== '<';

    if (hasVersion && isValidPrefix) {
      dependencies[dependency] = `${prefix}${await latestVersion(dependency)}${templateSuffix}`;
    }
  }
}

async function main() {
  for (let packageFile of PACKAGE_FILES) {
    let filePath = path.join(__dirname, packageFile);
    let pkg = JSON.parse(fs.readFileSync(filePath, { encoding: 'utf8' }));

    await updateDependencies(pkg.dependencies);
    await updateDependencies(pkg.devDependencies);

    let output = `${JSON.stringify(pkg, null, 2)}\n`;

    fs.writeFileSync(filePath, output, { encoding: 'utf8' });
  }
}

if (module === require.main) {
  // ensure promise rejection is a failure
  process.on('unhandledRejection', (error) => {
    if (!(error instanceof Error)) {
      error = new Error(`Promise rejected with value: ${util.inspect(error)}`);
    }

    console.error(error.stack);

    /* eslint-disable-next-line no-process-exit */
    process.exit(1);
  });

  if (OPTIONS.filter || (OPTIONS['ember-source'] && OPTIONS['ember-data'])) {
    main();
  } else {
    usage();
    process.exitCode = 1;
    return;
  }
}
<|endoftext|>


<commit_before>var temps = "http://api.wunderground.com/api/46f5f78c97801317/forecast/q/autoip.json";

//basic additions

var localWeather = Ti.UI.createLabel({
	text: "Local Weather",
	font: {fontSize: 30, fontWeight: "bold"},
	top: 50,
	left: 20
});

var cameraPic = Ti.UI.createImageView({
	top: 30,
	right: 20,
	image: "camera.png",
	height: "10%",
	width: "20%"
});

mainView.add(cameraPic, localWeather);

//basic additions - end

//database maybe?

var db = Ti.Database.open('weatherDB');
db.execute('DROP TABLE IF EXISTS weather');
db.execute('CREATE TABLE IF NOT EXISTS weather(id INTEGER PRIMARY KEY, day TEXT, forecast TEXT)');
db.file.setRemoteBackup(false);
db.close();

//database ENd

//Week 2 - Camera additions

cameraPic.addEventListener('click', function(e){
	Ti.Media.showCamera({
		saveToPhotoGallery: false,
		allowEditing: true,
		autohide:true,
		mediaTypes: [Ti.Media.MEDIA_TYPE_PHOTO],
		success: function(e) {
			if(e.mediaType === Ti.Media.MEDIA_TYPE_PHOTO) {
				outsideImage = e;
				mainView.backgroundImage = outsideImage.media;

			} else {
				alert("thought this was a photo but, it's:" + e.mediaType);
			}
		},
		error: function(error) {
			if (error.code === Ti.Media.NO_CAMERA) {
				alert("please run this on a device");
			} else {
				alert("other error: " + error.code);
			}
		}
	}); //closing showCamera
}); //closing takePicBtn

//Week 2 END

//HTTP Functions

var remoteResponse = function(e){
	if (Ti.Network.online) {
	var json = JSON.parse(this.responseText);

for(i=0;i<5;i++){

	var day = json.forecast.txt_forecast.forecastday[i].title;
	var forecast = json.forecast.txt_forecast.forecastday[i].fcttext;
	var weatherImage = json.forecast.txt_forecast.forecastday[i].icon_url;
	var balancer = i * 115;

	var postDay = Ti.UI.createLabel({
		text: day,
		color: "#ff6600",
		top: balancer + 120,
		left: 20
		});

	var postForecast = Ti.UI.createLabel({
		text: forecast,
		top: balancer + 138,
		color: "ff0000",
		left: 145,
		width: 160
	});

	var postImage = Ti.UI.createImageView({
		image: weatherImage,
		top: balancer + 145,
		left: 35
	});

	balancer = balancer + 50;

	mainView.add(postImage, postDay, postForecast);
	db.open();
	db.execute('INSERT INTO weather (day, forecast) VALUES (?,?)', day, forecast);
	var lastID = db.lastInsertRowID;
	db.close();

	}
	//end for loop
} else {
	Ti.API.debug("Status: " + this.status);
	Ti.API.debug("Response: " + this.responseText);
	Ti.API.debug("Error: " + e.error);
	alert("There was an error retrieving data. Please try again later.");
};

};
var remoteError = function(e){
	Ti.API.debug("Status: " + this.status);
	Ti.API.debug("Response: " + this.responseText);
	Ti.API.debug("Error: " + e.error);
	alert("There was an error.");
};

var xhr = Ti.Network.createHTTPClient({
	onload: remoteResponse,
	onerror: remoteError,
	timeout: 20000
});

xhr.open("GET", temps);
xhr.send();

//HTTP Functions - end
<commit_msg>Database working<commit_after>var temps = "http://api.wunderground.com/api/46f5f78c97801317/forecast/q/autoip.json";

//basic additions

var localWeather = Ti.UI.createLabel({
	text: "Local Weather",
	font: {fontSize: 30, fontWeight: "bold"},
	top: 50,
	left: 20
});

var cameraPic = Ti.UI.createImageView({
	top: 30,
	right: 20,
	image: "camera.png",
	height: "10%",
	width: "20%"
});

mainView.add(cameraPic, localWeather);

//basic additions - end

//database maybe?

//database ENd

//Week 2 - Camera additions

cameraPic.addEventListener('click', function(e){
	Ti.Media.showCamera({
		saveToPhotoGallery: false,
		allowEditing: true,
		autohide:true,
		mediaTypes: [Ti.Media.MEDIA_TYPE_PHOTO],
		success: function(e) {
			if(e.mediaType === Ti.Media.MEDIA_TYPE_PHOTO) {
				outsideImage = e;
				mainView.backgroundImage = outsideImage.media;

			} else {
				alert("thought this was a photo but, it's:" + e.mediaType);
			}
		},
		error: function(error) {
			if (error.code === Ti.Media.NO_CAMERA) {
				alert("please run this on a device");
			} else {
				alert("other error: " + error.code);
			}
		}
	}); //closing showCamera
}); //closing takePicBtn

//Week 2 END

//HTTP Functions

var remoteResponse = function(e){
	if (Ti.Network.online) {
	var json = JSON.parse(this.responseText);

for(i=0;i<5;i++){

	var day = json.forecast.txt_forecast.forecastday[i].title;
	var forecast = json.forecast.txt_forecast.forecastday[i].fcttext;
	var weatherImage = json.forecast.txt_forecast.forecastday[i].icon_url;
	var balancer = i * 115;

	var postDay = Ti.UI.createLabel({
		text: day,
		color: "#ff6600",
		top: balancer + 120,
		left: 20
		});

	var postForecast = Ti.UI.createLabel({
		text: forecast,
		top: balancer + 138,
		color: "ff0000",
		left: 145,
		width: 160
	});

	var postImage = Ti.UI.createImageView({
		image: weatherImage,
		top: balancer + 145,
		left: 35
	});

	balancer = balancer + 50;

	mainView.add(postImage, postDay, postForecast);

	var db = Ti.Database.open('weatherDB');
	db.open();
	db.execute('DROP TABLE IF EXISTS weather');
	db.execute('CREATE TABLE IF NOT EXISTS weather(id INTEGER PRIMARY KEY, day TEXT, forecast TEXT, image TEXT)');
	db.file.setRemoteBackup(false);
	db.execute('INSERT INTO weather (day, forecast, image) VALUES (?,?,?)', day, forecast, weatherImage);
	var offlineDay = db.execute('SELECT day FROM weather');
	var offlineForecast = db.execute('SELECT forecast FROM weather');
	var offlineImage = db.execute('SELECT image FROM weather');
	var lastRow = db.lastInsertRowId;

	console.log(offlineDay.field(0));
	console.log(offlineForecast.field(0));
	console.log(lastRow);
	db.close();
	}
	//end for loop
} else {
	Ti.API.debug("Status: " + this.status);
	Ti.API.debug("Response: " + this.responseText);
	Ti.API.debug("Error: " + e.error);
	alert("There was an error retrieving data. Please try again later.");

	db.open();
	console.log(offlineDay.field(0));

	var offlinePostDay = Ti.UI.createLabel({
		text: offlineDay.field(0),
		color: "#ff6600",
		top: balancer + 120,
		left: 20
		});

	var offlinePostForecast = Ti.UI.createLabel({
		text: offlineForecast.field(0),
		top: balancer + 138,
		color: "ff0000",
		left: 145,
		width: 160
	});

	var offlinePostImage = Ti.UI.createImageView({
		image: offlineImage.field(0),
		top: balancer + 145,
		left: 35
	});

	mainView.add(offlinePostDay, offlinePostForecast, offlinePostImage);
	db.close();
};

};
var remoteError = function(e){
	Ti.API.debug("Status: " + this.status);
	Ti.API.debug("Response: " + this.responseText);
	Ti.API.debug("Error: " + e.error);
	alert("There was an error.");
};

var xhr = Ti.Network.createHTTPClient({
	onload: remoteResponse,
	onerror: remoteError,
	timeout: 20000
});

xhr.open("GET", temps);
xhr.send();

//HTTP Functions - end
<|endoftext|>


<commit_before>module.exports = [
	{type: "getConfig", fn: _getConfig},
	{type: "gotConfig", fn: _gotConfig},

	{type: "addFolder", fn: _addFolder},
	{type: "folderAdded", fn: _folderAdded},
	{type: "deleteFolder", fn: _deleteFolder},
	{type: "folderDeleted", fn: _folderDeleted},

	{type: "toggleDryRun", fn: _toggleDryRun},
	{type: "dryRunToggled", fn: _dryRunToggled},
]

function _getConfig({state, actions, dispatch}, {api, _}) {
	dispatch(actions.opInProgress, actions.getConfig)

	api.getConfig()
		.then(json => {
			dispatch(actions.gotConfig, json)
		})
	// here i can catch the error and show an appropriate message

	return state
}

function _gotConfig({state, actions, dispatch}, _, config) {
	let newState = Object.assign({}, state)

	newState.config = config
	newState.opInProgress = null

	return newState
}

function _addFolder({state, actions, dispatch}, {api, _}, folder) {
	if (state.config.folders.indexOf(folder) !== -1) {
		return state
	}

	dispatch(actions.opInProgress, actions.addFolder)

	api.addFolder(folder)
		.then(json => {
			dispatch(actions.folderAdded, json)
		})

	return state
}

function _folderAdded({state, actions, dispatch}, _, config) {
	let newState = Object.assign({}, state)

	newState.config = config
	newState.opInProgress = null

	return newState
}

function _deleteFolder({state, actions, dispatch}, {api, _}, folder) {
	dispatch(actions.opInProgress, actions.deleteFolder)

	api.deleteFolder(folder)
		.then(json => {
			dispatch(actions.folderDeleted, json)
		})

	return state
}

function _folderDeleted({state, actions, dispatch}, _, config) {
	let newState = Object.assign({}, state)

	newState.config = config
	newState.opInProgress = null

	return newState
}

function _toggleDryRun({state, actions, dispatch}) {
	dispatch(actions.opInProgress, actions.toggleDryRun)

	api.toggleDryRun()
		.then(json => {
			dispatch(actions.dryRunToggled, json)
		})

	return state
}

function _dryRunToggled({state, actions, dispatch}, _, config) {
	let newState = Object.assign({}, state)

	newState.config = config
	newState.opInProgress = null

	return newState
}
<commit_msg>(front) Add missing api parameter<commit_after>module.exports = [
	{type: "getConfig", fn: _getConfig},
	{type: "gotConfig", fn: _gotConfig},

	{type: "addFolder", fn: _addFolder},
	{type: "folderAdded", fn: _folderAdded},
	{type: "deleteFolder", fn: _deleteFolder},
	{type: "folderDeleted", fn: _folderDeleted},

	{type: "toggleDryRun", fn: _toggleDryRun},
	{type: "dryRunToggled", fn: _dryRunToggled},
]

function _getConfig({state, actions, dispatch}, {api, _}) {
	dispatch(actions.opInProgress, actions.getConfig)

	api.getConfig()
		.then(json => {
			dispatch(actions.gotConfig, json)
		})
	// here i can catch the error and show an appropriate message

	return state
}

function _gotConfig({state, actions, dispatch}, _, config) {
	let newState = Object.assign({}, state)

	newState.config = config
	newState.opInProgress = null

	return newState
}

function _addFolder({state, actions, dispatch}, {api, _}, folder) {
	if (state.config.folders.indexOf(folder) !== -1) {
		return state
	}

	dispatch(actions.opInProgress, actions.addFolder)

	api.addFolder(folder)
		.then(json => {
			dispatch(actions.folderAdded, json)
		})

	return state
}

function _folderAdded({state, actions, dispatch}, _, config) {
	let newState = Object.assign({}, state)

	newState.config = config
	newState.opInProgress = null

	return newState
}

function _deleteFolder({state, actions, dispatch}, {api, _}, folder) {
	dispatch(actions.opInProgress, actions.deleteFolder)

	api.deleteFolder(folder)
		.then(json => {
			dispatch(actions.folderDeleted, json)
		})

	return state
}

function _folderDeleted({state, actions, dispatch}, _, config) {
	let newState = Object.assign({}, state)

	newState.config = config
	newState.opInProgress = null

	return newState
}

function _toggleDryRun({state, actions, dispatch}, {api, _}) {
	dispatch(actions.opInProgress, actions.toggleDryRun)

	api.toggleDryRun()
		.then(json => {
			dispatch(actions.dryRunToggled, json)
		})

	return state
}

function _dryRunToggled({state, actions, dispatch}, _, config) {
	let newState = Object.assign({}, state)

	newState.config = config
	newState.opInProgress = null

	return newState
}
<|endoftext|>


<commit_before>import React from 'react';
import { shallow } from 'enzyme';

import H3 from '../index';

describe('
', () => {
  it('should render a prop', () => {
    const id = 'testId';
    const renderedComponent = shallow(

    );
    expect(renderedComponent.prop('id')).toEqual(id);
  });

  it('should render its text', () => {
    const children = 'Text';
    const renderedComponent = shallow(

{children}

    );
    expect(renderedComponent.contains(children)).toBe(true);
  });
});
<commit_msg>fix unit testing for
 component<commit_after>import React from 'react';
import { shallow } from 'enzyme';

import H4 from '../index';

describe('
', () => {
  it('renders a
', () => {
    const renderedComponent = shallow(

    );
    expect(renderedComponent.find('h4').node).toBeDefined();
  });

  it('should render a prop', () => {
    const id = 'testId';
    const renderedComponent = shallow(

    );
    expect(renderedComponent.prop('id')).toEqual(id);
  });

  it('should render its text', () => {
    const children = 'Text';
    const renderedComponent = shallow(

{children}

    );
    expect(renderedComponent.contains(children)).toBe(true);
  });
});
<|endoftext|>


<commit_before>// Import React
import React from "react";
import mapValues from "lodash/mapValues";

// Import Spectacle Core tags
import {
  Appear,
  //BlockQuote,
  //Cite,
  CodePane,
  Deck,
  //Fill,
  Heading,
  Image,
  Layout,
  Link,
  List,
  ListItem,
  //Markdown,
  //Quote,
  Slide,
  Table,
  TableRow,
  TableHeaderItem,
  TableItem
  //Text
} from "spectacle";

import Counter from './counter_01';

// Import image preloader util
import preloader from "spectacle/lib/utils/preloader";

// Import theme
import createTheme from "spectacle/lib/themes/default";

// Require CSS
require("normalize.css");
require("spectacle/lib/themes/default/index.css");
require("./custom.css");

const slideTransition = ["slide"];
const images = mapValues({
  lifecycle: require("../images/lifecycle.png"),
  survivejs: require("../images/survivejs.png")
}, (v) => v.replace("/", ""));

preloader(images);

const theme = createTheme({
  primary: "white",
  secondary: "black",
  tertiary: "#09b5c4",
  quartenary: "rgba(255, 219, 169, 0.43)"
});

export default class Presentation extends React.Component {
  render() {
    return (
      <Deck transition={slideTransition} transitionDuration={500} theme={theme}>
        <Slide transition={slideTransition} bgColor="secondary">
          <Heading size={1} fit caps lineHeight={1} textColor="tertiary">
            React Components
          </Heading>
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={1}>
            React Philosophy
          </Heading>
          <List>
            <Appear><ListItem>Model your application as a component hierarchy</ListItem></Appear>
            <Appear><ListItem>Each component can have props and state</ListItem></Appear>
            <Appear><ListItem>Escape hatches through lifecycle methods and refs</ListItem></Appear>
            <Appear><ListItem>React forces you to think about state (a good thing!)</ListItem></Appear>
          </List>
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={1}>
            Components
          </Heading>
          <Layout>

                <TableRow>
                  <TableHeaderItem />
                  <TableHeaderItem>createClass</TableHeaderItem>
                  <TableHeaderItem>extends Component</TableHeaderItem>
                  <TableHeaderItem>Functions</TableHeaderItem>
                </TableRow>

                <Appear>
                  <TableRow>
                    <TableItem>props</TableItem>
                    <TableItem>X</TableItem>
                    <TableItem>X</TableItem>
                    <TableItem>X</TableItem>
                  </TableRow>
                </Appear>
                <Appear>
                  <TableRow>
                    <TableItem>context</TableItem>
                    <TableItem>X</TableItem>
                    <TableItem>X</TableItem>
                    <TableItem>X</TableItem>
                  </TableRow>
                </Appear>
                <Appear>
                  <TableRow>
                    <TableItem>refs</TableItem>
                    <TableItem>X</TableItem>
                    <TableItem>X</TableItem>
                    <TableItem>X</TableItem>
                  </TableRow>
                </Appear>
                <Appear>
                  <TableRow>
                    <TableItem>state</TableItem>
                    <TableItem>X</TableItem>
                    <TableItem>X</TableItem>
                    <TableItem />
                  </TableRow>
                </Appear>
                <Appear>
                  <TableRow>
                    <TableItem>Lifecycle methods</TableItem>
                    <TableItem>X</TableItem>
                    <TableItem>X</TableItem>
                    <TableItem />
                  </TableRow>
                </Appear>
                <Appear>
                  <TableRow>
                    <TableItem>Notes</TableItem>
                    <TableItem>Deprecated!</TableItem>
                    <TableItem />
                    <TableItem>Good default</TableItem>
                  </TableRow>
                </Appear>

          </Layout>
        </Slide>

        <Slide transition={slideTransition} bgColor="secondary">
          <Heading size={2} textColor="tertiary">
            React.Component
          </Heading>
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={1}>
            Cat Counter
          </Heading>
          <Counter />
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={1} fit>
            <Link href="https://codesandbox.io/s/76gK41lrQ">React.Component</Link>
          </Heading>
          <CodePane
            lang="jsx"
            source={require("raw-loader!content!./counter_01.jsx")}
            margin="20px auto"
          />
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={1}>
            <Link href="https://codesandbox.io/s/NxXNAOZAK">No JSX</Link>
          </Heading>
          <CodePane
            lang="js"
            source={require("raw-loader!content!./counter_no_jsx.js")}
            margin="20px auto"
          />
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={1} fit>
            <Link href="https://codesandbox.io/s/JZxJgDqNg">React.Component</Link> with <Link href="https://github.com/tc39/proposal-class-public-fields">public fields (stage 2)</Link>
          </Heading>
          <CodePane
            lang="jsx"
            source={require("raw-loader!content!./counter_02.jsx")}
            margin="20px auto"
          />
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={1} fit>
            <Link href="https://codesandbox.io/s/3lBqVwL5A">React.Component</Link> with Function Style setState
          </Heading>
          <CodePane
            lang="jsx"
            source={require("raw-loader!content!./counter_03.jsx")}
            margin="20px auto"
          />
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={1} fit>
            <Link href="https://codesandbox.io/s/g5kzWv3Zl">React.Component</Link> with Function Style setState Extracted
          </Heading>
          <CodePane
            lang="jsx"
            source={require("raw-loader!content!./counter_04.jsx")}
            margin="20px auto"
          />
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={1}>
            Exercises
          </Heading>
          <List>
            <Appear><ListItem>0. Fork the last code example at <Link href="https://codesandbox.io/">CodeSandbox</Link>. You can find a link to it in the header.</ListItem></Appear>
            <Appear><ListItem>1. Make it possible to add two cats at once</ListItem></Appear>
            <Appear><ListItem>2. Add a reset button to restore the count to zero*</ListItem></Appear>
            <Appear><ListItem>3. Add multiple options. Hint: [1, 2, 4].map(...). Look up React <Link href="https://facebook.github.io/react/docs/reconciliation.html">key</Link>. Why is it needed?**</ListItem></Appear>
            <Appear><ListItem>4. Try this.setState(..., cb)***</ListItem></Appear>
            <Appear><ListItem>Solutions: <Link href="https://codesandbox.io/s/g5kzWv3Zl">0</Link>, <Link href="https://codesandbox.io/s/L98PX9kMp">1</Link>, <Link href="https://codesandbox.io/s/Q1qvPRW55">2</Link>, <Link href="https://codesandbox.io/s/31J17rM7n">3</Link>, <Link href="https://codesandbox.io/s/qvEWNmJ0">4</Link></ListItem></Appear>
          </List>
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={1}>
            key
          </Heading>
          <CodePane
            lang="jsx"
            source={require("raw-loader!content!../examples/key_01.jsx")}
            margin="20px auto"
          />
          <Link href="https://facebook.github.io/react/docs/reconciliation.html">Read React reconciliation documentation to understand more</Link>
        </Slide>

        <Slide transition={slideTransition} bgColor="secondary">
          <Heading size={2} textColor="tertiary">
            Composition
          </Heading>
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={1} fit>
            <Link href="https://codesandbox.io/s/qvEWNmJ0">Why composition?</Link>
          </Heading>
          <CodePane
            lang="jsx"
            source={require("raw-loader!content!../examples/composition_01.jsx")}
            margin="20px auto"
          />
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={1} fit>
            <Link href="https://codesandbox.io/s/X6GyyXg9v">Decomposition</Link>
          </Heading>
          <CodePane
            lang="jsx"
            source={require("raw-loader!content!../examples/composition_02.jsx")}
            margin="20px auto"
          />
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={1}>
            Exercises
          </Heading>
          <List>
            <Appear><ListItem>0. Decompose the counter as in the slides</ListItem></Appear>
            <Appear><ListItem>1. Implement App that contains multiple CatCounters</ListItem></Appear>
            <Appear><ListItem>2. Implement a generic Counter so you can count other things*</ListItem></Appear>
            <Appear><ListItem>3. Count total of all things in the user interface**</ListItem></Appear>
            <Appear><ListItem>Solutions: <Link href="https://codesandbox.io/s/X6GyyXg9v">0</Link>, <Link href="https://codesandbox.io/s/73AKPwX3j">1</Link>, <Link href="https://codesandbox.io/s/O7L2zM0mg">2</Link>, <Link href="https://codesandbox.io/s/X64K29kMo">3</Link></ListItem></Appear>
          </List>
        </Slide>

        <Slide transition={slideTransition} bgColor="secondary">
          <Heading size={2} textColor="tertiary">
            refs
          </Heading>
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={4}>
            React.Component with a Ref
          </Heading>
          <CodePane
            lang="jsx"
            source={require("raw-loader!../examples/refs_01.jsx")}
            margin="20px auto"
          />
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={1}>
            Exercises
          </Heading>
          <List>
            <Appear><ListItem>0. Capture a custom amount using an input and a ref</ListItem></Appear>
            <Appear><ListItem>1. Do the same without a ref*</ListItem></Appear>
            <Appear><ListItem>Solutions: <Link href="https://codesandbox.io/s/VO7zJD0k5">0</Link> (can you see the bug?), <Link href="https://codesandbox.io/s/RoznJpjpE">1</Link></ListItem></Appear>
          </List>
        </Slide>

        <Slide transition={slideTransition} bgColor="secondary">
          <Heading size={2} textColor="tertiary">
            Lifecycle Methods
          </Heading>
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={1}>
            Lifecycle Methods
          </Heading>
          <Image src={images.lifecycle} margin="40px auto" height="324px" />
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={1}>
            Exercises
          </Heading>
          <List>
            <Appear><ListItem>0. Implement a shouldComponentUpdate at Counter so that it returns false and see when it gets triggered</ListItem></Appear>
            <Appear><ListItem>Solutions: <Link href="https://codesandbox.io/s/lO8pPZ2Zl">0</Link></ListItem></Appear>
          </List>
        </Slide>

        <Slide transition={slideTransition} bgColor="secondary">
          <Heading size={2} textColor="tertiary">
            Higher-Order Components
          </Heading>
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={1} fit>
            Why Higher-Order Components?
          </Heading>
          <List>
            <Appear><ListItem>Encapsulate a specific concern</ListItem></Appear>
            <Appear><ListItem>Examples: authenticated route, connect (pass state)</ListItem></Appear>
            <Appear><ListItem>Smaller slices to test</ListItem></Appear>
          </List>
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={1}>
            Exercises
          </Heading>
          <List>
            <Appear><ListItem>0. Refactor state management into a stateful HOC that contains setState</ListItem></Appear>
            <Appear><ListItem>1. Implement Provider and connect pair to pass state through hierarchy (hint: see Redux for basic API)*</ListItem></Appear>
          </List>
        </Slide>

        <Slide transition={slideTransition}>
          <Link href="https://www.survivejs.com/">
            <Heading size={1}>
              SurviveJS
            </Heading>
          </Link>
          <Image src={images.survivejs} margin="0px auto 40px" height="524px"/>
        </Slide>

        <Slide transition={slideTransition} bgColor="tertiary">
          <Heading size={1} caps fit textColor="primary">
            Made in Finland by
          </Heading>
          <Link href="https://twitter.com/bebraw">
            <Heading caps fit size={2} textColor="secondary">
              Juho Vepsäläinen
            </Heading>
          </Link>
        </Slide>
      </Deck>
    );
  }
}
<commit_msg>chore: Improve header hierarchy<commit_after>// Import React
import React from "react";
import mapValues from "lodash/mapValues";

// Import Spectacle Core tags
import {
  Appear,
  //BlockQuote,
  //Cite,
  CodePane,
  Deck,
  //Fill,
  Heading,
  Image,
  Layout,
  Link,
  List,
  ListItem,
  //Markdown,
  //Quote,
  Slide,
  Table,
  TableRow,
  TableHeaderItem,
  TableItem
  //Text
} from "spectacle";

import Counter from './counter_01';

// Import image preloader util
import preloader from "spectacle/lib/utils/preloader";

// Import theme
import createTheme from "spectacle/lib/themes/default";

// Require CSS
require("normalize.css");
require("spectacle/lib/themes/default/index.css");
require("./custom.css");

const slideTransition = ["slide"];
const images = mapValues({
  lifecycle: require("../images/lifecycle.png"),
  survivejs: require("../images/survivejs.png")
}, (v) => v.replace("/", ""));

preloader(images);

const theme = createTheme({
  primary: "white",
  secondary: "black",
  tertiary: "#09b5c4",
  quartenary: "rgba(255, 219, 169, 0.43)"
});

export default class Presentation extends React.Component {
  render() {
    return (
      <Deck transition={slideTransition} transitionDuration={500} theme={theme}>
        <Slide transition={slideTransition} bgColor="secondary">
          <Heading size={1} fit caps lineHeight={1} textColor="tertiary">
            React Components
          </Heading>
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2}>
            React Philosophy
          </Heading>
          <List>
            <Appear><ListItem>Model your application as a component hierarchy</ListItem></Appear>
            <Appear><ListItem>Each component can have props and state</ListItem></Appear>
            <Appear><ListItem>Escape hatches through lifecycle methods and refs</ListItem></Appear>
            <Appear><ListItem>React forces you to think about state (a good thing!)</ListItem></Appear>
          </List>
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2}>
            Components
          </Heading>
          <Layout>

                <TableRow>
                  <TableHeaderItem />
                  <TableHeaderItem>createClass</TableHeaderItem>
                  <TableHeaderItem>extends Component</TableHeaderItem>
                  <TableHeaderItem>Functions</TableHeaderItem>
                </TableRow>

                <Appear>
                  <TableRow>
                    <TableItem>props</TableItem>
                    <TableItem>X</TableItem>
                    <TableItem>X</TableItem>
                    <TableItem>X</TableItem>
                  </TableRow>
                </Appear>
                <Appear>
                  <TableRow>
                    <TableItem>context</TableItem>
                    <TableItem>X</TableItem>
                    <TableItem>X</TableItem>
                    <TableItem>X</TableItem>
                  </TableRow>
                </Appear>
                <Appear>
                  <TableRow>
                    <TableItem>refs</TableItem>
                    <TableItem>X</TableItem>
                    <TableItem>X</TableItem>
                    <TableItem>X</TableItem>
                  </TableRow>
                </Appear>
                <Appear>
                  <TableRow>
                    <TableItem>state</TableItem>
                    <TableItem>X</TableItem>
                    <TableItem>X</TableItem>
                    <TableItem />
                  </TableRow>
                </Appear>
                <Appear>
                  <TableRow>
                    <TableItem>Lifecycle methods</TableItem>
                    <TableItem>X</TableItem>
                    <TableItem>X</TableItem>
                    <TableItem />
                  </TableRow>
                </Appear>
                <Appear>
                  <TableRow>
                    <TableItem>Notes</TableItem>
                    <TableItem>Deprecated!</TableItem>
                    <TableItem />
                    <TableItem>Good default</TableItem>
                  </TableRow>
                </Appear>

          </Layout>
        </Slide>

        <Slide transition={slideTransition} bgColor="secondary">
          <Heading size={2} textColor="tertiary">
            React.Component
          </Heading>
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2}>
            Cat Counter
          </Heading>
          <Counter />
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2}>
            <Link href="https://codesandbox.io/s/76gK41lrQ">React.Component</Link>
          </Heading>
          <CodePane
            lang="jsx"
            source={require("raw-loader!content!./counter_01.jsx")}
            margin="20px auto"
          />
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2}>
            <Link href="https://codesandbox.io/s/NxXNAOZAK">No JSX</Link>
          </Heading>
          <CodePane
            lang="js"
            source={require("raw-loader!content!./counter_no_jsx.js")}
            margin="20px auto"
          />
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2} fit>
            <Link href="https://codesandbox.io/s/JZxJgDqNg">React.Component</Link> with <Link href="https://github.com/tc39/proposal-class-public-fields">public fields (stage 2)</Link>
          </Heading>
          <CodePane
            lang="jsx"
            source={require("raw-loader!content!./counter_02.jsx")}
            margin="20px auto"
          />
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2} fit>
            <Link href="https://codesandbox.io/s/3lBqVwL5A">React.Component</Link> with Function Style setState
          </Heading>
          <CodePane
            lang="jsx"
            source={require("raw-loader!content!./counter_03.jsx")}
            margin="20px auto"
          />
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2} fit>
            <Link href="https://codesandbox.io/s/g5kzWv3Zl">React.Component</Link> with Function Style setState Extracted
          </Heading>
          <CodePane
            lang="jsx"
            source={require("raw-loader!content!./counter_04.jsx")}
            margin="20px auto"
          />
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2}>
            Exercises
          </Heading>
          <List>
            <Appear><ListItem>0. Fork the last code example at <Link href="https://codesandbox.io/">CodeSandbox</Link>. You can find a link to it in the header.</ListItem></Appear>
            <Appear><ListItem>1. Make it possible to add two cats at once</ListItem></Appear>
            <Appear><ListItem>2. Add a reset button to restore the count to zero*</ListItem></Appear>
            <Appear><ListItem>3. Add multiple options. Hint: [1, 2, 4].map(...). Look up React <Link href="https://facebook.github.io/react/docs/reconciliation.html">key</Link>. Why is it needed?**</ListItem></Appear>
            <Appear><ListItem>4. Try this.setState(..., cb)***</ListItem></Appear>
            <Appear><ListItem>Solutions: <Link href="https://codesandbox.io/s/g5kzWv3Zl">0</Link>, <Link href="https://codesandbox.io/s/L98PX9kMp">1</Link>, <Link href="https://codesandbox.io/s/Q1qvPRW55">2</Link>, <Link href="https://codesandbox.io/s/31J17rM7n">3</Link>, <Link href="https://codesandbox.io/s/qvEWNmJ0">4</Link></ListItem></Appear>
          </List>
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2}>
            key
          </Heading>
          <CodePane
            lang="jsx"
            source={require("raw-loader!content!../examples/key_01.jsx")}
            margin="20px auto"
          />
          <Link href="https://facebook.github.io/react/docs/reconciliation.html">Read React reconciliation documentation to understand more</Link>
        </Slide>

        <Slide transition={slideTransition} bgColor="secondary">
          <Heading size={2} textColor="tertiary">
            Composition
          </Heading>
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2}>
            <Link href="https://codesandbox.io/s/qvEWNmJ0">Why composition?</Link>
          </Heading>
          <CodePane
            lang="jsx"
            source={require("raw-loader!content!../examples/composition_01.jsx")}
            margin="20px auto"
          />
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2}>
            <Link href="https://codesandbox.io/s/X6GyyXg9v">Decomposition</Link>
          </Heading>
          <CodePane
            lang="jsx"
            source={require("raw-loader!content!../examples/composition_02.jsx")}
            margin="20px auto"
          />
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2}>
            Exercises
          </Heading>
          <List>
            <Appear><ListItem>0. Decompose the counter as in the slides</ListItem></Appear>
            <Appear><ListItem>1. Implement App that contains multiple CatCounters</ListItem></Appear>
            <Appear><ListItem>2. Implement a generic Counter so you can count other things*</ListItem></Appear>
            <Appear><ListItem>3. Count total of all things in the user interface**</ListItem></Appear>
            <Appear><ListItem>Solutions: <Link href="https://codesandbox.io/s/X6GyyXg9v">0</Link>, <Link href="https://codesandbox.io/s/73AKPwX3j">1</Link>, <Link href="https://codesandbox.io/s/O7L2zM0mg">2</Link>, <Link href="https://codesandbox.io/s/X64K29kMo">3</Link></ListItem></Appear>
          </List>
        </Slide>

        <Slide transition={slideTransition} bgColor="secondary">
          <Heading size={2} textColor="tertiary">
            refs
          </Heading>
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2} fit>
            React.Component with a Ref
          </Heading>
          <CodePane
            lang="jsx"
            source={require("raw-loader!../examples/refs_01.jsx")}
            margin="20px auto"
          />
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2}>
            Exercises
          </Heading>
          <List>
            <Appear><ListItem>0. Capture a custom amount using an input and a ref</ListItem></Appear>
            <Appear><ListItem>1. Do the same without a ref*</ListItem></Appear>
            <Appear><ListItem>Solutions: <Link href="https://codesandbox.io/s/VO7zJD0k5">0</Link> (can you see the bug?), <Link href="https://codesandbox.io/s/RoznJpjpE">1</Link></ListItem></Appear>
          </List>
        </Slide>

        <Slide transition={slideTransition} bgColor="secondary">
          <Heading size={2} textColor="tertiary">
            Lifecycle Methods
          </Heading>
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2}>
            Lifecycle Methods
          </Heading>
          <Image src={images.lifecycle} margin="40px auto" height="324px" />
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2}>
            Exercises
          </Heading>
          <List>
            <Appear><ListItem>0. Implement a shouldComponentUpdate at Counter so that it returns false and see when it gets triggered</ListItem></Appear>
            <Appear><ListItem>Solutions: <Link href="https://codesandbox.io/s/lO8pPZ2Zl">0</Link></ListItem></Appear>
          </List>
        </Slide>

        <Slide transition={slideTransition} bgColor="secondary">
          <Heading size={2} textColor="tertiary">
            Higher-Order Components
          </Heading>
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2} fit>
            Why Higher-Order Components?
          </Heading>
          <List>
            <Appear><ListItem>Encapsulate a specific concern</ListItem></Appear>
            <Appear><ListItem>Examples: authenticated route, connect (pass state)</ListItem></Appear>
            <Appear><ListItem>Smaller slices to test</ListItem></Appear>
          </List>
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2}>
            Exercises
          </Heading>
          <List>
            <Appear><ListItem>0. Refactor state management into a stateful HOC that contains setState</ListItem></Appear>
            <Appear><ListItem>1. Implement Provider and connect pair to pass state through hierarchy (hint: see Redux for basic API)*</ListItem></Appear>
          </List>
        </Slide>

        <Slide transition={slideTransition}>
          <Link href="https://www.survivejs.com/">
            <Heading size={1}>
              SurviveJS
            </Heading>
          </Link>
          <Image src={images.survivejs} margin="0px auto 40px" height="524px"/>
        </Slide>

        <Slide transition={slideTransition} bgColor="tertiary">
          <Heading size={1} caps fit textColor="primary">
            Made in Finland by
          </Heading>
          <Link href="https://twitter.com/bebraw">
            <Heading caps fit size={2} textColor="secondary">
              Juho Vepsäläinen
            </Heading>
          </Link>
        </Slide>
      </Deck>
    );
  }
}
<|endoftext|>