summaryrefslogtreecommitdiff
path: root/js/view/packages.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/view/packages.js')
-rw-r--r--js/view/packages.js251
1 files changed, 251 insertions, 0 deletions
diff --git a/js/view/packages.js b/js/view/packages.js
new file mode 100644
index 0000000..e356984
--- /dev/null
+++ b/js/view/packages.js
@@ -0,0 +1,251 @@
+// guix-web - Web interface for GNU Guix
+// Copyright © 2014 David Thompson <davet@gnu.org>
+//
+// 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(packages) {
+ packages.view = function(ctrl) {
+ function renderName(package) {
+ var name = package.name;
+
+ return m("a", { href: "/packages/".concat(name) }, name);
+ }
+
+ function renderHomepage(package) {
+ if(package.homepage) {
+ return m("a", { href: package.homepage }, package.homepage);
+ } else {
+ return "";
+ }
+ }
+
+ function renderLicense(package) {
+ function licenseLink(license) {
+ return m("a", { href: license.uri }, license.name);
+ }
+
+ if(_.isArray(package.license)) {
+ return m("ul.list-inline", package.license.map(function(license) {
+ return m("li", licenseLink(license));
+ }));
+ } else if(package.license) {
+ return licenseLink(package.license);
+ } else {
+ return "";
+ }
+ }
+
+ function renderInstallLink(package) {
+ return m("a", {
+ href: "#",
+ onclick: function() {
+ ctrl.selectedPackage(package);
+ ctrl.phase(packages.PHASE_PROMPT);
+ return false;
+ }
+ }, "install");
+ }
+
+ function renderPackageTable() {
+ return m("table.table", [
+ m("thead", [
+ m("tr", [
+ ctrl.columns.map(function(column) {
+ return m("th", {
+ class: columnHeaderClass(column),
+ onclick: function() {
+ ctrl.sortBy(column.sortField);
+ }
+ }, column.header);
+ }).concat([m("th", "")])
+ ])
+ ]),
+ m("tbody", [
+ ctrl.currentPage().map(function(package) {
+ return m("tr", [
+ m("td", renderName(package)),
+ m("td", package.version),
+ m("td", package.synopsis),
+ m("td", renderHomepage(package)),
+ m("td", renderLicense(package)),
+ m("td", renderInstallLink(package))
+ ]);
+ })
+ ])
+ ]);
+ }
+
+ function renderPagination() {
+ function renderPage(text, opts) {
+ return m("li", {
+ class: opts.class || "",
+ onclick: opts.onclick
+ }, m("a", { href: "#" }, text));
+ }
+
+ return m("ul.pagination", [
+ // Back page
+ renderPage("«", {
+ class: ctrl.isFirstPage() ? "disabled" : "",
+ onclick: function() {
+ ctrl.currentPageIndex--;
+
+ return false;
+ }
+ })
+ ].concat(ctrl.pages().map(function(page, i) {
+ // Jump to page
+ return renderPage(i + 1, {
+ class: ctrl.isCurrentPage(i) ? "active" : "",
+ onclick: function() {
+ ctrl.currentPageIndex = i;
+
+ return false;
+ }
+ });
+ })).concat([
+ // Forward page
+ renderPage("»", {
+ class: ctrl.isLastPage() ? "disabled" : "",
+ onclick: function() {
+ ctrl.currentPageIndex++;
+
+ return false;
+ }
+ })
+ ]));
+ }
+
+ function renderSearchBox() {
+ return m("input.form-control", {
+ type: "text",
+ placeholder: "Search",
+ onchange: m.withAttr("value", function(value) {
+ ctrl.searchTerm(value);
+ ctrl.doSearch();
+ }),
+ value: ctrl.searchTerm()
+ });
+ }
+
+ function columnHeaderClass(column) {
+ var sorter = ctrl.sorter();
+
+ if(column.sortField === sorter.field) {
+ return sorter.isDescending ? "sorter sort-descend" : "sorter sort-ascend";
+ }
+
+ return "sorter";
+ }
+
+ function renderModal() {
+ function renderBody() {
+ switch(ctrl.phase()) {
+ case packages.PHASE_PROMPT:
+ return [
+ m("p", "Do you want to install the following packages?"),
+ m("ul", [
+ m("li", [
+ ctrl.selectedPackage().name,
+ " ",
+ ctrl.selectedPackage().version
+ ])
+ ])
+ ];
+ case packages.PHASE_DERIVATION:
+ return [
+ m("p", [
+ "Installing ",
+ ctrl.selectedPackage().name,
+ " ",
+ ctrl.selectedPackage().version,
+ "..."
+ ]),
+ m(".progress", [
+ m(".progress-bar.progress-bar-striped.active", {
+ role: "progressbar",
+ style: { width: "100%" }
+ })
+ ])
+ ];
+ case packages.PHASE_SUCCESS:
+ return m(".alert.alert-success", "Installation complete!");
+ case packages.PHASE_ERROR:
+ return m(".alert.alert-danger", "Installation failed!");
+ }
+
+ return null;
+ }
+
+ function renderButtons() {
+ switch(ctrl.phase()) {
+ case packages.PHASE_PROMPT:
+ return [
+ m(".btn.btn-default", "Cancel"),
+ m(".btn.btn-primary", {
+ onclick: function() {
+ ctrl.installSelectedPackage();
+ m.redraw();
+ }
+ }, "Install"),
+ ];
+ case packages.PHASE_DERIVATION:
+ return m(".btn.btn-danger", "Abort");
+ case packages.PHASE_SUCCESS:
+ case packages.PHASE_ERROR:
+ return m(".btn.btn-primary", {
+ onclick: function() {
+ ctrl.phase(packages.PHASE_NONE);
+ }
+ }, "Close");
+ }
+
+ return null;
+ }
+
+ if(ctrl.phase() != packages.PHASE_NONE) {
+ return [
+ m(".modal-backdrop.in"),
+ m("div.modal.modal-open", {
+ style: {
+ display: "block"
+ }
+ }, m(".modal-dialog", [
+ m(".modal-content", [
+ m(".modal-header", [
+ m("h4.modal-title", "Install Packages")
+ ]),
+ m(".modal-body", renderBody()),
+ m(".modal-footer", renderButtons())
+ ])
+ ]))
+ ];
+ }
+
+ return null;
+ }
+
+ return guix.withLayout([
+ m("h2", [
+ "Packages",
+ m("span.badge", ctrl.packageCount())
+ ]),
+ renderModal(),
+ renderSearchBox(),
+ renderPackageTable(),
+ renderPagination()
+ ]);
+ };
+})(guix.packages);