Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
632efeeab5
|
|||
|
deeea9961f
|
|||
|
7a109c9ba5
|
|||
|
10aae3c9b3
|
|||
|
b492e2aa89
|
53
app/components/dropdown-menu.gjs
Normal file
53
app/components/dropdown-menu.gjs
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
import Component from '@glimmer/component';
|
||||||
|
import { tracked } from '@glimmer/tracking';
|
||||||
|
import { action } from '@ember/object';
|
||||||
|
import { on } from '@ember/modifier';
|
||||||
|
import Icon from '#components/icon';
|
||||||
|
|
||||||
|
export default class DropdownMenu extends Component {
|
||||||
|
@tracked isOpen = false;
|
||||||
|
|
||||||
|
@action
|
||||||
|
toggleMenu(e) {
|
||||||
|
e?.stopPropagation();
|
||||||
|
this.isOpen = !this.isOpen;
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
closeMenu(e) {
|
||||||
|
e?.stopPropagation();
|
||||||
|
this.isOpen = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
get triggerIcon() {
|
||||||
|
return this.args.triggerIcon || 'more-vertical';
|
||||||
|
}
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="dropdown-menu-container">
|
||||||
|
<button
|
||||||
|
class="dropdown-trigger-btn btn-press"
|
||||||
|
type="button"
|
||||||
|
title={{@triggerTitle}}
|
||||||
|
{{on "click" this.toggleMenu}}
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
@name={{this.triggerIcon}}
|
||||||
|
@size={{@iconSize}}
|
||||||
|
@color={{@iconColor}}
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{{#if this.isOpen}}
|
||||||
|
<div class="dropdown-popover {{@popoverClass}}">
|
||||||
|
{{yield this.closeMenu}}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="menu-backdrop"
|
||||||
|
{{on "click" this.closeMenu}}
|
||||||
|
role="button"
|
||||||
|
></div>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
}
|
||||||
@@ -33,6 +33,14 @@ export default class PhotoCarousel extends Component {
|
|||||||
return !this.canScrollRight;
|
return !this.canScrollRight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get isGalleryMain() {
|
||||||
|
return this.args.variant === 'gallery-main';
|
||||||
|
}
|
||||||
|
|
||||||
|
get isGalleryThumbnails() {
|
||||||
|
return this.args.variant === 'gallery-thumbnails';
|
||||||
|
}
|
||||||
|
|
||||||
get variantClass() {
|
get variantClass() {
|
||||||
return this.args.variant || 'inline';
|
return this.args.variant || 'inline';
|
||||||
}
|
}
|
||||||
@@ -205,29 +213,47 @@ export default class PhotoCarousel extends Component {
|
|||||||
/>
|
/>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if photo.isLandscape}}
|
{{#if this.isGalleryMain}}
|
||||||
<picture>
|
<img
|
||||||
{{#if photo.thumbUrl}}
|
data-src={{photo.url}}
|
||||||
<source
|
class="place-header-photo
|
||||||
media="(max-width: 768px)"
|
{{if photo.isLandscape 'landscape' 'portrait'}}"
|
||||||
data-srcset={{photo.thumbUrl}}
|
alt={{@name}}
|
||||||
/>
|
{{fadeInImage photo.url}}
|
||||||
{{/if}}
|
/>
|
||||||
<img
|
{{else if this.isGalleryThumbnails}}
|
||||||
data-src={{photo.url}}
|
|
||||||
class="place-header-photo landscape"
|
|
||||||
alt={{@name}}
|
|
||||||
{{fadeInImage photo.url}}
|
|
||||||
/>
|
|
||||||
</picture>
|
|
||||||
{{else}}
|
|
||||||
{{! Portrait uses thumb everywhere if available }}
|
|
||||||
<img
|
<img
|
||||||
data-src={{if photo.thumbUrl photo.thumbUrl photo.url}}
|
data-src={{if photo.thumbUrl photo.thumbUrl photo.url}}
|
||||||
class="place-header-photo portrait"
|
class="place-header-photo
|
||||||
|
{{if photo.isLandscape 'landscape' 'portrait'}}"
|
||||||
alt={{@name}}
|
alt={{@name}}
|
||||||
{{fadeInImage (if photo.thumbUrl photo.thumbUrl photo.url)}}
|
{{fadeInImage (if photo.thumbUrl photo.thumbUrl photo.url)}}
|
||||||
/>
|
/>
|
||||||
|
{{else}}
|
||||||
|
{{#if photo.isLandscape}}
|
||||||
|
<picture>
|
||||||
|
{{#if photo.thumbUrl}}
|
||||||
|
<source
|
||||||
|
media="(max-width: 768px)"
|
||||||
|
data-srcset={{photo.thumbUrl}}
|
||||||
|
/>
|
||||||
|
{{/if}}
|
||||||
|
<img
|
||||||
|
data-src={{photo.url}}
|
||||||
|
class="place-header-photo landscape"
|
||||||
|
alt={{@name}}
|
||||||
|
{{fadeInImage photo.url}}
|
||||||
|
/>
|
||||||
|
</picture>
|
||||||
|
{{else}}
|
||||||
|
{{! Portrait uses thumb everywhere if available }}
|
||||||
|
<img
|
||||||
|
data-src={{if photo.thumbUrl photo.thumbUrl photo.url}}
|
||||||
|
class="place-header-photo portrait"
|
||||||
|
alt={{@name}}
|
||||||
|
{{fadeInImage (if photo.thumbUrl photo.thumbUrl photo.url)}}
|
||||||
|
/>
|
||||||
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
import Component from '@glimmer/component';
|
import Component from '@glimmer/component';
|
||||||
import { tracked } from '@glimmer/tracking';
|
import { tracked } from '@glimmer/tracking';
|
||||||
|
import { inject as service } from '@ember/service';
|
||||||
import { action } from '@ember/object';
|
import { action } from '@ember/object';
|
||||||
import { on } from '@ember/modifier';
|
import { on } from '@ember/modifier';
|
||||||
import Icon from './icon';
|
import { fn } from '@ember/helper';
|
||||||
|
import Icon from '#components/icon';
|
||||||
import PhotoCarousel from './photo-carousel';
|
import PhotoCarousel from './photo-carousel';
|
||||||
|
import DropdownMenu from '#components/dropdown-menu';
|
||||||
|
|
||||||
export default class PhotoGallery extends Component {
|
export default class PhotoGallery extends Component {
|
||||||
|
@service toast;
|
||||||
@tracked currentPhoto = this.args.selectedPhoto || this.args.photos?.[0];
|
@tracked currentPhoto = this.args.selectedPhoto || this.args.photos?.[0];
|
||||||
|
|
||||||
@action
|
@action
|
||||||
@@ -21,7 +25,8 @@ export default class PhotoGallery extends Component {
|
|||||||
if (
|
if (
|
||||||
e.target.closest('.thumbnail-strip-container') ||
|
e.target.closest('.thumbnail-strip-container') ||
|
||||||
e.target.closest('.carousel-nav-btn') ||
|
e.target.closest('.carousel-nav-btn') ||
|
||||||
e.target.closest('.close-btn')
|
e.target.closest('.close-btn') ||
|
||||||
|
e.target.closest('.actions-btn-container')
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -41,6 +46,20 @@ export default class PhotoGallery extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
async copyEventId(closeMenu) {
|
||||||
|
if (this.currentPhoto?.eventId) {
|
||||||
|
try {
|
||||||
|
await navigator.clipboard.writeText(this.currentPhoto.eventId);
|
||||||
|
this.toast.show('Event ID copied to clipboard');
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Failed to copy event ID:', err);
|
||||||
|
this.toast.show('Failed to copy event ID');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closeMenu();
|
||||||
|
}
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class="photo-gallery-overlay"
|
class="photo-gallery-overlay"
|
||||||
@@ -50,6 +69,26 @@ export default class PhotoGallery extends Component {
|
|||||||
>
|
>
|
||||||
{{! template-lint-disable no-invalid-interactive }}
|
{{! template-lint-disable no-invalid-interactive }}
|
||||||
<div class="photo-gallery-content">
|
<div class="photo-gallery-content">
|
||||||
|
<div class="actions-btn-container">
|
||||||
|
<DropdownMenu
|
||||||
|
@iconSize={{24}}
|
||||||
|
@triggerIcon="more-horizontal"
|
||||||
|
@iconColor="white"
|
||||||
|
as |closeMenu|
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
class="dropdown-item"
|
||||||
|
type="button"
|
||||||
|
{{on "click" (fn this.copyEventId closeMenu)}}
|
||||||
|
>Copy Photo Event ID</button>
|
||||||
|
<button
|
||||||
|
class="dropdown-item"
|
||||||
|
type="button"
|
||||||
|
{{on "click" closeMenu}}
|
||||||
|
>Report Photo</button>
|
||||||
|
</DropdownMenu>
|
||||||
|
</div>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="close-btn btn-text"
|
class="close-btn btn-text"
|
||||||
|
|||||||
@@ -2027,3 +2027,63 @@ button.create-place {
|
|||||||
.photo-carousel.gallery-thumbnails .carousel-nav-btn {
|
.photo-carousel.gallery-thumbnails .carousel-nav-btn {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Dropdown Menu Component */
|
||||||
|
.dropdown-menu-container {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-trigger-btn {
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-popover {
|
||||||
|
position: absolute;
|
||||||
|
top: 100%;
|
||||||
|
left: 0;
|
||||||
|
margin-top: 5px;
|
||||||
|
background: white;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 4px 12px rgb(0 0 0 / 15%);
|
||||||
|
padding: 0.5rem 0;
|
||||||
|
z-index: 3001;
|
||||||
|
min-width: 150px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-item {
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
text-align: left;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
color: #333;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-item:hover {
|
||||||
|
background: #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Actions button in photo gallery */
|
||||||
|
.photo-gallery-overlay .actions-btn-container {
|
||||||
|
position: absolute;
|
||||||
|
top: 0.5rem;
|
||||||
|
left: 0.5rem;
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
z-index: 10;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ import mail from 'feather-icons/dist/icons/mail.svg?raw';
|
|||||||
import map from 'feather-icons/dist/icons/map.svg?raw';
|
import map from 'feather-icons/dist/icons/map.svg?raw';
|
||||||
import mapPin from 'feather-icons/dist/icons/map-pin.svg?raw';
|
import mapPin from 'feather-icons/dist/icons/map-pin.svg?raw';
|
||||||
import menu from 'feather-icons/dist/icons/menu.svg?raw';
|
import menu from 'feather-icons/dist/icons/menu.svg?raw';
|
||||||
|
import moreHorizontal from 'feather-icons/dist/icons/more-horizontal.svg?raw';
|
||||||
|
import moreVertical from 'feather-icons/dist/icons/more-vertical.svg?raw';
|
||||||
import navigation from 'feather-icons/dist/icons/navigation.svg?raw';
|
import navigation from 'feather-icons/dist/icons/navigation.svg?raw';
|
||||||
import phone from 'feather-icons/dist/icons/phone.svg?raw';
|
import phone from 'feather-icons/dist/icons/phone.svg?raw';
|
||||||
import plus from 'feather-icons/dist/icons/plus.svg?raw';
|
import plus from 'feather-icons/dist/icons/plus.svg?raw';
|
||||||
@@ -81,10 +83,6 @@ import iceCreamOnCone from '@waysidemapping/pinhead/dist/icons/ice_cream_on_cone
|
|||||||
import industrialBuilding from '@waysidemapping/pinhead/dist/icons/industrial_building.svg?raw';
|
import industrialBuilding from '@waysidemapping/pinhead/dist/icons/industrial_building.svg?raw';
|
||||||
import jewel from '@waysidemapping/pinhead/dist/icons/jewel.svg?raw';
|
import jewel from '@waysidemapping/pinhead/dist/icons/jewel.svg?raw';
|
||||||
import lowriseBuilding from '@waysidemapping/pinhead/dist/icons/lowrise_building.svg?raw';
|
import lowriseBuilding from '@waysidemapping/pinhead/dist/icons/lowrise_building.svg?raw';
|
||||||
import marketStall from '@waysidemapping/pinhead/dist/icons/market_stall.svg?raw';
|
|
||||||
import memorialStoneWithInscription from '@waysidemapping/pinhead/dist/icons/memorial_stone_with_inscription.svg?raw';
|
|
||||||
import mobilePhoneWithKeypadAndAntenna from '@waysidemapping/pinhead/dist/icons/mobile_phone_with_keypad_and_antenna.svg?raw';
|
|
||||||
import molarTooth from '@waysidemapping/pinhead/dist/icons/molar_tooth.svg?raw';
|
|
||||||
import needleAndSpoolOfThread from '@waysidemapping/pinhead/dist/icons/needle_and_spool_of_thread.svg?raw';
|
import needleAndSpoolOfThread from '@waysidemapping/pinhead/dist/icons/needle_and_spool_of_thread.svg?raw';
|
||||||
import openBook from '@waysidemapping/pinhead/dist/icons/open_book.svg?raw';
|
import openBook from '@waysidemapping/pinhead/dist/icons/open_book.svg?raw';
|
||||||
import palace from '@waysidemapping/pinhead/dist/icons/palace.svg?raw';
|
import palace from '@waysidemapping/pinhead/dist/icons/palace.svg?raw';
|
||||||
@@ -193,11 +191,9 @@ const ICONS = {
|
|||||||
mail,
|
mail,
|
||||||
map,
|
map,
|
||||||
'map-pin': mapPin,
|
'map-pin': mapPin,
|
||||||
'market-stall': marketStall,
|
|
||||||
'memorial-stone-with-inscription': memorialStoneWithInscription,
|
|
||||||
menu,
|
menu,
|
||||||
'mobile-phone-with-keypad-and-antenna': mobilePhoneWithKeypadAndAntenna,
|
'more-horizontal': moreHorizontal,
|
||||||
'molar-tooth': molarTooth,
|
'more-vertical': moreVertical,
|
||||||
navigation,
|
navigation,
|
||||||
'needle-and-spool-of-thread': needleAndSpoolOfThread,
|
'needle-and-spool-of-thread': needleAndSpoolOfThread,
|
||||||
nostrich,
|
nostrich,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "marco",
|
"name": "marco",
|
||||||
"version": "1.21.2",
|
"version": "1.21.3",
|
||||||
"private": true,
|
"private": true,
|
||||||
"description": "Unhosted maps app",
|
"description": "Unhosted maps app",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -39,8 +39,8 @@
|
|||||||
<meta name="msapplication-TileColor" content="#F6E9A6">
|
<meta name="msapplication-TileColor" content="#F6E9A6">
|
||||||
<meta name="msapplication-TileImage" content="/icons/icon-144.png">
|
<meta name="msapplication-TileImage" content="/icons/icon-144.png">
|
||||||
|
|
||||||
<script type="module" crossorigin src="/assets/main-CjxGWim8.js"></script>
|
<script type="module" crossorigin src="/assets/main-C_1D7C3-.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/main-M5C-HUrg.css">
|
<link rel="stylesheet" crossorigin href="/assets/main-BmLeTC2Y.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
Reference in New Issue
Block a user