Compare commits

...

1 Commits
v5 ... v4-ui

Author SHA1 Message Date
6527e68e52 Ui stuff 2025-08-16 17:28:33 +02:00
13 changed files with 165 additions and 16 deletions

View File

@ -50,7 +50,6 @@ class WebConfig: WebMvcConfigurer {
}
}
})
}
override fun configurePathMatch(configurer: PathMatchConfigurer) {

View File

@ -0,0 +1,15 @@
package no.iktdev.mediaprocessing.ui.dto
import no.iktdev.mediaprocessing.shared.common.contract.data.Event
data class DatabaseEntriesDelete(
val referenceId: String,
val eventId: String
)
data class DatabaseEventEntries(
val referenceId: String,
val events: List<Event>,
val created: Long,
val lastEventCreated: Long,
)

View File

@ -0,0 +1,68 @@
package no.iktdev.mediaprocessing.ui.socket
import no.iktdev.eventi.data.referenceId
import no.iktdev.eventi.database.executeWithStatus
import no.iktdev.eventi.database.toEpochSeconds
import no.iktdev.eventi.database.withDirtyRead
import no.iktdev.eventi.database.withTransaction
import no.iktdev.mediaprocessing.shared.common.database.cal.toEvent
import no.iktdev.mediaprocessing.shared.common.database.tables.events
import no.iktdev.mediaprocessing.ui.dto.DatabaseEntriesDelete
import no.iktdev.mediaprocessing.ui.dto.DatabaseEventEntries
import no.iktdev.mediaprocessing.ui.eventDatabase
import no.iktdev.mediaprocessing.ui.eventsManager
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.jetbrains.exposed.sql.and
import org.jetbrains.exposed.sql.deleteWhere
import org.jetbrains.exposed.sql.selectAll
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.messaging.handler.annotation.MessageMapping
import org.springframework.messaging.handler.annotation.Payload
import org.springframework.messaging.simp.SimpMessagingTemplate
import org.springframework.stereotype.Controller
@Controller
class DatabaseEntriesTopic(
@Autowired private val template: SimpMessagingTemplate?
) {
private fun push(destination: String, payload: Any) = template?.convertAndSend(destination, payload)
private fun push(payload: Any) = template?.convertAndSend(payload)
@MessageMapping("/database/events/pull")
fun pullAllDatabaseEvents() {
val result = withDirtyRead(eventDatabase.database) {
events.selectAll().toEvent()
.groupBy { it.referenceId() }.onEach { (t, u) ->
u.sortedBy { x -> x.metadata.created }
}
} ?: emptyMap()
result.map { it -> DatabaseEventEntries(
referenceId = it.key,
events = it.value,
created = it.value.first().metadata.created.toEpochSeconds() * 1000L,
lastEventCreated = it.value.last().metadata.created.toEpochSeconds() * 1000L
) }.also {
push(it)
}
}
@MessageMapping("/database/events/delete")
fun deleteEvent(@Payload payload: DatabaseEntriesDelete) {
val status = executeWithStatus (eventDatabase.database) {
events.deleteWhere {
(referenceId eq payload.referenceId) and
(eventId eq payload.eventId)
}
}
if (status) {
pullAllDatabaseEvents()
}
}
@MessageMapping("/database/tasks")
fun pullAllDatabaseTasks() {
}
}

View File

@ -5,7 +5,6 @@ import no.iktdev.eventi.data.referenceId
import no.iktdev.eventi.database.toEpochSeconds
import no.iktdev.eventi.database.withDirtyRead
import no.iktdev.eventi.database.withTransaction
import no.iktdev.mediaprocessing.shared.common.contract.Events
import no.iktdev.mediaprocessing.shared.common.contract.ProcessType
import no.iktdev.mediaprocessing.shared.common.contract.data.*
import no.iktdev.mediaprocessing.shared.common.contract.dto.OperationEvents
@ -19,6 +18,7 @@ import no.iktdev.mediaprocessing.shared.common.task.TaskType
import no.iktdev.mediaprocessing.ui.WebSocketMonitoringService
import no.iktdev.mediaprocessing.ui.eventDatabase
import no.iktdev.mediaprocessing.ui.socket.a2a.ProcesserListenerService
import no.iktdev.mediaprocessing.ui.socket.impl.SocketListener
import org.jetbrains.exposed.sql.selectAll
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.messaging.handler.annotation.MessageMapping
@ -85,6 +85,7 @@ class ProcesserTasksTopic(
val encode: Status = Status.Skipped,
val extract: Status = Status.Skipped,
val convert: Status = Status.Skipped,
val completed: Status = Status.Awaiting,
val created: Long
) {}

View File

@ -0,0 +1,35 @@
package no.iktdev.mediaprocessing.ui.socket
import no.iktdev.eventi.database.withTransaction
import no.iktdev.mediaprocessing.shared.common.database.cal.toTask
import no.iktdev.mediaprocessing.shared.common.database.tables.tasks
import no.iktdev.mediaprocessing.shared.common.task.Task
import no.iktdev.mediaprocessing.ui.eventDatabase
import no.iktdev.mediaprocessing.ui.socket.impl.SocketListener
import org.jetbrains.exposed.sql.selectAll
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.messaging.handler.annotation.MessageMapping
import org.springframework.messaging.simp.SimpMessagingTemplate
import org.springframework.stereotype.Service
@Service
class TaskTableTopic(
@Autowired private val message: SimpMessagingTemplate?,
) : SocketListener(message) {
data class TaskGroup(
val referenceId: String,
val tasks: List<Task>
)
@MessageMapping("/taskTable/all")
fun pullAllTasks() {
val result = withTransaction(eventDatabase.database) {
tasks.selectAll().toTask()
.groupBy { it.referenceId }.map { g -> TaskGroup(g.key, g.value) }
} ?: emptyList()
template?.convertAndSend("/topic/taskTable/all", result)
}
}

View File

@ -7,10 +7,9 @@ import no.iktdev.mediaprocessing.shared.common.task.Task
import no.iktdev.mediaprocessing.ui.UIEnv
import no.iktdev.mediaprocessing.ui.WebSocketMonitoringService
import no.iktdev.mediaprocessing.ui.log
import no.iktdev.mediaprocessing.ui.socket.SocketClient
import no.iktdev.mediaprocessing.ui.socket.SocketMessageHandler
import no.iktdev.mediaprocessing.ui.socket.impl.SocketClient
import no.iktdev.mediaprocessing.ui.socket.impl.SocketMessageHandler
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.messaging.simp.SimpMessagingTemplate
import org.springframework.stereotype.Service
@Service

View File

@ -1,4 +1,4 @@
package no.iktdev.mediaprocessing.ui.socket
package no.iktdev.mediaprocessing.ui.socket.impl
import mu.KotlinLogging
import org.springframework.messaging.simp.stomp.StompCommand

View File

@ -1,4 +1,4 @@
package no.iktdev.mediaprocessing.ui.socket
package no.iktdev.mediaprocessing.ui.socket.impl
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.messaging.simp.SimpMessagingTemplate

View File

@ -1,4 +1,4 @@
package no.iktdev.mediaprocessing.ui.socket
package no.iktdev.mediaprocessing.ui.socket.impl
import org.springframework.messaging.simp.stomp.StompHeaders
import org.springframework.messaging.simp.stomp.StompSessionHandlerAdapter

View File

@ -28,6 +28,7 @@ import InputIcon from '@mui/icons-material/Input';
import NotStartedIcon from '@mui/icons-material/NotStarted';
import EventsPage from './app/page/EventsPage';
import TableChartIcon from '@mui/icons-material/TableChart';
import SubscriptionsIcon from '@mui/icons-material/Subscriptions';
function App() {
const client = useStompClient();
@ -94,21 +95,22 @@ function App() {
}}>
<QueueIcon />
</IconButton>
<IconButton onClick={() => window.location.href = "/tasks"} sx={{
<IconButton onClick={() => window.location.href = "/events"} sx={{
...iconHeight
}}>
<TableChartIcon />
<SubscriptionsIcon />
</IconButton>
</Box>
<Box sx={{
display: "block",
maxHeight: window.screen.height - 70,
height: window.screen.height - 70,
maxHeight: window.innerHeight - 70,
height: window.innerHeight - 70,
width: "100vw",
maxWidth: "100vw"
}}>
<BrowserRouter>
<Routes>
<Route path='/events' element={<EventsPage />} />
<Route path='/processer' element={<EventsPage />} />
<Route path='/unprocessed' element={<UnprocessedFilesPage />} />
<Route path='/files' element={<ExplorePage />} />

View File

@ -4,3 +4,18 @@ export interface CoordinatorOperationRequest {
source: string;
mode: "FLOW" | "MANUAL";
}
export interface Event {
referenceId: string;
eventId: string;
event: string;
data: any;
created: number;
}
export interface DatabaseEventEntry {
referenceId: string;
events: Array<Event>
created: number;
lastEventCreated: number;
}

View File

@ -25,7 +25,7 @@ import SimpleTable from "../features/table/sortableTable";
import { UnixTimestamp } from "../features/UxTc";
import ProgressbarWithLabel from "../features/components/ProgressbarWithLabel";
import { LinearProgress, Typography } from "@mui/material";
import { stat } from "fs";
import SaveIcon from '@mui/icons-material/Save';
interface RawNodeDatum {
name: string;
@ -107,6 +107,10 @@ function renderCustomNodeElement(nodeData: CustomNodeElementProps): JSX.Element
workIcon = <AutoAwesomeMotionIcon />
break;
}
case "completed": {
workIcon = <SaveIcon />
break;
}
}
@ -163,6 +167,16 @@ const transformToSteps = (state: ContentEventState): RawNodeDatum => ({
type: "convert",
status: state.extract
},
children: [
{
name: state.referenceId,
attributes: {
type: "completed",
status: state.completed
},
children: []
}
]
}
]
},
@ -181,7 +195,7 @@ export default function EventsPage() {
const items = events.items.map((event: ContentEventState) => {
return {
rowId: event.referenceId,
title: event.referenceId,
title: event.title ?? event.referenceId,
item: event
} as ExpandableItemRow
});
@ -210,7 +224,7 @@ export default function EventsPage() {
return (<>
<div id="treeWrapper" style={{
...linkThicc,
width: '150px', height: '90px'
width: '200px', height: '90px'
}} ref={containerRef}>
<Tree
dimensions={dimensions}

View File

@ -43,6 +43,7 @@ export interface ContentEventState {
encode: Status
extract: Status
convert: Status
completed: Status
created: number
encodeWork: ProcesserEventInfo
}