react-toastify#toast TypeScript Examples

The following examples show how to use react-toastify#toast. 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: utils.tsx    From posthog-foss with MIT License 7 votes vote down vote up
export function editingToast(
    item: string,
    setItemMode:
        | ((mode: DashboardMode | null, source: DashboardEventSource) => void)
        | ((mode: ItemMode | null, source: DashboardEventSource) => void)
): any {
    return toast(
        <>
            <h1>{item} edit mode</h1>
            <p>Tap below when finished.</p>
            <div className="text-right">
                <Button>Finish editing</Button>
            </div>
        </>,
        {
            type: 'info',
            autoClose: false,
            onClick: () => setItemMode(null, DashboardEventSource.Toast),
            closeButton: false,
            className: 'drag-items-toast accent-border',
        }
    )
}
Example #2
Source File: ErrorToast.tsx    From dxvote with GNU Affero General Public License v3.0 6 votes vote down vote up
export default function ErrorToast(toastText, modalText) {
  return toast.error(
    <div>
      {toastText}
      <ErrorToastButton>More</ErrorToastButton>
      <Modal
        header={<h1>Error</h1>}
        isOpen={true}
        onDismiss={() => console.log(1)}
        onConfirm={() => navigator.clipboard.writeText(modalText)}
        onCancel={() => console.log(1)}
        confirmText={'Copy to Clipboard'}
        cancelText={'Contact'}
      >
        <p>{modalText}</p>
      </Modal>
    </div>,
    {
      position: 'bottom-right',
      autoClose: 50000,
      hideProgressBar: false,
      closeOnClick: true,
      pauseOnHover: true,
      draggable: true,
      progress: undefined,
    }
  );
}
Example #3
Source File: Base.tsx    From mail-my-ballot with Apache License 2.0 6 votes vote down vote up
SignatureBase = <Info extends StateInfo>(
  {enrichValues, children}: Props<NoSignature<Info>>
) => {
  const [signature, setSignature] = React.useState<string | null>()

  const enrichValuesWithSignature = (baseInfo: StatelessInfo): Info | null => {
    const values = enrichValues(baseInfo)
    if (!values) return null

    if (!signature) {
      // Do not dismiss previous errors which may give more details on bad fields
      toast.error('Please fill out the signature field')
      return null
    }

    return {
      ...baseInfo,
      ...values,
      signature,
    } as Info  // hack b/c it cannot understand how to distribute over types
  }

  return <Base<Info>
    enrichValues={enrichValuesWithSignature}
  >
    { children }
    <Signature setSignature={setSignature}/>
  </Base>
}
Example #4
Source File: AlertContainer.tsx    From lightning-terminal with MIT License 6 votes vote down vote up
AlertToast: React.FC<AlertToastProps> = ({ alert, onClose }) => {
  // use useEffect to only run the side-effect one time
  useEffect(() => {
    const { id, type, message, title, ms: autoClose } = alert;
    // create a component to display inside of the toast
    const { Body, Title, Message } = Styled;
    const body = (
      <Body>
        {title && <Title>{title}</Title>}
        <Message>{message}</Message>
      </Body>
    );
    // display the toast popup containing the styled body
    toast(body, { type, autoClose, onClose: () => onClose(id) });
  }, [alert, onClose]);

  // do not render anything to the dom. the toast() func will display the content
  return null;
}
Example #5
Source File: newsFeedSaga.ts    From foodie with MIT License 6 votes vote down vote up
function* newsFeedSaga({ type, payload }: INewsFeedSaga) {
    switch (type) {
        case GET_FEED_START:
            try {
                yield put(isGettingFeed(true));
                yield put(setNewsFeedErrorMessage(null));

                const posts: IPost[] = yield call(getNewsFeed, payload);

                yield put(isGettingFeed(false));
                yield put(getNewsFeedSuccess(posts));
            } catch (e) {
                console.log(e);
                yield put(isGettingFeed(false));
                yield put(setNewsFeedErrorMessage(e))
            }

            break;
        case CREATE_POST_START:
            try {
                yield put(isCreatingPost(true));

                const post: IPost = yield call(createPost, payload);

                yield put(createPostSuccess(post));
                yield put(isCreatingPost(false));
                toast.dismiss();
                toast.dark('Post succesfully created.');
            } catch (e) {
                yield put(isCreatingPost(false));
                console.log(e);
            }
            break;
        default:
            throw new Error('Unexpected action type.')
    }
}
Example #6
Source File: index.tsx    From freedeck-configurator with GNU General Public License v3.0 6 votes vote down vote up
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
register({
  onUpdate: (registration) => {
    toast("There is an Update! Click here to update.", {
      autoClose: false,
      position: "bottom-right",
      onClick: () => {
        if (registration && registration.waiting) {
          registration.waiting.postMessage({ type: "SKIP_WAITING" });
        }
        window.location.reload();
      },
    });
  },
});
Example #7
Source File: store.ts    From polkabtc-ui with Apache License 2.0 6 votes vote down vote up
saveState = (store: AppState): void => {
  try {
    const preparedState = {
      ...store,
      issue: {
        ...store.issue,
        issueRequests: mapToArray(store.issue.issueRequests)
      },
      redeem: {
        ...store.redeem,
        redeemRequests: mapToArray(store.redeem.redeemRequests)
      }
    };
    const serializedState = JSON.stringify(preparedState);
    localStorage.setItem(constants.STORE_NAME, serializedState);
  } catch (error) {
    setTimeout(
      () => toast.error('Local storage is disabled. In order to use platform please enable local storage'),
      2000
    );
  }
}
Example #8
Source File: usePromoToast.ts    From index-ui with MIT License 6 votes vote down vote up
usePromoToast = (component: React.ReactElement, toastId: string) => {
  const [hasBeenDismissed, setHasBeenDismissed] = useLocalStorage(
    toastId,
    false
  )

  useEffect(() => {
    !hasBeenDismissed &&
      toast.success(component, {
        position: 'bottom-right',
        autoClose: false,
        closeOnClick: false,
        draggable: false,
        closeButton: true,
        toastId,
        onClose: () => setHasBeenDismissed(true),
      })
  }, [])

  return null
}
Example #9
Source File: store.ts    From polkabtc-ui with Apache License 2.0 6 votes vote down vote up
loadState = (): StoreType => {
  try {
    const serializedState = localStorage.getItem(constants.STORE_NAME);
    if (serializedState === null) {
      const initialState = getInitialState();
      return initialState;
    }
    const rawStore = JSON.parse(serializedState);
    const deserializedState = {
      ...rawStore,
      general: {
        ...rawStore.general,
        polkaBtcLoaded: false,
        relayerLoaded: false
      }
    };
    return {
      ...deserializedState,
      issue: {
        ...deserializedState.issue,
        issueRequests: arrayToMap(deserializedState.issue.issueRequests)
      },
      redeem: {
        ...deserializedState.redeem,
        redeemRequests: arrayToMap(deserializedState.redeem.redeemRequests)
      }
    };
  } catch (error) {
    setTimeout(
      () => toast.error('Local storage is disabled. In order to use platform please enable local storage'),
      2000
    );
    const initialState = getInitialState();
    return initialState;
  }
}
Example #10
Source File: useCopyClipboardToast.tsx    From tsplay.dev with MIT License 6 votes vote down vote up
useCopyClipboardToast = (): ShowToast => {
  const [toastId, setToastId] = React.useState<string | number>('')

  const showToast = React.useCallback<ShowToast>(
    (content, options = {}, isError) => {
      const toastFc = isError ? toast.error : toast

      if (toastId) {
        toast.dismiss(toastId)
        options.delay = 270
      }

      const newToastId = toastFc(content, options)
      setToastId(newToastId)
    },
    [toastId]
  )

  return showToast
}
Example #11
Source File: fetcher.ts    From yasd with MIT License 6 votes vote down vote up
fetcher = <T>(requestConfig: AxiosRequestConfig): Promise<T> => {
  return client
    .request<T>(requestConfig)
    .then((res) => res.data)
    .catch((error) => {
      if (error.response) {
        // The request was made and the server responded with a status code
        // that falls out of the range of 2xx
        console.error(error.response.data)
        console.error(error.response.status)
        toast.error('请求错误: ' + error.message + `(${error.response.status})`)
      } else if (error.request) {
        // The request was made but no response was received
        // `error.request` is an instance of XMLHttpRequest in the browser and an instance of
        // http.ClientRequest in node.js
        console.error(error.request)
        toast.error('无法连接服务器: ' + error.message, {
          toastId: error.message,
        })
      } else {
        // Something happened in setting up the request that triggered an Error
        console.error('Error', error.message)
        toast.error('发生错误: ' + error.message)
      }

      throw error
    })
}
Example #12
Source File: index.tsx    From Next.js_GraphQL_Express_Apollo_Boilerplate with MIT License 6 votes vote down vote up
handleSubmit = async (updateUser: any, event: any) => {
    try {
      event.preventDefault();
      const { state, props } = this;
      if (validateEmail(state.email)) {
        await updateUser({
          variables: {
            userId: props.userId,
            updateUser: { ...state },
          },
        });
        toast.success('Profile Updated');
        props.history.push('/welcome');
      } else {
        toast.error('Invalid Email');
      }
    } catch (error) {
      toast.error('Check your connection');
    }
  };
Example #13
Source File: requestJSON.ts    From Hybooru with MIT License 6 votes vote down vote up
export default async function requestJSON<Res, Req extends Record<string, any> = Record<string, any>>(options: RequestOptions<Req> = {}): Promise<Res> {
  if(isNode) return new Promise(() => {});
  let { method, href, host, pathname, search, cancelCb, data } = options;
  
  host = host || location.host;
  pathname = pathname || location.pathname;
  if(search && typeof search !== "string") {
    search = qs.stringify(search);
  }
  search = search ? "?" + search : location.search;
  href = href || `//${host}${pathname}${search}`;
  method = method || "GET";
  
  let response;
  try {
    response = await axios({
      method,
      url: href,
      data,
      cancelToken: cancelCb ? new CancelToken(cancelCb) : undefined,
    });
  } catch(err) {
    if(!(err instanceof axios.Cancel)) toast.error(err.response?.data?._error?.message || err.message);
    throw err;
  }
  
  return response.data;
}
Example #14
Source File: LogoutButton.tsx    From frontend with Apache License 2.0 6 votes vote down vote up
LogoutButton: FunctionComponent = () => {
  const { t } = useTranslation()
  // Using state to prevent user repeatedly initating fetches
  const [clicked, setClicked] = useState(false)
  const dispatch = useUserDispatch()

  // Only make a request on first click
  useEffect(() => {
    if (clicked) {
      logout(dispatch)
        .catch(err => {
          toast.error(t(err))
          setClicked(false)
        })
    }
  }, [dispatch, clicked, t])

  return (
    <Button onClick={() => setClicked(true)} type='primary'>
      {t('log-out')}
    </Button>
  )
}
Example #15
Source File: personalAPIKeysLogic.ts    From posthog-foss with MIT License 6 votes vote down vote up
personalAPIKeysLogic = kea<personalAPIKeysLogicType>({
    path: ['lib', 'components', 'PersonalAPIKeys', 'personalAPIKeysLogic'],
    loaders: ({ values }) => ({
        keys: [
            [] as PersonalAPIKeyType[],
            {
                loadKeys: async () => {
                    const response: PersonalAPIKeyType[] = await api.get('api/personal_api_keys/')
                    return response
                },
                createKey: async (label: string) => {
                    const newKey: PersonalAPIKeyType = await api.create('api/personal_api_keys/', {
                        label,
                    })
                    return [newKey, ...values.keys]
                },
                deleteKey: async (key: PersonalAPIKeyType) => {
                    await api.delete(`api/personal_api_keys/${key.id}/`)
                    return (values.keys as PersonalAPIKeyType[]).filter((filteredKey) => filteredKey.id != key.id)
                },
            },
        ],
    }),
    listeners: () => ({
        createKeySuccess: ({ keys }: { keys: PersonalAPIKeyType[] }) => {
            keys[0]?.value && copyToClipboard(keys[0].value, 'personal API key value')
        },
        deleteKeySuccess: ({}: { keys: PersonalAPIKeyType[] }) => {
            toast.success(`Personal API key deleted.`)
        },
    }),

    events: ({ actions }) => ({
        afterMount: [actions.loadKeys],
    }),
})
Example #16
Source File: index.ts    From sdc-ide with MIT License 6 votes vote down vote up
showToast = (type: 'success' | 'error', error?: OperationOutcome, index?: number) => {
    if (type === 'success') {
        return toast.success('New mapper created');
    }
    if (type === 'error') {
        return toast.error(
            formatError(error, {
                mapping: { conflict: 'Please reload page' },
                format: (errorCode, errorDescription) =>
                    `An error occurred: ${error?.issue[index as number]?.diagnostics || errorDescription} ${
                        error?.issue[index as number]?.expression?.[0] || ''
                    } (${errorCode}).`,
            }),
        );
    }
}
Example #17
Source File: groups.ts    From abrechnung with GNU Affero General Public License v3.0 6 votes vote down vote up
groupLog = atomFamily<Array<GroupLog>, number>({
    key: "groupLog",
    effects_UNSTABLE: (groupID) => [
        ({ setSelf }) => {
            setSelf(
                fetchLog({ groupID: groupID }).catch((err) => toast.error(`error when fetching group log: ${err}`))
            );

            ws.subscribe("group_log", groupID, (subscription_type, { log_id, element_id }) => {
                if (element_id === groupID) {
                    fetchLog({ groupID: element_id }).then((result) => setSelf(result));
                }
            });
            // TODO: handle registration errors

            return () => {
                ws.unsubscribe("group_log", groupID);
            };
        },
    ],
})
Example #18
Source File: experimentsLogic.tsx    From posthog-foss with MIT License 6 votes vote down vote up
experimentsLogic = kea<experimentsLogicType>({
    path: ['scenes', 'experiments', 'experimentsLogic'],
    connect: { values: [teamLogic, ['currentTeamId']] },
    actions: {},
    loaders: ({ values }) => ({
        experiments: [
            [] as Experiment[],
            {
                loadExperiments: async () => {
                    const response = await api.get(`api/projects/${values.currentTeamId}/experiments`)
                    return response.results as Experiment[]
                },
                deleteExperiment: async (id: number) => {
                    await api.delete(`api/projects/${values.currentTeamId}/experiments/${id}`)
                    toast(
                        <div>
                            <h1 className="text-success">
                                <CheckCircleOutlined /> Experiment removed
                            </h1>
                        </div>
                    )
                    return values.experiments.filter((experiment) => experiment.id !== id)
                },
            },
        ],
    }),
    events: ({ actions }) => ({
        afterMount: () => {
            actions.loadExperiments()
        },
    }),
})
Example #19
Source File: GroupDeleteModal.tsx    From abrechnung with GNU Affero General Public License v3.0 6 votes vote down vote up
export default function GroupDeleteModal({ show, onClose, groupToDelete }) {
    const confirmDeleteGroup = () => {
        deleteGroup({ groupID: groupToDelete.id })
            .then((res) => {
                onClose();
            })
            .catch((err) => {
                toast.error(err);
            });
    };

    return (
        <Dialog open={show} onClose={onClose}>
            <DialogTitle>Delete Group</DialogTitle>
            <DialogContent>
                <DialogContentText>
                    {groupToDelete ? <span>Are you sure you want to delete group {groupToDelete.name}</span> : null}
                </DialogContentText>
            </DialogContent>
            <DialogActions>
                <Button color="primary" onClick={onClose}>
                    No
                </Button>
                <Button color="error" onClick={confirmDeleteGroup}>
                    Yes pls
                </Button>
            </DialogActions>
        </Dialog>
    );
}
Example #20
Source File: Toast.tsx    From game-store-monorepo-app with MIT License 5 votes vote down vote up
toastWarn = (params: ToastParams) => {
  toast.warn(params.content, {
    ...defaultToastOptions,
    ...params.options,
  });
}
Example #21
Source File: Blurb.tsx    From mail-my-ballot with Apache License 2.0 5 votes vote down vote up
Blurb: React.FC<{}> = () => {
  const { path, pushAddress } = useAppHistory()
  const { address } = AddressContainer.useContainer()
  const zipRef = React.useRef<HTMLInputElement>(null)
  const { fetchingData, setFetchingData } = FetchingDataContainer.useContainer()

  // mobile browsers don't support 100vh, so use this trick instead
  // https://chanind.github.io/javascript/2019/09/28/avoid-100vh-on-mobile-web.html
  // Also, need to use a state variable instead of a simpler ts variable
  // https://stackoverflow.com/a/56156394/8930600
  const [height, setHeight] = React.useState('100vh')
  React.useEffect(() => {
    setHeight(`${window.innerHeight}px`)
  }, [])

  const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
    event.persist()  // allow async function call
    event.preventDefault()
    const zip = zipRef?.current?.value
    if (!zip) return
    setFetchingData(true)
    const resp = await client.fetchState(zip)
    if (resp.type === 'error') {
      toast.error('Error finding the ZIP code')
    } else {
      pushAddress(resp.data, zip)
    }
    setFetchingData(false)
  }

  const defaultValue = () => {
    if (path?.type === 'address' && path.zip) {
      return path.zip
    } else {
      return address?.postcode ?? undefined
    }
  }

  return <Background style={{height}}>
    <StyleContainer>
      <FlexBox style={{height}}>
        <Title>Vote by Mail</Title>
        <Text>
          Voting by mail is a secure, time-tested, and easy way to vote.  Your ballot arrives safely in the mail weeks before the election and can be filled out and returned at your convenience.
        </Text>
        <Text>Sign up today in <b>2 minutes</b> before your state deadline expires.
        </Text>
        <AppForm onSubmit={handleSubmit}>
          <Text><b>Enter your ZIP code</b> to get started</Text>
          <FlexContainer>
            {/* id is used by WarningMsg to fill out zipcode */}
            <ZipInput
              id='start-zip'
              data-testid='start-zip'
              type='text'
              pattern='[0-9]{5}'
              placeholder='ZIP code'
              defaultValue={defaultValue()}
              ref={zipRef} />
            <SubmitButton
              id='start-submit'
              data-testid='start-submit'
              variant='raised'
              disabled={fetchingData}
            >
              Start
            </SubmitButton>
          </FlexContainer>
        </AppForm>
      </FlexBox>
    </StyleContainer>
  </Background>
}
Example #22
Source File: skill-details.tsx    From liferay-grow with MIT License 5 votes vote down vote up
ProfileSkillDetails = () => {
  const i18n = useLang();

  const [onUpdateGrowMapSkills] = useMutation(UpdateGrowMapSkillDetails);

  const onSave = async (selectedSkills: SelectedSkills[], refetch) => {
    const knowledgeSkillDetails = selectedSkills.map(
      ({ isMentor, knowledgeMatrizId, knowledgeSkillId }) => ({
        isMentor,
        knowledgeMatrizId,
        knowledgeSkillId,
      }),
    );

    try {
      await onUpdateGrowMapSkills({
        variables: {
          data: {
            knowledgeSkillDetails,
          },
        },
      });

      await refetch();
      toast.info(i18n.get('your-request-completed-successfully'));
    } catch (error) {
      toast.error(i18n.get('an-unexpected-error-occurred'));
    }
  };

  return (
    <WrappedSafeComponent<RequestProps> query={getMe}>
      {({ data: { me }, refetch }) => {
        const knowledgeSkillDetails = me.growMap?.knowledgeSkillDetails || [];

        const selectedSkills: SelectedSkills[] = knowledgeSkillDetails.map(
          ({ isMentor = false, knowledgeMatriz, knowledgeSkill }) => ({
            isMentor,
            knowledgeMatrizId: knowledgeMatriz.id,
            knowledgeSkillId: knowledgeSkill.id,
          }),
        );

        return (
          <UserSkillTemplate title={i18n.get('skills-details')} me={me}>
            <SkillContextProvider defaultState={{ selectedSkills }}>
              <SkillDetails onSave={(skills) => onSave(skills, refetch)} />
            </SkillContextProvider>
          </UserSkillTemplate>
        );
      }}
    </WrappedSafeComponent>
  );
}
Example #23
Source File: useFileHandler.tsx    From foodie with MIT License 5 votes vote down vote up
useFileHandler = <T extends unknown>(type = "multiple", initState: T): IFileHandler<T> => {
    const [imageFile, setImageFile] = useState<T>(initState);
    const [isFileLoading, setFileLoading] = useState(false);

    const removeImage = (id: string) => {
        if (!Array.isArray(imageFile)) return;

        const items = imageFile.filter(item => item.id !== id);

        setImageFile(items as T);
    };

    const clearFiles = () => {
        setImageFile(initState as T);
    }

    const onFileChange = (event: React.ChangeEvent<HTMLInputElement>, callback?: (file?: IImage) => void) => {
        if (!event.target.files) return;
        if ((event.target.files.length + (imageFile as IImage[]).length) > 5) {
            return toast.error('Maximum of 5 photos per post allowed.', { hideProgressBar: true });
        }

        // TODO ===  FILTER OUT DUPLICATE IMAGES

        const val = event.target.value;
        const img = event.target.files[0] as File;

        if (!img) return;

        const size = img.size / 1024 / 1024;
        const regex = /(\.jpg|\.jpeg|\.png)$/i;

        setFileLoading(true);
        if (!regex.exec(val)) {
            toast.error('File type must be JPEG or PNG', { hideProgressBar: true });
            setFileLoading(false);
        } else if (size > 2) {
            toast.error('File size exceeded 2mb', { hideProgressBar: true });
            setFileLoading(false);
        } else if (type === 'single') {
            const file = event.target.files[0] as File;
            const url = URL.createObjectURL(file);
            setImageFile({
                file,
                url,
                id: file.name
            } as T);
            if (callback) callback(imageFile as IImage);
        } else {
            Array.from(event.target.files).forEach((file) => {
                const url = URL.createObjectURL(file);
                setImageFile((oldFiles) => ([...oldFiles as any, {
                    file,
                    url,
                    id: file.name
                }] as T));
            });
            if (callback) callback(imageFile as IImage);
            setFileLoading(false);
        }
    };

    return {
        imageFile,
        setImageFile,
        isFileLoading,
        onFileChange,
        removeImage,
        clearFiles
    };
}
Example #24
Source File: index.tsx    From polkabtc-ui with Apache License 2.0 5 votes vote down vote up
Layout = ({ children }: Props): JSX.Element => {
  const address = useSelector((state: StoreType) => state.general.address);
  const location = useLocation();
  const [ref, { height: footerHeight }] = useMeasure<HTMLDivElement>();

  const handleRequestDotFromFaucet = async (): Promise<void> => {
    // TODO: should show a descriptive warning
    if (!address) return;

    try {
      const receiverId = window.polkaBTC.api.createType(ACCOUNT_ID_TYPE_NAME, address);
      await window.faucet.fundAccount(receiverId);
      toast.success('Your account has been funded.');
    } catch (error) {
      toast.error(`Funding failed. ${error.message}`);
    }
  };

  /**
   * TODO: a hack for now.
   * - Should apply the gradient on the landing page
   */
  const isHomePage = location.pathname === PAGES.home;

  return (
    <div
      style={{
        //  TODO: should avoid hard-coding colors (https://tailwindcss.com/docs/gradient-color-stops)
        backgroundImage:
          isHomePage ?
            // eslint-disable-next-line max-len
            'linear-gradient(to right bottom, #e1106d, #e52766, #e83761, #ea445b, #eb5157, #ed5952, #ef624e, #f06a4a, #f37143, #f4783c, #f58035, #f5882d)' :
            'unset'
      }}
      className={clsx(
        'relative',
        'min-h-screen'
      )}>
      <main
        style={{ paddingBottom: footerHeight }}
        className={clsx(
          'flex',
          'flex-col'
        )}>
        {!checkStaticPage() && (
          <Topbar
            address={address}
            requestDOT={handleRequestDotFromFaucet} />
        )}
        {!isHomePage && <TestnetBanner />}
        {!isHomePage && <MaintenanceBanner />}
        {children}
      </main>
      <Footer
        ref={ref}
        className={clsx(
          'absolute',
          'bottom-0',
          'w-full',
          'shadow',
          'border-t'
        )} />
    </div>
  );
}
Example #25
Source File: message-container.component.tsx    From hive-keychain-extension with MIT License 5 votes vote down vote up
MessageContainer = ({ errorMessage, resetMessage }: PropsFromRedux) => {
  const [timeoutId, setTimeoutId] = useState<any>();
  useEffect(() => {
    if (errorMessage.key) {
      switch (errorMessage.type) {
        case MessageType.ERROR:
          toast.error(
            chrome.i18n.getMessage(errorMessage.key, errorMessage.params),
          );
          break;
        case MessageType.SUCCESS:
          toast.success(
            chrome.i18n.getMessage(errorMessage.key, errorMessage.params),
          );
          break;
        case MessageType.WARNING:
          toast.warning(
            chrome.i18n.getMessage(errorMessage.key, errorMessage.params),
          );
          break;
        case MessageType.INFO:
          toast.info(
            chrome.i18n.getMessage(errorMessage.key, errorMessage.params),
          );
          break;
      }

      const id = setTimeout(() => {
        close();
      }, DURATION);
      setTimeoutId(id);
    }
  }, [errorMessage]);

  const close = () => {
    resetMessage();
    clearTimeout(timeoutId);
  };

  return (
    <ToastContainer
      position="bottom-center"
      autoClose={DURATION}
      pauseOnHover
      theme="dark"
      onClick={() => close()}
      closeOnClick={true}
      draggable={false}
      bodyStyle={{ fontSize: '16px', fontFamily: 'Futura', fontWeight: '400' }}
    />
  );
}
Example #26
Source File: LinkCreator.tsx    From tsplay.dev with MIT License 5 votes vote down vote up
useLinkInput = ({ setShortened, setShortenedCreated, showToast, setLinks }: Props) => {
  const [inputValue, setInputValue] = React.useState('')
  const [loading, setLoading] = React.useState(false)
  const [customLink, setCustomLink] = React.useState('')

  const createLink = async () => {
    if (!inputValue) return
    if (!isTSLink(inputValue)) {
      toast(
        <div>
          <span role="img" aria-label="warning" className="prevent-hue-rotate">
            ⚠️{' '}
          </span>
          Not a TypeScript Playground URL
        </div>
      )
      return
    }
    if (customLink) {
      const [isValid, msg] = validateCustomLink(customLink)
      if (!isValid) {
        toast(msg)
        return
      }
    }
    try {
      setLoading(true)
      const body: CreatePayload = {
        url: inputValue,
        createdOn: 'client',
        expires: false,
        ...(customLink && { short: customLink }),
      }
      const { shortened } = await api<CreateResponse>('short', { body })
      setShortenedCreated(shortened)
      handleLinksList(shortened, setLinks)
      setCustomLink('')
      toast(
        <div>
          <span role="img" aria-label="warning" className="prevent-hue-rotate">
            ?{' '}
          </span>
          Short link created successfully!
        </div>
      )
      copyToClipboard(shortened.replace(/^https?:\/\//, ''), shortened, showToast)
      setInputValue('')
      setShortened(prev => (prev ? prev + 1 : 1))
    } catch (e) {
      // eslint-disable-next-line no-console
      console.log('Error trying to shorten URL', e)
      toast(
        <div>
          <span role="img" aria-label="warning" className="prevent-hue-rotate">
            ?️{' '}
          </span>
          Opps, something went wrong.
        </div>
      )
    } finally {
      setLoading(false)
    }
  }

  return { inputValue, loading, setInputValue, createLink, customLink, setCustomLink }
}
Example #27
Source File: index.tsx    From yasd with MIT License 5 votes vote down vote up
Page: React.FC = () => {
  const { t } = useTranslation()
  const { data: modules, error: modulesError } = useSWR<Modules>(
    '/modules',
    fetcher,
  )
  const [isLoading, setIsLoading] = useState(false)

  const isChecked = (name: string): boolean => {
    return modules?.enabled.includes(name) === true
  }

  const toggle = useCallback(
    (name: string, newVal: boolean) => {
      setIsLoading(true)

      fetcher({
        url: '/modules',
        method: 'POST',
        data: {
          [name]: newVal,
        },
      })
        .then(() => {
          toast.success(t('common.success_interaction'))
          return mutate('/modules')
        })
        .catch((err) => {
          toast.success(t('common.failed_interaction'))
          console.error(err)
        })
        .finally(() => {
          setIsLoading(false)
        })
    },
    [setIsLoading, t],
  )

  return (
    <PageContainer>
      <PageTitle title={t('home.modules')} />

      <div tw="divide-y divide-gray-200">
        {modules &&
          modules.available.map((mod) => {
            return (
              <div key={mod} tw="flex items-center justify-between p-3">
                <div tw="truncate leading-normal text-gray-700">{mod}</div>
                <div tw="flex items-center">
                  <Toggle
                    noMargin
                    label=""
                    labelChecked="on"
                    labelUnchecked="off"
                    disabled={isLoading}
                    checked={isChecked(mod)}
                    onChange={() => toggle(mod, !isChecked(mod))}
                  />
                </div>
              </div>
            )
          })}
      </div>
    </PageContainer>
  )
}
Example #28
Source File: DeleteButton.tsx    From frontend with Apache License 2.0 5 votes vote down vote up
DeleteButton: FunctionComponent = () => {
  const { t } = useTranslation()
  // Using state to prevent user repeatedly initating fetches
  const [clicked, setClicked] = useState(false)
  const [waiting, setWaiting] = useState(false)
  const [token, setToken] = useState('')
  const dispatch = useUserDispatch()

  // Only make a request on first click
  useEffect(() => {
    if (clicked) {
      requestDeletion(
        setWaiting,
        msg_id => {
          toast.error(t(msg_id));
          setClicked(false);
        },
        setToken
      )
    }
  }, [dispatch, clicked, t])

  if (waiting) {
    return <Spinner size={30} />
  }

  if (token) {
    // Callbacks must clear the token to hide the dialog
    return <ConfirmDialog
      prompt='Delete your account?'
      entry='I wish to delete my account'
      action={t('delete-account')}
      onConfirmed={() => {
        setWaiting(true)

        deleteAccount(dispatch, token)
          .catch(err => {
            toast.error(t(err))
            setClicked(false)
          })
          .finally(() => {
            setWaiting(false)
          })

        setToken('')
      }}
      onCancelled={() => {
        // Hide dialog and allow reuse of button
        setToken('')
        setClicked(false)
      }}
    />
  }

  return (
    <Button onClick={() => setClicked(true)} type='secondary'>
      {t('delete-account')}
    </Button>
  )
}
Example #29
Source File: index.tsx    From houston with MIT License 5 votes vote down vote up
static info(content: React.ReactNode, options?: IToastOptions): void {
    const theme = getCurrentTheme();
    toast.info(content, {
      ...options,
      style: { ...(theme ? { background: theme.feedbackColor.informative.pure } : {}) }
    });
  }