mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2026-08-26 13:17:30 -05:00
Fix location
This commit is contained in:
@@ -125,7 +125,6 @@ final class UpdateController extends Controller
|
||||
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
$resource = new Item($selectedGroup, $transformer, 'transactions');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
|
||||
|
||||
@@ -79,11 +79,12 @@ class UpdateRequest extends FormRequest
|
||||
'category_id',
|
||||
'bill_id',
|
||||
'recurrence_id',
|
||||
'zoom_level'
|
||||
];
|
||||
$this->dateFields = ['date', 'interest_date', 'book_date', 'process_date', 'due_date', 'payment_date', 'invoice_date'];
|
||||
$this->textareaFields = ['notes'];
|
||||
// not really floats, for validation.
|
||||
$this->floatFields = ['amount', 'foreign_amount'];
|
||||
$this->floatFields = ['amount', 'foreign_amount','longitude','latitude'];
|
||||
$this->stringFields = [
|
||||
'type',
|
||||
'currency_code',
|
||||
|
||||
@@ -35,6 +35,7 @@ use FireflyIII\Factory\TagFactory;
|
||||
use FireflyIII\Factory\TransactionJournalMetaFactory;
|
||||
use FireflyIII\Factory\TransactionTypeFactory;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\Location;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionGroup;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
@@ -194,6 +195,7 @@ class JournalUpdateService
|
||||
$this->updateCurrency();
|
||||
$this->updateAmount();
|
||||
$this->updateForeignAmount();
|
||||
$this->updateLocation();
|
||||
|
||||
Preferences::mark();
|
||||
|
||||
@@ -911,4 +913,28 @@ class JournalUpdateService
|
||||
}
|
||||
Log::debug('No type field present.');
|
||||
}
|
||||
|
||||
private function updateLocation(): void
|
||||
{
|
||||
if($this->hasFields(['longitude','latitude','zoom_level'])) {
|
||||
// if all are null or zero, delete current location.
|
||||
if(null === $this->data['longitude'] && null === $this->data['latitude'] && null === $this->data['zoom_level']) {
|
||||
$this->transactionJournal->locations()->delete();
|
||||
return;
|
||||
}
|
||||
if('' === $this->data['longitude'] && '' === $this->data['latitude'] && null === $this->data['zoom_level']) {
|
||||
$this->transactionJournal->locations()->delete();
|
||||
return;
|
||||
}
|
||||
$location = $this->transactionJournal->locations()->first();
|
||||
if(null === $location) {
|
||||
$location = new Location();
|
||||
$location->locatable()->associate($this->transactionJournal);
|
||||
}
|
||||
$location->longitude = $this->data['longitude'] ?? null;
|
||||
$location->latitude = $this->data['latitude'];
|
||||
$location->zoom_level = $this->data['zoom_level'];
|
||||
$location->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+27
-32
@@ -1,9 +1,10 @@
|
||||
{
|
||||
"name": "firefly-iii",
|
||||
"name": "release",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "release",
|
||||
"hasInstallScript": true,
|
||||
"workspaces": [
|
||||
"resources/assets/v3"
|
||||
@@ -1054,23 +1055,13 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/deepmerge-ts": {
|
||||
"version": "7.1.6",
|
||||
"resolved": "https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-7.1.6.tgz",
|
||||
"integrity": "sha512-gQhL1ksGBLQbHeAo47YU6cs2ahd3Pv+8PFYoWogNZbQnNwQyOh9Ad5kbeHFiWwbKdeWQJ5Z7Y7mwb9ew2hXBLw==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "ko-fi",
|
||||
"url": "https://ko-fi.com/rebeccastevens"
|
||||
},
|
||||
{
|
||||
"type": "tidelift",
|
||||
"url": "https://tidelift.com/funding/github/npm/deepmerge-ts"
|
||||
}
|
||||
],
|
||||
"license": "BSD-3-Clause",
|
||||
"node_modules/deepmerge": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
|
||||
"integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=16.0.0"
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/define-data-property": {
|
||||
@@ -2288,19 +2279,6 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/shepherd.js": {
|
||||
"version": "15.2.3",
|
||||
"resolved": "https://registry.npmjs.org/shepherd.js/-/shepherd.js-15.2.3.tgz",
|
||||
"integrity": "sha512-FyLH/c25YlTS5d+cL9oLajzfW0TzNl43sysQG6EK4bf60n9les7TsIUekHTTKyMEtcARIVHW2d1N9sqeDkIsbQ==",
|
||||
"license": "AGPL-3.0",
|
||||
"dependencies": {
|
||||
"@floating-ui/dom": "^1.8.0",
|
||||
"deepmerge-ts": "^7.1.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 20"
|
||||
}
|
||||
},
|
||||
"node_modules/slash": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
|
||||
@@ -2726,7 +2704,7 @@
|
||||
"bootstrap5-autocomplete": "^1",
|
||||
"bootstrap5-tags": "^1.7.17",
|
||||
"cally": "^0.9.2",
|
||||
"date-fns": "4.4.0",
|
||||
"date-fns": "^4.4.0",
|
||||
"fullcalendar": "^7.0.1",
|
||||
"i18next": "^26.0.3",
|
||||
"i18next-chained-backend": "^5.0.0",
|
||||
@@ -2734,7 +2712,7 @@
|
||||
"i18next-localstorage-backend": "^4.2.0",
|
||||
"leaflet": "^1.9.4",
|
||||
"patch-package": "^8.0.1",
|
||||
"shepherd.js": "^15.2.2",
|
||||
"shepherd.js": "^11.2.0",
|
||||
"store": "^2.0.12"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -2746,6 +2724,23 @@
|
||||
"vite": "^8.0.0",
|
||||
"vite-plugin-manifest-sri": "^0.2.0"
|
||||
}
|
||||
},
|
||||
"resources/assets/v3/node_modules/shepherd.js": {
|
||||
"version": "11.2.0",
|
||||
"resolved": "https://registry.npmjs.org/shepherd.js/-/shepherd.js-11.2.0.tgz",
|
||||
"integrity": "sha512-2hbz3N7GuuTjI7y3sfnoqKnH0cNhExx67IJtCTGQI2KhBEyvegsDYW5qjj5BlvvVtQjmL/O/J1GQEciwfoZWpw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@floating-ui/dom": "^1.5.1",
|
||||
"deepmerge": "^4.3.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "16.* || >= 18"
|
||||
},
|
||||
"funding": {
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/RobbieTheWagner"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,12 +50,17 @@ import {clearSourceAccount, clearDestinationAccount} from './shared/clear-fields
|
||||
import {detectTransactionType} from './shared/detect-transaction-type.js';
|
||||
import {determineAmountCurrency} from './shared/determine-amount-currency.js';
|
||||
import {loadCustomFields} from './shared/load-custom-fields.js';
|
||||
import {loadDefaultCoordinates} from './shared/load-default-coordinates.js';
|
||||
import L from 'leaflet';
|
||||
import 'leaflet/dist/leaflet.css';
|
||||
import {loadDefaultCoordinates} from './shared/load-default-coordinates.js';
|
||||
import markerIcon from "leaflet/dist/images/marker-icon.png";
|
||||
import markerRetinaIcon from "leaflet/dist/images/marker-icon-2x.png";
|
||||
import shadow from 'leaflet/dist/images/marker-shadow.png';
|
||||
import {displayMap} from './shared/display-map.js';
|
||||
import {renderMap} from './shared/render-map.js';
|
||||
import {onMapClick} from './shared/on-map-click.js';
|
||||
import {onMapZoom} from "./shared/on-map-zoom.js";
|
||||
|
||||
|
||||
// TODO fix two maps, perhaps disconnect from entries entirely.
|
||||
// TODO map location from preferences
|
||||
@@ -174,6 +179,10 @@ let create = function () {
|
||||
addAllAutocompleteToForm: addAllAutocompleteToForm,
|
||||
loadCustomFields: loadCustomFields,
|
||||
loadDefaultCoordinates: loadDefaultCoordinates,
|
||||
displayMap: displayMap,
|
||||
renderMap: renderMap,
|
||||
onMapClick: onMapClick,
|
||||
onMapZoom: onMapZoom,
|
||||
|
||||
|
||||
filterForeignCurrencies(code) {
|
||||
@@ -224,69 +233,8 @@ let create = function () {
|
||||
clearCategory(index) {
|
||||
this.entries[index].category_name = '';
|
||||
},
|
||||
displayMap(index) {
|
||||
index = parseInt(index);
|
||||
if (true === this.formBehaviour.customFields.location) {
|
||||
|
||||
if (false === this.formBehaviour.defaultCoordinates.loaded) {
|
||||
// load first, then show map.
|
||||
this.loadDefaultCoordinates().then(data => {
|
||||
this.formBehaviour.defaultCoordinates = data;
|
||||
this.renderMap(index, true);
|
||||
});
|
||||
return;
|
||||
}
|
||||
this.renderMap(index, false);
|
||||
}
|
||||
},
|
||||
onMapClick(event) {
|
||||
|
||||
L.Marker.prototype.setIcon(L.icon({
|
||||
iconUrl: markerIcon,
|
||||
iconRetinaIcon: markerRetinaIcon,
|
||||
shadowUrl: shadow,
|
||||
iconSize: [25, 41],
|
||||
iconAnchor: [12, 41]
|
||||
}));
|
||||
|
||||
|
||||
let index = parseInt(event.originalEvent.currentTarget.dataset.index);
|
||||
this.entries[index].hasLocation = true;
|
||||
this.entries[index].latitude = event.latlng.lat;
|
||||
this.entries[index].longitude = event.latlng.lng;
|
||||
this.entries[index].zoomLevel = this.maps[index].getZoom();
|
||||
|
||||
// add marker.
|
||||
if(this.markers.hasOwnProperty(index)) {
|
||||
this.maps[index].removeLayer(this.markers[index]);
|
||||
}
|
||||
this.markers[index] = L.marker(event.latlng);
|
||||
this.markers[index].addTo(this.maps[index]);
|
||||
|
||||
},
|
||||
renderMap(index, useDefault) {
|
||||
const el = document.getElementById('location_map_' + index);
|
||||
let latitude = parseFloat(this.formBehaviour.defaultCoordinates.latitude);
|
||||
let longitude = parseFloat(this.formBehaviour.defaultCoordinates.longitude);
|
||||
let zoomLevel = parseInt(this.formBehaviour.defaultCoordinates.zoom_level);
|
||||
if(!useDefault) {
|
||||
console.log('Using coordinates from data attributes');
|
||||
latitude = parseFloat(el.dataset.latitude);
|
||||
longitude = parseFloat(el.dataset.longitude);
|
||||
zoomLevel = parseInt(el.dataset.zoomLevel);
|
||||
}
|
||||
// console.log('lat', latitude);
|
||||
// console.log('long', longitude);
|
||||
// console.log('zoom', zoomLevel);
|
||||
|
||||
this.maps[index] = L.map(el).setView([latitude, longitude], zoomLevel);
|
||||
this.maps[index].on('click', this.onMapClick.bind(this));
|
||||
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 19,
|
||||
referrerPolicy: 'origin-when-cross-origin',
|
||||
attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
|
||||
}).addTo(this.maps[index]);
|
||||
},
|
||||
respondToTabSwitch(event) {
|
||||
// event.target // newly activated tab
|
||||
// event.relatedTarget // previous active tab
|
||||
|
||||
@@ -47,7 +47,13 @@ import {addSplit} from "./shared/add-split.js";
|
||||
import {clearDestinationAccount, clearSourceAccount} from "./shared/clear-fields.js";
|
||||
import {detectTransactionType} from "./shared/detect-transaction-type.js";
|
||||
import {determineAmountCurrency} from "./shared/determine-amount-currency.js";
|
||||
|
||||
import {loadCustomFields} from './shared/load-custom-fields.js';
|
||||
import {displayMap} from "./shared/display-map.js";
|
||||
import {loadDefaultCoordinates} from './shared/load-default-coordinates.js';
|
||||
import {renderMap} from './shared/render-map.js';
|
||||
import 'leaflet/dist/leaflet.css';
|
||||
import {onMapClick} from './shared/on-map-click.js';
|
||||
import {onMapZoom} from './shared/on-map-zoom.js';
|
||||
// TODO upload attachments to other file
|
||||
// TODO fix two maps, perhaps disconnect from entries entirely.
|
||||
// TODO group title
|
||||
@@ -67,6 +73,10 @@ let transactions = function () {
|
||||
entries: [],
|
||||
originals: [],
|
||||
|
||||
// maps are stored in this array so they can be referred to.
|
||||
maps: [],
|
||||
markers: [],
|
||||
|
||||
// state of the form is stored in formState:
|
||||
formStates: {
|
||||
loadingCurrencies: true,
|
||||
@@ -87,6 +97,12 @@ let transactions = function () {
|
||||
foreignCurrencyEnabled: true,
|
||||
categorySelectVisible: false,
|
||||
customFields: {},
|
||||
defaultCoordinates: {
|
||||
loaded: false,
|
||||
latitude: 30,
|
||||
longitude: 20,
|
||||
zoom_level: 9,
|
||||
},
|
||||
},
|
||||
|
||||
// form data (except transactions) is stored in formData
|
||||
@@ -136,6 +152,12 @@ let transactions = function () {
|
||||
detectTransactionType: detectTransactionType,
|
||||
determineAmountCurrency: determineAmountCurrency,
|
||||
addAllAutocompleteToForm: addAllAutocompleteToForm,
|
||||
loadCustomFields: loadCustomFields,
|
||||
displayMap: displayMap,
|
||||
loadDefaultCoordinates: loadDefaultCoordinates,
|
||||
renderMap: renderMap,
|
||||
onMapClick: onMapClick,
|
||||
onMapZoom: onMapZoom,
|
||||
|
||||
|
||||
// part of the account selection auto-complete
|
||||
@@ -159,7 +181,18 @@ let transactions = function () {
|
||||
getTags(index) {
|
||||
return this.entries[index].tags ?? [];
|
||||
},
|
||||
clearLocation(e) {
|
||||
|
||||
let index = parseInt(e.currentTarget.dataset.index);
|
||||
this.entries[index].hasLocation = false;
|
||||
this.entries[index].latitude = null;
|
||||
this.entries[index].longitude = null;
|
||||
this.entries[index].zoom_level = null;
|
||||
|
||||
if(this.markers.hasOwnProperty(index)) {
|
||||
this.maps[index].removeLayer(this.markers[index]);
|
||||
}
|
||||
},
|
||||
getTransactionGroup() {
|
||||
this.entries = [];
|
||||
const page = window.location.href.split('/');
|
||||
@@ -271,22 +304,23 @@ let transactions = function () {
|
||||
document.addEventListener('upload-error', (event) => {
|
||||
this.processUploadError(event);
|
||||
});
|
||||
document.addEventListener('location-move', (event) => {
|
||||
this.entries[event.detail.index].latitude = event.detail.latitude;
|
||||
this.entries[event.detail.index].longitude = event.detail.longitude;
|
||||
});
|
||||
// document.addEventListener('location-move', (event) => {
|
||||
// this.entries[event.detail.index].latitude = event.detail.latitude;
|
||||
// this.entries[event.detail.index].longitude = event.detail.longitude;
|
||||
// });
|
||||
|
||||
document.addEventListener('location-set', (event) => {
|
||||
this.entries[event.detail.index].hasLocation = true;
|
||||
this.entries[event.detail.index].latitude = event.detail.latitude;
|
||||
this.entries[event.detail.index].longitude = event.detail.longitude;
|
||||
this.entries[event.detail.index].zoomLevel = event.detail.zoomLevel;
|
||||
});
|
||||
// document.addEventListener('location-set', (event) => {
|
||||
// this.entries[event.detail.index].hasLocation = true;
|
||||
// this.entries[event.detail.index].latitude = event.detail.latitude;
|
||||
// this.entries[event.detail.index].longitude = event.detail.longitude;
|
||||
// this.entries[event.detail.index].zoom_level = event.detail.zoomLevel;
|
||||
// });
|
||||
|
||||
document.addEventListener('location-zoom', (event) => {
|
||||
this.entries[event.detail.index].hasLocation = true;
|
||||
this.entries[event.detail.index].zoomLevel = event.detail.zoomLevel;
|
||||
});
|
||||
// document.addEventListener('location-zoom', (event) => {
|
||||
// console.log('this happens?');
|
||||
// this.entries[event.detail.index].hasLocation = true;
|
||||
// this.entries[event.detail.index].zoom_level = event.detail.zoomLevel;
|
||||
// });
|
||||
},
|
||||
|
||||
|
||||
|
||||
@@ -104,7 +104,7 @@ export function createEmptySplit() {
|
||||
hasLocation: false,
|
||||
latitude: null,
|
||||
longitude: null,
|
||||
zoomLevel: null,
|
||||
zoom_level: null,
|
||||
|
||||
|
||||
// date and time
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
export function displayMap(index) {
|
||||
index = parseInt(index);
|
||||
// show location?
|
||||
if (true === this.formBehaviour.customFields.location) {
|
||||
if(true === this.entries[index].hasLocation) {
|
||||
this.renderMap(index, false);
|
||||
return;
|
||||
}
|
||||
if (false === this.formBehaviour.defaultCoordinates.loaded) {
|
||||
// load first, then show map.
|
||||
this.loadDefaultCoordinates().then(data => {
|
||||
this.formBehaviour.defaultCoordinates = data;
|
||||
this.renderMap(index, true);
|
||||
});
|
||||
return;
|
||||
}
|
||||
this.renderMap(index, false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
|
||||
import L from 'leaflet';
|
||||
import markerIcon from "leaflet/dist/images/marker-icon.png";
|
||||
import markerRetinaIcon from "leaflet/dist/images/marker-icon-2x.png";
|
||||
import shadow from 'leaflet/dist/images/marker-shadow.png';
|
||||
export function onMapClick(event) {
|
||||
|
||||
L.Marker.prototype.setIcon(L.icon({
|
||||
iconUrl: markerIcon,
|
||||
iconRetinaIcon: markerRetinaIcon,
|
||||
shadowUrl: shadow,
|
||||
iconSize: [25, 41],
|
||||
iconAnchor: [12, 41]
|
||||
}));
|
||||
|
||||
|
||||
let index = parseInt(event.originalEvent.currentTarget.dataset.index);
|
||||
this.entries[index].hasLocation = true;
|
||||
this.entries[index].latitude = event.latlng.lat;
|
||||
this.entries[index].longitude = event.latlng.lng;
|
||||
this.entries[index].zoom_level = this.maps[index].getZoom();
|
||||
|
||||
// add marker.
|
||||
if(this.markers.hasOwnProperty(index)) {
|
||||
this.maps[index].removeLayer(this.markers[index]);
|
||||
}
|
||||
this.markers[index] = L.marker(event.latlng);
|
||||
this.markers[index].addTo(this.maps[index]);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
|
||||
import L from 'leaflet';
|
||||
import markerIcon from "leaflet/dist/images/marker-icon.png";
|
||||
import markerRetinaIcon from "leaflet/dist/images/marker-icon-2x.png";
|
||||
import shadow from 'leaflet/dist/images/marker-shadow.png';
|
||||
export function onMapZoom(event) {
|
||||
let index = parseInt(event.target._container.dataset.index);
|
||||
this.entries[index].zoom_level = this.maps[index].getZoom();
|
||||
}
|
||||
@@ -86,7 +86,7 @@ export function parseDownloadedSplits(downloads, groupId) {
|
||||
current.hasLocation = true;
|
||||
current.latitude = download.latitude;
|
||||
current.longitude = download.longitude;
|
||||
current.zoomLevel = download.zoom_level;
|
||||
current.zoom_level = download.zoom_level;
|
||||
}
|
||||
returnArray.push(current);
|
||||
}
|
||||
|
||||
@@ -70,13 +70,15 @@ export function parseFromEntries(entries, originals, transactionType) {
|
||||
current.external_url = entry.external_url;
|
||||
|
||||
// location
|
||||
current.store_location = false;
|
||||
current.longitude = null;
|
||||
current.latitude = null;
|
||||
current.zoom_level = null;
|
||||
if (entry.hasLocation) {
|
||||
current.store_location = true;
|
||||
current.longitude = entry.longitude.toString();
|
||||
current.latitude = entry.latitude.toString();
|
||||
current.zoom_level = entry.zoomLevel;
|
||||
current.zoom_level = entry.zoom_level;
|
||||
}
|
||||
console.log('Zoom level is now ', entry.zoom_level);
|
||||
if ('__NO_CODE__' === entry.foreign_currency_code) {
|
||||
entry.foreign_currency_code = '';
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
|
||||
import L from 'leaflet';
|
||||
import markerIcon from "leaflet/dist/images/marker-icon.png";
|
||||
import markerRetinaIcon from "leaflet/dist/images/marker-icon-2x.png";
|
||||
import shadow from 'leaflet/dist/images/marker-shadow.png';
|
||||
|
||||
export function renderMap(index, useDefault) {
|
||||
const el = document.getElementById('location_map_' + index);
|
||||
let latitude = parseFloat(this.formBehaviour.defaultCoordinates.latitude);
|
||||
let longitude = parseFloat(this.formBehaviour.defaultCoordinates.longitude);
|
||||
let zoomLevel = parseInt(this.formBehaviour.defaultCoordinates.zoom_level);
|
||||
if(!useDefault) {
|
||||
console.log('Using coordinates from data attributes');
|
||||
latitude = parseFloat(el.dataset.latitude);
|
||||
longitude = parseFloat(el.dataset.longitude);
|
||||
zoomLevel = parseInt(el.dataset.zoomLevel);
|
||||
}
|
||||
|
||||
// console.log('lat', latitude);
|
||||
// console.log('long', longitude);
|
||||
// console.log('zoom', zoomLevel);
|
||||
|
||||
this.maps[index] = L.map(el).setView([latitude, longitude], zoomLevel);
|
||||
this.maps[index].on('click', this.onMapClick.bind(this));
|
||||
this.maps[index].on('zoom', this.onMapZoom.bind(this));
|
||||
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 19,
|
||||
referrerPolicy: 'origin-when-cross-origin',
|
||||
attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
|
||||
}).addTo(this.maps[index]);
|
||||
|
||||
if('true' === el.dataset.addMarker) {
|
||||
L.Marker.prototype.setIcon(L.icon({
|
||||
iconUrl: markerIcon,
|
||||
iconRetinaIcon: markerRetinaIcon,
|
||||
shadowUrl: shadow,
|
||||
iconSize: [25, 41],
|
||||
iconAnchor: [12, 41]
|
||||
}));
|
||||
|
||||
// add marker.
|
||||
if(this.markers.hasOwnProperty(index)) {
|
||||
this.maps[index].removeLayer(this.markers[index]);
|
||||
}
|
||||
this.markers[index] = L.marker([latitude, longitude]);
|
||||
this.markers[index].addTo(this.maps[index]);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -23,6 +23,7 @@ import sidebar from '../../pages/shared/sidebar.js';
|
||||
import dates from '../shared/dates.js';
|
||||
import i18next from "i18next";
|
||||
import Get from '../../api/model/transaction/get.js';
|
||||
import {format} from "date-fns";
|
||||
|
||||
let show = function () {
|
||||
return {
|
||||
@@ -45,7 +46,16 @@ let show = function () {
|
||||
downloadTransactionGroup() {
|
||||
(new Get()).show(this.group.id).then((response) => {
|
||||
const info = response.data.data;
|
||||
this.group.transactions = info.attributes.transactions;
|
||||
this.group.transactions = [];
|
||||
for(let i =0;i<info.attributes.transactions.length;i++){
|
||||
if(info.attributes.transactions.hasOwnProperty(i)) {
|
||||
let current =info.attributes.transactions[i];
|
||||
current.dateObject = new Date(current.date);
|
||||
current.dateFormatted = format(current.dateObject, this.i18next.t('config.date_time_fns'))
|
||||
this.group.transactions.push(current);
|
||||
}
|
||||
}
|
||||
|
||||
this.loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"bootstrap5-autocomplete": "^1",
|
||||
"bootstrap5-tags": "^1.7.17",
|
||||
"cally": "^0.9.2",
|
||||
"date-fns": "4.4.0",
|
||||
"date-fns": "^4.4.0",
|
||||
"fullcalendar": "^7.0.1",
|
||||
"i18next": "^26.0.3",
|
||||
"i18next-chained-backend": "^5.0.0",
|
||||
@@ -20,7 +20,7 @@
|
||||
"i18next-localstorage-backend": "^4.2.0",
|
||||
"leaflet": "^1.9.4",
|
||||
"patch-package": "^8.0.1",
|
||||
"shepherd.js": "^15.2.2",
|
||||
"shepherd.js": "^11.2.0",
|
||||
"store": "^2.0.12"
|
||||
},
|
||||
"type": "module",
|
||||
|
||||
@@ -12,9 +12,10 @@
|
||||
<template x-if="true || 0 === index">
|
||||
<div class="col-sm-10">
|
||||
<div x-init="displayMap(index)"
|
||||
:data-longitude="formBehaviour.defaultCoordinates.longitude"
|
||||
:data-latitude="formBehaviour.defaultCoordinates.latitude"
|
||||
:data-zoom-level="formBehaviour.defaultCoordinates.zoom_level"
|
||||
:data-add-marker="transaction.hasLocation ? 'true' : 'false'"
|
||||
:data-longitude="transaction.longitude ?? formBehaviour.defaultCoordinates.longitude"
|
||||
:data-latitude="transaction.latitude ?? formBehaviour.defaultCoordinates.latitude"
|
||||
:data-zoom-level="transaction.zoom_level ?? formBehaviour.defaultCoordinates.zoom_level"
|
||||
|
||||
:id="'location_map_' + index" class="map-size location-map" :data-index="index"></div>
|
||||
<span class="muted small">
|
||||
@@ -22,7 +23,7 @@
|
||||
<span>{{ __('firefly.click_tap_location') }}</span>
|
||||
</template>
|
||||
<template x-if="transaction.hasLocation">
|
||||
<a :data-index="index" href="#" @click="clearLocation">{{ __('firefly.clear_location') }}</a>
|
||||
<a :data-index="index" href="#" @click.prevent="clearLocation">{{ __('firefly.clear_location') }}</a>
|
||||
</template>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -10,12 +10,7 @@
|
||||
<x-transaction.tab-list />
|
||||
<div class="tab-content" id="splitTabsContent">
|
||||
<template x-for="transaction,index in entries">
|
||||
<x-transaction.split
|
||||
:zoomLevel="$zoomLevel"
|
||||
:latitude="$latitude"
|
||||
:longitude="$longitude"
|
||||
:optionalFields="$optionalFields"
|
||||
:optionalDateFields="$optionalDateFields"></x-transaction.split>
|
||||
<x-transaction.split />
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -90,12 +90,9 @@
|
||||
<tr>
|
||||
<td class="thirty">{{ trans('list.date') }}</td>
|
||||
<td>
|
||||
<span class="date-time" data-date="{{ $first['date']->toIso8601ZuluString() }}" title="{{ $first['date']->isoFormat($dateTimeFormat) }}@if('' !== $first['date_tz']) ({{ trans('firefly.stored_in_tz', ['timezone' => $first['date_tz']]) }}, {{ trans('firefly.displayed_in_tz', ['timezone' => config('app.timezone')]) }})@endif">
|
||||
{{ $first['date']->isoFormat($dateTimeFormat) }}
|
||||
@if('' !== $first['date_tz'])
|
||||
({{ trans('firefly.stored_in_tz', ['timezone' => $first['date_tz']]) }})
|
||||
@endif
|
||||
</span>
|
||||
<template x-if="group.transactions.length > 0">
|
||||
<span x-text="group.transactions[0].dateFormatted" :title="group.transactions[0].date"></span>
|
||||
</template>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
@@ -363,12 +360,13 @@
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ __('firefly.transaction_journal_id') }}</td>
|
||||
<td>#{{ $journal['transaction_journal_id'] }}</td>
|
||||
<td class="w-30">{{ __('firefly.transaction_journal_id') }}</td>
|
||||
<td>#{{ $journal['transaction_journal_id'] }}
|
||||
</td>
|
||||
</tr>
|
||||
@if(null !== $journal['category_id'])
|
||||
<tr>
|
||||
<td class="thirty">{{ __('firefly.category') }}</td>
|
||||
<td class="w-30">{{ __('firefly.category') }}</td>
|
||||
<td>
|
||||
<a href="{{ route('categories.show', [$journal['category_id']]) }}">{{ $journal['category_name'] }}</a>
|
||||
</td>
|
||||
@@ -376,7 +374,7 @@
|
||||
@endif
|
||||
@if(null !== $journal['budget_id'] && $first['transaction_type_type'] === 'Withdrawal')
|
||||
<tr>
|
||||
<td class="forty">{{ __('firefly.budget') }}</td>
|
||||
<td class="w-30">{{ __('firefly.budget') }}</td>
|
||||
<td>
|
||||
<a href="{{ route('budgets.show', [$journal['budget_id']]) }}">{{ $journal['budget_name'] }}</a>
|
||||
</td>
|
||||
@@ -384,17 +382,25 @@
|
||||
@endif
|
||||
@if(null !== $journal['bill_id'] && $first['transaction_type_type'] === 'Withdrawal')
|
||||
<tr>
|
||||
<td class="forty">{{ __('firefly.bill') }}</td>
|
||||
<td class="w-30">{{ __('firefly.bill') }}</td>
|
||||
<td>
|
||||
<a href="{{ route('subscriptions.show', [$journal['bill_id']]) }}">{{ $journal['bill_name'] }}</a>
|
||||
</td>
|
||||
</tr>
|
||||
@endif
|
||||
@if(null !== $journal['location']['latitude'])
|
||||
<tr>
|
||||
<td class="w-30"> {{ __('firefly.location') }}</td>
|
||||
<td>
|
||||
<div id="map_index_0">Map here</div>
|
||||
</td>
|
||||
</tr>
|
||||
@endif
|
||||
<!-- other fields -->
|
||||
@foreach(['interest_date','book_date','process_date','due_date','payment_date','invoice_date'] as $dateField)
|
||||
@if(journal_has_meta($journal['transaction_journal_id'], $dateField))
|
||||
<tr>
|
||||
<td class="forty">{{ trans('list.' . $dateField) }}</td>
|
||||
<td class="w-30">{{ trans('list.' . $dateField) }}</td>
|
||||
<td>{{ journal_get_meta_date($journal['transaction_journal_id'], $dateField)->isoFormat($monthAndDayFormat) }}</td>
|
||||
</tr>
|
||||
@endif
|
||||
|
||||
Reference in New Issue
Block a user