Added complete plugin documentation with visual mockups and expanded template
variable system with CONTEXT, DATE helpers, and default values.
Backend Changes:
- Extended template_parser.py to support all new template types
- Added PROMPT with default values: {{PROMPT:var|desc|default}}
- Added CONTEXT variables: {{CONTEXT:business_name}}, {{CONTEXT:owner_email}}
- Added DATE helpers: {{DATE:today}}, {{DATE:+7d}}, {{DATE:monday}}
- Implemented date expression evaluation for relative dates
- Updated compile_template to handle all template types
- Added context parameter for business data auto-fill
Frontend Changes:
- Created comprehensive HelpPluginDocs.tsx with Stripe-style API docs
- Added visual mockup of plugin configuration form
- Documented all template types with examples and benefits
- Added Command Reference section with allowed/blocked Python commands
- Documented all HTTP methods (GET, POST, PUT, PATCH, DELETE)
- Added URL whitelisting requirements and approval process
- Created Platform Staff management page with edit modal
- Added can_approve_plugins and can_whitelist_urls permissions
Platform Staff Features:
- List all platform_manager and platform_support users
- Edit user details with role-based permissions
- Superusers can edit anyone
- Platform managers can only edit platform_support users
- Permission cascade: users can only grant permissions they have
- Real-time updates via React Query cache invalidation
Documentation Highlights:
- 4 template types: PROMPT, CONTEXT, DATE, and automatic validation
- Visual form mockup showing exactly what users see
- All allowed control flow (if/elif/else, for, while, try/except, etc.)
- All allowed built-in functions (len, range, min, max, etc.)
- All blocked operations (import, exec, eval, class/function defs)
- Complete HTTP API reference with examples
- URL whitelisting process: contact pluginaccess@smoothschedule.com
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
83 lines
2.8 KiB
TypeScript
83 lines
2.8 KiB
TypeScript
import { test, expect } from '@playwright/test';
|
|
|
|
test('Debug Platform Staff Edit Button', async ({ page }) => {
|
|
// Navigate to platform login
|
|
await page.goto('http://platform.lvh.me:5173/login');
|
|
|
|
// Login as superuser
|
|
await page.getByPlaceholder(/username/i).fill('superuser');
|
|
await page.getByPlaceholder(/password/i).fill('starry12');
|
|
await page.getByRole('button', { name: /sign in/i }).click();
|
|
|
|
// Wait for dashboard to load
|
|
await page.waitForURL(/platform\/dashboard/, { timeout: 10000 });
|
|
|
|
// Navigate to Staff page
|
|
await page.goto('http://platform.lvh.me:5173/#/platform/staff');
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
// Wait for staff list to load
|
|
await page.waitForSelector('table', { timeout: 10000 });
|
|
|
|
// Log the current user data from localStorage or cookies
|
|
const currentUser = await page.evaluate(() => {
|
|
return {
|
|
cookies: document.cookie,
|
|
localStorage: localStorage.getItem('user')
|
|
};
|
|
});
|
|
console.log('Current user data:', currentUser);
|
|
|
|
// Check if Edit buttons exist
|
|
const editButtons = await page.locator('button:has-text("Edit")').all();
|
|
console.log('Number of Edit buttons found:', editButtons.length);
|
|
|
|
// Check if any buttons are disabled
|
|
for (let i = 0; i < editButtons.length; i++) {
|
|
const isDisabled = await editButtons[i].isDisabled();
|
|
const buttonText = await editButtons[i].textContent();
|
|
console.log(`Button ${i + 1} (${buttonText}): disabled = ${isDisabled}`);
|
|
}
|
|
|
|
// Try to click the first Edit button
|
|
if (editButtons.length > 0) {
|
|
const firstButton = editButtons[0];
|
|
const isDisabled = await firstButton.isDisabled();
|
|
|
|
if (isDisabled) {
|
|
console.log('First Edit button is DISABLED - this is the bug!');
|
|
|
|
// Get the user data from the API
|
|
const apiResponse = await page.evaluate(async () => {
|
|
const response = await fetch('http://lvh.me:8000/api/auth/me/', {
|
|
credentials: 'include'
|
|
});
|
|
return await response.json();
|
|
});
|
|
console.log('API /auth/me/ response:', apiResponse);
|
|
|
|
// Get platform users data
|
|
const platformUsers = await page.evaluate(async () => {
|
|
const response = await fetch('http://lvh.me:8000/api/platform/users/', {
|
|
credentials: 'include'
|
|
});
|
|
return await response.json();
|
|
});
|
|
console.log('API /platform/users/ response:', platformUsers);
|
|
|
|
} else {
|
|
console.log('First Edit button is ENABLED - attempting to click...');
|
|
await firstButton.click();
|
|
|
|
// Wait for modal to appear
|
|
await page.waitForSelector('text=Edit Platform User', { timeout: 5000 });
|
|
console.log('Modal opened successfully!');
|
|
}
|
|
} else {
|
|
console.log('No Edit buttons found on the page!');
|
|
}
|
|
|
|
// Take a screenshot
|
|
await page.screenshot({ path: 'platform-staff-debug.png', fullPage: true });
|
|
});
|