DashboardActivity.tsx 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /*
  2. Copyright (C) 2017 Cloudbase Solutions SRL
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Affero General Public License as
  5. published by the Free Software Foundation, either version 3 of the
  6. License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Affero General Public License for more details.
  11. You should have received a copy of the GNU Affero General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. */
  14. import * as React from "react";
  15. import { observer } from "mobx-react";
  16. import styled from "styled-components";
  17. import { Link } from "react-router-dom";
  18. import StatusIcon from "@src/components/ui/StatusComponents/StatusIcon";
  19. import StatusImage from "@src/components/ui/StatusComponents/StatusImage";
  20. import Button from "@src/components/ui/Button";
  21. import {
  22. InfoColumn,
  23. MainItemInfo,
  24. ItemReplicaBadge,
  25. ItemTitle,
  26. ItemDescription,
  27. } from "@src/components/ui/Dropdowns/NotificationDropdown";
  28. import type { NotificationItemData } from "@src/@types/NotificationItem";
  29. import { ThemePalette, ThemeProps } from "@src/components/Theme";
  30. import replicaImage from "./images/replica.svg";
  31. const Wrapper = styled.div<any>`
  32. flex-grow: 1;
  33. `;
  34. const Title = styled.div<any>`
  35. font-size: 24px;
  36. font-weight: ${ThemeProps.fontWeights.light};
  37. margin-bottom: 12px;
  38. `;
  39. const Module = styled.div<any>`
  40. background: ${ThemePalette.grayscale[0]};
  41. display: flex;
  42. overflow: hidden;
  43. border-radius: ${ThemeProps.borderRadius};
  44. height: 273px;
  45. `;
  46. const LoadingWrapper = styled.div<any>`
  47. width: 100%;
  48. height: 100%;
  49. display: flex;
  50. justify-content: center;
  51. align-items: center;
  52. overflow: hidden;
  53. `;
  54. const List = styled.div<any>`
  55. width: 100%;
  56. display: flex;
  57. flex-direction: column;
  58. flex-wrap: wrap;
  59. `;
  60. const ListItem = styled(Link)`
  61. padding: 8px 16px 8px 16px;
  62. cursor: pointer;
  63. text-decoration: none;
  64. color: inherit;
  65. display: block;
  66. transition: all ${ThemeProps.animations.swift};
  67. &:hover {
  68. background: ${ThemePalette.grayscale[1]};
  69. }
  70. `;
  71. const NoItems = styled.div<any>`
  72. display: flex;
  73. flex-direction: column;
  74. align-items: center;
  75. width: 100%;
  76. `;
  77. const ReplicaImage = styled.div<any>`
  78. ${ThemeProps.exactSize("148px")}
  79. background: url('${replicaImage}') center no-repeat;
  80. `;
  81. const Message = styled.div<any>`
  82. text-align: center;
  83. margin-bottom: 32px;
  84. `;
  85. type Props = {
  86. notificationItems: NotificationItemData[];
  87. style?: React.CSSProperties | null;
  88. loading?: boolean;
  89. large?: boolean;
  90. onNewClick?: () => void;
  91. };
  92. @observer
  93. class DashboardActivity extends React.Component<Props> {
  94. renderList() {
  95. return (
  96. <List>
  97. {this.props.notificationItems
  98. .filter((_, i) => i < (this.props.large ? 10 : 5))
  99. .map((item, i) => {
  100. const executionsHref =
  101. item.status === "RUNNING"
  102. ? item.type === "replica"
  103. ? "/executions"
  104. : item.type === "migration"
  105. ? "/tasks"
  106. : ""
  107. : "";
  108. return (
  109. <ListItem
  110. key={item.id}
  111. to={`/${item.type}s/${item.id}${executionsHref}`}
  112. style={{
  113. width: `calc(${this.props.large ? 50 : 100}% - 32px)`,
  114. paddingTop: i === 0 || i === 5 ? "16px" : "8px",
  115. }}
  116. >
  117. <InfoColumn>
  118. <MainItemInfo>
  119. <StatusIcon status={item.status} hollow />
  120. <ItemReplicaBadge type={item.type}>
  121. {item.type === "replica" ? "RE" : "MI"}
  122. </ItemReplicaBadge>
  123. <ItemTitle nowrap>{item.name}</ItemTitle>
  124. </MainItemInfo>
  125. <ItemDescription>{item.description}</ItemDescription>
  126. </InfoColumn>
  127. </ListItem>
  128. );
  129. })}
  130. </List>
  131. );
  132. }
  133. renderNoItems() {
  134. return (
  135. <NoItems>
  136. <ReplicaImage />
  137. <Message>
  138. There is no recent activity
  139. <br />
  140. in this project.
  141. </Message>
  142. <Button hollow primary transparent onClick={this.props.onNewClick}>
  143. New Replica / Migration
  144. </Button>
  145. </NoItems>
  146. );
  147. }
  148. renderLoading() {
  149. return (
  150. <LoadingWrapper>
  151. <StatusImage status="RUNNING" />
  152. </LoadingWrapper>
  153. );
  154. }
  155. render() {
  156. return (
  157. <Wrapper style={this.props.style}>
  158. <Title>Recent Activity</Title>
  159. <Module>
  160. {this.props.notificationItems.length === 0 && this.props.loading
  161. ? this.renderLoading()
  162. : this.props.notificationItems.length
  163. ? this.renderList()
  164. : this.renderNoItems()}
  165. </Module>
  166. </Wrapper>
  167. );
  168. }
  169. }
  170. export default DashboardActivity;