Signed-off-by: Matt Bruce <mbrucedogs@gmail.com>
This commit is contained in:
parent
4b2d1dcf77
commit
278eacf493
11
.firebase/hosting.ZGlzdA.cache
Normal file
11
.firebase/hosting.ZGlzdA.cache
Normal file
@ -0,0 +1,11 @@
|
||||
index.html,1752878080470,9b8fdb94da9772e3fdc164ee7349299247c1dfda01634fd218d723f2224bf8c1
|
||||
assets/swipe-back-BPfbhfLI.js,1752878080470,e9d1df947b33957e85fc7bc25f337d7fcf4b9879fb28143ab647b02494cb407c
|
||||
assets/status-tap-C1_bc3dv.js,1752878080470,46852d45f5582135c63f4a06b1d45843a02f9923dc3a82176595f77c11659cba
|
||||
vite.svg,499162500000,699a02e0e68a579f687d364bbbe7633161244f35af068220aee37b1b33dfb3c7
|
||||
assets/md.transition-BWAHip3-.js,1752878080471,edab01bf56e19bf7f76626a7bcb126d46dbd7efde20e05ee7665e58f7138ae02
|
||||
assets/ios.transition-Bu_-K7p5.js,1752878080471,e1861e447c4450d0cce5b3a9a80f5094c2d3ed5217b75709d3721cea2a62f290
|
||||
assets/input-shims-D7jb4dA4.js,1752878080470,cedf2d57f4e43340fa0fdf87b33639681e89543af2bc5538cfa31d5deddb5d31
|
||||
assets/index7-Er27DGeg.js,1752878080470,1d42622024e40ddc65f4aa143043032c50a4db1bf5afbf932029a0f46cda7006
|
||||
assets/focus-visible-supuXXMI.js,1752878080471,df9266429356671847fa2c8123e1564bae645f75df3094f0055c365fa2beae28
|
||||
assets/index-B7vPvsG_.css,1752878080470,dbc57fb127dc9dde819d6ce6a258663f05013f29ec8905f282fe0087d44faaff
|
||||
assets/index-CuxN5P9G.js,1752878080471,f901d381eb7e4cb488c572bcf2b3f16f891065275c33a8aecd8aca451a70f540
|
||||
8
.firebaserc
Normal file
8
.firebaserc
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"projects": {
|
||||
"webapp": "sings-a-lot",
|
||||
"sings-a-lot-database": "firebase-herse"
|
||||
},
|
||||
"targets": {},
|
||||
"etags": {}
|
||||
}
|
||||
93
DEPLOYMENT.md
Normal file
93
DEPLOYMENT.md
Normal file
@ -0,0 +1,93 @@
|
||||
# Deployment Guide - Multi-Project Firebase Setup
|
||||
|
||||
This project uses a multi-project Firebase setup where:
|
||||
- **Web App**: Hosted on `sings-a-lot` project
|
||||
- **Database & Functions**: Hosted on `firebase-herse` project
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
sings-a-lot (webapp) ← Frontend hosting
|
||||
firebase-herse (database) ← Database, Functions, Rules
|
||||
```
|
||||
|
||||
## Deployment Commands
|
||||
|
||||
### Deploy Web App Only (to sings-a-lot)
|
||||
```bash
|
||||
npm run deploy:webapp
|
||||
```
|
||||
|
||||
### Deploy Database & Functions Only (to firebase-herse)
|
||||
```bash
|
||||
npm run deploy:database
|
||||
```
|
||||
|
||||
### Deploy Everything
|
||||
```bash
|
||||
npm run deploy:all
|
||||
```
|
||||
|
||||
## Manual Deployment Steps
|
||||
|
||||
### 1. Deploy Web App
|
||||
```bash
|
||||
# Build the app
|
||||
npm run build
|
||||
|
||||
# Switch to webapp project
|
||||
firebase use webapp
|
||||
|
||||
# Deploy hosting
|
||||
firebase deploy --only hosting
|
||||
```
|
||||
|
||||
### 2. Deploy Database & Functions
|
||||
```bash
|
||||
# Switch to database project
|
||||
firebase use sings-a-lot-database
|
||||
|
||||
# Deploy database rules and functions
|
||||
firebase deploy --only database,functions
|
||||
```
|
||||
|
||||
## Environment Configuration
|
||||
|
||||
Make sure your `.env` file points to the correct database project:
|
||||
|
||||
```env
|
||||
# These should point to firebase-herse (database project)
|
||||
VITE_FIREBASE_API_KEY=your-api-key
|
||||
VITE_FIREBASE_AUTH_DOMAIN=firebase-herse.firebaseapp.com
|
||||
VITE_FIREBASE_DATABASE_URL=https://firebase-herse-default-rtdb.firebaseio.com
|
||||
VITE_FIREBASE_PROJECT_ID=firebase-herse
|
||||
VITE_FIREBASE_STORAGE_BUCKET=firebase-herse.appspot.com
|
||||
VITE_FIREBASE_MESSAGING_SENDER_ID=123456789
|
||||
VITE_FIREBASE_APP_ID=your-app-id
|
||||
|
||||
# App Configuration
|
||||
VITE_CONTROLLER_NAME=default
|
||||
VITE_APP_TITLE=SingSalot AI
|
||||
```
|
||||
|
||||
## Firebase Project Aliases
|
||||
|
||||
- `webapp` → `sings-a-lot` (frontend hosting)
|
||||
- `sings-a-lot-database` → `firebase-herse` (database, functions, rules)
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### If you get permission errors:
|
||||
1. Make sure you're logged into Firebase CLI: `firebase login`
|
||||
2. Check your project access: `firebase projects:list`
|
||||
3. Verify project aliases: `firebase use`
|
||||
|
||||
### If database connection fails:
|
||||
1. Check that your `.env` file points to the correct database project
|
||||
2. Verify database rules are deployed to the correct project
|
||||
3. Check Firebase console for the correct project
|
||||
|
||||
### If functions don't work:
|
||||
1. Make sure functions are deployed to the database project
|
||||
2. Check function logs: `firebase functions:log`
|
||||
3. Verify function configuration in `functions/src/index.ts`
|
||||
@ -7,5 +7,40 @@
|
||||
},
|
||||
"database": {
|
||||
"rules": "database.rules.json"
|
||||
},
|
||||
"hosting": {
|
||||
"public": "dist",
|
||||
"ignore": [
|
||||
"firebase.json",
|
||||
"**/.*",
|
||||
"**/node_modules/**"
|
||||
],
|
||||
"rewrites": [
|
||||
{
|
||||
"source": "**",
|
||||
"destination": "/index.html"
|
||||
}
|
||||
]
|
||||
},
|
||||
"targets": {
|
||||
"webapp": {
|
||||
"hosting": {
|
||||
"sings-a-lot": [
|
||||
"sings-a-lot"
|
||||
]
|
||||
}
|
||||
},
|
||||
"sings-a-lot-database": {
|
||||
"functions": {
|
||||
"functions": [
|
||||
"firebase-herse"
|
||||
]
|
||||
},
|
||||
"database": {
|
||||
"rules": [
|
||||
"firebase-herse"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -7,7 +7,10 @@
|
||||
"dev": "vite",
|
||||
"build": "tsc -b && vite build",
|
||||
"lint": "eslint .",
|
||||
"preview": "vite preview"
|
||||
"preview": "vite preview",
|
||||
"deploy:webapp": "npm run build && firebase use webapp && firebase deploy --only hosting",
|
||||
"deploy:database": "firebase use sings-a-lot-database && firebase deploy --only database,functions",
|
||||
"deploy:all": "npm run build && firebase use webapp && firebase deploy --only hosting && firebase use sings-a-lot-database && firebase deploy --only database,functions"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ionic/core": "^8.6.5",
|
||||
|
||||
@ -4,7 +4,7 @@ import { add, heart, heartOutline, trash } from 'ionicons/icons';
|
||||
import ActionButton from './ActionButton';
|
||||
import { useAppSelector } from '../../redux';
|
||||
import { selectQueue, selectFavorites } from '../../redux';
|
||||
import type { SongItemProps } from '../../types';
|
||||
import type { SongItemProps, QueueItem, Song } from '../../types';
|
||||
|
||||
// Utility function to extract filename from path
|
||||
const extractFilename = (path: string): string => {
|
||||
@ -31,8 +31,8 @@ const SongItem: React.FC<SongItemProps> = ({
|
||||
const favorites = useAppSelector(selectFavorites);
|
||||
|
||||
// Check if song is in queue or favorites based on path
|
||||
const isInQueue = Object.values(queue).some(item => item.song.path === song.path);
|
||||
const isInFavorites = Object.values(favorites).some(favSong => favSong.path === song.path);
|
||||
const isInQueue = (Object.values(queue) as QueueItem[]).some(item => item.song.path === song.path);
|
||||
const isInFavorites = (Object.values(favorites) as Song[]).some(favSong => favSong.path === song.path);
|
||||
const renderActionPanel = () => {
|
||||
const buttons = [];
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { IonButton, IonIcon, IonReorderGroup, IonReorder, IonItem, IonLabel, IonItemSliding, IonItemOptions, IonItemOption } from '@ionic/react';
|
||||
import { trash, reorderThreeOutline, reorderTwoOutline, playCircle } from 'ionicons/icons';
|
||||
import { trash, reorderThreeOutline, reorderTwoOutline } from 'ionicons/icons';
|
||||
import { ActionButton } from '../../components/common';
|
||||
import { useQueue } from '../../hooks';
|
||||
import { useAppSelector } from '../../redux';
|
||||
@ -18,7 +18,6 @@ const Queue: React.FC = () => {
|
||||
|
||||
const {
|
||||
queueItems,
|
||||
queueStats,
|
||||
canReorder,
|
||||
handleRemoveFromQueue,
|
||||
} = useQueue();
|
||||
|
||||
@ -16,7 +16,7 @@ export const useSongOperations = () => {
|
||||
|
||||
try {
|
||||
// Calculate the next order by finding the highest order value and adding 1
|
||||
const queueItems = Object.values(currentQueue);
|
||||
const queueItems = Object.values(currentQueue) as QueueItem[];
|
||||
const maxOrder = queueItems.length > 0
|
||||
? Math.max(...queueItems.map(item => item.order || 0))
|
||||
: 0;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import type { RootState, QueueItem, Singer, Song } from '../types';
|
||||
import type { RootState, QueueItem, Singer, Song, SongList } from '../types';
|
||||
import {
|
||||
selectSongs,
|
||||
selectQueue,
|
||||
@ -108,7 +108,7 @@ export const selectSingersArray = createSelector(
|
||||
|
||||
export const selectSongListArray = createSelector(
|
||||
[selectSongList],
|
||||
(songList) => objectToArray(songList)
|
||||
(songList) => (objectToArray(songList) as SongList[])
|
||||
);
|
||||
|
||||
export const selectArtistsArray = createSelector(
|
||||
|
||||
Loading…
Reference in New Issue
Block a user