minor adjustments
This commit is contained in:
parent
e663c743ab
commit
749194f9e1
@ -1,10 +1,20 @@
|
|||||||
package no.iktdev.mediaprocessing.ui.socket
|
package no.iktdev.mediaprocessing.ui.socket
|
||||||
|
|
||||||
|
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.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
|
||||||
import no.iktdev.mediaprocessing.shared.common.contract.dto.ProcesserEventInfo
|
import no.iktdev.mediaprocessing.shared.common.contract.dto.ProcesserEventInfo
|
||||||
|
import no.iktdev.mediaprocessing.shared.common.database.cal.toEvent
|
||||||
import no.iktdev.mediaprocessing.shared.common.database.cal.toTask
|
import no.iktdev.mediaprocessing.shared.common.database.cal.toTask
|
||||||
|
import no.iktdev.mediaprocessing.shared.common.database.tables.events
|
||||||
import no.iktdev.mediaprocessing.shared.common.database.tables.tasks
|
import no.iktdev.mediaprocessing.shared.common.database.tables.tasks
|
||||||
import no.iktdev.mediaprocessing.shared.common.task.Task
|
import no.iktdev.mediaprocessing.shared.common.task.Task
|
||||||
|
import no.iktdev.mediaprocessing.shared.common.task.TaskType
|
||||||
import no.iktdev.mediaprocessing.ui.WebSocketMonitoringService
|
import no.iktdev.mediaprocessing.ui.WebSocketMonitoringService
|
||||||
import no.iktdev.mediaprocessing.ui.eventDatabase
|
import no.iktdev.mediaprocessing.ui.eventDatabase
|
||||||
import no.iktdev.mediaprocessing.ui.socket.a2a.ProcesserListenerService
|
import no.iktdev.mediaprocessing.ui.socket.a2a.ProcesserListenerService
|
||||||
@ -13,25 +23,33 @@ import org.springframework.beans.factory.annotation.Autowired
|
|||||||
import org.springframework.messaging.handler.annotation.MessageMapping
|
import org.springframework.messaging.handler.annotation.MessageMapping
|
||||||
import org.springframework.messaging.simp.SimpMessagingTemplate
|
import org.springframework.messaging.simp.SimpMessagingTemplate
|
||||||
import org.springframework.stereotype.Service
|
import org.springframework.stereotype.Service
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
class ProcesserTasksTopic(
|
class ProcesserTasksTopic(
|
||||||
@Autowired a2AProcesserService: ProcesserListenerService,
|
@Autowired a2AProcesserService: ProcesserListenerService,
|
||||||
@Autowired private val webSocketMonitoringService: WebSocketMonitoringService,
|
@Autowired private val webSocketMonitoringService: WebSocketMonitoringService,
|
||||||
@Autowired override var template: SimpMessagingTemplate?,
|
@Autowired private val message: SimpMessagingTemplate?,
|
||||||
): SocketListener(template) {
|
): SocketListener(message) {
|
||||||
|
|
||||||
|
|
||||||
final val a2a = object : ProcesserListenerService.A2AProcesserListener {
|
final val a2a = object : ProcesserListenerService.A2AProcesserListener {
|
||||||
override fun onExtractProgress(info: ProcesserEventInfo) {
|
override fun onExtractProgress(info: ProcesserEventInfo) {
|
||||||
|
message?.convertAndSend("/topic/processer/extract/progress", info)
|
||||||
|
pullAllTasks()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onEncodeProgress(info: ProcesserEventInfo) {
|
override fun onEncodeProgress(info: ProcesserEventInfo) {
|
||||||
|
message?.convertAndSend("/topic/processer/encode/progress", info)
|
||||||
|
pullAllTasks()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onEncodeAssigned() {
|
override fun onEncodeAssigned() {
|
||||||
|
pullAllTasks()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onExtractAssigned() {
|
override fun onExtractAssigned() {
|
||||||
|
pullAllTasks()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,18 +57,96 @@ class ProcesserTasksTopic(
|
|||||||
a2AProcesserService.attachListener(a2a)
|
a2AProcesserService.attachListener(a2a)
|
||||||
}
|
}
|
||||||
|
|
||||||
data class TaskGroup(
|
enum class Status {
|
||||||
|
Skipped,
|
||||||
|
Awaiting, // Waiting for tasks to be created
|
||||||
|
NeedsApproval,
|
||||||
|
Pending,
|
||||||
|
InProgress,
|
||||||
|
Completed,
|
||||||
|
Failed,
|
||||||
|
}
|
||||||
|
|
||||||
|
data class ContentEventState(
|
||||||
val referenceId: String,
|
val referenceId: String,
|
||||||
val tasks: List<Task>
|
val title: String,
|
||||||
)
|
val encode: Status = Status.Skipped,
|
||||||
|
val extract: Status = Status.Skipped,
|
||||||
|
val convert: Status = Status.Skipped,
|
||||||
|
val created: Long
|
||||||
|
) {}
|
||||||
|
|
||||||
|
|
||||||
@MessageMapping("/tasks/all")
|
@MessageMapping("/tasks/all")
|
||||||
fun pullAllTasks() {
|
fun pullAllTaskss() {
|
||||||
|
val states = update()
|
||||||
|
template?.convertAndSend("/topic/tasks/all", states)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getOperationState(tasks: List<Task>, hasOperation: Boolean, canStart: Boolean): Status {
|
||||||
|
if (!hasOperation) return Status.Skipped
|
||||||
|
if (tasks.isEmpty()) return Status.Awaiting
|
||||||
|
|
||||||
|
if (!canStart) return Status.NeedsApproval
|
||||||
|
|
||||||
|
if (tasks.any { it.consumed }) {
|
||||||
|
return Status.Completed
|
||||||
|
}
|
||||||
|
if (tasks.any { it.claimed }) {
|
||||||
|
return Status.InProgress
|
||||||
|
}
|
||||||
|
if (tasks.any{ it.status == "ERROR"}) {
|
||||||
|
return Status.Failed
|
||||||
|
}
|
||||||
|
return Status.Pending
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun update(): MutableList<ContentEventState> {
|
||||||
|
val eventStates: MutableList<ContentEventState> = mutableListOf()
|
||||||
|
|
||||||
|
val tasks = pullAllTasks()
|
||||||
|
val availableEvents = pullAllEvents()
|
||||||
|
|
||||||
|
for ((referenceId, events) in availableEvents) {
|
||||||
|
val startEvent = events.findFirstEventOf<MediaProcessStartEvent>() ?: continue
|
||||||
|
val startData = startEvent.data ?: continue
|
||||||
|
val title = events.findFirstEventOf<BaseInfoEvent>()?.data?.sanitizedName ?: startData.file.let { File(it).nameWithoutExtension }
|
||||||
|
val canStart = if (startData.type == ProcessType.FLOW) true else {
|
||||||
|
events.findEventsOf<PermitWorkCreationEvent>().isNotEmpty()
|
||||||
|
}
|
||||||
|
val tasksCreated = tasks[referenceId]
|
||||||
|
val encode = tasksCreated?.filter { it.task == TaskType.Encode } ?: emptyList()
|
||||||
|
val extract = tasksCreated?.filter { it.task == TaskType.Extract } ?: emptyList()
|
||||||
|
val convert = tasksCreated?.filter { it.task == TaskType.Convert } ?: emptyList()
|
||||||
|
|
||||||
|
eventStates.add(ContentEventState(
|
||||||
|
title = title,
|
||||||
|
referenceId = referenceId,
|
||||||
|
encode = getOperationState(encode, startData.operations.contains(OperationEvents.ENCODE), canStart),
|
||||||
|
extract = getOperationState(extract, startData.operations.contains(OperationEvents.EXTRACT), canStart),
|
||||||
|
convert = getOperationState(convert, startData.operations.contains(OperationEvents.CONVERT), canStart),
|
||||||
|
created = startEvent.metadata.created.toEpochSeconds() * 1000L
|
||||||
|
))
|
||||||
|
}
|
||||||
|
return eventStates
|
||||||
|
}
|
||||||
|
|
||||||
|
fun pullAllTasks(): Map<String, List<Task>> {
|
||||||
val result = withTransaction(eventDatabase.database) {
|
val result = withTransaction(eventDatabase.database) {
|
||||||
tasks.selectAll().toTask()
|
tasks.selectAll().toTask()
|
||||||
.groupBy { it.referenceId }.map { g -> TaskGroup(g.key, g.value) }
|
.groupBy { it.referenceId }
|
||||||
} ?: emptyList()
|
} ?: emptyMap()
|
||||||
template?.convertAndSend("/topic/tasks/all", result)
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
fun pullAllEvents(): Map<String, List<Event>> {
|
||||||
|
val result = withDirtyRead(eventDatabase.database) {
|
||||||
|
events.selectAll().toEvent()
|
||||||
|
.groupBy { it.referenceId() }
|
||||||
|
} ?: emptyMap()
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -68,7 +68,7 @@ class UnprocessedFilesTopic(
|
|||||||
FileInfo(
|
FileInfo(
|
||||||
it[files.baseName],
|
it[files.baseName],
|
||||||
it[files.fileName],
|
it[files.fileName],
|
||||||
it[files.checksum]
|
it[files.checksum],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
unprocessedFiles = found
|
unprocessedFiles = found
|
||||||
|
|||||||
@ -15,7 +15,6 @@ import org.springframework.stereotype.Service
|
|||||||
@Service
|
@Service
|
||||||
class ProcesserListenerService(
|
class ProcesserListenerService(
|
||||||
@Autowired private val webSocketMonitoringService: WebSocketMonitoringService,
|
@Autowired private val webSocketMonitoringService: WebSocketMonitoringService,
|
||||||
@Autowired private val message: SimpMessagingTemplate?,
|
|
||||||
) {
|
) {
|
||||||
private val logger = KotlinLogging.logger {}
|
private val logger = KotlinLogging.logger {}
|
||||||
private val listeners: MutableList<A2AProcesserListener> = mutableListOf()
|
private val listeners: MutableList<A2AProcesserListener> = mutableListOf()
|
||||||
@ -50,9 +49,11 @@ class ProcesserListenerService(
|
|||||||
private val encodeProcessMessage = object : SocketMessageHandler() {
|
private val encodeProcessMessage = object : SocketMessageHandler() {
|
||||||
override fun onMessage(socketMessage: String) {
|
override fun onMessage(socketMessage: String) {
|
||||||
super.onMessage(socketMessage)
|
super.onMessage(socketMessage)
|
||||||
message?.convertAndSend("/topic/processer/encode/progress", socketMessage)
|
|
||||||
val response = gson.fromJson(socketMessage, ProcesserEventInfo::class.java)
|
val response = gson.fromJson(socketMessage, ProcesserEventInfo::class.java)
|
||||||
if (webSocketMonitoringService.anyListening()) {
|
listeners.forEach { listener ->
|
||||||
|
run {
|
||||||
|
listener.onEncodeProgress(response)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -61,11 +62,14 @@ class ProcesserListenerService(
|
|||||||
private val extractProcessFrameHandler = object : SocketMessageHandler() {
|
private val extractProcessFrameHandler = object : SocketMessageHandler() {
|
||||||
override fun onMessage(socketMessage: String) {
|
override fun onMessage(socketMessage: String) {
|
||||||
super.onMessage(socketMessage)
|
super.onMessage(socketMessage)
|
||||||
message?.convertAndSend("/topic/processer/extract/progress", socketMessage)
|
|
||||||
if (webSocketMonitoringService.anyListening()) {
|
if (webSocketMonitoringService.anyListening()) {
|
||||||
}
|
}
|
||||||
//val stringPayload = (if (payload is ByteArray) String(payload) else payload as String)
|
val response = gson.fromJson(socketMessage, ProcesserEventInfo::class.java)
|
||||||
//val response = gson.fromJson(stringPayload, ProcesserEventInfo::class.java)
|
listeners.forEach { listener ->
|
||||||
|
run {
|
||||||
|
listener.onEncodeProgress(response)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
63
apps/ui/web/package-lock.json
generated
63
apps/ui/web/package-lock.json
generated
@ -574,13 +574,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/helpers": {
|
"node_modules/@babel/helpers": {
|
||||||
"version": "7.22.6",
|
"version": "7.26.10",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.6.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.10.tgz",
|
||||||
"integrity": "sha512-YjDs6y/fVOYFV8hAf1rxd1QvR9wJe1pDBZ2AREKq/SDayfPzgk0PBnVuTCE5X1acEpMMNOVUqoe+OwiZGJ+OaA==",
|
"integrity": "sha512-UPYc3SauzZ3JGgj87GgZ89JVdC5dj0AoetR5Bw6wj4niittNyFh6+eOGonYvJ1ao6B8lEa3Q3klS7ADZ53bc5g==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/template": "^7.22.5",
|
"@babel/template": "^7.26.9",
|
||||||
"@babel/traverse": "^7.22.6",
|
"@babel/types": "^7.26.10"
|
||||||
"@babel/types": "^7.22.5"
|
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
@ -2085,9 +2085,10 @@
|
|||||||
"integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA=="
|
"integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA=="
|
||||||
},
|
},
|
||||||
"node_modules/@babel/runtime": {
|
"node_modules/@babel/runtime": {
|
||||||
"version": "7.25.0",
|
"version": "7.26.10",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.0.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.10.tgz",
|
||||||
"integrity": "sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw==",
|
"integrity": "sha512-2WJMeRQPHKSPemqk/awGrAiuFfzBmOIPXKizAsVhWH9YJqLZ0H+HS4c8loHGgW6utJ3E/ejXQUsiGaQy2NZ9Fw==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"regenerator-runtime": "^0.14.0"
|
"regenerator-runtime": "^0.14.0"
|
||||||
},
|
},
|
||||||
@ -2133,9 +2134,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/types": {
|
"node_modules/@babel/types": {
|
||||||
"version": "7.26.9",
|
"version": "7.26.10",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.9.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.10.tgz",
|
||||||
"integrity": "sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw==",
|
"integrity": "sha512-emqcG3vHrpxUKTrxcblR36dcrcoRDvKmnL/dCL6ZsHaShW80qxCAcNhzQZrpeM765VzEos+xOi4s+r4IXzTwdQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-string-parser": "^7.25.9",
|
"@babel/helper-string-parser": "^7.25.9",
|
||||||
@ -18009,11 +18010,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/use-sync-external-store": {
|
"node_modules/use-sync-external-store": {
|
||||||
"version": "1.2.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.4.0.tgz",
|
||||||
"integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
|
"integrity": "sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw==",
|
||||||
|
"license": "MIT",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/utf-8-validate": {
|
"node_modules/utf-8-validate": {
|
||||||
@ -19510,13 +19512,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@babel/helpers": {
|
"@babel/helpers": {
|
||||||
"version": "7.22.6",
|
"version": "7.26.10",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.6.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.10.tgz",
|
||||||
"integrity": "sha512-YjDs6y/fVOYFV8hAf1rxd1QvR9wJe1pDBZ2AREKq/SDayfPzgk0PBnVuTCE5X1acEpMMNOVUqoe+OwiZGJ+OaA==",
|
"integrity": "sha512-UPYc3SauzZ3JGgj87GgZ89JVdC5dj0AoetR5Bw6wj4niittNyFh6+eOGonYvJ1ao6B8lEa3Q3klS7ADZ53bc5g==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/template": "^7.22.5",
|
"@babel/template": "^7.26.9",
|
||||||
"@babel/traverse": "^7.22.6",
|
"@babel/types": "^7.26.10"
|
||||||
"@babel/types": "^7.22.5"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@babel/parser": {
|
"@babel/parser": {
|
||||||
@ -20481,9 +20482,9 @@
|
|||||||
"integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA=="
|
"integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA=="
|
||||||
},
|
},
|
||||||
"@babel/runtime": {
|
"@babel/runtime": {
|
||||||
"version": "7.25.0",
|
"version": "7.26.10",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.0.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.10.tgz",
|
||||||
"integrity": "sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw==",
|
"integrity": "sha512-2WJMeRQPHKSPemqk/awGrAiuFfzBmOIPXKizAsVhWH9YJqLZ0H+HS4c8loHGgW6utJ3E/ejXQUsiGaQy2NZ9Fw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"regenerator-runtime": "^0.14.0"
|
"regenerator-runtime": "^0.14.0"
|
||||||
},
|
},
|
||||||
@ -20520,9 +20521,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@babel/types": {
|
"@babel/types": {
|
||||||
"version": "7.26.9",
|
"version": "7.26.10",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.9.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.10.tgz",
|
||||||
"integrity": "sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw==",
|
"integrity": "sha512-emqcG3vHrpxUKTrxcblR36dcrcoRDvKmnL/dCL6ZsHaShW80qxCAcNhzQZrpeM765VzEos+xOi4s+r4IXzTwdQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/helper-string-parser": "^7.25.9",
|
"@babel/helper-string-parser": "^7.25.9",
|
||||||
"@babel/helper-validator-identifier": "^7.25.9"
|
"@babel/helper-validator-identifier": "^7.25.9"
|
||||||
@ -31684,9 +31685,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"use-sync-external-store": {
|
"use-sync-external-store": {
|
||||||
"version": "1.2.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.4.0.tgz",
|
||||||
"integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
|
"integrity": "sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw==",
|
||||||
"requires": {}
|
"requires": {}
|
||||||
},
|
},
|
||||||
"utf-8-validate": {
|
"utf-8-validate": {
|
||||||
|
|||||||
@ -12,7 +12,6 @@ import { updateItems } from './app/store/composed-slice';
|
|||||||
import ExplorePage from './app/page/ExplorePage';
|
import ExplorePage from './app/page/ExplorePage';
|
||||||
import { ThemeProvider } from '@mui/material';
|
import { ThemeProvider } from '@mui/material';
|
||||||
import theme from './theme';
|
import theme from './theme';
|
||||||
import { simpleEventsUpdate } from './app/store/kafka-items-flat-slice';
|
|
||||||
import { EventDataObject, SimpleEventDataObject } from './types';
|
import { EventDataObject, SimpleEventDataObject } from './types';
|
||||||
import EventsChainPage from './app/page/EventsChainPage';
|
import EventsChainPage from './app/page/EventsChainPage';
|
||||||
import UnprocessedFilesPage from './app/page/UnprocessedFilesPage';
|
import UnprocessedFilesPage from './app/page/UnprocessedFilesPage';
|
||||||
@ -22,6 +21,14 @@ import QueueIcon from '@mui/icons-material/Queue';
|
|||||||
import AppsIcon from '@mui/icons-material/Apps';
|
import AppsIcon from '@mui/icons-material/Apps';
|
||||||
import ConstructionIcon from '@mui/icons-material/Construction';
|
import ConstructionIcon from '@mui/icons-material/Construction';
|
||||||
import ProcesserTasksPage from './app/page/ProcesserTasksPage';
|
import ProcesserTasksPage from './app/page/ProcesserTasksPage';
|
||||||
|
import DashboardIcon from '@mui/icons-material/Dashboard';
|
||||||
|
import GraphicEqIcon from '@mui/icons-material/GraphicEq';
|
||||||
|
import HomeRepairServiceIcon from '@mui/icons-material/HomeRepairService';
|
||||||
|
import InboxIcon from '@mui/icons-material/Inbox';
|
||||||
|
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';
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const client = useStompClient();
|
const client = useStompClient();
|
||||||
@ -31,9 +38,6 @@ function App() {
|
|||||||
dispatch(updateItems(response))
|
dispatch(updateItems(response))
|
||||||
});
|
});
|
||||||
|
|
||||||
useWsSubscription<Array<SimpleEventDataObject>>("/topic/event/flat", (response) => {
|
|
||||||
dispatch(simpleEventsUpdate(response))
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -71,7 +75,12 @@ function App() {
|
|||||||
}}>
|
}}>
|
||||||
<AppsIcon />
|
<AppsIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
<IconButton onClick={() => window.location.href = "/events"} sx={{
|
<IconButton onClick={() => window.location.href = "/processer"} sx={{
|
||||||
|
...iconHeight
|
||||||
|
}}>
|
||||||
|
<GraphicEqIcon />
|
||||||
|
</IconButton>
|
||||||
|
<IconButton onClick={() => window.location.href = "/eventsflow"} sx={{
|
||||||
...iconHeight
|
...iconHeight
|
||||||
}}>
|
}}>
|
||||||
<AccountTreeIcon />
|
<AccountTreeIcon />
|
||||||
@ -89,7 +98,7 @@ function App() {
|
|||||||
<IconButton onClick={() => window.location.href = "/tasks"} sx={{
|
<IconButton onClick={() => window.location.href = "/tasks"} sx={{
|
||||||
...iconHeight
|
...iconHeight
|
||||||
}}>
|
}}>
|
||||||
<ConstructionIcon />
|
<TableChartIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Box>
|
</Box>
|
||||||
<Box sx={{
|
<Box sx={{
|
||||||
@ -102,9 +111,10 @@ function App() {
|
|||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path='/tasks' element={<ProcesserTasksPage />} />
|
<Route path='/tasks' element={<ProcesserTasksPage />} />
|
||||||
|
<Route path='/processer' element={<EventsPage />} />
|
||||||
<Route path='/unprocessed' element={<UnprocessedFilesPage />} />
|
<Route path='/unprocessed' element={<UnprocessedFilesPage />} />
|
||||||
<Route path='/files' element={<ExplorePage />} />
|
<Route path='/files' element={<ExplorePage />} />
|
||||||
<Route path='/events' element={<EventsChainPage />} />
|
<Route path='/eventsflow' element={<EventsChainPage />} />
|
||||||
<Route path='/' element={<LaunchPage />} />
|
<Route path='/' element={<LaunchPage />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
<Footer />
|
<Footer />
|
||||||
|
|||||||
@ -10,16 +10,31 @@ export interface ExpandableItem<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type ExpandableRender<T> = (item: T) => ExpandableItem<T> | null;
|
export type ExpandableRender<T> = (item: T) => ExpandableItem<T> | null;
|
||||||
|
export interface ExpandableTableItem {
|
||||||
|
rowId: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function ExpandableTable<T extends ExpandableTableItem>({ items, columns, cellCustomizer: customizer, expandableRender, onRowClickedEvent }: { items: Array<T>, columns: Array<TablePropetyConfig>, cellCustomizer?: TableCellCustomizer<T>, expandableRender: ExpandableRender<T>, onRowClickedEvent?: TableRowActionEvents<T> }) {
|
||||||
export default function ExpandableTable<T>({ items, columns, cellCustomizer: customizer, expandableRender, onRowClickedEvent }: { items: Array<T>, columns: Array<TablePropetyConfig>, cellCustomizer?: TableCellCustomizer<T>, expandableRender: ExpandableRender<T>, onRowClickedEvent?: TableRowActionEvents<T> }) {
|
|
||||||
const muiTheme = useTheme();
|
const muiTheme = useTheme();
|
||||||
|
|
||||||
const [order, setOrder] = useState<'asc' | 'desc'>('asc');
|
const [order, setOrder] = useState<'asc' | 'desc'>('asc');
|
||||||
const [orderBy, setOrderBy] = useState<string>('');
|
const [orderBy, setOrderBy] = useState<string>('');
|
||||||
|
const [expandedRowIds, setExpandedRowIds] = useState<Set<string>>(new Set());
|
||||||
const [selectedRow, setSelectedRow] = useState<T | null>(null);
|
const [selectedRow, setSelectedRow] = useState<T | null>(null);
|
||||||
|
|
||||||
const tableRowSingleClicked = (row: T | null) => {
|
const tableRowSingleClicked = (row: T | null) => {
|
||||||
|
if (row != null && 'rowId' in row) {
|
||||||
|
setExpandedRowIds(prev => {
|
||||||
|
const newExpandedRows = new Set(prev);
|
||||||
|
if (newExpandedRows.has(row.rowId)) {
|
||||||
|
newExpandedRows.delete(row.rowId);
|
||||||
|
} else {
|
||||||
|
newExpandedRows.add(row.rowId);
|
||||||
|
}
|
||||||
|
return newExpandedRows;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
if (row === selectedRow) {
|
if (row === selectedRow) {
|
||||||
setSelectedRow(null);
|
setSelectedRow(null);
|
||||||
} else {
|
} else {
|
||||||
@ -28,6 +43,7 @@ export default function ExpandableTable<T>({ items, columns, cellCustomizer: cus
|
|||||||
onRowClickedEvent.click(row);
|
onRowClickedEvent.click(row);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
const tableRowDoubleClicked = (row: T | null) => {
|
const tableRowDoubleClicked = (row: T | null) => {
|
||||||
setSelectedRow(row);
|
setSelectedRow(row);
|
||||||
@ -127,7 +143,7 @@ export default function ExpandableTable<T>({ items, columns, cellCustomizer: cus
|
|||||||
</TableCell>
|
</TableCell>
|
||||||
))}
|
))}
|
||||||
</TableRow>
|
</TableRow>
|
||||||
{(selectedRow == row) ?
|
{(expandedRowIds.has(row.rowId)) ?
|
||||||
(<TableRow key={rowIndex + "_1"}>
|
(<TableRow key={rowIndex + "_1"}>
|
||||||
<TableCell colSpan={columns.length}>
|
<TableCell colSpan={columns.length}>
|
||||||
{
|
{
|
||||||
|
|||||||
@ -59,12 +59,10 @@ export default function EventsChainPage() {
|
|||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (Object.keys(cursor).length === 0) {
|
|
||||||
client?.publish({
|
client?.publish({
|
||||||
destination: "/app/chained/all"
|
destination: "/app/chained/all"
|
||||||
});
|
});
|
||||||
}
|
}, [client, dispatch]);
|
||||||
}, [cursor, client, dispatch]);
|
|
||||||
|
|
||||||
const onRefresh = () => {
|
const onRefresh = () => {
|
||||||
client?.publish({
|
client?.publish({
|
||||||
|
|||||||
@ -16,6 +16,7 @@ import ContextMenu, { ContextMenuActionEvent, ContextMenuItem } from '../feature
|
|||||||
import { canConvert, canEncode, canExtract } from '../../fileUtil';
|
import { canConvert, canEncode, canExtract } from '../../fileUtil';
|
||||||
import SimpleTable from '../features/table/sortableTable';
|
import SimpleTable from '../features/table/sortableTable';
|
||||||
import TagIcon from '@mui/icons-material/Tag';
|
import TagIcon from '@mui/icons-material/Tag';
|
||||||
|
import { CoordinatorOperationRequest } from '../features/types';
|
||||||
|
|
||||||
|
|
||||||
const createTableCell: TableCellCustomizer<ExplorerItem> = (accessor, data) => {
|
const createTableCell: TableCellCustomizer<ExplorerItem> = (accessor, data) => {
|
||||||
@ -195,13 +196,6 @@ function getContextMenuFileActionMenuItems(row: ExplorerItem | null): ContextMen
|
|||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ExplorerOperationRequest {
|
|
||||||
destination: string;
|
|
||||||
file: string;
|
|
||||||
source: string;
|
|
||||||
mode: "FLOW" | "MANUAL";
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function ExplorePage() {
|
export default function ExplorePage() {
|
||||||
const muiTheme = useTheme();
|
const muiTheme = useTheme();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
@ -254,7 +248,7 @@ export default function ExplorePage() {
|
|||||||
file: value.path,
|
file: value.path,
|
||||||
source: `Web UI @ ${window.location.href}`,
|
source: `Web UI @ ${window.location.href}`,
|
||||||
mode: "FLOW"
|
mode: "FLOW"
|
||||||
} as ExplorerOperationRequest
|
} as CoordinatorOperationRequest
|
||||||
}
|
}
|
||||||
case 1: {
|
case 1: {
|
||||||
return {
|
return {
|
||||||
@ -262,7 +256,7 @@ export default function ExplorePage() {
|
|||||||
file: value.path,
|
file: value.path,
|
||||||
source: `Web UI @ ${window.location.href}`,
|
source: `Web UI @ ${window.location.href}`,
|
||||||
mode: "FLOW"
|
mode: "FLOW"
|
||||||
} as ExplorerOperationRequest
|
} as CoordinatorOperationRequest
|
||||||
}
|
}
|
||||||
case 2: {
|
case 2: {
|
||||||
return {
|
return {
|
||||||
@ -270,7 +264,7 @@ export default function ExplorePage() {
|
|||||||
file: value.path,
|
file: value.path,
|
||||||
source: `Web UI @ ${window.location.href}`,
|
source: `Web UI @ ${window.location.href}`,
|
||||||
mode: "FLOW"
|
mode: "FLOW"
|
||||||
} as ExplorerOperationRequest
|
} as CoordinatorOperationRequest
|
||||||
}
|
}
|
||||||
case 3: {
|
case 3: {
|
||||||
return {
|
return {
|
||||||
@ -278,7 +272,7 @@ export default function ExplorePage() {
|
|||||||
file: value.path,
|
file: value.path,
|
||||||
source: `Web UI @ ${window.location.href}`,
|
source: `Web UI @ ${window.location.href}`,
|
||||||
mode: "FLOW"
|
mode: "FLOW"
|
||||||
} as ExplorerOperationRequest
|
} as CoordinatorOperationRequest
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@ -22,15 +22,14 @@ export default function LaunchPage() {
|
|||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const muiTheme = useTheme();
|
const muiTheme = useTheme();
|
||||||
const client = useStompClient();
|
const client = useStompClient();
|
||||||
const simpleList = useSelector((state: RootState) => state.kafkaComposedFlat)
|
/*useEffect(() => {
|
||||||
useEffect(() => {
|
|
||||||
if (simpleList.items.filter((item) => item.encodingTimeLeft !== null).length > 0) {
|
if (simpleList.items.filter((item) => item.encodingTimeLeft !== null).length > 0) {
|
||||||
columns.push({
|
columns.push({
|
||||||
label: "Completion",
|
label: "Completion",
|
||||||
accessor: "encodingTimeLeft"
|
accessor: "encodingTimeLeft"
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}, [simpleList, dispatch])
|
}, [simpleList, dispatch])*/
|
||||||
|
|
||||||
const onRefresh = () => {
|
const onRefresh = () => {
|
||||||
client?.publish({
|
client?.publish({
|
||||||
@ -82,7 +81,6 @@ export default function LaunchPage() {
|
|||||||
position: "absolute",
|
position: "absolute",
|
||||||
width: "100%"
|
width: "100%"
|
||||||
}}>
|
}}>
|
||||||
<SimpleTable items={simpleList.items} columns={columns} />
|
|
||||||
|
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@ -3,13 +3,16 @@ import { useDispatch, useSelector } from "react-redux";
|
|||||||
import { useStompClient } from "react-stomp-hooks";
|
import { useStompClient } from "react-stomp-hooks";
|
||||||
import { Box, Button, Grid, TextField, Typography, useTheme } from '@mui/material';
|
import { Box, Button, Grid, TextField, Typography, useTheme } from '@mui/material';
|
||||||
import { ExplorerItem } from "../../types";
|
import { ExplorerItem } from "../../types";
|
||||||
import { ContextMenuItem } from "../features/ContextMenu";
|
import ContextMenu, { ContextMenuActionEvent, ContextMenuItem } from "../features/ContextMenu";
|
||||||
import { RootState } from "../store";
|
import { RootState } from "../store";
|
||||||
import { useWsSubscription } from "../ws/subscriptions";
|
import { useWsSubscription } from "../ws/subscriptions";
|
||||||
import { FileInfo, FileInfoGroup, IncomingUnprocessedFiles, update, } from "../store/unprocessed-files-slice";
|
import { FileInfo, FileInfoGroup, IncomingUnprocessedFiles, update, } from "../store/unprocessed-files-slice";
|
||||||
import SimpleTable from "../features/table/sortableTable";
|
import SimpleTable from "../features/table/sortableTable";
|
||||||
import { TablePropetyConfig } from "../features/table/table";
|
import { TablePropetyConfig, TableRowActionEvents } from "../features/table/table";
|
||||||
import MultiListSortedTable from "../features/table/multiListSortedTable";
|
import MultiListSortedTable from "../features/table/multiListSortedTable";
|
||||||
|
import { setContextMenuVisible, setContextMenuPosition } from "../store/context-menu-slice";
|
||||||
|
import { canConvert, canEncode, canExtract } from "../../fileUtil";
|
||||||
|
import { CoordinatorOperationRequest } from "../features/types";
|
||||||
|
|
||||||
|
|
||||||
const columns: Array<TablePropetyConfig> = [
|
const columns: Array<TablePropetyConfig> = [
|
||||||
@ -24,7 +27,7 @@ export default function UnprocessedFilesPage() {
|
|||||||
const files = useSelector((state: RootState) => state.unprocessedFiles);
|
const files = useSelector((state: RootState) => state.unprocessedFiles);
|
||||||
const [tableItems, setTableItems] = useState<Array<FileInfoGroup>>([]);
|
const [tableItems, setTableItems] = useState<Array<FileInfoGroup>>([]);
|
||||||
|
|
||||||
const [selectedRow, setSelectedRow] = useState<ExplorerItem|null>(null);
|
const [selectedRow, setSelectedRow] = useState<FileInfo|null>(null);
|
||||||
const [actionableItems, setActionableItems] = useState<Array<ContextMenuItem>>([]);
|
const [actionableItems, setActionableItems] = useState<Array<ContextMenuItem>>([]);
|
||||||
|
|
||||||
useWsSubscription<IncomingUnprocessedFiles>("/topic/files/unprocessed", (response) => {
|
useWsSubscription<IncomingUnprocessedFiles>("/topic/files/unprocessed", (response) => {
|
||||||
@ -32,6 +35,87 @@ export default function UnprocessedFilesPage() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
const onItemSelectedEvent: TableRowActionEvents<FileInfo> = {
|
||||||
|
contextMenu: (row: FileInfo, x: number, y: number) => {
|
||||||
|
dispatch(setContextMenuVisible(true));
|
||||||
|
dispatch(setContextMenuPosition({ x: x, y: y }));
|
||||||
|
setActionableItems(getContextMenuFileActionMenuItems(row));
|
||||||
|
},
|
||||||
|
click: function (row: FileInfo): void {
|
||||||
|
},
|
||||||
|
doubleClick: function (row: FileInfo): void {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function getContextMenuFileActionMenuItems(row: FileInfo | null): ContextMenuItem[] {
|
||||||
|
const items: Array<ContextMenuItem> = [
|
||||||
|
{
|
||||||
|
actionIndex: 0,
|
||||||
|
icon: null,
|
||||||
|
text: "All available"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
actionIndex: 1,
|
||||||
|
icon: null,
|
||||||
|
text: "Encode"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
actionIndex: 2,
|
||||||
|
icon: null,
|
||||||
|
text: "Extract"
|
||||||
|
}
|
||||||
|
|
||||||
|
];
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const onContextMenuItemClickedEvent: ContextMenuActionEvent<FileInfo> = {
|
||||||
|
selected: function (actionIndex: number | null, value: FileInfo | null): void {
|
||||||
|
if (!value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const payload = (() => {
|
||||||
|
switch(actionIndex) {
|
||||||
|
case 0: {
|
||||||
|
return {
|
||||||
|
destination: "request/all",
|
||||||
|
file: value.fileName,
|
||||||
|
source: `Web UI @ ${window.location.href}`,
|
||||||
|
mode: "FLOW"
|
||||||
|
} as CoordinatorOperationRequest
|
||||||
|
}
|
||||||
|
case 1: {
|
||||||
|
return {
|
||||||
|
destination: "request/encode",
|
||||||
|
file: value.fileName,
|
||||||
|
source: `Web UI @ ${window.location.href}`,
|
||||||
|
mode: "FLOW"
|
||||||
|
} as CoordinatorOperationRequest
|
||||||
|
}
|
||||||
|
case 2: {
|
||||||
|
return {
|
||||||
|
destination: "request/extract",
|
||||||
|
file: value.fileName,
|
||||||
|
source: `Web UI @ ${window.location.href}`,
|
||||||
|
mode: "FLOW"
|
||||||
|
} as CoordinatorOperationRequest
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
if (payload) {
|
||||||
|
client?.publish({
|
||||||
|
destination: "/app/"+payload.destination,
|
||||||
|
body: JSON.stringify(payload)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const pullData = () => {
|
const pullData = () => {
|
||||||
client?.publish({
|
client?.publish({
|
||||||
destination: "/app/files/unprocessed"
|
destination: "/app/files/unprocessed"
|
||||||
@ -99,9 +183,10 @@ export default function UnprocessedFilesPage() {
|
|||||||
position: "absolute",
|
position: "absolute",
|
||||||
width: "100%"
|
width: "100%"
|
||||||
}}>
|
}}>
|
||||||
<MultiListSortedTable items={tableItems ?? []} columns={columns} />
|
<MultiListSortedTable items={tableItems ?? []} columns={columns} onRowClickedEvent={onItemSelectedEvent} />
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
<ContextMenu row={selectedRow} actionItems={actionableItems} onContextMenuItemClicked={onContextMenuItemClickedEvent} />
|
||||||
|
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -1,24 +1,23 @@
|
|||||||
import { configureStore, ThunkAction, Action } from '@reduxjs/toolkit';
|
import { configureStore, ThunkAction, Action } from '@reduxjs/toolkit';
|
||||||
import composedSlice from './store/composed-slice';
|
import composedSlice from './store/composed-slice';
|
||||||
import explorerSlice from './store/explorer-slice';
|
import explorerSlice from './store/explorer-slice';
|
||||||
import kafkaItemsFlatSlice from './store/kafka-items-flat-slice';
|
|
||||||
import contextMenuSlice from './store/context-menu-slice';
|
import contextMenuSlice from './store/context-menu-slice';
|
||||||
import persistentEventsSlice from './store/persistent-events-slice';
|
import persistentEventsSlice from './store/persistent-events-slice';
|
||||||
import chainedEventsSlice from './store/chained-events-slice';
|
import chainedEventsSlice from './store/chained-events-slice';
|
||||||
import unprocessedFilesSlice from './store/unprocessed-files-slice';
|
import unprocessedFilesSlice from './store/unprocessed-files-slice';
|
||||||
import tasksSlice from './store/tasks-slice';
|
import tasksSlice from './store/tasks-slice';
|
||||||
|
import workSlice from './store/work-slice';
|
||||||
|
|
||||||
export const store = configureStore({
|
export const store = configureStore({
|
||||||
reducer: {
|
reducer: {
|
||||||
composed: composedSlice,
|
composed: composedSlice,
|
||||||
explorer: explorerSlice,
|
explorer: explorerSlice,
|
||||||
kafkaComposedFlat: kafkaItemsFlatSlice,
|
|
||||||
contextMenu: contextMenuSlice,
|
contextMenu: contextMenuSlice,
|
||||||
persistentEvents: persistentEventsSlice,
|
persistentEvents: persistentEventsSlice,
|
||||||
chained: chainedEventsSlice,
|
chained: chainedEventsSlice,
|
||||||
unprocessedFiles: unprocessedFilesSlice,
|
unprocessedFiles: unprocessedFilesSlice,
|
||||||
tasks: tasksSlice,
|
tasks: tasksSlice,
|
||||||
|
work: workSlice
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { createSlice, PayloadAction } from "@reduxjs/toolkit"
|
import { createSlice, PayloadAction } from "@reduxjs/toolkit"
|
||||||
|
import { ExpandableTableItem } from "../features/table/expandableTable";
|
||||||
|
|
||||||
export interface EventGroup {
|
export interface EventGroup extends ExpandableTableItem {
|
||||||
referenceId: string,
|
referenceId: string,
|
||||||
created: number,
|
created: number,
|
||||||
fileName: string|null,
|
fileName: string|null,
|
||||||
|
|||||||
@ -1,23 +0,0 @@
|
|||||||
import { PayloadAction, createSlice } from "@reduxjs/toolkit"
|
|
||||||
import { SimpleEventDataObject } from "../../types"
|
|
||||||
|
|
||||||
interface ComposedState {
|
|
||||||
items: Array<SimpleEventDataObject>
|
|
||||||
}
|
|
||||||
|
|
||||||
const initialState: ComposedState = {
|
|
||||||
items: []
|
|
||||||
}
|
|
||||||
|
|
||||||
const kafkaComposedFlat = createSlice({
|
|
||||||
name: "Composed",
|
|
||||||
initialState,
|
|
||||||
reducers: {
|
|
||||||
simpleEventsUpdate(state, action: PayloadAction<Array<SimpleEventDataObject>>) {
|
|
||||||
state.items = action.payload
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
export const { simpleEventsUpdate } = kafkaComposedFlat.actions;
|
|
||||||
export default kafkaComposedFlat.reducer;
|
|
||||||
@ -5,7 +5,9 @@ import no.iktdev.eventi.data.eventId
|
|||||||
import no.iktdev.eventi.data.referenceId
|
import no.iktdev.eventi.data.referenceId
|
||||||
import no.iktdev.eventi.data.toJson
|
import no.iktdev.eventi.data.toJson
|
||||||
import no.iktdev.eventi.database.*
|
import no.iktdev.eventi.database.*
|
||||||
|
import no.iktdev.mediaprocessing.shared.common.contract.Events
|
||||||
import no.iktdev.mediaprocessing.shared.common.contract.data.Event
|
import no.iktdev.mediaprocessing.shared.common.contract.data.Event
|
||||||
|
import no.iktdev.mediaprocessing.shared.common.contract.jsonToEvent
|
||||||
import no.iktdev.mediaprocessing.shared.common.database.tables.events
|
import no.iktdev.mediaprocessing.shared.common.database.tables.events
|
||||||
import no.iktdev.mediaprocessing.shared.common.database.tables.tasks
|
import no.iktdev.mediaprocessing.shared.common.database.tables.tasks
|
||||||
import no.iktdev.mediaprocessing.shared.common.task.Task
|
import no.iktdev.mediaprocessing.shared.common.task.Task
|
||||||
@ -196,3 +198,7 @@ fun Query?.toTask(): List<Task> {
|
|||||||
val res = this?.mapNotNull { dz.deserializeTask(it) } ?: emptyList()
|
val res = this?.mapNotNull { dz.deserializeTask(it) } ?: emptyList()
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Query?.toEvent(): List<Event> {
|
||||||
|
return this?.mapNotNull { it[events.data].jsonToEvent(it[events.event]) } ?: emptyList()
|
||||||
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user