repoindex/web/js/repomanagement.js

325 lines
16 KiB
JavaScript

var repoindex = (function(repoindex) {
var RepoEntry = {};
RepoEntry.prototype = new repoindex.Entry();
RepoEntry.prototype.constructor = RepoEntry;
RepoEntry = function(repoName, repoInfo, enabled) {
if(enabled === undefined) {
// per default enable all repos with a fix number of packages except the local database
enabled = repoInfo.packageCount && repoName !== "local";
}
repoindex.Entry.prototype.constructor.call(this, repoName, repoInfo, enabled);
this.info.currentServer = 0;
this.rowElement.onclick = function(e) {
repoindex.pageManager.repoManager.showRepoInfoForIndex(this.entry.index, typeof e === "object" && e.button === 1);
};
this.initTableRow = function() {
this.rowElement.addCell(this.name);
this.rowElement.addCell(this.info.desc);
};
this.initTableRow();
// create link
this.createLink = function() {
this.link = document.createElement("a");
this.link.href = "#";
this.link.className = enabled ? "btn btn-primary" : "btn btn-default";
this.link.setAttribute("role", "button");
this.link.repo = this;
this.link.onclick = function() {
if(repoindex.pageManager.repoManager.buttonContainerExclusiveButton.checked) {
repoindex.pageManager.repoManager.updateEnabledAll(false);
}
this.repo.toggleEnabled();
return false;
};
this.link.appendChild(document.createTextNode(repoName));
this.link.title = repoInfo.desc;
// use Bootstrap tooltip
this.link.setAttribute("data-placement", "bottom");
$(this.link).tooltip();
if(repoInfo.packageCount) {
// create badge with package count
var span = document.createElement("span");
span.className = "badge";
span.appendChild(document.createTextNode(repoInfo.packageCount));
this.link.appendChild(document.createTextNode(" "));
this.link.appendChild(span);
}
this.link.add = function() {
repoindex.pageManager.repoManager.buttonContainer.appendChild(this);
};
this.link.remove = function() {
this.parentNode.removeChild(this);
};
};
this.createLink();
this.link.add();
// provide a function to toggle enabled/disabled
this.updateEnabled = function(enabled, noNotify) {
if(this.enabled !== enabled) {
this.link.className = (this.enabled = enabled) ? "btn btn-primary" : "btn btn-default";
if(!noNotify) {
this.statusChanged(this);
}
}
};
this.toggleEnabled = function() {
this.updateEnabled(!this.enabled);
};
};
repoindex.RepoEntryManager = {};
repoindex.RepoEntryManager.prototype = new repoindex.EntryManager();
repoindex.RepoEntryManager.prototype.constructor = repoindex.RepoEntryManager;
repoindex.RepoEntryManager = function(pagination) {
repoindex.EntryManager.prototype.constructor.call(this, RepoEntry, document.getElementById("repos"), pagination);
this.entryName = "repository";
this.entryNamePlural = "repositories";
this.buttonRow = document.getElementById("row_repos_buttons");
this.buttonContainer = document.getElementById("repos_buttons");
this.buttonContainerOptionsDropdown = document.getElementById("repos_buttons_options_dropdown");
this.buttonContainerExclusiveButton = document.getElementById("repos_buttons_exclusive");
this.applyRepoStatusChange = function() {
// this is the RepoEntry object in this function!
var pageMgr = repoindex.pageManager;
var repoEntries = pageMgr.repoManager.entries;
var repoFilter = [];
for(var i = 0, end = repoEntries.length; i < end; ++i) {
if(repoEntries[i].enabled) {
repoFilter.push(repoEntries[i].name);
}
}
pageMgr.packageManager.filterRepos = pageMgr.groupManager.filterRepos = repoFilter;
pageMgr.packageManager.invalidate();
pageMgr.groupManager.invalidate();
};
// provide a function to add repo entries
this.addEntry = function(repoName, repoInfo) {
var entry = new RepoEntry(repoName, repoInfo);
entry.statusChanged = this.applyRepoStatusChange;
entry.pageManager = this;
entry.repoEntryManager = this;
entry.index = this.entries.length;
this.entries.push(entry);
return entry;
};
this.baseRemoveEntries = this.removeEntries;
this.removeEntries = function() {
for(var i = 0; i < this.entries.length; ++i) {
this.entries[i].link.remove();
}
this.baseRemoveEntries();
};
this.updateEnabledAll = function(enabled, noNotify) {
for(var i = 0; i < this.entries.length; ++i) {
this.entries[i].updateEnabled(enabled, true);
}
if(!noNotify) {
this.applyRepoStatusChange();
}
};
// handle a page selection
this.pagination.pageSelected = function(pageElement) {
var mgr = this.entryManager;
// remove elements from previously selected page
mgr.entryContainer.wipeChildren();
// if there is no page because there are no package entries, pageElement is null
if(pageElement) {
// show elements of selected page
pageElement.forRange(function(i) {
var entry = mgr.filteredEntries[i];
entry.add(mgr.entryContainer); // adds entry to the entry container
}, mgr.filteredEntries.length);
}
};
this.infoBox = document.getElementById("repos_info");
this.showRepoInfo = function(repo, newTab) {
var determineEntry = function() {
var res = repoindex.pageManager.repoManager.entries.filter(function(entry) {
return entry.name === repo;
});
// entry exists?
if(res.length > 0) {
// yes -> full package info available?
repoindex.pageManager.repoManager.showRepoInfoForIndex(res[0].index, newTab);
} else {
// no -> show error
repoindex.pageManager.repoManager.showRepoNotFound(repo);
}
};
// basic repo info available?
if(repoindex.client.hasBasicRepoInfo) {
// yes -> can determine entry instantly
determineEntry();
} else {
// no -> request info, use callback to determine entry when info becomes available
repoindex.client.requestBasicRepoInfo(determineEntry);
}
};
this.showRepoInfoForIndex = function(entryIndex, newTab) {
var entry = this.entryByIndex(entryIndex);
if(entry) {
// -> find info container and make info table
var infoContainer = repoindex.pageManager.createRepoInfoPane(entry, newTab);
infoContainer.wipeChildren();
var infoTable = repoindex.makeInfoTable();
var tb = infoTable.tbodyElement;
var info = entry.info;
repoindex.addField(tb, "Name", repoindex.makeStr(entry.name));
repoindex.addField(tb, "Description", repoindex.makeStr(info.desc));
repoindex.addField(tb, "Package count", repoindex.makeStr(info.packageCount));
repoindex.addField(tb, "Usage", repoindex.makeArray(info.usage, ", "));
repoindex.addField(tb, "Signature level", repoindex.makeArray(info.sigLevel, ", "));
repoindex.addField(tb, "Source-only", repoindex.makeBool(info.srcOnly));
repoindex.addField(tb, "Upgrade sources", repoindex.makeArray(info.upgradeSources, ", "));
var invokeUpgradeLookupParams = {repo: entry.name, invoke: "upgradelookup"};
repoindex.setDownloadButton(repoindex.addField(tb, "Upgrades"), "check for upgrades", repoindex.makeHash(repoindex.Pages.Repositories, invokeUpgradeLookupParams, true), function() {
repoindex.pageManager.repoManager.showAvailableUpgrades(entry.name);
repoindex.pageManager.denoteHash(repoindex.Pages.Repositories, invokeUpgradeLookupParams);
}, "refresh");
// set currentInfo (the pageManager needs this value to upgrade the hash)
this.currentInfo = info;
// ensures, that the "Package Info" box (with the properties just set) is shown
repoindex.pageManager.showRepoInfo();
infoContainer.appendChild(infoTable.tableElement);
}
};
this.showRepoNotFound = function(repo) {
repoindex.pageManager.msgboxCritical(
"Repository not found",
"The repository <i>" + repoindex.escapeHtml(repo) + "</i> can not be found.",
true);
};
this.showAvailableUpgrades = function(repo) {
var requestUpgrades = function() {
var showUpgrades = function(availableUpgrades) {
// check for errors
if(Array.isArray(availableUpgrades.errors)) {
for(var i = 0; i < availableUpgrades.errors.length; ++i) {
repoindex.pageManager.addError("Error: " + availableUpgrades.errors[i]);
}
} else {
// create package entries for the upgrades
var upgradeEntries = [];
var upgrades = [
{
name: "software upgrade",
namePlural: "software upgrades",
style: "background-color: " + repoindex.softwareUpgradeBackgroundColor,
color: repoindex.softwareUpgradeBackgroundColor,
entries: Array.isArray(availableUpgrades.softwareUpgrades) ? availableUpgrades.softwareUpgrades : [],
count: Array.isArray(availableUpgrades.softwareUpgrades) ? availableUpgrades.softwareUpgrades.length : 0
}, {
name: "package-only upgrade",
namePlural: "package-only upgrades",
style: "background-color: " + repoindex.packageUpgradeBackgroundColor,
color: repoindex.packageUpgradeBackgroundColor,
entries: Array.isArray(availableUpgrades.packageOnlyUpgrades) ? availableUpgrades.packageOnlyUpgrades : [],
count: Array.isArray(availableUpgrades.packageOnlyUpgrades) ? availableUpgrades.packageOnlyUpgrades.length : 0
}, {
name: "downgrade",
namePlural: "downgrades",
style: "background-color: " + repoindex.downgradesBackgroundColor,
color: repoindex.downgradesBackgroundColor,
entries: Array.isArray(availableUpgrades.downgrades) ? availableUpgrades.downgrades : [],
count: Array.isArray(availableUpgrades.downgrades) ? availableUpgrades.downgrades.length : 0
}, {
name: "orphaned package",
namePlural: "orphaned packages",
style: "background-color: " + repoindex.orphanedPackageBackgroundColor,
color: repoindex.orphanedPackageBackgroundColor,
entries: Array.isArray(availableUpgrades.orphanedPackages) ? availableUpgrades.orphanedPackages : [],
count: Array.isArray(availableUpgrades.orphanedPackages) ? availableUpgrades.orphanedPackages.length : 0
}
];
var pkgMgr = repoindex.pageManager.packageManager;
var repoMgr = repoindex.pageManager.repoManager;
for(var i1 = 0; i1 < upgrades.length; ++i1) {
// iterate through all kinds of "upgrades" declared above
for(var i2 = 0; i2 < upgrades[i1].entries.length; ++i2) {
// iterate through all entries which have been assigned to the current upgrade type
var upgradeEntry = upgrades[i1].entries[i2];
if(upgradeEntry.pkg) {
var packageInfo = repoindex.client.getPackageInfo(upgradeEntry.repo, upgradeEntry.name);
packageInfo.basics = upgradeEntry.pkg;
// find associated repo entry
var repoEntry;
if((repoEntry = repoMgr.entryByName(packageInfo.repo))) {
repoEntry.updateEnabled(true); // ensure repo is enabled
}
var newEntry = pkgMgr.createCustomEntry(repoEntry, upgradeEntry.name, packageInfo, upgrades[i1].color);
newEntry.curVer = upgradeEntry.curVer;
newEntry.index = upgradeEntries.length;
newEntry.updateTableRow();
} else {
repoindex.pageManager.addError("Upgrade entry replied by server does not include package info.");
}
upgradeEntries.push(newEntry);
}
}
// show warnings
if(Array.isArray(availableUpgrades.warnings)) {
for(var i = 0; i < availableUpgrades.warnings.length; ++i) {
repoindex.pageManager.addError("Warning: " + availableUpgrades.warnings[i]);
}
}
// show upgrades via package manager
pkgMgr.filterName = undefined;
pkgMgr.customSelection = upgradeEntries;
pkgMgr.customSelectionName = "upgrade";
pkgMgr.customSelectionNamePlural = "upgrades";
var quandityInfo = repoindex.makeQuandityInfo(upgrades);
if(quandityInfo) {
pkgMgr.customSelectionInfoText = "Upgrades for the repository <i>"
+ repoindex.escapeHtml(repo)
+ "</i>: " + quandityInfo
+ repoindex.removeFilterButtonHtml;
}
pkgMgr.filterDescr = "for the repository"
pkgMgr.invalidate();
repoindex.pageManager.setPage(repoindex.Pages.Packages);
}
};
repoindex.client.checkForUpgrades(repo, null, showUpgrades);
};
// basic repo info available?
if(repoindex.client.hasBasicRepoInfo) {
// yes -> request upgrades instantly
requestUpgrades();
} else {
// no -> request info, use callback to go on requesting upgrades when repo info becomes available
repoindex.client.requestBasicRepoInfo(requestUpgrades);
}
};
};
return repoindex;
})(repoindex || {});