mirror of
https://github.com/xtr-dev/payload-feature-flags.git
synced 2025-12-10 02:43:25 +00:00
Implement proper Payload CMS DefaultTemplate layout integration
Layout Implementation: - Fixed import to use DefaultTemplate from '@payloadcms/next/templates' - Added proper template props interface with i18n, locale, payload, etc. - Restructured component to use DefaultTemplate wrapper correctly - Created FeatureFlagsContent as child component for template Template Structure: - Component now receives standard Payload admin view props - DefaultTemplate provides proper admin layout with sidebar navigation - All template props (i18n, locale, params, payload, permissions, etc.) are passed through - Maintains theme integration and responsive design within admin layout The feature flags dashboard now properly integrates with Payload's admin layout system, including the navigation sidebar and standard admin styling, while preserving all spreadsheet functionality and inline editing capabilities. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -4,6 +4,7 @@ import {
|
|||||||
useConfig,
|
useConfig,
|
||||||
useTheme
|
useTheme
|
||||||
} from '@payloadcms/ui'
|
} from '@payloadcms/ui'
|
||||||
|
import { DefaultTemplate } from '@payloadcms/next/templates'
|
||||||
|
|
||||||
interface FeatureFlag {
|
interface FeatureFlag {
|
||||||
id: string
|
id: string
|
||||||
@@ -24,11 +25,17 @@ interface FeatureFlag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface FeatureFlagsViewProps {
|
interface FeatureFlagsViewProps {
|
||||||
// Props that would typically be passed from the parent view
|
i18n?: any
|
||||||
[key: string]: any
|
locale?: any
|
||||||
|
params?: any
|
||||||
|
payload?: any
|
||||||
|
permissions?: any
|
||||||
|
searchParams?: any
|
||||||
|
user?: any
|
||||||
|
visibleEntities?: any
|
||||||
}
|
}
|
||||||
|
|
||||||
const FeatureFlagsViewComponent = (props: FeatureFlagsViewProps = {}) => {
|
const FeatureFlagsViewComponent = (props: FeatureFlagsViewProps) => {
|
||||||
const { config } = useConfig()
|
const { config } = useConfig()
|
||||||
const { theme } = useTheme()
|
const { theme } = useTheme()
|
||||||
const [flags, setFlags] = useState<FeatureFlag[]>([])
|
const [flags, setFlags] = useState<FeatureFlag[]>([])
|
||||||
@@ -197,80 +204,72 @@ const FeatureFlagsViewComponent = (props: FeatureFlagsViewProps = {}) => {
|
|||||||
|
|
||||||
const styles = getThemeStyles()
|
const styles = getThemeStyles()
|
||||||
|
|
||||||
if (loading) {
|
const FeatureFlagsContent = () => (
|
||||||
return (
|
|
||||||
<div style={{
|
|
||||||
padding: '2rem',
|
|
||||||
textAlign: 'center',
|
|
||||||
minHeight: '400px',
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center'
|
|
||||||
}}>
|
|
||||||
<div style={{ fontSize: '1.125rem', color: styles.textMuted }}>Loading feature flags...</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div style={{
|
<div style={{
|
||||||
padding: '0',
|
padding: '2rem',
|
||||||
height: '100%',
|
maxWidth: '100%'
|
||||||
overflow: 'auto'
|
|
||||||
}}>
|
}}>
|
||||||
{/* Content Container */}
|
{/* Header */}
|
||||||
<div style={{
|
<div style={{ marginBottom: '2rem' }}>
|
||||||
padding: '2rem',
|
<h1 style={{
|
||||||
maxWidth: '100%'
|
fontSize: '2rem',
|
||||||
}}>
|
fontWeight: '700',
|
||||||
{/* Header */}
|
color: styles.text,
|
||||||
<div style={{ marginBottom: '2rem' }}>
|
margin: '0 0 0.5rem 0'
|
||||||
<h1 style={{
|
|
||||||
fontSize: '2rem',
|
|
||||||
fontWeight: '700',
|
|
||||||
color: styles.text,
|
|
||||||
margin: '0 0 0.5rem 0'
|
|
||||||
}}>
|
|
||||||
Feature Flags Dashboard
|
|
||||||
</h1>
|
|
||||||
<p style={{
|
|
||||||
color: styles.textMuted,
|
|
||||||
fontSize: '1rem',
|
|
||||||
margin: '0 0 2rem 0'
|
|
||||||
}}>
|
|
||||||
Manage all feature flags in a spreadsheet view with inline editing capabilities
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Success/Error Messages */}
|
|
||||||
{successMessage && (
|
|
||||||
<div style={{
|
|
||||||
position: 'fixed',
|
|
||||||
top: '20px',
|
|
||||||
right: '20px',
|
|
||||||
backgroundColor: styles.primary,
|
|
||||||
color: 'white',
|
|
||||||
padding: '0.75rem 1.5rem',
|
|
||||||
borderRadius: '0.5rem',
|
|
||||||
boxShadow: '0 4px 6px rgba(0,0,0,0.1)',
|
|
||||||
zIndex: 1000,
|
|
||||||
}}>
|
}}>
|
||||||
{successMessage}
|
Feature Flags Dashboard
|
||||||
</div>
|
</h1>
|
||||||
)}
|
<p style={{
|
||||||
|
color: styles.textMuted,
|
||||||
{error && (
|
fontSize: '1rem',
|
||||||
<div style={{
|
margin: '0 0 2rem 0'
|
||||||
marginBottom: '1rem',
|
|
||||||
backgroundColor: styles.error + '20',
|
|
||||||
border: `1px solid ${styles.error}`,
|
|
||||||
borderRadius: '0.5rem',
|
|
||||||
padding: '1rem',
|
|
||||||
color: styles.error
|
|
||||||
}}>
|
}}>
|
||||||
<strong>Error:</strong> {error}
|
Manage all feature flags in a spreadsheet view with inline editing capabilities
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{loading ? (
|
||||||
|
<div style={{
|
||||||
|
padding: '2rem',
|
||||||
|
textAlign: 'center',
|
||||||
|
minHeight: '400px',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center'
|
||||||
|
}}>
|
||||||
|
<div style={{ fontSize: '1.125rem', color: styles.textMuted }}>Loading feature flags...</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
) : (
|
||||||
|
<>
|
||||||
|
{/* Success/Error Messages */}
|
||||||
|
{successMessage && (
|
||||||
|
<div style={{
|
||||||
|
position: 'fixed',
|
||||||
|
top: '20px',
|
||||||
|
right: '20px',
|
||||||
|
backgroundColor: styles.primary,
|
||||||
|
color: 'white',
|
||||||
|
padding: '0.75rem 1.5rem',
|
||||||
|
borderRadius: '0.5rem',
|
||||||
|
boxShadow: '0 4px 6px rgba(0,0,0,0.1)',
|
||||||
|
zIndex: 1000,
|
||||||
|
}}>
|
||||||
|
{successMessage}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{error && (
|
||||||
|
<div style={{
|
||||||
|
marginBottom: '1rem',
|
||||||
|
backgroundColor: styles.error + '20',
|
||||||
|
border: `1px solid ${styles.error}`,
|
||||||
|
borderRadius: '0.5rem',
|
||||||
|
padding: '1rem',
|
||||||
|
color: styles.error
|
||||||
|
}}>
|
||||||
|
<strong>Error:</strong> {error}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Controls */}
|
{/* Controls */}
|
||||||
<div style={{
|
<div style={{
|
||||||
@@ -619,9 +618,25 @@ const FeatureFlagsViewComponent = (props: FeatureFlagsViewProps = {}) => {
|
|||||||
<span style={{ fontWeight: '600' }}>A/B Tests:</span> {flags.filter(f => f && f.variants && f.variants.length > 0).length}
|
<span style={{ fontWeight: '600' }}>A/B Tests:</span> {flags.filter(f => f && f.variants && f.variants.length > 0).length}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DefaultTemplate
|
||||||
|
i18n={props.i18n}
|
||||||
|
locale={props.locale}
|
||||||
|
params={props.params}
|
||||||
|
payload={props.payload}
|
||||||
|
permissions={props.permissions}
|
||||||
|
searchParams={props.searchParams}
|
||||||
|
user={props.user}
|
||||||
|
visibleEntities={props.visibleEntities}
|
||||||
|
>
|
||||||
|
<FeatureFlagsContent />
|
||||||
|
</DefaultTemplate>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const FeatureFlagsView = memo(FeatureFlagsViewComponent)
|
export const FeatureFlagsView = memo(FeatureFlagsViewComponent)
|
||||||
|
|||||||
Reference in New Issue
Block a user