mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2025-06-06 18:30:57 +00:00

# Description of Changes The change this PR aims to introduce is a setting for enabling an upload file size limit. The author of the issue mentioned in this PR wanted this feature as they themselves enforced a limit of 50MB file sizes on their NGINX configuration. This was implemented by adding an entry to the [settings.yml.template](e52fc0e478/src/main/resources/settings.yml.template
) file. This entry has two sub-configurations in which you declare if the application should enable upload file size limiting and then you declare the limit itself. For this to be available in code, a new field in the [System](e52fc0e478/src/main/java/stirling/software/SPDF/model/ApplicationProperties.java (L280)
) class was added, one named `uploadLimit`. After that, inside the [AppConfig](url) class, a new thymeleaf bean was created, one called `uploadLimit`. This bean takes the values available in the `System` class and creates a `long` value representing the limit value. This value is interpreted as non-existent if it is `0`, otherwise it is the value in `bytes` of the upload limit. In order to make this value available in the [common.html](e52fc0e478/src/main/resources/templates/fragments/common.html
) file, where the submitFile form is imported from, a new controller [GlobalUploadLimitWebController](e52fc0e478/src/main/java/stirling/software/SPDF/controller/web/GlobalUploadLimitWebController.java
) was created. This controller has the tag `ControllerAdvice` so that every controller has the `ModelAttributes` defined within it. I am not sure if this was a good approach but upon first investigations, I couldn't find another method to make these attributes available in every Controller, or template. If there is already a place like this in the code with this specific purpose, please let me know so I can fix it. After making these attributes available, I updated the code in `common.html`to now display the upload limit if it is defined. This was done with localization in mind. Lastly, the [downloader.js](e52fc0e478/src/main/resources/static/js/downloader.js
) and [fileInput.js](e52fc0e478/src/main/resources/static/js/fileInput.js
) files to include logic to enforce the upload limit if it is defined. The UI updates, when the upload limit is defined, are as so: <img width="708" alt="image" src="https://github.com/user-attachments/assets/4852fa10-2ec3-45cb-83e6-41a102f256d4" /> When the limit is disabled, the page looks exactly as it did before any implementation: <img width="707" alt="image" src="https://github.com/user-attachments/assets/21e5e810-ffdc-4a99-a16d-491aea103709" />\\ Thank you. Closes #2903 --- ## Checklist ### General - [x] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [x] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md) (if applicable) - [x] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md) (if applicable) - [x] I have performed a self-review of my own code - [x] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [x] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### UI Changes (if applicable) - [x] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [x] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#6-testing) for more details. --------- Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
322 lines
17 KiB
HTML
322 lines
17 KiB
HTML
<th:block th:fragment="head">
|
|
<!-- Title -->
|
|
<title th:text="${@appName} + (${title} != null and ${title} != '' ? ' - ' + ${title} : '')"></title>
|
|
|
|
<!-- Metadata -->
|
|
<meta charset="utf-8">
|
|
<meta name="description" th:content="${@appName} + (${header} != null and ${header} != '' ? ' - ' + ${header} : '')">
|
|
<meta name="msapplication-TileColor" content="#2d89ef">
|
|
<meta name="theme-color" content="#ffffff">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
|
<!-- Icons -->
|
|
<link rel="apple-touch-icon" sizes="180x180" th:href="@{'/apple-touch-icon.png'}">
|
|
<link rel="icon" type="image/png" sizes="32x32" th:href="@{'/favicon-32x32.png'}">
|
|
<link rel="icon" type="image/png" sizes="16x16" th:href="@{'/favicon-16x16.png'}">
|
|
<link rel="manifest" th:href="@{'/site.webmanifest'}" crossorigin="use-credentials">
|
|
<link rel="mask-icon" th:href="@{'/safari-pinned-tab.svg'}" color="#ca2b2a">
|
|
<link rel="shortcut icon" th:href="@{'/favicon.ico'}">
|
|
<meta name="apple-mobile-web-app-title" content="Stirling PDF">
|
|
<meta name="application-name" content="Stirling PDF">
|
|
<meta name="msapplication-TileColor" content="#00aba9">
|
|
<meta name="theme-color" content="#ffffff">
|
|
|
|
<script>
|
|
window.stirlingPDF = window.stirlingPDF || {};
|
|
</script>
|
|
<script th:src="@{'/js/thirdParty/pdf-lib.min.js'}"></script>
|
|
<script th:src="@{'/js/fetch-utils.js'}"></script>
|
|
<!-- jQuery -->
|
|
<script th:src="@{'/js/thirdParty/jquery.min.js'}"></script>
|
|
<script th:src="@{'/js/thirdParty/jquery.validate.min.js'}"></script>
|
|
<script th:src="@{'/js/thirdParty/jszip.min.js'}" th:if="${currentPage != 'home'}"></script>
|
|
|
|
<!-- Bootstrap -->
|
|
<script th:src="@{'/js/thirdParty/popper.min.js'}"></script>
|
|
<script th:src="@{'/js/thirdParty/bootstrap.min.js'}"></script>
|
|
|
|
<link rel="stylesheet" th:href="@{'/css/bootstrap.min.css'}">
|
|
|
|
<!-- Bootstrap Icons -->
|
|
<link rel="stylesheet" th:href="@{'/css/bootstrap-icons.min.css'}">
|
|
|
|
<!-- Pixel, doesn't collect any PII-->
|
|
<img referrerpolicy="no-referrer-when-downgrade" src="https://pixel.stirlingpdf.com/a.png?x-pxid=4f5fa02f-a065-4efb-bb2c-24509a4b6b92" style="position: absolute; visibility: hidden;"/>
|
|
|
|
<!-- Custom -->
|
|
<link rel="stylesheet" th:href="@{'/css/general.css'}">
|
|
<link rel="stylesheet" th:href="@{'/css/theme/theme.css'}">
|
|
<link rel="stylesheet" th:href="@{'/css/theme/componentes.css'}">
|
|
<link rel="stylesheet" th:href="@{'/css/theme/theme.light.css'}" id="light-mode-styles">
|
|
<link rel="stylesheet" th:href="@{'/css/theme/theme.dark.css'}" id="dark-mode-styles">
|
|
<link rel="stylesheet" th:href="@{'/css/rainbow-mode.css'}" id="rainbow-mode-styles" disabled>
|
|
<link rel="stylesheet" th:href="@{'/css/tab-container.css'}">
|
|
<link rel="stylesheet" th:href="@{'/css/navbar.css'}">
|
|
|
|
<link rel="stylesheet" th:href="@{'/css/error.css'}" th:if="${error}">
|
|
|
|
<link rel="stylesheet" th:href="@{'/css/home.css'}" th:if="${currentPage == 'home'}">
|
|
<link rel="stylesheet" th:href="@{'/css/home-legacy.css'}" th:if="${currentPage == 'home-legacy'}">
|
|
<link rel="stylesheet" th:href="@{'/css/account.css'}" th:if="${currentPage == 'account'}">
|
|
<link rel="stylesheet" th:href="@{'/css/licenses.css'}" th:if="${currentPage == 'licenses'}">
|
|
<link rel="stylesheet" th:href="@{'/css/multi-tool.css'}" th:if="${currentPage == 'multi-tool'}">
|
|
<link rel="stylesheet" th:href="@{'/css/rotate-pdf.css'}" th:if="${currentPage == 'rotate-pdf'}">
|
|
<link rel="stylesheet" th:href="@{'/css/stamp.css'}" th:if="${currentPage == 'stamp'}">
|
|
<link rel="stylesheet" th:href="@{'/css/fileSelect.css'}" th:if="${currentPage != 'home'}">
|
|
<link rel="stylesheet" th:href="@{'/css/footer.css'}">
|
|
|
|
<link rel="preload" th:href="@{'/fonts/google-symbol.woff2'}" as="font" type="font/woff2" crossorigin="anonymous">
|
|
<link rel="stylesheet" th:href="@{'/css/cookieconsent.css'}">
|
|
<link rel="stylesheet" th:href="@{'/css/cookieconsentCustomisation.css'}">
|
|
<script th:src="@{'/js/thirdParty/fontfaceobserver.standalone.js'}"></script>
|
|
|
|
<!-- Google MD Icons -->
|
|
<link rel="stylesheet" th:href="@{'/css/theme/font.css'}">
|
|
|
|
<!-- Help Modal -->
|
|
<link rel="stylesheet" th:href="@{'/css/errorBanner.css'}" th:if="${currentPage != 'home'}">
|
|
|
|
<script th:src="@{'/js/cacheFormInputs.js'}" th:if="${currentPage != 'home'}"></script>
|
|
<script th:src="@{'/js/tab-container.js'}"></script>
|
|
<script th:src="@{'/js/darkmode.js'}"></script>
|
|
<script th:src="@{'/js/csrf.js'}"></script>
|
|
<script th:inline="javascript">
|
|
|
|
function UpdatePosthogConsent(){
|
|
if(typeof(posthog) == "undefined") {
|
|
console.log("Posthog not initialised");
|
|
return;
|
|
}
|
|
|
|
window.CookieConsent.acceptedCategory('analytics')?
|
|
posthog.opt_in_capturing() : posthog.opt_out_capturing();
|
|
console.log("Posthog: Opted " + (posthog.has_opted_out_capturing()? "out" : "in"));
|
|
}
|
|
const stirlingPDFLabel = /*[[${@StirlingPDFLabel}]]*/ '';
|
|
const analyticsEnabled = /*[[${@analyticsEnabled}]]*/ false;
|
|
|
|
const cookieBannerPopUpTitle = /*[[#{cookieBanner.popUp.title}]]*/ "How we use Cookies";
|
|
const cookieBannerPopUpDescription1 = /*[[#{cookieBanner.popUp.description.1}]]*/ "";
|
|
const cookieBannerPopUpDescription2 = /*[[#{cookieBanner.popUp.description.2}]]*/ "";
|
|
const cookieBannerPopUpAcceptAllBtn = /*[[#{cookieBanner.popUp.acceptAllBtn}]]*/ "";
|
|
const cookieBannerPopUpAcceptNecessaryBtn = /*[[#{cookieBanner.popUp.acceptNecessaryBtn}]]*/ "";
|
|
const cookieBannerPopUpShowPreferencesBtn = /*[[#{cookieBanner.popUp.showPreferencesBtn}]]*/ "";
|
|
const cookieBannerPreferencesModalTitle = /*[[#{cookieBanner.preferencesModal.title}]]*/ "";
|
|
const cookieBannerPreferencesModalAcceptAllBtn = /*[[#{cookieBanner.preferencesModal.acceptAllBtn}]]*/ "";
|
|
const cookieBannerPreferencesModalAcceptNecessaryBtn = /*[[#{cookieBanner.preferencesModal.acceptNecessaryBtn}]]*/ "";
|
|
const cookieBannerPreferencesModalSavePreferencesBtn = /*[[#{cookieBanner.preferencesModal.savePreferencesBtn}]]*/ "";
|
|
const cookieBannerPreferencesModalCloseIconLabel = /*[[#{cookieBanner.preferencesModal.closeIconLabel}]]*/ "";
|
|
const cookieBannerPreferencesModalServiceCounterLabel = /*[[#{cookieBanner.preferencesModal.serviceCounterLabel}]]*/ "";
|
|
const cookieBannerPreferencesModalSubtitle = /*[[#{cookieBanner.preferencesModal.subtitle}]]*/ "";
|
|
const cookieBannerPreferencesModalDescription1 = /*[[#{cookieBanner.preferencesModal.description.1}]]*/ "";
|
|
const cookieBannerPreferencesModalDescription2= /*[[#{cookieBanner.preferencesModal.description.2}]]*/ "";
|
|
const cookieBannerPreferencesModalDescription3 = /*[[#{cookieBanner.preferencesModal.description.3}]]*/ "";
|
|
const cookieBannerPreferencesModalNecessaryTitle1 = /*[[#{cookieBanner.preferencesModal.necessary.title.1}]]*/ "";
|
|
const cookieBannerPreferencesModalNecessaryTitle2 = /*[[#{cookieBanner.preferencesModal.necessary.title.2}]]*/ "";
|
|
const cookieBannerPreferencesModalNecessaryDescription = /*[[#{cookieBanner.preferencesModal.necessary.description}]]*/ "";
|
|
const cookieBannerPreferencesModalAnalyticsTitle = /*[[#{cookieBanner.preferencesModal.analytics.title}]]*/ "";
|
|
const cookieBannerPreferencesModalAnalyticsDescription = /*[[#{cookieBanner.preferencesModal.analytics.description}]]*/ "";
|
|
|
|
if (analyticsEnabled) {
|
|
!function (t, e) {
|
|
var o, n, p, r;
|
|
e.__SV || (window.posthog = e, e._i = [], e.init = function (i, s, a) {
|
|
function g(t, e) {
|
|
var o = e.split(".");
|
|
2 == o.length && (t = t[o[0]], e = o[1]), t[e] = function () {
|
|
t.push([e].concat(Array.prototype.slice.call(arguments, 0)))
|
|
}
|
|
}
|
|
|
|
(p = t.createElement("script")).type = "text/javascript", p.async = !0, p.src = s.api_host + "/static/array.js", (r = t.getElementsByTagName("script")[0]).parentNode.insertBefore(p, r);
|
|
var u = e;
|
|
for (void 0 !== a ? u = e[a] = [] : a = "posthog", u.people = u.people || [], u.toString = function (t) {
|
|
var e = "posthog";
|
|
return "posthog" !== a && (e += "." + a), t || (e += " (stub)"), e
|
|
}, u.people.toString = function () {
|
|
return u.toString(1) + ".people (stub)"
|
|
}, o = "capture identify alias people.set people.set_once set_config register register_once unregister opt_out_capturing has_opted_out_capturing opt_in_capturing reset isFeatureEnabled onFeatureFlags getFeatureFlag getFeatureFlagPayload reloadFeatureFlags group updateEarlyAccessFeatureEnrollment getEarlyAccessFeatures getActiveMatchingSurveys getSurveys getNextSurveyStep onSessionId".split(" "), n = 0; n < o.length; n++) g(u, o[n]);
|
|
e._i.push([i, s, a])
|
|
}, e.__SV = 1)
|
|
}(document, window.posthog || []);
|
|
posthog.init('phc_fiR65u5j6qmXTYL56MNrLZSWqLaDW74OrZH0Insd2xq', {
|
|
api_host: 'https://eu.i.posthog.com',
|
|
persistence: 'localStorage',
|
|
person_profiles: 'always',
|
|
mask_all_text: true,
|
|
mask_all_element_attributes: true,
|
|
opt_out_capturing_by_default: true
|
|
})
|
|
const baseUrl = window.location.hostname;
|
|
posthog.register_once({
|
|
'hostname': baseUrl,
|
|
'UUID': /*[[${@UUID}]]*/ ''
|
|
})
|
|
}
|
|
|
|
window.addEventListener("cc:onConsent", UpdatePosthogConsent);
|
|
window.addEventListener("cc:onChange", UpdatePosthogConsent);
|
|
</script>
|
|
</th:block>
|
|
|
|
<th:block th:fragment="game">
|
|
<dialog id="game-container-wrapper" class="game-container-wrapper" data-bs-modal>
|
|
<script th:inline="javascript">
|
|
console.log("loaded game");
|
|
$(document).ready(function () {
|
|
|
|
// Find the file input within the form
|
|
var fileInput = $('input[type="file"]');
|
|
|
|
// Find the closest enclosing form of the file input
|
|
var form = fileInput.closest('form');
|
|
|
|
// Find the submit button within the form
|
|
var submitButton = form.find('button[type="submit"], input[type="submit"]');
|
|
|
|
const boredWaitingText = /*[[#{bored}]]*/ 'Bored Waiting?';
|
|
const downloadCompleteText = /*[[#{downloadComplete}]]*/ 'Download Complete';
|
|
window.downloadCompleteText = downloadCompleteText;
|
|
// Create the 'show-game-btn' button
|
|
var gameButton = $('<button type="button" class="btn btn-primary" id="show-game-btn" style="display:none;">' + boredWaitingText + '</button>');
|
|
|
|
// Insert the 'show-game-btn' just above the submit button
|
|
submitButton.before(gameButton);
|
|
|
|
function loadGameScript(callback) {
|
|
console.log('loadGameScript called');
|
|
const script = document.createElement('script');
|
|
script.src = 'js/game.js';
|
|
script.onload = callback;
|
|
document.body.appendChild(script);
|
|
}
|
|
let gameScriptLoaded = false;
|
|
const gameDialog = document.getElementById('game-container-wrapper');
|
|
$('#show-game-btn').on('click', function () {
|
|
console.log('Show game button clicked');
|
|
if (!gameScriptLoaded) {
|
|
console.log('Show game button load');
|
|
loadGameScript(function () {
|
|
console.log('Game script loaded');
|
|
window.initializeGame();
|
|
gameScriptLoaded = true;
|
|
});
|
|
} else {
|
|
window.resetGame();
|
|
}
|
|
gameDialog.showModal();
|
|
});
|
|
gameDialog.addEventListener("click", e => {
|
|
const dialogDimensions = gameDialog.getBoundingClientRect()
|
|
if (
|
|
e.clientX < dialogDimensions.left ||
|
|
e.clientX > dialogDimensions.right ||
|
|
e.clientY < dialogDimensions.top ||
|
|
e.clientY > dialogDimensions.bottom
|
|
) {
|
|
gameDialog.close();
|
|
}
|
|
})
|
|
})
|
|
</script>
|
|
<div id="game-container">
|
|
<div id="lives">Lives: 3</div>
|
|
<div id="score">Score: 0</div>
|
|
<div id="high-score">High Score: 0</div>
|
|
<div id="level">Level: 1</div>
|
|
<img th:src="@{'/favicon.svg'}" class="player" id="player" alt="favicon">
|
|
</div>
|
|
<link rel="stylesheet" th:href="@{'/css/game.css'}">
|
|
</dialog>
|
|
</th:block>
|
|
|
|
<th:block th:fragment="fileSelector(name, multipleInputsForSingleRequest)"
|
|
th:with="accept=${accept} ?: '*/*', inputText=${inputText} ?: #{pdfPrompt}, remoteCall=${remoteCall} ?: true, disableMultipleFiles=${disableMultipleFiles} ?: false, showUploads=${showUploads} ?: true, notRequired=${notRequired} ?: false">
|
|
<script th:inline="javascript">
|
|
(function () {
|
|
window.stirlingPDF.pdfPasswordPrompt = /*[[#{error.pdfPassword}]]*/ '';
|
|
window.stirlingPDF.multipleInputsForSingleRequest = /*[[${multipleInputsForSingleRequest}]]*/ false;
|
|
window.stirlingPDF.disableMultipleFiles = /*[[${disableMultipleFiles}]]*/ false;
|
|
window.stirlingPDF.remoteCall = /*[[${remoteCall}]]*/ true;
|
|
window.stirlingPDF.sessionExpired = /*[[#{session.expired}]]*/ '';
|
|
window.stirlingPDF.refreshPage = /*[[#{session.refreshPage}]]*/ 'Refresh Page';
|
|
window.stirlingPDF.error = /*[[#{error}]]*/ "Error";
|
|
window.stirlingPDF.uploadLimit = /*[[${uploadLimit}]]*/ 0;
|
|
window.stirlingPDF.uploadLimitReadable = /*[[${uploadLimitReadable}]]*/ 'Unlimited';
|
|
window.stirlingPDF.uploadLimitExceededSingular = /*[[#{uploadLimitExceededSingular}]]*/ 'is too large. Maximum allowed size is';
|
|
window.stirlingPDF.uploadLimitExceededPlural = /*[[#{uploadLimitExceededPlural}]]*/ 'are too large. Maximum allowed size is';
|
|
})();
|
|
</script>
|
|
<script type="module" th:src="@{'/pdfjs-legacy/pdf.mjs'}"></script>
|
|
<script th:src="@{'/js/downloader.js'}"></script>
|
|
<script>
|
|
window.decrypt = {
|
|
passwordPrompt: '[[#{decrypt.passwordPrompt}]]',
|
|
cancelled: '[[#{decrypt.cancelled}]]',
|
|
noPassword: '[[#{decrypt.noPassword}]]',
|
|
invalidPassword: '[[#{decrypt.invalidPassword}]]',
|
|
invalidPasswordHeader: '[[#{decrypt.invalidPasswordHeader}]]',
|
|
unexpectedError: '[[#{decrypt.unexpectedError}]]',
|
|
serverError: '[[#{decrypt.serverError}]]',
|
|
success: '[[#{decrypt.success}]]',
|
|
};
|
|
window.fileInput = {
|
|
dragAndDropPDF: '[[#{fileChooser.dragAndDropPDF}]]',
|
|
dragAndDropImage: '[[#{fileChooser.dragAndDropImage}]]',
|
|
extractPDF: '[[#{fileChooser.extractPDF}]]',
|
|
loading: '[[#{loading}]]'
|
|
};</script>
|
|
<div class="custom-file-chooser mb-3"
|
|
|
|
th:attr="data-bs-unique-id=${name}, data-bs-element-id=${name+'-input'}, data-bs-element-container-id=${name+'-input-container'}, data-bs-show-uploads=${showUploads}, data-bs-files-selected=#{filesSelected}, data-bs-pdf-prompt=#{pdfPrompt}, data-bs-no-file-selected=#{noFileSelected}">
|
|
<div class="mb-3 d-flex flex-column justify-content-center align-items-center flex-wrap input-container"
|
|
th:name="${name}+'-input'" th:id="${name}+'-input-container'" th:data-text="#{fileChooser.hoveredDragAndDrop}">
|
|
<label class="file-input-btn d-none">
|
|
<input type="file" class="form-control"
|
|
th:name="${name}"
|
|
th:id="${name}+'-input'"
|
|
th:accept="${accept == null ? '*/*': ((accept == '*/*') ? accept : (accept + ',.zip'))}"
|
|
th:attr="multiple=${!disableMultipleFiles}"
|
|
th:required="${notRequired} ? null : 'required'">
|
|
Browse
|
|
</label>
|
|
<div class="d-flex flex-column align-items-center">
|
|
<div class="d-flex justify-content-start align-items-center" id="fileInputText">
|
|
<div th:text="#{fileChooser.click}" style="margin-right: 5px"></div>
|
|
<div th:text="#{fileChooser.or}" style="margin-right: 5px"></div>
|
|
<div th:text="#{fileChooser.dragAndDrop}" id="dragAndDrop"></div>
|
|
</div>
|
|
<hr th:if="${@GoogleDriveEnabled == true}" class="horizontal-divider" >
|
|
</div>
|
|
<div th:if="${@GoogleDriveEnabled == true}" th:id="${name}+'-google-drive-button'" class="google-drive-button" th:attr="data-name=${name}, data-multiple=${!disableMultipleFiles}, data-accept=${accept}" >
|
|
<img th:src="@{'/images/google-drive.svg'}" alt="google drive">
|
|
</div>
|
|
</div>
|
|
<div class="selected-files flex-wrap"></div>
|
|
<div class="text-muted small mt-0 text-end w-100" th:if="${uploadLimit != 0}">
|
|
<span th:text="#{uploadLimit}">Maximum file size: </span>
|
|
<span th:text="${uploadLimitReadable}"></span>
|
|
</div>
|
|
</div>
|
|
<div class="progressBarContainer" style="display: none; position: relative;">
|
|
<div class="progress" style="height: 1rem;">
|
|
<div class="progressBar progress-bar progress-bar-striped progress-bar-animated bg-success" role="progressbar"
|
|
aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%;">
|
|
<span class="visually-hidden">Loading...</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<script th:src="@{'/js/fileInput.js'}" type="module"></script>
|
|
|
|
<div th:if="${@GoogleDriveEnabled == true}" >
|
|
<script type="text/javascript" th:src="@{'/js/googleFilePicker.js'}"></script>
|
|
<script async defer src="https://apis.google.com/js/api.js" onload="gapiLoaded()"></script>
|
|
<script async defer src="https://accounts.google.com/gsi/client" onload="gisLoaded()"></script>
|
|
|
|
<script th:inline="javascript">
|
|
window.stirlingPDF.GoogleDriveClientId = /*[[${@GoogleDriveConfig.getClientId()}]]*/ null;
|
|
window.stirlingPDF.GoogleDriveApiKey = /*[[${@GoogleDriveConfig.getApiKey()}]]*/ null;
|
|
window.stirlingPDF.GoogleDriveAppId = /*[[${@GoogleDriveConfig.getAppId()}]]*/ null;
|
|
</script>
|
|
</div>
|
|
</th:block> |