Updates
This commit is contained in:
parent
01a5d21e69
commit
a27e50f909
@ -4,6 +4,8 @@ import mu.KotlinLogging
|
|||||||
import no.iktdev.mediaprocessing.shared.common.SharedConfig
|
import no.iktdev.mediaprocessing.shared.common.SharedConfig
|
||||||
import no.iktdev.mediaprocessing.shared.common.contract.dto.ProcesserEventInfo
|
import no.iktdev.mediaprocessing.shared.common.contract.dto.ProcesserEventInfo
|
||||||
import no.iktdev.mediaprocessing.shared.common.task.Task
|
import no.iktdev.mediaprocessing.shared.common.task.Task
|
||||||
|
import no.iktdev.mediaprocessing.shared.common.tryPost
|
||||||
|
import no.iktdev.mediaprocessing.shared.common.trySend
|
||||||
import org.springframework.beans.factory.annotation.Autowired
|
import org.springframework.beans.factory.annotation.Autowired
|
||||||
import org.springframework.messaging.simp.SimpMessagingTemplate
|
import org.springframework.messaging.simp.SimpMessagingTemplate
|
||||||
import org.springframework.stereotype.Service
|
import org.springframework.stereotype.Service
|
||||||
@ -20,37 +22,21 @@ class Reporter() {
|
|||||||
|
|
||||||
|
|
||||||
fun encodeTaskAssigned(task: Task) {
|
fun encodeTaskAssigned(task: Task) {
|
||||||
try {
|
messageTemplate.trySend("/topic/encode/assigned", task)
|
||||||
messageTemplate.convertAndSend("/topic/encode/assigned", task)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
//log.error { e.message }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun extractTaskAssigned(task: Task) {
|
fun extractTaskAssigned(task: Task) {
|
||||||
try {
|
messageTemplate.trySend("/topic/extract/assigned", task)
|
||||||
messageTemplate.convertAndSend("/topic/extract/assigned", task)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
//log.error { e.message }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun sendEncodeProgress(progress: ProcesserEventInfo) {
|
fun sendEncodeProgress(progress: ProcesserEventInfo) {
|
||||||
try {
|
restTemplate.tryPost<String>(SharedConfig.uiUrl + "/encode/progress", progress)
|
||||||
restTemplate.postForEntity(SharedConfig.uiUrl + "/encode/progress", progress, String::class.java)
|
messageTemplate.trySend("/topic/encode/progress", progress)
|
||||||
messageTemplate.convertAndSend("/topic/encode/progress", progress)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
//log.error { e.message }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun sendExtractProgress(progress: ProcesserEventInfo) {
|
fun sendExtractProgress(progress: ProcesserEventInfo) {
|
||||||
try {
|
restTemplate.tryPost<String>(SharedConfig.uiUrl + "/extract/progress", progress)
|
||||||
restTemplate.postForEntity(SharedConfig.uiUrl + "/extract/progress", progress, String::class.java)
|
messageTemplate.trySend("/topic/extract/progress", progress)
|
||||||
messageTemplate.convertAndSend("/topic/extract/progress", progress)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
//log.error { e.message }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -73,4 +73,21 @@ class ExplorerCore {
|
|||||||
return getCursor(SharedConfig.inputRoot.absolutePath)
|
return getCursor(SharedConfig.inputRoot.absolutePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getRoots(): ExplorerCursor {
|
||||||
|
return ExplorerCursor(
|
||||||
|
name = "root",
|
||||||
|
path = "",
|
||||||
|
items = File.listRoots().map {
|
||||||
|
val attr = getAttr(it)
|
||||||
|
ExplorerItem(
|
||||||
|
path = it.absolutePath,
|
||||||
|
name = it.absolutePath,
|
||||||
|
extension = it.extension,
|
||||||
|
created = attr.created,
|
||||||
|
type = ExplorerItemType.FOLDER
|
||||||
|
)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1,6 +1,6 @@
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { UnixTimestamp } from '../features/UxTc';
|
import { UnixTimestamp } from '../features/UxTc';
|
||||||
import { Box, Button, Typography, useTheme } from '@mui/material';
|
import { Box, Button, IconButton, Typography, useTheme } from '@mui/material';
|
||||||
import { useDispatch, useSelector } from 'react-redux';
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
import { RootState } from '../store';
|
import { RootState } from '../store';
|
||||||
import { TableCellCustomizer, TablePropetyConfig, TableRowActionEvents } from '../features/table/table';
|
import { TableCellCustomizer, TablePropetyConfig, TableRowActionEvents } from '../features/table/table';
|
||||||
@ -15,6 +15,7 @@ import { ExplorerItem, ExplorerCursor, ExplorerItemType } from '../../types';
|
|||||||
import ContextMenu, { ContextMenuActionEvent, ContextMenuItem } from '../features/ContextMenu';
|
import ContextMenu, { ContextMenuActionEvent, ContextMenuItem } from '../features/ContextMenu';
|
||||||
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';
|
||||||
|
|
||||||
|
|
||||||
const createTableCell: TableCellCustomizer<ExplorerItem> = (accessor, data) => {
|
const createTableCell: TableCellCustomizer<ExplorerItem> = (accessor, data) => {
|
||||||
@ -46,20 +47,76 @@ const columns: Array<TablePropetyConfig> = [
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
type Segment = {
|
||||||
|
name: string;
|
||||||
|
absolutePath: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
function isWindowsPath(path: string): boolean {
|
||||||
|
return /^[A-Za-z]:\\/.test(path);
|
||||||
|
}
|
||||||
|
|
||||||
function getPartFor(path: string, index: number): string | null {
|
function getPartFor(path: string, index: number): string | null {
|
||||||
if (path.match(/\//)) {
|
const separator = path.includes("/") ? "/" : "\\";
|
||||||
return path.split(/\//, index + 1).join("/");
|
|
||||||
} else if (path.match(/\\/)) {
|
let parts: string[];
|
||||||
return path.split(/\\/, index + 1).join("\\");
|
if (isWindowsPath(path)) {
|
||||||
|
parts = [path.slice(0, 3), ...path.slice(3).split(separator)];
|
||||||
|
} else if (path.startsWith(separator)) {
|
||||||
|
parts = [separator, ...path.slice(1).split(separator)];
|
||||||
|
} else {
|
||||||
|
parts = path.split(separator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (index < parts.length) {
|
||||||
|
// Unngå å legge til ekstra backslash for første element i Windows-path
|
||||||
|
if (isWindowsPath(path) && index === 0) {
|
||||||
|
return parts[0];
|
||||||
|
}
|
||||||
|
return parts.slice(0, index + 1).join(separator);
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSegmentedNaviagatablePath(navigateTo: (path: string | null) => void, path: string | null): JSX.Element {
|
function getSegments(absolutePath: string): Array<Segment> {
|
||||||
console.log(path);
|
if (!absolutePath) return [];
|
||||||
const parts: Array<string> = path?.split(/\\|\//).map((value: string, index: number) => value.replaceAll(":", "")) ?? [];
|
|
||||||
const segments = parts.map((name: string, index: number) => {
|
const isWindows = isWindowsPath(absolutePath);
|
||||||
console.log(name)
|
const separator = isWindows ? "\\" : "/";
|
||||||
|
|
||||||
|
let parts: string[];
|
||||||
|
if (isWindows) {
|
||||||
|
parts = [absolutePath.slice(0, 3), ...absolutePath.slice(3).split(separator)];
|
||||||
|
} else if (absolutePath.startsWith(separator)) {
|
||||||
|
parts = [separator, ...absolutePath.slice(1).split(separator)];
|
||||||
|
} else {
|
||||||
|
parts = absolutePath.split(separator);
|
||||||
|
}
|
||||||
|
|
||||||
|
const segments = parts.map((value, index) => {
|
||||||
|
const name = isWindows && index === 0 ? value[0] : value;
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: name.replaceAll(":", ""),
|
||||||
|
absolutePath: getPartFor(absolutePath, index)!
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log({
|
||||||
|
segments: segments,
|
||||||
|
path: absolutePath
|
||||||
|
});
|
||||||
|
|
||||||
|
return segments.filter((segment) => segment.name !== "");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function getSegmentedNaviagatablePath(rootClick: () => void, navigateTo: (path: string | null) => void, path: string | null): JSX.Element {
|
||||||
|
const segments = getSegments(path!)
|
||||||
|
|
||||||
|
const utElements = segments.map((segment: Segment, index: number) => {
|
||||||
return (
|
return (
|
||||||
<Box key={index} sx={{
|
<Box key={index} sx={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
@ -69,19 +126,33 @@ function getSegmentedNaviagatablePath(navigateTo: (path: string | null) => void,
|
|||||||
<Button sx={{
|
<Button sx={{
|
||||||
borderRadius: 5,
|
borderRadius: 5,
|
||||||
textTransform: 'none'
|
textTransform: 'none'
|
||||||
}} onClick={() => navigateTo(getPartFor(path!, index))}>
|
}} onClick={() => navigateTo(segment.absolutePath!)}>
|
||||||
<Typography>{name}</Typography>
|
<Typography>{segment.name}</Typography>
|
||||||
</Button>
|
</Button>
|
||||||
{index < parts.length - 1 && <IconForward fontSize="small" />}
|
{ segments.length > 1 && index < segments.length - 1 && <IconForward fontSize="small" />}
|
||||||
</Box>
|
</Box>
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
console.log(parts)
|
|
||||||
return (
|
return (
|
||||||
<Box display="flex">
|
<Box display="flex">
|
||||||
{segments}
|
{isWindowsPath(path!) && (
|
||||||
|
<Box sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center"
|
||||||
|
}}>
|
||||||
|
<IconButton sx={{
|
||||||
|
borderRadius: 5,
|
||||||
|
textTransform: 'none'
|
||||||
|
}} onClick={() => rootClick()} >
|
||||||
|
<TagIcon />
|
||||||
|
</IconButton>
|
||||||
|
<IconForward fontSize="small" />
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
{utElements}
|
||||||
</Box>
|
</Box>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -229,6 +300,12 @@ export default function ExplorePage() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const onRootClick = () => {
|
||||||
|
client?.publish({
|
||||||
|
destination: "/app/explorer/root"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
useWsSubscription<ExplorerCursor>("/topic/explorer/go", (response) => {
|
useWsSubscription<ExplorerCursor>("/topic/explorer/go", (response) => {
|
||||||
dispatch(updateItems(response))
|
dispatch(updateItems(response))
|
||||||
});
|
});
|
||||||
@ -275,7 +352,7 @@ export default function ExplorePage() {
|
|||||||
borderRadius: 5,
|
borderRadius: 5,
|
||||||
backgroundColor: muiTheme.palette.divider
|
backgroundColor: muiTheme.palette.divider
|
||||||
}}>
|
}}>
|
||||||
{getSegmentedNaviagatablePath(navigateTo, cursor?.path)}
|
{getSegmentedNaviagatablePath(onRootClick, navigateTo, cursor?.path)}
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@ -2,6 +2,9 @@ package no.iktdev.mediaprocessing.shared.common
|
|||||||
|
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import mu.KotlinLogging
|
import mu.KotlinLogging
|
||||||
|
import org.springframework.messaging.simp.SimpMessagingTemplate
|
||||||
|
import org.springframework.web.client.RestTemplate
|
||||||
|
import org.springframework.web.client.postForEntity
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileInputStream
|
import java.io.FileInputStream
|
||||||
import java.io.RandomAccessFile
|
import java.io.RandomAccessFile
|
||||||
@ -163,3 +166,15 @@ fun getChecksum(filePath: String): String {
|
|||||||
}
|
}
|
||||||
return sb.toString()
|
return sb.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline fun <reified T> RestTemplate.tryPost(url: String, data: Any, noinline onError: ((Exception) -> Unit)? = null) {
|
||||||
|
try {
|
||||||
|
this.postForEntity(url, data, T::class.java)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
onError?.invoke(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun SimpMessagingTemplate.trySend(destination: String, data: Any) {
|
||||||
|
this.convertAndSend(destination, data)
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user