Skip to content

Enhancement: Custom Market Resolution Labels with Emoji Support#522

Merged
pwdel merged 12 commits intomainfrom
enhancement/custom-market-resolution-labels
Oct 20, 2025
Merged

Enhancement: Custom Market Resolution Labels with Emoji Support#522
pwdel merged 12 commits intomainfrom
enhancement/custom-market-resolution-labels

Conversation

@raisch
Copy link
Collaborator

@raisch raisch commented Oct 7, 2025

NOTE: Pushed here by mistake. Mea culpa.

Enhancement: Custom Market Resolution Labels with Emoji Support

Overview

This PR introduces a comprehensive custom labeling system for markets, allowing users to create more expressive and contextual market options beyond the standard "YES/NO" labels. The implementation includes emoji picker integration and dynamic UI updates throughout the application.

IMPORTANT: This change is really only cosmetic as it only affects the UI by allowing new markets to use other text labels than 'YES' and 'NO'. There are no changes to the business logic which still uses 'YES' and 'NO' internally for market resolution.

Key Features

🎯 Custom Market Labels

  • Database Schema Updates: Added yes_label and no_label fields to the Market model
  • Backend API Enhancement: Updated market creation and response handlers to support custom labels
  • Validation: Implemented proper validation for custom labels (1-20 characters)
  • Fallback Support: Maintains backward compatibility with default "YES/NO" labels

😀 Emoji Picker Integration

  • New Component: Created reusable EmojiPickerInput component using emoji-picker-react
  • Smart Cursor Positioning: Emojis are inserted at the exact cursor position
  • Dark Theme: Matches application's existing design system
  • Mobile Friendly: Responsive design with touch support
  • Integration Points: Added to question title, description, and custom label fields

🎨 Dynamic UI Updates

  • Label Mapping Utility: Created getMarketLabels() function for consistent label retrieval
  • Market Display: Updated all market tables and cards to show custom labels
  • Trading Interface: Enhanced buy/sell buttons and trade forms with custom labels
  • Activity Components: Updated positions, bets, and leaderboard displays
  • Resolution Interface: Custom labels appear in resolution alerts and status indicators

🔄 Component-Wide Integration

Updated 18+ components across the application:

  • Market creation form with emoji support
  • Market detail pages and trading interfaces
  • Portfolio and profile components
  • Activity tabs (positions, bets, leaderboard)
  • Market tables and mobile cards
  • Resolution alerts and status displays

Technical Implementation

Backend Changes

  • models/market.go: Added custom label fields with validation
  • handlers/markets/createmarket.go: Updated market creation logic
  • handlers/marketpublicresponse/: Enhanced public API responses
  • Database migration support for new fields

Frontend Changes

  • New Components:
    • EmojiPickerInput.jsx: Reusable emoji-enabled input component
    • Enhanced label mapping utilities
  • Updated Components: Market creation, trading interfaces, activity displays
  • Dependencies: Added emoji-picker-react@4.14.0

Key Features

  • Cursor Management: Maintains input focus and cursor position after emoji insertion
  • Click-Outside Handling: Intuitive UX with proper picker dismissal
  • Form Validation: Client and server-side validation for custom labels
  • Backward Compatibility: Existing markets continue to work with default labels

User Experience Improvements

  • Enhanced Market Creation: Users can create more expressive markets (e.g., "BULL 🚀" vs "BEAR 📉")
  • Visual Clarity: Custom labels provide better context for market outcomes
  • Emoji Support: Easy emoji insertion across all text fields
  • Consistent Display: Custom labels appear consistently throughout the application
  • Mobile Optimization: Touch-friendly emoji picker and responsive design

Example Use Cases

  • Sports betting: "WIN 🏆" vs "LOSE 😞"
  • Stock predictions: "BULL 🚀" vs "BEAR 📉"
  • Weather forecasts: "SUNNY ☀️" vs "RAINY 🌧️"
  • Event outcomes: "HAPPENS ✅" vs "CANCELLED ❌"

Testing

  • ✅ Custom label validation (length, character limits)
  • ✅ Emoji insertion at cursor position
  • ✅ Backward compatibility with existing markets
  • ✅ Mobile responsiveness and touch interactions
  • ✅ Cross-component label consistency

Breaking Changes

None - this is a fully backward-compatible enhancement.

Migration Notes

  • New database fields are optional with default values
  • Existing markets automatically use "YES/NO" labels
  • No data migration required for existing deployments

This enhancement significantly improves the user experience by allowing more expressive and contextual market creation while maintaining full backward compatibility with existing functionality.

@pwdel pwdel self-requested a review October 8, 2025 01:16
@pwdel pwdel requested a review from astrosnat October 8, 2025 19:52
onChange(syntheticEvent);

// Update cursor position and focus back to input
setTimeout(() => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is where me not being a react/frontend developer becomes a problem, I wonder if there is a library for this type of thing?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@raisch ... the above being said, maybe we should have a sort of, "phase two," project to just hire a real react frontend developer specialist at some point to kind of refactor and improve a bunch of stuff overall for us and decrease our footprint?

Of course this might be more of a nice to have rather than need to have. I have approved the MR so we can get all of this in here. I have not tested but assume it all works.

We could merge to main if you're confident it works and then we can deploy main to brierfoxforecast.com, demo, then we can tag it with a new version once it works there without issue.

This will be a breaking change so we would push to v1.0.0

@pwdel pwdel added the enhancement New feature or request label Oct 8, 2025
Copy link
Member

@pwdel pwdel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

migration/ ... I believe, for the purposes of upgrading from 0.X.X to 1.X.X we will need a migration to be in place.

pwdel and others added 2 commits October 8, 2025 21:45
updated docker-compose-dev.yaml with new images so that local instances build properly
@astrosnat
Copy link
Collaborator

Screenshot 2025-10-09 120213 I get this out of the docker logs (specifically the backend) when trying to work out why I keep getting NS_ERR_NET_RESET AND NS_ERROR_CONNECTION_REFUSED

@ntoufoudis
Copy link
Collaborator

I like the idea of providing demo data and the option for the user to use that data for evaluation or whatever reason they want.

But I don't like the idea of creating so many files in the scripts directory.

I would prefer an approach where the .sql file and the golang code be included in the backend code. This way all the required code and files will be bundled inside the backend container and the end user can simply run a command like:
docker exec -i backend-container-name go run seed_markets.go to populate the data.

A way to remove these data should be nice as well.

@astrosnat
Copy link
Collaborator

migration/ ... I believe, for the purposes of upgrading from 0.X.X to 1.X.X we will need a migration to be in place.

I second that we need a migration - the automigrate isn't working properly on dev for me

@pwdel
Copy link
Member

pwdel commented Oct 9, 2025

migration/ ... I believe, for the purposes of upgrading from 0.X.X to 1.X.X we will need a migration to be in place.

I second that we need a migration - the automigrate isn't working properly on dev for me

It's possible that @astrosnat has some other issue relating to the local .env, she's going to try to work through that.

But that being said, if automigrate doesn't work on the market model, then we might want to explicitly create a specific migration that will help migrate from v0.0.7 to v1.0.0 ... she's going to get back to us when she works on this tomorrow.

re: #522 (comment)

FYI @raisch

@astrosnat
Copy link
Collaborator

I did find some stray postgres images that were about 8 months old, and I just deleted them. I'm going to do a clean install of this branch now and see what happens.

@ntoufoudis
Copy link
Collaborator

We are still in version v0.x.z . That means we are still in development process. So each pull request/fix/update/new-release/etc should be treated as a clean, new install. It's code update has the potential of breaking changes, so each new code should be treated as a clean install.

@astrosnat
Copy link
Collaborator

We are still in version v0.x.z . That means we are still in development process. So each pull request/fix/update/new-release/etc should be treated as a clean, new install. It's code update has the potential of breaking changes, so each new code should be treated as a clean install.

Yes, I generally completely nuke my old install before I test out a PR, and I thought I did that but forgot to clear up an old stray image. Lesson learned

Screenshot 2025-10-10 183958 Screenshot 2025-10-10 184142

Now I get this instead

@astrosnat
Copy link
Collaborator

Also these logs come from socialpredict-nginx-container for me

2025-10-10 18:37:18.534 | /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
2025-10-10 18:37:18.534 | /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
2025-10-10 18:37:18.538 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
2025-10-10 18:37:18.564 | 10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
2025-10-10 18:37:18.583 | 10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
2025-10-10 18:37:18.583 | /docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh
2025-10-10 18:37:18.584 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
2025-10-10 18:37:18.599 | 20-envsubst-on-templates.sh: Running envsubst on /etc/nginx/templates/default.conf.template to /etc/nginx/conf.d/default.conf
2025-10-10 18:37:18.605 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
2025-10-10 18:37:18.608 | /docker-entrypoint.sh: Configuration complete; ready for start up
2025-10-10 18:37:22.650 | 2025/10/10 11:37:18 [emerg] 1#1: host not found in upstream "backend" in /etc/nginx/conf.d/default.conf:5
2025-10-10 18:37:22.650 | nginx: [emerg] host not found in upstream "backend" in /etc/nginx/conf.d/default.conf:5
2025-10-10 18:37:24.954 | /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
2025-10-10 18:37:24.963 | /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
2025-10-10 18:37:24.963 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
2025-10-10 18:37:24.963 | 10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
2025-10-10 18:37:24.971 | 10-listen-on-ipv6-by-default.sh: info: /etc/nginx/conf.d/default.conf differs from the packaged version
2025-10-10 18:37:24.972 | /docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh
2025-10-10 18:37:24.972 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
2025-10-10 18:37:24.983 | 20-envsubst-on-templates.sh: Running envsubst on /etc/nginx/templates/default.conf.template to /etc/nginx/conf.d/default.conf
2025-10-10 18:37:24.988 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
2025-10-10 18:37:24.992 | /docker-entrypoint.sh: Configuration complete; ready for start up
2025-10-10 18:37:28.991 | 2025/10/10 11:37:24 [emerg] 1#1: host not found in upstream "backend" in /etc/nginx/conf.d/default.conf:5
2025-10-10 18:37:28.991 | nginx: [emerg] host not found in upstream "backend" in /etc/nginx/conf.d/default.conf:5
2025-10-10 18:37:31.542 | /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
2025-10-10 18:37:31.542 | /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
2025-10-10 18:37:31.545 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
2025-10-10 18:37:31.551 | 10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
2025-10-10 18:37:31.562 | 10-listen-on-ipv6-by-default.sh: info: /etc/nginx/conf.d/default.conf differs from the packaged version
2025-10-10 18:37:31.563 | /docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh
2025-10-10 18:37:31.563 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
2025-10-10 18:37:31.583 | 20-envsubst-on-templates.sh: Running envsubst on /etc/nginx/templates/default.conf.template to /etc/nginx/conf.d/default.conf
2025-10-10 18:37:31.590 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
2025-10-10 18:37:31.594 | /docker-entrypoint.sh: Configuration complete; ready for start up
2025-10-10 18:37:35.732 | 2025/10/10 11:37:31 [emerg] 1#1: host not found in upstream "backend" in /etc/nginx/conf.d/default.conf:5
2025-10-10 18:37:35.732 | nginx: [emerg] host not found in upstream "backend" in /etc/nginx/conf.d/default.conf:5
2025-10-10 18:37:37.743 | /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
2025-10-10 18:37:37.744 | /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
2025-10-10 18:37:37.746 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
2025-10-10 18:37:37.752 | 10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
2025-10-10 18:37:37.763 | 10-listen-on-ipv6-by-default.sh: info: /etc/nginx/conf.d/default.conf differs from the packaged version
2025-10-10 18:37:37.763 | /docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh
2025-10-10 18:37:37.763 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
2025-10-10 18:37:37.777 | 20-envsubst-on-templates.sh: Running envsubst on /etc/nginx/templates/default.conf.template to /etc/nginx/conf.d/default.conf
2025-10-10 18:37:37.783 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
2025-10-10 18:37:37.788 | /docker-entrypoint.sh: Configuration complete; ready for start up
2025-10-10 18:37:43.943 | /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
2025-10-10 18:37:43.944 | /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
2025-10-10 18:37:43.946 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
2025-10-10 18:37:43.965 | 10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
2025-10-10 18:37:43.980 | 10-listen-on-ipv6-by-default.sh: info: /etc/nginx/conf.d/default.conf differs from the packaged version
2025-10-10 18:37:43.981 | /docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh
2025-10-10 18:37:43.981 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
2025-10-10 18:37:43.994 | 20-envsubst-on-templates.sh: Running envsubst on /etc/nginx/templates/default.conf.template to /etc/nginx/conf.d/default.conf
2025-10-10 18:37:44.000 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
2025-10-10 18:37:44.005 | /docker-entrypoint.sh: Configuration complete; ready for start up
2025-10-10 18:37:47.817 | 2025/10/10 11:37:44 [emerg] 1#1: host not found in upstream "backend" in /etc/nginx/conf.d/default.conf:5
2025-10-10 18:37:47.817 | nginx: [emerg] host not found in upstream "backend" in /etc/nginx/conf.d/default.conf:5
2025-10-10 18:37:50.678 | /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
2025-10-10 18:37:50.678 | /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
2025-10-10 18:37:50.680 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
2025-10-10 18:37:50.688 | 10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
2025-10-10 18:37:50.699 | 10-listen-on-ipv6-by-default.sh: info: /etc/nginx/conf.d/default.conf differs from the packaged version
2025-10-10 18:37:50.700 | /docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh
2025-10-10 18:37:50.700 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
2025-10-10 18:37:50.713 | 20-envsubst-on-templates.sh: Running envsubst on /etc/nginx/templates/default.conf.template to /etc/nginx/conf.d/default.conf
2025-10-10 18:37:50.718 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
2025-10-10 18:37:50.721 | /docker-entrypoint.sh: Configuration complete; ready for start up
2025-10-10 18:37:56.785 | /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
2025-10-10 18:37:56.785 | /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
2025-10-10 18:37:56.787 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
2025-10-10 18:37:56.795 | 10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
2025-10-10 18:37:56.807 | 10-listen-on-ipv6-by-default.sh: info: /etc/nginx/conf.d/default.conf differs from the packaged version
2025-10-10 18:37:56.808 | /docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh
2025-10-10 18:37:56.808 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
2025-10-10 18:37:56.821 | 20-envsubst-on-templates.sh: Running envsubst on /etc/nginx/templates/default.conf.template to /etc/nginx/conf.d/default.conf
2025-10-10 18:37:56.826 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
2025-10-10 18:37:56.829 | /docker-entrypoint.sh: Configuration complete; ready for start up
2025-10-10 18:38:07.401 | /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
2025-10-10 18:38:07.401 | /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
2025-10-10 18:38:07.406 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
2025-10-10 18:38:07.413 | 10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
2025-10-10 18:38:07.427 | 10-listen-on-ipv6-by-default.sh: info: /etc/nginx/conf.d/default.conf differs from the packaged version
2025-10-10 18:38:07.428 | /docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh
2025-10-10 18:38:07.428 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
2025-10-10 18:38:07.441 | 20-envsubst-on-templates.sh: Running envsubst on /etc/nginx/templates/default.conf.template to /etc/nginx/conf.d/default.conf
2025-10-10 18:38:07.446 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
2025-10-10 18:38:07.451 | /docker-entrypoint.sh: Configuration complete; ready for start up
2025-10-10 18:38:15.413 | 2025/10/10 11:38:07 [emerg] 1#1: host not found in upstream "backend" in /etc/nginx/conf.d/default.conf:5
2025-10-10 18:38:15.414 | nginx: [emerg] host not found in upstream "backend" in /etc/nginx/conf.d/default.conf:5
2025-10-10 18:38:17.422 | /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
2025-10-10 18:38:17.422 | /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
2025-10-10 18:38:17.424 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
2025-10-10 18:38:17.433 | 10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
2025-10-10 18:38:17.447 | 10-listen-on-ipv6-by-default.sh: info: /etc/nginx/conf.d/default.conf differs from the packaged version
2025-10-10 18:38:17.447 | /docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh
2025-10-10 18:38:17.447 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
2025-10-10 18:38:17.460 | 20-envsubst-on-templates.sh: Running envsubst on /etc/nginx/templates/default.conf.template to /etc/nginx/conf.d/default.conf
2025-10-10 18:38:17.466 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
2025-10-10 18:38:17.469 | /docker-entrypoint.sh: Configuration complete; ready for start up
2025-10-10 18:38:17.480 | 2025/10/10 11:38:17 [notice] 1#1: using the "epoll" event method
2025-10-10 18:38:17.480 | 2025/10/10 11:38:17 [notice] 1#1: nginx/1.29.2
2025-10-10 18:38:17.480 | 2025/10/10 11:38:17 [notice] 1#1: built by gcc 14.2.0 (Debian 14.2.0-19)
2025-10-10 18:38:17.480 | 2025/10/10 11:38:17 [notice] 1#1: OS: Linux 5.15.167.4-microsoft-standard-WSL2
2025-10-10 18:38:17.480 | 2025/10/10 11:38:17 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2025-10-10 18:38:17.480 | 2025/10/10 11:38:17 [notice] 1#1: start worker processes
2025-10-10 18:38:17.481 | 2025/10/10 11:38:17 [notice] 1#1: start worker process 34
2025-10-10 18:38:17.481 | 2025/10/10 11:38:17 [notice] 1#1: start worker process 35
2025-10-10 18:38:17.482 | 2025/10/10 11:38:17 [notice] 1#1: start worker process 36
2025-10-10 18:38:17.483 | 2025/10/10 11:38:17 [notice] 1#1: start worker process 37
2025-10-10 18:38:17.483 | 2025/10/10 11:38:17 [notice] 1#1: start worker process 38
2025-10-10 18:38:17.484 | 2025/10/10 11:38:17 [notice] 1#1: start worker process 39
2025-10-10 18:38:17.485 | 2025/10/10 11:38:17 [notice] 1#1: start worker process 40
2025-10-10 18:38:17.486 | 2025/10/10 11:38:17 [notice] 1#1: start worker process 41
2025-10-10 18:38:17.486 | 2025/10/10 11:38:17 [notice] 1#1: start worker process 42
2025-10-10 18:38:17.487 | 2025/10/10 11:38:17 [notice] 1#1: start worker process 43
2025-10-10 18:38:17.488 | 2025/10/10 11:38:17 [notice] 1#1: start worker process 44
2025-10-10 18:38:17.489 | 2025/10/10 11:38:17 [notice] 1#1: start worker process 45
2025-10-10 18:38:17.490 | 2025/10/10 11:38:17 [notice] 1#1: start worker process 46
2025-10-10 18:38:17.491 | 2025/10/10 11:38:17 [notice] 1#1: start worker process 47
2025-10-10 18:38:17.492 | 2025/10/10 11:38:17 [notice] 1#1: start worker process 48
2025-10-10 18:38:17.493 | 2025/10/10 11:38:17 [notice] 1#1: start worker process 49
2025-10-10 18:38:36.172 | 2025/10/10 11:37:37 [emerg] 1#1: host not found in upstream "backend" in /etc/nginx/conf.d/default.conf:5
2025-10-10 18:38:36.172 | nginx: [emerg] host not found in upstream "backend" in /etc/nginx/conf.d/default.conf:5
2025-10-10 18:38:49.218 | 2025/10/10 11:37:50 [emerg] 1#1: host not found in upstream "backend" in /etc/nginx/conf.d/default.conf:5
2025-10-10 18:38:49.218 | nginx: [emerg] host not found in upstream "backend" in /etc/nginx/conf.d/default.conf:5
2025-10-10 18:38:59.249 | 2025/10/10 11:37:56 [emerg] 1#1: host not found in upstream "backend" in /etc/nginx/conf.d/default.conf:5
2025-10-10 18:38:59.249 | nginx: [emerg] host not found in upstream "backend" in /etc/nginx/conf.d/default.conf:5
2025-10-10 18:39:15.430 | 2025/10/10 11:39:15 [error] 35#35: *2 connect() failed (111: Connection refused) while connecting to upstream, client: 172.20.0.1, server: , request: "GET / HTTP/1.1", upstream: "http://172.19.0.2:5173/", host: "localhost"
2025-10-10 18:39:15.430 | 172.20.0.1 - - [10/Oct/2025:11:39:15 +0000] "GET / HTTP/1.1" 502 157 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:143.0) Gecko/20100101 Firefox/143.0" "-"
2025-10-10 18:39:15.623 | 2025/10/10 11:39:15 [error] 35#35: *2 connect() failed (111: Connection refused) while connecting to upstream, client: 172.20.0.1, server: , request: "GET /favicon.ico HTTP/1.1", upstream: "http://172.19.0.2:5173/favicon.ico", host: "localhost", referrer: "http://localhost/"
2025-10-10 18:39:15.623 | 172.20.0.1 - - [10/Oct/2025:11:39:15 +0000] "GET /favicon.ico HTTP/1.1" 502 157 "http://localhost/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:143.0) Gecko/20100101 Firefox/143.0" "-"
2025-10-10 18:39:18.279 | 2025/10/10 11:39:18 [error] 35#35: *2 connect() failed (111: Connection refused) while connecting to upstream, client: 172.20.0.1, server: , request: "GET / HTTP/1.1", upstream: "http://172.19.0.2:5173/", host: "localhost"
2025-10-10 18:39:18.279 | 172.20.0.1 - - [10/Oct/2025:11:39:18 +0000] "GET / HTTP/1.1" 502 157 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:143.0) Gecko/20100101 Firefox/143.0" "-"
2025-10-10 18:40:37.264 | 2025/10/10 11:40:37 [error] 36#36: *6 connect() failed (111: Connection refused) while connecting to upstream, client: 172.20.0.1, server: , request: "GET / HTTP/1.1", upstream: "http://172.19.0.2:5173/", host: "localhost"
2025-10-10 18:40:37.264 | 172.20.0.1 - - [10/Oct/2025:11:40:37 +0000] "GET / HTTP/1.1" 502 157 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:143.0) Gecko/20100101 Firefox/143.0" "-"
2025-10-10 18:40:37.384 | 172.20.0.1 - - [10/Oct/2025:11:40:37 +0000] "GET /favicon.ico HTTP/1.1" 499 0 "http://localhost/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:143.0) Gecko/20100101 Firefox/143.0" "-"

@ntoufoudis
Copy link
Collaborator

Are you deploying prod or dev?

@astrosnat
Copy link
Collaborator

Are you deploying prod or dev?

Dev version

@ntoufoudis
Copy link
Collaborator

The .env file is missing the API_URL entry.
Add API_URL='domain.com' in your .env.example file and start again with a clean install.

#530 is attempting to fix that, along with some other changes.

@astrosnat
Copy link
Collaborator

The .env file is missing the API_URL entry.
Add API_URL='domain.com' in your .env.example file and start again with a clean install.

#530 is attempting to fix that, along with some other changes.

Thanks so much, will try

@astrosnat
Copy link
Collaborator

@ntoufoudis yes once I merged #530 into here it worked :) thank you so much

@raisch now I'm going to take a full and proper look now that I can actually run a local instance

@pwdel
Copy link
Member

pwdel commented Oct 20, 2025

Tested locally after refactor. Did not add timestamped migration.

image

Seems to work fine with autoupdate. However I may not have pulled from a previous database, in which case we could create a specific timestamped for this feature if we run into a problem.

So basically, timestamped migration is optional at this point.

image

@pwdel
Copy link
Member

pwdel commented Oct 20, 2025

Had to do some devops changes here. Tested on dev mode, not local.

dev was pulling from ghcr.

local was pulling from the local image.

Attempted to switch these around.

@pwdel pwdel self-assigned this Oct 20, 2025
@pwdel
Copy link
Member

pwdel commented Oct 20, 2025

Fixed "Show" button.

image image

@pwdel
Copy link
Member

pwdel commented Oct 20, 2025

Double checked localhost based upon my changes.

Localhost pulls from ghcr, not locally built images, and works. Dev changes not reflecting on local (presume because no code mount). My understanding is that local is meant to be static, not a "dev/local" thing with mounted code.

image
### Select Application Environment:
1) Development
2) Localhost
3) Production
4) Quit
Please enter your choice: 2

Building for Localhost

== localhost platform: linux/amd64 ==
Wrote docker-compose.override.yml to pin platform = linux/amd64
.env file found. Re-create for localhost? (y/N) y
localhost .env prepared for GHCR images.
.env file re-created successfully.

Pulling images ...
[+] Pulling 4/4
 ✔ db Pulled                                                                                                                                                                                                                             0.6s
 ✔ backend Pulled                                                                                                                                                                                                                        0.5s
 ✔ webserver Pulled                                                                                                                                                                                                                      0.5s
 ✔ frontend Pulled                                                                                                                                                                                                                       0.5s
Images pulled.
patrick@mini ~/Documents/Projects/socialpredict (enhancement/custom-market-resolution-labels)
% ./SocialPredict up
Using compose file: /Users/patrick/Documents/Projects/socialpredict/scripts/docker-compose-local.yaml
[+] Running 6/6
 ✔ Network socialpredict_network               Created                                                                                                                                                                                   0.0s
 ✔ Volume "scripts_pgdata"                     Created                                                                                                                                                                                   0.0s
 ✔ Container socialpredict-postgres-container  Healthy                                                                                                                                                                                   2.8s
 ✔ Container socialpredict-backend-container   Started                                                                                                                                                                                   2.9s
 ✔ Container socialpredict-frontend-container  Started                                                                                                                                                                                   3.0s
 ✔ Container socialpredict-nginx-container     Started

@pwdel pwdel requested a review from ntoufoudis October 20, 2025 17:03
Comment on lines +44 to +45
# Strip quotes from values
line=$(echo "$line" | sed "s/='\([^']*\)'/=\1/g" | sed 's/="\([^"]*\)"/=\1/g')
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stripping quotes from values can have unexpected behavior depending on the value the variable is holding. If it includes special characters, etc.
Why go this approach?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@raisch FYI

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm. Hadn't considered that. Then again, it's been a long time since I had to write bash scripts. ;-)

The problem here is that without striping quotes you can end up with export foo=''bar'' (double single quotes) which would be BAD™ :-)

Perhaps it might be better to parse out {$NAME}={$VALUE}, strip quotes from value and then export $NAME="$VALUE"?

Thoughts?

Comment on lines +27 to +55
# Function to load .env file
load_env() {
local env_file="${1:-.env}"

if [ -f "$env_file" ]; then
print_status "Loading configuration from $env_file"

# Export variables from .env file, ignoring comments and empty lines
# Use a safer approach that handles special characters and comments
while IFS= read -r line; do
# Skip empty lines and comments
if [[ -z "$line" || "$line" =~ ^[[:space:]]*# ]]; then
continue
fi

# Export the variable if it contains an equals sign
if [[ "$line" =~ = ]]; then
# Strip quotes from values
line=$(echo "$line" | sed "s/='\([^']*\)'/=\1/g" | sed 's/="\([^"]*\)"/=\1/g')
export "$line"
fi
done < "$env_file"

print_status "Environment variables loaded successfully"
else
print_warning ".env file not found at $env_file"
print_warning "Using default values or existing environment variables"
fi
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why export variables and not just source the .env file in the bash script?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To trap error conditions.

In most versions of bash,source $FILEPATH where FILEPATH is empty or non-existent, bash will not complain.

# populate_markets.sh
# Script to populate the SocialPredict database with example markets

set -e
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest using

set -o errexit
set -o nounset
set -o pipefail

in all bash scripts as a precaution.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agreed

# Usage: ./seed_markets_go.sh [SQL_FILE]
# Default: example_markets.sql

set -e
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest using

set -o errexit
set -o nounset
set -o pipefail

in all bash scripts as a precaution.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lol. same issue, different file... in the previous comment you said 'in all bash scripts' ;)

@pwdel pwdel merged commit 78f0e69 into main Oct 20, 2025
12 checks passed
Copy link
Collaborator Author

@raisch raisch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

left comments

Comment on lines +44 to +45
# Strip quotes from values
line=$(echo "$line" | sed "s/='\([^']*\)'/=\1/g" | sed 's/="\([^"]*\)"/=\1/g')
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm. Hadn't considered that. Then again, it's been a long time since I had to write bash scripts. ;-)

The problem here is that without striping quotes you can end up with export foo=''bar'' (double single quotes) which would be BAD™ :-)

Perhaps it might be better to parse out {$NAME}={$VALUE}, strip quotes from value and then export $NAME="$VALUE"?

Thoughts?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fix Merge Conflicts and then Integrate Custom Labels Support with Timestamped Migration

4 participants