@mui/material#ListItemSecondaryAction TypeScript Examples
The following examples show how to use
@mui/material#ListItemSecondaryAction.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: index.tsx From ExpressLRS-Configurator with GNU General Public License v3.0 | 4 votes |
UserDefinesList: FunctionComponent<UserDefinesListProps> = (props) => {
const { options, onChange, firmwareVersionData } = props;
const onChecked = (data: UserDefineKey) => {
const opt = options.find(({ key }) => key === data);
if (opt !== undefined) {
onChange({
...opt,
enabled: !opt.enabled,
});
} else {
throw new Error(`user define key ${data} not found`);
}
};
const onUserDefineValueChange = (data: UserDefineKey) => (
event: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>
) => {
const opt = options.find(({ key }) => key === data);
if (opt !== undefined) {
const update = {
...opt,
value: event.target.value,
};
onChange(update);
} else {
throw new Error(`user define key ${data} not found`);
}
};
const onEnumValueChange = (data: UserDefineKey) => (value: string | null) => {
const opt = options.find(({ key }) => key === data);
if (opt !== undefined) {
const update = {
...opt,
value,
};
onChange(update);
} else {
throw new Error(`user define key ${data} not found`);
}
};
const inputLabel = (key: UserDefineKey): string => {
switch (key) {
case UserDefineKey.ARM_CHANNEL:
return 'Arm channel';
case UserDefineKey.BINDING_PHRASE:
return 'Custom binding phrase';
case UserDefineKey.MY_STARTUP_MELODY:
return 'My startup melody';
default:
return 'Value';
}
};
return (
<List>
{options.map((item) => {
return (
<React.Fragment key={item.key}>
<ListItem
dense
selected={item.enabled}
button
onClick={onChecked.bind(this, item.key)}
>
<ListItemIcon sx={styles.icon}>
<Checkbox
edge="start"
checked={item.enabled}
tabIndex={-1}
disableRipple
/>
</ListItemIcon>
<ListItemText>{item.key}</ListItemText>
<ListItemSecondaryAction>
<UserDefineDescription
userDefine={item.key}
firmwareVersionData={firmwareVersionData}
/>
</ListItemSecondaryAction>
</ListItem>
{item.type === UserDefineKind.Text && item.enabled && (
<>
<ListItem sx={styles.complimentaryItem}>
{!item.sensitive && (
<TextField
size="small"
onChange={onUserDefineValueChange(item.key)}
value={item.value}
fullWidth
label={inputLabel(item.key)}
/>
)}
{item.sensitive && (
<SensitiveTextField
name={item.key}
size="small"
onChange={onUserDefineValueChange(item.key)}
value={item.value}
fullWidth
label={inputLabel(item.key)}
/>
)}
</ListItem>
</>
)}
{item.type === UserDefineKind.Enum && item.enabled && (
<ListItem sx={styles.complimentaryItem}>
<Omnibox
title={inputLabel(item.key)}
currentValue={{
value: item.value ?? '',
label: item.value ?? '',
}}
onChange={onEnumValueChange(item.key)}
options={
item?.enumValues?.map((opt) => ({
value: opt,
label: opt,
})) ?? []
}
/>
</ListItem>
)}
</React.Fragment>
);
})}
</List>
);
}
Example #2
Source File: AccountList.tsx From abrechnung with GNU Affero General Public License v3.0 | 4 votes |
export default function AccountList({ group }) {
const [speedDialOpen, setSpeedDialOpen] = useState(false);
const toggleSpeedDial = () => setSpeedDialOpen((currValue) => !currValue);
const [showPersonalAccountCreationModal, setShowPersonalAccountCreationModal] = useState(false);
const [showClearingAccountCreationModal, setShowClearingAccountCreationModal] = useState(false);
const [activeTab, setActiveTab] = useState("personal");
const [searchValuePersonal, setSearchValuePersonal] = useState("");
const [searchValueClearing, setSearchValueClearing] = useState("");
const [showPersonalAccountEditModal, setShowPersonalAccountEditModal] = useState(false);
const [showClearingAccountEditModal, setShowClearingAccountEditModal] = useState(false);
const [clearingAccountToCopy, setClearingAccountToCopy] = useState(undefined);
const [accountToEdit, setAccountToEdit] = useState(null);
const [clearingAccountToEdit, setClearingAccountToEdit] = useState(null);
const setAccounts = useSetRecoilState(groupAccounts(group.id));
const personalAccounts = useRecoilValue(personalAccountsSeenByUser(group.id));
const clearingAccounts = useRecoilValue(clearingAccountsSeenByUser(group.id));
const allAccounts = useRecoilValue(accountsSeenByUser(group.id));
const [accountToDelete, setAccountToDelete] = useState(null);
const userPermissions = useRecoilValue(currUserPermissions(group.id));
const currentUser = useRecoilValue(userData);
const memberIDToUsername = useRecoilValue(groupMemberIDsToUsername(group.id));
const [filteredPersonalAccounts, setFilteredPersonalAccounts] = useState([]);
const [filteredClearingAccounts, setFilteredClearingAccounts] = useState([]);
useEffect(() => {
if (searchValuePersonal != null && searchValuePersonal !== "") {
setFilteredPersonalAccounts(
personalAccounts.filter((t) => {
return (
t.name.toLowerCase().includes(searchValuePersonal.toLowerCase()) ||
t.description.toLowerCase().includes(searchValuePersonal.toLowerCase())
);
})
);
} else {
return setFilteredPersonalAccounts(personalAccounts);
}
}, [personalAccounts, searchValuePersonal, setFilteredPersonalAccounts]);
useEffect(() => {
if (searchValueClearing != null && searchValueClearing !== "") {
setFilteredClearingAccounts(
clearingAccounts.filter((t) => {
return (
t.name.toLowerCase().includes(searchValueClearing.toLowerCase()) ||
t.description.toLowerCase().includes(searchValueClearing.toLowerCase())
);
})
);
} else {
return setFilteredClearingAccounts(clearingAccounts);
}
}, [clearingAccounts, searchValueClearing, setFilteredClearingAccounts]);
useTitle(`${group.name} - Accounts`);
const openAccountEdit = (account) => {
setAccountToEdit(account);
setShowPersonalAccountEditModal(true);
};
const closeAccountEdit = (evt, reason) => {
if (reason !== "backdropClick") {
setShowPersonalAccountEditModal(false);
setAccountToEdit(null);
}
};
const openClearingAccountEdit = (account) => {
setClearingAccountToEdit(account);
setShowClearingAccountEditModal(true);
};
const closeClearingAccountEdit = (evt, reason) => {
if (reason !== "backdropClick") {
setShowClearingAccountEditModal(false);
setClearingAccountToEdit(null);
}
};
const confirmDeleteAccount = () => {
if (accountToDelete !== null) {
deleteAccount({ accountID: accountToDelete })
.then((account) => {
updateAccount(account, setAccounts);
setAccountToDelete(null);
})
.catch((err) => {
toast.error(err);
});
}
};
const openCreateDialog = () => {
setClearingAccountToCopy(undefined);
setShowClearingAccountCreationModal(true);
};
const copyClearingAccount = (account) => {
setClearingAccountToCopy(account);
setShowClearingAccountCreationModal(true);
};
return (
<>
<MobilePaper>
<TabContext value={activeTab}>
<Box sx={{ borderBottom: 1, borderColor: "divider" }}>
<TabList onChange={(e, newValue) => setActiveTab(newValue)} centered>
<Tab
value="personal"
label={
<TextBadge badgeContent={personalAccounts.length} color="primary">
<span>Personal Accounts</span>
</TextBadge>
}
/>
<Tab
label={
<TextBadge badgeContent={clearingAccounts.length} color="primary">
<span>Clearing Accounts</span>
</TextBadge>
}
value="clearing"
/>
</TabList>
</Box>
<TabPanel value="personal">
<List>
{personalAccounts.length === 0 ? (
<Alert severity="info">No Accounts</Alert>
) : (
<>
<ListItem>
<Input
value={searchValuePersonal}
onChange={(e) => setSearchValuePersonal(e.target.value)}
placeholder="Search…"
inputProps={{
"aria-label": "search",
}}
endAdornment={
<InputAdornment position="end">
<IconButton
aria-label="clear search input"
onClick={(e) => setSearchValuePersonal("")}
edge="end"
>
<Clear />
</IconButton>
</InputAdornment>
}
/>
</ListItem>
<Divider />
{filteredPersonalAccounts.map((account) => (
<ListItem sx={{ padding: 0 }} key={account.id}>
<ListItemLink to={`/groups/${group.id}/accounts/${account.id}`}>
<ListItemText
primary={
<div>
<span>{account.name}</span>
{account.owning_user_id === currentUser.id ? (
<span>
, owned by{" "}
<Chip
size="small"
component="span"
color="primary"
label="you"
/>
</span>
) : (
account.owning_user_id !== null && (
<span>
, owned by{" "}
<Chip
size="small"
component="span"
color="secondary"
label={
memberIDToUsername[
account.owning_user_id
]
}
/>
</span>
)
)}
</div>
}
secondary={account.description}
/>
</ListItemLink>
{userPermissions.can_write && (
<ListItemSecondaryAction>
<IconButton
color="primary"
onClick={() => openAccountEdit(account)}
>
<Edit />
</IconButton>
<IconButton
color="error"
onClick={() => setAccountToDelete(account.id)}
>
<Delete />
</IconButton>
</ListItemSecondaryAction>
)}
</ListItem>
))}
</>
)}
</List>
{userPermissions.can_write && (
<>
<Grid container justifyContent="center">
<Tooltip title="Create Personal Account">
<IconButton
color="primary"
onClick={() => setShowPersonalAccountCreationModal(true)}
>
<Add />
</IconButton>
</Tooltip>
</Grid>
<CreateAccountModal
show={showPersonalAccountCreationModal}
onClose={(evt, reason) => {
if (reason !== "backdropClick") {
setShowPersonalAccountCreationModal(false);
}
}}
group={group}
/>
<EditAccountModal
show={showPersonalAccountEditModal}
onClose={closeAccountEdit}
account={accountToEdit}
group={group}
/>
</>
)}
</TabPanel>
<TabPanel value="clearing">
<List>
{clearingAccounts.length === 0 ? (
<Alert severity="info">No Accounts</Alert>
) : (
<>
<ListItem>
<Input
value={searchValueClearing}
onChange={(e) => setSearchValueClearing(e.target.value)}
placeholder="Search…"
inputProps={{
"aria-label": "search",
}}
endAdornment={
<InputAdornment position="end">
<IconButton
aria-label="clear search input"
onClick={(e) => setSearchValueClearing("")}
edge="end"
>
<Clear />
</IconButton>
</InputAdornment>
}
/>
</ListItem>
<Divider />
{filteredClearingAccounts.map((account) => (
<ListItem sx={{ padding: 0 }} key={account.id}>
<ListItemLink to={`/groups/${group.id}/accounts/${account.id}`}>
<ListItemText primary={account.name} secondary={account.description} />
</ListItemLink>
{userPermissions.can_write && (
<ListItemSecondaryAction>
<IconButton
color="primary"
onClick={() => openClearingAccountEdit(account)}
>
<Edit />
</IconButton>
<IconButton
color="primary"
onClick={() => copyClearingAccount(account)}
>
<ContentCopy />
</IconButton>
<IconButton
color="error"
onClick={() => setAccountToDelete(account.id)}
>
<Delete />
</IconButton>
</ListItemSecondaryAction>
)}
</ListItem>
))}
</>
)}
</List>
{userPermissions.can_write && (
<>
<Grid container justifyContent="center">
<Tooltip title="Create Clearing Account">
<IconButton color="primary" onClick={openCreateDialog}>
<Add />
</IconButton>
</Tooltip>
</Grid>
<CreateClearingAccountModal
show={showClearingAccountCreationModal}
onClose={(evt, reason) => {
if (reason !== "backdropClick") {
setShowClearingAccountCreationModal(false);
}
}}
initialValues={clearingAccountToCopy}
group={group}
/>
<EditClearingAccountModal
show={showClearingAccountEditModal}
onClose={closeClearingAccountEdit}
account={clearingAccountToEdit}
group={group}
/>
</>
)}
</TabPanel>
</TabContext>
</MobilePaper>
{userPermissions.can_write && (
<>
<SpeedDial
ariaLabel="Create Account"
sx={{ position: "fixed", bottom: 20, right: 20 }}
icon={<SpeedDialIcon />}
// onClose={() => setSpeedDialOpen(false)}
// onOpen={() => setSpeedDialOpen(true)}
onClick={toggleSpeedDial}
open={speedDialOpen}
>
<SpeedDialAction
icon={<PersonalAccountIcon />}
tooltipTitle="Personal"
tooltipOpen
onClick={() => setShowPersonalAccountCreationModal(true)}
/>
<SpeedDialAction
icon={<ClearingAccountIcon />}
tooltipTitle="Clearing"
tooltipOpen
onClick={openCreateDialog}
/>
</SpeedDial>
<Dialog maxWidth="xs" aria-labelledby="confirmation-dialog-title" open={accountToDelete !== null}>
<DialogTitle id="confirmation-dialog-title">Confirm delete account</DialogTitle>
<DialogContent dividers>
Are you sure you want to delete the account "
{allAccounts.find((acc) => acc.id === accountToDelete)?.name}"
</DialogContent>
<DialogActions>
<Button autoFocus onClick={() => setAccountToDelete(null)} color="primary">
Cancel
</Button>
<Button onClick={confirmDeleteAccount} color="error">
Ok
</Button>
</DialogActions>
</Dialog>
</>
)}
</>
);
}
Example #3
Source File: GroupInvites.tsx From abrechnung with GNU Affero General Public License v3.0 | 4 votes |
export default function GroupInvites({ group }) {
const [showModal, setShowModal] = useState(false);
const invites = useRecoilValue(groupInvites(group.id));
const members = useRecoilValue(groupMembers(group.id));
const userPermissions = useRecoilValue(currUserPermissions(group.id));
const isGuest = useRecoilValue(isGuestUser);
useTitle(`${group.name} - Invite Links`);
const deleteToken = (id) => {
deleteGroupInvite({ groupID: group.id, inviteID: id }).catch((err) => {
toast.error(err);
});
};
const getMemberUsername = (member_id) => {
const member = members.find((member) => member.user_id === member_id);
if (member === undefined) {
return "unknown";
}
return member.username;
};
const selectLink = (event) => {
const node = event.target;
const selection = window.getSelection();
const range = document.createRange();
range.selectNodeContents(node);
selection.removeAllRanges();
selection.addRange(range);
};
const copyToClipboard = (content) => {
navigator.clipboard.writeText(content);
toast.info("Link copied to clipboard!");
};
return (
<MobilePaper>
<Typography component="h3" variant="h5">
Active Invite Links
</Typography>
{isGuest && (
<Alert severity="info">
You are a guest user on this Abrechnung and therefore not permitted to create group invites.
</Alert>
)}
<List>
{invites.length === 0 ? (
<ListItem>
<ListItemText primary="No Links" />
</ListItem>
) : (
invites.map((invite) => (
<ListItem key={invite.id}>
<ListItemText
primary={
invite.token === null ? (
<span>token hidden, was created by another member</span>
) : (
<span onClick={selectLink}>
{window.location.origin}/invite/
{invite.token}
</span>
)
}
secondary={
<>
{invite.description}, created by {getMemberUsername(invite.created_by)}, valid
until{" "}
{DateTime.fromISO(invite.valid_until).toLocaleString(DateTime.DATETIME_FULL)}
{invite.single_use && ", single use"}
{invite.join_as_editor && ", join as editor"}
</>
}
/>
{userPermissions.can_write && (
<ListItemSecondaryAction>
<IconButton
color="primary"
onClick={() =>
copyToClipboard(`${window.location.origin}/invite/${invite.token}`)
}
>
<ContentCopy />
</IconButton>
<IconButton color="error" onClick={() => deleteToken(invite.id)}>
<Delete />
</IconButton>
</ListItemSecondaryAction>
)}
</ListItem>
))
)}
</List>
{userPermissions.can_write && !isGuest && (
<>
<Grid container justifyContent="center">
<IconButton color="primary" onClick={() => setShowModal(true)}>
<Add />
</IconButton>
</Grid>
<InviteLinkCreate show={showModal} onClose={() => setShowModal(false)} group={group} />
</>
)}
</MobilePaper>
);
}
Example #4
Source File: GroupList.tsx From abrechnung with GNU Affero General Public License v3.0 | 4 votes |
export default function GroupList() {
const [showGroupCreationModal, setShowGroupCreationModal] = useState(false);
const [showGroupDeletionModal, setShowGroupDeletionModal] = useState(false);
const [groupToDelete, setGroupToDelete] = useState(null);
const groups = useRecoilValue(groupList);
const isGuest = useRecoilValue(isGuestUser);
const openGroupDeletionModal = (groupID) => {
setGroupToDelete(groups.find((group) => group.id === groupID));
setShowGroupDeletionModal(true);
};
const closeGroupDeletionModal = () => {
setShowGroupDeletionModal(false);
setGroupToDelete(null);
};
const openGroupCreateModal = () => {
setShowGroupCreationModal(true);
};
const closeGroupCreateModal = (evt, reason) => {
if (reason !== "backdropClick") {
setShowGroupCreationModal(false);
}
};
return (
<MobilePaper>
<Typography component="h3" variant="h5">
Groups
</Typography>
{isGuest && (
<Alert severity="info">
You are a guest user on this Abrechnung and therefore not permitted to create new groups.
</Alert>
)}
<List>
{groups.length === 0 ? (
<ListItem key={0}>
<span>No Groups</span>
</ListItem>
) : (
groups.map((group) => {
return (
<ListItem sx={{ padding: 0 }} key={group.id}>
<ListItemLink to={`/groups/${group.id}`}>
<ListItemText primary={group.name} secondary={group.description} />
</ListItemLink>
<ListItemSecondaryAction>
<IconButton
edge="end"
aria-label="delete-group"
onClick={() => openGroupDeletionModal(group.id)}
>
<Delete />
</IconButton>
</ListItemSecondaryAction>
</ListItem>
);
})
)}
</List>
{!isGuest && (
<>
<Grid container justifyContent="center">
<IconButton color="primary" onClick={openGroupCreateModal}>
<Add />
</IconButton>
</Grid>
<GroupCreateModal show={showGroupCreationModal} onClose={closeGroupCreateModal} />
</>
)}
<GroupDeleteModal
show={showGroupDeletionModal}
onClose={closeGroupDeletionModal}
groupToDelete={groupToDelete}
/>
</MobilePaper>
);
}
Example #5
Source File: GroupMemberList.tsx From abrechnung with GNU Affero General Public License v3.0 | 4 votes |
export default function GroupMemberList({ group }) {
const [showEditMemberDialog, setShowEditMemberDialog] = useState(false);
const [memberToEdit, setMemberToEdit] = useState(null);
const currentUser = useRecoilValue(userData);
const members = useRecoilValue(groupMembers(group.id));
const permissions = useRecoilValue(currUserPermissions(group.id));
useTitle(`${group.name} - Members`);
const handleEditMemberSubmit = (values, { setSubmitting }) => {
updateGroupMemberPrivileges({
groupID: group.id,
userID: values.userID,
canWrite: values.canWrite,
isOwner: values.isOwner,
})
.then((result) => {
setSubmitting(false);
setShowEditMemberDialog(false);
toast.success("Successfully updated group member permissions");
})
.catch((err) => {
setSubmitting(false);
toast.error(err);
});
};
const getMemberUsername = (member_id) => {
const member = members.find((member) => member.user_id === member_id);
if (member === undefined) {
return "unknown";
}
return member.username;
};
const closeEditMemberModal = () => {
setShowEditMemberDialog(false);
setMemberToEdit(null);
};
const openEditMemberModal = (userID) => {
const user = members.find((member) => member.user_id === userID);
// TODO: maybe deal with disappearing users in the list
setMemberToEdit(user);
setShowEditMemberDialog(true);
};
return (
<MobilePaper>
<List>
{members.length === 0 ? (
<ListItem>
<ListItemText primary="No Members" />
</ListItem>
) : (
members.map((member, index) => (
<ListItem key={index}>
<ListItemText
primary={
<>
<span style={{ marginRight: 5 }}>{member.username}</span>
{member.is_owner ? (
<Chip
size="small"
sx={{ mr: 1 }}
component="span"
color="primary"
label="owner"
variant="outlined"
/>
) : member.can_write ? (
<Chip
size="small"
sx={{ mr: 1 }}
component="span"
color="primary"
label="editor"
variant="outlined"
/>
) : null}
{member.user_id === currentUser.id ? (
<Chip
size="small"
sx={{ mr: 1 }}
component="span"
color="primary"
label="it's you"
/>
) : (
""
)}
</>
}
secondary={
<>
{member.invited_by && (
<small className="text-muted">
invited by {getMemberUsername(member.invited_by)}
</small>
)}
<small className="text-muted">
joined{" "}
{DateTime.fromISO(member.joined_at).toLocaleString(DateTime.DATETIME_FULL)}
</small>
</>
}
/>
{permissions.is_owner || permissions.can_write ? (
<ListItemSecondaryAction>
<IconButton onClick={() => openEditMemberModal(member.user_id)}>
<Edit />
</IconButton>
</ListItemSecondaryAction>
) : (
""
)}
</ListItem>
))
)}
</List>
<Dialog open={showEditMemberDialog} onClose={closeEditMemberModal}>
<DialogTitle>Edit Group Member</DialogTitle>
<DialogContent>
<Formik
initialValues={{
userID: memberToEdit ? memberToEdit.user_id : -1,
isOwner: memberToEdit ? memberToEdit.is_owner : false,
canWrite: memberToEdit ? memberToEdit.can_write : false,
}}
onSubmit={handleEditMemberSubmit}
enableReinitialize={true}
>
{({ values, handleBlur, handleChange, handleSubmit, isSubmitting }) => (
<Form>
<FormControlLabel
control={
<Checkbox
name="canWrite"
onBlur={handleBlur}
onChange={handleChange}
checked={values.canWrite}
/>
}
label="Can Write"
/>
<FormControlLabel
control={
<Checkbox
name="isOwner"
onBlur={handleBlur}
onChange={handleChange}
checked={values.isOwner}
/>
}
label="Is Owner"
/>
{isSubmitting && <LinearProgress />}
<DialogActions>
<Button type="submit" color="primary">
Save
</Button>
<Button color="error" onClick={closeEditMemberModal}>
Close
</Button>
</DialogActions>
</Form>
)}
</Formik>
</DialogContent>
</Dialog>
</MobilePaper>
);
}
Example #6
Source File: SessionList.tsx From abrechnung with GNU Affero General Public License v3.0 | 4 votes |
export default function SessionList() {
// TODO: fix editing functions
const [editedSessions, setEditedSessions] = useState({});
const [sessionToDelete, setSessionToDelete] = useState({
show: false,
toDelete: null,
});
const user = useRecoilValue(userData);
const sessions = user.sessions;
useTitle("Abrechnung - Sessions");
const editSession = (id) => {
if (!editedSessions.hasOwnProperty(id)) {
const newSessions = {
...editedSessions,
[id]: sessions.find((session) => session.id === id)?.name,
};
setEditedSessions(newSessions);
}
};
const stopEditSession = (id) => {
if (editedSessions.hasOwnProperty(id)) {
let newEditedSessions = { ...editedSessions };
delete newEditedSessions[id];
setEditedSessions(newEditedSessions);
}
};
const closeDeleteSessionModal = () => {
setSessionToDelete({ show: false, toDelete: null });
};
const performRename = (id) => {
if (editedSessions.hasOwnProperty(id)) {
renameSession({
sessionID: id,
name: editedSessions[id],
}).catch((err) => {
toast.error(err);
});
stopEditSession(id);
}
};
const openDeleteSessionModal = (id) => {
setSessionToDelete({ show: true, toDelete: id });
};
const confirmDeleteSession = () => {
if (sessionToDelete.toDelete !== null) {
deleteSession({ sessionID: sessionToDelete.toDelete }).catch((err) => {
toast.error(err);
});
setSessionToDelete({ show: false, toDelete: null });
}
};
const handleEditChange = (id, value) => {
const newEditedSessions = { ...editedSessions, [id]: value };
setEditedSessions(newEditedSessions);
};
const onKeyUp = (id) => (key) => {
if (key.keyCode === 13) {
performRename(id);
}
};
return (
<MobilePaper>
<Typography component="h3" variant="h5">
Login Sessions
</Typography>
<List>
{sessions.map((session) => {
if (editedSessions.hasOwnProperty(session.id)) {
return (
<ListItem key={session.id}>
<TextField
margin="normal"
variant="standard"
fullWidth
onKeyUp={onKeyUp(session.id)}
value={editedSessions[session.id]}
onChange={(event) => handleEditChange(session.id, event.target.value)}
/>
<ListItemSecondaryAction>
<Button onClick={() => performRename(session.id)}>
<Check />
</Button>
<Button onClick={() => stopEditSession(session.id)}>
<Close />
</Button>
</ListItemSecondaryAction>
</ListItem>
);
} else {
return (
<ListItem key={session.id}>
<ListItemText
primary={session.name}
secondary={
<>
<span>
Valid until{" "}
{DateTime.fromISO(session.valid_until).toLocaleString(
DateTime.DATETIME_FULL
) && "indefinitely"}
,{" "}
</span>
<span>
Last seen on{" "}
{DateTime.fromISO(session.last_seen).toLocaleString(
DateTime.DATETIME_FULL
)}
</span>
</>
}
/>
<ListItemSecondaryAction>
<IconButton onClick={() => editSession(session.id)}>
<Edit />
</IconButton>
<IconButton onClick={() => openDeleteSessionModal(session.id)}>
<Delete />
</IconButton>
</ListItemSecondaryAction>
</ListItem>
);
}
})}
</List>
<Dialog open={sessionToDelete.show} onClose={closeDeleteSessionModal}>
<DialogTitle>Delete Session?</DialogTitle>
<DialogContent>
<DialogContentText>
{sessionToDelete.toDelete !== null
? `Are you sure you want to delete session ${
sessions.find((session) => session.id === sessionToDelete.toDelete)?.name
}`
: null}
</DialogContentText>
</DialogContent>
<DialogActions>
<Button color="secondary" onClick={confirmDeleteSession}>
Yes pls
</Button>
<Button color="primary" onClick={closeDeleteSessionModal}>
No
</Button>
</DialogActions>
</Dialog>
</MobilePaper>
);
}
Example #7
Source File: LangSelect.tsx From Tachidesk-WebUI with Mozilla Public License 2.0 | 4 votes |
export default function LangSelect(props: IProps) {
const {
shownLangs, setShownLangs, allLangs, forcedLangs,
} = props;
// hold a copy and only sate state on parent when OK pressed, improves performance
const [mShownLangs, setMShownLangs] = useState(
removeAll(cloneObject(shownLangs), forcedLangs!),
);
const [open, setOpen] = useState<boolean>(false);
const handleCancel = () => {
setOpen(false);
};
const handleOk = () => {
setOpen(false);
setShownLangs(mShownLangs);
};
const handleChange = (event: React.ChangeEvent<HTMLInputElement>, lang: string) => {
const { checked } = event.target as HTMLInputElement;
if (checked) {
setMShownLangs([...mShownLangs, lang]);
} else {
const clone = cloneObject(mShownLangs);
clone.splice(clone.indexOf(lang), 1);
setMShownLangs(clone);
}
};
return (
<>
<IconButton
onClick={() => setOpen(true)}
aria-label="display more actions"
edge="end"
color="inherit"
size="large"
>
<FilterListIcon />
</IconButton>
<Dialog
sx={{
'.MuiDialog-paper': {
maxHeight: 435,
width: '80%',
},
}}
maxWidth="xs"
open={open}
>
<DialogTitle>Enabled Languages</DialogTitle>
<DialogContent dividers sx={{ padding: 0 }}>
<List>
{allLangs.map((lang) => (
<ListItem key={lang}>
<ListItemText primary={langCodeToName(lang)} />
<ListItemSecondaryAction>
<Switch
checked={mShownLangs.indexOf(lang) !== -1}
onChange={(e) => handleChange(e, lang)}
/>
</ListItemSecondaryAction>
</ListItem>
))}
</List>
</DialogContent>
<DialogActions>
<Button autoFocus onClick={handleCancel} color="primary">
Cancel
</Button>
<Button onClick={handleOk} color="primary">
Ok
</Button>
</DialogActions>
</Dialog>
</>
);
}