<commit_before>//****************************************************************************
// PopCalendar 4.1, Emailware(please mail&commend me if u like it)
// Originally coded by Liming(Victor) Weng, email: victorwon@netease.com
// Release date: 2000.5.9
// Anyone may modify it to satify his needs, but please leave this comment ahead.
//****************************************************************************

//****************************************************************************
// Extensively modified by Paul Geetz
// Date: August 2002
//****************************************************************************

var gdCtrl = new Object();
var gcGray = "#808080";
var gcToggle = "#ffff00";
var gcBG = "#cccccc";

var gRetCtrl;
var gFormat;
var gdCurDate = new Date();
var giYear = gdCurDate.getFullYear();
var giMonth = gdCurDate.getMonth()+1;
var giDay = gdCurDate.getDate();
var VicPopCal = null;

//****************************************************************************
// Param: popCtrl is the widget beyond which you want this calendar to appear;
//        dateCtrl is the widget into which you want to put the selected date;
//        popCal is the widget to display the calendar;
// i.e.: <input type="text" name="dc" style="text-align:center" readonly>
// <INPUT type="button" value="V" onclick="fPopCalendar(dc,dc,popCal);return false">
//****************************************************************************
function fPopCalendar(popCtrl, dateCtrl, valCtrl, popCal)
{
  if (VicPopCal) {
        fHideCalendar();
        return;
  }
  VicPopCal = popCal;
  gdCtrl = dateCtrl;
  gRetCtrl = valCtrl;
  gFormat = dateCtrl.format;

  var d = new Date();
  d.setTime(gRetCtrl.value);
  fSetYearMon(d.getYear(), d.getMonth()+1);

  var point = fGetXY(popCtrl);
  with (VicPopCal.style) {
    left = point.x;
  top  = point.y+popCtrl.offsetHeight+1;
  visibility = 'visible';
  }

  window.event.cancelBubble = true;
  document.body.attachEvent("onclick", fHideCalendar);
  VicPopCal.focus();
}

function fHideCalendar()
{
 if (VicPopCal) {
     VicPopCal.style.visibility = "hidden";
     VicPopCal = null;
     //document.body.detachEvent("onclick", fHideCalendar);
 }
}

function fSetDate(iYear, iMonth, iDay)
{
  var d = new Date();
  d.setYear(iYear);
  d.setMonth(iMonth-1);
  d.setDate(iDay);

  gdCtrl.value = formatDate(d);
  gRetCtrl.value = d.getTime();

  fHideCalendar();
}

var monthShortNames = new Array('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
var monthLongNames = new Array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December');
var dayNames = new Array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday','Friday', 'Saturday');

function pad(number,X)
{
	X = (!X ? 2 : X);
	number = ""+number;
	while (number.length<X) {
	    number="0"+number;
	}
	return number;
}

function formatDate(date)
{

    var bits = new Array();
    bits['d'] = date.getDate();
    bits['dd'] = pad(date.getDate(),2);
    bits['dddd'] = dayNames[date.getDay()];

    bits['M'] = date.getMonth()+1;
    bits['MM'] = pad(date.getMonth()+1,2);
    bits['MMM'] = monthShortNames[date.getMonth()];
    bits['MMMM'] = monthLongNames[date.getMonth()];
    bits['yyyy'] = date.getYear();
    bits['yy'] = bits['yyyy'].toString().substr(2,2);

    var frm = new String(gFormat);
    var sect;
    for (sect in bits) {
      frm=eval("frm.replace(/\\b"+sect+"\\b/,'"+bits[sect]+"');");
    }

    return frm;

}

function fSetSelected(aCell)
{
  var iOffset = 0;
  var iYear = parseInt(tbSelYear.value);
  var iMonth = parseInt(tbSelMonth.value);

  aCell.bgColor = gcBG;
  with (aCell.children["cellText"]){
    var iDay = parseInt(innerText);
    if (color==gcGray)
    iOffset = -1;
  iMonth += iOffset;
  if (iMonth<1) {
    iYear--;
    iMonth = 12;
  }else if (iMonth>12){
    iYear++;
    iMonth = 1;
  }
  }
  fSetDate(iYear, iMonth, iDay);
  window.event.cancelBubble = true;
}

function Point(iX, iY)
{
  this.x = iX;
  this.y = iY;
}

function fBuildCal(iYear, iMonth)
{
  var aMonth=new Array();
  for(i=1;i<7;i++)
    aMonth[i]=new Array(i);

  var dCalDate=new Date(iYear, iMonth-1, 1);
  var iDayOfFirst=dCalDate.getDay();
  var iDaysInMonth=new Date(iYear, iMonth, 0).getDate();
  var iOffsetLast=new Date(iYear, iMonth-1, 0).getDate()-iDayOfFirst+1;
  var iDate = 1;
  var iNext = 1;

  for (d = 0; d < 7; d++)
  aMonth[1][d] = (d<iDayOfFirst)?-(iOffsetLast+d):iDate++;
  for (w = 2; w < 7; w++)
    for (d = 0; d < 7; d++)
    aMonth[w][d] = (iDate<=iDaysInMonth)?iDate++:-(iNext++);
  return aMonth;
}

function fDrawCal(iYear, iMonth, iCellWidth, iDateTextSize)
{
  var WeekDay = new Array("Su","Mo","Tu","We","Th","Fr","Sa");
  var styleTD = " bgcolor='"+gcBG+"' width='"+iCellWidth+"' height = 19 bordercolor='"+gcBG+"' valign='middle' align='center'  style='font:bold "+iDateTextSize+" Courier;";            //Coded by Liming Weng(Victor Won)  email:victorwon@netease.com

  var txt="";
  txt+="
";
  for(i=0; i<7; i++)
    txt+="" + WeekDay[i] + "	";
  txt+="
";

    for (w = 1; w < 7; w++) {
    txt+="
";
    for (d = 0; d < 7; d++) {
      txt+="";
      txt+=" ";
      txt+="	";
    }
    txt+="
";
  }
  return txt;

}

function fUpdateCal(iYear, iMonth)
{
  myMonth = fBuildCal(iYear, iMonth);
  var i = 0;
  for (w = 0; w < 6; w++)
  for (d = 0; d < 7; d++)
    with (cellText[(7*w)+d]) {
      i++;
      if (myMonth[w+1][d]<0) {
        color = gcGray;
        innerText = -myMonth[w+1][d];
      }else{
        color = ((d==0)||(d==6))?"white":"black";
        innerText = myMonth[w+1][d];
      }
    }
  window.event.cancelBubble = true;
}

function fSetYearMon(iYear, iMon)
{
  tbSelMonth.options[iMon-1].selected = true;
  for (i = 0; i < tbSelYear.length; i++)
  if (tbSelYear.options[i].value == iYear)
    tbSelYear.options[i].selected = true;
  fUpdateCal(iYear, iMon);
}

function fPrevMonth()
{
  var iMon = tbSelMonth.value;
  var iYear = tbSelYear.value;

  if (--iMon<1) {
    iMon = 12;
    iYear--;
  }

  fSetYearMon(iYear, iMon);
  window.event.cancelBubble = true;
}

function fNextMonth()
{
  var iMon = tbSelMonth.value;
  var iYear = tbSelYear.value;

  if (++iMon>12) {
    iMon = 1;
    iYear++;
  }

  fSetYearMon(iYear, iMon);
  window.event.cancelBubble = true;
}

function fGetXY(aTag)
{
  var oTmp = aTag;
  var pt = new Point(0,0);
  do {
    pt.x += oTmp.offsetLeft;
    pt.y += oTmp.offsetTop;
    oTmp = oTmp.offsetParent;
  } while(oTmp.tagName!="BODY");
  return pt;
}

function doNuffin()
{
    window.event.cancelBubble = true;
}
<commit_msg>Fixed calendar month selection bug<commit_after>//****************************************************************************
// PopCalendar 4.1, Emailware(please mail&commend me if u like it)
// Originally coded by Liming(Victor) Weng, email: victorwon@netease.com
// Release date: 2000.5.9
// Anyone may modify it to satify his needs, but please leave this comment ahead.
//****************************************************************************

//****************************************************************************
// Extensively modified by Paul Geetz
// Date: August 2002
//****************************************************************************

var gdCtrl = new Object();
var gcGray = "#808080";
var gcToggle = "#ffff00";
var gcBG = "#cccccc";

var gRetCtrl;
var gFormat;
var gdCurDate = new Date();
var giYear = gdCurDate.getFullYear();
var giMonth = gdCurDate.getMonth()+1;
var giDay = gdCurDate.getDate();
var VicPopCal = null;

//****************************************************************************
// Param: popCtrl is the widget beyond which you want this calendar to appear;
//        dateCtrl is the widget into which you want to put the selected date;
//        popCal is the widget to display the calendar;
// i.e.: <input type="text" name="dc" style="text-align:center" readonly>
// <INPUT type="button" value="V" onclick="fPopCalendar(dc,dc,popCal);return false">
//****************************************************************************
function fPopCalendar(popCtrl, dateCtrl, valCtrl, popCal)
{
  if (VicPopCal) {
        fHideCalendar();
        return;
  }
  VicPopCal = popCal;
  gdCtrl = dateCtrl;
  gRetCtrl = valCtrl;
  gFormat = dateCtrl.format;

  var d = new Date();
  d.setTime(gRetCtrl.value);
  fSetYearMon(d.getYear(), d.getMonth()+1);

  var point = fGetXY(popCtrl);
  with (VicPopCal.style) {
    left = point.x;
  top  = point.y+popCtrl.offsetHeight+1;
  visibility = 'visible';
  }

  window.event.cancelBubble = true;
  document.body.attachEvent("onclick", fHideCalendar);
  VicPopCal.focus();
}

function fHideCalendar()
{
 if (VicPopCal) {
     VicPopCal.style.visibility = "hidden";
     VicPopCal = null;
     //document.body.detachEvent("onclick", fHideCalendar);
 }
}

function fSetDate(iYear, iMonth, iDay)
{
  var d = new Date();
  d.setYear(iYear);
  d.setMonth(iMonth-1);
  d.setDate(iDay);

  gdCtrl.value = formatDate(d);
  gRetCtrl.value = d.getTime();

  fHideCalendar();
}

var monthShortNames = new Array('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
var monthLongNames = new Array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December');
var dayNames = new Array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday','Friday', 'Saturday');

function pad(number,X)
{
	X = (!X ? 2 : X);
	number = ""+number;
	while (number.length<X) {
	    number="0"+number;
	}
	return number;
}

function formatDate(date)
{
    var bits = new Array();
    bits['d'] = date.getDate();
    bits['dd'] = pad(date.getDate(),2);
    bits['dddd'] = dayNames[date.getDay()];

    bits['M'] = date.getMonth()+1;
    bits['MM'] = pad(date.getMonth()+1,2);
    bits['MMM'] = monthShortNames[date.getMonth()];
    bits['MMMM'] = monthLongNames[date.getMonth()];
    bits['yyyy'] = date.getYear();
    bits['yy'] = bits['yyyy'].toString().substr(2,2);

    var frm = new String(gFormat);
    var sect;
    for (sect in bits) {
      frm=eval("frm.replace(/\\b"+sect+"\\b/,'"+bits[sect]+"');");
    }

    return frm;

}

function fSetSelected(aCell)
{
  var iOffset = 0;
  var iYear = parseInt(tbSelYear.value);
  var iMonth = parseInt(tbSelMonth.value);

  aCell.bgColor = gcBG;

  with (aCell.children["cellText"])
  {
    var iDay = parseInt(innerText);
    if (color == gcGray)
    {
      if (iDay < 13)
      {
        iOffset = 1;
      }
      else
      {
        iOffset = -1;
      }
    }
    iMonth += iOffset;

    if (iMonth < 1)
    {
      iYear--;
      iMonth = 12;
    }
    else if (iMonth > 12)
    {
      iYear++;
      iMonth = 1;
    }
  }
  fSetDate(iYear, iMonth, iDay);
  window.event.cancelBubble = true;
}

function Point(iX, iY)
{
  this.x = iX;
  this.y = iY;
}

function fBuildCal(iYear, iMonth)
{
  var aMonth=new Array();
  for(i=1;i<7;i++)
    aMonth[i]=new Array(i);

  var dCalDate=new Date(iYear, iMonth-1, 1);
  var iDayOfFirst=dCalDate.getDay();
  var iDaysInMonth=new Date(iYear, iMonth, 0).getDate();
  var iOffsetLast=new Date(iYear, iMonth-1, 0).getDate()-iDayOfFirst+1;
  var iDate = 1;
  var iNext = 1;

  for (d = 0; d < 7; d++)
  aMonth[1][d] = (d<iDayOfFirst)?-(iOffsetLast+d):iDate++;
  for (w = 2; w < 7; w++)
    for (d = 0; d < 7; d++)
    aMonth[w][d] = (iDate<=iDaysInMonth)?iDate++:-(iNext++);
  return aMonth;
}

function fDrawCal(iYear, iMonth, iCellWidth, iDateTextSize)
{
  var WeekDay = new Array("Su","Mo","Tu","We","Th","Fr","Sa");
  var styleTD = " bgcolor='" + gcBG + "' width='" + iCellWidth +
                "' height = 19 bordercolor='" + gcBG +
                "' valign='middle' align='center'  style='font:bold " +
                iDateTextSize + " Courier;";

  // Draw calendar table header
  var txt= "";
  txt += "
";
  for (i = 0; i < 7; i++) {
    txt += "" + WeekDay[i] + "	";
  }
  txt += "
";

  // Draw calendar table
  for (w = 1; w < 7; w++) {
    txt += "
";
    for (d = 0; d < 7; d++) {
      txt += "";
      txt += " ";
      txt += "	";
    }
    txt += "
";
  }
  return txt;
}

function fUpdateCal(iYear, iMonth)
{
  myMonth = fBuildCal(iYear, iMonth);
  var i = 0;
  for (w = 0; w < 6; w++)
  {
    for (d = 0; d < 7; d++)
    {
      with (cellText[(7*w)+d])
      {
        i++;
        if (myMonth[w+1][d] < 0)
        {
          color = gcGray;
          innerText = -myMonth[w+1][d];
        }
        else
        {
          color = ((d==0)||(d==6)) ? "white" : "black";
          innerText = myMonth[w+1][d];
        }
      }
    }
  }
  window.event.cancelBubble = true;
}

function fSetYearMon(iYear, iMon)
{
  tbSelMonth.options[iMon-1].selected = true;
  for (i = 0; i < tbSelYear.length; i++)
  if (tbSelYear.options[i].value == iYear)
    tbSelYear.options[i].selected = true;
  fUpdateCal(iYear, iMon);
}

function fPrevMonth()
{
  var iMon = tbSelMonth.value;
  var iYear = tbSelYear.value;

  if (--iMon<1) {
    iMon = 12;
    iYear--;
  }

  fSetYearMon(iYear, iMon);
  window.event.cancelBubble = true;
}

function fNextMonth()
{
  var iMon = tbSelMonth.value;
  var iYear = tbSelYear.value;

  if (++iMon>12) {
    iMon = 1;
    iYear++;
  }

  fSetYearMon(iYear, iMon);
  window.event.cancelBubble = true;
}

function fGetXY(aTag)
{
  var oTmp = aTag;
  var pt = new Point(0,0);
  do {
    pt.x += oTmp.offsetLeft;
    pt.y += oTmp.offsetTop;
    oTmp = oTmp.offsetParent;
  } while(oTmp.tagName!="BODY");
  return pt;
}

function doNuffin()
{
    window.event.cancelBubble = true;
}
<|endoftext|>


<commit_before>/**
 *	Copyright (C) 2016 3D Repo Ltd
 *
 *	This program is free software: you can redistribute it and/or modify
 *	it under the terms of the GNU Affero General Public License as
 *	published by the Free Software Foundation, either version 3 of the
 *	License, or (at your option) any later version.
 *
 *	This program is distributed in the hope that it will be useful,
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *	GNU Affero General Public License for more details.
 *
 *	You should have received a copy of the GNU Affero General Public License
 *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

(function () {
	"use strict";

	angular.module("3drepo")
		.directive("accountProject", accountProject);

	function accountProject () {
		return {
			restrict: 'E',
			templateUrl: 'accountProject.html',
			scope: {
				account: "=",
				project: "=",
				userAccount: "=",
				onUploadFile: "&",
				uploadedFile: "=",
				projectToUpload: "=",
				onShowPage: "&",
				onSetupDeleteProject: "&",
				quota: "=",
				isAccountAdmin: "=",
				subscriptions: "="
			},
			controller: AccountProjectCtrl,
			controllerAs: 'vm',
			bindToController: true,
			link: function (scope, element) {
				// Cleanup when destroyed
				element.on('$destroy', function(){
					scope.vm.uploadedFileWatch(); // Disable events watch
					scope.vm.projectToUploadFileWatch();

				});
			}
		};
	}

	AccountProjectCtrl.$inject = ["$scope", "$location", "$timeout", "$interval", "$filter", "UtilsService", "serverConfig", "RevisionsService", "NotificationService", "Auth"];

	function AccountProjectCtrl ($scope, $location, $timeout, $interval, $filter, UtilsService, serverConfig, RevisionsService, NotificationService, Auth) {

		var vm = this,
			infoTimeout = 4000,
			isUserAccount = (vm.account === vm.userAccount),
			dialogCloseToId;

		// Init
		vm.selectedFile = null;
		vm.project.name = vm.project.project;
		vm.dialogCloseTo = "accountProjectsOptionsMenu_" + vm.account + "_" + vm.project.name;
		dialogCloseToId = "#" + vm.dialogCloseTo;
		if (vm.project.timestamp !== null) {
			vm.project.timestampPretty = $filter("prettyDate")(vm.project.timestamp, {showSeconds: true});
		}
		vm.project.canUpload = true;
		// Options
		vm.projectOptions = {
			upload: {
				label: "Upload file",
				icon: "cloud_upload",
				hidden: !Auth.hasPermission(serverConfig.permissions.PERM_UPLOAD_FILES, vm.project.permissions)
			},
			team: {
				label: "Team",
				icon: "group",
				// !isUserAccount will be changed to Auth.hasPermission... when someone can pay for other accounts other than their own
				hidden: !isUserAccount
			},
			revision: {
				label: "Revisions",
				icon: "settings_backup_restore",
				hidden: false
			},
			projectsetting: {
				label: "Settings",
				 icon: "settings",
				 hidden: !Auth.hasPermission(serverConfig.permissions.PERM_CHANGE_PROJECT_SETTINGS, vm.project.permissions)
			}
		};
		if(vm.project.timestamp && !vm.project.federate){
			vm.projectOptions.download = {
				label: "Download",
				icon: "cloud_download",
				hidden: !Auth.hasPermission(serverConfig.permissions.PERM_DOWNLOAD_PROJECT, vm.project.permissions)
			};
		}
		vm.uploadButtonDisabled = true;
		vm.projectOptions.delete = {
			label: "Delete",
			icon: "delete",
			hidden: !Auth.hasPermission(serverConfig.permissions.PERM_DELETE_PROJECT, vm.project.permissions),
			color: "#F44336"
		};

		/**
		 * Display file uploading and info and setup watch if status is processing
		 */

		if (vm.project.status === "processing") {
			vm.project.uploading = true;
			vm.showUploading = true;
			vm.showFileUploadInfo = false;
			watchProjectStatus();
		}

		/*
		 * Watch changes in upload file
		 */
		vm.uploadedFileWatch = $scope.$watch("vm.uploadedFile", function () {

			if (angular.isDefined(vm.uploadedFile) && (vm.uploadedFile !== null) && (vm.uploadedFile.project.name === vm.project.name)) {

				console.log("Uploaded file", vm.uploadedFile);
				uploadFileToProject(vm.uploadedFile.file, vm.tag, vm.desc);

			}
		});

		vm.projectToUploadFileWatch = $scope.$watch("vm.projectToUpload", function () {
			if(vm.projectToUpload){

				var names = vm.projectToUpload.name.split('.');

				vm.uploadErrorMessage = null;

				if(names.length === 1){
					vm.uploadErrorMessage = 'Filename must have extension';
					vm.uploadButtonDisabled = true;
				} else if(serverConfig.acceptedFormat.indexOf(names[names.length - 1]) === -1) {
					vm.uploadErrorMessage = 'File format not supported';
					vm.uploadButtonDisabled = true;
				} else {
					vm.uploadButtonDisabled = false;
				}

			}
		});

		/**
		 * Go to the project viewer
		 */
		vm.goToProject = function () {
			if (!vm.project.uploading) {
				if (vm.project.timestamp === null) {
					// No timestamp indicates no model previously uploaded
					if(Auth.hasPermission(serverConfig.permissions.PERM_UPLOAD_FILES, vm.project.permissions)){
						vm.tag = null;
						vm.desc = null;
						vm.selectedFile = null;
						UtilsService.showDialog("uploadProjectDialog.html", $scope, event, true, null, false, dialogCloseToId);
					}
				}
				else {
					$location.path("/" + vm.account + "/" + vm.project.name, "_self").search("page", null);
				}
			}
		};

		/**
		 * Handle project option selection
		 * @param event
		 * @param option
		 */
		vm.doProjectOption = function (event, option) {
			switch (option) {
				case "projectsetting":
					$location.search("proj", vm.project.name);
					$location.search("targetAcct", vm.account);
					vm.onShowPage({page: "projectsetting", callingPage: "repos", data: {tabIndex: 0}});
					break;

				case "upload":
					vm.uploadErrorMessage = null;
					vm.tag = null;
					vm.desc = null;
					UtilsService.showDialog("uploadProjectDialog.html", $scope, event, true, null, false, dialogCloseToId);
					//vm.uploadFile();
					break;

				case "download":
					window.open(
						serverConfig.apiUrl(serverConfig.GET_API, vm.account + "/" + vm.project.name + "/download/latest"),
						'_blank'
					);
					break;

				case "team":
					setupEditTeam(event);
					break;

				case "delete":
					vm.onSetupDeleteProject({event: event, project: vm.project, account: vm.account});
					break;

				case "revision":
					if(!vm.revisions){
						UtilsService.doGet(vm.account + "/" + vm.project.name + "/revisions.json").then(function(response){
							vm.revisions = response.data;
						});
					}
					UtilsService.showDialog("revisionsDialog.html", $scope, event, true, null, false, dialogCloseToId);
					break;
			}
		};

		/**
		 * Go to the billing page to add more licenses
		 */
		vm.setupAddLicenses = function () {
			vm.onShowPage({page: "billing", callingPage: "repos"});
			UtilsService.closeDialog();
		};

		/**
		 * Close the dialog
		 */
		vm.closeDialog = function() {
			UtilsService.closeDialog();
		};

		/**
		 * When users click select file
		 */
		vm.selectFile = function(){
			vm.onUploadFile({project: vm.project});
		};

		/**
		 * When users click upload after selecting
		 */
		vm.uploadFile = function () {
			var revisions;
			vm.uploadErrorMessage = null;

			if(vm.tag && RevisionsService.isTagFormatInValid(vm.tag)){
				vm.uploadErrorMessage = 'Invalid revision name';
			} else {
				UtilsService.doGet(vm.account + "/" + vm.project.name + "/revisions.json").then(function(response){
					revisions = response.data;
					if(vm.tag){
						revisions.forEach(function(rev){
							if(rev.tag === vm.tag){
								vm.uploadErrorMessage = 'Revision name already exists';
							}
						});
					}

					if(!vm.uploadErrorMessage){
						vm.uploadedFile = {project: vm.project, file: vm.projectToUpload};
						vm.closeDialog();
					}
				});
			}
		};

		/**
		* Go to the specified revision
		*/
		vm.goToRevision = function(revId){
			$location.path("/" + vm.account + "/" + vm.project.name + "/" + revId , "_self");
		};

		/**
		 * Upload file/model to project
		 * @param file
		 * @param tag
		 * @param desc
		 */
		function uploadFileToProject(file, tag, desc) {
			var promise,
				formData;

			// Check the quota
			promise = UtilsService.doGet(vm.userAccount + ".json");

			promise.then(function (response) {

				var targetAccount = response.data.accounts.find(function(account){
					return account.account === vm.account;
				});

				var quota = targetAccount.quota;
				vm.targetAccountQuota = quota;

				if (file.size > (quota.spaceLimit - quota.spaceUsed)) {
					// Show the over quota dialog
					UtilsService.showDialog("overQuotaDialog.html", $scope, null, true);
				}
				else {
					vm.project.uploading = true;
					vm.showUploading = true;
					vm.showFileUploadInfo = false;

					// Check for file size limit
					if (file.size > serverConfig.uploadSizeLimit) {
						$timeout(function () {
							vm.showUploading = false;
							vm.showFileUploadInfo = true;
							vm.fileUploadInfo = "File exceeds size limit";
							$timeout(function () {
								vm.project.uploading = false;
							}, infoTimeout);
						});
					}
					else {

						vm.uploadFileName = file.name;

						formData = new FormData();
						formData.append("file", file);

						if(tag){
							formData.append('tag', tag);
						}

						if(desc){
							formData.append('desc', desc);
						}

						promise = UtilsService.doPost(formData, vm.account + "/" + vm.project.name + "/upload", {'Content-Type': undefined});

						promise.then(function (response) {
							console.log("uploadModel", response);
							if ((response.status === 400) || (response.status === 404)) {
								// Upload error
								vm.fileUploadInfo = UtilsService.getErrorMessage(response.data);
								vm.showUploading = false;
								vm.showFileUploadInfo = true;
								$timeout(function () {
									vm.project.uploading = false;
								}, infoTimeout);
							}
							else {
								console.log("Polling upload!");
								watchProjectStatus();
							}
						});
					}
				}
			});
		}

		/**
		 * Watch file upload status
		 */
		function watchProjectStatus(){
			NotificationService.subscribe.projectStatusChanged(vm.account, vm.project.project, function(data){
				console.log('upload status changed',  data);
				if ((data.status === "ok") || (data.status === "failed")) {
					if (data.status === "ok") {
						vm.project.timestamp = new Date();
						vm.project.timestampPretty = $filter("prettyDate")(vm.project.timestamp, {showSeconds: true});
						vm.fileUploadInfo = "Uploaded";
						// clear revisions cache
						vm.revisions = null;
					}

					//status=ok can have an error message too
					if (data.hasOwnProperty("errorReason")) {
						vm.fileUploadInfo = data.errorReason.message;
					} else if (data.status === "failed") {
						vm.fileUploadInfo = "Failed to upload file";
					}

					vm.showUploading = false;
					vm.showFileUploadInfo = true;
					$scope.$apply();
					$timeout(function () {
						vm.project.uploading = false;
					}, infoTimeout);

					NotificationService.unsubscribe.projectStatusChanged(vm.account, vm.project.project);
				}
			});

			$scope.$on('$destroy', function(){
				NotificationService.unsubscribe.projectStatusChanged(vm.account, vm.project.project);
			});
		}

		/**
		 * Set up team of project
		 *
		 * @param {Object} event
		 */
		function setupEditTeam (event) {
			vm.item = vm.project;
			UtilsService.showDialog("teamDialog.html", $scope, event, true, null, false, dialogCloseToId);
		}
	}
}());
<commit_msg>ISSUE #311 remove vm.selectedFile as it wasn't used anywhere. also remove selected file tag if the file is erroneous<commit_after>/**
 *	Copyright (C) 2016 3D Repo Ltd
 *
 *	This program is free software: you can redistribute it and/or modify
 *	it under the terms of the GNU Affero General Public License as
 *	published by the Free Software Foundation, either version 3 of the
 *	License, or (at your option) any later version.
 *
 *	This program is distributed in the hope that it will be useful,
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *	GNU Affero General Public License for more details.
 *
 *	You should have received a copy of the GNU Affero General Public License
 *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

(function () {
	"use strict";

	angular.module("3drepo")
		.directive("accountProject", accountProject);

	function accountProject () {
		return {
			restrict: 'E',
			templateUrl: 'accountProject.html',
			scope: {
				account: "=",
				project: "=",
				userAccount: "=",
				onUploadFile: "&",
				uploadedFile: "=",
				projectToUpload: "=",
				onShowPage: "&",
				onSetupDeleteProject: "&",
				quota: "=",
				isAccountAdmin: "=",
				subscriptions: "="
			},
			controller: AccountProjectCtrl,
			controllerAs: 'vm',
			bindToController: true,
			link: function (scope, element) {
				// Cleanup when destroyed
				element.on('$destroy', function(){
					scope.vm.uploadedFileWatch(); // Disable events watch
					scope.vm.projectToUploadFileWatch();

				});
			}
		};
	}

	AccountProjectCtrl.$inject = ["$scope", "$location", "$timeout", "$interval", "$filter", "UtilsService", "serverConfig", "RevisionsService", "NotificationService", "Auth"];

	function AccountProjectCtrl ($scope, $location, $timeout, $interval, $filter, UtilsService, serverConfig, RevisionsService, NotificationService, Auth) {

		var vm = this,
			infoTimeout = 4000,
			isUserAccount = (vm.account === vm.userAccount),
			dialogCloseToId;

		// Init
		vm.projectToUpload = null;
		vm.project.name = vm.project.project;
		vm.dialogCloseTo = "accountProjectsOptionsMenu_" + vm.account + "_" + vm.project.name;
		dialogCloseToId = "#" + vm.dialogCloseTo;
		if (vm.project.timestamp !== null) {
			vm.project.timestampPretty = $filter("prettyDate")(vm.project.timestamp, {showSeconds: true});
		}
		vm.project.canUpload = true;
		// Options
		vm.projectOptions = {
			upload: {
				label: "Upload file",
				icon: "cloud_upload",
				hidden: !Auth.hasPermission(serverConfig.permissions.PERM_UPLOAD_FILES, vm.project.permissions)
			},
			team: {
				label: "Team",
				icon: "group",
				// !isUserAccount will be changed to Auth.hasPermission... when someone can pay for other accounts other than their own
				hidden: !isUserAccount
			},
			revision: {
				label: "Revisions",
				icon: "settings_backup_restore",
				hidden: false
			},
			projectsetting: {
				label: "Settings",
				 icon: "settings",
				 hidden: !Auth.hasPermission(serverConfig.permissions.PERM_CHANGE_PROJECT_SETTINGS, vm.project.permissions)
			}
		};
		if(vm.project.timestamp && !vm.project.federate){
			vm.projectOptions.download = {
				label: "Download",
				icon: "cloud_download",
				hidden: !Auth.hasPermission(serverConfig.permissions.PERM_DOWNLOAD_PROJECT, vm.project.permissions)
			};
		}
		vm.uploadButtonDisabled = true;
		vm.projectOptions.delete = {
			label: "Delete",
			icon: "delete",
			hidden: !Auth.hasPermission(serverConfig.permissions.PERM_DELETE_PROJECT, vm.project.permissions),
			color: "#F44336"
		};

		/**
		 * Display file uploading and info and setup watch if status is processing
		 */

		if (vm.project.status === "processing") {
			vm.project.uploading = true;
			vm.showUploading = true;
			vm.showFileUploadInfo = false;
			watchProjectStatus();
		}

		/*
		 * Watch changes in upload file
		 */
		vm.uploadedFileWatch = $scope.$watch("vm.uploadedFile", function () {

			if (angular.isDefined(vm.uploadedFile) && (vm.uploadedFile !== null) && (vm.uploadedFile.project.name === vm.project.name)) {

				console.log("Uploaded file", vm.uploadedFile);
				uploadFileToProject(vm.uploadedFile.file, vm.tag, vm.desc);

			}
		});

		vm.projectToUploadFileWatch = $scope.$watch("vm.projectToUpload", function () {
			if(vm.projectToUpload){

				var names = vm.projectToUpload.name.split('.');

				vm.uploadErrorMessage = null;

				if(names.length === 1){
					vm.uploadErrorMessage = 'Filename must have extension';
					vm.projectToUpload = null;
					vm.uploadButtonDisabled = true;
				} else if(serverConfig.acceptedFormat.indexOf(names[names.length - 1]) === -1) {
					vm.uploadErrorMessage = 'File format not supported';
					vm.projectToUpload = null;
					vm.uploadButtonDisabled = true;
				} else {
					vm.uploadButtonDisabled = false;
				}

			}
		});

		/**
		 * Go to the project viewer
		 */
		vm.goToProject = function () {
			if (!vm.project.uploading) {
				if (vm.project.timestamp === null) {
					// No timestamp indicates no model previously uploaded
					if(Auth.hasPermission(serverConfig.permissions.PERM_UPLOAD_FILES, vm.project.permissions)){
						vm.tag = null;
						vm.desc = null;
						vm.projectToUpload = null;
						UtilsService.showDialog("uploadProjectDialog.html", $scope, event, true, null, false, dialogCloseToId);
					}
				}
				else {
					$location.path("/" + vm.account + "/" + vm.project.name, "_self").search("page", null);
				}
			}
		};

		/**
		 * Handle project option selection
		 * @param event
		 * @param option
		 */
		vm.doProjectOption = function (event, option) {
			switch (option) {
				case "projectsetting":
					$location.search("proj", vm.project.name);
					$location.search("targetAcct", vm.account);
					vm.onShowPage({page: "projectsetting", callingPage: "repos", data: {tabIndex: 0}});
					break;

				case "upload":
					vm.uploadErrorMessage = null;
					vm.tag = null;
					vm.desc = null;
					UtilsService.showDialog("uploadProjectDialog.html", $scope, event, true, null, false, dialogCloseToId);
					//vm.uploadFile();
					break;

				case "download":
					window.open(
						serverConfig.apiUrl(serverConfig.GET_API, vm.account + "/" + vm.project.name + "/download/latest"),
						'_blank'
					);
					break;

				case "team":
					setupEditTeam(event);
					break;

				case "delete":
					vm.onSetupDeleteProject({event: event, project: vm.project, account: vm.account});
					break;

				case "revision":
					if(!vm.revisions){
						UtilsService.doGet(vm.account + "/" + vm.project.name + "/revisions.json").then(function(response){
							vm.revisions = response.data;
						});
					}
					UtilsService.showDialog("revisionsDialog.html", $scope, event, true, null, false, dialogCloseToId);
					break;
			}
		};

		/**
		 * Go to the billing page to add more licenses
		 */
		vm.setupAddLicenses = function () {
			vm.onShowPage({page: "billing", callingPage: "repos"});
			UtilsService.closeDialog();
		};

		/**
		 * Close the dialog
		 */
		vm.closeDialog = function() {
			UtilsService.closeDialog();
		};

		/**
		 * When users click select file
		 */
		vm.selectFile = function(){
			vm.onUploadFile({project: vm.project});
		};

		/**
		 * When users click upload after selecting
		 */
		vm.uploadFile = function () {
			var revisions;
			vm.uploadErrorMessage = null;

			if(vm.tag && RevisionsService.isTagFormatInValid(vm.tag)){
				vm.uploadErrorMessage = 'Invalid revision name';
			} else {
				UtilsService.doGet(vm.account + "/" + vm.project.name + "/revisions.json").then(function(response){
					revisions = response.data;
					if(vm.tag){
						revisions.forEach(function(rev){
							if(rev.tag === vm.tag){
								vm.uploadErrorMessage = 'Revision name already exists';
							}
						});
					}

					if(!vm.uploadErrorMessage){
						vm.uploadedFile = {project: vm.project, file: vm.projectToUpload};
						vm.closeDialog();
					}
				});
			}
		};

		/**
		* Go to the specified revision
		*/
		vm.goToRevision = function(revId){
			$location.path("/" + vm.account + "/" + vm.project.name + "/" + revId , "_self");
		};

		/**
		 * Upload file/model to project
		 * @param file
		 * @param tag
		 * @param desc
		 */
		function uploadFileToProject(file, tag, desc) {
			var promise,
				formData;

			// Check the quota
			promise = UtilsService.doGet(vm.userAccount + ".json");

			promise.then(function (response) {

				var targetAccount = response.data.accounts.find(function(account){
					return account.account === vm.account;
				});

				var quota = targetAccount.quota;
				vm.targetAccountQuota = quota;

				if (file.size > (quota.spaceLimit - quota.spaceUsed)) {
					// Show the over quota dialog
					UtilsService.showDialog("overQuotaDialog.html", $scope, null, true);
				}
				else {
					vm.project.uploading = true;
					vm.showUploading = true;
					vm.showFileUploadInfo = false;

					// Check for file size limit
					if (file.size > serverConfig.uploadSizeLimit) {
						$timeout(function () {
							vm.showUploading = false;
							vm.showFileUploadInfo = true;
							vm.fileUploadInfo = "File exceeds size limit";
							$timeout(function () {
								vm.project.uploading = false;
							}, infoTimeout);
						});
					}
					else {

						vm.uploadFileName = file.name;

						formData = new FormData();
						formData.append("file", file);

						if(tag){
							formData.append('tag', tag);
						}

						if(desc){
							formData.append('desc', desc);
						}

						promise = UtilsService.doPost(formData, vm.account + "/" + vm.project.name + "/upload", {'Content-Type': undefined});

						promise.then(function (response) {
							console.log("uploadModel", response);
							if ((response.status === 400) || (response.status === 404)) {
								// Upload error
								vm.fileUploadInfo = UtilsService.getErrorMessage(response.data);
								vm.showUploading = false;
								vm.showFileUploadInfo = true;
								$timeout(function () {
									vm.project.uploading = false;
								}, infoTimeout);
							}
							else {
								console.log("Polling upload!");
								watchProjectStatus();
							}
						});
					}
				}
			});
		}

		/**
		 * Watch file upload status
		 */
		function watchProjectStatus(){
			NotificationService.subscribe.projectStatusChanged(vm.account, vm.project.project, function(data){
				console.log('upload status changed',  data);
				if ((data.status === "ok") || (data.status === "failed")) {
					if (data.status === "ok") {
						vm.project.timestamp = new Date();
						vm.project.timestampPretty = $filter("prettyDate")(vm.project.timestamp, {showSeconds: true});
						vm.fileUploadInfo = "Uploaded";
						// clear revisions cache
						vm.revisions = null;
					}

					//status=ok can have an error message too
					if (data.hasOwnProperty("errorReason")) {
						vm.fileUploadInfo = data.errorReason.message;
					} else if (data.status === "failed") {
						vm.fileUploadInfo = "Failed to upload file";
					}

					vm.showUploading = false;
					vm.showFileUploadInfo = true;
					$scope.$apply();
					$timeout(function () {
						vm.project.uploading = false;
					}, infoTimeout);

					NotificationService.unsubscribe.projectStatusChanged(vm.account, vm.project.project);
				}
			});

			$scope.$on('$destroy', function(){
				NotificationService.unsubscribe.projectStatusChanged(vm.account, vm.project.project);
			});
		}

		/**
		 * Set up team of project
		 *
		 * @param {Object} event
		 */
		function setupEditTeam (event) {
			vm.item = vm.project;
			UtilsService.showDialog("teamDialog.html", $scope, event, true, null, false, dialogCloseToId);
		}
	}
}());
<|endoftext|>


<commit_before><commit_msg>Test user controller (#94)<commit_after>describe("Team Controller", function() {
    beforeEach(module("teamform-user-app"));

    var $controller, $firebaseObject, $firebaseArray;

    beforeEach(inject(function(_$controller_, _$firebaseObject_, _$firebaseArray_) {
        // The injector unwraps the underscores (_) from around the parameter names when matching
        $controller = _$controller_;
        $firebaseObject = _$firebaseObject_;
        $firebaseArray = _$firebaseArray_;
    }));

    afterEach(function() {
        firebase.app().delete();
    });

    describe("$scope.changeCurrentTeamSize", function() {
        var $scope, controller;

        beforeEach(function() {
            $scope = {};
            controller = $controller("UserCtrl", {$scope: $scope, $firebaseObject: $firebaseObject, $firebaseArray: $firebaseArray});
        });
    });
});
<|endoftext|>


<commit_before>/* eslint-disable */
export default function initHsBeacon() {
  !function (e, o, n) { window.HSCW = o, window.HS = n, n.beacon = n.beacon || {}; var t = n.beacon; t.userConfig = {}, t.readyQueue = [], t.config = function (e) { this.userConfig = e; }, t.ready = function (e) { this.readyQueue.push(e); }, o.config = { docs:{ enabled:!1, baseUrl:'' }, contact:{ enabled:!0, formId:'f48f821c-fb20-11e5-a329-0ee2467769ff' } }; var r = e.getElementsByTagName('script')[0], c = e.createElement('script'); c.type = 'text/javascript', c.async = !0, c.src = 'https://djtflbt20bdde.cloudfront.net/', r.parentNode.insertBefore(c, r); }(document, window.HSCW || {}, window.HS || {});

  HS.beacon.config({
    modal: true,
    attachment: true,
    instructions: 'Please make sure to include a link if your question involves a specific repo, build or job.'
  });
}
<commit_msg>Change Help Scout beacon to show subject field<commit_after>/* eslint-disable */
export default function initHsBeacon() {
  !function (e, o, n) { window.HSCW = o, window.HS = n, n.beacon = n.beacon || {}; var t = n.beacon; t.userConfig = {}, t.readyQueue = [], t.config = function (e) { this.userConfig = e; }, t.ready = function (e) { this.readyQueue.push(e); }, o.config = { docs:{ enabled:!1, baseUrl:'' }, contact:{ enabled:!0, formId:'f48f821c-fb20-11e5-a329-0ee2467769ff' } }; var r = e.getElementsByTagName('script')[0], c = e.createElement('script'); c.type = 'text/javascript', c.async = !0, c.src = 'https://djtflbt20bdde.cloudfront.net/', r.parentNode.insertBefore(c, r); }(document, window.HSCW || {}, window.HS || {});

  HS.beacon.config({
    modal: true,
    attachment: true,
    instructions: 'Please make sure to include a link if your question involves a specific repo, build or job.',
    showSubject: true
  });
}
<|endoftext|>


<commit_before>module.exports = {
  components: {
    'overview-nav': require('./nav'),
    'overview-footer': require('./footer'),
    'error': require('../notification')
  },

  data: function() {
    return {
      store: window.Store.shareList,
      uiState: {
        selected: []
      }
    }
  },

  computed: {
    listHasItems: function() {
      return this.uiState.selected.length > 0;
    }
  },

  created: function() {
    this.store.actions.status(() => {
      this.store.actions.poll().start();
    });

  },

  destroyed: function() {
    this.store.actions.poll().stop();
  },

  methods: {
    toggleAll: function() {
      if(this.listHasItems) {
        this.uiState.selected = [];
      } else {
        this.store.shares.forEach((share) => {
          this.uiState.selected.push(share.id);
        });
      }
    },
    toggleItem: function(id) {
      let index = this.uiState.selected.indexOf(id);
      if(index >= 0) {
        this.uiState.selected.splice(index, 1);
      } else {
        this.uiState.selected.push(id);
      }
    }
  },

  template: `
<transition name="fade">

    <error class="error-stream alert alert-danger alert-dismissible" v-bind:notes="store.errors" v-bind:dismiss-action="store.actions.clearErrors"></error>

    <overview-nav></overview-nav>

Overview

                <input type="checkbox" v-model="listHasItems" v-on:change="toggleAll()" class="checkbox" id="selectAll">
                #
                Status

                Uptime
                Restarts
                Peers
                Shared

                    Start
                    Stop
                    Restart

                    Delete

                  <input v-model="uiState.selected"
                    v-on:change="toggleItem(share.id)"
                    v-bind:value="share.id"
                    type="checkbox"
                    class="checkbox">

                {{share.id}}

                {{share.meta.uptimeReadable}}
                {{share.meta.numRestarts}}
                {{share.meta.farmerState.totalPeers}}
                {{share.meta.farmerState.spaceUsed}} ({{share.meta.farmerState.percentUsed}}) %)

                    Start
                    Stop
                    Restart
                    Logs
                    Edit

                    Delete

                Add Drive to Get Started

    <overview-footer></overview-footer>

</transition>
  `
};
<commit_msg>Add link to empty overview state<commit_after>module.exports = {
  components: {
    'overview-nav': require('./nav'),
    'overview-footer': require('./footer'),
    'error': require('../notification')
  },

  data: function() {
    return {
      store: window.Store.shareList,
      uiState: {
        selected: []
      }
    }
  },

  computed: {
    listHasItems: function() {
      return this.uiState.selected.length > 0;
    }
  },

  created: function() {
    this.store.actions.status(() => {
      this.store.actions.poll().start();
    });

  },

  destroyed: function() {
    this.store.actions.poll().stop();
  },

  methods: {
    toggleAll: function() {
      if(this.listHasItems) {
        this.uiState.selected = [];
      } else {
        this.store.shares.forEach((share) => {
          this.uiState.selected.push(share.id);
        });
      }
    },
    toggleItem: function(id) {
      let index = this.uiState.selected.indexOf(id);
      if(index >= 0) {
        this.uiState.selected.splice(index, 1);
      } else {
        this.uiState.selected.push(id);
      }
    }
  },

  template: `
<transition name="fade">

    <error class="error-stream alert alert-danger alert-dismissible" v-bind:notes="store.errors" v-bind:dismiss-action="store.actions.clearErrors"></error>

    <overview-nav></overview-nav>

Overview

                <input type="checkbox" v-model="listHasItems" v-on:change="toggleAll()" class="checkbox" id="selectAll">
                #
                Status

                Uptime
                Restarts
                Peers
                Shared

                    Start
                    Stop
                    Restart

                    Delete

                  <input v-model="uiState.selected"
                    v-on:change="toggleItem(share.id)"
                    v-bind:value="share.id"
                    type="checkbox"
                    class="checkbox">

                {{share.id}}

                {{share.meta.uptimeReadable}}
                {{share.meta.numRestarts}}
                {{share.meta.farmerState.totalPeers}}
                {{share.meta.farmerState.spaceUsed}} ({{share.meta.farmerState.percentUsed}}) %)

                    Start
                    Stop
                    Restart
                    Logs
                    Edit

                    Delete

                <router-link :to="{path: '/share-wizard/wizard1'}">Add Drive to Get Started</router-link>

    <overview-footer></overview-footer>

</transition>
  `
};
<|endoftext|>


<commit_before>/* global Backbone, _ , i18n, $*/
var form_helper = require('../lib/form_helper');
var RefSvc = require('../service/ServiceReferential');
var ErrorHelper = require('../lib/error_helper');

var template = require('./templates/reference');
module.exports = Backbone.View.extend({
	tagName: 'tr',
	template: template,
	/*Best practice for debugging to name the anonymous function. In order to see it in the stack trace.*/
	initialize: function initializeReferenceView() {
		this.isEdit = false;
		this.listenTo(this.model, 'validated:valid', this.modelValid);
		this.listenTo(this.model, 'validated:invalid', this.modelInValid);
		this.listenTo(this.model, 'change:errors', this.render);
		this.listenTo(this.model, 'save:success', this.saveSuccess);
		this.listenTo(this.model, 'save:error', this.saveError);
	},
	events: {
		"click button#edit": "toogleEditMode",
		"click button[type='submit']": 'save'
	},
	toogleEditMode: function toogleEditMode(event) {
		event.preventDefault();
		this.isEdit = !this.isEdit;
		this.render();
	},
	save: function saveReferenceChange(event) {
		event.preventDefault();
		//Bind the model on the form.
		form_helper.formModelBinder({
			inputs: $('input', this.$el)
		}, this.model);
		this.model.validate();
	},
	saveSuccess: function refSaveSuccess(model) {
		//console.log(model);
		Backbone.Notification.addNotification({
			type: 'success',
			message: i18n.t('reference.save.success')
		}, true);
	},
	saveError: function refSaveError(response) {
		ErrorHelper.manageResponseErrors(response, {isDisplay: true});
	},
	//When there is a validation problem, we put the errors into the model in order to display them in the form.
	modelInValid: function refModelInValid(model, errors) {
		this.model.setErrors(errors);
	},

	//When the model is valid, the  process continue.
	modelValid: function refModelValid() {
		var refView = this;
		this.model.unsetErrors();
		RefSvc.save(this.model.toJSON())
              .then(refView.saveSuccess)
              .catch(refView.saveError);
	},
	render: function renderVirtualMachine() {
		this.$el.html(
			this.template(
				_.extend(
					this.model.toJSON(), {
						isEdit: this.isEdit
					})
			));
		return this;
	}
});<commit_msg>Few correction on promise.<commit_after>/* global Backbone, _ , i18n, $*/
var form_helper = require('../lib/form_helper');
var RefSvc = require('../service/ServiceReferential');
var ErrorHelper = require('../lib/error_helper');

var template = require('./templates/reference');
module.exports = Backbone.View.extend({
	tagName: 'tr',
	template: template,
	/*Best practice for debugging to name the anonymous function. In order to see it in the stack trace.*/
	initialize: function initializeReferenceView() {
		this.isEdit = false;
		this.listenTo(this.model, 'validated:valid', this.modelValid);
		this.listenTo(this.model, 'validated:invalid', this.modelInValid);
		this.listenTo(this.model, 'change:errors', this.render);
		this.listenTo(this.model, 'save:success', this.saveSuccess);
		this.listenTo(this.model, 'save:error', this.saveError);
	},
	events: {
		"click button#edit": "toogleEditMode",
		"click button[type='submit']": 'save'
	},
	toogleEditMode: function toogleEditMode(event) {
		event.preventDefault();
		this.isEdit = !this.isEdit;
		this.render();
	},
	save: function saveReferenceChange(event) {
		event.preventDefault();
		//Bind the model on the form.
		form_helper.formModelBinder({
			inputs: $('input', this.$el)
		}, this.model);
		// require("../lib/model-validation-promise").validate(this.model).then(function(success) {
		// 	console.log(success);
		// }).catch(function(error){console.error(error);});
		this.model.validate();
	},
	saveSuccess: function refSaveSuccess(model) {
		//console.log(model);
		Backbone.Notification.addNotification({
			type: 'success',
			message: i18n.t('reference.save.success')
		}, true);
	},
	saveError: function refSaveError(response) {
		ErrorHelper.manageResponseErrors(response, {
			isDisplay: true
		});
	},
	//When there is a validation problem, we put the errors into the model in order to display them in the form.
	modelInValid: function refModelInValid(model, errors) {
		this.model.setErrors(errors);
	},

	//When the model is valid, the  process continue.
	modelValid: function refModelValid() {
		var refView = this;
		this.model.unsetErrors();
		RefSvc.save(this.model.toJSON()).then(refView.saveSuccess).catch(refView.saveError);
	},
	render: function renderVirtualMachine() {
		this.$el.html(
			this.template(
				_.extend(
					this.model.toJSON(), {
						isEdit: this.isEdit
					})
			));
		return this;
	}
});<|endoftext|>


<commit_before>/* global menuJson:false */
window.addEventListener('WebComponentsReady', function() {
  // insert header after body-tag
  var header = document.createElement('uq-minimal-header');
  header.showIAButton = true;

  document.body.insertBefore(header, document.body.children[0]);

  // insert menu after header
  var menu = document.createElement('uql-menu');
  menu.menuJson = menuJson;

  document.body.insertBefore(menu, header);
  //header.appendChild(menu);

  header.addEventListener("menu-clicked", function(event) {
    menu.toggleMenu();
  });

  // insert footer before body-tag
  var footer = document.createElement('uq-minimal-footer');
  document.body.appendChild(footer);
});<commit_msg>libwww menu display<commit_after>/* global menuJson:false */
window.addEventListener('WebComponentsReady', function() {
  //original document
  var firstElement = document.body.children[0];

  // insert header after body-tag
  var header = document.createElement('uq-minimal-header');
  header.showIAButton = true;
  document.body.insertBefore(header, firstElement);

  // insert menu after header
  var menu = document.createElement('uql-menu');
  menu.menuJson = menuJson;
  document.body.insertBefore(menu, firstElement);
  //header.appendChild(menu);

  header.addEventListener("menu-clicked", function(event) {
    menu.toggleMenu();
  });

  // insert footer before body-tag
  var footer = document.createElement('uq-minimal-footer');
  document.body.appendChild(footer);
});<|endoftext|>


<commit_before>var primoViewHasLoaded = setInterval(function() {
    //wait for primo's angular to load itself (eg replaces primo-explore contents with angular contents, then insert header)
    if (document.querySelector('noscript') === null || typeof(document.querySelector('noscript')) === 'undefined' ) {
        clearInterval(primoViewHasLoaded);
        loadReusableComponents();
    }
}, 50);

function loadReusableComponents() {
    // insert elements, even before Polymer is loaded
    // first element of the original document
    var firstElement = document.querySelector('primo-explore');
    // var firstElement = document.body; //.children[0];

    // insert header inside primo's view
    var header = document.createElement('uq-minimal-header');
    header.setAttribute("show-login-button", "false");
    firstElement.insertBefore(header, firstElement.firstChild);

    // insert alerts inside primo's view
    var alerts = document.createElement('uqlibrary-alerts');
    firstElement.insertBefore(alerts, firstElement.firstChild);

    // while new PrimoUI has infinite scrolling, do not include footer

    // // insert sub footer before body-tag
    // var subFooter = document.createElement('uql-connect-footer');
    // document.body.appendChild(subFooter);
    //
    // // insert footer before body-tag
    // var footer = document.createElement('uq-minimal-footer');
    // document.body.appendChild(footer);

    window.addEventListener('WebComponentsReady', function() {
        // when polymer is ready - configure elements
        // header.showLoginButton = false;

        //move user area up into header
        document.querySelector('uq-minimal-header').appendChild(document.querySelector('prm-user-area'));

    });
}

// enable GTM
(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
    new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
    j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
    'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-W4KK37');

<commit_msg>fixing animation [#141568463]<commit_after>var primoViewHasLoaded = setInterval(function() {
    //wait for primo's angular to load itself (eg replaces primo-explore contents with angular contents, then insert header)
    if (document.querySelector('noscript') === null || typeof(document.querySelector('noscript')) === 'undefined' ) {
        clearInterval(primoViewHasLoaded);
        insertReusableComponents();
    }
}, 50);

function insertReusableComponents() {
    // insert elements, even before Polymer is loaded
    // first element of the original document
    var firstElement = document.querySelector('primo-explore');

    // insert header inside primo's view
    var header = document.createElement('uq-minimal-header');
    header.setAttribute("show-login-button", "false");
    firstElement.insertBefore(header, firstElement.firstChild);

    // insert alerts inside primo's view
    var alerts = document.createElement('uqlibrary-alerts');
    firstElement.insertBefore(alerts, firstElement.firstChild);

    // move user area into header, by this time Polymer and Angular should be loaded
    var header = document.querySelector('uq-minimal-header');
    var userArea = document.querySelector('prm-user-area');
    if (header && userArea) {
        header.appendChild(userArea);
    }

    // while new PrimoUI has infinite scrolling, do not include footer
    // // insert sub footer before body-tag
    // var subFooter = document.createElement('uql-connect-footer');
    // document.body.appendChild(subFooter);
    //
    // // insert footer before body-tag
    // var footer = document.createElement('uq-minimal-footer');
    // document.body.appendChild(footer);
}

// enable GTM
(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
    new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
    j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
    'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-W4KK37');

<|endoftext|>


<commit_before>Collection={
	artists:[],
	albums:[],
	songs:[],
	artistsById:{},
	albumsById:{},
	loaded:false,
	loading:false,
	loadedListeners:[],
	load:function(ready){
		if(ready){
			Collection.loadedListeners.push(ready);
		}
		if(!Collection.loading){
			Collection.loading=true;
			$.ajax({
				url: OC.linkTo('media','ajax/api.php')+'?action=get_collection',
				dataType: 'json',
				success: function(data){
					//normalize the data
					for(var i=0;i<data.artists.length;i++){
						var artist=data.artists[i];
						var artistData={name:artist.artist_name,songs:[],albums:[]};
						Collection.artistsById[artist.artist_id]=artistData;
						Collection.artists.push(artistData);
					}
					for(var i=0;i<data.albums.length;i++){
						var album=data.albums[i];
						var artistName=Collection.artistsById[album.album_artist].name;
						var albumData={name:album.album_name,artist:artistName,songs:[]};
						Collection.albumsById[album.album_id]=albumData;
						Collection.albums.push(albumData);
						Collection.artistsById[album.album_artist].albums.push(albumData);
					}
					for(var i=0;i<data.songs.length;i++){
						var song=data.songs[i];
						if(Collection.artistsById[song.song_artist] && Collection.albumsById[song.song_album]){
							var songData={
								name:song.song_name,
								artist:Collection.artistsById[song.song_artist].name,
								album:Collection.albumsById[song.song_album].name,
								lastPlayed:song.song_lastplayed,
								length:song.song_length,
								path:song.song_path,
								playCount:song.song_playcount,
							};
							Collection.songs.push(songData);
							Collection.artistsById[song.song_artist].songs.push(songData);
							Collection.albumsById[song.song_album].songs.push(songData);
						}
					}

					Collection.artists.sort(function(a,b){
						return a.name.localeCompare(b.name);
					});

					Collection.loaded=true;
					Collection.loading=false;
					for(var i=0;i<Collection.loadedListeners.length;i++){
						Collection.loadedListeners[i]();
					}
					if(data.songs.length==0){
						$('#scan input.start').val(t('media','Scan Collection'));
						$('#scan input.start').click();
					}

				}
			});
		}
	},
	display:function(){
		if(Collection.parent){
			Collection.parent.show();
		}
		if(!Collection.loaded){
			Collection.load(Collection.display)
		}else{
			if(Collection.parent){
				Collection.parent.find('tr:not(.template)').remove();
				var template=Collection.parent.find('tr.template');
				var lastArtist='';
				var lastAlbum='';
				$.each(Collection.artists,function(i,artist){
					if(artist.name && artist.songs.length>0){
						var tr=template.clone().removeClass('template');
						if(artist.songs.length>1){
							tr.find('td.title a').text(artist.songs.length+' '+t('media','songs'));
							tr.find('td.album a').text(artist.albums.length+' '+t('media','albums'));
						}else{
							tr.find('td.title a').text(artist.songs[0].name);
							tr.find('td.album a').text(artist.albums[0].name);
						}
						tr.find('td.artist a').text(artist.name);
						tr.data('artistData',artist);
						tr.find('td.artist a').click(function(event){
							event.preventDefault();
							PlayList.add(artist);
							PlayList.play(0);
							Collection.parent.find('tr').removeClass('active');
							$('tr[data-artist="'+artist.name+'"]').addClass('active');
						});
						if(artist.songs.length>1){
							var expander=$('>');
							expander.data('expanded',false);
							expander.click(function(event){
								var tr=$(this).parent().parent();
								if(expander.data('expanded')){
									Collection.hideArtist(tr.data('artist'));
								}else{
									Collection.showArtist(tr.data('artist'));
								}
							});
						}
						tr.find('td.artist').addClass('buttons');
						Collection.addButtons(tr,artist);
						tr.children('td.artist').append(expander);
						tr.attr('data-artist',artist.name);
						Collection.parent.find('tbody').append(tr);
					}
				});
			}
		}
	},
	showArtist:function(artist){
		var tr=Collection.parent.find('tr[data-artist="'+artist+'"]');
		var nextRow=tr.next();
		var artist=tr.data('artistData');
		var first=true;
		$.each(artist.albums,function(j,album){
			$.each(album.songs,function(i,song){
				if(first){
					newRow=tr;
				}else{
					var newRow=tr.clone();
					newRow.find('td.artist').text('');
					newRow.find('.expander').remove();
				}
				newRow.find('td.album .expander').remove();
				if(i==0){
					newRow.find('td.album a').text(album.name);
					newRow.find('td.album a').click(function(event){
						event.preventDefault();
						PlayList.add(album);
						PlayList.play(0);
						Collection.parent.find('tr').removeClass('active');
						$('tr[data-album="'+album.name+'"]').addClass('active');
					});
					if(album.songs.length>1){
						var expander=$('v ');
						expander.data('expanded',true);
						expander.click(function(event){
							var tr=$(this).parent().parent();
							if(expander.data('expanded')) {
								Collection.hideAlbum(tr.data('artist'),tr.data('album'));
							} else {
								Collection.showAlbum(tr.data('artist'),tr.data('album'));
							}
						});
						newRow.children('td.album').append(expander);
					}
					Collection.addButtons(newRow,album);
				} else {
					newRow.find('td.album a').text('');
					Collection.addButtons(newRow,song);
				}
				newRow.find('td.title a').text(song.name);
				newRow.find('td.title a').click(function(event){
					event.preventDefault();
					PlayList.add(song);
					PlayList.play(0);
					Collection.parent.find('tr').removeClass('active');
					$('tr[data-title="'+song.name+'"]').addClass('active');
				});
				newRow.attr('data-album',album.name);
				newRow.attr('data-title',song.name);
				newRow.attr('data-artist',artist.name);
				newRow.data('albumData',album);
				if(!first){
					nextRow.before(newRow);
				}
				first=false;
			});
		});
		tr.removeClass('collapsed');
		tr.find('td.artist a.expander').data('expanded',true);
		tr.find('td.artist a.expander').addClass('expanded');
		tr.find('td.artist a.expander').text('v');
	},
	hideArtist:function(artist){
		var tr=Collection.parent.find('tr[data-artist="'+artist+'"]');
		var artist=tr.first().data('artistData');
		tr.first().find('td.album a').first().text(artist.albums.length+' '+t('media','albums'));
		tr.first().find('td.album a.expander').remove();
		tr.first().find('td.title a').text(artist.songs.length+' '+t('media','songs'));
		tr.first().find('td.album a').unbind('click');
		tr.first().find('td.title a').unbind('click');
		tr.each(function(i,row){
			if(i>0){
				$(row).remove();
			}
		});
		tr.find('td.artist a.expander').data('expanded',false);
		tr.find('td.artist a.expander').removeClass('expanded');
		tr.find('td.artist a.expander').text('>');
		Collection.addButtons(tr,artist);
	},
	showAlbum:function(artist,album){
		var tr = Collection.parent.find('tr[data-artist="'+artist+'"][data-album="'+album+'"]');
		var albumData=tr.data('albumData');
		tr.find('td.album a.expander').data('expanded',true);
		tr.find('td.album a.expander').addClass('expanded');
		tr.find('td.album a.expander').text('v');
		var nextRow=tr.next();
		$.each(albumData.songs,function(i,song){
			if(i>0){
				var newRow=tr.clone();
				newRow.find('a.expander').remove();
				newRow.find('td.album a').text('');
				newRow.find('td.artist a').text('');
			}else{
				var newRow=tr;
			}
			newRow.find('td.title a').text(song.name);
			if(i>0){
				nextRow.before(newRow);
			}
		});
	},
	hideAlbum:function(artist,album){
		var tr = Collection.parent.find('tr[data-artist="'+artist+'"][data-album="'+album+'"]');
		var albumData=tr.data('albumData');
		tr.first().find('td.title a').text(albumData.songs.length+' '+t('media','songs'));
		tr.find('td.album a.expander').data('expanded',false);
		tr.find('td.album a.expander').removeClass('expanded');
		tr.find('td.album a.expander').text('> ');
		tr.each(function(i,row){
			if(i>0){
				$(row).remove();
			}
		});
	},
	parent:null,
	hide:function(){
		if(Collection.parent){
			Collection.parent.hide();
		}
	},
	registerPlay:function(item){
		if(item){
			var song=Collection.findSong(item.artist,item.album,item.name);
			song.song_playcount++;
		}
	},
	addButtons:function(parent,data){
		buttons = parent.find('.buttons');
		if(buttons.find('.add').length<=0) {
			buttons.prepend('');
		}
		buttons.find('.add').unbind('click');
		buttons.find('.add').click(function(event){
			event.preventDefault();
			PlayList.add(data,true);
			PlayList.render();
		});
	},
	find:function(artistName,albumName,songName){
		if(songName){
			return Collection.findSong(artistName,albumName,songName);
		}else if(albumName){
			return Collection.findAlbum(artistName,albumName);
		}else{
			return Collection.findArtist(artistName);
		}
	},
	findArtist:function(name){
		for(var i=0;i<Collection.artists.length;i++){
			if(Collection.artists[i].name==name){
				return Collection.artists[i];
			}
		}
	},
	findAlbum:function(artistName,albumName){
		var artist=Collection.findArtist(artistName);
		if(artist){
			for(var i=0;i<artist.albums.length;i++){
				if(artist.albums[i].name==albumName){
					return artist.albums[i];
				}
			}
		}
	},
	findSong:function(artistName,albumName,songName){
		var album=Collection.findAlbum(artistName,albumName);
		if(album){
			for(var i=0;i<album.songs.length;i++){
				if(album.songs[i].name==songName){
					return album.songs[i];
				}
			}
		}
	},
	addSong:function(song){
		var artist=false
		var album=false;
		for(var i=0;i<Collection.artists.length;i++){
			if(Collection.artists[i].artist_id==song.song_artist){
				artist=Collection.artists[i];
				for(var j=0;j<artist.albums.length;j++){
					if(artist.albums[j].album_id==song.song_album){
						album=artist.albums[j];
						break;
					}
				}
				break;
			}
		}
		if(!artist){
			artist={artist_id:song.song_artist,artist_name:song.artist,albums:[]};
			Collection.artists.push(artist);
			if(!Collection.parent || Collection.parent.is(":visible")){
				Collection.display();
			}

		}
		if(!album){
			album={album_id:song.song_album,album_name:song.album,album_artist:song.song_artist,songs:[]};
			artist.albums.push(album)
		}
		album.songs.push(song)
	}
}

$(document).ready(function(){
	Collection.parent=$('#collection');
	Collection.load();
	Collection.parent.hide();
	$('#scan input.start').click(function(){
		$('#scan input.start').hide();
		$('#scan input.stop').show();
		$('#scan input.stop').click(function(){
			Scanner.toggle();
		});
		Scanner.scanCollection();
	});
});
<commit_msg>catch some edge cases in media player<commit_after>Collection={
	artists:[],
	albums:[],
	songs:[],
	artistsById:{},
	albumsById:{},
	loaded:false,
	loading:false,
	loadedListeners:[],
	load:function(ready){
		if(ready){
			Collection.loadedListeners.push(ready);
		}
		if(!Collection.loading){
			Collection.loading=true;
			$.ajax({
				url: OC.linkTo('media','ajax/api.php')+'?action=get_collection',
				dataType: 'json',
				success: function(data){
					//normalize the data
					for(var i=0;i<data.artists.length;i++){
						var artist=data.artists[i];
						var artistData={name:artist.artist_name,songs:[],albums:[]};
						Collection.artistsById[artist.artist_id]=artistData;
						Collection.artists.push(artistData);
					}
					for(var i=0;i<data.albums.length;i++){
						var album=data.albums[i];
						if(Collection.artistsById[album.album_artist]){
							var artistName=Collection.artistsById[album.album_artist].name;
						}else{
							var artistName='unknown';
						}
						var albumData={name:album.album_name,artist:artistName,songs:[]};
						Collection.albumsById[album.album_id]=albumData;
						Collection.albums.push(albumData);
						if(Collection.artistsById[album.album_artist]){
							Collection.artistsById[album.album_artist].albums.push(albumData);
						}
					}
					for(var i=0;i<data.songs.length;i++){
						var song=data.songs[i];
						if(Collection.artistsById[song.song_artist] && Collection.albumsById[song.song_album]){
							var songData={
								name:song.song_name,
								artist:Collection.artistsById[song.song_artist].name,
								album:Collection.albumsById[song.song_album].name,
								lastPlayed:song.song_lastplayed,
								length:song.song_length,
								path:song.song_path,
								playCount:song.song_playcount,
							};
							Collection.songs.push(songData);
							Collection.artistsById[song.song_artist].songs.push(songData);
							Collection.albumsById[song.song_album].songs.push(songData);
						}
					}

					Collection.artists.sort(function(a,b){
						if(!a.name){
							return -1;
						}
						return a.name.localeCompare(b.name);
					});

					Collection.loaded=true;
					Collection.loading=false;
					for(var i=0;i<Collection.loadedListeners.length;i++){
						Collection.loadedListeners[i]();
					}
					if(data.songs.length==0){
						$('#scan input.start').val(t('media','Scan Collection'));
						$('#scan input.start').click();
					}

				}
			});
		}
	},
	display:function(){
		if(Collection.parent){
			Collection.parent.show();
		}
		if(!Collection.loaded){
			Collection.load(Collection.display)
		}else{
			if(Collection.parent){
				Collection.parent.find('tr:not(.template)').remove();
				var template=Collection.parent.find('tr.template');
				var lastArtist='';
				var lastAlbum='';
				$.each(Collection.artists,function(i,artist){
					if(artist.name && artist.songs.length>0){
						var tr=template.clone().removeClass('template');
						if(artist.songs.length>1){
							tr.find('td.title a').text(artist.songs.length+' '+t('media','songs'));
							tr.find('td.album a').text(artist.albums.length+' '+t('media','albums'));
						}else{
							tr.find('td.title a').text(artist.songs[0].name);
							tr.find('td.album a').text(artist.albums[0].name);
						}
						tr.find('td.artist a').text(artist.name);
						tr.data('artistData',artist);
						tr.find('td.artist a').click(function(event){
							event.preventDefault();
							PlayList.add(artist);
							PlayList.play(0);
							Collection.parent.find('tr').removeClass('active');
							$('tr[data-artist="'+artist.name+'"]').addClass('active');
						});
						if(artist.songs.length>1){
							var expander=$('>');
							expander.data('expanded',false);
							expander.click(function(event){
								var tr=$(this).parent().parent();
								if(expander.data('expanded')){
									Collection.hideArtist(tr.data('artist'));
								}else{
									Collection.showArtist(tr.data('artist'));
								}
							});
						}
						tr.find('td.artist').addClass('buttons');
						Collection.addButtons(tr,artist);
						tr.children('td.artist').append(expander);
						tr.attr('data-artist',artist.name);
						Collection.parent.find('tbody').append(tr);
					}
				});
			}
		}
	},
	showArtist:function(artist){
		var tr=Collection.parent.find('tr[data-artist="'+artist+'"]');
		var nextRow=tr.next();
		var artist=tr.data('artistData');
		var first=true;
		$.each(artist.albums,function(j,album){
			$.each(album.songs,function(i,song){
				if(first){
					newRow=tr;
				}else{
					var newRow=tr.clone();
					newRow.find('td.artist').text('');
					newRow.find('.expander').remove();
				}
				newRow.find('td.album .expander').remove();
				if(i==0){
					newRow.find('td.album a').text(album.name);
					newRow.find('td.album a').click(function(event){
						event.preventDefault();
						PlayList.add(album);
						PlayList.play(0);
						Collection.parent.find('tr').removeClass('active');
						$('tr[data-album="'+album.name+'"]').addClass('active');
					});
					if(album.songs.length>1){
						var expander=$('v ');
						expander.data('expanded',true);
						expander.click(function(event){
							var tr=$(this).parent().parent();
							if(expander.data('expanded')) {
								Collection.hideAlbum(tr.data('artist'),tr.data('album'));
							} else {
								Collection.showAlbum(tr.data('artist'),tr.data('album'));
							}
						});
						newRow.children('td.album').append(expander);
					}
					Collection.addButtons(newRow,album);
				} else {
					newRow.find('td.album a').text('');
					Collection.addButtons(newRow,song);
				}
				newRow.find('td.title a').text(song.name);
				newRow.find('td.title a').click(function(event){
					event.preventDefault();
					PlayList.add(song);
					PlayList.play(0);
					Collection.parent.find('tr').removeClass('active');
					$('tr[data-title="'+song.name+'"]').addClass('active');
				});
				newRow.attr('data-album',album.name);
				newRow.attr('data-title',song.name);
				newRow.attr('data-artist',artist.name);
				newRow.data('albumData',album);
				if(!first){
					nextRow.before(newRow);
				}
				first=false;
			});
		});
		tr.removeClass('collapsed');
		tr.find('td.artist a.expander').data('expanded',true);
		tr.find('td.artist a.expander').addClass('expanded');
		tr.find('td.artist a.expander').text('v');
	},
	hideArtist:function(artist){
		var tr=Collection.parent.find('tr[data-artist="'+artist+'"]');
		var artist=tr.first().data('artistData');
		tr.first().find('td.album a').first().text(artist.albums.length+' '+t('media','albums'));
		tr.first().find('td.album a.expander').remove();
		tr.first().find('td.title a').text(artist.songs.length+' '+t('media','songs'));
		tr.first().find('td.album a').unbind('click');
		tr.first().find('td.title a').unbind('click');
		tr.each(function(i,row){
			if(i>0){
				$(row).remove();
			}
		});
		tr.find('td.artist a.expander').data('expanded',false);
		tr.find('td.artist a.expander').removeClass('expanded');
		tr.find('td.artist a.expander').text('>');
		Collection.addButtons(tr,artist);
	},
	showAlbum:function(artist,album){
		var tr = Collection.parent.find('tr[data-artist="'+artist+'"][data-album="'+album+'"]');
		var albumData=tr.data('albumData');
		tr.find('td.album a.expander').data('expanded',true);
		tr.find('td.album a.expander').addClass('expanded');
		tr.find('td.album a.expander').text('v');
		var nextRow=tr.next();
		$.each(albumData.songs,function(i,song){
			if(i>0){
				var newRow=tr.clone();
				newRow.find('a.expander').remove();
				newRow.find('td.album a').text('');
				newRow.find('td.artist a').text('');
			}else{
				var newRow=tr;
			}
			newRow.find('td.title a').text(song.name);
			if(i>0){
				nextRow.before(newRow);
			}
		});
	},
	hideAlbum:function(artist,album){
		var tr = Collection.parent.find('tr[data-artist="'+artist+'"][data-album="'+album+'"]');
		var albumData=tr.data('albumData');
		tr.first().find('td.title a').text(albumData.songs.length+' '+t('media','songs'));
		tr.find('td.album a.expander').data('expanded',false);
		tr.find('td.album a.expander').removeClass('expanded');
		tr.find('td.album a.expander').text('> ');
		tr.each(function(i,row){
			if(i>0){
				$(row).remove();
			}
		});
	},
	parent:null,
	hide:function(){
		if(Collection.parent){
			Collection.parent.hide();
		}
	},
	registerPlay:function(item){
		if(item){
			var song=Collection.findSong(item.artist,item.album,item.name);
			song.song_playcount++;
		}
	},
	addButtons:function(parent,data){
		buttons = parent.find('.buttons');
		if(buttons.find('.add').length<=0) {
			buttons.prepend('');
		}
		buttons.find('.add').unbind('click');
		buttons.find('.add').click(function(event){
			event.preventDefault();
			PlayList.add(data,true);
			PlayList.render();
		});
	},
	find:function(artistName,albumName,songName){
		if(songName){
			return Collection.findSong(artistName,albumName,songName);
		}else if(albumName){
			return Collection.findAlbum(artistName,albumName);
		}else{
			return Collection.findArtist(artistName);
		}
	},
	findArtist:function(name){
		for(var i=0;i<Collection.artists.length;i++){
			if(Collection.artists[i].name==name){
				return Collection.artists[i];
			}
		}
	},
	findAlbum:function(artistName,albumName){
		var artist=Collection.findArtist(artistName);
		if(artist){
			for(var i=0;i<artist.albums.length;i++){
				if(artist.albums[i].name==albumName){
					return artist.albums[i];
				}
			}
		}
	},
	findSong:function(artistName,albumName,songName){
		var album=Collection.findAlbum(artistName,albumName);
		if(album){
			for(var i=0;i<album.songs.length;i++){
				if(album.songs[i].name==songName){
					return album.songs[i];
				}
			}
		}
	},
	addSong:function(song){
		var artist=false
		var album=false;
		for(var i=0;i<Collection.artists.length;i++){
			if(Collection.artists[i].artist_id==song.song_artist){
				artist=Collection.artists[i];
				for(var j=0;j<artist.albums.length;j++){
					if(artist.albums[j].album_id==song.song_album){
						album=artist.albums[j];
						break;
					}
				}
				break;
			}
		}
		if(!artist){
			artist={artist_id:song.song_artist,artist_name:song.artist,albums:[]};
			Collection.artists.push(artist);
			if(!Collection.parent || Collection.parent.is(":visible")){
				Collection.display();
			}

		}
		if(!album){
			album={album_id:song.song_album,album_name:song.album,album_artist:song.song_artist,songs:[]};
			artist.albums.push(album)
		}
		album.songs.push(song)
	}
}

$(document).ready(function(){
	Collection.parent=$('#collection');
	Collection.load();
	Collection.parent.hide();
	$('#scan input.start').click(function(){
		$('#scan input.start').hide();
		$('#scan input.stop').show();
		$('#scan input.stop').click(function(){
			Scanner.toggle();
		});
		Scanner.scanCollection();
	});
});
<|endoftext|>


<commit_before>// ==========================================================================
// Project:   TestRunner.Target
// Copyright: ©2009 My Company, Inc.
// ==========================================================================
/*globals TestRunner */

/** @class

  Describes a single target in the current project.  A target can have a name,
  a type and one or more tests that are loaded on demand.

  @extends SC.Record
  @author Charles Jolley
*/
TestRunner.Target = SC.Record.extend(
/** @scope TestRunner.Target.prototype */ {

  /** name is the human readable target */
  nameType: String,

  /** The target type.  Generally one of app, framework, or theme */
  kindType: String,

  /** Load the tests for the target. */
  tests: function() {
    this.refreshTests();
    return this._tests;
  }.property().cacheable(),

  /** Refresh the tests from the server */
  refreshTests: function() {
  }

}) ;
<commit_msg>cleanup<commit_after>// ==========================================================================
// Project:   TestRunner.Target
// Copyright: ©2009 My Company, Inc.
// ==========================================================================
/*globals TestRunner */

/** @class

  Describes a single target in the current project.  A target can have a name,
  a type and one or more tests that are loaded on demand.

  @extends SC.Record
  @author Charles Jolley
*/
TestRunner.Target = SC.Record.extend(
/** @scope TestRunner.Target.prototype */ {

  /** Load the tests for the target. */
  tests: function() {
    this.refreshTests();
    return this._tests;
  }.property().cacheable(),

  /** Refresh the tests from the server */
  refreshTests: function() {
  }

}) ;
<|endoftext|>