From aa1856acb7696223d8fc000f8674def915904fc3 Mon Sep 17 00:00:00 2001 From: Franzz Date: Fri, 8 May 2026 18:42:22 +0200 Subject: [PATCH] Fix media marker popup --- lib/Spot.php | 63 ++++++++++++++++++------------ src/components/project.vue | 7 ++-- src/components/projectPopup.vue | 31 +++++++++++---- src/components/spotIcon.vue | 36 +++++++++++------ src/styles/_page.project.feed.scss | 39 +++++++++--------- src/styles/_page.project.map.scss | 4 ++ 6 files changed, 113 insertions(+), 67 deletions(-) diff --git a/lib/Spot.php b/lib/Spot.php index f87b703..13e1f82 100755 --- a/lib/Spot.php +++ b/lib/Spot.php @@ -275,33 +275,38 @@ class Spot extends Main public function getMarkers($asMessageIds=array(), $asMediaIds=array(), $bInternal=false) { + //Get messages $asMessages = $this->getSpotMessages($asMessageIds); - $asGeoMedias = array(); - usort($asMessages, function($a, $b){return $a['unix_time'] > $b['unix_time'];}); - $bHasMsg = !empty($asMessages); - foreach($asMessages as &$asMessage) { - $asMessage['id'] = $asMessage[Db::getId(Feed::MSG_TABLE)]; - $asMessage['type'] = 'message'; - $asMessage['subtype'] = 'message'; + $asMessage['id'] = $asMessage[Db::getId(Feed::MSG_TABLE)]; + $asMessage['type'] = 'message'; + $asMessage['subtype'] = 'message'; } - //Add medias + //Get Geo-positioned Medias $asMedias = $this->getMedias('taken_on', $asMediaIds); - usort($asMedias, function($a, $b){return $a['unix_time'] > $b['unix_time'];}); + $asGeoMedias = $this->getMedias('posted_on', $asMediaIds, true); + foreach($asGeoMedias as &$asGeoMedia) { + $iId = $asGeoMedia[Db::getId(Media::MEDIA_TABLE)]; + unset($asGeoMedia[Db::getId(Media::MEDIA_TABLE)]); + + $asGeoMedia['id'] = $iId; + $asGeoMedia['type'] = 'media'; + $asGeoMedia['lat_dms'] = self::decToDms($asGeoMedia['latitude'], 'lat'); + $asGeoMedia['lon_dms'] = self::decToDms($asGeoMedia['longitude'], 'lon'); + $asGeoMedia['medias'] = array_values(array_filter($asMedias, function($asMedia) use ($iId) { + return $asMedia['id_media'] == $iId; + })); + } //Assign medias to closest message - $iIndex = 0; - $iMaxIndex = count($asMessages) - 1; - foreach($asMedias as $asMedia) { - if($asMedia['latitude']!='' && $asMedia['longitude']!='') { - $asMedia['id'] = $asMedia[Db::getId(Media::MEDIA_TABLE)]; - $asMedia['type'] = 'media'; - $asMedia['lat_dms'] = self::decToDms($asMedia['latitude'], 'lat'); - $asMedia['lon_dms'] = self::decToDms($asMedia['longitude'], 'lon'); - $asGeoMedias[] = $asMedia; - } - if($bHasMsg) { + if(!empty($asMessages)) { + usort($asMessages, function($a, $b){return $a['unix_time'] > $b['unix_time'];}); + usort($asMedias, function($a, $b){return $a['unix_time'] > $b['unix_time'];}); + + $iIndex = 0; + $iMaxIndex = count($asMessages) - 1; + foreach($asMedias as $asMedia) { while($iIndex <= $iMaxIndex && $asMedia['unix_time'] > $asMessages[$iIndex]['unix_time']) $iIndex++; //All medias before first message or after last message are assigned to first/last message respectively @@ -316,6 +321,7 @@ class Spot extends Main } } + //Combine markers $asMarkers = [...$asMessages, ...$asGeoMedias]; usort($asMarkers, function($a, $b){return $a['unix_time'] > $b['unix_time'];}); @@ -400,13 +406,19 @@ class Spot extends Main * @param String $sTimeRefField Field to calculate relative times: 'taken_on' or 'posted_on' * @return Array Medias info */ - private function getMedias($sTimeRefField, $asMediaIds=array()) + private function getMedias($sTimeRefField, $asMediaIds=array(), $bOnlyGeoMedia=false) { //Constraints $asConstraints = $this->getFeedConstraints(Media::MEDIA_TABLE, $sTimeRefField); if(!empty($asMediaIds)) { - $asConstraints['constraint'][Db::getId(Media::MEDIA_TABLE)] = $asMediaIds; $asConstraints['constOpe'][Db::getId(Media::MEDIA_TABLE)] = 'IN'; + $asConstraints['constraint'][Db::getId(Media::MEDIA_TABLE)] = $asMediaIds; + } + if($bOnlyGeoMedia) { + $asConstraints['constOpe']['latitude'] = ' IS NOT '; + $asConstraints['constraint']['latitude'] = 'NULL'; + $asConstraints['constOpe']['longitude'] = ' IS NOT '; + $asConstraints['constraint']['longitude'] = 'NULL'; } $asMedias = $this->oMedia->getMediasInfo($asConstraints); @@ -550,7 +562,6 @@ class Spot extends Main $this->oDb->cleanSql($sDirection); $this->oDb->cleanSql($sSort); - $sMediaRefField = 'posted_on'; $sProjectIdField = Db::getId(Project::PROJ_TABLE); $sMsgIdField = Db::getId(Feed::MSG_TABLE); $sMediaIdField = Db::getId(Media::MEDIA_TABLE); @@ -564,9 +575,9 @@ class Spot extends Main "INNER JOIN ".Feed::FEED_TABLE." USING({$sFeedIdField})", $this->getFeedConstraints(Feed::MSG_TABLE, 'site_time', 'sql'), "UNION", - "SELECT {$sProjectIdField}, {$sMediaIdField} AS id, 'media' AS type, CONCAT(UNIX_TIMESTAMP({$sMediaRefField}), '.1', {$sMediaIdField}) AS ref", + "SELECT {$sProjectIdField}, {$sMediaIdField} AS id, 'media' AS type, CONCAT(UNIX_TIMESTAMP(posted_on), '.1', {$sMediaIdField}) AS ref", "FROM ".Media::MEDIA_TABLE, - $this->getFeedConstraints(Media::MEDIA_TABLE, $sMediaRefField, 'sql'), + $this->getFeedConstraints(Media::MEDIA_TABLE, 'posted_on', 'sql'), "UNION", "SELECT {$sProjectIdField}, {$sPostIdField} AS id, 'post' AS type, CONCAT(UNIX_TIMESTAMP(site_time), '.2', {$sPostIdField}) AS ref", "FROM ".self::POST_TABLE, @@ -594,7 +605,7 @@ class Spot extends Main } $asFeedAttrs = array( 'message' => empty($asFeedIds['message'])?array():$this->getSpotMessages(array_keys($asFeedIds['message'])), - 'media' => empty($asFeedIds['media'])?array():$this->getMedias($sMediaRefField, array_keys($asFeedIds['media'])), + 'media' => empty($asFeedIds['media'])?array():$this->getMedias('posted_on', array_keys($asFeedIds['media'])), 'post' => empty($asFeedIds['post'])?array():$this->getPosts(array_keys($asFeedIds['post'])) ); diff --git a/src/components/project.vue b/src/components/project.vue index 1d10492..f225f81 100644 --- a/src/components/project.vue +++ b/src/components/project.vue @@ -29,7 +29,6 @@ export default { settingsPanelOpen: false, track: null, markers: [], - markerSize: {width: 32, height: 32}, markerProps: { image: {mainClasses: 'media', iconMain: 'marker', iconSub: 'image'}, video: {mainClasses: 'media', iconMain: 'marker', iconSub: 'video'}, @@ -304,12 +303,12 @@ export default { this.closePopup(); let oMarker = this.markers.find((oCandidate) => oCandidate.id == iMarkerId && oCandidate.type == sMarkerType); this.openPopup({ - offset: [0, this.markerSize.height * -1], //FIXME lnglat: [oMarker.longitude, oMarker.latitude], - options: oMarker + options: oMarker, + offset: [0, -32] //FIXME }); }, - openPopup({offset=[0, 0], lnglat, options={}} = {}) { + openPopup({lnglat, options={}, offset=[0, 0]} = {}) { const $Popup = document.createElement('div'); this.popup.element = new Popup({ anchor: 'bottom', diff --git a/src/components/projectPopup.vue b/src/components/projectPopup.vue index f3abc7e..dc0873f 100644 --- a/src/components/projectPopup.vue +++ b/src/components/projectPopup.vue @@ -17,11 +17,27 @@ export default { }, inject: ['lang', 'consts'], computed: { - timeIcon() { - return (this.options.type == 'media')?'image-shot':'time'; + timeinfo() { + return (this.options.type == 'media')? + { + icon: 'image-shot', + local_time: this.options.taken_on_formatted_time_local, + site_time: this.options.taken_on_formatted_time, + offset: this.options.taken_on_day_offset, + relative_time: this.options.taken_on_relative_time + }: + { + icon: 'time', + local_time: this.options.formatted_time_local, + site_time: this.options.formatted_time, + offset: this.options.day_offset, + relative_time: this.options.relative_time + }; }, - medias() { - return (this.options.type == 'media')?[this.options]:this.options?.medias; + localTime() { + return this.timeinfo.local_time + + ((this.project.mode == this.consts.modes.blog)?' (' + this.timeinfo.relative_time + ')':'') + ; } } } @@ -53,16 +69,15 @@ export default {
- - ({{ options.relative_time }}) +
-
+
- +
diff --git a/src/components/spotIcon.vue b/src/components/spotIcon.vue index ad2e4ba..4109411 100644 --- a/src/components/spotIcon.vue +++ b/src/components/spotIcon.vue @@ -18,7 +18,7 @@ export default { transform: String }, computed: { - classNames() { + iconClassNames() { return [ 'spot-icon', this.icon, @@ -49,23 +49,37 @@ export default { - + \ No newline at end of file diff --git a/src/styles/_page.project.feed.scss b/src/styles/_page.project.feed.scss index 825e473..b0e7daf 100644 --- a/src/styles/_page.project.feed.scss +++ b/src/styles/_page.project.feed.scss @@ -178,25 +178,28 @@ top: var.$block-spacing; right: var.$block-spacing; - .spot-icon { - font-size: 1.3em; - vertical-align: middle; - height: var.$block-spacing; - background: color.$message; - color: color.$message-bg; - border-radius: var.$block-radius 0 0 var.$block-radius; - padding: var.$elem-spacing; - margin-right: 0; - } + .spot-icon-with-text { + gap: 0; + + .spot-icon { + font-size: 1.3em; + vertical-align: middle; + height: var.$block-spacing; + background: color.$message; + color: color.$message-bg; + border-radius: var.$block-radius 0 0 var.$block-radius; + padding: var.$elem-spacing; + } - .temperature { - display: inline-block; - line-height: var.$block-spacing; - vertical-align: middle; - padding: var.$elem-spacing; - background: color.$message-bg; - color: color.$message; - border-radius: 0 var.$block-radius var.$block-radius 0; + .temperature { + display: inline-block; + line-height: var.$block-spacing; + vertical-align: middle; + padding: var.$elem-spacing; + background: color.$message-bg; + color: color.$message; + border-radius: 0 var.$block-radius var.$block-radius 0; + } } } diff --git a/src/styles/_page.project.map.scss b/src/styles/_page.project.map.scss index 931482a..601be8d 100644 --- a/src/styles/_page.project.map.scss +++ b/src/styles/_page.project.map.scss @@ -15,6 +15,10 @@ $thumbnail-max-size: 60px; max-width: 300px; } + .maplibregl-popup-tip { + border-top-color: color.$default-bg-light; + } + .maplibregl-popup-content { padding: var.$block-spacing; background-color: color.$default-bg-light;