Skip to content

Commit

Permalink
added dynamic and subset loading of zim-files in kiwix-serve
Browse files Browse the repository at this point in the history
  • Loading branch information
MananJethwani committed May 26, 2021
1 parent 188694f commit 03d7d4e
Show file tree
Hide file tree
Showing 6 changed files with 170 additions and 86 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ subprojects/googletest-release*
*.class
build/
.vscode/
builddir/
25 changes: 2 additions & 23 deletions src/server/internalServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -281,27 +281,6 @@ MustacheData InternalServer::get_default_data() const
return data;
}

MustacheData InternalServer::homepage_data() const
{
auto data = get_default_data();

MustacheData books{MustacheData::type::list};
for (auto& bookId: mp_library->filter(kiwix::Filter().local(true).valid(true))) {
auto& currentBook = mp_library->getBookById(bookId);

MustacheData book;
book.set("name", mp_nameMapper->getNameForId(bookId));
book.set("title", currentBook.getTitle());
book.set("description", currentBook.getDescription());
book.set("articleCount", beautifyInteger(currentBook.getArticleCount()));
book.set("mediaCount", beautifyInteger(currentBook.getMediaCount()));
books.push_back(book);
}

data.set("books", books);
return data;
}

bool InternalServer::etag_not_needed(const RequestContext& request) const
{
const std::string url = request.get_url();
Expand All @@ -325,7 +304,7 @@ InternalServer::get_matching_if_none_match_etag(const RequestContext& r) const

std::unique_ptr<Response> InternalServer::build_homepage(const RequestContext& request)
{
return ContentResponse::build(*this, RESOURCE::templates::index_html, homepage_data(), "text/html; charset=utf-8");
return ContentResponse::build(*this, RESOURCE::templates::index_html, get_default_data(), "text/html; charset=utf-8");
}

std::unique_ptr<Response> InternalServer::handle_meta(const RequestContext& request)
Expand Down Expand Up @@ -663,7 +642,7 @@ std::vector<std::string>
InternalServer::search_catalog(const RequestContext& request,
kiwix::OPDSDumper& opdsDumper)
{
auto filter = kiwix::Filter().valid(true).local(true).remote(true);
auto filter = kiwix::Filter().valid(true).local(true);
string query("<Empty query>");
size_t count(10);
size_t startIndex(0);
Expand Down
1 change: 0 additions & 1 deletion src/server/internalServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ class InternalServer {
kiwix::OPDSDumper& opdsDumper);

MustacheData get_default_data() const;
MustacheData homepage_data() const;

std::shared_ptr<Reader> get_reader(const std::string& bookName) const;
bool etag_not_needed(const RequestContext& r) const;
Expand Down
1 change: 1 addition & 0 deletions static/resources_list.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ skin/jquery-ui/jquery-ui.theme.min.css
skin/jquery-ui/jquery-ui.min.css
skin/caret.png
skin/taskbar.js
skin/index.js
skin/taskbar.css
skin/block_external.js
templates/search_result.html
Expand Down
74 changes: 74 additions & 0 deletions static/skin/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
(function() {
const root = $(`link[type='root']`).attr('href');
let isFetching = false;
const incrementalLoadingParams = {
start: 0,
count: viewPortToCount()
};

function queryUrlBuilder() {
let url = `${root}/catalog/search?`;
url += Object.keys(incrementalLoadingParams).map(key => `${key}=${incrementalLoadingParams[key]}`).join("&");
return url;
}

function viewPortToCount(){
return Math.floor(window.innerHeight/100 + 1)*(window.innerWidth>1000 ? 3 : 2);
}

function getInnerHtml(node, query) {
return node.querySelector(query).innerHTML;
}

function generateBookHtml(book) {
const link = book.querySelector('link').getAttribute('href');
const title = getInnerHtml(book, 'title');
const description = getInnerHtml(book, 'summary');
const id = getInnerHtml(book, 'id');
const iconUrl = getInnerHtml(book, 'icon');
const articleCount = getInnerHtml(book, 'articleCount');
const mediaCount = getInnerHtml(book, 'mediaCount');

return `<a href='${link}' data-id='${id}'><div class='book'>
<div class='book__background' style="background-image: url('${iconUrl}');">
<div class='book__title' title='${title}'>${title}</div>
<div class='book__description' title='${description}'>${description}</div>
<div class='book__info'>${articleCount} articles, ${mediaCount} medias</div>
</div>
</div></a>`;
}

async function loadAndDisplayBooks() {
if (isFetching) return;
isFetching = true;
fetch(queryUrlBuilder()).then(async (resp) => {
const data = new window.DOMParser().parseFromString(await resp.text(), 'application/xml');
const books = data.querySelectorAll('entry');
let bookHtml = '';
books.forEach((book) => {bookHtml += generateBookHtml(book)});
document.querySelector('.book__list').innerHTML += bookHtml;
incrementalLoadingParams.start += books.length;
if (books.length < incrementalLoadingParams.count) {
incrementalLoadingParams.count = 0;
}
isFetching = false;
});
}

async function loadSubset() {
if (incrementalLoadingParams.count && window.innerHeight + window.scrollY >= document.body.offsetHeight) {
loadAndDisplayBooks();
}
}

window.addEventListener('resize', async () => {
incrementalLoadingParams.count = incrementalLoadingParams.count && viewPortToCount();
loadSubset();
});

window.addEventListener('scroll', loadSubset);

window.onload = async () => {
loadAndDisplayBooks();
}
})();
154 changes: 92 additions & 62 deletions static/templates/index.html
Original file line number Diff line number Diff line change
@@ -1,66 +1,96 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8" />
<title>Welcome to Kiwix Server</title>
<script type="text/javascript" src="{{root}}/skin/jquery-ui/external/jquery/jquery.js"></script>
<script type="text/javascript" src="{{root}}/skin/jquery-ui/jquery-ui.min.js"></script>
<link type="text/css" href="{{root}}/skin/jquery-ui/jquery-ui.min.css" rel="Stylesheet" />
<link type="text/css" href="{{root}}/skin/jquery-ui/jquery-ui.theme.min.css" rel="Stylesheet" />
<style>
body {
background:
radial-gradient(#EEEEEE 15%, transparent 16%) 0 0,
radial-gradient(#EEEEEE 15%, transparent 16%) 8px 8px,
radial-gradient(rgba(255,255,255,.1) 15%, transparent 20%) 0 1px,
radial-gradient(rgba(255,255,255,.1) 15%, transparent 20%) 8px 9px;
background-color:#E8E8E8;
background-size:16px 16px;
margin-left: auto;
margin-right: auto;
max-width: 1100px;
}
.book__list { text-align: center; }
.book {
display: inline-block; vertical-align: bottom; margin: 8px; padding: 12px 15px; width: 300px;
border: 1px solid #ccc; border-radius: 8px;
text-align: left; color: #000; font-family: sans-serif; font-size: 13px;
background-color:#F1F1F1;
box-shadow: 2px 2px 5px 0px #ccc;
}
.book:hover { background-color: #F9F9F9; box-shadow: none;}
.book__background { background-repeat: no-repeat; background-size: 48px 48px; background-position: top right; }
.book__title {
padding: 0 55px 0 0;overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
font-size: 18px; color: #0645ad; line-height: 1em;
}
.book__description {
padding: 5px 55px 5px 0px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
font-size: 15px; line-height: 1em;
}
.book__info { color: #777; font-weight: bold; font-size: 13px; line-height: 1em; }
</style>
<script type="text/javascript" src="{{root}}/skin/taskbar.js" async></script>
</head>
<body class="kiwix">
<head>
<meta charset="UTF-8" />
<title>Welcome to Kiwix Server</title>
<script
type="text/javascript"
src="{{root}}/skin/jquery-ui/external/jquery/jquery.js"
></script>
<script
type="text/javascript"
src="{{root}}/skin/jquery-ui/jquery-ui.min.js"
></script>
<link
type="text/css"
href="{{root}}/skin/jquery-ui/jquery-ui.min.css"
rel="Stylesheet"
/>
<link
type="text/css"
href="{{root}}/skin/jquery-ui/jquery-ui.theme.min.css"
rel="Stylesheet"
/>
<style>
body {
background: radial-gradient(#eeeeee 15%, transparent 16%) 0 0,
radial-gradient(#eeeeee 15%, transparent 16%) 8px 8px,
radial-gradient(rgba(255, 255, 255, 0.1) 15%, transparent 20%) 0 1px,
radial-gradient(rgba(255, 255, 255, 0.1) 15%, transparent 20%) 8px 9px;
background-color: #e8e8e8;
background-size: 16px 16px;
margin-left: auto;
margin-right: auto;
max-width: 1100px;
}
.book__list {
text-align: center;
}
.book {
display: inline-block;
vertical-align: bottom;
margin: 8px;
padding: 12px 15px;
width: 300px;
border: 1px solid #ccc;
border-radius: 8px;
text-align: left;
color: #000;
font-family: sans-serif;
font-size: 13px;
background-color: #f1f1f1;
box-shadow: 2px 2px 5px 0px #ccc;
}
.book:hover {
background-color: #f9f9f9;
box-shadow: none;
}
.book__background {
background-repeat: no-repeat;
background-size: 48px 48px;
background-position: top right;
}
.book__title {
padding: 0 55px 0 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 18px;
color: #0645ad;
line-height: 1em;
}
.book__description {
padding: 5px 55px 5px 0px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 15px;
line-height: 1em;
}
.book__info {
color: #777;
font-weight: bold;
font-size: 13px;
line-height: 1em;
}
</style>
<script type="text/javascript" src="{{root}}/skin/index.js" async></script>
</head>
<body class="kiwix">
<div class="kiwix">
<div class="book__list"></div>
</div>

<div class="kiwix">
<div class='book__list'>
{{#books}}
<a href="{{root}}/{{name}}"><div class='book'>
<div class='book__background' style="background-image: url('{{root}}/meta?content={{#urlencoded}}{{{name}}}{{/urlencoded}}&name=favicon');">
<div class='book__title' title='{{title}}'>{{title}}</div>
<div class='book__description' title='{{description}}'>{{description}}</div>
<div class='book__info'>{{articleCount}} articles, {{mediaCount}} medias</div>
</div>
</div></a>
{{/books}}
</div>
</div>

<div id="kiwixfooter">
Powered by <a href="https://kiwix.org">Kiwix</a>
</div>

</body>
<div id="kiwixfooter">Powered by <a href="https://kiwix.org">Kiwix</a></div>
</body>
</html>

0 comments on commit 03d7d4e

Please sign in to comment.