ProjectSection.tsx 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. import React, { Component } from 'react';
  2. import styled from 'styled-components';
  3. import gradient from 'assets/gradient.jpg';
  4. import { Context } from 'shared/Context';
  5. import { ProjectType, InfraType } from 'shared/types';
  6. import { RouteComponentProps, withRouter } from 'react-router';
  7. type PropsType = RouteComponentProps & {
  8. currentProject: ProjectType,
  9. projects: ProjectType[],
  10. };
  11. type StateType = {
  12. expanded: boolean
  13. };
  14. class ProjectSection extends Component<PropsType, StateType> {
  15. state = {
  16. expanded: false,
  17. };
  18. renderOptionList = () => {
  19. let { setCurrentProject } = this.context;
  20. return this.props.projects.map((project: ProjectType, i: number) => {
  21. return (
  22. <Option
  23. key={i}
  24. selected={project.name === this.props.currentProject.name}
  25. onClick={() => setCurrentProject(project)}
  26. >
  27. <ProjectIcon>
  28. <ProjectImage src={gradient} />
  29. <Letter>{project.name[0].toUpperCase()}</Letter>
  30. </ProjectIcon>
  31. <ProjectLabel>{project.name}</ProjectLabel>
  32. </Option>
  33. );
  34. });
  35. }
  36. renderDropdown = () => {
  37. if (this.state.expanded) {
  38. return (
  39. <div>
  40. <CloseOverlay onClick={() => this.setState({ expanded: false })} />
  41. <Dropdown>
  42. {this.renderOptionList()}
  43. <Option
  44. selected={false}
  45. lastItem={true}
  46. onClick={() => this.props.history.push('new-project')}
  47. >
  48. <ProjectIconAlt>+</ProjectIconAlt>
  49. <ProjectLabel>Create a Project</ProjectLabel>
  50. </Option>
  51. </Dropdown>
  52. </div>
  53. );
  54. }
  55. }
  56. handleExpand = () => {
  57. this.setState({ expanded: !this.state.expanded });
  58. }
  59. render() {
  60. let { currentProject } = this.props;
  61. if (currentProject) {
  62. return (
  63. <StyledProjectSection>
  64. <MainSelector
  65. onClick={this.handleExpand}
  66. expanded={this.state.expanded}
  67. >
  68. <ProjectIcon>
  69. <ProjectImage src={gradient} />
  70. <Letter>{currentProject.name[0].toUpperCase()}</Letter>
  71. </ProjectIcon>
  72. <ProjectName>{currentProject.name}</ProjectName>
  73. <i className="material-icons">arrow_drop_down</i>
  74. </MainSelector>
  75. {this.renderDropdown()}
  76. </StyledProjectSection>
  77. );
  78. }
  79. return (
  80. <InitializeButton onClick={() => this.props.history.push('new-project')}>
  81. <Plus>+</Plus> Create a Project
  82. </InitializeButton>
  83. );
  84. }
  85. }
  86. ProjectSection.contextType = Context;
  87. export default withRouter(ProjectSection);
  88. const ProjectLabel = styled.div`
  89. overflow: hidden;
  90. white-space: nowrap;
  91. text-overflow: ellipsis;
  92. `;
  93. const AddButton = styled.div`
  94. display: flex;
  95. align-items: center;
  96. font-size: 13px;
  97. padding: 12px 15px;
  98. `;
  99. const Plus = styled.div`
  100. margin-right: 10px;
  101. font-size: 15px;
  102. `;
  103. const InitializeButton = styled.div`
  104. position: relative;
  105. display: flex;
  106. align-items: center;
  107. justify-content: center;
  108. width: calc(100% - 30px);
  109. height: 38px;
  110. margin: 8px 15px;
  111. font-size: 13px;
  112. font-weight: 500;
  113. border-radius: 3px;
  114. color: #ffffff;
  115. padding-bottom: 1px;
  116. cursor: pointer;
  117. background: #ffffff11;
  118. :hover {
  119. background: #ffffff22;
  120. }
  121. `;
  122. const Option = styled.div`
  123. width: 100%;
  124. border-top: 1px solid #00000000;
  125. border-bottom: 1px solid ${(props: { selected: boolean, lastItem?: boolean }) => props.lastItem ? '#ffffff00' : '#ffffff15'};
  126. height: 45px;
  127. display: flex;
  128. align-items: center;
  129. font-size: 13px;
  130. align-items: center;
  131. padding-left: 10px;
  132. cursor: pointer;
  133. padding-right: 10px;
  134. background: ${(props: { selected: boolean, lastItem?: boolean }) => props.selected ? '#ffffff11' : ''};
  135. :hover {
  136. background: ${(props: { selected: boolean, lastItem?: boolean }) => props.selected ? '' : '#ffffff22'};
  137. }
  138. > i {
  139. font-size: 18px;
  140. margin-right: 12px;
  141. margin-left: 5px;
  142. color: #ffffff44;
  143. }
  144. `;
  145. const CloseOverlay = styled.div`
  146. position: fixed;
  147. top: 0;
  148. left: 0;
  149. width: 100%;
  150. height: 100%;
  151. z-index: 999;
  152. `;
  153. const Dropdown = styled.div`
  154. position: absolute;
  155. right: 10px;
  156. top: calc(100% + 5px);
  157. background: #26282f;
  158. width: 180px;
  159. max-height: 500px;
  160. border-radius: 3px;
  161. z-index: 999;
  162. overflow-y: auto;
  163. margin-bottom: 20px;
  164. box-shadow: 0 5px 15px 5px #00000077;
  165. `;
  166. const ProjectName = styled.div`
  167. overflow: hidden;
  168. white-space: nowrap;
  169. text-overflow: ellipsis;
  170. `;
  171. const Letter = styled.div`
  172. height: 100%;
  173. width: 100%;
  174. position: absolute;
  175. background: #00000028;
  176. top: 0;
  177. left: 0;
  178. display: flex;
  179. align-items: center;
  180. justify-content: center;
  181. `;
  182. const ProjectImage = styled.img`
  183. width: 100%;
  184. height: 100%;
  185. `;
  186. const ProjectIcon = styled.div`
  187. width: 25px;
  188. min-width: 25px;
  189. height: 25px;
  190. border-radius: 3px;
  191. overflow: hidden;
  192. position: relative;
  193. margin-right: 10px;
  194. font-weight: 400;
  195. `;
  196. const ProjectIconAlt = styled(ProjectIcon)`
  197. border: 1px solid #ffffff44;
  198. display: flex;
  199. align-items: center;
  200. justify-content: center;
  201. `;
  202. const StyledProjectSection = styled.div`
  203. position: relative;
  204. `;
  205. const MainSelector = styled.div`
  206. display: flex;
  207. align-items: center;
  208. margin: 10px 0 0;
  209. font-size: 14px;
  210. font-family: 'Work Sans', sans-serif;
  211. font-weight: 600;
  212. cursor: pointer;
  213. padding: 10px 0;
  214. padding-left: 20px;
  215. :hover {
  216. > i {
  217. background: #ffffff22;
  218. }
  219. }
  220. > i {
  221. margin-left: 7px;
  222. margin-right: 12px;
  223. font-size: 20px;
  224. display: flex;
  225. align-items: center;
  226. justify-content: center;
  227. border-radius: 20px;
  228. background: ${(props: { expanded: boolean }) => props.expanded ? '#ffffff22' : ''};
  229. }
  230. `;