Merge branch 'main' into session_2025_03_22

This commit is contained in:
Ludy 2025-04-05 15:30:36 +00:00 committed by GitHub
commit b68a3dfd6b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 318 additions and 63 deletions

View File

@ -112,7 +112,7 @@
"ms-python.flake8", // Flake8 linter for Python to enforce code quality "ms-python.flake8", // Flake8 linter for Python to enforce code quality
"ms-python.python", // Official Microsoft Python extension with IntelliSense, debugging, and Jupyter support "ms-python.python", // Official Microsoft Python extension with IntelliSense, debugging, and Jupyter support
"ms-vscode-remote.vscode-remote-extensionpack", // Remote Development Pack for SSH, WSL, and Containers "ms-vscode-remote.vscode-remote-extensionpack", // Remote Development Pack for SSH, WSL, and Containers
"Oracle.oracle-java", // Oracle Java extension with additional features for Java development // "Oracle.oracle-java", // Oracle Java extension with additional features for Java development
"streetsidesoftware.code-spell-checker", // Spell checker for code to avoid typos "streetsidesoftware.code-spell-checker", // Spell checker for code to avoid typos
"vmware.vscode-boot-dev-pack", // Developer tools for Spring Boot by VMware "vmware.vscode-boot-dev-pack", // Developer tools for Spring Boot by VMware
"vscjava.vscode-java-pack", // Java Extension Pack with essential Java tools for VS Code "vscjava.vscode-java-pack", // Java Extension Pack with essential Java tools for VS Code

View File

@ -6,7 +6,7 @@
"ms-python.flake8", // Flake8 linter for Python to enforce code quality "ms-python.flake8", // Flake8 linter for Python to enforce code quality
"ms-python.python", // Official Microsoft Python extension with IntelliSense, debugging, and Jupyter support "ms-python.python", // Official Microsoft Python extension with IntelliSense, debugging, and Jupyter support
"ms-vscode-remote.vscode-remote-extensionpack", // Remote Development Pack for SSH, WSL, and Containers "ms-vscode-remote.vscode-remote-extensionpack", // Remote Development Pack for SSH, WSL, and Containers
"Oracle.oracle-java", // Oracle Java extension with additional features for Java development // "Oracle.oracle-java", // Oracle Java extension with additional features for Java development
"streetsidesoftware.code-spell-checker", // Spell checker for code to avoid typos "streetsidesoftware.code-spell-checker", // Spell checker for code to avoid typos
"vmware.vscode-boot-dev-pack", // Developer tools for Spring Boot by VMware "vmware.vscode-boot-dev-pack", // Developer tools for Spring Boot by VMware
"vscjava.vscode-java-pack", // Java Extension Pack with essential Java tools for VS Code "vscjava.vscode-java-pack", // Java Extension Pack with essential Java tools for VS Code

View File

@ -11,6 +11,7 @@ import stirling.software.SPDF.EE.KeygenLicenseVerifier.License;
import stirling.software.SPDF.model.ApplicationProperties; import stirling.software.SPDF.model.ApplicationProperties;
import stirling.software.SPDF.model.ApplicationProperties.EnterpriseEdition; import stirling.software.SPDF.model.ApplicationProperties.EnterpriseEdition;
import stirling.software.SPDF.model.ApplicationProperties.Premium; import stirling.software.SPDF.model.ApplicationProperties.Premium;
import stirling.software.SPDF.model.ApplicationProperties.Premium.ProFeatures.GoogleDrive;
@Configuration @Configuration
@Order(Ordered.HIGHEST_PRECEDENCE) @Order(Ordered.HIGHEST_PRECEDENCE)
@ -43,6 +44,17 @@ public class EEAppConfig {
return applicationProperties.getPremium().getProFeatures().isSsoAutoLogin(); return applicationProperties.getPremium().getProFeatures().isSsoAutoLogin();
} }
@Bean(name = "GoogleDriveEnabled")
public boolean googleDriveEnabled() {
return runningProOrHigher()
&& applicationProperties.getPremium().getProFeatures().getGoogleDrive().isEnabled();
}
@Bean(name = "GoogleDriveConfig")
public GoogleDrive googleDriveConfig() {
return applicationProperties.getPremium().getProFeatures().getGoogleDrive();
}
// TODO: Remove post migration // TODO: Remove post migration
public void migrateEnterpriseSettingsToPremium(ApplicationProperties applicationProperties) { public void migrateEnterpriseSettingsToPremium(ApplicationProperties applicationProperties) {
EnterpriseEdition enterpriseEdition = applicationProperties.getEnterpriseEdition(); EnterpriseEdition enterpriseEdition = applicationProperties.getEnterpriseEdition();

View File

@ -394,6 +394,7 @@ public class ApplicationProperties {
// TODO: Remove post migration // TODO: Remove post migration
@Data @Data
@Deprecated(since = "0.45.0")
public static class EnterpriseEdition { public static class EnterpriseEdition {
private boolean enabled; private boolean enabled;
@ToString.Exclude private String key; @ToString.Exclude private String key;
@ -430,6 +431,7 @@ public class ApplicationProperties {
public static class ProFeatures { public static class ProFeatures {
private boolean ssoAutoLogin; private boolean ssoAutoLogin;
private CustomMetadata customMetadata = new CustomMetadata(); private CustomMetadata customMetadata = new CustomMetadata();
private GoogleDrive googleDrive = new GoogleDrive();
@Data @Data
public static class CustomMetadata { public static class CustomMetadata {
@ -448,6 +450,26 @@ public class ApplicationProperties {
: producer; : producer;
} }
} }
@Data
public static class GoogleDrive {
private boolean enabled;
private String clientId;
private String apiKey;
private String appId;
public String getClientId() {
return clientId == null || clientId.trim().isEmpty() ? "" : clientId;
}
public String getApiKey() {
return apiKey == null || apiKey.trim().isEmpty() ? "" : apiKey;
}
public String getAppId() {
return appId == null || appId.trim().isEmpty() ? "" : appId;
}
}
} }
@Data @Data

View File

@ -234,29 +234,29 @@ adminUserSettings.totalUsers=Skupno število uporabnikov:
adminUserSettings.lastRequest=Zadnja zahteva adminUserSettings.lastRequest=Zadnja zahteva
adminUserSettings.usage=View Usage adminUserSettings.usage=View Usage
endpointStatistics.title=Endpoint Statistics endpointStatistics.title=Statistika končne točke
endpointStatistics.header=Endpoint Statistics endpointStatistics.header=Statistika končne točke
endpointStatistics.top10=Top 10 endpointStatistics.top10=10 najboljših
endpointStatistics.top20=Top 20 endpointStatistics.top20=20 najboljših
endpointStatistics.all=All endpointStatistics.all=Vse
endpointStatistics.refresh=Refresh endpointStatistics.refresh=Osveži
endpointStatistics.includeHomepage=Include Homepage ('/') endpointStatistics.includeHomepage=Vključi domačo stran ('/')
endpointStatistics.includeLoginPage=Include Login Page ('/login') endpointStatistics.includeLoginPage=Vključi prijavno stran ('/login')
endpointStatistics.totalEndpoints=Total Endpoints endpointStatistics.totalEndpoints=Skupno končnih točk
endpointStatistics.totalVisits=Total Visits endpointStatistics.totalVisits=Skupno število obiskov
endpointStatistics.showing=Showing endpointStatistics.showing=Prikaz
endpointStatistics.selectedVisits=Selected Visits endpointStatistics.selectedVisits=Izbrani obiski
endpointStatistics.endpoint=Endpoint endpointStatistics.endpoint=Končna točka
endpointStatistics.visits=Visits endpointStatistics.visits=Obiski
endpointStatistics.percentage=Percentage endpointStatistics.percentage=Odstotek
endpointStatistics.loading=Loading... endpointStatistics.loading=Nalaganje...
endpointStatistics.failedToLoad=Failed to load endpoint data. Please try refreshing. endpointStatistics.failedToLoad=Nalaganje podatkov končne točke ni uspelo. Poskusite osvežiti.
endpointStatistics.home=Home endpointStatistics.home=Domača stran
endpointStatistics.login=Login endpointStatistics.login=Prijava
endpointStatistics.top=Top endpointStatistics.top=Na vrh
endpointStatistics.numberOfVisits=Number of Visits endpointStatistics.numberOfVisits=Število obiskov
endpointStatistics.visitsTooltip=Visits: {0} ({1}% of total) endpointStatistics.visitsTooltip=Obiski: {0} ({1}% vseh)
endpointStatistics.retry=Retry endpointStatistics.retry=Poskusi znova
database.title=Uvoz/izvoz baze podatkov database.title=Uvoz/izvoz baze podatkov
database.header=Uvoz/izvoz baze podatkov database.header=Uvoz/izvoz baze podatkov
@ -291,14 +291,14 @@ home.viewPdf.title=View/Edit PDF
home.viewPdf.desc=Oglejte si, komentirajte, dodajte besedilo ali slike home.viewPdf.desc=Oglejte si, komentirajte, dodajte besedilo ali slike
viewPdf.tags=ogled, branje, opomba, besedilo, slika viewPdf.tags=ogled, branje, opomba, besedilo, slika
home.setFavorites=Set Favourites home.setFavorites=Nastavi priljubljene
home.hideFavorites=Hide Favourites home.hideFavorites=Skrij priljubljene
home.showFavorites=Show Favourites home.showFavorites=Prikaži priljubljene
home.legacyHomepage=Old homepage home.legacyHomepage=Stara domača stran
home.newHomePage=Try our new homepage! home.newHomePage=Preizkusite našo novo domačo stran!
home.alphabetical=Alphabetical home.alphabetical=Abecedno
home.globalPopularity=Global Popularity home.globalPopularity=Globalna priljubljenost
home.sortBy=Sort by: home.sortBy=Razvrsti po:
home.multiTool.title=PDF Multi Tool home.multiTool.title=PDF Multi Tool
home.multiTool.desc=Spoji, zavrti, prerazporedi, razdeli in odstrani strani home.multiTool.desc=Spoji, zavrti, prerazporedi, razdeli in odstrani strani
@ -552,7 +552,7 @@ splitPdfByChapters.tags=razdeli,poglavja,zaznamki,organiziraj
home.validateSignature.title=Preveri podpis PDF home.validateSignature.title=Preveri podpis PDF
home.validateSignature.desc=Preveri digitalne podpise in potrdila v dokumentih PDF home.validateSignature.desc=Preveri digitalne podpise in potrdila v dokumentih PDF
validateSignature.tags=podpis,verify,validate,pdf,certificate,digitalni podpis,Validate Signature,Validate certificate validateSignature.tags=podpis,preveri,validiraj,pdf,certificate,digitalni podpis,Preveri podpis,Preveri certifikat
#replace-invert-color #replace-invert-color
replace-color.title=Napredne barvne možnosti replace-color.title=Napredne barvne možnosti
@ -787,7 +787,7 @@ autoSplitPDF.selectText.3=Naložite eno veliko optično prebrano datoteko PDF in
autoSplitPDF.selectText.4=Ločilne strani so samodejno zaznane in odstranjene, kar zagotavlja čist končni dokument. autoSplitPDF.selectText.4=Ločilne strani so samodejno zaznane in odstranjene, kar zagotavlja čist končni dokument.
autoSplitPDF.formPrompt=Pošljite PDF, ki vsebuje razdelilnike strani Stirling-PDF: autoSplitPDF.formPrompt=Pošljite PDF, ki vsebuje razdelilnike strani Stirling-PDF:
autoSplitPDF.duplexMode=Dupleksni način (skeniranje spredaj in zadaj) autoSplitPDF.duplexMode=Dupleksni način (skeniranje spredaj in zadaj)
autoSplitPDF.dividerDownload2=Prenesi 'Auto Splitter Divider (z navodili).pdf' autoSplitPDF.dividerDownload2=Prenesi 'Samodejni razdelilnik (z navodili).pdf'
autoSplitPDF.submit=Pošlji autoSplitPDF.submit=Pošlji
@ -886,8 +886,8 @@ sign.last=Zadnja stran
sign.next=Naslednja stran sign.next=Naslednja stran
sign.previous=Prejšnja stran sign.previous=Prejšnja stran
sign.maintainRatio=Preklopi ohranjanje razmerja stranic sign.maintainRatio=Preklopi ohranjanje razmerja stranic
sign.undo=Undo sign.undo=Razveljavi
sign.redo=Redo sign.redo=Ponovi
#repair #repair
repair.title=Popravilo repair.title=Popravilo
@ -958,8 +958,8 @@ compress.title=Stisnite
compress.header=Stisnite PDF compress.header=Stisnite PDF
compress.credit=Ta storitev uporablja qpdf za stiskanje/optimizacijo PDF. compress.credit=Ta storitev uporablja qpdf za stiskanje/optimizacijo PDF.
compress.grayscale.label=Uporabi sivinsko lestvico za stiskanje compress.grayscale.label=Uporabi sivinsko lestvico za stiskanje
compress.selectText.1=Compression Settings compress.selectText.1=Nastavitve stiskanja
compress.selectText.1.1=1-3 PDF compression,</br> 4-6 lite image compression,</br> 7-9 intense image compression Will dramatically reduce image quality compress.selectText.1.1=1-3 stiskanje PDF,</br> 4-6 enostavno stiskanje slik,</br> 7-9 intenzivno stiskanje slik Bo dramatično zmanjšalo kakovost slike
compress.selectText.2=Raven optimizacije: compress.selectText.2=Raven optimizacije:
compress.selectText.4=Samodejni način - Samodejno prilagodi kakovost, da dobi PDF na natančno velikost compress.selectText.4=Samodejni način - Samodejno prilagodi kakovost, da dobi PDF na natančno velikost
compress.selectText.5=Pričakovana velikost PDF (npr. 25 MB, 10,8 MB, 25 KB) compress.selectText.5=Pričakovana velikost PDF (npr. 25 MB, 10,8 MB, 25 KB)
@ -1307,15 +1307,15 @@ survey.please=Prosimo, razmislite o sodelovanju v naši anketi, če želite pris
survey.disabled=(Pojavno okno ankete bo v naslednjih posodobitvah onemogočeno, vendar na voljo na dnu strani) survey.disabled=(Pojavno okno ankete bo v naslednjih posodobitvah onemogočeno, vendar na voljo na dnu strani)
survey.button=Izpolnite anketo survey.button=Izpolnite anketo
survey.dontShowAgain=Ne prikaži več survey.dontShowAgain=Ne prikaži več
survey.meeting.1=If you're using Stirling PDF at work, we'd love to speak to you. We're offering technical support sessions in exchange for a 15 minute user discovery session. survey.meeting.1=Če v službi uporabljate Stirling PDF, bi radi govorili z vami. Ponujamo seje tehnične podpore v zameno za 15-minutno sejo odkrivanja uporabnikov.
survey.meeting.2=This is a chance to: survey.meeting.2=To je priložnost za:
survey.meeting.3=Get help with deployment, integrations, or troubleshooting survey.meeting.3=Poiščite pomoč pri uvajanju, integracijah ali odpravljanju težav
survey.meeting.4=Provide direct feedback on performance, edge cases, and feature gaps survey.meeting.4=Zagotovite neposredne povratne informacije o zmogljivosti, robnih primerih in vrzeli v funkcijah
survey.meeting.5=Help us refine Stirling PDF for real-world enterprise use survey.meeting.5=Pomagajte nam izboljšati Stirling PDF za uporabo v podjetju v resničnem svetu
survey.meeting.6=If you're interested, you can book time with our team directly. (English speaking only) survey.meeting.6=Če ste zainteresirani, si lahko rezervirate čas neposredno pri naši ekipi. (samo angleško govoreči)
survey.meeting.7=Looking forward to digging into your use cases and making Stirling PDF even better! survey.meeting.7=Veselimo se poglobitve v vaše primere uporabe in izboljšanja Stirling PDF-ja!
survey.meeting.notInterested=Not a business and/or interested in a meeting? survey.meeting.notInterested=Niste podjetje in/ali vas zanima srečanje?
survey.meeting.button=Book meeting survey.meeting.button=Rezerviraj srečanje
#error #error
error.sorry=Oprostite za težavo! error.sorry=Oprostite za težavo!

View File

@ -10,7 +10,6 @@
# If you want to override with environment parameter follow parameter naming SECURITY_INITIALLOGIN_USERNAME # # If you want to override with environment parameter follow parameter naming SECURITY_INITIALLOGIN_USERNAME #
############################################################################################################# #############################################################################################################
security: security:
enableLogin: false # set to 'true' to enable login enableLogin: false # set to 'true' to enable login
csrfDisabled: false # set to 'true' to disable CSRF protection (not recommended for production) csrfDisabled: false # set to 'true' to disable CSRF protection (not recommended for production)
@ -61,7 +60,6 @@ security:
privateKey: classpath:saml-private-key.key # Your private key. Generated from your keypair privateKey: classpath:saml-private-key.key # Your private key. Generated from your keypair
spCert: classpath:saml-public-cert.crt # Your signing certificate. Generated from your keypair spCert: classpath:saml-public-cert.crt # Your signing certificate. Generated from your keypair
premium: premium:
key: 00000000-0000-0000-0000-000000000000 key: 00000000-0000-0000-0000-000000000000
enabled: false # Enable license key checks for pro/enterprise features enabled: false # Enable license key checks for pro/enterprise features
@ -72,6 +70,11 @@ premium:
author: username author: username
creator: Stirling-PDF creator: Stirling-PDF
producer: Stirling-PDF producer: Stirling-PDF
googleDrive:
enabled: false
clientId: ''
apiKey: ''
appId: ''
legal: legal:
termsAndConditions: https://www.stirlingpdf.com/terms-and-conditions # URL to the terms and conditions of your application (e.g. https://example.com/terms). Empty string to disable or filename to load from local file in static folder termsAndConditions: https://www.stirlingpdf.com/terms-and-conditions # URL to the terms and conditions of your application (e.g. https://example.com/terms). Empty string to disable or filename to load from local file in static folder
@ -102,13 +105,11 @@ system:
name: postgres # set the name of your database. Should match the name of the database you create name: postgres # set the name of your database. Should match the name of the database you create
customPaths: customPaths:
pipeline: pipeline:
watchedFoldersDir: "" #Defaults to /pipeline/watchedFolders watchedFoldersDir: '' #Defaults to /pipeline/watchedFolders
finishedFoldersDir: "" #Defaults to /pipeline/finishedFolders finishedFoldersDir: '' #Defaults to /pipeline/finishedFolders
operations: operations:
weasyprint: "" #Defaults to /opt/venv/bin/weasyprint weasyprint: '' #Defaults to /opt/venv/bin/weasyprint
unoconvert: "" #Defaults to /opt/venv/bin/unoconvert unoconvert: '' #Defaults to /opt/venv/bin/unoconvert
ui: ui:
appName: '' # application's visible name appName: '' # application's visible name

View File

@ -271,3 +271,28 @@
align-items: center; align-items: center;
z-index: 9999; z-index: 9999;
} }
.google-drive-button {
width: 2.5rem;
pointer-events: auto;
cursor: pointer;
transition-duration: 0.4s;
border-radius: 0.5rem;
box-shadow: 0 0 5px var(--md-sys-color-on-surface-variant);
background-color: var(--md-sys-color-on-surface-container-high)
}
.horizontal-divider {
width: 85%;
border-top: 1px dashed;
padding: 0px;
margin: 10px;
}
.google-drive-button img {
width:100%
}
.google-drive-button:hover {
background-color: var(--md-sys-color-on-surface-variant)
}

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="96px" height="96px"><path fill="#1e88e5" d="M38.59,39c-0.535,0.93-0.298,1.68-1.195,2.197C36.498,41.715,35.465,42,34.39,42H13.61 c-1.074,0-2.106-0.285-3.004-0.802C9.708,40.681,9.945,39.93,9.41,39l7.67-9h13.84L38.59,39z"/><path fill="#fbc02d" d="M27.463,6.999c1.073-0.002,2.104-0.716,3.001-0.198c0.897,0.519,1.66,1.27,2.197,2.201l10.39,17.996 c0.537,0.93,0.807,1.967,0.808,3.002c0.001,1.037-1.267,2.073-1.806,3.001l-11.127-3.005l-6.924-11.993L27.463,6.999z"/><path fill="#e53935" d="M43.86,30c0,1.04-0.27,2.07-0.81,3l-3.67,6.35c-0.53,0.78-1.21,1.4-1.99,1.85L30.92,30H43.86z"/><path fill="#4caf50" d="M5.947,33.001c-0.538-0.928-1.806-1.964-1.806-3c0.001-1.036,0.27-2.073,0.808-3.004l10.39-17.996 c0.537-0.93,1.3-1.682,2.196-2.2c0.897-0.519,1.929,0.195,3.002,0.197l3.459,11.009l-6.922,11.989L5.947,33.001z"/><path fill="#1565c0" d="M17.08,30l-6.47,11.2c-0.78-0.45-1.46-1.07-1.99-1.85L4.95,33c-0.54-0.93-0.81-1.96-0.81-3H17.08z"/><path fill="#2e7d32" d="M30.46,6.8L24,18L17.53,6.8c0.78-0.45,1.66-0.73,2.6-0.79L27.46,6C28.54,6,29.57,6.28,30.46,6.8z"/></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -35,6 +35,7 @@ function setupFileInput(chooser) {
const pdfPrompt = chooser.getAttribute('data-bs-pdf-prompt'); const pdfPrompt = chooser.getAttribute('data-bs-pdf-prompt');
const inputContainerId = chooser.getAttribute('data-bs-element-container-id'); const inputContainerId = chooser.getAttribute('data-bs-element-container-id');
const showUploads = chooser.getAttribute('data-bs-show-uploads') === "true"; const showUploads = chooser.getAttribute('data-bs-show-uploads') === "true";
const name = chooser.getAttribute('data-bs-unique-id')
const noFileSelectedPrompt = chooser.getAttribute('data-bs-no-file-selected'); const noFileSelectedPrompt = chooser.getAttribute('data-bs-no-file-selected');
let inputContainer = document.getElementById(inputContainerId); let inputContainer = document.getElementById(inputContainerId);
@ -87,6 +88,21 @@ function setupFileInput(chooser) {
overlay = false; overlay = false;
} }
const googleDriveFileListener = function (e) {
const googleDriveFiles = e.detail;
const fileInput = document.getElementById(elementId);
if (fileInput?.hasAttribute('multiple')) {
pushFileListTo(googleDriveFiles, allFiles);
} else if (fileInput) {
allFiles = [googleDriveFiles[0]];
}
const dataTransfer = new DataTransfer();
allFiles.forEach((file) => dataTransfer.items.add(file));
fileInput.files = dataTransfer.files;
fileInput.dispatchEvent(new CustomEvent('change', { bubbles: true, detail: { source: 'drag-drop' } }));
}
const dropListener = function (e) { const dropListener = function (e) {
e.preventDefault(); e.preventDefault();
@ -137,6 +153,7 @@ function setupFileInput(chooser) {
document.body.addEventListener('dragenter', dragenterListener); document.body.addEventListener('dragenter', dragenterListener);
document.body.addEventListener('dragleave', dragleaveListener); document.body.addEventListener('dragleave', dragleaveListener);
document.body.addEventListener('drop', dropListener); document.body.addEventListener('drop', dropListener);
document.body.addEventListener(name + 'GoogleDriveDrivePicked', googleDriveFileListener);
$('#' + elementId).on('change', async function (e) { $('#' + elementId).on('change', async function (e) {
let element = e.target; let element = e.target;

View File

@ -0,0 +1,158 @@
const SCOPES = "https://www.googleapis.com/auth/drive.readonly";
const SESSION_STORAGE_ID = "googleDrivePickerAccessToken";
let tokenClient;
let accessToken = sessionStorage.getItem(SESSION_STORAGE_ID);
let isScriptExecuted = false;
if (!isScriptExecuted) {
isScriptExecuted = true;
document.addEventListener("DOMContentLoaded", function () {
document.querySelectorAll(".google-drive-button").forEach(setupGoogleDrivePicker);
});
}
function gisLoaded() {
tokenClient = google.accounts.oauth2.initTokenClient({
client_id: window.stirlingPDF.GoogleDriveClientId,
scope: SCOPES,
callback: "", // defined later
});
}
// add more as needed.
// Google picker is limited on what mimeTypes are supported
// Wild card are not supported
const expandableMimeTypes = {
"image/*" : ["image/jpeg", "image/png","image/svg+xml" ]
}
function fileInputToGooglePickerMimeTypes(accept) {
if(accept == null || accept == "" || accept.includes("*/*")){
// Setting null will accept all supported mimetypes
return null;
}
let mimeTypes = [];
accept.split(',').forEach(part => {
if(!(part in expandableMimeTypes)){
mimeTypes.push(part);
return;
}
expandableMimeTypes[part].forEach(mimeType => {
mimeTypes.push(mimeType);
});
});
const mimeString = mimeTypes.join(",").replace(/\s+/g, '');
console.log([accept, "became", mimeString]);
return mimeString;
}
/**
* Callback after api.js is loaded.
*/
function gapiLoaded() {
gapi.load("client:picker", initializePicker);
}
/**
* Callback after the API client is loaded. Loads the
* discovery doc to initialize the API.
*/
async function initializePicker() {
await gapi.client.load("https://www.googleapis.com/discovery/v1/apis/drive/v3/rest");
}
function setupGoogleDrivePicker(picker) {
const name = picker.getAttribute('data-name');
const accept = picker.getAttribute('data-accept');
const multiple = picker.getAttribute('data-multiple') === "true";
const mimeTypes = fileInputToGooglePickerMimeTypes(accept);
picker.addEventListener("click", onGoogleDriveButtonClick);
function onGoogleDriveButtonClick(e) {
e.stopPropagation();
tokenClient.callback = (response) => {
if (response.error !== undefined) {
throw response;
}
accessToken = response.access_token;
sessionStorage.setItem(SESSION_STORAGE_ID, accessToken);
createGooglePicker();
};
tokenClient.requestAccessToken({ prompt: accessToken === null ? "consent" : "" });
}
/**
* Sign out the user upon button click.
*/
function signOut() {
if (accessToken) {
sessionStorage.removeItem(SESSION_STORAGE_ID);
google.accounts.oauth2.revoke(accessToken);
accessToken = null;
}
}
function createGooglePicker() {
let builder = new google.picker.PickerBuilder()
.setDeveloperKey(window.stirlingPDF.GoogleDriveApiKey)
.setAppId(window.stirlingPDF.GoogleDriveAppId)
.setOAuthToken(accessToken)
.addView(
new google.picker.DocsView()
.setIncludeFolders(true)
.setMimeTypes(mimeTypes)
)
.addView(
new google.picker.DocsView()
.setIncludeFolders(true)
.setEnableDrives(true)
.setMimeTypes(mimeTypes)
)
.setCallback(pickerCallback);
if(multiple) {
builder.enableFeature(google.picker.Feature.MULTISELECT_ENABLED);
}
const picker = builder.build();
picker.setVisible(true);
}
/**
* Displays the file details of the user's selection.
* @param {object} data - Containers the user selection from the picker
*/
async function pickerCallback(data) {
if (data.action === google.picker.Action.PICKED) {
const files = await Promise.all(
data[google.picker.Response.DOCUMENTS].map(async (pickedFile) => {
const fileId = pickedFile[google.picker.Document.ID];
console.log(fileId);
const res = await gapi.client.drive.files.get({
fileId: fileId,
alt: "media",
});
let file = new File([new Uint8Array(res.body.length).map((_, i) => res.body.charCodeAt(i))], pickedFile.name, {
type: pickedFile.mimeType,
lastModified: pickedFile.lastModified,
endings: pickedFile.endings,
});
return file;
})
);
document.body.dispatchEvent(new CustomEvent(name+"GoogleDriveDrivePicked", { detail: files }));
}
}
}

View File

@ -228,8 +228,9 @@
loading: '[[#{loading}]]' loading: '[[#{loading}]]'
};</script> };</script>
<div class="custom-file-chooser mb-3" <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}"> 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-row justify-content-center align-items-center flex-wrap input-container" <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}"> th:name="${name}+'-input'" th:id="${name}+'-input-container'" th:data-text="#{fileChooser.hoveredDragAndDrop}">
<label class="file-input-btn d-none"> <label class="file-input-btn d-none">
<input type="file" class="form-control" <input type="file" class="form-control"
@ -240,11 +241,17 @@
th:required="${notRequired} ? null : 'required'"> th:required="${notRequired} ? null : 'required'">
Browse Browse
</label> </label>
<div class="d-flex flex-column align-items-center">
<div class="d-flex justify-content-start align-items-center" id="fileInputText"> <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.click}" style="margin-right: 5px"></div>
<div th:text="#{fileChooser.or}" style="margin-right: 5px"></div> <div th:text="#{fileChooser.or}" style="margin-right: 5px"></div>
<div th:text="#{fileChooser.dragAndDrop}" id="dragAndDrop"></div> <div th:text="#{fileChooser.dragAndDrop}" id="dragAndDrop"></div>
</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>
<div class="selected-files flex-wrap"></div> <div class="selected-files flex-wrap"></div>
</div> </div>
@ -258,4 +265,16 @@
</div> </div>
</div> </div>
<script th:src="@{'/js/fileInput.js'}" type="module"></script> <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> </th:block>