GettingStarted.tsx 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. // Libraries
  2. import { css, cx } from '@emotion/css';
  3. import React, { PureComponent } from 'react';
  4. import { PanelProps } from '@grafana/data';
  5. import { config } from '@grafana/runtime';
  6. import { Button, Spinner, stylesFactory } from '@grafana/ui';
  7. import { contextSrv } from 'app/core/core';
  8. import { backendSrv } from 'app/core/services/backend_srv';
  9. import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
  10. import { Step } from './components/Step';
  11. import { getSteps } from './steps';
  12. import { Card, SetupStep } from './types';
  13. interface State {
  14. checksDone: boolean;
  15. currentStep: number;
  16. steps: SetupStep[];
  17. }
  18. export class GettingStarted extends PureComponent<PanelProps, State> {
  19. state = {
  20. checksDone: false,
  21. currentStep: 0,
  22. steps: getSteps(),
  23. };
  24. async componentDidMount() {
  25. const { steps } = this.state;
  26. const checkedStepsPromises: Array<Promise<SetupStep>> = steps.map(async (step: SetupStep) => {
  27. const checkedCardsPromises: Array<Promise<Card>> = step.cards.map((card: Card) => {
  28. return card.check().then((passed) => {
  29. return { ...card, done: passed };
  30. });
  31. });
  32. const checkedCards = await Promise.all(checkedCardsPromises);
  33. return {
  34. ...step,
  35. done: checkedCards.every((c) => c.done),
  36. cards: checkedCards,
  37. };
  38. });
  39. const checkedSteps = await Promise.all(checkedStepsPromises);
  40. this.setState({
  41. currentStep: !checkedSteps[0].done ? 0 : 1,
  42. steps: checkedSteps,
  43. checksDone: true,
  44. });
  45. }
  46. onForwardClick = () => {
  47. this.setState((prevState) => ({
  48. currentStep: prevState.currentStep + 1,
  49. }));
  50. };
  51. onPreviousClick = () => {
  52. this.setState((prevState) => ({
  53. currentStep: prevState.currentStep - 1,
  54. }));
  55. };
  56. dismiss = () => {
  57. const { id } = this.props;
  58. const dashboard = getDashboardSrv().getCurrent();
  59. const panel = dashboard?.getPanelById(id);
  60. dashboard?.removePanel(panel!);
  61. backendSrv
  62. .request({
  63. method: 'PUT',
  64. url: '/api/user/helpflags/1',
  65. showSuccessAlert: false,
  66. })
  67. .then((res: any) => {
  68. contextSrv.user.helpFlags1 = res.helpFlags1;
  69. });
  70. };
  71. render() {
  72. const { checksDone, currentStep, steps } = this.state;
  73. const styles = getStyles();
  74. const step = steps[currentStep];
  75. return (
  76. <div className={styles.container}>
  77. {!checksDone ? (
  78. <div className={styles.loading}>
  79. <div className={styles.loadingText}>Checking completed setup steps</div>
  80. <Spinner size={24} inline />
  81. </div>
  82. ) : (
  83. <>
  84. <div className={styles.dismiss}>
  85. <div onClick={this.dismiss}>Remove this panel</div>
  86. </div>
  87. {currentStep === steps.length - 1 && (
  88. <div className={cx(styles.backForwardButtons, styles.previous)} onClick={this.onPreviousClick}>
  89. <Button aria-label="To advanced tutorials" icon="angle-left" variant="secondary" />
  90. </div>
  91. )}
  92. <div className={styles.content}>
  93. <Step step={step} />
  94. </div>
  95. {currentStep < steps.length - 1 && (
  96. <div className={cx(styles.backForwardButtons, styles.forward)} onClick={this.onForwardClick}>
  97. <Button aria-label="To basic tutorials" icon="angle-right" variant="secondary" />
  98. </div>
  99. )}
  100. </>
  101. )}
  102. </div>
  103. );
  104. }
  105. }
  106. const getStyles = stylesFactory(() => {
  107. const { theme } = config;
  108. return {
  109. container: css`
  110. display: flex;
  111. flex-direction: column;
  112. height: 100%;
  113. // background: url(public/img/getting_started_bg_${theme.type}.svg) no-repeat;
  114. background-size: cover;
  115. padding: ${theme.spacing.xl} ${theme.spacing.md} 0;
  116. `,
  117. content: css`
  118. label: content;
  119. display: flex;
  120. justify-content: center;
  121. @media only screen and (max-width: ${theme.breakpoints.xxl}) {
  122. margin-left: ${theme.spacing.lg};
  123. justify-content: flex-start;
  124. }
  125. `,
  126. header: css`
  127. label: header;
  128. margin-bottom: ${theme.spacing.lg};
  129. display: flex;
  130. flex-direction: column;
  131. @media only screen and (min-width: ${theme.breakpoints.lg}) {
  132. flex-direction: row;
  133. }
  134. `,
  135. headerLogo: css`
  136. height: 58px;
  137. padding-right: ${theme.spacing.md};
  138. display: none;
  139. @media only screen and (min-width: ${theme.breakpoints.md}) {
  140. display: block;
  141. }
  142. `,
  143. heading: css`
  144. label: heading;
  145. margin-right: ${theme.spacing.lg};
  146. margin-bottom: ${theme.spacing.lg};
  147. flex-grow: 1;
  148. display: flex;
  149. @media only screen and (min-width: ${theme.breakpoints.md}) {
  150. margin-bottom: 0;
  151. }
  152. `,
  153. backForwardButtons: css`
  154. position: absolute;
  155. bottom: 50%;
  156. top: 50%;
  157. height: 50px;
  158. `,
  159. previous: css`
  160. left: 10px;
  161. @media only screen and (max-width: ${theme.breakpoints.md}) {
  162. left: 0;
  163. }
  164. `,
  165. forward: css`
  166. right: 10px;
  167. @media only screen and (max-width: ${theme.breakpoints.md}) {
  168. right: 0;
  169. }
  170. `,
  171. dismiss: css`
  172. display: flex;
  173. justify-content: flex-end;
  174. cursor: pointer;
  175. text-decoration: underline;
  176. margin-right: ${theme.spacing.md};
  177. margin-bottom: ${theme.spacing.sm};
  178. `,
  179. loading: css`
  180. display: flex;
  181. justify-content: center;
  182. align-items: center;
  183. height: 100%;
  184. `,
  185. loadingText: css`
  186. margin-right: ${theme.spacing.sm};
  187. `,
  188. };
  189. });