Spaces:
Running
Running
Upload folder using huggingface_hub
Browse files- Dockerfile +13 -3
- README.md +1 -1
- components/ChatPage.tsx +15 -9
- components/SimulationPage.tsx +32 -19
Dockerfile
CHANGED
|
@@ -7,9 +7,19 @@ RUN npm run build
|
|
| 7 |
|
| 8 |
FROM node:20-slim
|
| 9 |
WORKDIR /app
|
| 10 |
-
|
| 11 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
RUN npm install --only=production
|
| 13 |
-
COPY server.cjs ./
|
|
|
|
| 14 |
EXPOSE 7860
|
| 15 |
CMD ["node", "server.cjs"]
|
|
|
|
| 7 |
|
| 8 |
FROM node:20-slim
|
| 9 |
WORKDIR /app
|
| 10 |
+
|
| 11 |
+
# Create a non-root user
|
| 12 |
+
RUN useradd -m -u 1000 user
|
| 13 |
+
USER user
|
| 14 |
+
ENV HOME=/home/user \
|
| 15 |
+
PATH=/home/user/.local/bin:$PATH
|
| 16 |
+
|
| 17 |
+
WORKDIR $HOME/app
|
| 18 |
+
|
| 19 |
+
COPY --from=build --chown=user /app/dist ./dist
|
| 20 |
+
COPY --from=build --chown=user /app/package*.json ./
|
| 21 |
RUN npm install --only=production
|
| 22 |
+
COPY --chown=user server.cjs ./
|
| 23 |
+
|
| 24 |
EXPOSE 7860
|
| 25 |
CMD ["node", "server.cjs"]
|
README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
---
|
| 2 |
-
title:
|
| 3 |
emoji: 🔄
|
| 4 |
colorFrom: blue
|
| 5 |
colorTo: blue
|
|
|
|
| 1 |
---
|
| 2 |
+
title: Branding Content Testing
|
| 3 |
emoji: 🔄
|
| 4 |
colorFrom: blue
|
| 5 |
colorTo: blue
|
components/ChatPage.tsx
CHANGED
|
@@ -126,12 +126,19 @@ const ChatInput: React.FC<{ onSimulate: (msg: string) => void; onHelpMeCraft: (m
|
|
| 126 |
>
|
| 127 |
Help Me Craft <Sparkles size={12} />
|
| 128 |
</button>
|
| 129 |
-
<
|
| 130 |
-
|
| 131 |
-
|
| 132 |
-
|
| 133 |
-
|
| 134 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 135 |
</div>
|
| 136 |
</div>
|
| 137 |
</div>
|
|
@@ -270,7 +277,6 @@ const ChatPage: React.FC<ChatPageProps> = ({ onBack, simulationResult, setSimula
|
|
| 270 |
<h2 className="text-xl font-medium tracking-tight">New Simulation</h2>
|
| 271 |
</div>
|
| 272 |
<div className="flex items-center gap-4">
|
| 273 |
-
{simulationId && <span className="text-[10px] text-gray-500 uppercase tracking-widest hidden md:block">Active Group: {simulationId}</span>}
|
| 274 |
<button onClick={onBack} className="p-2 text-gray-500 hover:text-white hover:bg-gray-900 rounded-full transition-colors">
|
| 275 |
<X size={24} />
|
| 276 |
</button>
|
|
@@ -287,12 +293,12 @@ const ChatPage: React.FC<ChatPageProps> = ({ onBack, simulationResult, setSimula
|
|
| 287 |
<div className="flex-1">
|
| 288 |
<h4 className="font-semibold text-green-300 mb-1">Simulation Status</h4>
|
| 289 |
<p className="text-sm text-green-200/70 leading-relaxed">
|
| 290 |
-
The simulation process can take up to <strong className="text-white">30 minutes</strong>. Click "Gather Results" to fetch the latest state.
|
| 291 |
</p>
|
| 292 |
{simulationResult && (
|
| 293 |
<div className="mt-4 p-3 bg-black/40 rounded-xl border border-green-500/20 text-xs text-green-200 flex flex-col gap-3">
|
| 294 |
<div className="font-medium flex items-center gap-2">
|
| 295 |
-
<div className={`w-1.5 h-1.5 rounded-full ${simulationResult.status === 'Error' ? 'bg-red-500' : 'bg-green-500
|
| 296 |
{simulationResult.message}
|
| 297 |
</div>
|
| 298 |
{simulationResult.data && (
|
|
|
|
| 126 |
>
|
| 127 |
Help Me Craft <Sparkles size={12} />
|
| 128 |
</button>
|
| 129 |
+
<div className="flex gap-2">
|
| 130 |
+
<ChatButton
|
| 131 |
+
label="Send"
|
| 132 |
+
onClick={() => onSimulate(message)}
|
| 133 |
+
icon={<MessageSquare size={14} />}
|
| 134 |
+
/>
|
| 135 |
+
<ChatButton
|
| 136 |
+
label={isSimulating ? "Please wait..." : "Simulate"}
|
| 137 |
+
primary
|
| 138 |
+
onClick={() => onSimulate(message)}
|
| 139 |
+
icon={isSimulating ? <Loader2 size={14} className="animate-spin" /> : undefined}
|
| 140 |
+
/>
|
| 141 |
+
</div>
|
| 142 |
</div>
|
| 143 |
</div>
|
| 144 |
</div>
|
|
|
|
| 277 |
<h2 className="text-xl font-medium tracking-tight">New Simulation</h2>
|
| 278 |
</div>
|
| 279 |
<div className="flex items-center gap-4">
|
|
|
|
| 280 |
<button onClick={onBack} className="p-2 text-gray-500 hover:text-white hover:bg-gray-900 rounded-full transition-colors">
|
| 281 |
<X size={24} />
|
| 282 |
</button>
|
|
|
|
| 293 |
<div className="flex-1">
|
| 294 |
<h4 className="font-semibold text-green-300 mb-1">Simulation Status</h4>
|
| 295 |
<p className="text-sm text-green-200/70 leading-relaxed">
|
| 296 |
+
Please wait, the results will show here. The simulation process can take up to <strong className="text-white">30 minutes</strong>. Click "Gather Results" to fetch the latest state.
|
| 297 |
</p>
|
| 298 |
{simulationResult && (
|
| 299 |
<div className="mt-4 p-3 bg-black/40 rounded-xl border border-green-500/20 text-xs text-green-200 flex flex-col gap-3">
|
| 300 |
<div className="font-medium flex items-center gap-2">
|
| 301 |
+
<div className={`w-1.5 h-1.5 rounded-full ${simulationResult.status === 'Error' ? 'bg-red-500' : 'bg-green-500'}`}></div>
|
| 302 |
{simulationResult.message}
|
| 303 |
</div>
|
| 304 |
{simulationResult.data && (
|
components/SimulationPage.tsx
CHANGED
|
@@ -46,8 +46,8 @@ const VIEW_FILTERS: Record<string, Array<{ label: string; color: string }>> = {
|
|
| 46 |
const SimulationPage: React.FC<SimulationPageProps> = ({
|
| 47 |
onBack, onOpenConversation, onOpenChat, user, onLogin, simulationResult, setSimulationResult
|
| 48 |
}) => {
|
| 49 |
-
const [society, setSociety] = useState('
|
| 50 |
-
const [societies, setSocieties] = useState<string[]>([
|
| 51 |
const [viewMode, setViewMode] = useState('Job Title');
|
| 52 |
const [isRefreshing, setIsRefreshing] = useState(false);
|
| 53 |
const [isBuilding, setIsBuilding] = useState(false);
|
|
@@ -67,17 +67,22 @@ const SimulationPage: React.FC<SimulationPageProps> = ({
|
|
| 67 |
// Fetch real focus groups
|
| 68 |
const fetchSocieties = async () => {
|
| 69 |
try {
|
| 70 |
-
const
|
| 71 |
-
|
|
|
|
|
|
|
|
|
|
| 72 |
const names = list
|
| 73 |
-
.map((s: any) =>
|
| 74 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 75 |
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
setSociety(names[0]);
|
| 80 |
-
}
|
| 81 |
}
|
| 82 |
}
|
| 83 |
} catch (e) {
|
|
@@ -160,6 +165,14 @@ const SimulationPage: React.FC<SimulationPageProps> = ({
|
|
| 160 |
<div className="h-px bg-gray-800 my-4" />
|
| 161 |
|
| 162 |
{/* Actions */}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 163 |
<button
|
| 164 |
onClick={onOpenConversation}
|
| 165 |
className="w-full flex items-center justify-between text-left text-sm text-gray-300 hover:text-white group py-2"
|
|
@@ -177,14 +190,14 @@ const SimulationPage: React.FC<SimulationPageProps> = ({
|
|
| 177 |
<span className="font-medium text-sm">Open Global Chat</span>
|
| 178 |
</button>
|
| 179 |
|
| 180 |
-
{/* Setup Warning */}
|
| 181 |
-
<div className="bg-
|
| 182 |
-
<div className="flex items-center gap-2 text-
|
| 183 |
-
<
|
| 184 |
-
<span>
|
| 185 |
</div>
|
| 186 |
-
<p className="text-
|
| 187 |
-
Assemble
|
| 188 |
</p>
|
| 189 |
</div>
|
| 190 |
|
|
@@ -322,7 +335,7 @@ const SimulationPage: React.FC<SimulationPageProps> = ({
|
|
| 322 |
) : (
|
| 323 |
<div className="space-y-3">
|
| 324 |
<div className="flex items-center gap-2 text-xs font-medium text-green-400">
|
| 325 |
-
<div className="w-1.5 h-1.5 rounded-full bg-green-500
|
| 326 |
{simulationResult.status}
|
| 327 |
</div>
|
| 328 |
<p className="text-[11px] text-gray-400">{simulationResult.message}</p>
|
|
|
|
| 46 |
const SimulationPage: React.FC<SimulationPageProps> = ({
|
| 47 |
onBack, onOpenConversation, onOpenChat, user, onLogin, simulationResult, setSimulationResult
|
| 48 |
}) => {
|
| 49 |
+
const [society, setSociety] = useState('');
|
| 50 |
+
const [societies, setSocieties] = useState<string[]>([]);
|
| 51 |
const [viewMode, setViewMode] = useState('Job Title');
|
| 52 |
const [isRefreshing, setIsRefreshing] = useState(false);
|
| 53 |
const [isBuilding, setIsBuilding] = useState(false);
|
|
|
|
| 67 |
// Fetch real focus groups
|
| 68 |
const fetchSocieties = async () => {
|
| 69 |
try {
|
| 70 |
+
const result = await GradioService.listSimulations();
|
| 71 |
+
// Handle both direct array and Gradio data wrap
|
| 72 |
+
const list = Array.isArray(result) ? result : (result?.data?.[0] || []);
|
| 73 |
+
|
| 74 |
+
if (Array.isArray(list)) {
|
| 75 |
const names = list
|
| 76 |
+
.map((s: any) => {
|
| 77 |
+
if (typeof s === 'string') return s;
|
| 78 |
+
if (typeof s === 'object' && s !== null) return s.id || s.name || '';
|
| 79 |
+
return '';
|
| 80 |
+
})
|
| 81 |
+
.filter(name => name.length > 0);
|
| 82 |
|
| 83 |
+
setSocieties(names);
|
| 84 |
+
if (names.length > 0 && (!society || !names.includes(society))) {
|
| 85 |
+
setSociety(names[0]);
|
|
|
|
|
|
|
| 86 |
}
|
| 87 |
}
|
| 88 |
} catch (e) {
|
|
|
|
| 165 |
<div className="h-px bg-gray-800 my-4" />
|
| 166 |
|
| 167 |
{/* Actions */}
|
| 168 |
+
<button
|
| 169 |
+
onClick={onOpenConversation}
|
| 170 |
+
className="w-full flex items-center justify-between text-left text-sm text-gray-300 hover:text-white group py-2 border-b border-gray-800/50 mb-1"
|
| 171 |
+
>
|
| 172 |
+
<span>Assemble new group</span>
|
| 173 |
+
<Plus size={18} className="text-gray-500 group-hover:text-white" />
|
| 174 |
+
</button>
|
| 175 |
+
|
| 176 |
<button
|
| 177 |
onClick={onOpenConversation}
|
| 178 |
className="w-full flex items-center justify-between text-left text-sm text-gray-300 hover:text-white group py-2"
|
|
|
|
| 190 |
<span className="font-medium text-sm">Open Global Chat</span>
|
| 191 |
</button>
|
| 192 |
|
| 193 |
+
{/* Setup Warning / Info Box */}
|
| 194 |
+
<div className="bg-blue-900/30 border border-blue-700/50 rounded-xl p-4 mt-4">
|
| 195 |
+
<div className="flex items-center gap-2 text-blue-200 font-bold text-xs mb-1">
|
| 196 |
+
<Info size={14}/>
|
| 197 |
+
<span>Configuration Required</span>
|
| 198 |
</div>
|
| 199 |
+
<p className="text-blue-200/70 text-[10px] leading-relaxed">
|
| 200 |
+
Assemble new group and create a new test are required to be configured first before using any chat.
|
| 201 |
</p>
|
| 202 |
</div>
|
| 203 |
|
|
|
|
| 335 |
) : (
|
| 336 |
<div className="space-y-3">
|
| 337 |
<div className="flex items-center gap-2 text-xs font-medium text-green-400">
|
| 338 |
+
<div className="w-1.5 h-1.5 rounded-full bg-green-500"></div>
|
| 339 |
{simulationResult.status}
|
| 340 |
</div>
|
| 341 |
<p className="text-[11px] text-gray-400">{simulationResult.message}</p>
|