// guix-web - Web interface for GNU Guix // Copyright © 2014 David Thompson // // 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 // . (function() { var packages = guix.packages; packages.controller = function() { var PAGE_SIZE = 20; // Throttle search to twice per second maximum. var SEARCH_THROTTLE = 500; var packages = K.fromPromise(guix.packages.Packages()); var searchTerm = K.emitter(); var sorterStream = K.emitter(); var pageIndex = K.emitter(); var phaseStream = K.emitter(); var selectedPackageStream = K.emitter(); var filteredPackages = K.combine([ packages, searchTerm.throttle(SEARCH_THROTTLE).toProperty("") ], function(packages, search) { var regexp = new RegExp(search === "" ? ".*" : search, "i"); return packages.filter(function(package) { return regexp.test(package.name) || regexp.test(package.synopsis); }); }); var sorter = sorterStream.toProperty({ field: "name", reverse: false }); var sortFields = { license: function(package) { if(_.isArray(package.license)) { // Concatenate all license names together for sorting. return package.license.reduce(function(memo, l) { return memo.concat(l.name); }, ""); } return package.license.name; } }; var sortedPackages = K.combine([ filteredPackages, sorter ], function(packages, sorter) { var field = sorter.field; var sorted = _.sortBy(packages, sortFields[field] || field); return sorter.reverse ? sorted.reverse() : sorted; }); var pages = sortedPackages.map(function(packages) { return guix.chunk(packages, PAGE_SIZE); }).toProperty([[]]); var page = K.combine([ pages, pageIndex.toProperty(0) ], function(pages, i) { return { index: i, packages: pages[i] }; }); var phase = phaseStream.toProperty(guix.packages.PHASE_NONE); return guix.ui.spinUntil(K.combine([ packages, pages, page, searchTerm.toProperty(""), sorter, phase, selectedPackageStream.toProperty(null) ], function(packages, pages, page, search, sorter, phase, selectedPackage) { function renderName(package) { var name = package.name; return m("a", { config: m.route, href: "/package/".concat(name) }, name); } function renderHomepage(package) { if(package.homepage) { return m("a", { href: package.homepage }, package.homepage); } else { return ""; } } function renderHeader(title, field) { var isCurrentSorter = sorter.field === field; var sorterClass = (function() { if(isCurrentSorter) { return sorter.reverse ? "sorter sort-descend" : "sorter sort-ascend"; } return "sorter"; })(); return m("th", { class: sorterClass, onclick: function() { if(isCurrentSorter) { sorterStream.emit({ field: field, reverse: !sorter.reverse }); } else { sorterStream.emit({ field: field, reverse: false }); } } }, title); } function renderInstallLink(package) { return m("a", { href: "#", onclick: function() { selectedPackageStream.emit(package); phaseStream.emit(guix.packages.PHASE_PROMPT); } }, "install"); } var pagination = guix.ui.paginate(page.index, pages.length, 10, pageIndex); return [ guix.ui.headerWithBadge("Packages", packages.length), // Installation modal guix.packages.view.installModal(selectedPackage, phase, phaseStream), // Search box m("input.form-control", { type: "text", placeholder: "Search", oninput: guix.withEmitAttr("value", searchTerm) }), pagination, // Package table m("table.table", [ m("thead", [ m("tr", [ renderHeader("Name", "name"), renderHeader("Version", "version"), renderHeader("Synopsis", "synopsis"), renderHeader("Home page", "homepage"), renderHeader("License", "license"), m("th", "") ]) ]), m("tbody", [ page.packages.map(function(package) { return m("tr", [ m("td", renderName(package)), m("td", package.version), m("td", package.synopsis), m("td", renderHomepage(package)), m("td", guix.ui.licenseList(package)), m("td", renderInstallLink(package)) ]); }) ]) ]), pagination ]; })).map(guix.withLayout); }; })();