Added First run dialog with Donation Component
This commit is contained in:
@@ -47,6 +47,7 @@ Datacenter Modeler is a React-based web application for designing datacenter rac
|
||||
- Export a PDF report with the diagram and rack inventory
|
||||
- Dark/light theme selector
|
||||
- Material UI-based interface
|
||||
- Welcome dialog with an optional Cash App donation link
|
||||
|
||||
## Component Library
|
||||
|
||||
@@ -170,3 +171,4 @@ Each rack/cabinet contains its own metadata and an array of installed equipment.
|
||||
- JSON export is the portable save format for moving diagrams between browsers or computers.
|
||||
- PDF and image exports are generated from the rendered workspace.
|
||||
- The current implementation is client-side only; no backend server or database is required.
|
||||
- Donations are optional and use the Cash App link for `$MatthewPuckett`.
|
||||
|
||||
67
src/App.tsx
67
src/App.tsx
@@ -42,6 +42,7 @@ import {
|
||||
Image,
|
||||
Inventory2,
|
||||
LightMode,
|
||||
OpenInNew,
|
||||
PictureAsPdf,
|
||||
Power,
|
||||
Router,
|
||||
@@ -50,6 +51,7 @@ import {
|
||||
SettingsInputComponent,
|
||||
Storage,
|
||||
Terminal,
|
||||
VolunteerActivism,
|
||||
ViewColumn,
|
||||
} from '@mui/icons-material';
|
||||
import html2canvas from 'html2canvas';
|
||||
@@ -147,6 +149,8 @@ export default function App() {
|
||||
const [exportAnchor, setExportAnchor] = useState<HTMLElement | null>(null);
|
||||
const [pendingContainer, setPendingContainer] = useState<'rack' | 'cabinet' | null>(null);
|
||||
const [pendingSize, setPendingSize] = useState(42);
|
||||
const [welcomeOpen, setWelcomeOpen] = useState(true);
|
||||
const [donationAmount, setDonationAmount] = useState(5);
|
||||
const [notice, setNotice] = useState('');
|
||||
const workspaceRef = useRef<HTMLDivElement>(null);
|
||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||
@@ -444,6 +448,11 @@ export default function App() {
|
||||
}
|
||||
};
|
||||
|
||||
const openDonation = () => {
|
||||
const amount = clampNumber(donationAmount, 1, 500, 5);
|
||||
window.open(`https://cash.app/$MatthewPuckett/${amount}`, '_blank', 'noopener,noreferrer');
|
||||
};
|
||||
|
||||
const captureWorkspace = async () => {
|
||||
if (!workspaceRef.current) {
|
||||
throw new Error('Workspace is not ready.');
|
||||
@@ -683,6 +692,64 @@ export default function App() {
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
|
||||
<Dialog open={welcomeOpen} onClose={() => setWelcomeOpen(false)} maxWidth="sm" fullWidth>
|
||||
<DialogTitle sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
|
||||
<Dns color="primary" />
|
||||
Welcome to Datacenter Modeler
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<Stack spacing={2.5}>
|
||||
<Typography color="text.secondary">
|
||||
Build rack and cabinet diagrams by dragging components onto the workspace, snapping equipment into rack units,
|
||||
editing metadata in the properties panel, and exporting your layout as JSON, images, or a PDF report.
|
||||
</Typography>
|
||||
|
||||
<Divider />
|
||||
|
||||
<Box>
|
||||
<Stack direction="row" alignItems="center" spacing={1} sx={{ mb: 1 }}>
|
||||
<VolunteerActivism color="secondary" />
|
||||
<Typography variant="subtitle1" sx={{ fontWeight: 800 }}>
|
||||
Support the project
|
||||
</Typography>
|
||||
</Stack>
|
||||
<Typography variant="body2" color="text.secondary" sx={{ mb: 2 }}>
|
||||
This application was made by a homebrew developer. A donation is appreciated if this tool helps you,
|
||||
but it is absolutely not required.
|
||||
</Typography>
|
||||
<Stack spacing={1.5}>
|
||||
<Stack direction="row" spacing={1} flexWrap="wrap" useFlexGap>
|
||||
{[5, 10, 20, 50].map((amount) => (
|
||||
<Button
|
||||
key={amount}
|
||||
size="small"
|
||||
variant={donationAmount === amount ? 'contained' : 'outlined'}
|
||||
onClick={() => setDonationAmount(amount)}
|
||||
>
|
||||
${amount}
|
||||
</Button>
|
||||
))}
|
||||
</Stack>
|
||||
<TextField
|
||||
label="Donation amount"
|
||||
type="number"
|
||||
value={donationAmount}
|
||||
inputProps={{ min: 1, max: 500 }}
|
||||
onChange={(event) => setDonationAmount(clampNumber(event.target.value, 1, 500, donationAmount))}
|
||||
fullWidth
|
||||
/>
|
||||
<Button variant="contained" color="secondary" startIcon={<VolunteerActivism />} endIcon={<OpenInNew />} onClick={openDonation}>
|
||||
Donate with Cash App
|
||||
</Button>
|
||||
</Stack>
|
||||
</Box>
|
||||
</Stack>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setWelcomeOpen(false)}>Continue to app</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
|
||||
<Snackbar open={Boolean(notice)} autoHideDuration={3200} message={notice} onClose={() => setNotice('')} />
|
||||
</Box>
|
||||
</ThemeProvider>
|
||||
|
||||
Reference in New Issue
Block a user