Update web app with SMS and calls stuff
This commit is contained in:
		
							parent
							
								
									7677c50b0e
								
							
						
					
					
						commit
						eb0805a470
					
				
					 14 changed files with 274 additions and 39 deletions
				
			
		|  | @ -51,6 +51,7 @@ import {ContentCopy, Public} from "@mui/icons-material"; | |||
| import MenuItem from "@mui/material/MenuItem"; | ||||
| import DialogContentText from "@mui/material/DialogContentText"; | ||||
| import {IncorrectPasswordError, UnauthorizedError} from "../app/errors"; | ||||
| import {ProChip} from "./SubscriptionPopup"; | ||||
| 
 | ||||
| const Account = () => { | ||||
|     if (!session.exists()) { | ||||
|  | @ -337,23 +338,18 @@ const Stats = () => { | |||
|                 {t("account_usage_title")} | ||||
|             </Typography> | ||||
|             <PrefGroup> | ||||
|                 <Pref title={t("account_usage_reservations_title")}> | ||||
|                     {(account.role === Role.ADMIN || account.limits.reservations > 0) && | ||||
|                         <> | ||||
|                             <div> | ||||
|                                 <Typography variant="body2" sx={{float: "left"}}>{account.stats.reservations}</Typography> | ||||
|                                 <Typography variant="body2" sx={{float: "right"}}>{account.role === Role.USER ? t("account_usage_of_limit", {limit: account.limits.reservations}) : t("account_usage_unlimited")}</Typography> | ||||
|                             </div> | ||||
|                             <LinearProgress | ||||
|                                 variant="determinate" | ||||
|                                 value={account.role === Role.USER && account.limits.reservations > 0 ? normalize(account.stats.reservations, account.limits.reservations) : 100} | ||||
|                             /> | ||||
|                         </> | ||||
|                     } | ||||
|                     {account.role === Role.USER && account.limits.reservations === 0 && | ||||
|                         <em>{t("account_usage_reservations_none")}</em> | ||||
|                     } | ||||
|                 </Pref> | ||||
|                 {(account.role === Role.ADMIN || account.limits.reservations > 0) && | ||||
|                     <Pref title={t("account_usage_reservations_title")}> | ||||
|                         <div> | ||||
|                             <Typography variant="body2" sx={{float: "left"}}>{account.stats.reservations.toLocaleString()}</Typography> | ||||
|                             <Typography variant="body2" sx={{float: "right"}}>{account.role === Role.USER ? t("account_usage_of_limit", { limit: account.limits.reservations.toLocaleString() }) : t("account_usage_unlimited")}</Typography> | ||||
|                         </div> | ||||
|                         <LinearProgress | ||||
|                             variant="determinate" | ||||
|                             value={account.role === Role.USER && account.limits.reservations > 0 ? normalize(account.stats.reservations, account.limits.reservations) : 100} | ||||
|                         /> | ||||
|                     </Pref> | ||||
|                 } | ||||
|                 <Pref title={ | ||||
|                     <> | ||||
|                         {t("account_usage_messages_title")} | ||||
|  | @ -361,8 +357,8 @@ const Stats = () => { | |||
|                     </> | ||||
|                 }> | ||||
|                     <div> | ||||
|                         <Typography variant="body2" sx={{float: "left"}}>{account.stats.messages}</Typography> | ||||
|                         <Typography variant="body2" sx={{float: "right"}}>{account.role === Role.USER ? t("account_usage_of_limit", { limit: account.limits.messages }) : t("account_usage_unlimited")}</Typography> | ||||
|                         <Typography variant="body2" sx={{float: "left"}}>{account.stats.messages.toLocaleString()}</Typography> | ||||
|                         <Typography variant="body2" sx={{float: "right"}}>{account.role === Role.USER ? t("account_usage_of_limit", { limit: account.limits.messages.toLocaleString() }) : t("account_usage_unlimited")}</Typography> | ||||
|                     </div> | ||||
|                     <LinearProgress | ||||
|                         variant="determinate" | ||||
|  | @ -376,14 +372,48 @@ const Stats = () => { | |||
|                     </> | ||||
|                 }> | ||||
|                     <div> | ||||
|                         <Typography variant="body2" sx={{float: "left"}}>{account.stats.emails}</Typography> | ||||
|                         <Typography variant="body2" sx={{float: "right"}}>{account.role === Role.USER ? t("account_usage_of_limit", { limit: account.limits.emails }) : t("account_usage_unlimited")}</Typography> | ||||
|                         <Typography variant="body2" sx={{float: "left"}}>{account.stats.emails.toLocaleString()}</Typography> | ||||
|                         <Typography variant="body2" sx={{float: "right"}}>{account.role === Role.USER ? t("account_usage_of_limit", { limit: account.limits.emails.toLocaleString() }) : t("account_usage_unlimited")}</Typography> | ||||
|                     </div> | ||||
|                     <LinearProgress | ||||
|                         variant="determinate" | ||||
|                         value={account.role === Role.USER ? normalize(account.stats.emails, account.limits.emails) : 100} | ||||
|                     /> | ||||
|                 </Pref> | ||||
|                 {(account.role === Role.ADMIN || account.limits.sms > 0) && | ||||
|                     <Pref title={ | ||||
|                         <> | ||||
|                             {t("account_usage_sms_title")} | ||||
|                             <Tooltip title={t("account_usage_limits_reset_daily")}><span><InfoIcon/></span></Tooltip> | ||||
|                         </> | ||||
|                     }> | ||||
|                         <div> | ||||
|                             <Typography variant="body2" sx={{float: "left"}}>{account.stats.sms.toLocaleString()}</Typography> | ||||
|                             <Typography variant="body2" sx={{float: "right"}}>{account.role === Role.USER ? t("account_usage_of_limit", { limit: account.limits.sms.toLocaleString() }) : t("account_usage_unlimited")}</Typography> | ||||
|                         </div> | ||||
|                         <LinearProgress | ||||
|                             variant="determinate" | ||||
|                             value={account.role === Role.USER && account.limits.sms > 0 ? normalize(account.stats.sms, account.limits.sms) : 100} | ||||
|                         /> | ||||
|                     </Pref> | ||||
|                 } | ||||
|                 {(account.role === Role.ADMIN || account.limits.calls > 0) && | ||||
|                     <Pref title={ | ||||
|                         <> | ||||
|                             {t("account_usage_calls_title")} | ||||
|                             <Tooltip title={t("account_usage_limits_reset_daily")}><span><InfoIcon/></span></Tooltip> | ||||
|                         </> | ||||
|                     }> | ||||
|                         <div> | ||||
|                             <Typography variant="body2" sx={{float: "left"}}>{account.stats.calls.toLocaleString()}</Typography> | ||||
|                             <Typography variant="body2" sx={{float: "right"}}>{account.role === Role.USER ? t("account_usage_of_limit", { limit: account.limits.calls.toLocaleString() }) : t("account_usage_unlimited")}</Typography> | ||||
|                         </div> | ||||
|                         <LinearProgress | ||||
|                             variant="determinate" | ||||
|                             value={account.role === Role.USER && account.limits.sms > 0 ? normalize(account.stats.calls, account.limits.calls) : 100} | ||||
|                         /> | ||||
|                     </Pref> | ||||
|                 } | ||||
|                 <Pref | ||||
|                     alignTop | ||||
|                     title={t("account_usage_attachment_storage_title")} | ||||
|  | @ -404,6 +434,21 @@ const Stats = () => { | |||
|                         value={account.role === Role.USER ? normalize(account.stats.attachment_total_size, account.limits.attachment_total_size) : 100} | ||||
|                     /> | ||||
|                 </Pref> | ||||
|                 {config.enable_reservations && account.role === Role.USER && account.limits.reservations === 0 && | ||||
|                     <Pref title={<>{t("account_usage_reservations_title")}{config.enable_payments && <ProChip/>}</>}> | ||||
|                         <em>{t("account_usage_reservations_none")}</em> | ||||
|                     </Pref> | ||||
|                 } | ||||
|                 {config.enable_sms && account.role === Role.USER && account.limits.sms === 0 && | ||||
|                     <Pref title={<>{t("account_usage_sms_title")}{config.enable_payments && <ProChip/>}</>}> | ||||
|                         <em>{t("account_usage_sms_none")}</em> | ||||
|                     </Pref> | ||||
|                 } | ||||
|                 {config.enable_calls && account.role === Role.USER && account.limits.calls === 0 && | ||||
|                     <Pref title={<>{t("account_usage_calls_title")}{config.enable_payments && <ProChip/>}</>}> | ||||
|                         <em>{t("account_usage_calls_none")}</em> | ||||
|                     </Pref> | ||||
|                 } | ||||
|             </PrefGroup> | ||||
|             {account.role === Role.USER && account.limits.basis === LimitBasis.IP && | ||||
|                 <Typography variant="body1"> | ||||
|  |  | |||
|  | @ -45,6 +45,8 @@ const PublishDialog = (props) => { | |||
|     const [filename, setFilename] = useState(""); | ||||
|     const [filenameEdited, setFilenameEdited] = useState(false); | ||||
|     const [email, setEmail] = useState(""); | ||||
|     const [sms, setSms] = useState(""); | ||||
|     const [call, setCall] = useState(""); | ||||
|     const [delay, setDelay] = useState(""); | ||||
|     const [publishAnother, setPublishAnother] = useState(false); | ||||
| 
 | ||||
|  | @ -52,6 +54,8 @@ const PublishDialog = (props) => { | |||
|     const [showClickUrl, setShowClickUrl] = useState(false); | ||||
|     const [showAttachUrl, setShowAttachUrl] = useState(false); | ||||
|     const [showEmail, setShowEmail] = useState(false); | ||||
|     const [showSms, setShowSms] = useState(false); | ||||
|     const [showCall, setShowCall] = useState(false); | ||||
|     const [showDelay, setShowDelay] = useState(false); | ||||
| 
 | ||||
|     const showAttachFile = !!attachFile && !showAttachUrl; | ||||
|  | @ -124,6 +128,12 @@ const PublishDialog = (props) => { | |||
|         if (email.trim()) { | ||||
|             url.searchParams.append("email", email.trim()); | ||||
|         } | ||||
|         if (sms.trim()) { | ||||
|             url.searchParams.append("sms", sms.trim()); | ||||
|         } | ||||
|         if (call.trim()) { | ||||
|             url.searchParams.append("call", call.trim()); | ||||
|         } | ||||
|         if (delay.trim()) { | ||||
|             url.searchParams.append("delay", delay.trim()); | ||||
|         } | ||||
|  | @ -406,6 +416,48 @@ const PublishDialog = (props) => { | |||
|                             /> | ||||
|                         </ClosableRow> | ||||
|                     } | ||||
|                     {showSms && | ||||
|                         <ClosableRow disabled={disabled} closeLabel={t("publish_dialog_sms_reset")} onClose={() => { | ||||
|                             setSms(""); | ||||
|                             setShowSms(false); | ||||
|                         }}> | ||||
|                             <TextField | ||||
|                                 margin="dense" | ||||
|                                 label={t("publish_dialog_sms_label")} | ||||
|                                 placeholder={t("publish_dialog_sms_placeholder")} | ||||
|                                 value={sms} | ||||
|                                 onChange={ev => setSms(ev.target.value)} | ||||
|                                 disabled={disabled} | ||||
|                                 type="tel" | ||||
|                                 variant="standard" | ||||
|                                 fullWidth | ||||
|                                 inputProps={{ | ||||
|                                     "aria-label": t("publish_dialog_sms_label") | ||||
|                                 }} | ||||
|                             /> | ||||
|                         </ClosableRow> | ||||
|                     } | ||||
|                     {showCall && | ||||
|                         <ClosableRow disabled={disabled} closeLabel={t("publish_dialog_call_reset")} onClose={() => { | ||||
|                             setCall(""); | ||||
|                             setShowCall(false); | ||||
|                         }}> | ||||
|                             <TextField | ||||
|                                 margin="dense" | ||||
|                                 label={t("publish_dialog_call_label")} | ||||
|                                 placeholder={t("publish_dialog_call_placeholder")} | ||||
|                                 value={call} | ||||
|                                 onChange={ev => setCall(ev.target.value)} | ||||
|                                 disabled={disabled} | ||||
|                                 type="tel" | ||||
|                                 variant="standard" | ||||
|                                 fullWidth | ||||
|                                 inputProps={{ | ||||
|                                     "aria-label": t("publish_dialog_call_label") | ||||
|                                 }} | ||||
|                             /> | ||||
|                         </ClosableRow> | ||||
|                     } | ||||
|                     {showAttachUrl && | ||||
|                         <ClosableRow disabled={disabled} closeLabel={t("publish_dialog_attach_reset")} onClose={() => { | ||||
|                             setAttachUrl(""); | ||||
|  | @ -510,6 +562,8 @@ const PublishDialog = (props) => { | |||
|                     <div> | ||||
|                         {!showClickUrl && <Chip clickable disabled={disabled} label={t("publish_dialog_chip_click_label")} aria-label={t("publish_dialog_chip_click_label")} onClick={() => setShowClickUrl(true)} sx={{marginRight: 1, marginBottom: 1}}/>} | ||||
|                         {!showEmail && <Chip clickable disabled={disabled} label={t("publish_dialog_chip_email_label")} aria-label={t("publish_dialog_chip_email_label")} onClick={() => setShowEmail(true)} sx={{marginRight: 1, marginBottom: 1}}/>} | ||||
|                         {!showSms && <Chip clickable disabled={disabled} label={t("publish_dialog_chip_sms_label")} aria-label={t("publish_dialog_chip_sms_label")} onClick={() => setShowSms(true)} sx={{marginRight: 1, marginBottom: 1}}/>} | ||||
|                         {!showCall && <Chip clickable disabled={disabled} label={t("publish_dialog_chip_call_label")} aria-label={t("publish_dialog_chip_call_label")} onClick={() => setShowCall(true)} sx={{marginRight: 1, marginBottom: 1}}/>} | ||||
|                         {!showAttachUrl && !showAttachFile && <Chip clickable disabled={disabled} label={t("publish_dialog_chip_attach_url_label")} aria-label={t("publish_dialog_chip_attach_url_label")} onClick={() => setShowAttachUrl(true)} sx={{marginRight: 1, marginBottom: 1}}/>} | ||||
|                         {!showAttachFile && !showAttachUrl && <Chip clickable disabled={disabled} label={t("publish_dialog_chip_attach_file_label")} aria-label={t("publish_dialog_chip_attach_file_label")} onClick={() => handleAttachFileClick()} sx={{marginRight: 1, marginBottom: 1}}/>} | ||||
|                         {!showDelay && <Chip clickable disabled={disabled} label={t("publish_dialog_chip_delay_label")} aria-label={t("publish_dialog_chip_delay_label")} onClick={() => setShowDelay(true)} sx={{marginRight: 1, marginBottom: 1}}/>} | ||||
|  |  | |||
|  | @ -277,14 +277,14 @@ const LimitReachedChip = () => { | |||
|     ); | ||||
| }; | ||||
| 
 | ||||
| const ProChip = () => { | ||||
| export const ProChip = () => { | ||||
|     const { t } = useTranslation(); | ||||
|     return ( | ||||
|         <Chip | ||||
|             label={"ntfy Pro"} | ||||
|             variant="outlined" | ||||
|             color="primary" | ||||
|             sx={{ opacity: 0.8, borderWidth: "2px", height: "24px", marginLeft: "5px" }} | ||||
|             sx={{ opacity: 0.8, fontWeight: "bold", borderWidth: "2px", height: "24px", marginLeft: "5px" }} | ||||
|         /> | ||||
|     ); | ||||
| }; | ||||
|  |  | |||
|  | @ -298,11 +298,14 @@ const TierCard = (props) => { | |||
|                         </div> | ||||
|                         <List dense> | ||||
|                             {tier.limits.reservations > 0 && <Feature>{t("account_upgrade_dialog_tier_features_reservations", { reservations: tier.limits.reservations, count: tier.limits.reservations })}</Feature>} | ||||
|                             {tier.limits.reservations === 0 && <NoFeature>{t("account_upgrade_dialog_tier_features_no_reservations")}</NoFeature>} | ||||
|                             <Feature>{t("account_upgrade_dialog_tier_features_messages", { messages: formatNumber(tier.limits.messages), count: tier.limits.messages })}</Feature> | ||||
|                             <Feature>{t("account_upgrade_dialog_tier_features_emails", { emails: formatNumber(tier.limits.emails), count: tier.limits.emails })}</Feature> | ||||
|                             {tier.limits.sms > 0 && <Feature>{t("account_upgrade_dialog_tier_features_sms", { sms: formatNumber(tier.limits.sms), count: tier.limits.sms })}</Feature>} | ||||
|                             {tier.limits.calls > 0 && <Feature>{t("account_upgrade_dialog_tier_features_calls", { calls: formatNumber(tier.limits.calls), count: tier.limits.calls })}</Feature>} | ||||
|                             <Feature>{t("account_upgrade_dialog_tier_features_attachment_file_size", { filesize: formatBytes(tier.limits.attachment_file_size, 0) })}</Feature> | ||||
|                             <Feature>{t("account_upgrade_dialog_tier_features_attachment_total_size", { totalsize: formatBytes(tier.limits.attachment_total_size, 0) })}</Feature> | ||||
|                             {tier.limits.reservations === 0 && <NoFeature>{t("account_upgrade_dialog_tier_features_no_reservations")}</NoFeature>} | ||||
|                             {tier.limits.sms === 0 && <NoFeature>{t("account_upgrade_dialog_tier_features_no_sms")}</NoFeature>} | ||||
|                             {tier.limits.calls === 0 && <NoFeature>{t("account_upgrade_dialog_tier_features_no_calls")}</NoFeature>} | ||||
|                         </List> | ||||
|                         {tier.prices && props.interval === SubscriptionInterval.MONTH && | ||||
|                             <Typography variant="body2" color="gray"> | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue