Skip to content

Commit 56a2c45

Browse files
committed
feat: implementts add widget
1 parent a1ba9f8 commit 56a2c45

File tree

4 files changed

+161
-11
lines changed

4 files changed

+161
-11
lines changed

src/components/IFrameWidget/editor.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,14 @@ class IFrameWidgetEditor extends Component<Props, IFrameWidgetProps> {
195195
</div>
196196
);
197197
}
198+
199+
public static defaultProps: IFrameWidgetProps = {
200+
url: "",
201+
retry_time: 10,
202+
retry_count: 3,
203+
width: 640,
204+
height: 480,
205+
};
198206
}
199207

200208
export { IFrameWidgetEditor };

src/components/TextWidget/editor.tsx

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,17 +41,18 @@ class Color {
4141
}
4242

4343
// from #rrggbb
44-
static fromRGBCode(rgb: string): Color {
45-
return new Color(
44+
static fromRGBCode?(rgb: string): Color {
45+
return rgb ? new Color(
4646
parseInt(rgb.substr(1,2), 16),
4747
parseInt(rgb.substr(3,2), 16),
4848
parseInt(rgb.substr(5,2), 16),
4949
1,
50-
);
50+
) : new Color(0, 0, 0, 1);
5151
}
5252

5353
// from rgba(r,g,b,a)
54-
static fromRGBA(rgba: string): Color {
54+
static fromRGBA(rgba?: string): Color {
55+
if (!rgba) return new Color(0, 0, 0, 1);
5556
const match = rgba.match(/rgba\((\d+),(\d+),(\d+),(\d(\.\d+)?)\)/);
5657
return new Color(
5758
parseInt(match[1]),
@@ -342,6 +343,12 @@ class TextWidgetEditor extends Component<Props, TextWidgetProps> {
342343
</div>
343344
);
344345
}
346+
347+
public static defaultProps: TextWidgetProps = {
348+
text: "",
349+
hidden: false,
350+
autoHidden: true,
351+
}
345352
}
346353

347354
export { TextWidgetEditor };

src/components/TimeWidget/editor.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,11 @@ class TimeWidgetEditor extends Component<Props, TimeWidgetProps> {
8989
</div>
9090
);
9191
}
92+
93+
public static defaultProps: TimeWidgetProps = {
94+
size: 24,
95+
hidden: false,
96+
};
9297
}
9398

9499
export { TimeWidgetEditor };

src/pages/admin/index.tsx

Lines changed: 137 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,32 @@
1-
import { useEffect, useState } from 'react';
1+
import { useEffect, useState, MouseEvent } from 'react';
2+
import styled from 'styled-components';
23
import {
34
CssBaseline,
45
Container,
56
Box,
67
AppBar,
78
Toolbar,
9+
Menu,
10+
MenuItem,
811
Typography,
912
Button,
13+
IconButton,
14+
FormControl,
15+
InputLabel,
16+
TextField,
17+
Select,
18+
Backdrop,
19+
Dialog,
20+
DialogActions,
21+
DialogContent,
22+
DialogTitle,
23+
Fade,
1024
} from '@mui/material';
1125
import { makeStyles } from '@mui/styles'
26+
import AddIcon from '@mui/icons-material/Add';
27+
import AccountCircleIcon from '@mui/icons-material/AccountCircle';
1228
import { User } from '@firebase/auth';
13-
import { ref, onValue, DataSnapshot } from '@firebase/database';
29+
import { ref, set, onValue, DataSnapshot } from '@firebase/database';
1430

1531
import { AuthProvider } from '@/lib/AuthProvider';
1632
import { auth, db } from '@/lib/firebase';
@@ -72,11 +88,86 @@ const Widgets = () => {
7288
}
7389
</div>
7490
);
75-
}
91+
};
92+
93+
const AddWidgetModel = ({ open, onClose }: { open: boolean, onClose: () => void }) => {
94+
const [widgetId, setWidgetId] = useState("");
95+
const [widgetType, setWidgetType] = useState("text");
96+
97+
const FormGroup = styled.div`
98+
display: flex;
99+
margin-bottom: 1rem;
100+
& > div {
101+
flex-grow: 1;
102+
margin-left: 0.25rem;
103+
}
104+
`;
105+
106+
const style = {
107+
display: 'flex',
108+
flexDirection: 'column',
109+
position: 'absolute' as 'absolute',
110+
top: '50%',
111+
left: '50%',
112+
transform: 'translate(-50%, -50%)',
113+
width: 640,
114+
bgcolor: 'background.paper',
115+
border: '1px solid #ddd',
116+
borderRadius: '4px',
117+
boxShadow: 24,
118+
pt: 4,
119+
px: 4,
120+
pb: 3,
121+
};
122+
123+
return (
124+
<Dialog
125+
open={open}
126+
onClose={onClose}
127+
>
128+
<DialogTitle>Add Widget</DialogTitle>
129+
<DialogContent>
130+
<FormGroup>
131+
<FormControl variant="standard">
132+
<TextField autoFocus fullWidth label="ID" value={widgetId} variant="standard" onChange={(e) => { setWidgetId(e.target.value); }}/>
133+
</FormControl>
134+
</FormGroup>
135+
136+
<FormGroup>
137+
<FormControl variant="standard">
138+
<InputLabel id="widget-type-label">Widget</InputLabel>
139+
<Select
140+
labelId="widget-type-label"
141+
id="widget-type"
142+
value={widgetType}
143+
label="Widget"
144+
onChange={(e) => { setWidgetType(e.target.value); }}
145+
>
146+
<MenuItem value={"text"}>Text</MenuItem>
147+
<MenuItem value={"time"}>Time</MenuItem>
148+
<MenuItem value={"iframe"}>IFrame</MenuItem>
149+
</Select>
150+
</FormControl>
151+
</FormGroup>
152+
</DialogContent>
153+
<DialogActions>
154+
<Button color="primary" variant="contained" onClick={() => {
155+
set(ref(db, `/widgets/${widgetId}`), {
156+
name: widgetType,
157+
props: Editors[widgetType].defaultProps
158+
});
159+
}}>Add</Button>
160+
</DialogActions>
161+
</Dialog>
162+
);
163+
};
76164

77165
const AdminIndexPage = () => {
78166
const classes = useStyles();
79167
const [currentUser, setCurrentUser] = useState<User | null>(null);
168+
const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null);
169+
const [addWidgetModalOpened, setAddWidgetModalOpened] = useState(false);
170+
const isUserMenuOpen = Boolean(anchorEl);
80171

81172
useEffect(() => {
82173
auth.onAuthStateChanged((user) => {
@@ -85,13 +176,22 @@ const AdminIndexPage = () => {
85176
});
86177

87178
const signout = async () => {
179+
setAnchorEl(null);
88180
try {
89181
await auth.signOut();
90182
} catch (err) {
91183
alert(err.message);
92184
}
93185
};
94186

187+
const userMenuId = 'user-menu';
188+
const handleUserMenuOpen = (event: MouseEvent<HTMLElement>) => {
189+
setAnchorEl(event.currentTarget);
190+
};
191+
const handleUserMenuClose = () => {
192+
setAnchorEl(null);
193+
};
194+
95195
return currentUser !== null ? (
96196
<AuthProvider>
97197
<CssBaseline />
@@ -101,12 +201,42 @@ const AdminIndexPage = () => {
101201
<Typography variant="h6" className={classes.title}>
102202
Admin
103203
</Typography>
104-
<Typography>{currentUser.email}</Typography>
105-
<Button color="inherit" onClick={signout}>
106-
Logout
107-
</Button>
204+
<Box sx={{ flexGrow: 1 }} />
205+
<Box sx={{ display: { xs: 'none', md: 'flex' } }}>
206+
<IconButton
207+
size="large"
208+
color="inherit"
209+
onClick={()=>{setAddWidgetModalOpened(true);}}
210+
>
211+
<AddIcon />
212+
</IconButton>
213+
<IconButton
214+
size="large"
215+
color="inherit"
216+
edge="end"
217+
aria-controls={userMenuId}
218+
aria-haspopup="true"
219+
onClick={handleUserMenuOpen}
220+
>
221+
<AccountCircleIcon />
222+
</IconButton>
223+
</Box>
108224
</Toolbar>
109225
</AppBar>
226+
<Menu
227+
id={userMenuId}
228+
anchorEl={anchorEl}
229+
open={isUserMenuOpen}
230+
onClose={handleUserMenuClose}
231+
>
232+
<MenuItem color="inherit" onClick={signout}>Logout</MenuItem>
233+
</Menu>
234+
<AddWidgetModel
235+
open={addWidgetModalOpened}
236+
onClose={() => {
237+
setAddWidgetModalOpened(false);
238+
}}
239+
/>
110240

111241
<Container className={classes.content}>
112242
<Box my={4}>

0 commit comments

Comments
 (0)