Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Extensions are provided by apps. These are the apps, that are provided by this r
- [web-app-external-sites](./packages/web-app-external-sites/)
- [web-app-importer](./packages/web-app-importer/)
- [web-app-json-viewer](./packages/web-app-json-viewer/)
- [web-app-maps](./packages/web-app-maps/)
- [web-app-progress-bars](./packages/web-app-progress-bars/)
- [web-app-unzip](./packages/web-app-unzip/)

Expand Down
35 changes: 35 additions & 0 deletions dev/docker/csp.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
directives:
child-src:
- "'self'"
connect-src:
- "'self'"
- 'blob:'
default-src:
- "'none'"
font-src:
- "'self'"
frame-ancestors:
- "'self'"
frame-src:
- "'self'"
- 'blob:'
- 'https://embed.diagrams.net/'
img-src:
- "'self'"
- 'data:'
- 'blob:'
- 'https://tile.openstreetmap.org/'
manifest-src:
- "'self'"
media-src:
- "'self'"
object-src:
- "'self'"
- 'blob:'
script-src:
- "'self'"
- "'unsafe-inline'"
- 'https://www.gstatic.com/'
style-src:
- "'self'"
- "'unsafe-inline'"
31 changes: 30 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,23 @@ services:
OC_URL: https://host.docker.internal:9200
OC_INSECURE: true
OC_LOG_LEVEL: error

IDM_CREATE_DEMO_USERS: true
IDM_ADMIN_PASSWORD: admin

# PROXY
PROXY_ENABLE_BASIC_AUTH: true
PROXY_TLS: 'false'
PROXY_TLS: false
PROXY_CSP_CONFIG_FILE_LOCATION: /etc/opencloud/csp.yaml

# WEB
WEB_ASSET_APPS_PATH: /web/apps
WEB_UI_CONFIG_FILE: /web/config.json

# TIKA
SEARCH_EXTRACTOR_TYPE: 'tika'
SEARCH_EXTRACTOR_TIKA_TIKA_URL: 'http://host.docker.internal:9998'
SEARCH_EXTRACTOR_CS3SOURCE_INSECURE: 'true'
labels:
traefik.enable: true
traefik.http.routers.opencloud.tls: true
Expand All @@ -23,12 +35,14 @@ services:
- opencloud-config:/etc/opencloud
- ./dev/docker/opencloud.web.config.json:/web/config.json
- ./dev/docker/opencloud.apps.yaml:/etc/opencloud/apps.yaml
- ./dev/docker/csp.yaml:/etc/opencloud/csp.yaml
# apps
- ./packages/web-app-cast/dist:/web/apps/cast
- ./packages/web-app-draw-io/dist:/web/apps/draw-io
- ./packages/web-app-external-sites/dist:/web/apps/external-sites
- ./packages/web-app-importer/dist:/web/apps/importer
- ./packages/web-app-json-viewer/dist:/web/apps/json-viewer
- ./packages/web-app-maps/dist:/web/apps/maps
- ./packages/web-app-progress-bars/dist:/web/apps/progress-bars
- ./packages/web-app-unzip/dist:/web/apps/unzip
depends_on:
Expand Down Expand Up @@ -58,6 +72,21 @@ services:
traefik.http.routers.companion.entrypoints: opencloud
traefik.http.services.companion.loadbalancer.server.port: 3020

tika-service:
image: dadarek/wait-for-dependencies:latest
container_name: web_tika_service
depends_on:
- tika
command:
- 'wait-for -it tika:9998 -t 300'

tika:
image: apache/tika:3.2.1.0
container_name: web_tika
ports:
- '9998:9998'
restart: unless-stopped

traefik:
image: traefik:v3.4.4
restart: unless-stopped
Expand Down
22 changes: 22 additions & 0 deletions packages/web-app-maps/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# OpenCloud Maps

OpenCloud Maps app can display `.gpx` files and show geo location data for single pictures in the sidebar or for a whole folder as a folder view.

## Config

In `apps.yaml` you can override configuration like this:

```yaml
maps:
config:
tileLayerUrlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png'
tileLayerOptions:
maxZoom: 19
attribution: '© OpenStreetMap'
```

`tileLayerUrlTemplate` and `tileLayerOptions` have the above as default values, you can override it if you want to use another tile layer provider.

## Privacy Notice

The rendered maps are loaded from OpenStreetMap (by default). This allows them to do at least some basic kind of tracking, simply because files are loaded from their servers by your browser.
1 change: 1 addition & 0 deletions packages/web-app-maps/extension.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/// <reference types="vite/client" />
10 changes: 10 additions & 0 deletions packages/web-app-maps/l10n/.tx/config
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[main]
host = https://www.transifex.com

[o:opencloud-eu:p:opencloud-eu:r:web-extensions-maps]
file_filter = locale/<lang>/app.po
minimum_perc = 0
resource_name = web-extensions-maps
source_file = template.pot
source_lang = en
type = PO
1 change: 1 addition & 0 deletions packages/web-app-maps/l10n/translations.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
27 changes: 27 additions & 0 deletions packages/web-app-maps/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"name": "web-app-maps",
"version": "0.1.0",
"private": true,
"description": "OpenCloud Web Maps",
"license": "AGPL-3.0",
"type": "module",
"scripts": {
"build": "pnpm vite build",
"build:w": "pnpm vite build --watch --mode development",
"check:types": "vue-tsc --noEmit",
"test:unit": "NODE_OPTIONS=--unhandled-rejections=throw vitest"
},
"devDependencies": {
"vite-plugin-static-copy": "^0.13.0",
"vue": "^3.4.21",
"vue3-gettext": "^2.4.0"
},
"dependencies": {
"leaflet": "1.9.4",
"leaflet-gpx": "2.2.0"
},
"peerDependencies": {
"@opencloud-eu/web-pkg": "^3.0.0",
"@opencloud-eu/web-client": "^3.0.0"
}
}
3 changes: 3 additions & 0 deletions packages/web-app-maps/public/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"entrypoint": "maps.js"
}
133 changes: 133 additions & 0 deletions packages/web-app-maps/src/components/GpxMap.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
<template>
<div style="display: flex; flex-direction: column">
<div ref="leafletElement" class="oc-width-1-1 oc-height-1-1" />
<div class="data-table-container">
<table class="data-table">
<tr>
<th v-text="$gettext('Property')" />
<th v-text="$gettext('Value')" />
</tr>
<tr>
<td v-text="$gettext('Name')" />
<td>{{ meta.name }}</td>
</tr>
<tr>
<td v-text="$gettext('Distance')" />
<td>{{ meta.distance }}km</td>
</tr>
<tr>
<td v-text="$gettext('Elevation Gain')" />
<td>{{ meta.elevationGain }}m</td>
</tr>
<tr>
<td v-text="$gettext('Elevation Loss')" />
<td>{{ meta.elevationLoss }}m</td>
</tr>
</table>
</div>
</div>
</template>

<script lang="ts">
import { defineComponent, onMounted, ref, onBeforeUnmount, Ref } from 'vue'
import { useGettext } from 'vue3-gettext'

import * as L from 'leaflet'

import { useLeaflet } from '../composables'
import { unref, watch } from 'vue'

export default defineComponent({
props: {
currentContent: {
type: String,
required: true
},
applicationConfig: {
type: Object,
required: true
}
},
setup(props) {
const { assetsBaseUrl, createMap } = useLeaflet()
const leafletElement = ref<HTMLElement | null>()
const { $gettext } = useGettext()

let mapObject: L.Map | null = null
const meta: Ref<{
name?: string
distance?: string
elevationGain?: string
elevationLoss?: string
elevationNet?: string
}> = ref({})

const gpxOptions = {
async: true,
marker_options: {
clickable: false
},
markers: {
startIcon: `${assetsBaseUrl}/pin-icon-start.png`,
endIcon: `${assetsBaseUrl}/pin-icon-end.png`,
wptIcons: {
start: `${assetsBaseUrl}/pin-icon-start.png`,
end: `${assetsBaseUrl}/pin-icon-end.png`,
'': `${assetsBaseUrl}/pin-icon-wpt.png`
}
}
}

let gpxLayer: L.GPX | null = null
const setView = () => {
if (!mapObject) {
return
}
if (gpxLayer) {
mapObject.removeLayer(gpxLayer)
}
gpxLayer = new L.GPX(props.currentContent, gpxOptions)
.on('loaded', (e) => {
const gpx = e.target
mapObject.fitBounds(e.target.getBounds())

meta.value = {
name: gpx.get_name(),
distance: gpx.get_distance_imp().toFixed(2),
elevationGain: gpx.to_ft(gpx.get_elevation_gain()).toFixed(0),
elevationLoss: gpx.to_ft(gpx.get_elevation_loss()).toFixed(0),
elevationNet: gpx.to_ft(gpx.get_elevation_gain() - gpx.get_elevation_loss()).toFixed(0)
}
})
.addTo(mapObject)
}

onMounted(() => {
mapObject = createMap(props.applicationConfig, unref(leafletElement))
setView()
})

watch(() => props.currentContent, setView)

onBeforeUnmount(() => {
mapObject.remove()
})

return {
$gettext,
leafletElement,
meta
}
}
})
</script>

<style type="scss" scoped>
.data-table-container {
flex-grow: 0;
flex-shrink: 0;
}
.data-table {
border-spacing: 10px;
}
</style>
Loading