Merge branch 'beta' into refactor/external-media-types
This commit is contained in:
@@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
".": "3.35.0-beta.0"
|
".": "3.36.0-beta.0"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,13 @@ All notable changes to PicPeak will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [3.36.0-beta.0](https://github.com/the-luap/picpeak/compare/v3.35.0-beta.0...v3.36.0-beta.0) (2026-05-04)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **events:** prefill admin email + admin picker on event creation ([3fe8e61](https://github.com/the-luap/picpeak/commit/3fe8e61bd1175e35dcb61604447e5d9c2e902ec5))
|
||||||
|
|
||||||
## [3.35.0-beta.0](https://github.com/the-luap/picpeak/compare/v3.34.2-beta.0...v3.35.0-beta.0) (2026-05-04)
|
## [3.35.0-beta.0](https://github.com/the-luap/picpeak/compare/v3.34.2-beta.0...v3.35.0-beta.0) (2026-05-04)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "picpeak-backend",
|
"name": "picpeak-backend",
|
||||||
"version": "3.35.0-beta.0",
|
"version": "3.36.0-beta.0",
|
||||||
"description": "Backend for PicPeak event photo sharing platform",
|
"description": "Backend for PicPeak event photo sharing platform",
|
||||||
"main": "server.js",
|
"main": "server.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "picpeak-frontend",
|
"name": "picpeak-frontend",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "3.35.0-beta.0",
|
"version": "3.36.0-beta.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
|||||||
@@ -1019,6 +1019,8 @@
|
|||||||
"welcomeMessagePlaceholder": "Willkommen zu unserem besonderen Tag! Laden Sie diese Erinnerungen gerne herunter und teilen Sie sie...",
|
"welcomeMessagePlaceholder": "Willkommen zu unserem besonderen Tag! Laden Sie diese Erinnerungen gerne herunter und teilen Sie sie...",
|
||||||
"hostEmailPlaceholder": "[email protected]",
|
"hostEmailPlaceholder": "[email protected]",
|
||||||
"adminEmailPlaceholder": "[email protected]",
|
"adminEmailPlaceholder": "[email protected]",
|
||||||
|
"adminEmailPickFromAdmins": "Aus Admins wählen:",
|
||||||
|
"adminEmailCustom": "Eigene E-Mail",
|
||||||
"securityAndAccess": "Sicherheit & Zugriff",
|
"securityAndAccess": "Sicherheit & Zugriff",
|
||||||
"accessAndSecurity": "Zugriff & Sicherheit",
|
"accessAndSecurity": "Zugriff & Sicherheit",
|
||||||
"enterPassword": "Passwort eingeben",
|
"enterPassword": "Passwort eingeben",
|
||||||
|
|||||||
@@ -356,6 +356,8 @@
|
|||||||
"welcomeMessagePlaceholder": "Welcome to our special day! Feel free to download and share these memories...",
|
"welcomeMessagePlaceholder": "Welcome to our special day! Feel free to download and share these memories...",
|
||||||
"hostEmailPlaceholder": "[email protected]",
|
"hostEmailPlaceholder": "[email protected]",
|
||||||
"adminEmailPlaceholder": "[email protected]",
|
"adminEmailPlaceholder": "[email protected]",
|
||||||
|
"adminEmailPickFromAdmins": "Pick from admins:",
|
||||||
|
"adminEmailCustom": "Custom email",
|
||||||
"securityAndAccess": "Security & Access",
|
"securityAndAccess": "Security & Access",
|
||||||
"accessAndSecurity": "Access & Security",
|
"accessAndSecurity": "Access & Security",
|
||||||
"enterPassword": "Enter password",
|
"enterPassword": "Enter password",
|
||||||
|
|||||||
@@ -350,6 +350,8 @@
|
|||||||
"welcomeMessagePlaceholder": "Welkom bij onze bijzondere dag! Voel u vrij om deze herinneringen te downloaden en te delen...",
|
"welcomeMessagePlaceholder": "Welkom bij onze bijzondere dag! Voel u vrij om deze herinneringen te downloaden en te delen...",
|
||||||
"hostEmailPlaceholder": "[email protected]",
|
"hostEmailPlaceholder": "[email protected]",
|
||||||
"adminEmailPlaceholder": "[email protected]",
|
"adminEmailPlaceholder": "[email protected]",
|
||||||
|
"adminEmailPickFromAdmins": "Kies uit beheerders:",
|
||||||
|
"adminEmailCustom": "Aangepast e-mailadres",
|
||||||
"securityAndAccess": "Beveiliging & Toegang",
|
"securityAndAccess": "Beveiliging & Toegang",
|
||||||
"accessAndSecurity": "Toegang & Beveiliging",
|
"accessAndSecurity": "Toegang & Beveiliging",
|
||||||
"enterPassword": "Voer wachtwoord in",
|
"enterPassword": "Voer wachtwoord in",
|
||||||
|
|||||||
@@ -350,6 +350,8 @@
|
|||||||
"welcomeMessagePlaceholder": "Bem-vindo(a) ao nosso dia especial! Sinta-se à vontade para baixar e compartilhar essas memórias...",
|
"welcomeMessagePlaceholder": "Bem-vindo(a) ao nosso dia especial! Sinta-se à vontade para baixar e compartilhar essas memórias...",
|
||||||
"hostEmailPlaceholder": "[email protected]",
|
"hostEmailPlaceholder": "[email protected]",
|
||||||
"adminEmailPlaceholder": "[email protected]",
|
"adminEmailPlaceholder": "[email protected]",
|
||||||
|
"adminEmailPickFromAdmins": "Escolher entre administradores:",
|
||||||
|
"adminEmailCustom": "E-mail personalizado",
|
||||||
"securityAndAccess": "Segurança e Acesso",
|
"securityAndAccess": "Segurança e Acesso",
|
||||||
"accessAndSecurity": "Acesso e Segurança",
|
"accessAndSecurity": "Acesso e Segurança",
|
||||||
"enterPassword": "Digite a senha",
|
"enterPassword": "Digite a senha",
|
||||||
|
|||||||
@@ -350,6 +350,8 @@
|
|||||||
"welcomeMessagePlaceholder": "Добро пожаловать на наш особый день! Скачивайте и делитесь этими воспоминаниями...",
|
"welcomeMessagePlaceholder": "Добро пожаловать на наш особый день! Скачивайте и делитесь этими воспоминаниями...",
|
||||||
"hostEmailPlaceholder": "[email protected]",
|
"hostEmailPlaceholder": "[email protected]",
|
||||||
"adminEmailPlaceholder": "[email protected]",
|
"adminEmailPlaceholder": "[email protected]",
|
||||||
|
"adminEmailPickFromAdmins": "Выбрать из админов:",
|
||||||
|
"adminEmailCustom": "Произвольный e-mail",
|
||||||
"securityAndAccess": "Безопасность и доступ",
|
"securityAndAccess": "Безопасность и доступ",
|
||||||
"accessAndSecurity": "Доступ и безопасность",
|
"accessAndSecurity": "Доступ и безопасность",
|
||||||
"enterPassword": "Введите пароль",
|
"enterPassword": "Введите пароль",
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ import { settingsService } from '../../services/settings.service';
|
|||||||
import { usePublicSettings } from '../../hooks/usePublicSettings';
|
import { usePublicSettings } from '../../hooks/usePublicSettings';
|
||||||
import { cssTemplatesService } from '../../services/cssTemplates.service';
|
import { cssTemplatesService } from '../../services/cssTemplates.service';
|
||||||
import { eventTypesService } from '../../services/eventTypes.service';
|
import { eventTypesService } from '../../services/eventTypes.service';
|
||||||
|
import { userManagementService } from '../../services/userManagement.service';
|
||||||
|
import { useAdminAuth } from '../../contexts/AdminAuthContext';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { ThemeConfig, GALLERY_THEME_PRESETS } from '../../types/theme.types';
|
import { ThemeConfig, GALLERY_THEME_PRESETS } from '../../types/theme.types';
|
||||||
import { Code } from 'lucide-react';
|
import { Code } from 'lucide-react';
|
||||||
@@ -172,6 +174,41 @@ export const CreateEventPage: React.FC = () => {
|
|||||||
|
|
||||||
const { data: publicSettings } = usePublicSettings();
|
const { data: publicSettings } = usePublicSettings();
|
||||||
|
|
||||||
|
// Current logged-in admin (used to prefill the admin email field)
|
||||||
|
const { user: currentAdmin } = useAdminAuth();
|
||||||
|
|
||||||
|
// Optional: list of admin users — used to populate the email picker when
|
||||||
|
// there are multiple admins. Falls back to an empty list silently if the
|
||||||
|
// current user lacks `users.view` permission, so basic admins still get
|
||||||
|
// the auto-prefill from `currentAdmin` without errors surfacing.
|
||||||
|
const { data: adminUsers } = useQuery({
|
||||||
|
queryKey: ['admin-users-list'],
|
||||||
|
queryFn: async () => {
|
||||||
|
try {
|
||||||
|
return await userManagementService.getUsers();
|
||||||
|
} catch {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
staleTime: 5 * 60 * 1000,
|
||||||
|
retry: false
|
||||||
|
});
|
||||||
|
|
||||||
|
const activeAdmins = useMemo(
|
||||||
|
() => (adminUsers || []).filter(u => u.isActive !== false && !!u.email),
|
||||||
|
[adminUsers]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Auto-prefill admin email with the current user's email exactly once,
|
||||||
|
// and only if the field is still empty (don't clobber typed input).
|
||||||
|
const didPrefillAdminEmailRef = useRef(false);
|
||||||
|
useEffect(() => {
|
||||||
|
if (didPrefillAdminEmailRef.current) return;
|
||||||
|
if (!currentAdmin?.email) return;
|
||||||
|
didPrefillAdminEmailRef.current = true;
|
||||||
|
setFormData(prev => (prev.admin_email ? prev : { ...prev, admin_email: currentAdmin.email }));
|
||||||
|
}, [currentAdmin?.email]);
|
||||||
|
|
||||||
// Get field requirements (default to true if not set)
|
// Get field requirements (default to true if not set)
|
||||||
const requireCustomerName = publicSettings?.event_require_customer_name !== false;
|
const requireCustomerName = publicSettings?.event_require_customer_name !== false;
|
||||||
const requireCustomerEmail = publicSettings?.event_require_customer_email !== false;
|
const requireCustomerEmail = publicSettings?.event_require_customer_email !== false;
|
||||||
@@ -673,6 +710,31 @@ export const CreateEventPage: React.FC = () => {
|
|||||||
error={errors.admin_email}
|
error={errors.admin_email}
|
||||||
leftIcon={<Mail className="w-5 h-5" />}
|
leftIcon={<Mail className="w-5 h-5" />}
|
||||||
/>
|
/>
|
||||||
|
{activeAdmins.length > 1 && (
|
||||||
|
<div className="flex items-center gap-2 -mt-1">
|
||||||
|
<label htmlFor="admin-email-picker" className="text-xs text-neutral-600 dark:text-neutral-400 whitespace-nowrap">
|
||||||
|
{t('events.adminEmailPickFromAdmins', 'Pick from admins:')}
|
||||||
|
</label>
|
||||||
|
<select
|
||||||
|
id="admin-email-picker"
|
||||||
|
value={activeAdmins.some(a => a.email === formData.admin_email) ? formData.admin_email : ''}
|
||||||
|
onChange={(e) => {
|
||||||
|
const email = e.target.value;
|
||||||
|
if (email) {
|
||||||
|
setFormData(prev => ({ ...prev, admin_email: email }));
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
className="text-xs px-2 py-1 border border-neutral-300 dark:border-neutral-600 bg-white dark:bg-neutral-800 text-neutral-900 dark:text-neutral-100 rounded focus:ring-2 focus:ring-primary-500 focus:border-primary-500"
|
||||||
|
>
|
||||||
|
<option value="">{t('events.adminEmailCustom', 'Custom email')}</option>
|
||||||
|
{activeAdmins.map(a => (
|
||||||
|
<option key={a.id} value={a.email}>
|
||||||
|
{a.username} ({a.email})
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ import { api } from '../../config/api';
|
|||||||
import { buildResourceUrl, buildShareLinkUrl } from '../../utils/url';
|
import { buildResourceUrl, buildShareLinkUrl } from '../../utils/url';
|
||||||
import { isGalleryPublic, normalizeRequirePassword } from '../../utils/accessControl';
|
import { isGalleryPublic, normalizeRequirePassword } from '../../utils/accessControl';
|
||||||
import { archiveService } from '../../services/archive.service';
|
import { archiveService } from '../../services/archive.service';
|
||||||
import { externalMediaService } from '../../services/externalMedia.service';
|
import { externalMediaService, type ExternalEntry } from '../../services/externalMedia.service';
|
||||||
import { photosService, AdminPhoto, type PhotoFilters as PhotoFilterParams, type FeedbackFilters } from '../../services/photos.service';
|
import { photosService, AdminPhoto, type PhotoFilters as PhotoFilterParams, type FeedbackFilters } from '../../services/photos.service';
|
||||||
import { feedbackService, FeedbackSettings as FeedbackSettingsType } from '../../services/feedback.service';
|
import { feedbackService, FeedbackSettings as FeedbackSettingsType } from '../../services/feedback.service';
|
||||||
import { cssTemplatesService, type EnabledTemplate } from '../../services/cssTemplates.service';
|
import { cssTemplatesService, type EnabledTemplate } from '../../services/cssTemplates.service';
|
||||||
|
|||||||
Reference in New Issue
Block a user