feat: Embedded Microsoft Office Viewer and Google Docs Viewer web services and no longer download as default action when viewer is supported when loading directory with file attachment that doesn't automatically render.

This commit is contained in:
David Ball 2024-06-24 01:02:26 -04:00
parent e0b93cf355
commit 1f1071f5a9
6 changed files with 104 additions and 44 deletions

View File

@ -186,6 +186,14 @@ const renderArchive = (html: string, paths: string[]) => {
return html;
}
const isMsOfficeViewerSupported = (file: string) => {
return path.extname(file).search(/^((?:.pptx)|(?:.docx)|(?:.xlsx)|(?:.ppt)|(?:.doc)|(?:.xls))$/ig) != -1;
}
const isGoogleDocsViewerSupported = (file: string) => {
return isMsOfficeViewerSupported(file) || path.extname(file).search(/^((?:.pdf))$/ig) != -1;
}
export default {
leftTrimFirstDirectory,
trimSlashes,
@ -205,4 +213,6 @@ export default {
inspect,
md,
moment,
isMsOfficeViewerSupported,
isGoogleDocsViewerSupported,
};

View File

@ -78,7 +78,7 @@ export default function () {
}
});
const renderData = { breadcrumbs, content, filePath, fullFilePath, paths, req, route, ...fmData };
res.render("page", { h: helpers, ...renderData });
res.render("page", { h: helpers, path, config, ...renderData });
});
});
@ -122,7 +122,7 @@ export default function () {
console.log(`Setting route for ${route}`);
pageRouter.get(route, async (req, res) => {
const html = fs.readFileSync(fullFilePath).toString();
const renderData = { route, filePath, fullFilePath, req, paths, html };
const renderData = { route, filePath, fullFilePath, req, paths, html, path, config };
res.render("archive", { h: helpers, ...renderData });
});
});
@ -183,7 +183,7 @@ export default function () {
}
});
const renderData = { breadcrumbs, route, filePath, fullFilePath, req, paths, directory: path.join('public', directory), videoURL, subtitleURL, subtitleVTT, info };
res.render("video-player", { h: helpers, ...renderData });
res.render("video-player", { h: helpers, path, config, ...renderData });
}
});
});

View File

@ -184,8 +184,9 @@ export const directoryTemplate = (vals: ServeDirectoryTemplateParameters) => {
});
}
return new Promise((resolve, reject) => {
ejs.renderFile(path.join(config.viewsPath, 'directory.ejs'), { breadcrumbs, h: helpers, ...vals }, (err, str) => {
ejs.renderFile(path.join(config.viewsPath, 'directory.ejs'), { h: helpers, path, config, breadcrumbs, ...vals }, (err, str) => {
if (err) {
console.error(err);
reject(err);
} else {
resolve(str);
@ -196,8 +197,9 @@ export const directoryTemplate = (vals: ServeDirectoryTemplateParameters) => {
export const errorTemplate = (vals: ServeErrorTemplateParameters) => {
return new Promise((resolve, reject) => {
ejs.renderFile(path.join(config.viewsPath, 'error.ejs'), { h: helpers, ...vals }, (err, str) => {
ejs.renderFile(path.join(config.viewsPath, 'error.ejs'), { h: helpers, path, config, ...vals }, (err, str) => {
if (err) {
console.error(err);
reject(err);
} else {
resolve(str);

View File

@ -4,18 +4,13 @@
<title><%=h.getDirectoryTitle(directory)%></title>
<%- include('./includes/common-head.ejs') %>
</head>
<body onload="initPage()">
<%- include('./includes/top-navbar.ejs') %>
<%- include('./includes/no-trash-svg.ejs') %>
<main class="container">
<header>
<%- include('./includes/breadcrumbs.ejs') %>
</header>
<% if (h.directoryContainsReadme(directory)) {%>
<div class="row p-4 pb-0 pe-lg-0 pt-lg-5 align-items-center rounded-3 border shadow-lg">
<div class="col-lg-12 p-3 p-lg-5 pt-lg-3">
@ -27,13 +22,69 @@
<b>Document Date:</b> <%= h.moment(h.readmeFm(directory).docDate).format('MMMM D, YYYY') %>
<% } %>
<%if (typeof h.readmeFm(directory).file !== 'undefined') { %>
<b>Attached Document:</b> <a href="<%- encodeURI(h.readmeFm(directory).file) %>"><%- h.readmeFm(directory).file %></a>
<b>Document:</b> <a href="<%- encodeURI(path.basename(h.readmeFm(directory).file)) %>"><%- h.readmeFm(directory).file %></a>
<% } %>
</small>
</p>
<% } %>
<% if (typeof h.readmeFm(directory).file !== 'undefined') { %>
<iframe src="<%- encodeURI(h.readmeFm(directory).file) %>" style="width: 100%; height: 90vh;"></iframe>
<ul class="nav nav-tabs" id="readerTab" role="tablist">
<% if (h.isMsOfficeViewerSupported(h.readmeFm(directory).file)) { %>
<li class="nav-item" role="presentation">
<button class="nav-link active" id="ms-office-viewer-tab" data-bs-toggle="tab" data-bs-target="#ms-office-viewer" type="button" role="tab" aria-controls="ms-office-viewer" aria-selected="true">Microsoft Office Web Viewer</button>
</li>
<% } %>
<% if (h.isGoogleDocsViewerSupported(h.readmeFm(directory).file)) { %>
<li class="nav-item" role="presentation">
<button class="nav-link<%=h.isMsOfficeViewerSupported(h.readmeFm(directory).file) ? '' : ' active'%>" id="google-docs-viewer-tab" data-bs-toggle="tab" data-bs-target="#google-docs-viewer" type="button" role="tab" aria-controls="google-docs-viewer" aria-selected="false">Google Docs Viewer</button>
</li>
<% } %>
<li class="nav-item" role="presentation">
<button class="nav-link" id="view-download-tab" data-bs-toggle="tab" data-bs-target="#view-download" type="button" role="tab" aria-controls="view-download" aria-selected="false">View/Download</button>
</li>
</ul>
<div class="tab-content">
<% if (h.isMsOfficeViewerSupported(h.readmeFm(directory).file)) { %>
<div class="tab-pane active" id="ms-office-viewer" role="tabpanel" aria-labelledby="ms-office-viewer-tab" tabindex="0">
<iframe src="https://view.officeapps.live.com/op/embed.aspx?src=<%- encodeURIComponent(h.trimSlashes(config.siteUrl) + path.posix.join(breadcrumbs[breadcrumbs.length-1].url, (h.readmeFm(directory).file.replaceAll('\\', '/')))) %>" style="width: 100%; height: 85vh; border: solid 1px #dfd7ca; border-top: 0px; border-bottom-left-radius: 0.25rem; border-bottom-right-radius: 0.25rem;" frameborder="0"></iframe>
</div>
<% } %>
<% if (h.isGoogleDocsViewerSupported(h.readmeFm(directory).file)) { %>
<div class="tab-pane<%=h.isMsOfficeViewerSupported(h.readmeFm(directory).file) ? '' : ' active'%>" id="google-docs-viewer" role="tabpanel" aria-labelledby="google-docs-viewer-tab" tabindex="0">
<iframe src="https://docs.google.com/gview?embedded=true&url=<%- encodeURIComponent(h.trimSlashes(config.siteUrl) + path.posix.join(breadcrumbs[breadcrumbs.length-1].url, (h.readmeFm(directory).file.replaceAll('\\', '/')))) %>" style="width: 100%; height: 85vh; border: solid 1px #dfd7ca; border-top: 0px; border-bottom-left-radius: 0.25rem; border-bottom-right-radius: 0.25rem;" frameborder="0"></iframe>
</div>
<% } %>
<div class="tab-pane<%=(h.isMsOfficeViewerSupported(h.readmeFm(directory).file) || h.isGoogleDocsViewerSupported(h.readmeFm(directory).file)) ? '' : ' active'%>" id="view-download" role="tabpanel" aria-labelledby="view-download-tab" tabindex="0">
<iframe src="about:blank" style="width: 100%; height: 85vh; border: solid 1px #dfd7ca; border-top: 0px; border-bottom-left-radius: 0.25rem; border-bottom-right-radius: 0.25rem;" frameborder="0"></iframe>
</div>
<script>
$(document).ready(function () {
var viewDownloadTabButton = $('button#view-download-tab');
var viewDownloadTab = new bootstrap.Tab(viewDownloadTabButton);
var viewDownloadTabPaneIFrame = $('#view-download iframe');
viewDownloadTabButton.on('click', function (event) {
event.preventDefault();
viewDownloadTab.show();
if (viewDownloadTabPaneIFrame.attr('src') == 'about:blank') {
console.log('View/Download tab clicked. Loading iframe.');
viewDownloadTabPaneIFrame.attr('src', '<%- encodeURI(h.readmeFm(directory).file) %>');
} else {
console.log('View/Download tab clicked. iframe previously loaded.');
}
})
})
</script>
<% if (!h.isMsOfficeViewerSupported(h.readmeFm(directory).file) && !h.isGoogleDocsViewerSupported(h.readmeFm(directory).file)) { %>
<script>
$(document).ready(function () {
setTimeout(function () {
var viewDownloadTabButton = $('button#view-download-tab');
viewDownloadTabButton.click();
}, 100);
});
</script>
<% } %>
</div>
<% } else { %>
<%- h.printReadme(directory) %>
<% } %>
@ -54,7 +105,6 @@
</div>
<% } %>
<% } %>
<ul id="files" class="list-group shadow-lg">
<% files.forEach(function(value, index) { %>
<li class="list-group-item list-group-item-action flex-column align-items-start">
@ -65,7 +115,6 @@
<% }); %>
</ul>
</main>
<%- include('./includes/bottom-navbar.ejs') %>
<%- include('./includes/bottom-scripts.ejs') %>
</body>

View File

@ -1,5 +1,4 @@
<!-- Bootstrap JS (optional, if you need Bootstrap JS features) -->
<script src="https://daball.me/vendor/jquery/jquery.min.js"></script>
<script src="https://daball.me/vendor/popper.js/dist/popper.min.js"></script>
<script src="https://daball.me/vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<script src="https://daball.me/vendor/jquery-easing/jquery.easing.min.js"></script>

View File

@ -10,7 +10,6 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8937572456576531" crossorigin="anonymous"></script>
<!-- Bootstrap CSS -->
<link href="https://daball.me/vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://fonts.googleapis.com/css?family=Saira+Extra+Condensed:100,200,300,400,500,600,700,800,900" rel="stylesheet" />
@ -26,3 +25,4 @@
<link href="https://daball.me/vendor/simple-line-icons/css/simple-line-icons.css" rel="stylesheet" />
<link href="https://daball.me/layouts/blog/css/blog.min.css" rel="stylesheet" />
<link href="/css/nm3clol.css" rel="stylesheet" />
<script src="https://daball.me/vendor/jquery/jquery.min.js"></script>