PluginCard.tsx 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. import React, { useState } from 'react';
  2. import { useTranslation } from 'next-i18next';
  3. import Link from 'next/link';
  4. import { apiv3Delete, apiv3Put } from '~/client/util/apiv3-client';
  5. import { toastSuccess, toastError } from '~/client/util/toastr';
  6. import styles from './PluginCard.module.scss';
  7. type Props = {
  8. id: string,
  9. name: string,
  10. url: string,
  11. isEnalbed: boolean,
  12. mutate: () => void,
  13. desc?: string,
  14. }
  15. export const PluginCard = (props: Props): JSX.Element => {
  16. const {
  17. id, name, url, isEnalbed, desc, mutate,
  18. } = props;
  19. const { t } = useTranslation('admin');
  20. const PluginCardButton = (): JSX.Element => {
  21. const [isEnabled, setState] = useState<boolean>(isEnalbed);
  22. const onChangeHandler = async() => {
  23. try {
  24. if (isEnabled) {
  25. const reqUrl = `/plugins/${id}/deactivate`;
  26. const res = await apiv3Put(reqUrl);
  27. setState(!isEnabled);
  28. const pluginName = res.data.pluginName;
  29. toastSuccess(t('toaster.deactivate_plugin_success', { pluginName }));
  30. }
  31. else {
  32. const reqUrl = `/plugins/${id}/activate`;
  33. const res = await apiv3Put(reqUrl);
  34. setState(!isEnabled);
  35. const pluginName = res.data.pluginName;
  36. toastSuccess(t('toaster.activate_plugin_success', { pluginName }));
  37. }
  38. }
  39. catch (err) {
  40. toastError(err);
  41. }
  42. };
  43. return (
  44. <div className={`${styles.plugin_card}`}>
  45. <div className="switch">
  46. <label className="switch__label">
  47. <input
  48. type="checkbox"
  49. className="switch__input"
  50. onChange={() => onChangeHandler()}
  51. checked={isEnabled}
  52. />
  53. <span className="switch__content"></span>
  54. <span className="switch__circle"></span>
  55. </label>
  56. </div>
  57. </div>
  58. );
  59. };
  60. const PluginDeleteButton = (): JSX.Element => {
  61. const onClickPluginDeleteBtnHandler = async() => {
  62. const reqUrl = `/plugins/${id}/remove`;
  63. try {
  64. const res = await apiv3Delete(reqUrl);
  65. const pluginName = res.data.pluginName;
  66. toastSuccess(t('toaster.remove_plugin_success', { pluginName }));
  67. }
  68. catch (err) {
  69. toastError(err);
  70. }
  71. finally {
  72. mutate();
  73. }
  74. };
  75. return (
  76. <div className="">
  77. <button
  78. type="submit"
  79. className="btn btn-primary"
  80. onClick={() => onClickPluginDeleteBtnHandler()}
  81. >
  82. Delete
  83. </button>
  84. </div>
  85. );
  86. };
  87. return (
  88. <div className="card shadow border-0" key={name}>
  89. <div className="card-body px-5 py-4 mt-3">
  90. <div className="row mb-3">
  91. <div className="col-9">
  92. <h2 className="card-title h3 border-bottom pb-2 mb-3">
  93. <Link href={`${url}`}>{name}</Link>
  94. </h2>
  95. <p className="card-text text-muted">{desc}</p>
  96. </div>
  97. <div className='col-3'>
  98. <div>
  99. <PluginCardButton />
  100. </div>
  101. <div className="mt-4">
  102. <PluginDeleteButton />
  103. </div>
  104. </div>
  105. </div>
  106. </div>
  107. <div className="card-footer px-5 border-top-0 mp-bg-light-blue">
  108. <p className="d-flex justify-content-between align-self-center mb-0">
  109. </p>
  110. </div>
  111. </div>
  112. );
  113. };