Skip to content

Commit e1721bb

Browse files
committed
-image metadata
-thumbs are not recreated for same blobs -bug fixes -resolved #21
1 parent db06567 commit e1721bb

23 files changed

+304
-311
lines changed

infrastructure/db.sql

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*!999999\- enable the sandbox mode */
22
-- MariaDB dump 10.19 Distrib 10.11.8-MariaDB, for debian-linux-gnu (x86_64)
33
--
4-
-- Host: localhost Database: openobjectstorage
4+
-- Host: localhost Database: opendistributedfilestorage
55
-- ------------------------------------------------------
66
-- Server version 10.11.8-MariaDB-0ubuntu0.24.04.1
77

@@ -99,6 +99,22 @@ CREATE TABLE `blobs_metadata` (
9999
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
100100
/*!40101 SET character_set_client = @saved_cs_client */;
101101

102+
--
103+
-- Table structure for table `blobs_versions`
104+
--
105+
106+
DROP TABLE IF EXISTS `blobs_versions`;
107+
/*!40101 SET @saved_cs_client = @@character_set_client */;
108+
/*!40101 SET character_set_client = utf8 */;
109+
CREATE TABLE `blobs_versions` (
110+
`blobId` int(10) unsigned NOT NULL,
111+
`title` varchar(100) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
112+
PRIMARY KEY (`blobId`,`title`),
113+
KEY `files_versions_blobId` (`blobId`),
114+
CONSTRAINT `files_versions_blobId` FOREIGN KEY (`blobId`) REFERENCES `blobs` (`id`)
115+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
116+
/*!40101 SET character_set_client = @saved_cs_client */;
117+
102118
--
103119
-- Table structure for table `containers`
104120
--
@@ -181,24 +197,6 @@ CREATE TABLE `files_tags` (
181197
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
182198
/*!40101 SET character_set_client = @saved_cs_client */;
183199

184-
--
185-
-- Table structure for table `files_versions`
186-
--
187-
188-
DROP TABLE IF EXISTS `files_versions`;
189-
/*!40101 SET @saved_cs_client = @@character_set_client */;
190-
/*!40101 SET character_set_client = utf8 */;
191-
CREATE TABLE `files_versions` (
192-
`fileId` int(10) unsigned NOT NULL,
193-
`blobId` int(10) unsigned NOT NULL,
194-
`title` varchar(100) NOT NULL,
195-
KEY `files_versions_fileId` (`fileId`),
196-
KEY `files_versions_blobId` (`blobId`),
197-
CONSTRAINT `files_versions_blobId` FOREIGN KEY (`blobId`) REFERENCES `blobs` (`id`),
198-
CONSTRAINT `files_versions_fileId` FOREIGN KEY (`fileId`) REFERENCES `files` (`id`)
199-
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
200-
/*!40101 SET character_set_client = @saved_cs_client */;
201-
202200
--
203201
-- Table structure for table `storagebackends`
204202
--
@@ -289,4 +287,4 @@ CREATE TABLE `tags` (
289287
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
290288
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
291289

292-
-- Dump completed on 2024-11-10 22:20:40
290+
-- Dump completed on 2024-12-15 21:19:33

portal/api.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@
33
"source": "../service/dist/openapi.json",
44
"destination": "./dist/api.ts",
55
"excludedStatusCodes": [],
6-
"header": "interface OptionalRequestData{}"
6+
"header": "interface OptionalRequestData{}",
7+
"target": "browser"
78
}

portal/src/file-explorer/ViewFileComponent.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,12 @@ export class ViewFileComponent extends Component
8585

8686
private RenderSubNav()
8787
{
88+
const isAudio = this.data?.mediaType.startsWith("audio/") ?? false;
89+
const isImage = this.data?.mediaType.startsWith("image/") ?? false;
8890
return <ul className="nav nav-pills flex-column">
8991
<NavItem route={"/" + this.containerId + "/" + this.fileId + "/content"}><BootstrapIcon>eyeglasses</BootstrapIcon> View</NavItem>
90-
{this.data?.mediaType.startsWith("audio/") ? <NavItem route={"/" + this.containerId + "/" + this.fileId + "/metadata"}><BootstrapIcon>info-circle</BootstrapIcon> Song info</NavItem> : null}
92+
{isAudio ? <NavItem route={"/" + this.containerId + "/" + this.fileId + "/metadata"}><BootstrapIcon>info-circle</BootstrapIcon> Song info</NavItem> : null}
93+
{isImage ? <NavItem route={"/" + this.containerId + "/" + this.fileId + "/imgmetadata"}><BootstrapIcon>info-circle</BootstrapIcon> Photo info</NavItem> : null}
9194
<NavItem route={"/" + this.containerId + "/" + this.fileId + "/accesses"}><BootstrapIcon>graph-up</BootstrapIcon> Access statistics</NavItem>
9295
<NavItem route={"/" + this.containerId + "/" + this.fileId + "/revisions"}><BootstrapIcon>card-list</BootstrapIcon> Revisions</NavItem>
9396
<NavItem route={"/" + this.containerId + "/" + this.fileId + "/versions"}><BootstrapIcon>clock-history</BootstrapIcon> Versions</NavItem>

portal/src/file-explorer/EditAVMetaDataComponent.tsx renamed to portal/src/file-explorer/metadata/EditAVMetaDataComponent.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
* */
1818

1919
import { BootstrapIcon, FormField, JSX_CreateElement, LineEdit, PushButton, Router, TextArea, Use, UseAPI, UseDeferredAPI, UseRouteParameter, UseState } from "acfrontend";
20-
import { APIService } from "../APIService";
21-
import { AudioMetadataTags } from "../../dist/api";
20+
import { AudioMetadataTags } from "../../../dist/api";
21+
import { APIService } from "../../APIService";
2222

2323
function FormComponent(input: { containerId: number; fileId: number; audioTags: AudioMetadataTags; })
2424
{
@@ -50,5 +50,5 @@ export function EditAVMetaDataComponent()
5050
const fileId = UseRouteParameter("route", "fileId", "unsigned");
5151

5252
const apiState = UseAPI( () => Use(APIService).files._any_.meta.get(fileId) );
53-
return apiState.success ? <FormComponent containerId={containerId} fileId={fileId} audioTags={apiState.data} /> : apiState.fallback;
53+
return apiState.success ? <FormComponent containerId={containerId} fileId={fileId} audioTags={apiState.data as AudioMetadataTags} /> : apiState.fallback;
5454
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/**
2+
* OpenDistributedFileStorage
3+
* Copyright (C) 2024 Amir Czwink ([email protected])
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU Affero General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU Affero General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Affero General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
* */
18+
import { APIService } from "../../APIService";
19+
import { ImageTags } from "../../../dist/api";
20+
import { JSX_CreateElement, JSX_Fragment, Use, UseAPI, UseRouteParameter } from "acfrontend";
21+
22+
function InfoComponent(input: { containerId: number; fileId: number; tags: ImageTags; })
23+
{
24+
const t = input.tags;
25+
26+
if(t.geolocation !== undefined)
27+
{
28+
const lat = t.geolocation.latitude.substring(0, t.geolocation.latitude.length - 2);
29+
const lon = t.geolocation.longitude.substring(0, t.geolocation.longitude.length - 2);
30+
31+
const points = [{
32+
lat: parseFloat(lat),
33+
lon: parseFloat(lon)
34+
}];
35+
const data = {
36+
points,
37+
};
38+
return <>
39+
Taken on: {t.geolocation.dateTime} <br />
40+
<iframe src={"/leaflet.htm?data=" + encodeURIComponent(JSON.stringify(data))} style="width: 100%; height: 80vh" />;
41+
</>;
42+
}
43+
44+
return "No tags";
45+
}
46+
47+
export function ViewImageMetaDataComponent()
48+
{
49+
const containerId = UseRouteParameter("route", "containerId", "unsigned");
50+
const fileId = UseRouteParameter("route", "fileId", "unsigned");
51+
52+
const apiState = UseAPI( () => Use(APIService).files._any_.meta.get(fileId) );
53+
return apiState.success ? <InfoComponent containerId={containerId} fileId={fileId} tags={apiState.data as ImageTags} /> : apiState.fallback;
54+
}

portal/src/routing.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,9 @@ import { ListStorageBackendsComponent } from "./storage-backends/ListStorageBack
3232
import { CreateStorageBackendComponent } from "./storage-backends/CreateStorageBackendComponent";
3333
import { ViewFileVersionsComponent } from "./file-explorer/ViewFileVersionsComponent";
3434
import { CreateFileVersionComponent } from "./file-explorer/CreateFileVersionComponent";
35-
import { EditAVMetaDataComponent } from "./file-explorer/EditAVMetaDataComponent";
3635
import { FileAccessesComponent } from "./file-explorer/FileAccessesComponent";
36+
import { EditAVMetaDataComponent } from "./file-explorer/metadata/EditAVMetaDataComponent";
37+
import { ViewImageMetaDataComponent } from "./file-explorer/metadata/ViewImageMetaDataComponent";
3738

3839
const writeGuard = new OAuth2Guard({ config: CONFIG_OIDC, scopes: [SCOPE_FILES_WRITE] });
3940

@@ -42,6 +43,7 @@ const fileRoutes: Routes = [
4243
{ path: "content", component: <ViewFileContentComponent /> },
4344
{ path: "edit", component: <EditFileAttributesComponent />, guards: [ writeGuard ] },
4445
{ path: "metadata", component: <EditAVMetaDataComponent />, guards: [ writeGuard ] },
46+
{ path: "imgmetadata", component: <ViewImageMetaDataComponent /> },
4547
{ path: "revisions", component: <ViewFileRevisionsComponent /> },
4648
{ path: "versions/create", component: <CreateFileVersionComponent />, guards: [ writeGuard ] },
4749
{ path: "versions", component: <ViewFileVersionsComponent /> },

portal/static/leaflet.htm

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<!doctype html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1">
6+
<base href="/">
7+
<title></title>
8+
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin=""/>
9+
</head>
10+
<body>
11+
<div id="map" style="height: 100vh;" />
12+
<script src="https://unpkg.com/[email protected]/dist/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script>
13+
<script>
14+
function DrawMap()
15+
{
16+
const data = decodeURIComponent(window.location.search.substring("?data=".length));
17+
const parsedData = JSON.parse(data);
18+
19+
var map = L.map('map')
20+
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
21+
maxZoom: 19,
22+
attribution: '© OpenStreetMap'
23+
}).addTo(map);
24+
25+
const markers = [];
26+
for (const point of parsedData.points)
27+
{
28+
const marker = L.marker([point.lat, point.lon]).addTo(map);
29+
markers.push(marker);
30+
}
31+
32+
if(markers.length > 0)
33+
{
34+
const group = new L.featureGroup(markers);
35+
map.fitBounds(group.getBounds());
36+
}
37+
if(markers.length === 1)
38+
{
39+
map.setZoom(13);
40+
}
41+
}
42+
window.onload = DrawMap;
43+
</script>
44+
</body>
45+
</html>

service/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
FROM node
22

33
WORKDIR /app
4-
RUN apt update && apt install --no-install-recommends -y ffmpeg rclone && apt clean autoclean && apt autoremove --yes && rm -rf /var/lib/{apt,dpkg,cache,log}/ && rm -rf /tmp/* /var/tmp/*
4+
RUN apt update && apt install --no-install-recommends -y ffmpeg libimage-exiftool-perl rclone && apt clean autoclean && apt autoremove --yes && rm -rf /var/lib/{apt,dpkg,cache,log}/ && rm -rf /tmp/* /var/tmp/*
55

66
COPY ./dist/bundle.js ./
77
CMD [ "node", "bundle.js" ]

service/package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"scripts": {
77
"build": "npx acts-util-apilib && npx webpack",
88
"build-docker-image": "docker build -t odfs .",
9-
"run-dev-server": "nodemon --exec \"npx acts-util-apilib; tsc; node dist/src/main.js\""
9+
"run-dev-server": "nodemon --exec \"npx acts-util-apilib; tsc; rm /srv/OpenDistributedFileStorage/crash_check; node dist/src/main.js\""
1010
},
1111
"keywords": [],
1212
"author": "Amir Czwink",
@@ -26,7 +26,6 @@
2626
"acts-util-node": "*",
2727
"amqplib": "^0.10.4",
2828
"dotenv": "^16.4.5",
29-
"ftp-srv": "^4.6.3",
3029
"jsonwebtoken": "^9.0.2"
3130
}
3231
}

service/src/BackgroundJob.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,15 @@ export type StreamingVersionType = "360p" | "480p";
2020
interface ComputeStreamingVersion
2121
{
2222
type: "compute-streaming-version";
23-
fileId: number;
23+
blobId: number;
2424
targetType: StreamingVersionType;
2525
}
2626

2727
interface ComputeThumbs
2828
{
2929
type: "compute-thumbs";
30-
fileId: number;
30+
blobId: number;
31+
mediaType: string;
3132
}
3233

3334
interface FileUploadJob

0 commit comments

Comments
 (0)