<commit_before>(function prepareMigrations(){

	var migrationButton = document.getElementById("button-migrate");
	var appliedMigrationsList = document.getElementById("ul-migrations-applied");
	var availableMigrationsList = document.getElementById("ul-migrations-available");

	var self = this;
	self.migrationHistory = [];
	self.appliedMigrations = [];
	self.availableMigrations = [];
	const migrationHistoryRef = "migrationHistory";

	var migrations = [
		//Define migrations here, in the order they should be applied.
		//migrations are objects with the following properties:
		//  name - a short unique identifying string
		//  description - go into more detail about what it does for reference
		//  doMigration - a function that adds, updates or deletes nodes from the database
		//                (assuming that the database has had all previous migrations applied
		//                and has been used by regular users since).
		//                Takes no input
		//                Returns a promise to act upon after the migration
		//Don't forget to also adjust the firebaserules.json as required.
		{
			name: "<NAME>",
			description: "Added migration system.  Requires 'admins' node defined in database populated with an array of user ids",
			doMigration: function(){
				//Set up the empty migration history node
				return firebase.database().ref(migrationHistoryRef).set(self.migrationHistory);
			}
		},
	];

	var applyMigration = function(migration){
		return migration.doMigration().then(function(){
			//Strip out function definition when pushing to database but add timestamp for reference
			self.migrationHistory.push({
				name: migration.name,
				description: migration.description,
				timestamp: new Date().toUTCString()
			});
		});
	}

	var populateMigrationList = function(listElement, migrations){
		var migration = {};
		var li = null;
		var nameSpan = null;
		var descriptionSpan = null;
		var timestampSpan = null;
		listElement.innerHTML = "";

		if (migrations.length === 0){
			li = document.createElement("li");
			li.appendChild(document.createTextNode("No Migrations"));
			listElement.appendChild(li);
		}
		else{
			for (var i = 0; i < migrations.length ; i++){
				migration = migrations[i];
				li = document.createElement("li");
				nameSpan = document.createElement("span");
				nameSpan.appendChild(document.createTextNode(migration.name));
				li.appendChild(nameSpan);
				descriptionSpan = document.createElement("span");
				descriptionSpan.appendChild(document.createTextNode(migration.description));
				li.appendChild(descriptionSpan);
				timestampSpan = document.createElement("span");
				timestampSpan.appendChild(document.createTextNode(migration.timestamp));
				li.appendChild(timestampSpan);
				listElement.appendChild(li);
			}
		}

	}

	firebase.database().ref(migrationHistoryRef).on("value", function(migrationHistorySnapshot){
		var migration = {};

		//Handle no migration history node
		self.migrationHistory = migrationHistorySnapshot.val()
		if (self.migrationHistory === null){
			self.migrationHistory = [];
		}

		//Work out which of the above migrations are applied or waiting to be applied
		self.appliedMigrations = [];
		self.availableMigrations = [];

		for (var i = 0; i < migrations.length ; i++){
			migration = migrations[i];
			if (self.migrationHistory.find(function(historyItem){return historyItem.name === migration.name}) === undefined){
				self.availableMigrations.push(migration);
			}
			else{
				self.appliedMigrations.push(migration);
			}
		}

		populateMigrationList(appliedMigrationsList, self.appliedMigrations);
		populateMigrationList(availableMigrationsList, self.availableMigrations);

		//Refresh the apply migration click handler so it applys only the required migrations
		migrationButton.onclick = function(mouseEvent){
			//Empty promise to begin promise chain
			var promise = Promise.resolve();
			for (var i = 0; i < self.availableMigrations.length ; i++){
				migration = migrations[i];
				promise = promise.then(applyMigration(migration));
			}
			promise.then(() => firebase.database().ref(migrationHistoryRef).set(self.migrationHistory));
		};
	});
})();
<commit_msg>Fixed issue with migration timestamp display Migrations no longer display underfined in the timestamp field. Also added error handlers to some web calls for debugging purposes.<commit_after>(function prepareMigrations(){

	var migrationButton = document.getElementById("button-migrate");
	var appliedMigrationsList = document.getElementById("ul-migrations-applied");
	var availableMigrationsList = document.getElementById("ul-migrations-available");

	var self = this;
	self.migrationHistory = [];
	self.appliedMigrations = [];
	self.availableMigrations = [];
	const migrationHistoryRef = "migrationHistory";

	var migrations = [
		//Define migrations here, in the order they should be applied.
		//migrations are objects with the following properties:
		//  name - a short unique identifying string
		//  description - go into more detail about what it does for reference
		//  doMigration - a function that adds, updates or deletes nodes from the database
		//                (assuming that the database has had all previous migrations applied
		//                and has been used by regular users since).
		//                Takes no input
		//                Returns a promise to act upon after the migration
		//Don't forget to also adjust the firebaserules.json as required.
		{
			name: "Initial migration",
			description: "Added migration system.  Requires 'admins' node defined in database populated with an array of user ids",
			doMigration: function(){
				//Set up the empty migration history node
				return firebase.database().ref(migrationHistoryRef).set(self.migrationHistory);
			}
		},
	];

	var applyMigration = function(migration){
		return migration.doMigration().then(function(){
			//Strip out function definition when pushing to database but add timestamp for reference
			self.migrationHistory.push({
				name: migration.name,
				description: migration.description,
				timestamp: new Date().toUTCString()
			});
		});
	}

	var populateMigrationList = function(listElement, migrations){
		var migration = {};
		var li = null;
		var nameSpan = null;
		var descriptionSpan = null;
		var timestampSpan = null;
		listElement.innerHTML = "";

		if (migrations.length === 0){
			li = document.createElement("li");
			li.appendChild(document.createTextNode("No Migrations"));
			listElement.appendChild(li);
		}
		else{
			for (var i = 0; i < migrations.length ; i++){
				migration = migrations[i];
				li = document.createElement("li");
				nameSpan = document.createElement("span");
				nameSpan.appendChild(document.createTextNode(migration.name));
				li.appendChild(nameSpan);
				descriptionSpan = document.createElement("span");
				descriptionSpan.appendChild(document.createTextNode(migration.description));
				li.appendChild(descriptionSpan);
				if(migration.timestamp !== undefined){
					timestampSpan = document.createElement("span");
					timestampSpan.appendChild(document.createTextNode(migration.timestamp));
					li.appendChild(timestampSpan);
				}
				listElement.appendChild(li);
			}
		}

	}

	firebase.database().ref(migrationHistoryRef).on("value", function(migrationHistorySnapshot){
		var migration = {};
		var migrationHistoryItem = {};

		//Handle no migration history node
		self.migrationHistory = migrationHistorySnapshot.val()
		if (self.migrationHistory === null){
			self.migrationHistory = [];
		}

		//Work out which of the above migrations are applied or waiting to be applied
		self.appliedMigrations = [];
		self.availableMigrations = [];

		for (var i = 0; i < migrations.length ; i++){
			migration = migrations[i];
			migrationHistoryItem = self.migrationHistory.find(function(historyItem){return historyItem.name === migration.name});
			if (migrationHistoryItem === undefined){
				self.availableMigrations.push(migration);
			}
			else{
				self.appliedMigrations.push(migrationHistoryItem);
			}
		}

		populateMigrationList(appliedMigrationsList, self.appliedMigrations);
		populateMigrationList(availableMigrationsList, self.availableMigrations);

		//Refresh the apply migration click handler so it applys only the required migrations
		migrationButton.onclick = function(mouseEvent){
			//Empty promise to begin promise chain
			var promise = Promise.resolve();
			for (var i = 0; i < self.availableMigrations.length ; i++){
				migration = migrations[i];
				promise = promise.then(applyMigration(migration));
			}
			promise.then(() => firebase.database().ref(migrationHistoryRef).set(self.migrationHistory),(error) => console.log(error));
		};
	}, function(error){
		console.log(error);
	});
})();

{'fraction_non_alphanumeric': 0.11083209679260358, 'fraction_numerical': 0.0009131377696609977, 'mean_word_length': 4.073537927041111, 'pattern_counts': {'":': 0, '<': 10, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7183239', 'n_tokens_mistral': 2679, 'n_tokens_neox': 2350, 'n_words': 643}