This commit is contained in:
2026-04-24 14:27:10 +07:00
parent 751f3aefe4
commit 7749e18f4c
14 changed files with 3778 additions and 373 deletions
+10 -6
View File
@@ -1,17 +1,22 @@
# Stage 1: Build the application # Stage 1: Build the application
FROM maven:3.8.6-openjdk-11 AS build FROM maven:3.8.6-openjdk-11 AS build
# Install Node.js and Grunt (required by the prod profile for JS/CSS compilation)
RUN curl -fsSL https://deb.nodesource.com/setup_16.x | bash - && \
apt-get install -y nodejs && \
npm install -g grunt-cli
COPY . /usr/src/app COPY . /usr/src/app
WORKDIR /usr/src/app WORKDIR /usr/src/app
RUN mvn clean package -DskipTests -pl docs-web -am
# Build with the 'prod' profile so Grunt compiles JS/CSS into dist/
RUN mvn clean package -DskipTests -Pprod -pl docs-web -am
# Stage 2: Runtime environment # Stage 2: Runtime environment
FROM ubuntu:22.04 FROM ubuntu:22.04
LABEL maintainer="b.gamard@sismics.com" LABEL maintainer="b.gamard@sismics.com"
# Run Debian in non interactive mode
ENV DEBIAN_FRONTEND noninteractive ENV DEBIAN_FRONTEND noninteractive
# Configure env
ENV LANG C.UTF-8 ENV LANG C.UTF-8
ENV LC_ALL C.UTF-8 ENV LC_ALL C.UTF-8
ENV JAVA_HOME /usr/lib/jvm/java-11-openjdk-amd64/ ENV JAVA_HOME /usr/lib/jvm/java-11-openjdk-amd64/
@@ -52,9 +57,8 @@ RUN mkdir /app && \
# Copy build artifacts from Stage 1 # Copy build artifacts from Stage 1
COPY --from=build /usr/src/app/docs.xml /app/webapps/docs.xml COPY --from=build /usr/src/app/docs.xml /app/webapps/docs.xml
COPY --from=build /usr/src/app/docs-web/target/docs-web-*.war /app/webapps/docs.war COPY --from=build /usr/src/app/docs-web/target/docs-web-1.12-SNAPSHOT.war /app/webapps/docs.war
WORKDIR /app WORKDIR /app
CMD ["java", "-jar", "/opt/jetty/start.jar"] CMD ["java", "-jar", "/opt/jetty/start.jar"]
+3125
View File
File diff suppressed because one or more lines are too long
+1
View File
@@ -0,0 +1 @@
862027
Executable
+46
View File
@@ -0,0 +1,46 @@
#!/bin/bash
# Dừng script ngay lập tức nếu có lỗi xảy ra
set -e
# Cấu hình thông tin
USERNAME="victorphan03"
IMAGE_NAME="teedy-custom"
REGISTRY="ghcr.io"
echo "-------------------------------------------------------"
echo " Teedy Custom Build & Push System"
echo "-------------------------------------------------------"
# Yêu cầu nhập Version (Tag)
read -p "Nhập phiên bản mới (ví dụ: v1.0.5): " VERSION
if [ -z "$VERSION" ]; then
echo "Lỗi: Phiên bản không được để trống!"
exit 1
fi
FULL_IMAGE_NAME="${REGISTRY}/${USERNAME}/${IMAGE_NAME}:${VERSION}"
echo ""
echo ">>> [1/3] Đang tiến hành Build Docker Image: ${IMAGE_NAME}:${VERSION}..."
echo "Lưu ý: Quá trình này có thể mất vài phút vì cần biên dịch Maven & Grunt."
# Thực hiện build (Dùng BuildKit để nhanh hơn)
DOCKER_BUILDKIT=1 docker build -t "${IMAGE_NAME}:${VERSION}" .
echo ""
echo ">>> [2/3] Đang gắn thẻ (Tag) cho GitHub Container Registry..."
docker tag "${IMAGE_NAME}:${VERSION}" "${FULL_IMAGE_NAME}"
echo ""
echo ">>> [3/3] Đang đẩy (Push) Image lên GHCR..."
docker push "${FULL_IMAGE_NAME}"
echo "-------------------------------------------------------"
echo " HOÀN THÀNH THÀNH CÔNG!"
echo " Image của bạn đã sẵn sàng tại: ${FULL_IMAGE_NAME}"
echo "-------------------------------------------------------"
echo "Để cập nhật server, hãy sửa file docker-compose-ghcr.yml và chạy:"
echo "docker-compose pull && docker-compose up -d"
echo "-------------------------------------------------------"
+1 -1
View File
@@ -1,7 +1,7 @@
version: '3' version: '3'
services: services:
teedy: teedy:
image: ghcr.io/victorphan03/teedy-custom:v1.0.0 image: ghcr.io/victorphan03/teedy-custom:v1.0.5
container_name: teedy-custom container_name: teedy-custom
restart: always restart: always
ports: ports:
+1 -1
View File
@@ -106,7 +106,7 @@ module.exports = function(grunt) {
dist: { dist: {
expand: true, expand: true,
cwd: 'src/', cwd: 'src/',
src: ['**', '!**/*.js', '!*.html', '!**/*.less', '!**/*.css', 'locale/**'], src: ['**', '!**/*.js', '!*.html', '!**/*.less', '!**/*.css', 'locale/**', 'lib/pdf.min.js', 'lib/pdf.worker.min.js'],
dest: 'dist/' dest: 'dist/'
} }
}, },
@@ -1,5 +1,6 @@
/** /**
* PDF Annotation Viewer directive. * PDF Annotation Viewer directive.
* Written in ES5 for ngAnnotate compatibility.
*/ */
var module; var module;
try { try {
@@ -16,76 +17,84 @@ module.directive('pdfAnnotationViewer', function ($stateParams, Restangular, $ti
documentId: '=', documentId: '=',
shareId: '=' shareId: '='
}, },
template: ` template: '<div class="pdf-annotation-container">' +
<div class="pdf-annotation-container"> '<div class="pdf-toolbar">' +
<div class="pdf-toolbar"> '<div class="btn-group">' +
<div class="btn-group"> '<button class="btn btn-default" ng-class="{active: tool === \'cursor\'}" ng-click="setTool(\'cursor\')" uib-tooltip="Cursor"><span class="fas fa-mouse-pointer"></span></button>' +
<button class="btn btn-default" ng-class="{active: tool === 'cursor'}" ng-click="setTool('cursor')" uib-tooltip="Cursor"><span class="fas fa-mouse-pointer"></span></button> '<button class="btn btn-default" ng-class="{active: tool === \'pencil\'}" ng-click="setTool(\'pencil\')" uib-tooltip="Pencil"><span class="fas fa-pencil-alt"></span></button>' +
<button class="btn btn-default" ng-class="{active: tool === 'pencil'}" ng-click="setTool('pencil')" uib-tooltip="Pencil"><span class="fas fa-pencil-alt"></span></button> '<button class="btn btn-default" ng-class="{active: tool === \'highlight\'}" ng-click="setTool(\'highlight\')" uib-tooltip="Highlight"><span class="fas fa-highlighter"></span></button>' +
<button class="btn btn-default" ng-class="{active: tool === 'highlight'}" ng-click="setTool('highlight')" uib-tooltip="Highlight"><span class="fas fa-highlighter"></span></button> '<button class="btn btn-default" ng-class="{active: tool === \'text\'}" ng-click="setTool(\'text\')" uib-tooltip="Text"><span class="fas fa-font"></span></button>' +
<button class="btn btn-default" ng-class="{active: tool === 'text'}" ng-click="setTool('text')" uib-tooltip="Text"><span class="fas fa-font"></span></button> '<button class="btn btn-default" ng-class="{active: tool === \'eraser\'}" ng-click="setTool(\'eraser\')" uib-tooltip="Eraser (click to delete)"><span class="fas fa-eraser"></span></button>' +
<button class="btn btn-default" ng-class="{active: tool === 'eraser'}" ng-click="setTool('eraser')" uib-tooltip="Eraser (click to delete)"><span class="fas fa-eraser"></span></button> '</div>' +
</div> '<div class="btn-group">' +
<div class="btn-group"> '<button class="btn btn-default" ng-click="zoomOut()"><span class="fas fa-search-minus"></span></button>' +
<button class="btn btn-default" ng-click="zoomOut()"><span class="fas fa-search-minus"></span></button> '<span class="btn btn-placeholder">{{ zoom * 100 | number:0 }}%</span>' +
<span class="btn btn-placeholder">{{ zoom * 100 | number:0 }}%</span> '<button class="btn btn-default" ng-click="zoomIn()"><span class="fas fa-search-plus"></span></button>' +
<button class="btn btn-default" ng-click="zoomIn()"><span class="fas fa-search-plus"></span></button> '</div>' +
</div> '<div class="btn-group pull-right">' +
<div class="btn-group pull-right"> '<button class="btn btn-default" ng-click="exportPdf()" ng-disabled="exporting" uib-tooltip="Export as PDF">' +
<button class="btn btn-default" ng-click="exportPdf()" ng-disabled="exporting" uib-tooltip="Export as PDF"> '<span class="fas fa-file-pdf"></span> {{ exporting === \'pdf\' ? \'Exporting...\' : \'PDF\' }}' +
<span class="fas fa-file-pdf"></span> {{ exporting === 'pdf' ? 'Exporting...' : 'PDF' }} '</button>' +
</button> '<button class="btn btn-danger" ng-click="clearAllAnnotations()" ng-disabled="saving || shareId || annotations.length === 0" uib-tooltip="Clear all annotations">' +
<button class="btn btn-danger" ng-click="clearAllAnnotations()" ng-disabled="saving || shareId || annotations.length === 0" uib-tooltip="Clear all annotations"> '<span class="fas fa-trash"></span>' +
<span class="fas fa-trash"></span> '</button>' +
</button> '<button class="btn btn-warning" ng-click="saveAsVersion()" ng-disabled="exporting || saving || shareId" uib-tooltip="Save as a new PDF version in Teedy">' +
<button class="btn btn-warning" ng-click="saveAsVersion()" ng-disabled="exporting || saving || shareId" uib-tooltip="Save as a new PDF version in Teedy"> '<span class="fas fa-file-upload"></span> {{ exporting === \'version\' ? \'Uploading...\' : \'Save Version\' }}' +
<span class="fas fa-file-upload"></span> {{ exporting === 'version' ? 'Uploading...' : 'Save Version' }} '</button>' +
</button> '<button class="btn btn-primary" ng-click="saveAnnotations()" ng-disabled="saving || shareId">' +
<button class="btn btn-primary" ng-click="saveAnnotations()" ng-disabled="saving || shareId"> '<span class="fas fa-save"></span> {{ (saving ? \'Saving...\' : \'Save\') }}' +
<span class="fas fa-save"></span> {{ (saving ? 'Saving...' : 'Save') }} '</button>' +
</button> '</div>' +
</div> '</div>' +
</div> '<div class="pdf-viewer-scroll">' +
<div class="pdf-viewer-scroll"> '<div class="pdf-pages-container" id="pdf-pages"></div>' +
<div class="pdf-pages-container" id="pdf-pages"> '</div>' +
<!-- Pages will be rendered here --> '</div>' +
</div> '<style>' +
</div> '.pdf-annotation-container { display: flex; flex-direction: column; height: 100%; position: relative; background: #525659; }' +
</div> '.pdf-toolbar { background: #323639; padding: 10px; color: white; display: flex; gap: 10px; align-items: center; z-index: 100; box-shadow: 0 2px 5px rgba(0,0,0,0.3); }' +
<style> '.pdf-viewer-scroll { flex: 1; overflow: auto; padding: 20px; }' +
.pdf-annotation-container { display: flex; flex-direction: column; height: 100%; position: relative; background: #525659; } '.pdf-pages-container { display: flex; flex-direction: column; align-items: center; gap: 20px; }' +
.pdf-toolbar { background: #323639; padding: 10px; color: white; display: flex; gap: 10px; align-items: center; z-index: 100; box-shadow: 0 2px 5px rgba(0,0,0,0.3); } '.pdf-page-wrapper { position: relative; box-shadow: 0 0 10px rgba(0,0,0,0.5); background: white; }' +
.pdf-viewer-scroll { flex: 1; overflow: auto; padding: 20px; } '.pdf-canvas { display: block; }' +
.pdf-pages-container { display: flex; flex-direction: column; align-items: center; gap: 20px; } '.annotation-layer { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; }' +
.pdf-page-wrapper { position: relative; box-shadow: 0 0 10px rgba(0,0,0,0.5); background: white; } '.annotation-layer.active { pointer-events: all; cursor: crosshair; }' +
.pdf-canvas { display: block; } '.annotation-layer.tool-cursor { cursor: default; }' +
.annotation-layer { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; } '.pdf-text-input { position: absolute; border: 1px solid #2aabd2; background: rgba(255,255,255,0.8); z-index: 200; outline: none; padding: 2px; }' +
.annotation-layer.active { pointer-events: all; cursor: crosshair; } '</style>',
.annotation-layer.tool-cursor { cursor: default; }
.pdf-text-input { position: absolute; border: 1px solid #2aabd2; background: rgba(255,255,255,0.8); z-index: 200; outline: none; padding: 2px; }
</style>
`,
link: function (scope, element) { link: function (scope, element) {
scope.tool = 'cursor'; scope.tool = 'cursor';
scope.zoom = 1.0; scope.zoom = 1.0;
scope.annotations = []; scope.annotations = [];
scope.saving = false; scope.saving = false;
scope.exporting = null;
let pdfDoc = null; var pdfDoc = null;
let pages = []; var pages = [];
let currentRenderId = 0; // Global sequence ID to cancel stale renders var currentRenderId = 0;
let deregisterDocIdWatch = null; var deregisterDocIdWatch = null;
const getDocId = () => scope.documentId || $stateParams.documentId || $stateParams.id; var isDrawing = false;
const pdfUrl = `../api/file/${scope.fileId}/data` + (scope.shareId ? `?share=${scope.shareId}` : ''); var currentPath = null;
var currentElement = null;
function getDocId() {
return scope.documentId || $stateParams.documentId || $stateParams.id;
}
// Initialize PDF.js // Initialize PDF.js
pdfjsLib.GlobalWorkerOptions.workerSrc = 'lib/pdf.worker.js'; pdfjsLib.GlobalWorkerOptions.workerSrc = 'lib/pdf.worker.min.js';
// Fetch annotations from server as a Promise (does not render, just returns data) // Fetch annotations from server
const fetchAnnotations = (docId) => { function fetchAnnotations(docId) {
if (!docId) return Promise.resolve([]); if (!docId) return Promise.resolve([]);
return Restangular.one('comment', docId).get({ share: scope.shareId }).then(data => { return Restangular.one('comment', docId).get({ share: scope.shareId }).then(function (data) {
const annoComment = data.comments.find(c => c.content.startsWith('[ANNOTATION]')); var annoComment = null;
for (var i = 0; i < data.comments.length; i++) {
if (data.comments[i].content.indexOf('[ANNOTATION]') === 0) {
annoComment = data.comments[i];
break;
}
}
if (annoComment) { if (annoComment) {
try { try {
return JSON.parse(annoComment.content.replace('[ANNOTATION]', '')); return JSON.parse(annoComment.content.replace('[ANNOTATION]', ''));
@@ -94,69 +103,31 @@ module.directive('pdfAnnotationViewer', function ($stateParams, Restangular, $ti
} }
} }
return []; return [];
}, () => []); }, function () { return []; });
}; }
// Start loading: fetch PDF document + annotations in parallel. // Render annotations for a single page
const startLoading = (url) => { function renderPageAnnotations(pageNum, svg) {
const myRenderId = ++currentRenderId; svg.innerHTML = '';
var pageAnnos = [];
// IMMEDIATE CLEANUP for (var i = 0; i < scope.annotations.length; i++) {
scope.annotations = []; if (scope.annotations[i].page === pageNum) {
pages = []; pageAnnos.push({ a: scope.annotations[i], idx: i });
}
const container = element[0].querySelector('#pdf-pages');
container.innerHTML = '<div style="color:white;padding:20px;text-align:center"><span class="fas fa-spinner fa-spin"></span> Loading...</div>';
container.style.minHeight = '0px';
// Start fetching annotations immediately in parallel
const docId = getDocId();
let annotationsPromise;
if (docId) {
annotationsPromise = fetchAnnotations(docId);
} else {
annotationsPromise = new Promise(resolve => {
if (deregisterDocIdWatch) deregisterDocIdWatch();
deregisterDocIdWatch = scope.$watch(getDocId, (newDocId) => {
if (!newDocId || myRenderId !== currentRenderId) return;
deregisterDocIdWatch();
deregisterDocIdWatch = null;
fetchAnnotations(newDocId).then(resolve);
});
});
} }
// Load PDF document pageAnnos.forEach(function (item) {
pdfjsLib.getDocument(url).promise.then(async (loadedPdf) => { var a = item.a;
if (myRenderId !== currentRenderId) return; // Stale request var idx = item.idx;
pdfDoc = loadedPdf; var el;
await renderPages(annotationsPromise, myRenderId);
}).catch(e => {
if (myRenderId !== currentRenderId) return;
console.error('Error loading PDF:', e);
element.html('<div class="alert alert-danger">Error loading PDF: ' + e.message + '</div>');
});
};
// Render a single page's annotations onto its SVG layer.
// Each element is tagged with data-anno-idx for eraser identification.
const renderPageAnnotations = (pageNum, svg) => {
svg.innerHTML = '';
const pageAnnos = scope.annotations
.map((a, idx) => ({ a, idx }))
.filter(({ a }) => a.page === pageNum);
pageAnnos.forEach(({ a, idx }) => {
let el;
if (a.type === 'pencil' || a.type === 'highlight') { if (a.type === 'pencil' || a.type === 'highlight') {
el = document.createElementNS('http://www.w3.org/2000/svg', 'path'); el = document.createElementNS('http://www.w3.org/2000/svg', 'path');
el.setAttribute('fill', 'none'); el.setAttribute('fill', 'none');
el.setAttribute('stroke', a.color); el.setAttribute('stroke', a.color);
el.setAttribute('stroke-width', a.width * scope.zoom); var sw = Math.max(a.width * scope.zoom, scope.tool === 'eraser' ? 12 : a.width * scope.zoom);
el.setAttribute('stroke-width', sw);
el.setAttribute('stroke-linecap', 'round'); el.setAttribute('stroke-linecap', 'round');
// Increase hit area for eraser by adding a transparent wider path var scaledPath = a.data.replace(/([0-9.]+)/g, function (match) { return parseFloat(match) * scope.zoom; });
el.setAttribute('stroke-width', Math.max(a.width * scope.zoom, scope.tool === 'eraser' ? 12 : a.width * scope.zoom));
const scaledPath = a.data.replace(/([0-9.]+)/g, (match) => parseFloat(match) * scope.zoom);
el.setAttribute('d', scaledPath); el.setAttribute('d', scaledPath);
} else if (a.type === 'text') { } else if (a.type === 'text') {
el = document.createElementNS('http://www.w3.org/2000/svg', 'text'); el = document.createElementNS('http://www.w3.org/2000/svg', 'text');
@@ -172,10 +143,12 @@ module.directive('pdfAnnotationViewer', function ($stateParams, Restangular, $ti
if (scope.tool === 'eraser') { if (scope.tool === 'eraser') {
el.style.cursor = 'not-allowed'; el.style.cursor = 'not-allowed';
el.style.pointerEvents = 'all'; el.style.pointerEvents = 'all';
el.addEventListener('click', (e) => { (function (capturedIdx) {
e.stopPropagation(); el.addEventListener('click', function (e) {
scope.$apply(() => scope.deleteAnnotation(idx)); e.stopPropagation();
}); scope.$apply(function () { scope.deleteAnnotation(capturedIdx); });
});
})(idx);
} else { } else {
el.style.pointerEvents = 'none'; el.style.pointerEvents = 'none';
} }
@@ -183,25 +156,67 @@ module.directive('pdfAnnotationViewer', function ($stateParams, Restangular, $ti
svg.appendChild(el); svg.appendChild(el);
} }
}); });
}; }
// Render all pages progressively. function renderAnnotations() {
const renderPages = async (annotationsPromise, myRenderId) => { pages.forEach(function (p) { renderPageAnnotations(p.i, p.svg); });
if (!pdfDoc) return; }
// Render a single page (returns a Promise)
function renderSinglePage(i, container, myRenderId, scrollContainer, scrollPercent) {
return pdfDoc.getPage(i).then(function (page) {
if (myRenderId !== currentRenderId) return;
var viewport = page.getViewport({ scale: scope.zoom });
var wrapper = document.createElement('div');
wrapper.className = 'pdf-page-wrapper';
wrapper.style.width = viewport.width + 'px';
wrapper.style.height = viewport.height + 'px';
var canvas = document.createElement('canvas');
canvas.className = 'pdf-canvas';
canvas.width = viewport.width;
canvas.height = viewport.height;
var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
svg.setAttribute('class', 'annotation-layer tool-' + scope.tool);
if (scope.tool !== 'cursor') svg.classList.add('active');
svg.setAttribute('width', viewport.width);
svg.setAttribute('height', viewport.height);
wrapper.appendChild(canvas);
wrapper.appendChild(svg);
container.appendChild(wrapper);
var context = canvas.getContext('2d');
return page.render({ canvasContext: context, viewport: viewport }).promise.then(function () {
if (myRenderId !== currentRenderId) return;
pages.push({ i: i, page: page, wrapper: wrapper, svg: svg, viewport: viewport });
setupDrawing(svg, i);
renderPageAnnotations(i, svg);
if (i === 1 || i === Math.floor(pdfDoc.numPages * scrollPercent)) {
scrollContainer.scrollTop = scrollPercent * scrollContainer.scrollHeight;
}
});
});
}
// Render all pages progressively (sequential Promise chain)
function renderPages(annotationsPromise, myRenderId) {
if (!pdfDoc) return Promise.resolve();
if (!myRenderId) myRenderId = ++currentRenderId; if (!myRenderId) myRenderId = ++currentRenderId;
const scrollContainer = element[0].querySelector('.pdf-viewer-scroll'); var scrollContainer = element[0].querySelector('.pdf-viewer-scroll');
const container = element[0].querySelector('#pdf-pages'); var container = element[0].querySelector('#pdf-pages');
const scrollPercent = scrollContainer.scrollTop / (scrollContainer.scrollHeight || 1); var scrollPercent = scrollContainer.scrollTop / (scrollContainer.scrollHeight || 1);
pages = []; pages = [];
// If annotationsPromise provided, handle it safely
if (annotationsPromise) { if (annotationsPromise) {
annotationsPromise.then(annos => { annotationsPromise.then(function (annos) {
if (myRenderId !== currentRenderId) return; if (myRenderId !== currentRenderId) return;
scope.annotations = annos; scope.annotations = annos;
pages.forEach(p => renderPageAnnotations(p.i, p.svg)); pages.forEach(function (p) { renderPageAnnotations(p.i, p.svg); });
}); });
} }
@@ -210,59 +225,68 @@ module.directive('pdfAnnotationViewer', function ($stateParams, Restangular, $ti
} }
container.innerHTML = ''; container.innerHTML = '';
try { // Build sequential chain: page 1, then page 2, etc.
for (let i = 1; i <= pdfDoc.numPages; i++) { var chain = Promise.resolve();
if (myRenderId !== currentRenderId) return; // Stop rendering if ID changed for (var i = 1; i <= pdfDoc.numPages; i++) {
(function (pageNum) {
chain = chain.then(function () {
if (myRenderId !== currentRenderId) return;
return renderSinglePage(pageNum, container, myRenderId, scrollContainer, scrollPercent);
});
})(i);
}
const page = await pdfDoc.getPage(i); return chain.then(function () {
const viewport = page.getViewport({ scale: scope.zoom });
const wrapper = document.createElement('div');
wrapper.className = 'pdf-page-wrapper';
wrapper.style.width = viewport.width + 'px';
wrapper.style.height = viewport.height + 'px';
const canvas = document.createElement('canvas');
canvas.className = 'pdf-canvas';
canvas.width = viewport.width;
canvas.height = viewport.height;
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
svg.setAttribute('class', `annotation-layer tool-${scope.tool}`);
if (scope.tool !== 'cursor') svg.classList.add('active');
svg.setAttribute('width', viewport.width);
svg.setAttribute('height', viewport.height);
wrapper.appendChild(canvas);
wrapper.appendChild(svg);
container.appendChild(wrapper);
const context = canvas.getContext('2d');
await page.render({ canvasContext: context, viewport: viewport }).promise;
if (myRenderId !== currentRenderId) return;
pages.push({ i: i, page: page, wrapper: wrapper, svg: svg, viewport: viewport });
setupDrawing(svg, i);
renderPageAnnotations(i, svg);
if (i === 1 || i === Math.floor(pdfDoc.numPages * scrollPercent)) {
scrollContainer.scrollTop = scrollPercent * scrollContainer.scrollHeight;
}
}
} finally {
if (myRenderId === currentRenderId) { if (myRenderId === currentRenderId) {
container.style.minHeight = ''; container.style.minHeight = '';
scrollContainer.scrollTop = scrollPercent * scrollContainer.scrollHeight; scrollContainer.scrollTop = scrollPercent * scrollContainer.scrollHeight;
} }
});
}
// Start loading: fetch PDF + annotations in parallel
function startLoading(url) {
var myRenderId = ++currentRenderId;
scope.annotations = [];
pages = [];
var container = element[0].querySelector('#pdf-pages');
container.innerHTML = '<div style="color:white;padding:20px;text-align:center"><span class="fas fa-spinner fa-spin"></span> Loading...</div>';
container.style.minHeight = '0px';
var docId = getDocId();
var annotationsPromise;
if (docId) {
annotationsPromise = fetchAnnotations(docId);
} else {
annotationsPromise = new Promise(function (resolve) {
if (deregisterDocIdWatch) deregisterDocIdWatch();
deregisterDocIdWatch = scope.$watch(getDocId, function (newDocId) {
if (!newDocId || myRenderId !== currentRenderId) return;
deregisterDocIdWatch();
deregisterDocIdWatch = null;
fetchAnnotations(newDocId).then(resolve);
});
});
} }
};
pdfjsLib.getDocument(url).promise.then(function (loadedPdf) {
if (myRenderId !== currentRenderId) return;
pdfDoc = loadedPdf;
return renderPages(annotationsPromise, myRenderId);
}).catch(function (e) {
if (myRenderId !== currentRenderId) return;
console.error('Error loading PDF:', e);
element.html('<div class="alert alert-danger">Error loading PDF: ' + e.message + '</div>');
});
}
// Tool handling // Tool handling
scope.setTool = (tool) => { scope.setTool = function (tool) {
scope.tool = tool; scope.tool = tool;
element[0].querySelectorAll('.annotation-layer').forEach(svg => { element[0].querySelectorAll('.annotation-layer').forEach(function (svg) {
svg.className = `annotation-layer tool-${tool}`; svg.className = 'annotation-layer tool-' + tool;
if (tool === 'cursor') { if (tool === 'cursor') {
svg.classList.remove('active'); svg.classList.remove('active');
svg.style.cursor = 'default'; svg.style.cursor = 'default';
@@ -274,183 +298,165 @@ module.directive('pdfAnnotationViewer', function ($stateParams, Restangular, $ti
svg.style.cursor = 'crosshair'; svg.style.cursor = 'crosshair';
} }
}); });
// Re-render to update pointer-events on annotation elements
renderAnnotations(); renderAnnotations();
}; };
// Delete a single annotation by index and re-render scope.deleteAnnotation = function (idx) {
scope.deleteAnnotation = (idx) => {
scope.annotations.splice(idx, 1); scope.annotations.splice(idx, 1);
renderAnnotations(); renderAnnotations();
}; };
// Clear all annotations with confirmation scope.clearAllAnnotations = function () {
scope.clearAllAnnotations = () => {
if (!confirm('Clear all annotations on this document? This cannot be undone until you reload.')) return; if (!confirm('Clear all annotations on this document? This cannot be undone until you reload.')) return;
scope.annotations = []; scope.annotations = [];
renderAnnotations(); renderAnnotations();
}; };
scope.zoomIn = () => { scope.zoom += 0.2; renderPages(); }; scope.zoomIn = function () { scope.zoom += 0.2; renderPages(); };
scope.zoomOut = () => { if (scope.zoom > 0.4) { scope.zoom -= 0.2; renderPages(); } }; scope.zoomOut = function () { if (scope.zoom > 0.4) { scope.zoom -= 0.2; renderPages(); } };
// ── Export helpers ────────────────────────────────────────────────── // ── Export helpers ──────────────────────────────────────────────────
scope.exporting = null; function buildHighResMergedCanvas(pageNum) {
return pdfDoc.getPage(pageNum).then(function (page) {
var EXPORT_SCALE = 2.0;
var viewport = page.getViewport({ scale: EXPORT_SCALE });
// Build a high-resolution merged canvas for export (independent of screen zoom) var canvas = document.createElement('canvas');
const buildHighResMergedCanvas = async (pageNum) => { canvas.width = viewport.width;
const page = await pdfDoc.getPage(pageNum); canvas.height = viewport.height;
const EXPORT_SCALE = 2.0; // High res for crisp PDF var ctx = canvas.getContext('2d');
const viewport = page.getViewport({ scale: EXPORT_SCALE });
// 1. Render PDF page to a hidden canvas return page.render({ canvasContext: ctx, viewport: viewport }).promise.then(function () {
const canvas = document.createElement('canvas'); var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
canvas.width = viewport.width; svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
canvas.height = viewport.height; svg.setAttribute('width', viewport.width);
const ctx = canvas.getContext('2d'); svg.setAttribute('height', viewport.height);
await page.render({ canvasContext: ctx, viewport: viewport }).promise;
// 2. Prepare SVG overlay scope.annotations.filter(function (a) { return a.page === pageNum; }).forEach(function (a) {
// We need to filter and scale annotations for the export scale if (a.type === 'pencil' || a.type === 'highlight') {
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); var el = document.createElementNS('http://www.w3.org/2000/svg', 'path');
svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg'); el.setAttribute('fill', 'none');
svg.setAttribute('width', viewport.width); el.setAttribute('stroke', a.color);
svg.setAttribute('height', viewport.height); el.setAttribute('stroke-width', a.width * EXPORT_SCALE);
el.setAttribute('stroke-linecap', 'round');
var scaledPath = a.data.replace(/([0-9.]+)/g, function (match) { return parseFloat(match) * EXPORT_SCALE; });
el.setAttribute('d', scaledPath);
svg.appendChild(el);
} else if (a.type === 'text') {
var el2 = document.createElementNS('http://www.w3.org/2000/svg', 'text');
el2.setAttribute('x', a.x * EXPORT_SCALE);
el2.setAttribute('y', a.y * EXPORT_SCALE);
el2.setAttribute('fill', 'red');
el2.setAttribute('font-size', (16 * EXPORT_SCALE) + 'px');
el2.setAttribute('dominant-baseline', 'hanging');
el2.textContent = a.text;
svg.appendChild(el2);
}
});
scope.annotations.filter(a => a.page === pageNum).forEach(a => { return new Promise(function (resolve) {
if (a.type === 'pencil' || a.type === 'highlight') { var svgStr = new XMLSerializer().serializeToString(svg);
const el = document.createElementNS('http://www.w3.org/2000/svg', 'path'); var svgBlob = new Blob([svgStr], { type: 'image/svg+xml;charset=utf-8' });
el.setAttribute('fill', 'none'); var blobUrl = URL.createObjectURL(svgBlob);
el.setAttribute('stroke', a.color); var img = new Image();
el.setAttribute('stroke-width', a.width * EXPORT_SCALE); img.onload = function () {
el.setAttribute('stroke-linecap', 'round'); ctx.drawImage(img, 0, 0);
const scaledPath = a.data.replace(/([0-9.]+)/g, (match) => parseFloat(match) * EXPORT_SCALE); URL.revokeObjectURL(blobUrl);
el.setAttribute('d', scaledPath); resolve(canvas);
svg.appendChild(el); };
} else if (a.type === 'text') { img.onerror = function () { URL.revokeObjectURL(blobUrl); resolve(canvas); };
const el = document.createElementNS('http://www.w3.org/2000/svg', 'text'); img.src = blobUrl;
el.setAttribute('x', a.x * EXPORT_SCALE); });
el.setAttribute('y', a.y * EXPORT_SCALE); });
el.setAttribute('fill', 'red');
el.setAttribute('font-size', (16 * EXPORT_SCALE) + 'px');
el.setAttribute('dominant-baseline', 'hanging');
el.textContent = a.text;
svg.appendChild(el);
}
}); });
}
// 3. Merge SVG into Canvas function generateAnnotatedPdf() {
return new Promise((resolve) => { var loadJsPdf = Promise.resolve();
const svgStr = new XMLSerializer().serializeToString(svg);
const svgBlob = new Blob([svgStr], { type: 'image/svg+xml;charset=utf-8' });
const url = URL.createObjectURL(svgBlob);
const img = new Image();
img.onload = () => {
ctx.drawImage(img, 0, 0);
URL.revokeObjectURL(url);
resolve(canvas);
};
img.onerror = () => { URL.revokeObjectURL(url); resolve(canvas); };
img.src = url;
});
};
// Export all pages as a PDF file with annotations burned in
scope.exportPdf = async () => {
if (scope.exporting || !pdfDoc) return;
scope.exporting = 'pdf';
try {
const pdf = await generateAnnotatedPdf();
pdf.save('annotated.pdf');
} catch (e) {
console.error('PDF export error:', e);
alert('Export failed: ' + e.message);
} finally {
scope.$apply(() => { scope.exporting = null; });
}
};
// Helper to generate the jsPDF object
const generateAnnotatedPdf = async () => {
// Dynamically load jsPDF if not present
if (typeof window.jspdf === 'undefined') { if (typeof window.jspdf === 'undefined') {
await new Promise((resolve, reject) => { loadJsPdf = new Promise(function (resolve, reject) {
const s = document.createElement('script'); var s = document.createElement('script');
s.src = 'https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js'; s.src = 'https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js';
s.onload = resolve; s.onload = resolve;
s.onerror = reject; s.onerror = reject;
document.head.appendChild(s); document.head.appendChild(s);
}); });
} }
const { jsPDF } = window.jspdf; return loadJsPdf.then(function () {
const pageIndices = Array.from({ length: pdfDoc.numPages }, (_, i) => i + 1); var jsPDF = window.jspdf.jsPDF;
const canvases = await Promise.all(pageIndices.map(buildHighResMergedCanvas)); var promises = [];
for (var i = 1; i <= pdfDoc.numPages; i++) {
promises.push(buildHighResMergedCanvas(i));
}
return Promise.all(promises).then(function (canvases) {
var firstW = canvases[0].width;
var firstH = canvases[0].height;
var pdf = new jsPDF({
orientation: firstW > firstH ? 'landscape' : 'portrait',
unit: 'px',
format: [firstW, firstH],
hotfixes: ['px_scaling']
});
canvases.forEach(function (c, i) {
if (i > 0) pdf.addPage([c.width, c.height], c.width > c.height ? 'landscape' : 'portrait');
pdf.addImage(c.toDataURL('image/jpeg', 0.95), 'JPEG', 0, 0, c.width, c.height);
});
return pdf;
});
});
}
const firstW = canvases[0].width; scope.exportPdf = function () {
const firstH = canvases[0].height; if (scope.exporting || !pdfDoc) return;
const pdf = new jsPDF({ scope.exporting = 'pdf';
orientation: firstW > firstH ? 'landscape' : 'portrait', generateAnnotatedPdf().then(function (pdf) {
unit: 'px', pdf.save('annotated.pdf');
format: [firstW, firstH], }).catch(function (e) {
hotfixes: ['px_scaling'] console.error('PDF export error:', e);
alert('Export failed: ' + e.message);
}).then(function () {
scope.$apply(function () { scope.exporting = null; });
}); });
canvases.forEach((c, i) => {
if (i > 0) pdf.addPage([c.width, c.height], c.width > c.height ? 'landscape' : 'portrait');
pdf.addImage(c.toDataURL('image/jpeg', 0.95), 'JPEG', 0, 0, c.width, c.height);
});
return pdf;
}; };
// Save the annotated PDF back to Teedy as a new version scope.saveAsVersion = function () {
scope.saveAsVersion = async () => { var docId = getDocId();
const docId = getDocId();
if (scope.exporting || scope.shareId || !docId) return; if (scope.exporting || scope.shareId || !docId) return;
if (!confirm('This will save a new PDF version with annotations permanently "burned in". Continue?')) return; if (!confirm('This will save a new PDF version with annotations permanently "burned in". Continue?')) return;
scope.exporting = 'version'; scope.exporting = 'version';
try { generateAnnotatedPdf().then(function (pdf) {
const pdf = await generateAnnotatedPdf(); var pdfBlob = pdf.output('blob');
const pdfBlob = pdf.output('blob'); var fd = new FormData();
// Prepare multipart form data for Teedy API
const fd = new FormData();
fd.append('id', docId); fd.append('id', docId);
fd.append('previousFileId', scope.fileId); fd.append('previousFileId', scope.fileId);
fd.append('file', pdfBlob, 'annotated.pdf'); fd.append('file', pdfBlob, 'annotated.pdf');
console.log('Uploading new version to Teedy...'); return $http.put('../api/file', fd, {
const resp = await $http.put('../api/file', fd, {
transformRequest: angular.identity, transformRequest: angular.identity,
headers: { 'Content-Type': undefined } headers: { 'Content-Type': undefined }
}); });
}).then(function () {
console.log('Version saved successfully:', resp.data);
alert('New version saved successfully! The page will now reload.'); alert('New version saved successfully! The page will now reload.');
window.location.reload(); // Reload to show the new version window.location.reload();
} catch (e) { }).catch(function (e) {
console.error('Save version error:', e); console.error('Save version error:', e);
alert('Failed to save version: ' + (e.data ? e.data.message : e.message)); alert('Failed to save version: ' + (e.data ? e.data.message : e.message));
} finally { }).then(function () {
scope.$apply(() => { scope.exporting = null; }); scope.$apply(function () { scope.exporting = null; });
} });
}; };
// Drawing logic // Drawing logic
let isDrawing = false; function setupDrawing(svg, pageNum) {
let currentPath = null; svg.onmousedown = function (e) {
let currentElement = null;
const setupDrawing = (svg, pageNum) => {
svg.onmousedown = (e) => {
if (scope.tool === 'cursor' || scope.tool === 'text' || scope.tool === 'eraser' || scope.shareId) return; if (scope.tool === 'cursor' || scope.tool === 'text' || scope.tool === 'eraser' || scope.shareId) return;
var rect = svg.getBoundingClientRect();
const rect = svg.getBoundingClientRect(); var x = (e.clientX - rect.left) / scope.zoom;
const x = (e.clientX - rect.left) / scope.zoom; var y = (e.clientY - rect.top) / scope.zoom;
const y = (e.clientY - rect.top) / scope.zoom;
isDrawing = true; isDrawing = true;
currentPath = `M ${x} ${y}`; currentPath = 'M ' + x + ' ' + y;
currentElement = document.createElementNS('http://www.w3.org/2000/svg', 'path'); currentElement = document.createElementNS('http://www.w3.org/2000/svg', 'path');
currentElement.setAttribute('fill', 'none'); currentElement.setAttribute('fill', 'none');
currentElement.setAttribute('stroke', scope.tool === 'highlight' ? 'rgba(255, 255, 0, 0.4)' : 'red'); currentElement.setAttribute('stroke', scope.tool === 'highlight' ? 'rgba(255, 255, 0, 0.4)' : 'red');
@@ -460,26 +466,25 @@ module.directive('pdfAnnotationViewer', function ($stateParams, Restangular, $ti
svg.appendChild(currentElement); svg.appendChild(currentElement);
}; };
svg.onclick = (e) => { svg.onclick = function (e) {
if (scope.tool !== 'text' || scope.shareId) return; if (scope.tool !== 'text' || scope.shareId) return;
const rect = svg.getBoundingClientRect(); var rect = svg.getBoundingClientRect();
const x = (e.clientX - rect.left) / scope.zoom; var x = (e.clientX - rect.left) / scope.zoom;
const y = (e.clientY - rect.top) / scope.zoom; var y = (e.clientY - rect.top) / scope.zoom;
addTextInput(svg, x, y, pageNum); addTextInput(svg, x, y, pageNum);
}; };
svg.onmousemove = (e) => { svg.onmousemove = function (e) {
if (!isDrawing || !currentElement) return; if (!isDrawing || !currentElement) return;
const rect = svg.getBoundingClientRect(); var rect = svg.getBoundingClientRect();
const x = (e.clientX - rect.left) / scope.zoom; var x = (e.clientX - rect.left) / scope.zoom;
const y = (e.clientY - rect.top) / scope.zoom; var y = (e.clientY - rect.top) / scope.zoom;
currentPath += ' L ' + x + ' ' + y;
currentPath += ` L ${x} ${y}`; var scaledPath = currentPath.replace(/([0-9.]+)/g, function (match) { return parseFloat(match) * scope.zoom; });
const scaledPath = currentPath.replace(/([0-9.]+)/g, (match) => parseFloat(match) * scope.zoom);
currentElement.setAttribute('d', scaledPath); currentElement.setAttribute('d', scaledPath);
}; };
svg.onmouseup = () => { svg.onmouseup = function () {
if (!isDrawing) return; if (!isDrawing) return;
isDrawing = false; isDrawing = false;
if (currentElement) { if (currentElement) {
@@ -493,20 +498,16 @@ module.directive('pdfAnnotationViewer', function ($stateParams, Restangular, $ti
currentElement = null; currentElement = null;
} }
}; };
}; }
const addTextInput = (svg, x, y, pageNum) => { function addTextInput(svg, x, y, pageNum) {
const input = document.createElement('input'); var input = document.createElement('input');
input.type = 'text'; input.type = 'text';
input.className = 'pdf-text-input'; input.className = 'pdf-text-input';
// Prevent browser extensions (e.g. password managers) from attaching autofill overlays
// which cause DOM errors when the input is removed.
input.setAttribute('autocomplete', 'off'); input.setAttribute('autocomplete', 'off');
input.setAttribute('spellcheck', 'false'); input.setAttribute('spellcheck', 'false');
input.setAttribute('data-lpignore', 'true'); input.setAttribute('data-lpignore', 'true');
input.setAttribute('data-1p-ignore', 'true'); input.setAttribute('data-1p-ignore', 'true');
input.style.left = (x * scope.zoom) + 'px'; input.style.left = (x * scope.zoom) + 'px';
input.style.top = (y * scope.zoom) + 'px'; input.style.top = (y * scope.zoom) + 'px';
input.style.fontSize = (16 * scope.zoom) + 'px'; input.style.fontSize = (16 * scope.zoom) + 'px';
@@ -514,15 +515,11 @@ module.directive('pdfAnnotationViewer', function ($stateParams, Restangular, $ti
input.style.minWidth = '120px'; input.style.minWidth = '120px';
input.style.zIndex = '9999'; input.style.zIndex = '9999';
input.placeholder = 'Type here, Enter to confirm'; input.placeholder = 'Type here, Enter to confirm';
// IMPORTANT: disable SVG pointer events while typing so they don't steal focus
svg.style.pointerEvents = 'none'; svg.style.pointerEvents = 'none';
svg.parentElement.appendChild(input); svg.parentElement.appendChild(input);
input.focus(); input.focus();
const finishInput = () => { var finishInput = function () {
// Re-enable SVG pointer events
svg.style.pointerEvents = ''; svg.style.pointerEvents = '';
if (input.value.trim()) { if (input.value.trim()) {
scope.annotations.push({ scope.annotations.push({
@@ -538,77 +535,66 @@ module.directive('pdfAnnotationViewer', function ($stateParams, Restangular, $ti
}; };
input.onblur = finishInput; input.onblur = finishInput;
input.onkeydown = function (e) {
input.onkeydown = (e) => {
e.stopPropagation(); e.stopPropagation();
if (e.key === 'Enter') { input.onblur = null; finishInput(); } if (e.key === 'Enter') { input.onblur = null; finishInput(); }
else if (e.key === 'Escape') { input.onblur = null; svg.style.pointerEvents = ''; input.remove(); } else if (e.key === 'Escape') { input.onblur = null; svg.style.pointerEvents = ''; input.remove(); }
}; };
}; }
const renderAnnotations = () => { // Save annotations
pages.forEach(p => renderPageAnnotations(p.i, p.svg)); scope.saveAnnotations = function () {
}; var docId = getDocId();
scope.saveAnnotations = () => {
const docId = getDocId();
if (scope.shareId) return; if (scope.shareId) return;
if (!docId) { if (!docId) {
alert('Cannot save: Document ID is missing. Are you in Quick Upload mode?'); alert('Cannot save: Document ID is missing.');
return; return;
} }
scope.saving = true; scope.saving = true;
Restangular.one('comment', docId).get().then(data => { Restangular.one('comment', docId).get().then(function (data) {
const oldAnnos = data.comments.filter(c => c.content.startsWith('[ANNOTATION]')); var oldAnnos = data.comments.filter(function (c) { return c.content.indexOf('[ANNOTATION]') === 0; });
const deleteNext = () => { var deleteNext = function () {
if (oldAnnos.length > 0) { if (oldAnnos.length > 0) {
const c = oldAnnos.shift(); var c = oldAnnos.shift();
Restangular.one('comment', c.id).remove().then(deleteNext).catch(err => { Restangular.one('comment', c.id).remove().then(deleteNext).catch(function (err) {
console.error('Error deleting old annotation:', err); console.error('Error deleting old annotation:', err);
alert('Failed to overwrite old annotations.'); alert('Failed to overwrite old annotations.');
scope.$apply(() => { scope.saving = false; }); scope.$apply(function () { scope.saving = false; });
}); });
} else { } else {
// Server uses @PUT with @FormParam - must send as application/x-www-form-urlencoded var formData = 'id=' + encodeURIComponent(docId) +
const formData = 'id=' + encodeURIComponent(docId) + '&content=' + encodeURIComponent('[ANNOTATION]' + JSON.stringify(scope.annotations));
'&content=' + encodeURIComponent('[ANNOTATION]' + JSON.stringify(scope.annotations));
$http({ $http({
method: 'PUT', method: 'PUT',
url: '../api/comment', url: '../api/comment',
data: formData, data: formData,
headers: { 'Content-Type': 'application/x-www-form-urlencoded' } headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
}).then(() => { }).then(function () {
console.log('Annotations saved successfully!'); console.log('Annotations saved successfully!');
scope.saving = false; scope.saving = false;
}, err => { }, function (err) {
console.error('Error saving annotation:', err); console.error('Error saving annotation:', err);
alert('Failed to save annotations. Check console for details.'); alert('Failed to save annotations.');
scope.saving = false; scope.saving = false;
}); });
} }
}; };
deleteNext(); deleteNext();
}).catch(err => { }).catch(function (err) {
console.error('Error fetching comments:', err); console.error('Error fetching comments:', err);
alert('Failed to connect to the server to save annotations. Are you still logged in?'); alert('Failed to connect to server. Are you still logged in?');
scope.$apply(() => { scope.saving = false; }); scope.$apply(function () { scope.saving = false; });
}); });
}; };
// Watch fileId - reset all state and reload when switching between files // Watch fileId - reset and reload when switching files
scope.$watch('fileId', (newFileId) => { scope.$watch('fileId', function (newFileId) {
if (!newFileId) return; if (!newFileId) return;
// Reset state
scope.annotations = []; scope.annotations = [];
pdfDoc = null; pdfDoc = null;
pages = []; pages = [];
const url = `../api/file/${newFileId}/data` + (scope.shareId ? `?share=${scope.shareId}` : ''); var url = '../api/file/' + newFileId + '/data' + (scope.shareId ? '?share=' + scope.shareId : '');
$timeout(function () {
// Use $timeout to wait for the current digest cycle to finish.
// This ensures scope.documentId is updated before we fetch annotations.
$timeout(() => {
startLoading(url); startLoading(url);
}); });
}); });
+1 -1
View File
@@ -28,6 +28,7 @@
}; };
</script> </script>
<!-- endref --> <!-- endref -->
<script src="lib/pdf.min.js" type="text/javascript"></script>
<!-- ref:js docs.min.js?@build.date@ --> <!-- ref:js docs.min.js?@build.date@ -->
<script src="lib/jquery.js" type="text/javascript"></script> <script src="lib/jquery.js" type="text/javascript"></script>
<script src="lib/jquery.ui.js" type="text/javascript"></script> <script src="lib/jquery.ui.js" type="text/javascript"></script>
@@ -51,7 +52,6 @@
<script src="lib/angular.qrcode.js" type="text/javascript"></script> <script src="lib/angular.qrcode.js" type="text/javascript"></script>
<script src="lib/angular.timeago.js" type="text/javascript"></script> <script src="lib/angular.timeago.js" type="text/javascript"></script>
<script src="lib/angular.ng-onboarding.js" type="text/javascript"></script> <script src="lib/angular.ng-onboarding.js" type="text/javascript"></script>
<script src="lib/pdf.js" type="text/javascript"></script>
<script src="app/docs/app.js" type="text/javascript"></script> <script src="app/docs/app.js" type="text/javascript"></script>
<script src="app/docs/directive/PdfAnnotationViewer.js" type="text/javascript"></script> <script src="app/docs/directive/PdfAnnotationViewer.js" type="text/javascript"></script>
<script src="app/docs/controller/Login.js" type="text/javascript"></script> <script src="app/docs/controller/Login.js" type="text/javascript"></script>
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -24,6 +24,7 @@
}; };
</script> </script>
<!-- endref --> <!-- endref -->
<script src="lib/pdf.min.js" type="text/javascript"></script>
<!-- ref:js share.min.js?@build.date@ --> <!-- ref:js share.min.js?@build.date@ -->
<script src="lib/jquery.js" type="text/javascript"></script> <script src="lib/jquery.js" type="text/javascript"></script>
<script src="lib/less.js" type="text/javascript"></script> <script src="lib/less.js" type="text/javascript"></script>
@@ -35,7 +36,6 @@
<script src="lib/angular.tmhDynamicLocale.js" type="text/javascript"></script> <script src="lib/angular.tmhDynamicLocale.js" type="text/javascript"></script>
<script src="lib/angular.ui-router.js" type="text/javascript"></script> <script src="lib/angular.ui-router.js" type="text/javascript"></script>
<script src="lib/angular.ui-bootstrap.js" type="text/javascript"></script> <script src="lib/angular.ui-bootstrap.js" type="text/javascript"></script>
<script src="lib/pdf.js" type="text/javascript"></script>
<script src="app/share/app.js" type="text/javascript"></script> <script src="app/share/app.js" type="text/javascript"></script>
<script src="app/docs/directive/PdfAnnotationViewer.js" type="text/javascript"></script> <script src="app/docs/directive/PdfAnnotationViewer.js" type="text/javascript"></script>
<script src="app/share/controller/Main.js" type="text/javascript"></script> <script src="app/share/controller/Main.js" type="text/javascript"></script>
Binary file not shown.
+3
View File
@@ -0,0 +1,3 @@
2026-04-24 02:44:38 jdbc[3]: exception
org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "T_CONFIG" not found; SQL statement:
select c.CFG_VALUE_C from T_CONFIG c where c.CFG_ID_C='DB_VERSION' [42102-199]
+196
View File
@@ -0,0 +1,196 @@
24 Apr 2026 01:06:23,641 INFO com.sismics.util.jpa.EMF.getEntityManagerProperties(EMF.java:67) Configuring EntityManager from hibernate.properties
24 Apr 2026 01:06:24,459 INFO com.sismics.util.jpa.DbOpenHelper.open(DbOpenHelper.java:57) Opening database and executing incremental updates
24 Apr 2026 01:06:24,460 INFO com.sismics.util.jpa.DbOpenHelper.open(DbOpenHelper.java:83) Unable to get database version: Table T_CONFIG not found
24 Apr 2026 01:06:24,461 INFO com.sismics.util.jpa.DbOpenHelper.open(DbOpenHelper.java:98) Executing initial schema creation script
24 Apr 2026 01:06:24,465 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-000-0.sql
24 Apr 2026 01:06:24,518 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-000-1.sql
24 Apr 2026 01:06:24,523 INFO com.sismics.util.jpa.DbOpenHelper.open(DbOpenHelper.java:106) Found database version 0, new version is 31, executing database incremental update scripts
24 Apr 2026 01:06:24,524 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-001-0.sql
24 Apr 2026 01:06:24,550 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-002-0.sql
24 Apr 2026 01:06:24,556 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-003-0.sql
24 Apr 2026 01:06:24,562 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-004-0.sql
24 Apr 2026 01:06:24,573 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-005-0.sql
24 Apr 2026 01:06:24,576 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-006-0.sql
24 Apr 2026 01:06:24,678 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-007-0.sql
24 Apr 2026 01:06:24,682 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-008-0.sql
24 Apr 2026 01:06:24,686 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-009-0.sql
24 Apr 2026 01:06:24,691 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-010-0.sql
24 Apr 2026 01:06:24,694 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-011-0.sql
24 Apr 2026 01:06:24,699 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-012-0.sql
24 Apr 2026 01:06:24,704 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-013-0.sql
24 Apr 2026 01:06:24,709 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-014-0.sql
24 Apr 2026 01:06:24,716 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-015-0.sql
24 Apr 2026 01:06:24,729 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-016-0.sql
24 Apr 2026 01:06:24,731 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-017-0.sql
24 Apr 2026 01:06:24,734 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-018-0.sql
24 Apr 2026 01:06:24,769 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-019-0.sql
24 Apr 2026 01:06:24,771 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-020-0.sql
24 Apr 2026 01:06:24,773 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-021-0.sql
24 Apr 2026 01:06:24,781 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-022-0.sql
24 Apr 2026 01:06:24,790 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-023-0.sql
24 Apr 2026 01:06:24,796 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-024-0.sql
24 Apr 2026 01:06:24,803 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-025-0.sql
24 Apr 2026 01:06:24,805 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-026-0.sql
24 Apr 2026 01:06:24,806 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-027-0.sql
24 Apr 2026 01:06:24,806 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-028-0.sql
24 Apr 2026 01:06:24,807 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-029-0.sql
24 Apr 2026 01:06:24,811 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-030-0.sql
24 Apr 2026 01:06:24,813 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-031-0.sql
24 Apr 2026 01:06:24,814 INFO com.sismics.util.jpa.DbOpenHelper.open(DbOpenHelper.java:108) Database upgrade complete
24 Apr 2026 01:06:24,815 INFO com.sismics.util.jpa.EMF.getEntityManagerProperties(EMF.java:67) Configuring EntityManager from hibernate.properties
24 Apr 2026 01:06:27,303 INFO com.sismics.util.ClasspathScanner.findClasses(ClasspathScanner.java:48) Found 1 classes for IndexingHandler
24 Apr 2026 01:06:27,389 INFO com.sismics.docs.core.util.indexing.LuceneIndexingHandler.initLucene(LuceneIndexingHandler.java:129) Using RAM Lucene storage
24 Apr 2026 01:06:27,537 INFO com.sismics.docs.core.service.FileService.startUp(FileService.java:39) File service starting up
24 Apr 2026 01:06:27,545 INFO com.sismics.docs.core.service.InboxService.startUp(InboxService.java:52) Inbox service starting up
24 Apr 2026 01:06:27,547 INFO com.sismics.docs.core.service.FileSizeService.startUp(FileSizeService.java:30) File size service starting up
24 Apr 2026 01:06:27,864 INFO com.sismics.docs.core.service.FileSizeService.lambda$runOneIteration$0(FileSizeService.java:50) No more file to process, stopping the service
24 Apr 2026 01:06:27,866 INFO com.sismics.docs.core.service.FileSizeService.shutDown(FileSizeService.java:35) File size service shutting down
24 Apr 2026 01:06:59,064 INFO com.sismics.docs.core.service.InboxService.shutDown(InboxService.java:57) Inbox service shutting down
24 Apr 2026 01:06:59,065 INFO com.sismics.docs.core.service.FileService.shutDown(FileService.java:44) File service shutting down
24 Apr 2026 01:07:01,905 INFO com.sismics.util.jpa.EMF.getEntityManagerProperties(EMF.java:67) Configuring EntityManager from hibernate.properties
24 Apr 2026 01:07:02,419 INFO com.sismics.util.jpa.DbOpenHelper.open(DbOpenHelper.java:57) Opening database and executing incremental updates
24 Apr 2026 01:07:02,420 INFO com.sismics.util.jpa.DbOpenHelper.open(DbOpenHelper.java:83) Unable to get database version: Table T_CONFIG not found
24 Apr 2026 01:07:02,420 INFO com.sismics.util.jpa.DbOpenHelper.open(DbOpenHelper.java:98) Executing initial schema creation script
24 Apr 2026 01:07:02,425 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-000-0.sql
24 Apr 2026 01:07:02,475 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-000-1.sql
24 Apr 2026 01:07:02,480 INFO com.sismics.util.jpa.DbOpenHelper.open(DbOpenHelper.java:106) Found database version 0, new version is 31, executing database incremental update scripts
24 Apr 2026 01:07:02,482 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-001-0.sql
24 Apr 2026 01:07:02,503 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-002-0.sql
24 Apr 2026 01:07:02,507 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-003-0.sql
24 Apr 2026 01:07:02,513 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-004-0.sql
24 Apr 2026 01:07:02,525 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-005-0.sql
24 Apr 2026 01:07:02,528 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-006-0.sql
24 Apr 2026 01:07:02,618 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-007-0.sql
24 Apr 2026 01:07:02,622 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-008-0.sql
24 Apr 2026 01:07:02,628 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-009-0.sql
24 Apr 2026 01:07:02,632 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-010-0.sql
24 Apr 2026 01:07:02,634 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-011-0.sql
24 Apr 2026 01:07:02,637 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-012-0.sql
24 Apr 2026 01:07:02,642 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-013-0.sql
24 Apr 2026 01:07:02,644 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-014-0.sql
24 Apr 2026 01:07:02,648 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-015-0.sql
24 Apr 2026 01:07:02,657 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-016-0.sql
24 Apr 2026 01:07:02,659 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-017-0.sql
24 Apr 2026 01:07:02,662 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-018-0.sql
24 Apr 2026 01:07:02,687 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-019-0.sql
24 Apr 2026 01:07:02,689 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-020-0.sql
24 Apr 2026 01:07:02,692 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-021-0.sql
24 Apr 2026 01:07:02,696 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-022-0.sql
24 Apr 2026 01:07:02,702 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-023-0.sql
24 Apr 2026 01:07:02,706 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-024-0.sql
24 Apr 2026 01:07:02,711 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-025-0.sql
24 Apr 2026 01:07:02,712 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-026-0.sql
24 Apr 2026 01:07:02,713 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-027-0.sql
24 Apr 2026 01:07:02,714 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-028-0.sql
24 Apr 2026 01:07:02,715 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-029-0.sql
24 Apr 2026 01:07:02,719 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-030-0.sql
24 Apr 2026 01:07:02,721 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-031-0.sql
24 Apr 2026 01:07:02,722 INFO com.sismics.util.jpa.DbOpenHelper.open(DbOpenHelper.java:108) Database upgrade complete
24 Apr 2026 01:07:02,722 INFO com.sismics.util.jpa.EMF.getEntityManagerProperties(EMF.java:67) Configuring EntityManager from hibernate.properties
24 Apr 2026 01:07:04,607 INFO com.sismics.util.ClasspathScanner.findClasses(ClasspathScanner.java:48) Found 1 classes for IndexingHandler
24 Apr 2026 01:07:04,680 INFO com.sismics.docs.core.util.indexing.LuceneIndexingHandler.initLucene(LuceneIndexingHandler.java:129) Using RAM Lucene storage
24 Apr 2026 01:07:04,758 INFO com.sismics.docs.core.service.FileService.startUp(FileService.java:39) File service starting up
24 Apr 2026 01:07:04,765 INFO com.sismics.docs.core.service.InboxService.startUp(InboxService.java:52) Inbox service starting up
24 Apr 2026 01:07:04,767 INFO com.sismics.docs.core.service.FileSizeService.startUp(FileSizeService.java:30) File size service starting up
24 Apr 2026 01:07:05,033 INFO com.sismics.docs.core.service.FileSizeService.lambda$runOneIteration$0(FileSizeService.java:50) No more file to process, stopping the service
24 Apr 2026 01:07:05,034 INFO com.sismics.docs.core.service.FileSizeService.shutDown(FileSizeService.java:35) File size service shutting down
24 Apr 2026 02:28:14,883 INFO com.sismics.docs.core.service.InboxService.shutDown(InboxService.java:57) Inbox service shutting down
24 Apr 2026 02:28:14,886 INFO com.sismics.docs.core.service.FileService.shutDown(FileService.java:44) File service shutting down
24 Apr 2026 02:28:20,277 INFO com.sismics.util.jpa.EMF.getEntityManagerProperties(EMF.java:67) Configuring EntityManager from hibernate.properties
24 Apr 2026 02:28:21,203 INFO com.sismics.util.jpa.DbOpenHelper.open(DbOpenHelper.java:57) Opening database and executing incremental updates
24 Apr 2026 02:28:21,204 INFO com.sismics.util.jpa.DbOpenHelper.open(DbOpenHelper.java:83) Unable to get database version: Table T_CONFIG not found
24 Apr 2026 02:28:21,204 INFO com.sismics.util.jpa.DbOpenHelper.open(DbOpenHelper.java:98) Executing initial schema creation script
24 Apr 2026 02:28:21,211 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-000-0.sql
24 Apr 2026 02:28:21,270 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-000-1.sql
24 Apr 2026 02:28:21,274 INFO com.sismics.util.jpa.DbOpenHelper.open(DbOpenHelper.java:106) Found database version 0, new version is 31, executing database incremental update scripts
24 Apr 2026 02:28:21,275 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-001-0.sql
24 Apr 2026 02:28:21,297 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-002-0.sql
24 Apr 2026 02:28:21,302 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-003-0.sql
24 Apr 2026 02:28:21,307 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-004-0.sql
24 Apr 2026 02:28:21,320 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-005-0.sql
24 Apr 2026 02:28:21,323 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-006-0.sql
24 Apr 2026 02:28:21,423 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-007-0.sql
24 Apr 2026 02:28:21,427 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-008-0.sql
24 Apr 2026 02:28:21,431 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-009-0.sql
24 Apr 2026 02:28:21,436 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-010-0.sql
24 Apr 2026 02:28:21,437 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-011-0.sql
24 Apr 2026 02:28:21,441 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-012-0.sql
24 Apr 2026 02:28:21,447 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-013-0.sql
24 Apr 2026 02:28:21,449 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-014-0.sql
24 Apr 2026 02:28:21,454 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-015-0.sql
24 Apr 2026 02:28:21,464 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-016-0.sql
24 Apr 2026 02:28:21,465 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-017-0.sql
24 Apr 2026 02:28:21,467 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-018-0.sql
24 Apr 2026 02:28:21,497 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-019-0.sql
24 Apr 2026 02:28:21,499 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-020-0.sql
24 Apr 2026 02:28:21,501 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-021-0.sql
24 Apr 2026 02:28:21,506 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-022-0.sql
24 Apr 2026 02:28:21,513 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-023-0.sql
24 Apr 2026 02:28:21,517 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-024-0.sql
24 Apr 2026 02:28:21,522 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-025-0.sql
24 Apr 2026 02:28:21,524 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-026-0.sql
24 Apr 2026 02:28:21,526 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-027-0.sql
24 Apr 2026 02:28:21,527 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-028-0.sql
24 Apr 2026 02:28:21,528 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-029-0.sql
24 Apr 2026 02:28:21,532 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-030-0.sql
24 Apr 2026 02:28:21,533 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-031-0.sql
24 Apr 2026 02:28:21,534 INFO com.sismics.util.jpa.DbOpenHelper.open(DbOpenHelper.java:108) Database upgrade complete
24 Apr 2026 02:28:21,534 INFO com.sismics.util.jpa.EMF.getEntityManagerProperties(EMF.java:67) Configuring EntityManager from hibernate.properties
24 Apr 2026 02:28:23,680 INFO com.sismics.util.ClasspathScanner.findClasses(ClasspathScanner.java:48) Found 1 classes for IndexingHandler
24 Apr 2026 02:28:23,737 INFO com.sismics.docs.core.util.indexing.LuceneIndexingHandler.initLucene(LuceneIndexingHandler.java:129) Using RAM Lucene storage
24 Apr 2026 02:28:23,815 INFO com.sismics.docs.core.service.FileService.startUp(FileService.java:39) File service starting up
24 Apr 2026 02:28:23,822 INFO com.sismics.docs.core.service.InboxService.startUp(InboxService.java:52) Inbox service starting up
24 Apr 2026 02:28:23,825 INFO com.sismics.docs.core.service.FileSizeService.startUp(FileSizeService.java:30) File size service starting up
24 Apr 2026 02:28:24,137 INFO com.sismics.docs.core.service.FileSizeService.lambda$runOneIteration$0(FileSizeService.java:50) No more file to process, stopping the service
24 Apr 2026 02:28:24,138 INFO com.sismics.docs.core.service.FileSizeService.shutDown(FileSizeService.java:35) File size service shutting down
24 Apr 2026 02:44:22,529 INFO com.sismics.docs.core.service.InboxService.shutDown(InboxService.java:57) Inbox service shutting down
24 Apr 2026 02:44:22,530 INFO com.sismics.docs.core.service.FileService.shutDown(FileService.java:44) File service shutting down
24 Apr 2026 02:44:38,323 INFO com.sismics.util.jpa.EMF.getEntityManagerProperties(EMF.java:87) Configuring EntityManager from environment parameters
24 Apr 2026 02:44:38,327 WARN com.sismics.util.jpa.EMF.getEntityManagerProperties(EMF.java:92) Using an embedded H2 database. Only suitable for testing purpose, not for production!
24 Apr 2026 02:44:38,871 INFO com.sismics.util.jpa.DbOpenHelper.open(DbOpenHelper.java:57) Opening database and executing incremental updates
24 Apr 2026 02:44:38,873 INFO com.sismics.util.jpa.DbOpenHelper.open(DbOpenHelper.java:83) Unable to get database version: Table T_CONFIG not found
24 Apr 2026 02:44:38,874 INFO com.sismics.util.jpa.DbOpenHelper.open(DbOpenHelper.java:98) Executing initial schema creation script
24 Apr 2026 02:44:38,878 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-000-0.sql
24 Apr 2026 02:44:38,929 INFO com.sismics.util.jpa.DbOpenHelper.open(DbOpenHelper.java:106) Found database version 0, new version is 31, executing database incremental update scripts
24 Apr 2026 02:44:38,931 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-001-0.sql
24 Apr 2026 02:44:38,955 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-002-0.sql
24 Apr 2026 02:44:38,959 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-003-0.sql
24 Apr 2026 02:44:38,963 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-004-0.sql
24 Apr 2026 02:44:38,974 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-005-0.sql
24 Apr 2026 02:44:38,975 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-006-0.sql
24 Apr 2026 02:44:39,028 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-007-0.sql
24 Apr 2026 02:44:39,031 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-008-0.sql
24 Apr 2026 02:44:39,036 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-009-0.sql
24 Apr 2026 02:44:39,041 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-010-0.sql
24 Apr 2026 02:44:39,044 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-011-0.sql
24 Apr 2026 02:44:39,046 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-012-0.sql
24 Apr 2026 02:44:39,050 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-013-0.sql
24 Apr 2026 02:44:39,052 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-014-0.sql
24 Apr 2026 02:44:39,057 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-015-0.sql
24 Apr 2026 02:44:39,066 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-016-0.sql
24 Apr 2026 02:44:39,068 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-017-0.sql
24 Apr 2026 02:44:39,069 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-018-0.sql
24 Apr 2026 02:44:39,085 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-019-0.sql
24 Apr 2026 02:44:39,087 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-020-0.sql
24 Apr 2026 02:44:39,089 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-021-0.sql
24 Apr 2026 02:44:39,094 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-022-0.sql
24 Apr 2026 02:44:39,102 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-023-0.sql
24 Apr 2026 02:44:39,108 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-024-0.sql
24 Apr 2026 02:44:39,112 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-025-0.sql
24 Apr 2026 02:44:39,114 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-026-0.sql
24 Apr 2026 02:44:39,115 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-027-0.sql
24 Apr 2026 02:44:39,116 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-028-0.sql
24 Apr 2026 02:44:39,117 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-029-0.sql
24 Apr 2026 02:44:39,121 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-030-0.sql
24 Apr 2026 02:44:39,123 INFO com.sismics.util.jpa.DbOpenHelper.executeAllScript(DbOpenHelper.java:142) Executing script: dbupdate-031-0.sql
24 Apr 2026 02:44:39,124 INFO com.sismics.util.jpa.DbOpenHelper.open(DbOpenHelper.java:108) Database upgrade complete
24 Apr 2026 02:44:39,125 INFO com.sismics.util.jpa.EMF.getEntityManagerProperties(EMF.java:87) Configuring EntityManager from environment parameters
24 Apr 2026 02:44:39,125 WARN com.sismics.util.jpa.EMF.getEntityManagerProperties(EMF.java:92) Using an embedded H2 database. Only suitable for testing purpose, not for production!
24 Apr 2026 02:44:41,034 INFO com.sismics.util.ClasspathScanner.findClasses(ClasspathScanner.java:48) Found 1 classes for IndexingHandler
24 Apr 2026 02:44:41,080 INFO com.sismics.docs.core.util.indexing.LuceneIndexingHandler.initLucene(LuceneIndexingHandler.java:132) Using file Lucene storage: /data/lucene
24 Apr 2026 02:44:41,167 INFO com.sismics.docs.core.service.FileService.startUp(FileService.java:39) File service starting up
24 Apr 2026 02:44:41,174 INFO com.sismics.docs.core.service.InboxService.startUp(InboxService.java:52) Inbox service starting up
24 Apr 2026 02:44:41,176 INFO com.sismics.docs.core.service.FileSizeService.startUp(FileSizeService.java:30) File size service starting up
24 Apr 2026 02:44:41,477 INFO com.sismics.docs.core.service.FileSizeService.lambda$runOneIteration$0(FileSizeService.java:50) No more file to process, stopping the service
24 Apr 2026 02:44:41,479 INFO com.sismics.docs.core.service.FileSizeService.shutDown(FileSizeService.java:35) File size service shutting down
24 Apr 2026 06:18:50,414 INFO com.sismics.util.ClasspathScanner.findClasses(ClasspathScanner.java:48) Found 2 classes for AuthenticationHandler