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: 0 additions & 1 deletion .eslintignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
js/
l10n/
src/adminSettings.js
src/filetypes.js
src/utils.js
3 changes: 0 additions & 3 deletions css/filetypes.css

This file was deleted.

25 changes: 19 additions & 6 deletions lib/Controller/PageController.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,27 @@
namespace OCA\Maps\Controller;

use OCA\Files\Event\LoadSidebar;
use OCA\Maps\Service\MyMapsService;
use OCA\Viewer\Event\LoadViewer;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\RedirectResponse;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\AppFramework\Services\IInitialState;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\IConfig;
use OCP\IInitialStateService;
use OCP\IRequest;
use OCP\IURLGenerator;

class PageController extends Controller {

public function __construct(
string $appName,
IRequest $request,
private string $userId,
private IEventDispatcher $eventDispatcher,
private IConfig $config,
private IInitialStateService $initialStateService,
private string $userId,
private IInitialState $initialState,
private IURLGenerator $urlGenerator,
) {
parent::__construct($appName, $request);
}
Expand All @@ -50,7 +54,7 @@ public function index(): TemplateResponse {
$this->eventDispatcher->dispatch(LoadViewer::class, new LoadViewer());

$params = ['user' => $this->userId];
$this->initialStateService->provideInitialState($this->appName, 'photos', $this->config->getAppValue('photos', 'enabled', 'no') === 'yes');
$this->initialState->provideInitialState('photos', $this->config->getAppValue('photos', 'enabled', 'no') === 'yes');
$response = new TemplateResponse('maps', 'main', $params);

$this->addCsp($response);
Expand All @@ -62,12 +66,21 @@ public function index(): TemplateResponse {
* @NoAdminRequired
* @NoCSRFRequired
*/
public function indexMyMap($myMapId): TemplateResponse {
public function indexMyMap(int $myMapId, MyMapsService $service): TemplateResponse|RedirectResponse {
$map = $service->getMyMap($myMapId, $this->userId);
if ($map !== null && $map['id'] !== $myMapId) {
// Instead of the id of the map containing folder the '.index.maps' file id was passed so redirect
// this happens if coming from the files app integration
return new RedirectResponse(
$this->urlGenerator->linkToRouteAbsolute('maps.page.indexMyMap', ['myMapId' => $map['id']]),
);
}

$this->eventDispatcher->dispatch(LoadSidebar::class, new LoadSidebar());
$this->eventDispatcher->dispatch(LoadViewer::class, new LoadViewer());

$params = ['user' => $this->userId];
$this->initialStateService->provideInitialState($this->appName, 'photos', $this->config->getAppValue('photos', 'enabled', 'no') === 'yes');
$this->initialState->provideInitialState('photos', $this->config->getAppValue('photos', 'enabled', 'no') === 'yes');
$response = new TemplateResponse('maps', 'main', $params);

$this->addCsp($response);
Expand Down
3 changes: 1 addition & 2 deletions lib/Listener/LoadAdditionalScriptsListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ public function handle(Event $event): void {
return;
}

Util::addScript('maps', 'maps-filetypes');
Util::addStyle('maps', 'filetypes');
Util::addInitScript('maps', 'maps-init-files');
}
}
26 changes: 25 additions & 1 deletion lib/Service/MyMapsService.php
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,30 @@ public function getAllMyMaps($userId) {
return $MyMaps;
}

/**
* Try to lookup a my map by id
*
* @param int $id The map id to lookup
* @param string $userId The current user id
* @return null|array Either the MyMap or null if not found with that id for the given user
*/
public function getMyMap(int $id, string $userId) {
$userFolder = $this->root->getUserFolder($userId);
$node = $userFolder->getFirstNodeById($id);
if ($node instanceof Folder) {
try {
$node = $node->get('.index.maps');
} catch (NotFoundException) {
return null;
}
}

if ($node->getMimetype() === 'application/x-nextcloud-maps') {
return $this->node2MyMap($node, $userFolder);
}
return null;
}

public function updateMyMap($id, $values, $userId) {
$userFolder = $this->root->getUserFolder($userId);
$folders = $userFolder->getById($id);
Expand All @@ -158,7 +182,7 @@ public function updateMyMap($id, $values, $userId) {
try {
$file = $folder->get('.index.maps');
} catch (NotFoundException $e) {
$file = $folder->newFile('.index.maps', $content = '{}');
$file = $folder->newFile('.index.maps', '{}');
}
$mapData = json_decode($file->getContent(), true);
$renamed = false;
Expand Down
54 changes: 46 additions & 8 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,12 @@
"dependencies": {
"@fortawesome/fontawesome-free": "^6.7.2",
"@maplibre/maplibre-gl-leaflet": "^0.1.2",
"@mdi/svg": "^7.4.47",
"@nextcloud/auth": "^2.5.1",
"@nextcloud/axios": "^2.5.1",
"@nextcloud/dialogs": "^6.3.1",
"@nextcloud/event-bus": "^3.3.1",
"@nextcloud/files": "^3.12.0",
"@nextcloud/l10n": "^3.1.0",
"@nextcloud/moment": "^1.3.4",
"@nextcloud/paths": "^2.1.0",
Expand Down Expand Up @@ -84,6 +86,8 @@
"@nextcloud/eslint-config": "^8.4.1",
"@nextcloud/stylelint-config": "^3.1.0",
"@nextcloud/webpack-vue-config": "^6.3.0",
"@types/leaflet": "^1.9.20"
"@types/leaflet": "^1.9.20",
"@vue/tsconfig": "^0.5.1",
"typescript": "^5.9.2"
}
}
49 changes: 49 additions & 0 deletions src/files-actions/import-devices.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import axios from '@nextcloud/axios'
import { showError, showSuccess } from '@nextcloud/dialogs'
import { FileAction, Permission } from '@nextcloud/files'
import { n, t } from '@nextcloud/l10n'
import { generateUrl } from '@nextcloud/router'

import svgMapMarker from '@mdi/svg/svg/map-marker.svg?raw'

export default new FileAction({
id: 'maps:import-device',

displayName() {
return t('maps', 'Import as devices in Maps')
},

enabled(files) {
if (files.length !== 1) {
return false
}

const [file] = files
if (!(file.permissions & Permission.READ)) {
return false
}
return [
'application/gpx+xml',
'application/vnd.google-earth.kmz',
'application/vnd.google-earth.kml+xml',
].includes(file.mime)
},

async exec(file) {
const path = file.path
const url = generateUrl('/apps/maps/import/devices')
try {
const { data } = await axios.post(url, { path })
const number = typeof data === 'number' ? data : data.nbImported
showSuccess(n('maps', 'One device imported', '%n devices imported', number))
} catch (error) {
showError(t('maps', 'Failed to import devices'))
console.error('Failed to import devices', { error })
}
return null
},

iconSvgInline() {
return svgMapMarker
},
})
50 changes: 50 additions & 0 deletions src/files-actions/import-favorite.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import axios from '@nextcloud/axios'
import { showError, showSuccess } from '@nextcloud/dialogs'
import { FileAction, Permission } from '@nextcloud/files'
import { n, t } from '@nextcloud/l10n'
import { generateUrl } from '@nextcloud/router'

import svgMapMarker from '@mdi/svg/svg/map-marker.svg?raw'

export default new FileAction({
id: 'maps:import-as-favorite',

displayName() {
return t('maps', 'Import as favorites in Maps')
},

enabled(files) {
if (files.length !== 1) {
return false
}

const [file] = files
if (!(file.permissions & Permission.READ)) {
return false
}
return [
'application/geo+json',
'application/gpx+xml',
'application/vnd.google-earth.kmz',
'application/vnd.google-earth.kml+xml',
].includes(file.mime)
},

async exec(file) {
const path = file.path
const url = generateUrl('/apps/maps/import/favorites')
try {
const { data } = await axios.post(url, { path })
const number = typeof data === 'number' ? data : data.nbImported
showSuccess(n('maps', 'One favorite imported', '%n favorites imported', number))
} catch (error) {
showError(t('maps', 'Failed to import favorites'))
console.error('Failed to import favorites', { error })
}
return null
},

iconSvgInline() {
return svgMapMarker
},
})
Loading
Loading