mirror of
https://github.com/hwanny1128/HGZero.git
synced 2025-12-06 13:46:24 +00:00
add new meeting
This commit is contained in:
commit
5eeb251551
@ -1,9 +0,0 @@
|
|||||||
{
|
|
||||||
"permissions": {
|
|
||||||
"allow": [
|
|
||||||
"Bash(git commit:*)"
|
|
||||||
],
|
|
||||||
"deny": [],
|
|
||||||
"ask": []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,2 +1,2 @@
|
|||||||
#Thu Oct 23 16:04:00 KST 2025
|
#Thu Oct 23 16:03:15 KST 2025
|
||||||
gradle.version=8.14
|
gradle.version=8.14
|
||||||
|
|||||||
@ -12,4 +12,7 @@ dependencies {
|
|||||||
// Feign (for external API calls)
|
// Feign (for external API calls)
|
||||||
implementation "io.github.openfeign:feign-jackson:${feignJacksonVersion}"
|
implementation "io.github.openfeign:feign-jackson:${feignJacksonVersion}"
|
||||||
implementation "io.github.openfeign:feign-okhttp:${feignJacksonVersion}"
|
implementation "io.github.openfeign:feign-okhttp:${feignJacksonVersion}"
|
||||||
|
|
||||||
|
// H2 Database for local development
|
||||||
|
runtimeOnly 'com.h2database:h2'
|
||||||
}
|
}
|
||||||
|
|||||||
298
ai/logs/ai.log
Normal file
298
ai/logs/ai.log
Normal file
@ -0,0 +1,298 @@
|
|||||||
|
2025-10-23 16:24:30 [main] INFO com.unicorn.hgzero.ai.AiApplication - Starting AiApplication using Java 23.0.2 with PID 33322 (/Users/jominseo/HGZero/ai/build/classes/java/main started by jominseo in /Users/jominseo/HGZero/ai)
|
||||||
|
2025-10-23 16:24:30 [main] DEBUG com.unicorn.hgzero.ai.AiApplication - Running with Spring Boot v3.3.0, Spring v6.1.8
|
||||||
|
2025-10-23 16:24:30 [main] INFO com.unicorn.hgzero.ai.AiApplication - The following 1 profile is active: "local"
|
||||||
|
2025-10-23 16:24:31 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode
|
||||||
|
2025-10-23 16:24:31 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Bootstrapping Spring Data JPA repositories in DEFAULT mode.
|
||||||
|
2025-10-23 16:24:31 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 4 ms. Found 0 JPA repository interfaces.
|
||||||
|
2025-10-23 16:24:31 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode
|
||||||
|
2025-10-23 16:24:31 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Bootstrapping Spring Data Redis repositories in DEFAULT mode.
|
||||||
|
2025-10-23 16:24:31 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 0 ms. Found 0 Redis repository interfaces.
|
||||||
|
2025-10-23 16:24:31 [main] INFO o.s.b.w.e.tomcat.TomcatWebServer - Tomcat initialized with port 8084 (http)
|
||||||
|
2025-10-23 16:24:31 [main] INFO o.a.catalina.core.StandardService - Starting service [Tomcat]
|
||||||
|
2025-10-23 16:24:31 [main] INFO o.a.catalina.core.StandardEngine - Starting Servlet engine: [Apache Tomcat/10.1.24]
|
||||||
|
2025-10-23 16:24:31 [main] INFO o.a.c.c.C.[Tomcat].[localhost].[/] - Initializing Spring embedded WebApplicationContext
|
||||||
|
2025-10-23 16:24:31 [main] INFO o.s.b.w.s.c.ServletWebServerApplicationContext - Root WebApplicationContext: initialization completed in 694 ms
|
||||||
|
2025-10-23 16:24:31 [main] INFO o.h.jpa.internal.util.LogHelper - HHH000204: Processing PersistenceUnitInfo [name: default]
|
||||||
|
2025-10-23 16:24:31 [main] INFO org.hibernate.Version - HHH000412: Hibernate ORM core version 6.5.2.Final
|
||||||
|
2025-10-23 16:24:31 [main] INFO o.h.c.i.RegionFactoryInitiator - HHH000026: Second-level cache disabled
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration boolean -> org.hibernate.type.BasicTypeReference@5c5f12e
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration boolean -> org.hibernate.type.BasicTypeReference@5c5f12e
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Boolean -> org.hibernate.type.BasicTypeReference@5c5f12e
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration numeric_boolean -> org.hibernate.type.BasicTypeReference@23f8036d
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration org.hibernate.type.NumericBooleanConverter -> org.hibernate.type.BasicTypeReference@23f8036d
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration true_false -> org.hibernate.type.BasicTypeReference@68f69ca3
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration org.hibernate.type.TrueFalseConverter -> org.hibernate.type.BasicTypeReference@68f69ca3
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration yes_no -> org.hibernate.type.BasicTypeReference@1e3566e
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration org.hibernate.type.YesNoConverter -> org.hibernate.type.BasicTypeReference@1e3566e
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration byte -> org.hibernate.type.BasicTypeReference@2b058bfd
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration byte -> org.hibernate.type.BasicTypeReference@2b058bfd
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Byte -> org.hibernate.type.BasicTypeReference@2b058bfd
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration binary -> org.hibernate.type.BasicTypeReference@4805069b
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration byte[] -> org.hibernate.type.BasicTypeReference@4805069b
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration [B -> org.hibernate.type.BasicTypeReference@4805069b
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration binary_wrapper -> org.hibernate.type.BasicTypeReference@14ca88bc
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration wrapper-binary -> org.hibernate.type.BasicTypeReference@14ca88bc
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration image -> org.hibernate.type.BasicTypeReference@f01fc6d
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration blob -> org.hibernate.type.BasicTypeReference@85cd413
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.sql.Blob -> org.hibernate.type.BasicTypeReference@85cd413
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration materialized_blob -> org.hibernate.type.BasicTypeReference@688d2a5d
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration materialized_blob_wrapper -> org.hibernate.type.BasicTypeReference@2842c098
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration short -> org.hibernate.type.BasicTypeReference@2820b369
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration short -> org.hibernate.type.BasicTypeReference@2820b369
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Short -> org.hibernate.type.BasicTypeReference@2820b369
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration integer -> org.hibernate.type.BasicTypeReference@46b21632
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration int -> org.hibernate.type.BasicTypeReference@46b21632
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Integer -> org.hibernate.type.BasicTypeReference@46b21632
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration long -> org.hibernate.type.BasicTypeReference@476c137b
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration long -> org.hibernate.type.BasicTypeReference@476c137b
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Long -> org.hibernate.type.BasicTypeReference@476c137b
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration float -> org.hibernate.type.BasicTypeReference@79144d0e
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration float -> org.hibernate.type.BasicTypeReference@79144d0e
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Float -> org.hibernate.type.BasicTypeReference@79144d0e
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration double -> org.hibernate.type.BasicTypeReference@540212be
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration double -> org.hibernate.type.BasicTypeReference@540212be
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Double -> org.hibernate.type.BasicTypeReference@540212be
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration big_integer -> org.hibernate.type.BasicTypeReference@2579d8a
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.math.BigInteger -> org.hibernate.type.BasicTypeReference@2579d8a
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration big_decimal -> org.hibernate.type.BasicTypeReference@2507a170
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.math.BigDecimal -> org.hibernate.type.BasicTypeReference@2507a170
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration character -> org.hibernate.type.BasicTypeReference@7e20f4e3
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration char -> org.hibernate.type.BasicTypeReference@7e20f4e3
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Character -> org.hibernate.type.BasicTypeReference@7e20f4e3
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration character_nchar -> org.hibernate.type.BasicTypeReference@3af39e7b
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration string -> org.hibernate.type.BasicTypeReference@4f6ff62
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.String -> org.hibernate.type.BasicTypeReference@4f6ff62
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration nstring -> org.hibernate.type.BasicTypeReference@1c62d2ad
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration characters -> org.hibernate.type.BasicTypeReference@651caa2e
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration char[] -> org.hibernate.type.BasicTypeReference@651caa2e
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration [C -> org.hibernate.type.BasicTypeReference@651caa2e
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration wrapper-characters -> org.hibernate.type.BasicTypeReference@433ae0b0
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration text -> org.hibernate.type.BasicTypeReference@70840a5a
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration ntext -> org.hibernate.type.BasicTypeReference@7af9595d
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration clob -> org.hibernate.type.BasicTypeReference@7a34c1f6
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.sql.Clob -> org.hibernate.type.BasicTypeReference@7a34c1f6
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration nclob -> org.hibernate.type.BasicTypeReference@6e9f8160
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.sql.NClob -> org.hibernate.type.BasicTypeReference@6e9f8160
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration materialized_clob -> org.hibernate.type.BasicTypeReference@3e998033
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration materialized_clob_char_array -> org.hibernate.type.BasicTypeReference@e1a150c
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration materialized_clob_character_array -> org.hibernate.type.BasicTypeReference@527d5e48
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration materialized_nclob -> org.hibernate.type.BasicTypeReference@407b41e6
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration materialized_nclob_character_array -> org.hibernate.type.BasicTypeReference@3291d9c2
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration materialized_nclob_char_array -> org.hibernate.type.BasicTypeReference@6cfd08e9
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration Duration -> org.hibernate.type.BasicTypeReference@54ca9420
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.Duration -> org.hibernate.type.BasicTypeReference@54ca9420
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration LocalDateTime -> org.hibernate.type.BasicTypeReference@4ea48b2e
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.LocalDateTime -> org.hibernate.type.BasicTypeReference@4ea48b2e
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration LocalDate -> org.hibernate.type.BasicTypeReference@72c704f1
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.LocalDate -> org.hibernate.type.BasicTypeReference@72c704f1
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration LocalTime -> org.hibernate.type.BasicTypeReference@76f9e000
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.LocalTime -> org.hibernate.type.BasicTypeReference@76f9e000
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration OffsetDateTime -> org.hibernate.type.BasicTypeReference@7612116b
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.OffsetDateTime -> org.hibernate.type.BasicTypeReference@7612116b
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration OffsetDateTimeWithTimezone -> org.hibernate.type.BasicTypeReference@1c05097c
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration OffsetDateTimeWithoutTimezone -> org.hibernate.type.BasicTypeReference@562f6681
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration OffsetTime -> org.hibernate.type.BasicTypeReference@6f6f65a4
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.OffsetTime -> org.hibernate.type.BasicTypeReference@6f6f65a4
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration OffsetTimeUtc -> org.hibernate.type.BasicTypeReference@990b86b
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration OffsetTimeWithTimezone -> org.hibernate.type.BasicTypeReference@3dea1ecc
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration OffsetTimeWithoutTimezone -> org.hibernate.type.BasicTypeReference@105c6c9e
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration ZonedDateTime -> org.hibernate.type.BasicTypeReference@40a7974
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.ZonedDateTime -> org.hibernate.type.BasicTypeReference@40a7974
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration ZonedDateTimeWithTimezone -> org.hibernate.type.BasicTypeReference@8d5da7e
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration ZonedDateTimeWithoutTimezone -> org.hibernate.type.BasicTypeReference@65a4b9d6
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration date -> org.hibernate.type.BasicTypeReference@16ef1160
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.sql.Date -> org.hibernate.type.BasicTypeReference@16ef1160
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration time -> org.hibernate.type.BasicTypeReference@41f90b10
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.sql.Time -> org.hibernate.type.BasicTypeReference@41f90b10
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration timestamp -> org.hibernate.type.BasicTypeReference@67593f7b
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.sql.Timestamp -> org.hibernate.type.BasicTypeReference@67593f7b
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.util.Date -> org.hibernate.type.BasicTypeReference@67593f7b
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration calendar -> org.hibernate.type.BasicTypeReference@2773504f
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.util.Calendar -> org.hibernate.type.BasicTypeReference@2773504f
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.util.GregorianCalendar -> org.hibernate.type.BasicTypeReference@2773504f
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration calendar_date -> org.hibernate.type.BasicTypeReference@497921d0
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration calendar_time -> org.hibernate.type.BasicTypeReference@40d10264
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration instant -> org.hibernate.type.BasicTypeReference@6edd4fe2
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.Instant -> org.hibernate.type.BasicTypeReference@6edd4fe2
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration uuid -> org.hibernate.type.BasicTypeReference@53918b5e
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.util.UUID -> org.hibernate.type.BasicTypeReference@53918b5e
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration pg-uuid -> org.hibernate.type.BasicTypeReference@53918b5e
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration uuid-binary -> org.hibernate.type.BasicTypeReference@5366575d
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration uuid-char -> org.hibernate.type.BasicTypeReference@1b6cad77
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration class -> org.hibernate.type.BasicTypeReference@1fca53a7
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Class -> org.hibernate.type.BasicTypeReference@1fca53a7
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration currency -> org.hibernate.type.BasicTypeReference@40dee07b
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration Currency -> org.hibernate.type.BasicTypeReference@40dee07b
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.util.Currency -> org.hibernate.type.BasicTypeReference@40dee07b
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration locale -> org.hibernate.type.BasicTypeReference@21e39b82
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.util.Locale -> org.hibernate.type.BasicTypeReference@21e39b82
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration serializable -> org.hibernate.type.BasicTypeReference@5f9a8ddc
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.io.Serializable -> org.hibernate.type.BasicTypeReference@5f9a8ddc
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration timezone -> org.hibernate.type.BasicTypeReference@1280bae3
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.util.TimeZone -> org.hibernate.type.BasicTypeReference@1280bae3
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration ZoneOffset -> org.hibernate.type.BasicTypeReference@256a5df0
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.ZoneOffset -> org.hibernate.type.BasicTypeReference@256a5df0
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration url -> org.hibernate.type.BasicTypeReference@1868ed54
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.net.URL -> org.hibernate.type.BasicTypeReference@1868ed54
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration vector -> org.hibernate.type.BasicTypeReference@131777e8
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration row_version -> org.hibernate.type.BasicTypeReference@45790cb
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration object -> org.hibernate.type.JavaObjectType@2bc2e022
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Object -> org.hibernate.type.JavaObjectType@2bc2e022
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration null -> org.hibernate.type.NullType@1ff81b0d
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration imm_date -> org.hibernate.type.BasicTypeReference@1c610f
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration imm_time -> org.hibernate.type.BasicTypeReference@5abc5854
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration imm_timestamp -> org.hibernate.type.BasicTypeReference@5c3007d
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration imm_calendar -> org.hibernate.type.BasicTypeReference@66b40dd3
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration imm_calendar_date -> org.hibernate.type.BasicTypeReference@7296fe0b
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration imm_calendar_time -> org.hibernate.type.BasicTypeReference@4a5066f5
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration imm_binary -> org.hibernate.type.BasicTypeReference@578d472a
|
||||||
|
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration imm_serializable -> org.hibernate.type.BasicTypeReference@1191029d
|
||||||
|
2025-10-23 16:24:31 [main] INFO o.s.o.j.p.SpringPersistenceUnitInfo - No LoadTimeWeaver setup: ignoring JPA class transformer
|
||||||
|
2025-10-23 16:24:31 [main] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Starting...
|
||||||
|
2025-10-23 16:24:32 [main] WARN o.h.e.j.e.i.JdbcEnvironmentInitiator - HHH000342: Could not obtain connection to query metadata
|
||||||
|
java.lang.NullPointerException: Cannot invoke "org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(java.sql.SQLException, String)" because the return value of "org.hibernate.resource.transaction.backend.jdbc.internal.JdbcIsolationDelegate.sqlExceptionHelper()" is null
|
||||||
|
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcIsolationDelegate.delegateWork(JdbcIsolationDelegate.java:116)
|
||||||
|
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.getJdbcEnvironmentUsingJdbcMetadata(JdbcEnvironmentInitiator.java:290)
|
||||||
|
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:123)
|
||||||
|
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:77)
|
||||||
|
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:221)
|
||||||
|
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.<init>(InFlightMetadataCollectorImpl.java:189)
|
||||||
|
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:75)
|
||||||
|
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:390)
|
||||||
|
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409)
|
||||||
|
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396)
|
||||||
|
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:366)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1835)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1784)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:600)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337)
|
||||||
|
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:205)
|
||||||
|
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:952)
|
||||||
|
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:624)
|
||||||
|
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146)
|
||||||
|
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754)
|
||||||
|
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456)
|
||||||
|
at org.springframework.boot.SpringApplication.run(SpringApplication.java:335)
|
||||||
|
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1363)
|
||||||
|
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1352)
|
||||||
|
at com.unicorn.hgzero.ai.AiApplication.main(AiApplication.java:20)
|
||||||
|
2025-10-23 16:24:32 [main] ERROR o.s.o.j.LocalContainerEntityManagerFactoryBean - Failed to initialize JPA EntityManagerFactory: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] due to: Unable to determine Dialect without JDBC metadata (please set 'jakarta.persistence.jdbc.url' for common cases or 'hibernate.dialect' when a custom Dialect implementation must be provided)
|
||||||
|
2025-10-23 16:24:32 [main] WARN o.s.b.w.s.c.AnnotationConfigServletWebServerApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] due to: Unable to determine Dialect without JDBC metadata (please set 'jakarta.persistence.jdbc.url' for common cases or 'hibernate.dialect' when a custom Dialect implementation must be provided)
|
||||||
|
2025-10-23 16:24:32 [main] INFO o.a.catalina.core.StandardService - Stopping service [Tomcat]
|
||||||
|
2025-10-23 16:24:32 [main] INFO o.s.b.a.l.ConditionEvaluationReportLogger -
|
||||||
|
|
||||||
|
Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
|
||||||
|
2025-10-23 16:24:32 [main] ERROR o.s.boot.SpringApplication - Application run failed
|
||||||
|
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] due to: Unable to determine Dialect without JDBC metadata (please set 'jakarta.persistence.jdbc.url' for common cases or 'hibernate.dialect' when a custom Dialect implementation must be provided)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1788)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:600)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337)
|
||||||
|
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:205)
|
||||||
|
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:952)
|
||||||
|
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:624)
|
||||||
|
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146)
|
||||||
|
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754)
|
||||||
|
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456)
|
||||||
|
at org.springframework.boot.SpringApplication.run(SpringApplication.java:335)
|
||||||
|
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1363)
|
||||||
|
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1352)
|
||||||
|
at com.unicorn.hgzero.ai.AiApplication.main(AiApplication.java:20)
|
||||||
|
Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] due to: Unable to determine Dialect without JDBC metadata (please set 'jakarta.persistence.jdbc.url' for common cases or 'hibernate.dialect' when a custom Dialect implementation must be provided)
|
||||||
|
at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:276)
|
||||||
|
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:221)
|
||||||
|
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.<init>(InFlightMetadataCollectorImpl.java:189)
|
||||||
|
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:75)
|
||||||
|
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:390)
|
||||||
|
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409)
|
||||||
|
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396)
|
||||||
|
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:366)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1835)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1784)
|
||||||
|
... 15 common frames omitted
|
||||||
|
Caused by: org.hibernate.HibernateException: Unable to determine Dialect without JDBC metadata (please set 'jakarta.persistence.jdbc.url' for common cases or 'hibernate.dialect' when a custom Dialect implementation must be provided)
|
||||||
|
at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.determineDialect(DialectFactoryImpl.java:191)
|
||||||
|
at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.buildDialect(DialectFactoryImpl.java:87)
|
||||||
|
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.getJdbcEnvironmentWithDefaults(JdbcEnvironmentInitiator.java:152)
|
||||||
|
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.getJdbcEnvironmentUsingJdbcMetadata(JdbcEnvironmentInitiator.java:362)
|
||||||
|
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:123)
|
||||||
|
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:77)
|
||||||
|
at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:130)
|
||||||
|
at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:263)
|
||||||
|
... 30 common frames omitted
|
||||||
|
2025-10-23 16:25:55 [main] INFO com.unicorn.hgzero.ai.AiApplication - Starting AiApplication using Java 23.0.2 with PID 33935 (/Users/jominseo/HGZero/ai/build/classes/java/main started by jominseo in /Users/jominseo/HGZero/ai)
|
||||||
|
2025-10-23 16:25:55 [main] DEBUG com.unicorn.hgzero.ai.AiApplication - Running with Spring Boot v3.3.0, Spring v6.1.8
|
||||||
|
2025-10-23 16:25:55 [main] INFO com.unicorn.hgzero.ai.AiApplication - The following 1 profile is active: "local"
|
||||||
|
2025-10-23 16:25:55 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode
|
||||||
|
2025-10-23 16:25:55 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Bootstrapping Spring Data JPA repositories in DEFAULT mode.
|
||||||
|
2025-10-23 16:25:56 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 3 ms. Found 0 JPA repository interfaces.
|
||||||
|
2025-10-23 16:25:56 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode
|
||||||
|
2025-10-23 16:25:56 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Bootstrapping Spring Data Redis repositories in DEFAULT mode.
|
||||||
|
2025-10-23 16:25:56 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 0 ms. Found 0 Redis repository interfaces.
|
||||||
|
2025-10-23 16:25:56 [main] INFO o.s.b.w.e.tomcat.TomcatWebServer - Tomcat initialized with port 8084 (http)
|
||||||
|
2025-10-23 16:25:56 [main] INFO o.a.catalina.core.StandardService - Starting service [Tomcat]
|
||||||
|
2025-10-23 16:25:56 [main] INFO o.a.catalina.core.StandardEngine - Starting Servlet engine: [Apache Tomcat/10.1.24]
|
||||||
|
2025-10-23 16:25:56 [main] INFO o.a.c.c.C.[Tomcat].[localhost].[/] - Initializing Spring embedded WebApplicationContext
|
||||||
|
2025-10-23 16:25:56 [main] INFO o.s.b.w.s.c.ServletWebServerApplicationContext - Root WebApplicationContext: initialization completed in 608 ms
|
||||||
|
2025-10-23 16:25:56 [main] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Starting...
|
||||||
|
2025-10-23 16:25:56 [main] INFO com.zaxxer.hikari.pool.HikariPool - HikariPool-1 - Added connection conn0: url=jdbc:h2:mem:testdb user=SA
|
||||||
|
2025-10-23 16:25:56 [main] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Start completed.
|
||||||
|
2025-10-23 16:25:56 [main] INFO o.s.b.a.h.H2ConsoleAutoConfiguration - H2 console available at '/h2-console'. Database available at 'jdbc:h2:mem:testdb'
|
||||||
|
2025-10-23 16:25:56 [main] INFO o.h.jpa.internal.util.LogHelper - HHH000204: Processing PersistenceUnitInfo [name: default]
|
||||||
|
2025-10-23 16:25:56 [main] INFO org.hibernate.Version - HHH000412: Hibernate ORM core version 6.5.2.Final
|
||||||
|
2025-10-23 16:25:56 [main] INFO o.h.c.i.RegionFactoryInitiator - HHH000026: Second-level cache disabled
|
||||||
|
2025-10-23 16:25:56 [main] INFO o.s.o.j.p.SpringPersistenceUnitInfo - No LoadTimeWeaver setup: ignoring JPA class transformer
|
||||||
|
2025-10-23 16:25:56 [main] WARN org.hibernate.orm.deprecation - HHH90000025: H2Dialect does not need to be specified explicitly using 'hibernate.dialect' (remove the property setting and it will be selected by default)
|
||||||
|
2025-10-23 16:25:56 [main] INFO o.h.e.t.j.p.i.JtaPlatformInitiator - HHH000489: No JTA platform available (set 'hibernate.transaction.jta.platform' to enable JTA platform integration)
|
||||||
|
2025-10-23 16:25:56 [main] INFO o.s.o.j.LocalContainerEntityManagerFactoryBean - Initialized JPA EntityManagerFactory for persistence unit 'default'
|
||||||
|
2025-10-23 16:25:56 [main] WARN o.s.b.a.o.j.JpaBaseConfiguration$JpaWebConfiguration - spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
|
||||||
|
2025-10-23 16:25:56 [main] ERROR i.n.r.d.DnsServerAddressStreamProviders - Unable to load io.netty.resolver.dns.macos.MacOSDnsServerAddressStreamProvider, fallback to system defaults. This may result in incorrect DNS resolutions on MacOS. Check whether you have a dependency on 'io.netty:netty-resolver-dns-native-macos'. Use DEBUG level to see the full stack: java.lang.UnsatisfiedLinkError: failed to load the required native library
|
||||||
|
2025-10-23 16:25:57 [main] WARN o.s.b.a.s.s.UserDetailsServiceAutoConfiguration -
|
||||||
|
|
||||||
|
Using generated security password: 1665e64f-a0ac-49dc-806e-846f88237e7c
|
||||||
|
|
||||||
|
This generated password is for development use only. Your security configuration must be updated before running your application in production.
|
||||||
|
|
||||||
|
2025-10-23 16:25:57 [main] INFO o.s.s.c.a.a.c.InitializeUserDetailsBeanManagerConfigurer$InitializeUserDetailsManagerConfigurer - Global AuthenticationManager configured with UserDetailsService bean with name inMemoryUserDetailsManager
|
||||||
|
2025-10-23 16:25:57 [main] INFO o.s.b.a.e.web.EndpointLinksResolver - Exposing 3 endpoints beneath base path '/actuator'
|
||||||
|
2025-10-23 16:25:57 [main] INFO o.s.s.web.DefaultSecurityFilterChain - Will secure any request with [org.springframework.security.web.session.DisableEncodeUrlFilter@54ad9ff9, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@3b6b9981, org.springframework.security.web.context.SecurityContextHolderFilter@3ce34b92, org.springframework.security.web.header.HeaderWriterFilter@4a89722e, org.springframework.web.filter.CorsFilter@2eb6e166, org.springframework.security.web.csrf.CsrfFilter@2c3762c7, org.springframework.security.web.authentication.logout.LogoutFilter@751e7d99, org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@331b0bfd, org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter@20894afb, org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter@43b1fdb7, org.springframework.security.web.authentication.www.BasicAuthenticationFilter@61d4e070, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@f511a8e, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@1b52f723, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@7bdbf06f, org.springframework.security.web.access.ExceptionTranslationFilter@64c009b8, org.springframework.security.web.access.intercept.AuthorizationFilter@7dfbdcfe]
|
||||||
|
2025-10-23 16:25:57 [main] INFO o.s.b.w.e.tomcat.TomcatWebServer - Tomcat started on port 8084 (http) with context path '/'
|
||||||
|
2025-10-23 16:25:57 [main] INFO com.unicorn.hgzero.ai.AiApplication - Started AiApplication in 1.733 seconds (process running for 1.843)
|
||||||
|
2025-10-23 16:26:47 [http-nio-8084-exec-1] INFO o.a.c.c.C.[Tomcat].[localhost].[/] - Initializing Spring DispatcherServlet 'dispatcherServlet'
|
||||||
|
2025-10-23 16:26:47 [http-nio-8084-exec-1] INFO o.s.web.servlet.DispatcherServlet - Initializing Servlet 'dispatcherServlet'
|
||||||
|
2025-10-23 16:26:47 [http-nio-8084-exec-1] INFO o.s.web.servlet.DispatcherServlet - Completed initialization in 0 ms
|
||||||
|
2025-10-23 16:26:47 [http-nio-8084-exec-1] DEBUG o.s.security.web.FilterChainProxy - Securing GET /
|
||||||
|
2025-10-23 16:26:47 [http-nio-8084-exec-1] DEBUG o.s.s.w.a.AnonymousAuthenticationFilter - Set SecurityContextHolder to anonymous SecurityContext
|
||||||
|
2025-10-23 16:26:47 [http-nio-8084-exec-1] DEBUG o.s.s.w.s.HttpSessionRequestCache - Saved request http://localhost:8084/?continue to session
|
||||||
|
2025-10-23 16:26:47 [http-nio-8084-exec-1] DEBUG o.s.s.w.a.DelegatingAuthenticationEntryPoint - Trying to match using And [Not [RequestHeaderRequestMatcher [expectedHeaderName=X-Requested-With, expectedHeaderValue=XMLHttpRequest]], MediaTypeRequestMatcher [contentNegotiationStrategy=org.springframework.web.accept.ContentNegotiationManager@32da6cef, matchingMediaTypes=[application/xhtml+xml, image/*, text/html, text/plain], useEquals=false, ignoredMediaTypes=[*/*]]]
|
||||||
|
2025-10-23 16:26:47 [http-nio-8084-exec-1] DEBUG o.s.s.w.a.DelegatingAuthenticationEntryPoint - Match found! Executing org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint@104972a0
|
||||||
|
2025-10-23 16:26:47 [http-nio-8084-exec-1] DEBUG o.s.s.web.DefaultRedirectStrategy - Redirecting to http://localhost:8084/login
|
||||||
|
2025-10-23 16:26:47 [http-nio-8084-exec-2] DEBUG o.s.security.web.FilterChainProxy - Securing GET /login
|
||||||
|
2025-10-23 16:26:47 [http-nio-8084-exec-3] DEBUG o.s.security.web.FilterChainProxy - Securing GET /favicon.ico
|
||||||
|
2025-10-23 16:26:47 [http-nio-8084-exec-3] DEBUG o.s.s.w.a.AnonymousAuthenticationFilter - Set SecurityContextHolder to anonymous SecurityContext
|
||||||
|
2025-10-23 16:26:47 [http-nio-8084-exec-3] DEBUG o.s.s.w.a.DelegatingAuthenticationEntryPoint - Trying to match using And [Not [RequestHeaderRequestMatcher [expectedHeaderName=X-Requested-With, expectedHeaderValue=XMLHttpRequest]], MediaTypeRequestMatcher [contentNegotiationStrategy=org.springframework.web.accept.ContentNegotiationManager@32da6cef, matchingMediaTypes=[application/xhtml+xml, image/*, text/html, text/plain], useEquals=false, ignoredMediaTypes=[*/*]]]
|
||||||
|
2025-10-23 16:26:47 [http-nio-8084-exec-3] DEBUG o.s.s.w.a.DelegatingAuthenticationEntryPoint - Match found! Executing org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint@104972a0
|
||||||
|
2025-10-23 16:26:47 [http-nio-8084-exec-3] DEBUG o.s.s.web.DefaultRedirectStrategy - Redirecting to http://localhost:8084/login
|
||||||
|
2025-10-23 16:26:47 [http-nio-8084-exec-4] DEBUG o.s.security.web.FilterChainProxy - Securing GET /login
|
||||||
|
2025-10-23 16:27:13 [SpringApplicationShutdownHook] INFO o.s.o.j.LocalContainerEntityManagerFactoryBean - Closing JPA EntityManagerFactory for persistence unit 'default'
|
||||||
|
2025-10-23 16:27:13 [SpringApplicationShutdownHook] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Shutdown initiated...
|
||||||
|
2025-10-23 16:27:13 [SpringApplicationShutdownHook] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Shutdown completed.
|
||||||
@ -6,7 +6,7 @@ spring:
|
|||||||
datasource:
|
datasource:
|
||||||
url: jdbc:${DB_KIND:postgresql}://${DB_HOST:20.249.153.213}:${DB_PORT:5432}/${DB_NAME:aidb}
|
url: jdbc:${DB_KIND:postgresql}://${DB_HOST:20.249.153.213}:${DB_PORT:5432}/${DB_NAME:aidb}
|
||||||
username: ${DB_USERNAME:hgzerouser}
|
username: ${DB_USERNAME:hgzerouser}
|
||||||
password: ${DB_PASSWORD:}
|
password: ${DB_PASSWORD:Hi5Jessica!}
|
||||||
driver-class-name: org.postgresql.Driver
|
driver-class-name: org.postgresql.Driver
|
||||||
hikari:
|
hikari:
|
||||||
maximum-pool-size: 20
|
maximum-pool-size: 20
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@ -88,27 +88,57 @@
|
|||||||
margin-bottom: var(--space-md);
|
margin-bottom: var(--space-md);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 통계 카드 - 모바일에서 컴팩트하게 */
|
/* 통계 카드 - 정보 표시용 (인터랙션 없음) */
|
||||||
.stat-box {
|
.stat-box {
|
||||||
min-height: 80px;
|
min-height: 80px;
|
||||||
padding: var(--space-sm);
|
padding: var(--space-sm);
|
||||||
|
background: var(--gray-100); /* 플랫한 배경 */
|
||||||
|
border: 1px solid var(--gray-200); /* 얇은 경계선 */
|
||||||
|
border-radius: var(--radius-md); /* 부드러운 모서리 */
|
||||||
|
box-shadow: none; /* 그림자 제거 */
|
||||||
|
transition: none; /* 호버 효과 제거 */
|
||||||
}
|
}
|
||||||
|
|
||||||
.stat-box.highlight {
|
/* 상태별 컬러 코딩 */
|
||||||
background: var(--primary-light);
|
.stat-box.stat-incomplete {
|
||||||
border: 2px solid var(--primary);
|
background: linear-gradient(135deg, #E3F2FD 0%, #BBDEFB 100%); /* 차분한 블루 그라데이션 */
|
||||||
|
border-color: #90CAF9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-box.stat-urgent {
|
||||||
|
background: linear-gradient(135deg, #FFF3E0 0%, #FFE0B2 100%); /* 주의 오렌지 그라데이션 */
|
||||||
|
border-color: #FFB74D;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-box.stat-overdue {
|
||||||
|
background: linear-gradient(135deg, #FFEBEE 0%, #FFCDD2 100%); /* 긴급 레드 그라데이션 */
|
||||||
|
border-color: #EF5350;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stat-number {
|
.stat-number {
|
||||||
font-size: var(--font-h2);
|
font-size: var(--font-h1); /* 더 크게 강조 */
|
||||||
font-weight: var(--font-weight-bold);
|
font-weight: var(--font-weight-bold);
|
||||||
color: var(--primary);
|
line-height: 1.2;
|
||||||
margin-bottom: 2px;
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-box.stat-incomplete .stat-number {
|
||||||
|
color: #1976D2; /* 진한 블루 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-box.stat-urgent .stat-number {
|
||||||
|
color: #F57C00; /* 진한 오렌지 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-box.stat-overdue .stat-number {
|
||||||
|
color: #D32F2F; /* 진한 레드 */
|
||||||
}
|
}
|
||||||
|
|
||||||
.stat-text {
|
.stat-text {
|
||||||
font-size: var(--font-caption);
|
font-size: var(--font-caption);
|
||||||
color: var(--gray-700);
|
color: var(--gray-600); /* 더 연하게 */
|
||||||
|
font-weight: var(--font-weight-regular); /* 보통 굵기 */
|
||||||
|
opacity: 0.85;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 원형 진행 바 - 모바일에서 축소 */
|
/* 원형 진행 바 - 모바일에서 축소 */
|
||||||
@ -131,17 +161,17 @@
|
|||||||
/* 데스크톱에서 통계 카드 크기 복원 */
|
/* 데스크톱에서 통계 카드 크기 복원 */
|
||||||
@media (min-width: 768px) {
|
@media (min-width: 768px) {
|
||||||
.stat-box {
|
.stat-box {
|
||||||
min-height: 100px;
|
min-height: 110px;
|
||||||
padding: var(--space-md);
|
padding: var(--space-lg);
|
||||||
}
|
}
|
||||||
|
|
||||||
.stat-number {
|
.stat-number {
|
||||||
font-size: var(--font-h1);
|
font-size: 2.5rem; /* 더 큰 숫자 */
|
||||||
margin-bottom: var(--space-xs);
|
margin-bottom: var(--space-xs);
|
||||||
}
|
}
|
||||||
|
|
||||||
.stat-text {
|
.stat-text {
|
||||||
font-size: var(--font-small);
|
font-size: var(--font-body);
|
||||||
}
|
}
|
||||||
|
|
||||||
.circular-progress {
|
.circular-progress {
|
||||||
@ -227,23 +257,26 @@
|
|||||||
border-color: var(--primary);
|
border-color: var(--primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Todo 카드 */
|
/* Todo 카드 - 컴팩트 디자인 */
|
||||||
.todo-card {
|
.todo-card {
|
||||||
position: relative;
|
position: relative;
|
||||||
background: var(--white);
|
background: var(--white);
|
||||||
padding: var(--space-md);
|
padding: var(--space-md);
|
||||||
border-radius: var(--radius-lg);
|
border-radius: var(--radius-lg);
|
||||||
box-shadow: var(--shadow-md);
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
|
||||||
margin-bottom: var(--space-md);
|
margin-bottom: var(--space-sm);
|
||||||
transition: all var(--transition-normal);
|
transition: all var(--transition-normal);
|
||||||
|
border: 1px solid var(--gray-200);
|
||||||
}
|
}
|
||||||
|
|
||||||
.todo-card:hover {
|
.todo-card:hover {
|
||||||
box-shadow: var(--shadow-lg);
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.12);
|
||||||
|
border-color: var(--primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.todo-card.completed {
|
.todo-card.completed {
|
||||||
opacity: 0.6;
|
opacity: 0.5;
|
||||||
|
background: var(--gray-50);
|
||||||
}
|
}
|
||||||
|
|
||||||
.todo-card.completed .todo-title {
|
.todo-card.completed .todo-title {
|
||||||
@ -251,20 +284,22 @@
|
|||||||
color: var(--gray-500);
|
color: var(--gray-500);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 레이아웃: 체크박스 + 콘텐츠 */
|
||||||
.todo-top {
|
.todo-top {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: var(--space-md);
|
gap: var(--space-md);
|
||||||
margin-bottom: var(--space-md);
|
align-items: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
.todo-checkbox-wrapper {
|
.todo-checkbox-wrapper {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
padding-top: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.todo-checkbox {
|
.todo-checkbox {
|
||||||
width: 24px;
|
width: 24px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
border: 2px solid var(--gray-300);
|
border: 2px solid var(--gray-400);
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all var(--transition-fast);
|
transition: all var(--transition-fast);
|
||||||
@ -277,41 +312,41 @@
|
|||||||
|
|
||||||
.todo-content-wrapper {
|
.todo-content-wrapper {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
min-width: 0; /* 텍스트 오버플로우 방지 */
|
||||||
}
|
}
|
||||||
|
|
||||||
.todo-title {
|
/* 배지 영역 */
|
||||||
font-size: var(--font-body);
|
|
||||||
font-weight: var(--font-weight-medium);
|
|
||||||
color: var(--gray-900);
|
|
||||||
margin-bottom: var(--space-sm);
|
|
||||||
}
|
|
||||||
|
|
||||||
.todo-badges {
|
.todo-badges {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: var(--space-sm);
|
gap: var(--space-xs);
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
margin-bottom: var(--space-sm);
|
margin-bottom: var(--space-xs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Todo 제목 */
|
||||||
|
.todo-title {
|
||||||
|
font-size: var(--font-body);
|
||||||
|
font-weight: var(--font-weight-regular);
|
||||||
|
color: var(--gray-900);
|
||||||
|
margin-bottom: var(--space-xs);
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 하단 메타 정보 */
|
||||||
.todo-meta-row {
|
.todo-meta-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: var(--space-md);
|
gap: var(--space-sm);
|
||||||
font-size: var(--font-small);
|
font-size: var(--font-small);
|
||||||
color: var(--gray-500);
|
color: var(--gray-500);
|
||||||
}
|
flex-wrap: wrap;
|
||||||
|
|
||||||
.todo-assignee {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: var(--space-sm);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.todo-meeting-link {
|
.todo-meeting-link {
|
||||||
display: flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: var(--space-xs);
|
gap: 4px;
|
||||||
color: var(--primary);
|
color: #4CAF50; /* 연한 초록색 */
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
font-size: var(--font-small);
|
font-size: var(--font-small);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@ -319,19 +354,47 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.todo-meeting-link:hover {
|
.todo-meeting-link:hover {
|
||||||
color: var(--primary-dark);
|
color: #388E3C;
|
||||||
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
.todo-progress-section {
|
/* 담당자 정보 숨김 (간결한 디자인) */
|
||||||
margin-top: var(--space-md);
|
.todo-assignee {
|
||||||
padding-top: var(--space-md);
|
display: none;
|
||||||
border-top: 1px solid var(--gray-300);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.todo-progress-label {
|
/* 액션 버튼 영역 */
|
||||||
font-size: var(--font-small);
|
.todo-actions {
|
||||||
color: var(--gray-700);
|
margin-top: var(--space-xs);
|
||||||
margin-bottom: var(--space-sm);
|
}
|
||||||
|
|
||||||
|
/* 아이콘 버튼 */
|
||||||
|
.icon-btn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
padding: 0;
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
border-radius: var(--radius-md);
|
||||||
|
color: var(--gray-600);
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all var(--transition-fast);
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-btn:hover {
|
||||||
|
background: var(--gray-100);
|
||||||
|
color: var(--primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-btn:active {
|
||||||
|
background: var(--gray-200);
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-btn .material-icons {
|
||||||
|
font-size: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 빈 상태 */
|
/* 빈 상태 */
|
||||||
@ -463,44 +526,33 @@
|
|||||||
<main class="main-content">
|
<main class="main-content">
|
||||||
<!-- 통계 개요 -->
|
<!-- 통계 개요 -->
|
||||||
<div class="stats-overview">
|
<div class="stats-overview">
|
||||||
<div class="stat-box">
|
<div class="stat-box stat-incomplete">
|
||||||
<div class="stat-number" id="totalTodos">0</div>
|
<div class="stat-number" id="totalTodos">0</div>
|
||||||
<div class="stat-text">전체</div>
|
<div class="stat-text">미완료</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="stat-box highlight">
|
<div class="stat-box stat-urgent">
|
||||||
<div class="circular-progress">
|
<div class="stat-number" id="urgentTodos">0</div>
|
||||||
<svg viewBox="0 0 80 80">
|
|
||||||
<circle class="bg-circle" cx="40" cy="40" r="36"></circle>
|
|
||||||
<circle class="progress-circle" cx="40" cy="40" r="36"
|
|
||||||
stroke-dasharray="226" stroke-dashoffset="226" id="progressCircle"></circle>
|
|
||||||
</svg>
|
|
||||||
<div class="circular-progress-text" id="completionRate">0%</div>
|
|
||||||
</div>
|
|
||||||
<div class="stat-text">완료율</div>
|
|
||||||
</div>
|
|
||||||
<div class="stat-box">
|
|
||||||
<div class="stat-number" id="inProgressTodos">0</div>
|
|
||||||
<div class="stat-text">진행 중</div>
|
|
||||||
</div>
|
|
||||||
<div class="stat-box">
|
|
||||||
<div class="stat-number text-error" id="urgentTodos">0</div>
|
|
||||||
<div class="stat-text">마감 임박</div>
|
<div class="stat-text">마감 임박</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="stat-box stat-overdue">
|
||||||
|
<div class="stat-number" id="overdueTodos">0</div>
|
||||||
|
<div class="stat-text">지연</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 필터 탭 -->
|
<!-- 필터 탭 -->
|
||||||
<div class="filter-tabs">
|
<div class="filter-tabs">
|
||||||
<button class="filter-tab active" data-filter="all" onclick="filterTodos('all')">
|
<button class="filter-tab active" data-filter="all" onclick="filterTodos('all')">
|
||||||
전체
|
전체 (<span id="filterAllCount">0</span>)
|
||||||
</button>
|
</button>
|
||||||
<button class="filter-tab" data-filter="in_progress" onclick="filterTodos('in_progress')">
|
<button class="filter-tab" data-filter="overdue" onclick="filterTodos('overdue')">
|
||||||
진행 중
|
지연 (<span id="filterOverdueCount">0</span>)
|
||||||
</button>
|
|
||||||
<button class="filter-tab" data-filter="completed" onclick="filterTodos('completed')">
|
|
||||||
완료
|
|
||||||
</button>
|
</button>
|
||||||
<button class="filter-tab" data-filter="urgent" onclick="filterTodos('urgent')">
|
<button class="filter-tab" data-filter="urgent" onclick="filterTodos('urgent')">
|
||||||
마감 임박
|
마감 임박 (<span id="filterUrgentCount">0</span>)
|
||||||
|
</button>
|
||||||
|
<button class="filter-tab" data-filter="completed" onclick="filterTodos('completed')">
|
||||||
|
완료 (<span id="filterCompletedCount">0</span>)
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -623,28 +675,27 @@
|
|||||||
|
|
||||||
// 통계 업데이트
|
// 통계 업데이트
|
||||||
function updateStats() {
|
function updateStats() {
|
||||||
const total = allTodos.length;
|
const total = allTodos.filter(t => t.status !== 'completed').length; // 미완료 전체
|
||||||
const completed = allTodos.filter(t => t.status === 'completed').length;
|
const completed = allTodos.filter(t => t.status === 'completed').length;
|
||||||
const inProgress = allTodos.filter(t => t.status === 'in_progress').length;
|
|
||||||
const urgent = allTodos.filter(t => {
|
const urgent = allTodos.filter(t => {
|
||||||
const dday = calculateDday(t.dueDate);
|
const dday = calculateDday(t.dueDate);
|
||||||
return dday >= 0 && dday <= 3 && t.status !== 'completed';
|
return dday >= 0 && dday <= 3 && t.status !== 'completed';
|
||||||
}).length;
|
}).length;
|
||||||
|
const overdue = allTodos.filter(t => {
|
||||||
|
const dday = calculateDday(t.dueDate);
|
||||||
|
return dday < 0 && t.status !== 'completed';
|
||||||
|
}).length;
|
||||||
|
|
||||||
// 카운터 애니메이션
|
// 상단 통계 블록 카운터 애니메이션
|
||||||
animateCounter('totalTodos', total);
|
animateCounter('totalTodos', total);
|
||||||
animateCounter('inProgressTodos', inProgress);
|
|
||||||
animateCounter('urgentTodos', urgent);
|
animateCounter('urgentTodos', urgent);
|
||||||
|
animateCounter('overdueTodos', overdue);
|
||||||
|
|
||||||
// 완료율 원형 진행 바
|
// 필터 탭 개수 업데이트
|
||||||
const completionRate = total > 0 ? Math.round((completed / total) * 100) : 0;
|
$('#filterAllCount').textContent = allTodos.length;
|
||||||
const circumference = 226;
|
$('#filterOverdueCount').textContent = overdue;
|
||||||
const offset = circumference - (completionRate / 100 * circumference);
|
$('#filterUrgentCount').textContent = urgent;
|
||||||
|
$('#filterCompletedCount').textContent = completed;
|
||||||
setTimeout(() => {
|
|
||||||
$('#progressCircle').style.strokeDashoffset = offset;
|
|
||||||
$('#completionRate').textContent = `${completionRate}%`;
|
|
||||||
}, 100);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Todo 리스트 렌더링
|
// Todo 리스트 렌더링
|
||||||
@ -655,8 +706,11 @@
|
|||||||
// 필터 적용
|
// 필터 적용
|
||||||
if (currentFilter === 'completed') {
|
if (currentFilter === 'completed') {
|
||||||
filteredTodos = allTodos.filter(t => t.status === 'completed');
|
filteredTodos = allTodos.filter(t => t.status === 'completed');
|
||||||
} else if (currentFilter === 'in_progress') {
|
} else if (currentFilter === 'overdue') {
|
||||||
filteredTodos = allTodos.filter(t => t.status === 'in_progress');
|
filteredTodos = allTodos.filter(t => {
|
||||||
|
const dday = calculateDday(t.dueDate);
|
||||||
|
return dday < 0 && t.status !== 'completed';
|
||||||
|
});
|
||||||
} else if (currentFilter === 'urgent') {
|
} else if (currentFilter === 'urgent') {
|
||||||
filteredTodos = allTodos.filter(t => {
|
filteredTodos = allTodos.filter(t => {
|
||||||
const dday = calculateDday(t.dueDate);
|
const dday = calculateDday(t.dueDate);
|
||||||
@ -702,7 +756,6 @@
|
|||||||
onchange="toggleTodoComplete('${todo.id}', this.checked)">
|
onchange="toggleTodoComplete('${todo.id}', this.checked)">
|
||||||
</div>
|
</div>
|
||||||
<div class="todo-content-wrapper">
|
<div class="todo-content-wrapper">
|
||||||
<div class="todo-title">${todo.title}</div>
|
|
||||||
<div class="todo-badges">
|
<div class="todo-badges">
|
||||||
${createBadge(statusInfo.badgeText, statusInfo.badgeType)}
|
${createBadge(statusInfo.badgeText, statusInfo.badgeType)}
|
||||||
${createBadge(
|
${createBadge(
|
||||||
@ -711,28 +764,17 @@
|
|||||||
todo.priority
|
todo.priority
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
<div class="todo-title">${todo.title}</div>
|
||||||
<div class="todo-meta-row">
|
<div class="todo-meta-row">
|
||||||
<div class="todo-assignee">
|
|
||||||
${createAvatar(todo.assignee, 'sm')}
|
|
||||||
<span>${todo.assignee.name}</span>
|
|
||||||
</div>
|
|
||||||
<span>•</span>
|
|
||||||
<span>${formatDate(todo.dueDate)}</span>
|
|
||||||
</div>
|
|
||||||
<a class="todo-meeting-link" onclick="goToMeeting('${todo.meetingId}')">
|
<a class="todo-meeting-link" onclick="goToMeeting('${todo.meetingId}')">
|
||||||
🔗 ${todo.meetingTitle}
|
🔗 ${todo.meetingTitle}
|
||||||
</a>
|
</a>
|
||||||
${!isCompleted && todo.progress > 0 ? `
|
<span>${formatDate(todo.dueDate)}</span>
|
||||||
<div class="todo-progress-section">
|
|
||||||
<div class="todo-progress-label">진행률: ${todo.progress}%</div>
|
|
||||||
${createProgressBar(todo.progress)}
|
|
||||||
</div>
|
</div>
|
||||||
` : ''}
|
|
||||||
${!isCompleted ? `
|
${!isCompleted ? `
|
||||||
<div class="todo-actions">
|
<div class="todo-actions">
|
||||||
<button class="btn btn-ghost btn-sm" onclick="editTodo('${todo.id}')">
|
<button class="icon-btn" onclick="editTodo('${todo.id}')" title="편집">
|
||||||
<span class="material-icons" style="font-size: 16px;">edit</span>
|
<span class="material-icons">edit</span>
|
||||||
편집
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
` : ''}
|
` : ''}
|
||||||
@ -760,11 +802,11 @@
|
|||||||
// Todo 완료 토글
|
// Todo 완료 토글
|
||||||
function toggleTodoComplete(todoId, isChecked) {
|
function toggleTodoComplete(todoId, isChecked) {
|
||||||
if (isChecked) {
|
if (isChecked) {
|
||||||
if (confirm('이 Todo를 완료 처리하시겠습니까?')) {
|
// 완료 처리
|
||||||
|
if (confirm('완료 처리하시겠습니까?')) {
|
||||||
const todo = allTodos.find(t => t.id === todoId);
|
const todo = allTodos.find(t => t.id === todoId);
|
||||||
if (todo) {
|
if (todo) {
|
||||||
todo.status = 'completed';
|
todo.status = 'completed';
|
||||||
todo.progress = 100;
|
|
||||||
showToast('Todo가 완료되었습니다', 'success');
|
showToast('Todo가 완료되었습니다', 'success');
|
||||||
updateStats();
|
updateStats();
|
||||||
renderTodoList();
|
renderTodoList();
|
||||||
@ -773,12 +815,18 @@
|
|||||||
event.target.checked = false;
|
event.target.checked = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// 미완료로 되돌리기
|
||||||
|
if (confirm('미완료로 변경하시겠습니까?')) {
|
||||||
const todo = allTodos.find(t => t.id === todoId);
|
const todo = allTodos.find(t => t.id === todoId);
|
||||||
if (todo) {
|
if (todo) {
|
||||||
todo.status = 'in_progress';
|
todo.status = 'incomplete';
|
||||||
|
showToast('미완료로 변경되었습니다', 'info');
|
||||||
updateStats();
|
updateStats();
|
||||||
renderTodoList();
|
renderTodoList();
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
event.target.checked = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -591,8 +591,8 @@
|
|||||||
<!-- 탭 네비게이션 -->
|
<!-- 탭 네비게이션 -->
|
||||||
<nav class="tab-nav">
|
<nav class="tab-nav">
|
||||||
<div class="tabs">
|
<div class="tabs">
|
||||||
<div class="tab active" data-tab="minutes">회의록</div>
|
<div class="tab active" data-tab="dashboard">대시보드</div>
|
||||||
<div class="tab" data-tab="dashboard">대시보드</div>
|
<div class="tab" data-tab="minutes">회의록</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
@ -642,7 +642,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 회의록 탭 -->
|
<!-- 회의록 탭 -->
|
||||||
<div id="minutes-content" class="tab-content active">
|
<div id="minutes-content" class="tab-content">
|
||||||
<!-- 안건 1 -->
|
<!-- 안건 1 -->
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<div class="section-header">
|
<div class="section-header">
|
||||||
@ -826,7 +826,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 대시보드 탭 -->
|
<!-- 대시보드 탭 -->
|
||||||
<div id="dashboard-content" class="tab-content">
|
<div id="dashboard-content" class="tab-content active">
|
||||||
<!-- 핵심내용 -->
|
<!-- 핵심내용 -->
|
||||||
<div class="section dashboard-section">
|
<div class="section dashboard-section">
|
||||||
<div class="section-header">
|
<div class="section-header">
|
||||||
|
|||||||
@ -234,41 +234,32 @@
|
|||||||
color: var(--gray-700);
|
color: var(--gray-700);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 잠금 해제 요청 버튼 */
|
/* 읽기 전용 표시 */
|
||||||
.unlock-request-btn {
|
.readonly-badge {
|
||||||
display: flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 4px;
|
padding: 4px 8px;
|
||||||
padding: 6px 12px;
|
background: var(--gray-100);
|
||||||
background: transparent;
|
border-radius: var(--radius-sm);
|
||||||
border: 1px solid var(--primary);
|
color: var(--gray-600);
|
||||||
border-radius: var(--radius-md);
|
|
||||||
color: var(--primary);
|
|
||||||
font-size: var(--font-caption);
|
font-size: var(--font-caption);
|
||||||
font-weight: var(--font-weight-medium);
|
font-weight: var(--font-weight-medium);
|
||||||
cursor: pointer;
|
margin-left: 8px;
|
||||||
transition: all var(--transition-fast);
|
|
||||||
white-space: nowrap;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.unlock-request-btn img {
|
|
||||||
width: 16px;
|
|
||||||
height: 16px;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.unlock-request-btn:hover {
|
|
||||||
background: var(--primary-light);
|
|
||||||
border-color: var(--primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.unlock-request-btn:active {
|
|
||||||
transform: scale(0.98);
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<!--
|
||||||
|
[진입 경로]
|
||||||
|
10-회의록상세조회.html → 하단 액션 바 "수정" 버튼 클릭
|
||||||
|
|
||||||
|
[권한 제어]
|
||||||
|
- 검증완료 전 (작성중/초안 상태): 모든 참석자가 수정 가능
|
||||||
|
- 검증완료 후: 회의 생성자만 수정 가능 (참석자는 "수정" 버튼 비활성화)
|
||||||
|
- 참석자 관리: 회의 생성자만 추가/삭제 가능
|
||||||
|
- 회의 일시/장소: 읽기 전용 (회의 예약 화면에서만 변경 가능)
|
||||||
|
-->
|
||||||
|
|
||||||
<!-- 헤더 -->
|
<!-- 헤더 -->
|
||||||
<header class="header">
|
<header class="header">
|
||||||
<div class="header-left">
|
<div class="header-left">
|
||||||
@ -287,6 +278,7 @@
|
|||||||
<main class="main-content">
|
<main class="main-content">
|
||||||
<!-- 기본 정보 -->
|
<!-- 기본 정보 -->
|
||||||
<div class="info-card">
|
<div class="info-card">
|
||||||
|
<!-- 회의 제목 (편집 가능) -->
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
class="meeting-title-input"
|
class="meeting-title-input"
|
||||||
@ -294,13 +286,17 @@
|
|||||||
placeholder="회의 제목을 입력하세요"
|
placeholder="회의 제목을 입력하세요"
|
||||||
oninput="markAsUnsaved()"
|
oninput="markAsUnsaved()"
|
||||||
>
|
>
|
||||||
|
<!-- 회의 일시 (읽기 전용 - 회의 예약 화면에서만 변경 가능) -->
|
||||||
<div class="info-row">
|
<div class="info-row">
|
||||||
<span class="info-icon">📅</span>
|
<span class="info-icon">📅</span>
|
||||||
<span>2025년 10월 25일 14:00 (90분)</span>
|
<span>2025년 10월 25일 14:00 (90분)</span>
|
||||||
|
<span class="text-caption text-muted" style="margin-left: 8px;">(읽기 전용)</span>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- 회의 장소 (읽기 전용 - 회의 예약 화면에서만 변경 가능) -->
|
||||||
<div class="info-row">
|
<div class="info-row">
|
||||||
<span class="info-icon">📍</span>
|
<span class="info-icon">📍</span>
|
||||||
<span>본사 2층 대회의실</span>
|
<span>본사 2층 대회의실</span>
|
||||||
|
<span class="text-caption text-muted" style="margin-left: 8px;">(읽기 전용)</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="info-row">
|
<div class="info-row">
|
||||||
<span class="info-icon">✅</span>
|
<span class="info-icon">✅</span>
|
||||||
@ -383,17 +379,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 검증 완료 -->
|
<!-- 검증 완료 (읽기 전용) -->
|
||||||
<div class="verification-lock">
|
<div class="verification-lock">
|
||||||
<input type="checkbox" class="checkbox" id="verify-1" checked disabled>
|
<input type="checkbox" class="checkbox" id="verify-1" checked disabled>
|
||||||
<label for="verify-1" style="flex: 1; min-width: 0;">
|
<label for="verify-1" style="flex: 1; min-width: 0;">
|
||||||
<span class="font-medium">검증 완료</span>
|
<span class="font-medium">검증 완료</span>
|
||||||
<span class="text-caption text-muted"> (잠금됨)</span>
|
<span class="text-caption text-muted"> (잠금됨 · 회의 생성자만 수정 가능)</span>
|
||||||
</label>
|
</label>
|
||||||
<button class="unlock-request-btn" onclick="unlockSection(1)">
|
<span class="readonly-badge">🔒 읽기 전용</span>
|
||||||
<img src="img/padlock.png" alt="">
|
|
||||||
<span>잠금해제요청</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -456,12 +449,9 @@
|
|||||||
<input type="checkbox" class="checkbox" id="verify-2" checked disabled>
|
<input type="checkbox" class="checkbox" id="verify-2" checked disabled>
|
||||||
<label for="verify-2" style="flex: 1; min-width: 0;">
|
<label for="verify-2" style="flex: 1; min-width: 0;">
|
||||||
<span class="font-medium">검증 완료</span>
|
<span class="font-medium">검증 완료</span>
|
||||||
<span class="text-caption text-muted"> (잠금됨)</span>
|
<span class="text-caption text-muted"> (잠금됨 · 회의 생성자만 수정 가능)</span>
|
||||||
</label>
|
</label>
|
||||||
<button class="unlock-request-btn" onclick="unlockSection(2)">
|
<span class="readonly-badge">🔒 읽기 전용</span>
|
||||||
<img src="img/padlock.png" alt="">
|
|
||||||
<span>잠금해제요청</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -519,12 +509,9 @@
|
|||||||
<input type="checkbox" class="checkbox" id="verify-3" checked disabled>
|
<input type="checkbox" class="checkbox" id="verify-3" checked disabled>
|
||||||
<label for="verify-3" style="flex: 1; min-width: 0;">
|
<label for="verify-3" style="flex: 1; min-width: 0;">
|
||||||
<span class="font-medium">검증 완료</span>
|
<span class="font-medium">검증 완료</span>
|
||||||
<span class="text-caption text-muted"> (잠금됨)</span>
|
<span class="text-caption text-muted"> (잠금됨 · 회의 생성자만 수정 가능)</span>
|
||||||
</label>
|
</label>
|
||||||
<button class="unlock-request-btn" onclick="unlockSection(3)">
|
<span class="readonly-badge">🔒 읽기 전용</span>
|
||||||
<img src="img/padlock.png" alt="">
|
|
||||||
<span>잠금해제요청</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
@ -643,11 +630,6 @@
|
|||||||
}, 2000);
|
}, 2000);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 섹션 잠금 해제 요청
|
|
||||||
function unlockSection(sectionId) {
|
|
||||||
showToast('검증 해제 승인을 요청했습니다', 'info');
|
|
||||||
}
|
|
||||||
|
|
||||||
// 관련회의록 제거
|
// 관련회의록 제거
|
||||||
function removeReference(btn) {
|
function removeReference(btn) {
|
||||||
const item = btn.closest('.reference-item');
|
const item = btn.closest('.reference-item');
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
- **작성일**: 2025-10-21
|
- **작성일**: 2025-10-21
|
||||||
- **최종 수정일**: 2025-10-23
|
- **최종 수정일**: 2025-10-23
|
||||||
- **작성자**: 이미준 (서비스 기획자)
|
- **작성자**: 이미준 (서비스 기획자)
|
||||||
- **버전**: 1.4.4
|
- **버전**: 1.4.7
|
||||||
- **설계 철학**: Mobile First Design
|
- **설계 철학**: Mobile First Design
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -1099,106 +1099,116 @@ graph TD
|
|||||||
### 09-Todo관리
|
### 09-Todo관리
|
||||||
|
|
||||||
#### 개요
|
#### 개요
|
||||||
- **목적**: 할당된 Todo 목록 조회 및 진행 상황 관리
|
- **목적**: 나의 Todo(내가 담당자인 Todo) 조회 및 관리
|
||||||
- **관련 유저스토리**: UFR-TODO-010, UFR-TODO-030, **UFR-TODO-040 (Todo 수정)**
|
- **관련 유저스토리**: UFR-TODO-040 (Todo 관리)
|
||||||
- **비즈니스 중요도**: 높음
|
- **비즈니스 중요도**: 높음
|
||||||
- **접근 경로**: 대시보드 → 하단 네비게이션 "Todo" 또는 대시보드 "내 Todo" 카드 → "전체 보기"
|
- **접근 경로**: 대시보드 → 하단 네비게이션 "Todo" 또는 대시보드 "내 Todo" 카드 → "전체 보기"
|
||||||
|
- **대전제**:
|
||||||
|
- Todo의 상태는 완료/미완료만 존재
|
||||||
|
- 09-Todo관리 화면에서는 나의 Todo(내가 담당자인 Todo)만 표시
|
||||||
|
|
||||||
#### 주요 기능
|
#### 주요 기능
|
||||||
1. Todo 목록 표시 (상태별 필터링)
|
1. 나의 Todo 목록 표시 (필터링)
|
||||||
2. **Todo 수정 (UFR-TODO-040)** - 신규 추가
|
2. Todo 완료/미완료 상태 변경
|
||||||
3. Todo 완료 처리
|
3. Todo 편집 (모달)
|
||||||
4. 회의록 원문으로 이동 (양방향 연결)
|
4. 회의록 상세로 이동 (양방향 연결)
|
||||||
5. Todo 진행 상황 통계
|
5. Todo 통계 (전체, 마감임박, 지연)
|
||||||
6. 마감 임박 Todo 알림
|
|
||||||
|
|
||||||
#### UI 구성요소
|
#### UI 구성요소
|
||||||
|
|
||||||
**Mobile (320px~768px)**
|
**Mobile (320px~768px)**
|
||||||
- **헤더**
|
- **헤더**
|
||||||
- "내 Todo" 타이틀
|
- "Todo 관리" 타이틀
|
||||||
- 필터 버튼 (상태별)
|
- 프로필 아이콘 (모바일)
|
||||||
|
|
||||||
- **통계 카드**
|
- **상단 통계 블록** (4개 블록)
|
||||||
- 전체 Todo 개수
|
- **전체**: 미완료 전체 개수
|
||||||
- 완료율 (원형 진행 바)
|
- **마감임박**: 기한 3일 이내 미완료 개수 (강조 스타일)
|
||||||
- 마감 임박 Todo 개수 (배지)
|
- **지연**: 기한이 지난 미완료 개수
|
||||||
|
|
||||||
- **필터 탭**
|
- **필터 탭**
|
||||||
- 전체, 진행 중, 완료, 마감 임박
|
- **전체 (개수)**: 완료/미완료 전체
|
||||||
|
- **지연 (개수)**: 기한이 지난 미완료
|
||||||
|
- **마감임박 (개수)**: 기한 3일 이내 미완료
|
||||||
|
- **완료 (개수)**: 완료된 Todo
|
||||||
|
|
||||||
- **Todo 리스트**
|
- **Todo 리스트 블록**
|
||||||
- 각 Todo 카드:
|
- **정렬**: 미완료 → 완료 순서, 기한일 오래된 순 (복합 정렬)
|
||||||
- 체크박스 (완료 처리)
|
- **각 Todo 카드** (블록 형태):
|
||||||
- Todo 내용
|
- **체크박스** (완료/미완료 토글, 액션 가능 표시)
|
||||||
- 마감일 (색상 코딩: 초록-여유, 노랑-임박, 빨강-지연)
|
- **Todo 제목**
|
||||||
- 우선순위 배지 (높음/보통/낮음)
|
- **상태 뱃지**: D+n(지연) / D-day / D-n / 완료
|
||||||
- 관련 회의록 링크 아이콘
|
- **우선순위 뱃지**: 높음(빨강) / 보통(노랑) / 낮음(회색)
|
||||||
- **"편집" 버튼** (본인 담당 Todo만 표시) - 신규
|
- **기한**
|
||||||
- 스와이프 액션: 수정, 삭제
|
- **회의록 제목 + 링크** (클릭 시 10-회의록상세조회 대시보드 탭으로 이동)
|
||||||
|
- **편집 버튼** (권한 있는 경우에만 노출, 액션 가능 표시)
|
||||||
- **FAB** (Floating Action Button)
|
- **페이징**: 최초 10건 노출, 10건 이상일 경우 하단에 "10개 더보기" 버튼
|
||||||
- "Todo 추가" (수동 추가)
|
|
||||||
|
|
||||||
**Tablet/Desktop (768px+)**
|
**Tablet/Desktop (768px+)**
|
||||||
- 좌측: Todo 리스트
|
- 좌측 사이드바 + 메인 콘텐츠 영역
|
||||||
- 우측: 선택된 Todo 상세 정보
|
- 통계 블록 4개 가로 배치
|
||||||
- Todo 내용
|
- Todo 리스트 그리드 레이아웃 (2열)
|
||||||
- 담당자
|
|
||||||
- 마감일
|
|
||||||
- 우선순위
|
|
||||||
- 관련 회의록 섹션 (임베디드 뷰)
|
|
||||||
- 진행 메모 (추가 가능)
|
|
||||||
|
|
||||||
#### 인터랙션
|
#### 인터랙션
|
||||||
1. **Todo 수정 (UFR-TODO-040)** - 신규 추가
|
1. **Todo 완료/미완료 상태 변경**
|
||||||
- **편집 버튼 클릭**:
|
- **체크박스 클릭**:
|
||||||
- 인라인 편집 모드로 전환 또는 수정 모달 표시
|
- 완료 처리 시: "완료 처리하시겠습니까?" 확인 모달
|
||||||
- **수정 가능 항목** (담당자 권한):
|
- 미완료로 되돌릴 때: "미완료로 변경하시겠습니까?" 확인 모달
|
||||||
- ✏️ Todo 제목 (문구)
|
- 확인 시: 상태 업데이트, 통계 갱신, 리스트 재정렬
|
||||||
- 📅 마감일 (날짜 선택기)
|
- 취소 시: 이전 상태 유지
|
||||||
- 🎯 우선순위 (high/medium/low 드롭다운)
|
|
||||||
- ❌ 담당자 변경 불가 (본인 담당 Todo)
|
2. **Todo 편집 (UFR-TODO-040)**
|
||||||
- **저장 버튼**: 수정 완료
|
- **편집 버튼 클릭** (권한: 담당자 본인 OR 회의 생성자):
|
||||||
- **취소 버튼**: 편집 모드 취소
|
- 편집 모달 표시
|
||||||
- **수정 완료 시**:
|
- **모바일**: 바텀시트 형식
|
||||||
|
- **데스크톱**: 중앙 모달
|
||||||
|
- **수정 가능 항목**:
|
||||||
|
- ✏️ Todo 제목 (input, 필수)
|
||||||
|
- 👤 담당자 (select, 회의록 참석자 중 선택) - **회의 생성자만 변경 가능**
|
||||||
|
- 📅 마감일 (날짜 선택기, 필수)
|
||||||
|
- 🎯 우선순위 (높음/보통/낮음 select, 필수)
|
||||||
|
- **권한 표시**:
|
||||||
|
- 담당자 본인: "본인에게 할당된 Todo만 수정할 수 있습니다. 담당자는 변경할 수 없습니다."
|
||||||
|
- 회의 생성자: "회의 생성자로서 모든 항목을 수정할 수 있습니다. 담당자 변경 시 알림이 전송됩니다."
|
||||||
|
- **저장 버튼 클릭**:
|
||||||
|
- 유효성 검사 (제목, 마감일 필수)
|
||||||
- "Todo가 수정되었습니다" 토스트 메시지
|
- "Todo가 수정되었습니다" 토스트 메시지
|
||||||
- 회의록에 수정 내용 실시간 반영
|
- 회의록에 수정 내용 실시간 반영
|
||||||
- 마감일 변경 시 캘린더 자동 업데이트
|
- 담당자 변경 시: 이전/새 담당자에게 알림 발송
|
||||||
- **권한 제어**:
|
- 마감일 변경 시: 캘린더 자동 업데이트
|
||||||
- 본인에게 할당된 Todo만 편집 버튼 표시
|
- **취소 버튼**: 모달 닫기, 변경 사항 취소
|
||||||
- 다른 사람의 Todo는 조회만 가능 (편집 버튼 숨김)
|
|
||||||
|
|
||||||
2. **Todo 완료 처리**
|
3. **회의록 링크 클릭**
|
||||||
- 체크박스 클릭:
|
- 10-회의록상세조회 화면으로 이동
|
||||||
- 확인 다이얼로그 ("완료 처리하시겠습니까?")
|
- **대시보드 탭이 우선 노출**
|
||||||
- 완료 시: 체크 애니메이션, 회의록에 실시간 반영
|
|
||||||
- 완료 Todo는 리스트 하단으로 이동 (취소선)
|
|
||||||
|
|
||||||
3. **회의록 연결**
|
4. **필터 탭 클릭**
|
||||||
- 회의록 링크 아이콘 클릭:
|
- 선택한 필터 기준으로 Todo 목록 갱신
|
||||||
- 회의록상세조회 화면으로 이동
|
- 활성 탭 강조 표시
|
||||||
- 해당 Todo가 언급된 섹션으로 자동 스크롤
|
|
||||||
- 하이라이트 효과
|
|
||||||
|
|
||||||
4. **필터링**
|
5. **10개 더보기 버튼**
|
||||||
- 필터 탭 클릭: 해당 상태의 Todo만 표시
|
- 클릭 시 하단에 10건씩 추가 로드
|
||||||
- 마감 임박: 3일 이내 마감 Todo
|
- 페이지 새로고침 없이 무한 스크롤 방식
|
||||||
|
|
||||||
5. **수동 추가**
|
#### 디자인 요구사항
|
||||||
- FAB 클릭: Todo 추가 모달
|
- **액션 블록 vs 정보 블록 차별화**:
|
||||||
- 내용, 마감일, 우선순위 입력
|
- 액션 가능 (체크박스, 편집 버튼): 호버 시 배경색 변경, 그림자 효과
|
||||||
|
- 정보 표시 (상태 뱃지, 우선순위, 기한): 정적 표시, 호버 효과 없음
|
||||||
|
- **모바일 최적화**:
|
||||||
|
- 바텀시트 편집 모달 (전체 화면 X)
|
||||||
|
- 터치 영역 최소 44px × 44px
|
||||||
|
|
||||||
#### 데이터 요구사항
|
#### 데이터 요구사항
|
||||||
- **입력**: 사용자 ID
|
- **입력**: 사용자 ID (내가 담당자인 Todo만 조회)
|
||||||
- **출력**:
|
- **출력**:
|
||||||
- Todo 목록 (상태, 내용, 담당자, 마감일, 우선순위, 회의록 링크)
|
- Todo 목록 (제목, 상태, 담당자, 마감일, 우선순위, 회의록 제목, 회의록 ID)
|
||||||
- Todo 통계 (전체, 완료, 진행 중)
|
- Todo 통계 (전체, 마감임박, 지연, 완료)
|
||||||
- **연동**: Todo 서비스, Meeting 서비스
|
- **연동**: Meeting 서비스 (Todo 관리 통합)
|
||||||
|
|
||||||
#### 에러 처리
|
#### 에러 처리
|
||||||
- **Todo 로딩 실패**: "Todo 목록을 불러올 수 없습니다" + 재시도 버튼
|
- **Todo 로딩 실패**: "Todo 목록을 불러올 수 없습니다" + 재시도 버튼
|
||||||
- **완료 처리 실패**: "완료 처리에 실패했습니다. 다시 시도해주세요"
|
- **상태 변경 실패**: "상태 변경에 실패했습니다. 다시 시도해주세요"
|
||||||
|
- **편집 저장 실패**: "저장에 실패했습니다. 다시 시도해주세요"
|
||||||
- **빈 상태**: "할당된 Todo가 없습니다. 새 회의를 시작해보세요!"
|
- **빈 상태**: "할당된 Todo가 없습니다. 새 회의를 시작해보세요!"
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -1236,8 +1246,8 @@ graph TD
|
|||||||
- 작성자 및 최종 수정 시간
|
- 작성자 및 최종 수정 시간
|
||||||
|
|
||||||
- **탭 네비게이션** (상단, Fixed)
|
- **탭 네비게이션** (상단, Fixed)
|
||||||
- "회의록" 탭 (기본 활성)
|
- "대시보드" 탭 (기본 활성)
|
||||||
- "대시보드" 탭
|
- "회의록" 탭
|
||||||
|
|
||||||
- **회의록 탭 콘텐츠** (섹션별 구조)
|
- **회의록 탭 콘텐츠** (섹션별 구조)
|
||||||
- 각 섹션:
|
- 각 섹션:
|
||||||
@ -1300,8 +1310,8 @@ graph TD
|
|||||||
|
|
||||||
**Tablet/Desktop (768px+)**
|
**Tablet/Desktop (768px+)**
|
||||||
- **상단**: 탭 네비게이션
|
- **상단**: 탭 네비게이션
|
||||||
- 회의록 (기본)
|
- 대시보드 (기본 활성)
|
||||||
- 대시보드
|
- 회의록
|
||||||
- **메인 영역**:
|
- **메인 영역**:
|
||||||
- 회의록 탭: 전체 회의록 내용 (섹션별 구조)
|
- 회의록 탭: 전체 회의록 내용 (섹션별 구조)
|
||||||
- 대시보드 탭: 핵심내용, 결정사항, Todo 진행상황, 참고자료 (11-회의록대시보드.html 구조 참조)
|
- 대시보드 탭: 핵심내용, 결정사항, Todo 진행상황, 참고자료 (11-회의록대시보드.html 구조 참조)
|
||||||
@ -1389,42 +1399,45 @@ graph TD
|
|||||||
- **목적**: 지난 회의록 조회 및 수정
|
- **목적**: 지난 회의록 조회 및 수정
|
||||||
- **관련 유저스토리**: UFR-MEET-055, UFR-AI-040, **UFR-TODO-040 (Todo 수정)**
|
- **관련 유저스토리**: UFR-MEET-055, UFR-AI-040, **UFR-TODO-040 (Todo 수정)**
|
||||||
- **비즈니스 중요도**: 중간
|
- **비즈니스 중요도**: 중간
|
||||||
- **접근 경로**: 대시보드 → "내 회의록" → 회의록상세조회 → "수정"
|
- **접근 경로**: 10-회의록상세조회 → 하단 액션 바 "수정" 버튼 클릭
|
||||||
|
- **권한 제어**:
|
||||||
|
- **검증완료 전**: 모든 참석자가 수정 가능
|
||||||
|
- **검증완료 후**: 회의 생성자만 수정 가능 (참석자는 "수정" 버튼 비활성화)
|
||||||
|
|
||||||
#### 주요 기능
|
#### 주요 기능
|
||||||
1. 회의록 목록 조회 (필터링, 정렬, 검색)
|
1. 회의 기본 정보 표시 및 수정
|
||||||
|
- 회의 제목: 수정 가능
|
||||||
|
- 회의 일시/장소: 읽기 전용 (회의 예약 화면에서만 변경 가능)
|
||||||
|
- 참석자 관리: 회의 생성자만 추가/삭제 가능
|
||||||
2. 회의록 내용 수정 (섹션별)
|
2. 회의록 내용 수정 (섹션별)
|
||||||
3. **AI 요약 수정** (섹션별)
|
3. **AI 요약 수정** (섹션별)
|
||||||
4. **참고자료 편집** (추가/제거)
|
4. **참고자료 편집** (추가/제거)
|
||||||
5. **Todo 수정 (UFR-TODO-040)** - 신규 추가 (회의 생성자만)
|
5. **Todo 수정 (UFR-TODO-040)** - 신규 추가 (회의 생성자만)
|
||||||
6. 자동 저장 (30초 간격)
|
6. 자동 저장 (30초 간격)
|
||||||
7. 수정 이력 관리
|
7. 수정 이력 관리
|
||||||
8. 상태 변경 (확정완료 → 작성중)
|
8. 상태 변경 (검증완료 → 작성중으로 자동 변경)
|
||||||
|
|
||||||
#### UI 구성요소
|
#### UI 구성요소
|
||||||
|
|
||||||
**Mobile (320px~768px)**
|
**Mobile (320px~768px)**
|
||||||
- **헤더**
|
- **헤더**
|
||||||
- 뒤로가기 버튼
|
- 뒤로가기 버튼 (10-회의록상세조회로 이동)
|
||||||
- "회의록 수정" 타이틀
|
- "회의록 수정" 타이틀
|
||||||
- "저장" 버튼 (Primary)
|
- "저장" 버튼 (Primary)
|
||||||
- 자동 저장 인디케이터
|
- 자동 저장 인디케이터 ("저장됨", "저장 중...")
|
||||||
|
|
||||||
- **필터 및 검색** (상단)
|
- **회의 기본 정보 영역**
|
||||||
- 상태 필터: 전체 / 작성중 / 확정완료
|
- 회의 제목: 편집 가능 (텍스트 필드)
|
||||||
- 정렬: 최신순 / 회의일시순 / 제목순
|
- 회의 일시: 읽기 전용 (📅 아이콘 + 날짜/시간 표시)
|
||||||
- 검색창: 제목, 참석자, 키워드
|
- 회의 장소: 읽기 전용 (📍 아이콘 + 장소명)
|
||||||
|
- 참석자 목록:
|
||||||
|
- 회의 생성자: 추가/삭제 가능 (05-회의진행 화면과 동일한 UI)
|
||||||
|
- 참석자: 읽기 전용 표시
|
||||||
|
- 각 참석자: 아바타 + 이름, 삭제(×) 버튼 (생성자는 삭제 불가)
|
||||||
|
- "참석자 추가" 버튼 (이메일 입력 + 초대)
|
||||||
|
- 회의록 상태 배지 (자동 관리)
|
||||||
|
|
||||||
- **회의록 리스트** (목록 모드)
|
- **편집 화면**
|
||||||
- 각 회의록 카드:
|
|
||||||
- 회의 제목
|
|
||||||
- 회의 일시
|
|
||||||
- 상태 배지
|
|
||||||
- 마지막 수정 시간
|
|
||||||
- 검증 완료율 (작성중인 경우)
|
|
||||||
- 스와이프 액션: 수정, 삭제
|
|
||||||
|
|
||||||
- **수정 모드** (편집 화면)
|
|
||||||
- 섹션별 편집 영역
|
- 섹션별 편집 영역
|
||||||
- 각 섹션:
|
- 각 섹션:
|
||||||
- 섹션 제목
|
- 섹션 제목
|
||||||
@ -1452,24 +1465,28 @@ graph TD
|
|||||||
- 자동 저장 상태 표시 ("저장됨", "저장 중...")
|
- 자동 저장 상태 표시 ("저장됨", "저장 중...")
|
||||||
|
|
||||||
**Tablet/Desktop (768px+)**
|
**Tablet/Desktop (768px+)**
|
||||||
- 좌측: 회의록 리스트
|
- **헤더**: Mobile과 동일 (뒤로가기, 타이틀, 저장 버튼, 자동 저장 인디케이터)
|
||||||
- 중앙: 선택된 회의록 편집 영역
|
- **메인 영역**:
|
||||||
- 우측: 수정 이력 패널
|
- 회의 기본 정보 영역 (Mobile과 동일)
|
||||||
|
- 편집 화면 (섹션별 편집, AI 요약, 참고자료, Todo)
|
||||||
|
- **우측 패널** (선택사항):
|
||||||
|
- 수정 이력 (v2.0 고도화 예정)
|
||||||
|
- 미리보기
|
||||||
|
|
||||||
#### 인터랙션
|
#### 인터랙션
|
||||||
1. **회의록 선택**
|
1. **화면 진입**
|
||||||
- 리스트에서 회의록 클릭: 편집 모드로 전환
|
- 10-회의록상세조회 → "수정" 버튼 클릭
|
||||||
- 편집 모드에서 다른 회의록 선택: 저장 확인 다이얼로그
|
- 권한 확인: 검증완료 후에는 회의 생성자만 접근 가능
|
||||||
|
- 바로 편집 모드로 시작
|
||||||
|
|
||||||
2. **내용 수정**
|
2. **내용 수정**
|
||||||
- 텍스트 영역 클릭: 포커스 및 편집 가능
|
- 텍스트 영역 클릭: 포커스 및 편집 가능
|
||||||
- 자동 저장: 30초 간격, 인디케이터 표시
|
- 자동 저장: 30초 간격, 인디케이터 표시
|
||||||
- 수동 저장: "저장" 버튼 클릭
|
- 수동 저장: "저장" 버튼 클릭
|
||||||
|
|
||||||
3. **섹션 잠금 해제**
|
3. **검증완료 섹션 (권한별 차등 표시)**
|
||||||
- 잠긴 섹션: 회의 생성자에게 승인 요청
|
- **회의 생성자**: 06-검증완료 화면에서 잠금 해제 가능
|
||||||
- 승인 대기 중: "승인 대기 중" 배지 표시
|
- **참석자**: 읽기 전용 표시 ("🔒 읽기 전용" 배지)
|
||||||
- 승인 완료: 편집 가능
|
|
||||||
|
|
||||||
4. **AI 요약 편집**
|
4. **AI 요약 편집**
|
||||||
- 요약 텍스트 필드 클릭: 직접 수정 가능
|
- 요약 텍스트 필드 클릭: 직접 수정 가능
|
||||||
@ -2015,6 +2032,8 @@ graph TD
|
|||||||
| 1.4.4 | 2025-10-23 | 강지수, 도그냥 | Todo 수정 기능 추가 (UFR-TODO-040)<br>- **유저스토리**: UFR-TODO-040 (Todo수정) 신규 추가<br> - 회의록 확정 전/후 Todo 수정 기능<br> - 권한별 수정 범위: 담당자(본인 Todo만), 회의 생성자(모든 Todo)<br> - 수정 항목: 제목, 담당자, 마감일, 우선순위<br>- **09-Todo관리**: Todo 수정 기능 추가<br> - "편집" 버튼 추가 (완료되지 않은 본인 Todo만 표시)<br> - Todo 편집 모달: 제목, 마감일, 우선순위 수정 (담당자 변경 불가)<br> - 수정 완료 시 회의록에 실시간 반영, 마감일 변경 시 캘린더 자동 업데이트<br> - 권한 제어: 본인에게 할당된 Todo만 편집 버튼 표시<br>- **11-회의록수정**: Todo 섹션 편집 기능 추가 (회의 생성자만)<br> - Todo 목록 표시 및 인라인 편집 (제목, 담당자, 마감일, 우선순위)<br> - Todo 추가/삭제 기능<br> - 담당자 변경 시 이전/새 담당자에게 알림 발송<br>- **프로토타입**: design/uiux/prototype/09-Todo관리.html 수정 (편집 모달 및 기능 구현) |
|
| 1.4.4 | 2025-10-23 | 강지수, 도그냥 | Todo 수정 기능 추가 (UFR-TODO-040)<br>- **유저스토리**: UFR-TODO-040 (Todo수정) 신규 추가<br> - 회의록 확정 전/후 Todo 수정 기능<br> - 권한별 수정 범위: 담당자(본인 Todo만), 회의 생성자(모든 Todo)<br> - 수정 항목: 제목, 담당자, 마감일, 우선순위<br>- **09-Todo관리**: Todo 수정 기능 추가<br> - "편집" 버튼 추가 (완료되지 않은 본인 Todo만 표시)<br> - Todo 편집 모달: 제목, 마감일, 우선순위 수정 (담당자 변경 불가)<br> - 수정 완료 시 회의록에 실시간 반영, 마감일 변경 시 캘린더 자동 업데이트<br> - 권한 제어: 본인에게 할당된 Todo만 편집 버튼 표시<br>- **11-회의록수정**: Todo 섹션 편집 기능 추가 (회의 생성자만)<br> - Todo 목록 표시 및 인라인 편집 (제목, 담당자, 마감일, 우선순위)<br> - Todo 추가/삭제 기능<br> - 담당자 변경 시 이전/새 담당자에게 알림 발송<br>- **프로토타입**: design/uiux/prototype/09-Todo관리.html 수정 (편집 모달 및 기능 구현) |
|
||||||
| 1.4.4 | 2025-10-23 | 강지수 | Mobile 하단 네비게이션 프로토타입 구현 기준 반영<br>- **Mobile 하단 네비게이션**: 4개 메뉴 → 3개 메뉴로 수정 (홈/회의록/Todo)<br> - 프로필 메뉴 제거 (Desktop 사이드바의 사용자 정보 영역으로 통합)<br> - 프로토타입 실제 구현 상태 반영 (02-대시보드.html, 09-Todo관리.html, 12-회의록목록조회.html)<br> - 사용 화면 번호 업데이트: 08→09, 11→12<br>- **참고 사항**: 프로필 메뉴가 필요한 경우 프로토타입에 추가 구현 필요<br>- **설계서-프로토타입 일관성**: 네비게이션 구조 완전 통일 달성 |
|
| 1.4.4 | 2025-10-23 | 강지수 | Mobile 하단 네비게이션 프로토타입 구현 기준 반영<br>- **Mobile 하단 네비게이션**: 4개 메뉴 → 3개 메뉴로 수정 (홈/회의록/Todo)<br> - 프로필 메뉴 제거 (Desktop 사이드바의 사용자 정보 영역으로 통합)<br> - 프로토타입 실제 구현 상태 반영 (02-대시보드.html, 09-Todo관리.html, 12-회의록목록조회.html)<br> - 사용 화면 번호 업데이트: 08→09, 11→12<br>- **참고 사항**: 프로필 메뉴가 필요한 경우 프로토타입에 추가 구현 필요<br>- **설계서-프로토타입 일관성**: 네비게이션 구조 완전 통일 달성 |
|
||||||
| 1.4.5 | 2025-10-23 | 강지수 | 로그아웃 기능 추가 (Desktop 사이드바 + Mobile 헤더)<br>- **Desktop 좌측 사이드바**: 하단에 사용자 정보 영역 추가<br> - 사용자 정보 (아바타 + 이름 + 이메일)<br> - 로그아웃 버튼 (btn-ghost btn-sm)<br>- **Mobile 상단 헤더**: 우측에 프로필 아이콘 버튼 추가 (👤)<br> - 클릭 시 드롭다운 메뉴 표시 (사용자 정보 + 로그아웃 버튼)<br> - 드롭다운 위치: 우측 상단 기준 아래로 펼침<br> - 오버레이 배경으로 UX 개선<br>- **프로토타입 파일**: 02-대시보드.html, 09-Todo관리.html, 12-회의록목록조회.html<br>- **JavaScript 함수**: toggleProfileMenu(), logout() 추가<br>- **반응형 처리**: Desktop에서는 드롭다운 숨김, Mobile에서는 사이드바 사용자 영역 숨김<br>- **설계서-프로토타입 일관성**: 로그아웃 기능 완전 통일 |
|
| 1.4.5 | 2025-10-23 | 강지수 | 로그아웃 기능 추가 (Desktop 사이드바 + Mobile 헤더)<br>- **Desktop 좌측 사이드바**: 하단에 사용자 정보 영역 추가<br> - 사용자 정보 (아바타 + 이름 + 이메일)<br> - 로그아웃 버튼 (btn-ghost btn-sm)<br>- **Mobile 상단 헤더**: 우측에 프로필 아이콘 버튼 추가 (👤)<br> - 클릭 시 드롭다운 메뉴 표시 (사용자 정보 + 로그아웃 버튼)<br> - 드롭다운 위치: 우측 상단 기준 아래로 펼침<br> - 오버레이 배경으로 UX 개선<br>- **프로토타입 파일**: 02-대시보드.html, 09-Todo관리.html, 12-회의록목록조회.html<br>- **JavaScript 함수**: toggleProfileMenu(), logout() 추가<br>- **반응형 처리**: Desktop에서는 드롭다운 숨김, Mobile에서는 사이드바 사용자 영역 숨김<br>- **설계서-프로토타입 일관성**: 로그아웃 기능 완전 통일 |
|
||||||
|
| 1.4.6 | 2025-10-23 | 강지수 | 검증완료 섹션 잠금해제 정책 단순화<br>- **정책 변경**: 검증완료 섹션은 회의 생성자만 잠금 해제 후 수정 가능 (참석자는 수정 불가)<br>- **제거**: 참석자용 잠금해제 요청 기능 완전 제거 (공수 절감)<br>- **11-회의록수정**: 검증완료 섹션에 "🔒 읽기 전용" 배지 표시 (참석자 화면)<br> - 잠금해제요청 버튼 제거<br> - unlockSection() 함수 제거<br> - 읽기 전용 안내 텍스트 추가: "(잠금됨 · 회의 생성자만 수정 가능)"<br>- **06-검증완료**: 회의 생성자용 잠금해제 버튼 유지 (변경 없음)<br>- **인터랙션**: "3. 섹션 잠금 해제" → "3. 검증완료 섹션 (권한별 차등 표시)"로 수정<br>- **유저스토리**: UFR-MEET-055, UFR-COLLAB-030 권한 제어 명확화 |
|
||||||
|
| 1.4.7 | 2025-10-23 | 강지수, 도그냥 | Todo 및 회의록 관련 UI/UX 재정의<br>- **09-Todo관리**: "Todo수정" → "Todo관리" 기능 확장<br> - 통계 블록: 전체(미완료), 마감임박(3일 이내), 지연(기한 경과)<br> - 필터 탭 개수 표시: 전체(개수), 지연(개수), 마감임박(개수), 완료(개수)<br> - 편집 모달: 제목, 담당자, 마감일, 우선순위 수정<br> - 체크박스 확인 모달: 완료/미완료 전환 시 확인<br> - 프로토타입: 09-Todo관리.html (통계, 필터, 모달 구현)<br>- **10-회의록상세조회**: 탭 순서 및 기본 노출 변경<br> - 탭 순서: 대시보드 → 회의록 (기존: 회의록 → 대시보드)<br> - 기본 활성 탭: 대시보드 (Desktop/Mobile 공통)<br> - 프로토타입: 10-회의록상세조회.html (탭 순서 변경, active 클래스 이동)<br>- **11-회의록수정**: 진입 경로 및 권한 제어 명확화<br> - 진입 경로: 10-회의록상세조회 → "수정" 버튼 클릭<br> - 권한 제어: 검증완료 전(모든 참석자), 검증완료 후(회의 생성자만)<br> - 회의 일시/장소: 읽기 전용 표시 추가 "(읽기 전용)"<br> - UI 구성: 회의록 리스트 제거, 직접 편집 화면으로 시작<br> - 프로토타입: 11-회의록수정.html (권한 코멘트 추가, readonly 표시) |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
# AI기반 회의록 작성 및 이력 관리 개선 서비스 - 유저스토리 (v2.0.3)
|
# AI기반 회의록 작성 및 이력 관리 개선 서비스 - 유저스토리 (v2.0.5)
|
||||||
|
|
||||||
- [AI기반 회의록 작성 및 이력 관리 개선 서비스 - 유저스토리 (v2.0.3)](#ai기반-회의록-작성-및-이력-관리-개선-서비스---유저스토리-v203)
|
- [AI기반 회의록 작성 및 이력 관리 개선 서비스 - 유저스토리 (v2.0.5)](#ai기반-회의록-작성-및-이력-관리-개선-서비스---유저스토리-v205)
|
||||||
- [차별화 전략](#차별화-전략)
|
- [차별화 전략](#차별화-전략)
|
||||||
- [1. 기본 기능 (Hygiene Factors)](#1-기본-기능-hygiene-factors)
|
- [1. 기본 기능 (Hygiene Factors)](#1-기본-기능-hygiene-factors)
|
||||||
- [2. 핵심 차별화 포인트 (Differentiators)](#2-핵심-차별화-포인트-differentiators)
|
- [2. 핵심 차별화 포인트 (Differentiators)](#2-핵심-차별화-포인트-differentiators)
|
||||||
@ -316,9 +316,22 @@ UFR-MEET-047: [회의록상세조회] 회의록 작성자로서 | 나는, 지난
|
|||||||
- 각 회의록별 정보: 제목, 날짜, 관련도 %, 요약 내용
|
- 각 회의록별 정보: 제목, 날짜, 관련도 %, 요약 내용
|
||||||
- 클릭 시 해당 회의록으로 이동
|
- 클릭 시 해당 회의록으로 이동
|
||||||
|
|
||||||
|
[탭 네비게이션]
|
||||||
|
- **탭 구성**: 대시보드 / 회의록 (2개 탭)
|
||||||
|
- **기본 노출**: 대시보드 탭 우선 노출
|
||||||
|
- **탭 전환**: 클릭 시 콘텐츠 전환, URL 변경 없음
|
||||||
|
- **대시보드 탭 내용**:
|
||||||
|
- 핵심내용 (주요 포인트 요약)
|
||||||
|
- 결정사항
|
||||||
|
- Todo 진행상황
|
||||||
|
- 관련회의록
|
||||||
|
- **회의록 탭 내용**:
|
||||||
|
- 섹션별 상세 내용
|
||||||
|
- AI 요약
|
||||||
|
- 관련회의록
|
||||||
|
|
||||||
[부가 기능]
|
[부가 기능]
|
||||||
- 회의록 수정 버튼 (수정 권한이 있는 경우만 활성화)
|
- 회의록 수정 버튼 (수정 권한이 있는 경우만 활성화)
|
||||||
- 탭 네비게이션 (회의록/대시보드)
|
|
||||||
- 뒤로가기 버튼 (회의록 목록으로 복귀)
|
- 뒤로가기 버튼 (회의록 목록으로 복귀)
|
||||||
- 더보기 메뉴 (다운로드, 삭제 등)
|
- 더보기 메뉴 (다운로드, 삭제 등)
|
||||||
|
|
||||||
@ -336,10 +349,15 @@ UFR-MEET-047: [회의록상세조회] 회의록 작성자로서 | 나는, 지난
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
UFR-MEET-055: [회의록수정] 회의록 작성자로서 | 나는, 검증이 완료되지 않았거나 수정이 필요한 | 지난 회의록을 수정하고 싶다.
|
UFR-MEET-055: [회의록수정] 회의 참석자로서 | 나는, 검증이 완료되지 않았거나 수정이 필요한 | 지난 회의록을 수정하고 싶다.
|
||||||
|
- **화면번호**: 11-회의록수정
|
||||||
- 시나리오: 지난 회의록 수정
|
- 시나리오: 지난 회의록 수정
|
||||||
회의록 상세 화면에서 수정 버튼을 클릭하면 | 회의록 수정 화면으로 이동하고 | 내용을 수정할 수 있다.
|
회의록 상세 화면에서 수정 버튼을 클릭하면 | 회의록 수정 화면으로 이동하고 | 내용을 수정할 수 있다.
|
||||||
|
|
||||||
|
[진입 경로]
|
||||||
|
- 10-회의록상세조회 화면 → 하단 액션 바 "수정" 버튼 클릭
|
||||||
|
- 권한이 있는 경우에만 "수정" 버튼 활성화
|
||||||
|
|
||||||
[수정 가능 항목]
|
[수정 가능 항목]
|
||||||
- ✅ **회의 제목**: 수정 가능
|
- ✅ **회의 제목**: 수정 가능
|
||||||
- ❌ **회의 일시**: 수정 불가 (readonly, 회의 예약 화면에서만 변경 가능)
|
- ❌ **회의 일시**: 수정 불가 (readonly, 회의 예약 화면에서만 변경 가능)
|
||||||
@ -351,7 +369,7 @@ UFR-MEET-055: [회의록수정] 회의록 작성자로서 | 나는, 검증이
|
|||||||
- ✅ **섹션별 AI 요약**: AI 재생성 버튼으로 수정 가능
|
- ✅ **섹션별 AI 요약**: AI 재생성 버튼으로 수정 가능
|
||||||
- ✅ **섹션별 내용**: 마크다운 에디터로 수정 가능
|
- ✅ **섹션별 내용**: 마크다운 에디터로 수정 가능
|
||||||
- ✅ **관련회의록**: 추가/삭제 가능
|
- ✅ **관련회의록**: 추가/삭제 가능
|
||||||
- ❌ **검증완료 섹션**: 잠금 해제 후 수정 가능 (회의록 생성자만 잠금 해제 가능)
|
- ❌ **검증완료 섹션**: 회의 생성자만 잠금 해제 후 수정 가능 (참석자는 수정 불가)
|
||||||
- 🔄 **회의록 상태**: 수정 시 자동으로 '작성중'으로 변경 (사용자 직접 변경 불가)
|
- 🔄 **회의록 상태**: 수정 시 자동으로 '작성중'으로 변경 (사용자 직접 변경 불가)
|
||||||
|
|
||||||
[수정 기능]
|
[수정 기능]
|
||||||
@ -366,9 +384,16 @@ UFR-MEET-055: [회의록수정] 회의록 작성자로서 | 나는, 검증이
|
|||||||
- 취소 시 이전 상태로 복원
|
- 취소 시 이전 상태로 복원
|
||||||
|
|
||||||
[권한 제어]
|
[권한 제어]
|
||||||
- 본인이 작성한 회의록만 수정 가능
|
**검증완료 전 (작성중/초안 상태)**
|
||||||
- 검증완료 섹션 잠금/해제는 회의록 생성자만 가능
|
- 모든 참석자가 회의록 수정 가능
|
||||||
- 조회 전용 권한인 경우 수정 버튼 비활성화
|
- 모든 섹션 편집 가능 (검증완료 섹션 없음)
|
||||||
|
- 참석자 관리: 회의 생성자만 가능
|
||||||
|
|
||||||
|
**검증완료 후**
|
||||||
|
- 회의 생성자만 회의록 수정 가능
|
||||||
|
- 참석자는 "수정" 버튼 비활성화 (조회만 가능)
|
||||||
|
- 검증완료 섹션: 회의 생성자만 잠금 해제 후 수정 가능
|
||||||
|
- 수정 시 회의록 상태는 '작성중'으로 자동 변경 (재검증 필요)
|
||||||
|
|
||||||
- M/13
|
- M/13
|
||||||
|
|
||||||
@ -773,10 +798,10 @@ UFR-COLLAB-030: [검증완료] 회의 참석자로서 | 나는, 회의록의 정
|
|||||||
- 미검증 → 검증 중 → 검증 완료
|
- 미검증 → 검증 중 → 검증 완료
|
||||||
|
|
||||||
[섹션 잠금 기능]
|
[섹션 잠금 기능]
|
||||||
- 회의 생성자만 가능
|
- 회의 생성자만 잠금/해제 가능
|
||||||
- 주요 섹션 검증 완료 시 잠금 가능 (선택)
|
- 주요 섹션 검증 완료 시 잠금 가능 (선택)
|
||||||
- 잠긴 섹션은 추가 수정 불가
|
- 잠긴 섹션은 회의 생성자만 잠금 해제 후 수정 가능
|
||||||
- 회의 생성자가 잠그면 검증 완료로 표시
|
- 참석자는 검증완료된 섹션을 읽기 전용으로만 확인 가능
|
||||||
|
|
||||||
[처리 결과]
|
[처리 결과]
|
||||||
- 검증이 완료됨
|
- 검증이 완료됨
|
||||||
@ -890,62 +915,87 @@ UFR-TODO-030: [Todo완료처리] Todo 담당자로서 | 나는, 완료된 Todo
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
UFR-TODO-040: [Todo수정] Todo 담당자 또는 회의 생성자로서 | 나는, Todo 내용을 변경하기 위해 | 회의록 확정 전후에 Todo를 수정하고 싶다.
|
UFR-TODO-040: [Todo관리] Todo 담당자로서 | 나는, 나의 Todo를 효율적으로 관리하기 위해 | Todo 목록을 조회하고 상태를 변경하고 편집하고 싶다.
|
||||||
- 시나리오: Todo 수정
|
- 시나리오: Todo 관리 화면 조회 및 관리
|
||||||
Todo 목록에서 수정이 필요한 상황에서 | 담당자 또는 회의 생성자가 Todo 수정 버튼을 클릭하면 | Todo 내용, 담당자, 마감일, 우선순위를 변경할 수 있다.
|
09-Todo관리 화면에 접근하면 | 나의 Todo(내가 담당자인 Todo) 목록이 표시되고 | 필터링, 상태 변경, 편집이 가능하다.
|
||||||
|
|
||||||
[화면 정보]
|
[화면 정보]
|
||||||
- 화면번호: 09-Todo관리
|
- 화면번호: 09-Todo관리
|
||||||
- 프로토타입: design/uiux/prototype/09-Todo관리.html
|
- 프로토타입: design/uiux/prototype/09-Todo관리.html
|
||||||
|
|
||||||
[수정 가능 항목]
|
[대전제]
|
||||||
- Todo 제목 (문구)
|
- Todo의 상태는 완료/미완료만 존재
|
||||||
- 담당자 (드롭다운 선택)
|
- 09-Todo관리 화면에서는 나의 Todo(내가 담당자인 Todo)만 표시
|
||||||
- 마감일 (날짜 선택기)
|
|
||||||
- 우선순위 (high/medium/low)
|
|
||||||
|
|
||||||
[수정 시점]
|
[화면 구성]
|
||||||
- **회의록 확정 전**: 회의 진행 중(05-회의진행) 또는 회의 종료 전(07-회의종료)에서 수정 가능
|
**1. 상단 통계 블록**
|
||||||
- **회의록 확정 후**: Todo 관리 화면(09-Todo관리) 또는 회의록 수정 화면(11-회의록수정)에서 수정 가능
|
- 전체: 미완료 전체 개수
|
||||||
|
- 마감임박: 기한 3일 이내 미완료 개수
|
||||||
|
- 지연: 기한이 지난 미완료 개수
|
||||||
|
|
||||||
|
**2. 필터링 기준**
|
||||||
|
- 전체(개수): 완료/미완료 전체
|
||||||
|
- 지연(개수): 기한이 지난 미완료
|
||||||
|
- 마감임박(개수): 기한 3일 이내 미완료
|
||||||
|
- 완료(개수): 완료된 Todo
|
||||||
|
|
||||||
|
**3. Todo 리스트 블록**
|
||||||
|
- 정렬: 미완료 → 완료 순서, 기한일 오래된 순 (복합 정렬)
|
||||||
|
- 표시 항목:
|
||||||
|
- 체크박스 (완료/미완료 토글)
|
||||||
|
- Todo 제목
|
||||||
|
- 상태 뱃지: D+n(지연) / D-day / D-n / 완료
|
||||||
|
- 우선순위 뱃지: 높음 / 보통 / 낮음
|
||||||
|
- 기한
|
||||||
|
- 회의록 제목 + 링크 (해당 Todo가 속한 회의록 상세로 이동)
|
||||||
|
- 편집 버튼 (권한 있는 경우에만 노출)
|
||||||
|
- 페이징: 최초 10건 노출, 10건 이상일 경우 하단에 "10개 더보기" 버튼 표시
|
||||||
|
|
||||||
|
**4. 편집 모달**
|
||||||
|
- 제목 (input)
|
||||||
|
- 담당자 (해당 회의록 참석자 중 select) - 회의 생성자만 변경 가능
|
||||||
|
- 마감일 (달력)
|
||||||
|
- 우선순위 (높음/보통/낮음 select)
|
||||||
|
|
||||||
|
[UI/UX 요구사항]
|
||||||
|
- **디자인 차별화**: 액션 가능한 블록(체크박스, 편집 버튼)과 정보 표시 블록은 시각적으로 구분
|
||||||
|
- **체크박스 동작**:
|
||||||
|
- 체크박스 클릭 시 "완료 처리하시겠습니까?" 확인 모달 표시
|
||||||
|
- 확인 시 완료 처리, 취소 시 이전 상태 유지
|
||||||
|
- 미완료로 되돌릴 때도 "미완료로 변경하시겠습니까?" 확인 모달 표시
|
||||||
|
- **편집 버튼**: 담당자 본인 OR 회의 생성자인 경우에만 노출
|
||||||
|
- **편집 모달**: 모바일에서는 바텀시트 형식으로 표시
|
||||||
|
- **회의록 링크**: 클릭 시 10-회의록상세조회 화면으로 이동 (대시보드 탭 우선 노출)
|
||||||
|
|
||||||
[권한 제어]
|
[권한 제어]
|
||||||
- **Todo 담당자**: 본인에게 할당된 Todo만 수정 가능 (09-Todo관리)
|
- **Todo 담당자**: 본인에게 할당된 Todo만 편집 가능
|
||||||
- 수정 가능 항목: 제목, 마감일, 우선순위
|
- 수정 가능 항목: 제목, 마감일, 우선순위
|
||||||
- 담당자 변경 불가 (본인 담당 Todo)
|
- 담당자 변경 불가
|
||||||
- **회의 생성자**: 해당 회의의 모든 Todo 수정 가능 (11-회의록수정)
|
- **회의 생성자**: 해당 회의의 모든 Todo 편집 가능 (11-회의록수정 화면에서)
|
||||||
- 수정 가능 항목: 제목, 담당자, 마감일, 우선순위
|
- 수정 가능 항목: 제목, 담당자, 마감일, 우선순위
|
||||||
- 담당자 변경 가능
|
- 담당자 변경 가능
|
||||||
|
|
||||||
[수정 인터페이스]
|
|
||||||
- 09-Todo관리: 각 Todo 항목에 "편집" 버튼 표시
|
|
||||||
- 클릭 시 인라인 편집 모드 또는 수정 모달 표시
|
|
||||||
- 수정 완료 후 "저장" 버튼 클릭
|
|
||||||
- 11-회의록수정: "액션 아이템(Todo)" 섹션에서 수정
|
|
||||||
- 회의록 수정 시 Todo 섹션도 편집 가능
|
|
||||||
- Todo 추가/삭제/수정 모두 가능
|
|
||||||
|
|
||||||
[처리 결과]
|
[처리 결과]
|
||||||
|
- Todo 상태 변경 시:
|
||||||
|
- 완료/미완료 상태 즉시 업데이트
|
||||||
|
- 통계 블록 갱신
|
||||||
|
- 리스트 재정렬
|
||||||
|
- Todo 편집 저장 시:
|
||||||
- Todo 정보 업데이트
|
- Todo 정보 업데이트
|
||||||
- 수정 시간 기록
|
- 수정 시간 기록
|
||||||
- 수정자 정보 저장
|
|
||||||
- 회의록에 수정 내용 실시간 반영
|
- 회의록에 수정 내용 실시간 반영
|
||||||
- 담당자 변경 시 이전 담당자와 새 담당자에게 알림 발송
|
- 담당자 변경 시 이전/새 담당자에게 알림 발송
|
||||||
- 마감일 변경 시 캘린더 자동 업데이트
|
- 마감일 변경 시 캘린더 자동 업데이트
|
||||||
|
|
||||||
[알림 발송]
|
|
||||||
- 담당자 변경 시: 이전 담당자 및 새 담당자에게 알림
|
|
||||||
- 마감일 변경 시: 담당자에게 알림 (캘린더 업데이트)
|
|
||||||
- 제목/우선순위 변경 시: 담당자에게 알림 (변경 사항 안내)
|
|
||||||
|
|
||||||
[Policy/Rule]
|
[Policy/Rule]
|
||||||
- 담당자는 본인 Todo만 수정 가능 (담당자 변경 불가)
|
- 필터별 개수 표시로 사용자가 전체 보기 여부 판단 가능
|
||||||
- 회의 생성자는 모든 Todo 수정 가능 (담당자 변경 가능)
|
- 체크박스 토글 시 확인 액션 필수 (실수 방지)
|
||||||
- 확정 전/후 모두 수정 가능
|
- 편집 권한 없는 Todo는 편집 버튼 미노출
|
||||||
- 수정 시 회의록에 즉시 반영
|
|
||||||
|
|
||||||
[비고]
|
[비고]
|
||||||
- 회의록 확정 후에도 유연한 Todo 관리 가능
|
- 진행률 표시 제거 (상태는 완료/미완료만)
|
||||||
- 인사 이동, 우선순위 변경, 일정 조정 등 실무 요구사항 반영
|
- 날짜별 그룹핑은 v2.0 고도화 시 고려
|
||||||
|
- Todo 하이라이트 기능은 v2.0 고도화 시 고려
|
||||||
|
|
||||||
- M/13
|
- M/13
|
||||||
|
|
||||||
@ -1044,5 +1094,7 @@ UFR-TODO-040: [Todo수정] Todo 담당자 또는 회의 생성자로서 | 나는
|
|||||||
| 2.0.1 | 2025-10-23 | 강지수 (Product Designer) | 공유 기능 제거 반영 <br>- AFR-USER-020: 대시보드 "공유받은 회의록" 섹션 제거<br>- UFR-MEET-046: 회의록 목록 카테고리 필터 "공유받은 회의" 제거 |
|
| 2.0.1 | 2025-10-23 | 강지수 (Product Designer) | 공유 기능 제거 반영 <br>- AFR-USER-020: 대시보드 "공유받은 회의록" 섹션 제거<br>- UFR-MEET-046: 회의록 목록 카테고리 필터 "공유받은 회의" 제거 |
|
||||||
| 2.0.2 | 2025-10-23 | 강지수, 도그냥 | Todo 수정 기능 추가 (UFR-TODO-040)<br>- 회의록 확정 전/후 Todo 수정 기능 추가<br>- 권한별 수정 범위: 담당자(본인 Todo만), 회의 생성자(모든 Todo)<br>- 수정 항목: 제목, 담당자, 마감일, 우선순위<br>- 09-Todo관리, 11-회의록수정 화면에서 수정 가능 |
|
| 2.0.2 | 2025-10-23 | 강지수, 도그냥 | Todo 수정 기능 추가 (UFR-TODO-040)<br>- 회의록 확정 전/후 Todo 수정 기능 추가<br>- 권한별 수정 범위: 담당자(본인 Todo만), 회의 생성자(모든 Todo)<br>- 수정 항목: 제목, 담당자, 마감일, 우선순위<br>- 09-Todo관리, 11-회의록수정 화면에서 수정 가능 |
|
||||||
| 2.0.3 | 2025-10-23 | 강지수 (Product Designer) | 회의록 수정 항목 정책 명확화 (UFR-MEET-055)<br>- 회의 일시/장소: readonly 처리 (회의 예약 화면에서만 변경 가능)<br>- 참석자 관리: 회의 생성자만 추가/삭제 가능 (11-회의록수정 화면에서 직접 관리)<br>- 참석자 UI: 05-회의진행 화면과 동일한 방식으로 구현<br>- 프로토타입: 11-회의록수정.html에 참석자 관리 섹션 추가 |
|
| 2.0.3 | 2025-10-23 | 강지수 (Product Designer) | 회의록 수정 항목 정책 명확화 (UFR-MEET-055)<br>- 회의 일시/장소: readonly 처리 (회의 예약 화면에서만 변경 가능)<br>- 참석자 관리: 회의 생성자만 추가/삭제 가능 (11-회의록수정 화면에서 직접 관리)<br>- 참석자 UI: 05-회의진행 화면과 동일한 방식으로 구현<br>- 프로토타입: 11-회의록수정.html에 참석자 관리 섹션 추가 |
|
||||||
|
| 2.0.4 | 2025-10-23 | 강지수 (Product Designer) | 검증완료 섹션 잠금해제 정책 단순화<br>- **정책 변경**: 검증완료 섹션은 회의 생성자만 잠금 해제 후 수정 가능 (참석자는 수정 불가)<br>- **제거**: 참석자용 잠금해제 요청 기능 완전 제거 (공수 절감)<br>- UFR-MEET-055: 권한 제어 명확화 (생성자만 잠금 해제 가능)<br>- UFR-COLLAB-030: 섹션 잠금 기능 설명 업데이트<br>- 프로토타입 11-회의록수정.html: 잠금해제요청 버튼 제거, 검증완료 섹션 읽기 전용 표시 |
|
||||||
|
| 2.0.5 | 2025-10-23 | 강지수 (Product Designer), 도그냥 (Service Planner) | Todo 및 회의록 관련 요구사항 재정의<br>- **UFR-TODO-040 (09-Todo관리)**: "Todo수정" → "Todo관리" 기능 확장<br> - 통계 블록 재정의: 전체(미완료), 마감임박(3일 이내), 지연(기한 경과)<br> - 필터링: 전체, 지연, 마감임박, 완료 (각 필터에 개수 표시)<br> - 체크박스 확인 모달: 완료/미완료 전환 시 확인<br> - 권한: 담당자 본인 OR 회의록 작성자만 편집 가능<br>- **UFR-MEET-047 (10-회의록상세조회)**: 탭 순서 및 기본 노출 변경<br> - 탭 구성: 대시보드 / 회의록<br> - 기본 노출: 대시보드 탭 우선 노출 (기존: 회의록 우선)<br>- **UFR-MEET-055 (11-회의록수정)**: 진입 경로 및 권한 제어 명확화<br> - 진입 경로: 10-회의록상세조회 → "수정" 버튼 클릭<br> - 권한 제어: 검증완료 전(모든 참석자), 검증완료 후(회의 생성자만)<br> - 회의 일시/장소: 읽기 전용 표시 명시 |
|
||||||
|
|
||||||
---
|
---
|
||||||
123
develop/dev/run-profiles-guide.md
Normal file
123
develop/dev/run-profiles-guide.md
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
# 백엔드 서비스 실행 프로파일 가이드
|
||||||
|
|
||||||
|
## 개요
|
||||||
|
HGZero 프로젝트의 모든 백엔드 서비스를 IntelliJ IDEA에서 실행할 수 있는 실행 프로파일을 생성했습니다.
|
||||||
|
|
||||||
|
## 생성된 실행 프로파일
|
||||||
|
|
||||||
|
### 1. UserApplication
|
||||||
|
- **포트**: 8080
|
||||||
|
- **데이터베이스**: userdb (20.214.121.121:5432)
|
||||||
|
- **Redis 데이터베이스**: 0
|
||||||
|
- **메인 클래스**: `com.unicorn.hgzero.user.UserApplication`
|
||||||
|
- **모듈**: user
|
||||||
|
- **로그 파일**: logs/user.log
|
||||||
|
|
||||||
|
### 2. NotificationApplication
|
||||||
|
- **포트**: 8084
|
||||||
|
- **데이터베이스**: notificationdb (4.230.159.143:5432)
|
||||||
|
- **Redis 데이터베이스**: 4
|
||||||
|
- **메인 클래스**: `com.unicorn.hgzero.notification.NotificationApplication`
|
||||||
|
- **모듈**: notification
|
||||||
|
- **로그 파일**: logs/notification.log
|
||||||
|
|
||||||
|
### 3. AiApplication
|
||||||
|
- **포트**: 8083
|
||||||
|
- **데이터베이스**: aidb (20.249.153.213:5432)
|
||||||
|
- **Redis 데이터베이스**: 4
|
||||||
|
- **메인 클래스**: `com.unicorn.hgzero.ai.AiApplication`
|
||||||
|
- **모듈**: ai
|
||||||
|
- **로그 파일**: logs/ai.log
|
||||||
|
|
||||||
|
### 4. SttApplication
|
||||||
|
- **포트**: 8082
|
||||||
|
- **데이터베이스**: sttdb (4.230.65.89:5432)
|
||||||
|
- **Redis 데이터베이스**: 2
|
||||||
|
- **메인 클래스**: `com.unicorn.hgzero.stt.SttApplication`
|
||||||
|
- **모듈**: stt
|
||||||
|
- **로그 파일**: logs/stt.log
|
||||||
|
|
||||||
|
## 환경 변수 설정
|
||||||
|
|
||||||
|
각 서비스별로 다음 환경 변수들이 설정되어 있습니다:
|
||||||
|
|
||||||
|
### 공통 환경 변수
|
||||||
|
- `JWT_SECRET`: 각 서비스별 개발용 JWT 시크릿 키
|
||||||
|
- `CORS_ALLOWED_ORIGINS`: http://localhost:*
|
||||||
|
- `SHOW_SQL`: true (개발용)
|
||||||
|
- `DDL_AUTO`: update (개발용)
|
||||||
|
- `LOG_LEVEL_APP`: DEBUG
|
||||||
|
- 기타 로깅 레벨 설정
|
||||||
|
|
||||||
|
### 서비스별 특화 환경 변수
|
||||||
|
|
||||||
|
#### AI 서비스
|
||||||
|
- `AZURE_OPENAI_API_KEY`: OpenAI API 키가 설정됨
|
||||||
|
- `AZURE_OPENAI_ENDPOINT`: https://api.openai.com/v1
|
||||||
|
- `AZURE_OPENAI_DEPLOYMENT`: gpt-4o
|
||||||
|
- `AZURE_OPENAI_EMBEDDING_DEPLOYMENT`: text-embedding-3-large
|
||||||
|
|
||||||
|
#### Notification 서비스
|
||||||
|
- `MAIL_HOST`: smtp.gmail.com
|
||||||
|
- `MAIL_PORT`: 587
|
||||||
|
- `NOTIFICATION_FROM_EMAIL`: noreply@hgzero.com
|
||||||
|
- `NOTIFICATION_FROM_NAME`: HGZero
|
||||||
|
|
||||||
|
#### STT 서비스
|
||||||
|
- `AZURE_SPEECH_REGION`: eastus
|
||||||
|
- `AZURE_SPEECH_LANGUAGE`: ko-KR
|
||||||
|
- `AZURE_BLOB_CONTAINER_NAME`: recordings
|
||||||
|
|
||||||
|
#### User 서비스
|
||||||
|
- `LDAP_URLS`: ldaps://ldap.example.com:636
|
||||||
|
- `LDAP_BASE`: dc=example,dc=com
|
||||||
|
|
||||||
|
## 실행 방법
|
||||||
|
|
||||||
|
### IntelliJ IDEA에서 실행
|
||||||
|
1. IntelliJ IDEA에서 프로젝트 열기
|
||||||
|
2. Run/Debug Configurations 에서 원하는 서비스 선택
|
||||||
|
3. Run 또는 Debug 모드로 실행
|
||||||
|
|
||||||
|
### 서비스 실행 순서 권장사항
|
||||||
|
1. **UserApplication** (8080) - 사용자 인증 서비스
|
||||||
|
2. **SttApplication** (8082) - 음성 인식 서비스
|
||||||
|
3. **AiApplication** (8083) - AI 처리 서비스
|
||||||
|
4. **NotificationApplication** (8084) - 알림 서비스
|
||||||
|
|
||||||
|
## 주의사항
|
||||||
|
|
||||||
|
### 데이터베이스 연결 설정
|
||||||
|
**현재 설정된 데이터베이스 비밀번호**: `hgzero123!`
|
||||||
|
- 모든 서비스가 동일한 데이터베이스 비밀번호를 사용하도록 설정되었습니다
|
||||||
|
- **HIBERNATE_DIALECT**가 `org.hibernate.dialect.PostgreSQLDialect`로 명시적으로 설정되어 연결 오류를 방지합니다
|
||||||
|
|
||||||
|
### 필수 설정이 필요한 환경 변수
|
||||||
|
다음 환경 변수들은 실제 운영 시 설정이 필요합니다:
|
||||||
|
|
||||||
|
- `REDIS_PASSWORD`: Redis 비밀번호 (필요시)
|
||||||
|
- `AZURE_SPEECH_SUBSCRIPTION_KEY`: Azure Speech 서비스 키 (STT 서비스)
|
||||||
|
- `AZURE_EVENTHUB_CONNECTION_STRING`: Event Hub 연결 문자열
|
||||||
|
- `AZURE_STORAGE_CONNECTION_STRING`: Azure Storage 연결 문자열
|
||||||
|
- `MAIL_USERNAME`, `MAIL_PASSWORD`: 이메일 발송용 계정 정보
|
||||||
|
|
||||||
|
### 포트 충돌 방지
|
||||||
|
- User: 8080
|
||||||
|
- STT: 8082
|
||||||
|
- AI: 8083
|
||||||
|
- Notification: 8084
|
||||||
|
|
||||||
|
모든 서비스가 서로 다른 포트를 사용하므로 동시 실행이 가능합니다.
|
||||||
|
|
||||||
|
## 로그 파일 위치
|
||||||
|
- 모든 로그는 프로젝트 루트의 `logs/` 디렉토리에 저장됩니다
|
||||||
|
- 각 서비스별 로그 파일:
|
||||||
|
- `logs/user.log`
|
||||||
|
- `logs/notification.log`
|
||||||
|
- `logs/ai.log`
|
||||||
|
- `logs/stt.log`
|
||||||
|
|
||||||
|
## 개발 환경 설정
|
||||||
|
- 모든 프로파일은 `dev` 프로파일로 설정됨
|
||||||
|
- SQL 로깅이 활성화되어 개발 중 디버깅 용이
|
||||||
|
- DDL 자동 업데이트로 스키마 변경 자동 반영
|
||||||
1440
logs/ai.log
Normal file
1440
logs/ai.log
Normal file
File diff suppressed because it is too large
Load Diff
@ -13,6 +13,6 @@ import org.springframework.context.annotation.ComponentScan;
|
|||||||
public class UserApplication {
|
public class UserApplication {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
SpringApplication.run(UserApplication.java, args);
|
SpringApplication.run(UserApplication.class, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user