diff --git a/data/demo.mv.db b/data/demo.mv.db index c687424bbc764ff63cdef9e93a82885258976e41..7ce692294bc8c4f8f1c7c478ed4243370dcb0e91 100644 Binary files a/data/demo.mv.db and b/data/demo.mv.db differ diff --git a/data/demo.trace.db b/data/demo.trace.db index 3cde3d557eac8e2db17864936f7172b79c1db6f1..761ae41aba90c3047e5e8ef8cbdd918503f7dba4 100644 --- a/data/demo.trace.db +++ b/data/demo.trace.db @@ -3366,3 +3366,270 @@ insert into documents (abstract_text,category_id,content,doi,notes,publication_y org.h2.jdbc.JdbcSQLDataException: Hodnota je prĂliš dlhá pre stÄşpec "TITLE CHARACTER VARYING(255)": "'The in vitro induction of human immunodeficiency virus (HIV) replication in pur... (311)" Value too long for column "TITLE CHARACTER VARYING(255)": "'The in vitro induction of human immunodeficiency virus (HIV) replication in pur... (311)"; SQL statement: insert into documents (abstract_text,category_id,content,doi,notes,publication_year,publisher,status,target,title,id) values (?,?,?,?,?,?,?,?,?,?,default) [22001-232] +2025-04-29 11:42:42.721697+02:00 database: flush +org.h2.message.DbException: Všeobecná chyba: "org.h2.mvstore.MVStoreException: The file is locked: C:/Users/elidr/pdf-processor/data/demo.mv.db [2.3.232/7]" +General error: "org.h2.mvstore.MVStoreException: The file is locked: C:/Users/elidr/pdf-processor/data/demo.mv.db [2.3.232/7]" [50000-232] + at org.h2.message.DbException.get(DbException.java:212) + at org.h2.message.DbException.convert(DbException.java:407) + at org.h2.mvstore.db.Store.lambda$new$0(Store.java:122) + at org.h2.mvstore.MVStore.handleException(MVStore.java:1546) + at org.h2.mvstore.MVStore.panic(MVStore.java:371) + at org.h2.mvstore.MVStore.<init>(MVStore.java:291) + at org.h2.mvstore.MVStore$Builder.open(MVStore.java:2035) + at org.h2.mvstore.db.Store.<init>(Store.java:133) + at org.h2.engine.Database.<init>(Database.java:326) + at org.h2.engine.Engine.openSession(Engine.java:92) + at org.h2.engine.Engine.openSession(Engine.java:222) + at org.h2.engine.Engine.createSession(Engine.java:201) + at org.h2.engine.SessionRemote.connectEmbeddedOrServer(SessionRemote.java:344) + at org.h2.jdbc.JdbcConnection.<init>(JdbcConnection.java:124) + at org.h2.Driver.connect(Driver.java:59) + at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:137) + at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:360) + at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:202) + at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:461) + at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:550) + at com.zaxxer.hikari.pool.HikariPool.<init>(HikariPool.java:98) + at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:111) + at org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration.getConnectionUrl(H2ConsoleAutoConfiguration.java:94) + at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:215) + at java.base/java.util.ArrayList.forEach(ArrayList.java:1597) + at java.base/java.util.stream.SortedOps$RefSortingSink.end(SortedOps.java:395) + at java.base/java.util.stream.Sink$ChainedReference.end(Sink.java:261) + at java.base/java.util.stream.Sink$ChainedReference.end(Sink.java:261) + at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:571) + at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:560) + at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:636) + at java.base/java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:291) + at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:656) + at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:662) + at java.base/java.util.stream.ReferencePipeline.toList(ReferencePipeline.java:667) + at org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration.logDataSources(H2ConsoleAutoConfiguration.java:86) + at org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration.lambda$h2Console$0(H2ConsoleAutoConfiguration.java:69) + at org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration.withThreadContextClassLoader(H2ConsoleAutoConfiguration.java:78) + at org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration.h2Console(H2ConsoleAutoConfiguration.java:69) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) + at java.base/java.lang.reflect.Method.invoke(Method.java:580) + at org.springframework.beans.factory.support.SimpleInstantiationStrategy.lambda$instantiate$0(SimpleInstantiationStrategy.java:171) + at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiateWithFactoryMethod(SimpleInstantiationStrategy.java:88) + at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:168) + at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:645) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1351) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1181) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:563) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:523) + at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:336) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:288) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:334) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:204) + at org.springframework.boot.web.servlet.ServletContextInitializerBeans.getOrderedBeansOfType(ServletContextInitializerBeans.java:211) + at org.springframework.boot.web.servlet.ServletContextInitializerBeans.getOrderedBeansOfType(ServletContextInitializerBeans.java:202) + at org.springframework.boot.web.servlet.ServletContextInitializerBeans.addServletContextInitializerBeans(ServletContextInitializerBeans.java:97) + at org.springframework.boot.web.servlet.ServletContextInitializerBeans.<init>(ServletContextInitializerBeans.java:86) + at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.getServletContextInitializerBeans(ServletWebServerApplicationContext.java:266) + at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.selfInitialize(ServletWebServerApplicationContext.java:240) + at org.springframework.boot.web.embedded.tomcat.TomcatStarter.onStartup(TomcatStarter.java:52) + at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:4426) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:164) + at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1203) + at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1193) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317) + at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75) + at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:148) + at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:749) + at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:772) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:164) + at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1203) + at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1193) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317) + at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75) + at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:148) + at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:749) + at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:203) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:164) + at org.apache.catalina.core.StandardService.startInternal(StandardService.java:415) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:164) + at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:870) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:164) + at org.apache.catalina.startup.Tomcat.start(Tomcat.java:437) + at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.initialize(TomcatWebServer.java:128) + at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.<init>(TomcatWebServer.java:107) + at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getTomcatWebServer(TomcatServletWebServerFactory.java:516) + at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getWebServer(TomcatServletWebServerFactory.java:222) + at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:188) + at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:162) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:621) + at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:752) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:439) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:318) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:1361) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:1350) + at com.dre0059.articleprocessor.ArticleProcessorApplication.main(ArticleProcessorApplication.java:10) +Caused by: org.h2.jdbc.JdbcSQLNonTransientException: Všeobecná chyba: "org.h2.mvstore.MVStoreException: The file is locked: C:/Users/elidr/pdf-processor/data/demo.mv.db [2.3.232/7]" +General error: "org.h2.mvstore.MVStoreException: The file is locked: C:/Users/elidr/pdf-processor/data/demo.mv.db [2.3.232/7]" [50000-232] + at org.h2.message.DbException.getJdbcSQLException(DbException.java:566) + at org.h2.message.DbException.getJdbcSQLException(DbException.java:489) + ... 98 more +Caused by: org.h2.mvstore.MVStoreException: The file is locked: C:/Users/elidr/pdf-processor/data/demo.mv.db [2.3.232/7] + at org.h2.mvstore.DataUtils.newMVStoreException(DataUtils.java:996) + at org.h2.mvstore.SingleFileStore.lockFileChannel(SingleFileStore.java:143) + at org.h2.mvstore.SingleFileStore.open(SingleFileStore.java:117) + at org.h2.mvstore.SingleFileStore.open(SingleFileStore.java:81) + at org.h2.mvstore.MVStore.<init>(MVStore.java:286) + ... 92 more +2025-04-29 11:42:44.133669+02:00 database: flush +org.h2.message.DbException: Všeobecná chyba: "org.h2.mvstore.MVStoreException: The file is locked: C:/Users/elidr/pdf-processor/data/demo.mv.db [2.3.232/7]" +General error: "org.h2.mvstore.MVStoreException: The file is locked: C:/Users/elidr/pdf-processor/data/demo.mv.db [2.3.232/7]" [50000-232] + at org.h2.message.DbException.get(DbException.java:212) + at org.h2.message.DbException.convert(DbException.java:407) + at org.h2.mvstore.db.Store.lambda$new$0(Store.java:122) + at org.h2.mvstore.MVStore.handleException(MVStore.java:1546) + at org.h2.mvstore.MVStore.panic(MVStore.java:371) + at org.h2.mvstore.MVStore.<init>(MVStore.java:291) + at org.h2.mvstore.MVStore$Builder.open(MVStore.java:2035) + at org.h2.mvstore.db.Store.<init>(Store.java:133) + at org.h2.engine.Database.<init>(Database.java:326) + at org.h2.engine.Engine.openSession(Engine.java:92) + at org.h2.engine.Engine.openSession(Engine.java:222) + at org.h2.engine.Engine.createSession(Engine.java:201) + at org.h2.engine.SessionRemote.connectEmbeddedOrServer(SessionRemote.java:344) + at org.h2.jdbc.JdbcConnection.<init>(JdbcConnection.java:124) + at org.h2.Driver.connect(Driver.java:59) + at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:137) + at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:360) + at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:202) + at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:461) + at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:550) + at com.zaxxer.hikari.pool.HikariPool.<init>(HikariPool.java:98) + at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:111) + at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:126) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:467) + at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcIsolationDelegate.delegateWork(JdbcIsolationDelegate.java:61) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.getJdbcEnvironmentUsingJdbcMetadata(JdbcEnvironmentInitiator.java:320) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:129) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:81) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:130) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:263) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:238) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:215) + at org.hibernate.boot.model.relational.Database.<init>(Database.java:45) + at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.getDatabase(InFlightMetadataCollectorImpl.java:226) + at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.<init>(InFlightMetadataCollectorImpl.java:194) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:171) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1431) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1502) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:66) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:390) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:419) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:400) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:366) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1849) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1798) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:601) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:523) + at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:336) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:288) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:334) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:204) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:970) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:627) + at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:752) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:439) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:318) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:1361) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:1350) + at com.dre0059.articleprocessor.ArticleProcessorApplication.main(ArticleProcessorApplication.java:10) +Caused by: org.h2.jdbc.JdbcSQLNonTransientException: Všeobecná chyba: "org.h2.mvstore.MVStoreException: The file is locked: C:/Users/elidr/pdf-processor/data/demo.mv.db [2.3.232/7]" +General error: "org.h2.mvstore.MVStoreException: The file is locked: C:/Users/elidr/pdf-processor/data/demo.mv.db [2.3.232/7]" [50000-232] + at org.h2.message.DbException.getJdbcSQLException(DbException.java:566) + at org.h2.message.DbException.getJdbcSQLException(DbException.java:489) + ... 60 more +Caused by: org.h2.mvstore.MVStoreException: The file is locked: C:/Users/elidr/pdf-processor/data/demo.mv.db [2.3.232/7] + at org.h2.mvstore.DataUtils.newMVStoreException(DataUtils.java:996) + at org.h2.mvstore.SingleFileStore.lockFileChannel(SingleFileStore.java:143) + at org.h2.mvstore.SingleFileStore.open(SingleFileStore.java:117) + at org.h2.mvstore.SingleFileStore.open(SingleFileStore.java:81) + at org.h2.mvstore.MVStore.<init>(MVStore.java:286) + ... 54 more +2025-04-29 11:42:45.852115+02:00 database: flush +org.h2.message.DbException: Všeobecná chyba: "org.h2.mvstore.MVStoreException: The file is locked: C:/Users/elidr/pdf-processor/data/demo.mv.db [2.3.232/7]" +General error: "org.h2.mvstore.MVStoreException: The file is locked: C:/Users/elidr/pdf-processor/data/demo.mv.db [2.3.232/7]" [50000-232] + at org.h2.message.DbException.get(DbException.java:212) + at org.h2.message.DbException.convert(DbException.java:407) + at org.h2.mvstore.db.Store.lambda$new$0(Store.java:122) + at org.h2.mvstore.MVStore.handleException(MVStore.java:1546) + at org.h2.mvstore.MVStore.panic(MVStore.java:371) + at org.h2.mvstore.MVStore.<init>(MVStore.java:291) + at org.h2.mvstore.MVStore$Builder.open(MVStore.java:2035) + at org.h2.mvstore.db.Store.<init>(Store.java:133) + at org.h2.engine.Database.<init>(Database.java:326) + at org.h2.engine.Engine.openSession(Engine.java:92) + at org.h2.engine.Engine.openSession(Engine.java:222) + at org.h2.engine.Engine.createSession(Engine.java:201) + at org.h2.engine.SessionRemote.connectEmbeddedOrServer(SessionRemote.java:344) + at org.h2.jdbc.JdbcConnection.<init>(JdbcConnection.java:124) + at org.h2.Driver.connect(Driver.java:59) + at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:137) + at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:360) + at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:202) + at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:461) + at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:550) + at com.zaxxer.hikari.pool.HikariPool.<init>(HikariPool.java:98) + at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:111) + at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:126) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:467) + at org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl.getIsolatedConnection(DdlTransactionIsolatorNonJtaImpl.java:46) + at org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl.getIsolatedConnection(DdlTransactionIsolatorNonJtaImpl.java:39) + at org.hibernate.tool.schema.internal.exec.ImprovedExtractionContextImpl.getJdbcConnection(ImprovedExtractionContextImpl.java:63) + at org.hibernate.tool.schema.extract.spi.ExtractionContext.getQueryResults(ExtractionContext.java:43) + at org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl.extractMetadata(SequenceInformationExtractorLegacyImpl.java:39) + at org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl.initializeSequences(DatabaseInformationImpl.java:66) + at org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl.<init>(DatabaseInformationImpl.java:60) + at org.hibernate.tool.schema.internal.Helper.buildDatabaseInformation(Helper.java:185) + at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.doMigration(AbstractSchemaMigrator.java:93) + at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction(SchemaManagementToolCoordinator.java:280) + at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.lambda$process$5(SchemaManagementToolCoordinator.java:144) + at java.base/java.util.HashMap.forEach(HashMap.java:1430) + at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process(SchemaManagementToolCoordinator.java:141) + at org.hibernate.boot.internal.SessionFactoryObserverForSchemaExport.sessionFactoryCreated(SessionFactoryObserverForSchemaExport.java:37) + at org.hibernate.internal.SessionFactoryObserverChain.sessionFactoryCreated(SessionFactoryObserverChain.java:35) + at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:324) + at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:463) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1506) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:66) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:390) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:419) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:400) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:366) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1849) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1798) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:601) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:523) + at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:336) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:288) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:334) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:204) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:970) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:627) + at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:752) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:439) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:318) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:1361) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:1350) + at com.dre0059.articleprocessor.ArticleProcessorApplication.main(ArticleProcessorApplication.java:10) +Caused by: org.h2.jdbc.JdbcSQLNonTransientException: Všeobecná chyba: "org.h2.mvstore.MVStoreException: The file is locked: C:/Users/elidr/pdf-processor/data/demo.mv.db [2.3.232/7]" +General error: "org.h2.mvstore.MVStoreException: The file is locked: C:/Users/elidr/pdf-processor/data/demo.mv.db [2.3.232/7]" [50000-232] + at org.h2.message.DbException.getJdbcSQLException(DbException.java:566) + at org.h2.message.DbException.getJdbcSQLException(DbException.java:489) + ... 64 more +Caused by: org.h2.mvstore.MVStoreException: The file is locked: C:/Users/elidr/pdf-processor/data/demo.mv.db [2.3.232/7] + at org.h2.mvstore.DataUtils.newMVStoreException(DataUtils.java:996) + at org.h2.mvstore.SingleFileStore.lockFileChannel(SingleFileStore.java:143) + at org.h2.mvstore.SingleFileStore.open(SingleFileStore.java:117) + at org.h2.mvstore.SingleFileStore.open(SingleFileStore.java:81) + at org.h2.mvstore.MVStore.<init>(MVStore.java:286) + ... 58 more diff --git a/src/main/java/com/dre0059/articleprocessor/controller/DocumentController.java b/src/main/java/com/dre0059/articleprocessor/controller/DocumentController.java index 4fef59b5eb7f750ca1b0e1f804f8fdb3cbe8b99a..379bc5b700ad5623b114b9ce55a9eb212e9b7494 100644 --- a/src/main/java/com/dre0059/articleprocessor/controller/DocumentController.java +++ b/src/main/java/com/dre0059/articleprocessor/controller/DocumentController.java @@ -2,7 +2,9 @@ package com.dre0059.articleprocessor.controller; import com.dre0059.articleprocessor.dto.DocumentDto; import com.dre0059.articleprocessor.dto.SimpleDocumentDto; +import com.dre0059.articleprocessor.model.Category; import com.dre0059.articleprocessor.model.Dokument; +import com.dre0059.articleprocessor.repository.CategoryRepository; import com.dre0059.articleprocessor.repository.DocumentRepository; import com.dre0059.articleprocessor.service.DocumentService; @@ -23,6 +25,9 @@ public class DocumentController { private final DocumentService documentService; + @Autowired + private CategoryRepository categoryRepository; + @Autowired private DocumentRepository dokumentRepository; @@ -53,23 +58,36 @@ public class DocumentController { var references = documentService.getReferencedDocumentsById(id); Dokument document = dokumentRepository.findById(id).get(); + if (documentService.getDocumentById(id) == null) { throw new IllegalArgumentException("Document with ID " + id + " not found."); } if(!document.getStatus().equals("Referenced")) - model.addAttribute("category", document.getCategory().getName()); + model.addAttribute("category", document.getCategory().getName()); model.addAttribute("author", document.authorsToString()); model.addAttribute("year", document.getYear()); model.addAttribute("doi", document.getDoi()); model.addAttribute("link", document.getTarget()); model.addAttribute("tags", document.tagsToString()); model.addAttribute("notes", document.getNotes()); + model.addAttribute("status", document.getStatus()); model.addAttribute("documentId", id); model.addAttribute("references", references); model.addAttribute("docTitle", documentService.getDocumentById(id).getTitle()); + // add category + if (document.getCategory() != null) { + model.addAttribute("category", document.getCategory().getName()); + model.addAttribute("currentCategoryId", document.getCategory().getId()); + } else { + model.addAttribute("category", "No category assigned"); + model.addAttribute("currentCategoryId", null); // Ak nie je kategĂłria, nastavĂme na null + } + + model.addAttribute("categories", categoryRepository.findAll()); + return "view-pdf"; } @@ -104,4 +122,35 @@ public class DocumentController { return ResponseEntity.ok(response); } + + @PostMapping("/api/documents/{documentId}/setCategory") + @ResponseBody + public ResponseEntity<Map<String, Object>> setCategory(@PathVariable Long documentId, @RequestBody Map<String, String> payload) { + Dokument document = dokumentRepository.findById(documentId) + .orElseThrow(() -> new IllegalArgumentException("Document not found")); + + String categoryName = payload.get("categoryName"); + + // Skontrolujeme, ÄŤi kategĂłria existuje + Category category = categoryRepository.findByName(categoryName); + if (category == null) { + // Ak kategĂłria neexistuje, mĂ´Ĺľeme buÄŹ priradiĹĄ default hodnotu, alebo poslaĹĄ error + return ResponseEntity.badRequest().body(Map.of("error", "Category with name '" + categoryName + "' not found")); + } + + document.setCategory(category); + dokumentRepository.save(document); + + Map<String, Object> response = new HashMap<>(); + response.put("success", true); + + return ResponseEntity.ok(response); + } + @GetMapping("/about") + public String aboutProject() { + return "about-project"; // názov HTML sĂşboru bez prĂpony + } + + + } diff --git a/src/main/java/com/dre0059/articleprocessor/controller/StatisticsController.java b/src/main/java/com/dre0059/articleprocessor/controller/StatisticsController.java index 8a8348b0787987466eedf61554ed28b26eabfd2a..380f0c447cc7d50a8fa8a98c5723097351c4f3ae 100644 --- a/src/main/java/com/dre0059/articleprocessor/controller/StatisticsController.java +++ b/src/main/java/com/dre0059/articleprocessor/controller/StatisticsController.java @@ -74,4 +74,48 @@ public class StatisticsController { return "statistics"; } + + // sofistikovanĂ˝ graf + @GetMapping("/statistics/citation-timeline") + public String citationTimeline(@RequestParam("documentId") Long documentId, Model model) { + Optional<Dokument> mainDocOpt = documentRepository.findById(documentId); + + if (mainDocOpt.isEmpty()) { + return "redirect:/statistics"; + } + + Dokument mainDoc = mainDocOpt.get(); + + List<Map<String, Object>> references = mainDoc.getReferences().stream() + .map(ref -> { + Dokument cited = ref.getToDocument(); + Map<String, Object> refMap = new HashMap<>(); + refMap.put("title", cited.getTitle()); + refMap.put("year", cited.getPublicationYear()); + refMap.put("category", cited.getCategory() != null ? cited.getCategory().getName() : "Unknown"); + return refMap; + }) + .filter(refMap -> refMap.get("year") != null) + .collect(Collectors.toList()); + + // 🆕 ZĂskame všetky existujĂşce kategĂłrie pre Y-os grafu + List<Dokument> allDocuments = documentRepository.findAll(); + List<String> categories = allDocuments.stream() + .map(Dokument::getCategory) + .filter(Objects::nonNull) + .map(c -> c.getName()) + .distinct() + .sorted() + .collect(Collectors.toList()); + + model.addAttribute("mainArticleTitle", mainDoc.getTitle()); + model.addAttribute("mainArticleYear", mainDoc.getPublicationYear()); + model.addAttribute("mainArticleCategory", mainDoc.getCategory() != null ? mainDoc.getCategory().getName() : "Unknown"); + model.addAttribute("references", references); + model.addAttribute("categories", categories); // âś… DĂ´leĹľitĂ© pre JS + + return "citation-timeline"; + } + + } diff --git a/src/main/java/com/dre0059/articleprocessor/repository/CategoryRepository.java b/src/main/java/com/dre0059/articleprocessor/repository/CategoryRepository.java index 823a39dae8a0bc6a415a8ce643a2066fa9d204e2..23f69955b997ab5ba6cccdb7e5e480bd95bf9478 100644 --- a/src/main/java/com/dre0059/articleprocessor/repository/CategoryRepository.java +++ b/src/main/java/com/dre0059/articleprocessor/repository/CategoryRepository.java @@ -6,5 +6,5 @@ import org.springframework.stereotype.Repository; @Repository public interface CategoryRepository extends JpaRepository<Category, String> { - + Category findByName(String name); } diff --git a/src/main/java/com/dre0059/articleprocessor/service/HeaderService.java b/src/main/java/com/dre0059/articleprocessor/service/HeaderService.java index bcdfa43a67c4482abbc655d9de94b11bbb28315b..d621352759ed8ff49e20a509ee1243231d27f725 100644 --- a/src/main/java/com/dre0059/articleprocessor/service/HeaderService.java +++ b/src/main/java/com/dre0059/articleprocessor/service/HeaderService.java @@ -84,16 +84,6 @@ public class HeaderService { System.out.println("Author list before checking duplicity: " + authorList); System.out.println("Author last names before checking duplicity: " + authorLastNames); - - // check duplicity of the document - /*if(documentRepository.existsByTitleAndAuthorsIn(title, authorLastNames)){ - System.out.println("Document with this title and authors already exist"); - - return null; - }*/ - - //Dokument dok = new Dokument(title, year, doi, publisher, "PDF"); - List<Author> savedAuthors = authorRepository.saveAll(authorList); Dokument dokument = documentRepository.findByTitleAndAuthorsIn(title, authorLastNames) diff --git a/src/main/resources/static/assets/logo_FEI_en.png b/src/main/resources/static/assets/logo_FEI_en.png new file mode 100644 index 0000000000000000000000000000000000000000..06d62423addb44af461bbaf0a5aeb84a07b2809d Binary files /dev/null and b/src/main/resources/static/assets/logo_FEI_en.png differ diff --git a/src/main/resources/templates/about-project.html b/src/main/resources/templates/about-project.html new file mode 100644 index 0000000000000000000000000000000000000000..db4482d5979643ac9943b8a8a3a3f9931b44c839 --- /dev/null +++ b/src/main/resources/templates/about-project.html @@ -0,0 +1,123 @@ +<!DOCTYPE html> +<html lang="en" xmlns:th="http://www.thymeleaf.org"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>About Project</title> + + <link rel="icon" type="image/x-icon" href="/assets/favicon.ico" /> + <link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.5.0/font/bootstrap-icons.css" rel="stylesheet" /> + <link href="https://fonts.googleapis.com/css?family=Lato:300,400,700,300italic,400italic,700italic" rel="stylesheet" /> + <link rel="stylesheet" th:href="@{/styles.css}" /> + + <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> + + <style> + .navbar-nav .nav-link { + font-size: 1.2rem; + margin-right: 20px; + color: rgb(51, 102, 255); + } + + .navbar-nav .nav-link:hover { + color: #00134d; + } + + .navbar-nav .nav-link.active { + color: rgb(51, 102, 255) !important; + } + + .navbar-nav .nav-link.active:hover { + color: #00134d !important; + } + + .about-container { + max-width: 800px; + margin: 60px auto; + padding: 20px; + font-size: 1.2rem; + line-height: 1.8; + color: #333; + } + + h2.about-heading { + text-align: center; + margin-bottom: 30px; + font-size: 2rem; + font-weight: bold; + } + </style> +</head> + +<body> + +<!-- navbar --> +<nav class="navbar navbar-expand-lg navbar-light bg-light static-top"> + <div class="container"> + <a class="navbar-brand" href="/upload">Article Processor</a> + <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" + aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation"> + <span class="navbar-toggler-icon"></span> + </button> + <div class="collapse navbar-collapse justify-content-end" id="navbarNav"> + <ul class="navbar-nav"> + <li class="nav-item"> + <a class="nav-link" href="/upload">Upload</a> + </li> + <li class="nav-item"> + <a class="nav-link" href="/view">View all</a> + </li> + <li class="nav-item"> + <a class="nav-link" href="/statistics">Statistics</a> + </li> + <li class="nav-item"> + <a class="nav-link active" href="/about">About project</a> + </li> + </ul> + </div> + </div> +</nav> + +<header class="masthead"> + <div class="container position-relative"> + <div class="row justify-content-center"> + <div class="col-xl-8"> + <div class="text-center text-white"> + <h1 class="mb-4">About the project</h1> + </div> + </div> + </div> + </div> +</header> + +<!-- About Project Content --> +<div class="about-container"> + + <p> + <h2 class="about-heading">About the Project</h2> + This web application was developed as part of a bachelor's thesis with the goal of creating a simple and interactive + tool for processing scientific PDF documents. + </p> + <p> + The whole project was created at <strong>VĹ B Technical University of Ostrava</strong>. + </p> + <p> + It utilizes the open-source GROBID system to extract metadata such as + authors, titles, abstracts, and references. Users can upload PDF files, and the application automatically analyzes them + and stores the structured results in a database. + </p> + <p> + The application follows a clean three-layer architecture (MVC) and is built using Spring Boot and Java. Extracted data + is processed and displayed in a clear format, providing users with a user-friendly way to manage and browse academic content. + </p> + <img src="/assets/logo_FEI_en.png" alt="fei" style="max-width: 100%; margin-bottom: 20px;" /> +</div> + +<!-- Footer --> +<footer class="footer bg-light mt-5"> + <div class="container text-center"> + <p class="text-muted small">© Eliška Kozáčiková 2025. All Rights Reserved.</p> + </div> +</footer> +</body> +</html> diff --git a/src/main/resources/templates/citation-timeline.html b/src/main/resources/templates/citation-timeline.html new file mode 100644 index 0000000000000000000000000000000000000000..4baff6bf9cbe63e6de67927e8db1858621b3023e --- /dev/null +++ b/src/main/resources/templates/citation-timeline.html @@ -0,0 +1,238 @@ + <!DOCTYPE html> + <html xmlns:th="http://www.thymeleaf.org"> + <head> + <meta charset="UTF-8"> + <title>Document Statistics</title> + <script src="https://cdn.plot.ly/plotly-1.58.5.min.js"></script> + + <link rel="icon" type="image/x-icon" href="/assets/favicon.ico" /> + <link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.5.0/font/bootstrap-icons.css" rel="stylesheet" /> + <link href="https://fonts.googleapis.com/css?family=Lato:300,400,700,300italic,400italic,700italic" rel="stylesheet" /> + + <link rel="stylesheet" th:href="@{/styles.css}" /> + + <style> + .navbar-nav .nav-link { + font-size: 1.2rem; + margin-right: 20px; + color: rgb(51, 102, 255); + } + + .navbar-nav .nav-link:hover { + color: #00134d; + } + + .navbar-nav .nav-link.active { + color: rgb(51, 102, 255) !important; + } + + .navbar-nav .nav-link.active:hover { + color: #00134d !important; + } + + h2 { + color: #ffffff; + text-align: center; + margin-top: 30px; + } + + .chart-container { + display: flex; + justify-content: space-between; + flex-wrap: wrap; + gap: 20px; + margin-top: 30px; + } + + .chart-box { + flex: 1; + min-width: 400px; + height: 500px; + background-color: #6780a3; + border-radius: 12px; + padding: 15px; + overflow: hidden; + } + + .chart-box:hover { + transform: scale(1.01); + transition: transform 0.2s ease-in-out; + } + + .chart-box .js-plotly-plot { + position: absolute; + top: 0; + left: 0; + width: 100% !important; /* natiahne graf presne na šĂrku boxu */ + height: 100% !important; /* natiahne graf presne na výšku boxu */ + } + </style> + </head> + + <body> + <!-- Navbar --> + <nav class="navbar navbar-expand-lg navbar-light bg-light static-top"> + <div class="container"> + <a class="navbar-brand" href="/upload">Article Processor</a> + <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" + aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation"> + <span class="navbar-toggler-icon"></span> + </button> + <div class="collapse navbar-collapse justify-content-end" id="navbarNav"> + <ul class="navbar-nav"> + <li class="nav-item"> + <a class="nav-link" href="/upload">Upload</a> + </li> + <li class="nav-item"> + <a class="nav-link" href="/view">View all</a> + </li> + <li class="nav-item"> + <a class="nav-link" href="/statistics">Statistics</a> + </li> + <li class="nav-item"> + <a class="nav-link" href="/upload">About project</a> + </li> + </ul> + </div> + </div> + </nav> + + <!-- Page Content --> + <header class="masthead"> + <div class="container position-relative"> + <div class="row justify-content-center"> + <div class="col-xl-8"> + <div class="text-center text-white"> + <h1 class="mb-4">📊 Graph of references</h1> + </div> + </div> + </div> + </div> + </header> + + <!-- sofistikovanĂ˝ graf --> + <div class="container mt-5"> + <div class="chart-container"> + <div id="referenceTimelineChart" class="chart-box"></div> + </div> + </div> + + + <script th:inline="javascript"> + // Predpokladám, Ĺľe tieto Ăşdaje sĂş dostupnĂ© z backendu cez Thymeleaf. + const mainArticle = { + title: [[${mainArticleTitle}]], + year: [[${mainArticleYear}]], + category: [[${mainArticleCategory}]] + }; + + const references = [[${references}]]; + const categories = [[${categories}]]; // KategĂłrie, ktorĂ© dostaneme z databázy + console.log("Categories received:", categories); + + // Predstavujeme kategĂłrie ako mapu (indexovanie podÄľa názvu kategĂłrie) + const categoryIndex = categories.reduce((acc, category, index) => { + acc[category] = index + 1; // ZaÄŤneme od 1, aby sme vyhli hodnotám 0 + return acc; + }, {}); + + // Funkcia pre zĂskanie Y-ovej hodnoty podÄľa kategĂłrie + function getCategoryY(categoryName) { + return categoryIndex[categoryName] || 0; // Ak kategĂłria nie je v zozname, pouĹľijeme hodnotu 0 + } + + // PripravĂme hlavnĂ˝ dokument + const mainTrace = { + x: [mainArticle.year], + y: [getCategoryY(mainArticle.category)], + mode: 'markers', + type: 'scatter', + name: mainArticle.title, + hoverinfo: 'text', + marker: { + size: 14, + color: 'gold' + }, + // Po kliknutĂ na marker sa zobrazĂ informácia + customdata: [{ title: mainArticle.title, year: mainArticle.year, category: mainArticle.category }] + }; + + // PripravĂme referencie + const referenceTrace = { + x: references.map(r => r.year), + y: references.map(r => getCategoryY(r.category)), + mode: 'markers', + type: 'scatter', + name: 'References', + text: references.map(r => r.title), + hoverinfo: 'text', + marker: { + size: 10, + color: '#66ccff' + }, + customdata: references.map(r => ({ title: r.title, year: r.year, category: r.category })) + }; + + // Spojovacie ÄŤiary medzi referenciami a hlavnĂ˝m dokumentom + const connectionLines = references.map(ref => ({ + type: 'line', + x0: ref.year, + y0: getCategoryY(ref.category), + x1: mainArticle.year, + y1: getCategoryY(mainArticle.category), + line: { + color: '#ffffff', + width: 1.5, + dash: 'dot' + } + })); + + // Konfigurácia grafu + const layout = { + title: 'Chronological graph of categories & references', + paper_bgcolor: '#6780a3', + plot_bgcolor: '#6780a3', + font: { color: '#ffffff' }, + margin: { + l: 180, // zväčšà ľavĂ˝ okraj pre ÄŤitateÄľnosĹĄ názvov kategĂłriĂ + t: 150 // zväčšà hornĂ˝ okraj pre pridanie odsadenia pod nadpis + }, + xaxis: { + title: 'Publication Year', + showgrid: true, + zeroline: false, + range: [1950, 2030] + }, + yaxis: { + title: 'Category', + tickmode: 'array', + tickvals: categories.map((_, index) => index + 1), + ticktext: categories, + showgrid: true, + automargin: true, + tickfont: { + size: 14 + } + }, + shapes: connectionLines, + legend: { + orientation: 'h', // horizontálne usporiadanie legendy + yanchor: 'bottom', // pozĂcia legendy + y: 1.1, // trošku nad grafom + xanchor: 'center', + x: 0.5 + } + }; + + // Vytvorenie grafu bez pridania event listenera na kliknutie + Plotly.newPlot('referenceTimelineChart', [mainTrace, referenceTrace], layout, { responsive: true }); + </script> + + + <footer class="footer bg-light mt-5"> + <div class="container text-center"> + <p class="text-muted small">© Eliška Kozáčiková 2025. All Rights Reserved.</p> + </div> + </footer> + </body> + </html> diff --git a/src/main/resources/templates/view-all.html b/src/main/resources/templates/view-all.html index cc516be2496d06ee6686a919eeb27626ca482422..5150e3bf4f91005ef69fa3f616319e9ba3c0232f 100644 --- a/src/main/resources/templates/view-all.html +++ b/src/main/resources/templates/view-all.html @@ -56,7 +56,7 @@ <a class="nav-link" href="/statistics">Statistics</a> </li> <li class="nav-item"> - <a class="nav-link" href="/upload">About project</a> + <a class="nav-link" href="/about">About project</a> </li> </ul> </div> diff --git a/src/main/resources/templates/view-pdf.html b/src/main/resources/templates/view-pdf.html index 6779709b396089f8e6d3cea68ae34ff5ec1c369e..a4a7f7e06104a0f5d0c55e4c75d252cbd6c8210f 100644 --- a/src/main/resources/templates/view-pdf.html +++ b/src/main/resources/templates/view-pdf.html @@ -12,7 +12,7 @@ <style> .navbar { - background-color : #dfe2ec !important; + background-color: #dfe2ec !important; } .navbar-nav .nav-link { font-size: 1.2rem; @@ -29,8 +29,15 @@ color: #00134d !important; } - .italic{ - font-style:italic; + .italic { + font-style: italic; + } + + /* Center the graph */ + #graphContainer { + display: flex; + justify-content: center; + margin-top: 20px; } </style> @@ -68,6 +75,11 @@ <div class="container mt-4"> <h2><span class="italic" th:text="${docTitle}"></span></h2> + <!-- Button to show graph of references --> + <div class="mt-4" id="graphContainer" style="display: none;"> + <button id="showGraphButton" class="btn btn-secondary">SHOW GRAPH OF REFERENCES</button> + </div> + <div class="row mt-4"> <div class="col-md-6"> <h3>Information about Document</h3> @@ -80,7 +92,6 @@ <p><strong>Tags:</strong> <span class="italic" th:text="${tags}"></span></p> <p><strong>Notes:</strong> <span class="italic" th:text="${notes}"></span></p> - <!-- Form for adding notes and delete document buttons --> <div class="d-flex justify-content-between mt-4"> <!-- Add Notes Button --> @@ -102,6 +113,16 @@ </div> </div> + <!-- choose Category --> + <form id="categoryForm" class="mt-3"> + <label for="categorySelect" class="form-label"><strong>Category:</strong></label> + <select id="categorySelect" class="form-select" name="category"> + <option th:each="category : ${categories}" th:value="${category.name}" th:text="${category.name}" + th:selected="${category.name == category}"></option> + </select> + <button type="button" class="btn btn-primary mt-2" id="saveCategoryButton">Save Category</button> + </form> + <h3 class="mt-4">References:</h3> <div class="table-responsive"> <table class="table table-bordered table-striped"> @@ -140,14 +161,48 @@ <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script> -<script> +<script th:inline="javascript"> + // Check if the status is "PDF" and show the button + const status = [[${status}]]; // Get the status from the backend + + if (status === "PDF") { + document.getElementById("graphContainer").style.display = "block"; + } + + // Save the category to the document + document.getElementById("saveCategoryButton").addEventListener("click", function () { + const selectedCategoryName = document.getElementById("categorySelect").value; + let documentId = [[${documentId}]]; + + // Send the selected category to the backend to update the document + fetch(`/api/documents/${documentId}/setCategory`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ categoryName: selectedCategoryName }) // Send the selected category ID + }) + .then(response => { + if (response.ok) { + alert("Category updated successfully!"); + } else { + alert("Error updating category."); + } + }) + .catch(error => { + console.error("Error:", error); + alert("An error occurred."); + }); + }); + + // Handle notes addition document.getElementById("addNotesButton").addEventListener("click", function() { document.getElementById("notesForm").style.display = "block"; }); document.getElementById("saveNotesButton").addEventListener("click", function() { const notes = document.getElementById("notesTextarea").value; - const documentId = [[${documentId}]]; + const documentId = [[${documentId}]]; // Insert the documentId here (e.g., from Thymeleaf) fetch(`/api/documents/${documentId}/setNotes`, { method: 'POST', @@ -169,6 +224,16 @@ alert("Error saving notes!"); }); }); + + // "SHOW GRAPH OF REFERENCES" button + document.getElementById("showGraphButton").addEventListener("click", function() { + // Get the document ID from Thymeleaf model + const documentId = [[${documentId}]]; + + // Redirect to the citation timeline page + window.location.href = `/statistics/citation-timeline?documentId=${documentId}`; + }); </script> + </body> </html>