Skip to content

Commit

Permalink
Combined search/list deps page (#449)
Browse files Browse the repository at this point in the history
Signed-off-by: R. Kent James <[email protected]>
  • Loading branch information
rkent authored Dec 13, 2024
1 parent 6b438c7 commit c78cf55
Show file tree
Hide file tree
Showing 8 changed files with 448 additions and 10 deletions.
6 changes: 3 additions & 3 deletions _data/common.yml
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,8 @@ package_manager_names:
# It is used to limit the display of platforms when space is at a premium. Items consist of a
# Hash with <platforms key>: '<display name>'
current_platforms:
ubuntu: 'Ubuntu'
rhel: 'RHEL'
debian: 'Debian'
openembedded: 'OpenEmbedded'
osx: 'macOS'
rhel: 'RHEL'
ubuntu: 'Ubuntu'
openembedded: 'OpenEmbedded'
2 changes: 0 additions & 2 deletions _layouts/noscroll-default.html
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,6 @@
<script src={{ "/js/jquery-cookie.js" | prepend: site.baseurl }} type="text/javascript"></script>
{% include_cached google_analytics.html %}
<script type="text/javascript" src={{ "/js/toc.js" | prepend: site.baseurl }}></script>

<script src={{ "/js/distro_switch.js" | prepend: site.baseurl }}></script>
</head>

<body style="height: 100vh;">
Expand Down
289 changes: 289 additions & 0 deletions _layouts/search_deps.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,289 @@
---
layout: noscroll-default
---
<div class="container-fluid" style="padding-top:10px; height:100%;">
<div class="container-fluid" style="height:100%;">
<div class="row" style="height:var(--distro-height);">
<h4 style="margin-top:2px;">System Dependencies</h4>
</div>
<div class="row" style="height:var(--search-height);">
<div class="panel panel-default" style="height:100%;">
<div class="panel-heading" style="height:100%;">
<div class="row" style="height:100%;">
<div class="col-xs-6">
<div class="input-group">
<span class="input-group-addon">
<input type="checkbox" id="search-enable-box"/>
<span class="hidden-xs"> Enable search </span>
</span>
<input id="search-query" type="text" class="form-control"
autocomplete="off" placeholder="Search dependencies">
<span class="input-group-btn">
<button id="search-button" title="Search dependencies" class="btn btn-default">
<span class="glyphicon glyphicon-search"></span>
</button>
</span>
</div>
</div>
<div class="col-xs-4">
<p style="line-height:35px">
<span class="hidden-xs">Showing </span>
<span id="table-filtered-count">0</span> of
<span id="table-unfiltered-count">0</span>
<span class="hidden-xs"> dependencies</span>
</p>
</div>
<div class="col-xs-2 text-right">
<p style="line-height:35px">
<a href="{{site.baseurl}}/help/system_dependencies/">
<span class="glyphicon glyphicon-question-sign"></span>
<span class="hidden-xs"> Help</span>
</a>
</p>
</div>
</div>
</div>
</div>
</div>
<div class="row" style="height:calc(100% - var(--search-height) - var(--distro-height))">
<div id="dependencies-table"></div>
</div>
</div>
</div>

<!-- See https://github.com/olifolkerd/tabulator/issues/4419 for issue with Tabulator post-5.6.0 -->
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/tabulator.min.css" rel="stylesheet">
<!-- <script src={{ "/js/tabulator.js" | prepend: site.baseurl }}></script> -->
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/tabulator.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/[email protected]/build/global/luxon.min.js"></script>
<script src="{{ site.baseurl }}/js/lunr.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
var gData_promise = null;
var gIndex_promise =null;
var gTable = null;
const DEFAULT_SORT = [{column:"url", dir:"asc"}]

function addFilter(table, field, type, value) {
// Add a new table filter, removing existing
removeFilterByField(table, field);
table.addFilter(field, type, value);
}

function removeFilterByField(table, field) {
// remove all filters on a specified field, if any
for (const existingFilter of table.getFilters()) {
if ('field' in existingFilter && existingFilter['field'] == field) {
table.removeFilter(existingFilter.field, existingFilter.type, existingFilter.value);
}
}
}

function getData() {
// start and return a promise to get json data
if (gData_promise) {
return gData_promise;
}
gData_promise =
fetch(`{{ site.baseurl }}/search/deps/data.0.json`)
.then((response) => response.json());

return gData_promise;
}

function getIndex() {
// start and return a promise to get json index
if (gIndex_promise) {
return gIndex_promise;
}
gIndex_promise =
fetch(`{{ site.baseurl }}/search/deps/index.0.json`)
.then((response) => response.json())
.then((indexData) => {
return lunr.Index.load(indexData);
});

return gIndex_promise;
}

function getWindowSearchQuery() {
return new URL(window.location.toString()).searchParams.get('deps');
}

// Populate the search input with querystring parameter
function setWindowSearchQuery(query) {
var url = new URL(window.location.toString());
url.searchParams.set('deps', query);
window.history.pushState({}, '', url);
}

function copySearchQueryToUI() {
var query = getWindowSearchQuery() || '';
$('#search-query').val(query);
$("#search-enable-box").prop("checked", !!query);
}

function copyUIToSearchQuery() {
if ($("#search-enable-box").prop("checked")) {
setWindowSearchQuery($('#search-query').val());
} else {
setWindowSearchQuery('');
}
}

// Returns a promise resolving to a hash of {ref: score} with hits
function getSearchHash(query) {
if (!query) {
return Promise.resolve(null);
}
return getIndex().then(searchIndex => {
var searchResults = searchIndex.search(query);
// Tabulator filters don't seem to work with zero entries
searchHash = {'-1': 0.0};
for (const result of searchResults) {
searchHash[result.ref] = result.score;
}
console.log(`Search returned ${searchResults.length} results`);
return searchHash;
});
}

function doSearch(table, query) {
console.log(`doSearch query="${query}"`);
getData().then(data => {
getSearchHash(query).then(searchHash => {
// Add score to table data
for (const dataValue of data) {
ref = dataValue['id'].toString();
if (searchHash && ref in searchHash) {
dataValue['score'] = searchHash[ref];
}
else {
dataValue['score'] = 0.0;
}
}
if (searchHash) {
keysArray = Object.keys(searchHash).map((key) => parseInt(key));
addFilter(table, 'id', 'in', keysArray);
table.setSort([
{column:'score', dir:'desc'}
]);
}
else {
removeFilterByField(table, 'id');
table.setSort([
DEFAULT_SORT
]);
}
})
})
}

function makeTable(data, searchArray) {
const RIGHT_ARROW = "\u27A1";
var initialFilter = (searchArray === undefined || searchArray === null) ?
[] : [{field: 'id', type: 'in', value: searchArray}];

columns = [ // Define Table Columns
{ title:"Dependency Name", field:"url", minWidth:150, maxWidth:200,
formatter:"link", formatterParams:{labelField:"name", urlPrefix:"{{ site.baseurl }}"}},
{ title:"Description", field:"description", minWidth:300},
{ title:RIGHT_ARROW, field:"usage", width:40, hozAlign:"right", headerTooltip:"dependency used by count"},
{ title:"score", field:"score", visible:false},
];

{% for cp in site.data.common.current_platforms %}
{% assign key = cp[0] %}
{% assign name = cp[1] %}
columns.push({ title: "{{ name }}", field: "{{ key }}", width: 90, headerTooltip:"{{ name }}", hozAlign:"center"});
{% endfor %}

const table = new Tabulator("#dependencies-table", {
columnDefaults:{ tooltip:true },
maxHeight:"100%",
data:data, //assign data to table
layout:"fitColumns", //fit columns to width of table (optional)
rowHeight:30, // Workaround for https://github.com/olifolkerd/tabulator/issues/4419
initialFilter: initialFilter,
initialSort: DEFAULT_SORT,
columns: columns,
});
return table;
}

// Returns a promise that resolves to a Tabulator table
function showTable(query) {
console.log(`showTable query: ${query}`);
var searchPromise = query ? getSearchHash(query) : Promise.resolve(null);
return Promise.all([getData(), searchPromise]).then(values => {
var data = values[0];
var searchHash = values[1];
searchArray = searchHash ? Object.keys(searchHash).map(ref => parseInt(ref)) : [];
const table = makeTable(data, searchArray);
$("#table-filtered-count").text(data.length);
$("#table-unfiltered-count").text(data.length);
table.on("dataFiltered", (filters, rows) => {
$("#table-filtered-count").text(rows.length);
$("#table-unfiltered-count").text(table.getDataCount());
});
table.on("tableBuilt", () => {
$("#table-filtered-count").text(table.getDataCount('active'));
$("#table-unfiltered-count").text(table.getDataCount());
});
return table;
});
}

$(function() {
console.log('document ready');
copySearchQueryToUI();
var query = getWindowSearchQuery();
showTable(query)
.then(table => gTable = table);

window.addEventListener('hashchange', (event) => {
var query = getWindowSearchQuery();
showTable(query)
.then(table => gTable = table);
});

$('#search-query').on('focus', (e) => {
// Pre-load index to speed up search response
getIndex();
});

$('#search-query').bind('keypress', (e) => {
if (e.which == 13) {
$("#search-enable-box").prop("checked", true);
copyUIToSearchQuery();
var query = getWindowSearchQuery() || '';
doSearch(gTable, query);
}
});

$("#search-enable-box").on('click', (e) => {
element = e.currentTarget;
console.log(`#search-enable click ${element.checked}`);
query = $("#search-query").val();
if (element.checked && query) {
copyUIToSearchQuery();
doSearch(gTable, query);
} else {
setWindowSearchQuery('');
removeFilterByField(gTable, 'id');
if (gTable) {
gTable.setSort(DEFAULT_SORT);
}
}
});

$("#search-button").on('click', (e) => {
query = $("#search-query").val();
if (query) {
$("#search-enable-box").prop("checked", true);
copyUIToSearchQuery();
doSearch(gTable, query);
}
});

});
</script>
1 change: 1 addition & 0 deletions _layouts/search_packages.html
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
<!-- See https://github.com/olifolkerd/tabulator/issues/4419 for issue with Tabulator post-5.6.0 -->
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/tabulator.min.css" rel="stylesheet">
<!-- <script src={{ "/js/tabulator.js" | prepend: site.baseurl }}></script> -->
<script src={{ "/js/distro_switch.js" | prepend: site.baseurl }}></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/tabulator.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/[email protected]/build/global/luxon.min.js"></script>
<script src="{{site.baseurl}}/js/lunr.js" type="text/javascript" charset="utf-8"></script>
Expand Down
Loading

0 comments on commit c78cf55

Please sign in to comment.