mirror of
https://github.com/Dvorinka/MyClubServer.git
synced 2026-06-04 02:32:57 +00:00
gr
This commit is contained in:
@@ -116,7 +116,6 @@ const SetupPage: React.FC = () => {
|
|||||||
const [instagramUrl, setInstagramUrl] = useState('');
|
const [instagramUrl, setInstagramUrl] = useState('');
|
||||||
const [youtubeUrl, setYoutubeUrl] = useState('');
|
const [youtubeUrl, setYoutubeUrl] = useState('');
|
||||||
const [galleryUrl, setGalleryUrl] = useState('');
|
const [galleryUrl, setGalleryUrl] = useState('');
|
||||||
const [galleryLabel, setGalleryLabel] = useState('Fotogalerie');
|
|
||||||
|
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@@ -293,7 +292,6 @@ const SetupPage: React.FC = () => {
|
|||||||
instagram_url: instagramUrl || undefined,
|
instagram_url: instagramUrl || undefined,
|
||||||
youtube_url: youtubeUrl || undefined,
|
youtube_url: youtubeUrl || undefined,
|
||||||
gallery_url: galleryUrl || undefined,
|
gallery_url: galleryUrl || undefined,
|
||||||
gallery_label: galleryLabel || undefined,
|
|
||||||
// GPS location (optional)
|
// GPS location (optional)
|
||||||
location_latitude: typeof gpsLat === 'number' ? gpsLat : undefined,
|
location_latitude: typeof gpsLat === 'number' ? gpsLat : undefined,
|
||||||
location_longitude: typeof gpsLng === 'number' ? gpsLng : undefined,
|
location_longitude: typeof gpsLng === 'number' ? gpsLng : undefined,
|
||||||
@@ -564,7 +562,7 @@ const SetupPage: React.FC = () => {
|
|||||||
</FormControl>
|
</FormControl>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<FormLabel>URL loga klubu</FormLabel>
|
<FormLabel>URL loga klubu</FormLabel>
|
||||||
<Input value={clubLogoUrl} onChange={(e) => setClubLogoUrl(e.target.value)} />
|
<Input id="clubLogoUrlInput" value={clubLogoUrl} onChange={(e) => setClubLogoUrl(e.target.value)} />
|
||||||
<HStack mt={2} spacing={3}>
|
<HStack mt={2} spacing={3}>
|
||||||
<Button as="label" size="sm" leftIcon={<InfoOutlineIcon />}>
|
<Button as="label" size="sm" leftIcon={<InfoOutlineIcon />}>
|
||||||
Nahrát logo
|
Nahrát logo
|
||||||
@@ -572,6 +570,7 @@ const SetupPage: React.FC = () => {
|
|||||||
type="file"
|
type="file"
|
||||||
display="none"
|
display="none"
|
||||||
accept="image/*,image/svg+xml,application/pdf"
|
accept="image/*,image/svg+xml,application/pdf"
|
||||||
|
id="clubLogoFileInput"
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
const f = e.target.files?.[0] || null;
|
const f = e.target.files?.[0] || null;
|
||||||
// Process selected file
|
// Process selected file
|
||||||
@@ -695,10 +694,6 @@ const SetupPage: React.FC = () => {
|
|||||||
<Input placeholder="https://photos.example.com/club" value={galleryUrl} onChange={(e) => setGalleryUrl(e.target.value)} />
|
<Input placeholder="https://photos.example.com/club" value={galleryUrl} onChange={(e) => setGalleryUrl(e.target.value)} />
|
||||||
<FormHelperText>Můžete použít libovolný web (SmugMug, Flickr, Google Photos, Zonerama...).</FormHelperText>
|
<FormHelperText>Můžete použít libovolný web (SmugMug, Flickr, Google Photos, Zonerama...).</FormHelperText>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormControl>
|
|
||||||
<FormLabel>Popisek odkazu fotogalerie</FormLabel>
|
|
||||||
<Input placeholder="Fotogalerie" value={galleryLabel} onChange={(e) => setGalleryLabel(e.target.value)} />
|
|
||||||
</FormControl>
|
|
||||||
</SimpleGrid>
|
</SimpleGrid>
|
||||||
|
|
||||||
<Divider my={6} />
|
<Divider my={6} />
|
||||||
|
|||||||
@@ -4553,9 +4553,6 @@ func (bc *BaseController) UpdateSettings(c *gin.Context) {
|
|||||||
if body.MapStyle != nil {
|
if body.MapStyle != nil {
|
||||||
s.MapStyle = strings.TrimSpace(*body.MapStyle)
|
s.MapStyle = strings.TrimSpace(*body.MapStyle)
|
||||||
}
|
}
|
||||||
if body.ShowMapOnHomepage != nil {
|
|
||||||
s.ShowMapOnHomepage = *body.ShowMapOnHomepage
|
|
||||||
}
|
|
||||||
|
|
||||||
if s.ID == 0 {
|
if s.ID == 0 {
|
||||||
if err := bc.DB.Create(&s).Error; err != nil {
|
if err := bc.DB.Create(&s).Error; err != nil {
|
||||||
@@ -4569,6 +4566,11 @@ func (bc *BaseController) UpdateSettings(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
logger.Info("UpdateSettings saved: club_id=%s club_name=%s gallery_url=%s gallery_label=%s", s.ClubID, s.ClubName, s.GalleryURL, s.GalleryLabel)
|
logger.Info("UpdateSettings saved: club_id=%s club_name=%s gallery_url=%s gallery_label=%s", s.ClubID, s.ClubName, s.GalleryURL, s.GalleryLabel)
|
||||||
|
// Best-effort: trigger prefetch so cached settings.json and dependent files update immediately
|
||||||
|
go func() {
|
||||||
|
base := getPrefetchBaseURL()
|
||||||
|
services.PrefetchOnce(base)
|
||||||
|
}()
|
||||||
// If gallery_url is a Zonerama link, refresh Zonerama cache immediately
|
// If gallery_url is a Zonerama link, refresh Zonerama cache immediately
|
||||||
if g := strings.TrimSpace(s.GalleryURL); g != "" && strings.Contains(strings.ToLower(g), "zonerama.com") {
|
if g := strings.TrimSpace(s.GalleryURL); g != "" && strings.Contains(strings.ToLower(g), "zonerama.com") {
|
||||||
go func(link string) { _ = services.RefreshZoneramaNow(link) }(g)
|
go func(link string) { _ = services.RefreshZoneramaNow(link) }(g)
|
||||||
|
|||||||
@@ -521,12 +521,13 @@ func doPrefetchCycle(client *http.Client, baseURL string) {
|
|||||||
// 1) Static public endpoints
|
// 1) Static public endpoints
|
||||||
endpoints := map[string]string{
|
endpoints := map[string]string{
|
||||||
"/settings": "settings.json",
|
"/settings": "settings.json",
|
||||||
|
"/seo": "seo.json",
|
||||||
"/articles?page=1&page_size=10&published=true": "articles.json",
|
"/articles?page=1&page_size=10&published=true": "articles.json",
|
||||||
"/sponsors": "sponsors.json",
|
"/sponsors": "sponsors.json",
|
||||||
"/events/upcoming": "events_upcoming.json",
|
"/events/upcoming": "events_upcoming.json",
|
||||||
"/public/team-logo-overrides": "team_logo_overrides.json",
|
"/public/team-logo-overrides": "team_logo_overrides.json",
|
||||||
"/competition-aliases": "competition_aliases.json",
|
"/competition-aliases": "competition_aliases.json",
|
||||||
}
|
}
|
||||||
statuses = make([]epStatus, 0, len(endpoints))
|
statuses = make([]epStatus, 0, len(endpoints))
|
||||||
for path, file := range endpoints {
|
for path, file := range endpoints {
|
||||||
url := baseURL + path
|
url := baseURL + path
|
||||||
@@ -595,14 +596,25 @@ func doPrefetchCycle(client *http.Client, baseURL string) {
|
|||||||
|
|
||||||
// in-flight guard to avoid overlapping cycles
|
// in-flight guard to avoid overlapping cycles
|
||||||
var prefetchInFlight int32
|
var prefetchInFlight int32
|
||||||
|
var prefetchPending int32
|
||||||
|
|
||||||
func doPrefetchCycleGuarded(client *http.Client, baseURL string) {
|
func doPrefetchCycleGuarded(client *http.Client, baseURL string) {
|
||||||
if !atomic.CompareAndSwapInt32(&prefetchInFlight, 0, 1) {
|
if !atomic.CompareAndSwapInt32(&prefetchInFlight, 0, 1) {
|
||||||
log.Printf("[prefetch] skip: previous cycle still running")
|
// Mark a rerun so we don't lose triggers (e.g., from setup) while a cycle is running
|
||||||
return
|
atomic.StoreInt32(&prefetchPending, 1)
|
||||||
}
|
log.Printf("[prefetch] in-flight: marked pending rerun")
|
||||||
defer atomic.StoreInt32(&prefetchInFlight, 0)
|
return
|
||||||
doPrefetchCycle(client, baseURL)
|
}
|
||||||
|
defer func() {
|
||||||
|
atomic.StoreInt32(&prefetchInFlight, 0)
|
||||||
|
// If a trigger arrived during this run, execute one more cycle immediately
|
||||||
|
if atomic.SwapInt32(&prefetchPending, 0) == 1 {
|
||||||
|
// Small delay to allow DB/cache writes to settle
|
||||||
|
time.Sleep(500 * time.Millisecond)
|
||||||
|
doPrefetchCycleGuarded(client, baseURL)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
doPrefetchCycle(client, baseURL)
|
||||||
}
|
}
|
||||||
|
|
||||||
func isDuringMatch(cacheDir string) bool {
|
func isDuringMatch(cacheDir string) bool {
|
||||||
|
|||||||
Reference in New Issue
Block a user