project-list-root.tsx 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. import {
  2. ProjectListProvider,
  3. useProjectListContext,
  4. } from '../context/project-list-context'
  5. import { ColorPickerProvider } from '../context/color-picker-context'
  6. import * as eventTracking from '../../../infrastructure/event-tracking'
  7. import { Col, Row } from 'react-bootstrap'
  8. import { useTranslation } from 'react-i18next'
  9. import useWaitForI18n from '../../../shared/hooks/use-wait-for-i18n'
  10. import CurrentPlanWidget from './current-plan-widget/current-plan-widget'
  11. import NewProjectButton from './new-project-button'
  12. import ProjectListTable from './table/project-list-table'
  13. import SurveyWidget from './survey-widget'
  14. import WelcomeMessage from './welcome-message'
  15. import LoadingBranded from '../../../shared/components/loading-branded'
  16. import SystemMessages from './notifications/system-messages'
  17. import UserNotifications from './notifications/user-notifications'
  18. import SearchForm from './search-form'
  19. import ProjectsDropdown from './dropdown/projects-dropdown'
  20. import SortByDropdown from './dropdown/sort-by-dropdown'
  21. import ProjectTools from './table/project-tools/project-tools'
  22. import ProjectListTitle from './title/project-list-title'
  23. import Sidebar from './sidebar/sidebar'
  24. import LoadMore from './load-more'
  25. import { useEffect } from 'react'
  26. import getMeta from '../../../utils/meta'
  27. import WelcomeMessageNew from './welcome-message-new'
  28. import withErrorBoundary from '../../../infrastructure/error-boundary'
  29. import { GenericErrorBoundaryFallback } from '../../../shared/components/generic-error-boundary-fallback'
  30. function ProjectListRoot() {
  31. const { isReady } = useWaitForI18n()
  32. return isReady ? (
  33. <ProjectListProvider>
  34. <ColorPickerProvider>
  35. <ProjectListPageContent />
  36. </ColorPickerProvider>
  37. </ProjectListProvider>
  38. ) : null
  39. }
  40. function ProjectListPageContent() {
  41. const {
  42. totalProjectsCount,
  43. error,
  44. isLoading,
  45. loadProgress,
  46. searchText,
  47. setSearchText,
  48. selectedProjects,
  49. filter,
  50. tags,
  51. selectedTagId,
  52. } = useProjectListContext()
  53. const selectedTag = tags.find(tag => tag._id === selectedTagId)
  54. const welcomePageRedesignVariant = getMeta(
  55. 'ol-welcomePageRedesignVariant'
  56. ) as 'enabled' | 'default'
  57. useEffect(() => {
  58. eventTracking.sendMB('loads_v2_dash', {})
  59. }, [])
  60. return isLoading ? (
  61. <div className="loading-container">
  62. <LoadingBranded loadProgress={loadProgress} />
  63. </div>
  64. ) : (
  65. <>
  66. <SystemMessages />
  67. <div className="project-list-wrapper clearfix">
  68. {totalProjectsCount > 0 ? (
  69. <>
  70. <Sidebar />
  71. <div className="project-list-main-react">
  72. {error ? <DashApiError /> : ''}
  73. <Row>
  74. <Col xs={12}>
  75. <UserNotifications />
  76. </Col>
  77. </Row>
  78. <div className="project-list-header-row">
  79. <ProjectListTitle
  80. filter={filter}
  81. selectedTag={selectedTag}
  82. className="hidden-xs text-truncate"
  83. />
  84. <div className="project-tools">
  85. <div className="hidden-xs">
  86. {selectedProjects.length === 0 ? (
  87. <CurrentPlanWidget />
  88. ) : (
  89. <ProjectTools />
  90. )}
  91. </div>
  92. <div className="visible-xs">
  93. <CurrentPlanWidget />
  94. </div>
  95. </div>
  96. </div>
  97. <Row className="hidden-xs">
  98. <Col md={7}>
  99. <SearchForm
  100. inputValue={searchText}
  101. setInputValue={setSearchText}
  102. filter={filter}
  103. selectedTag={selectedTag}
  104. />
  105. </Col>
  106. </Row>
  107. <div className="project-list-sidebar-survey-wrapper visible-xs">
  108. <SurveyWidget />
  109. </div>
  110. <div className="visible-xs mt-1">
  111. <div role="toolbar" className="projects-toolbar">
  112. <ProjectsDropdown />
  113. <SortByDropdown />
  114. </div>
  115. </div>
  116. <Row className="row-spaced">
  117. <Col xs={12}>
  118. <div className="card project-list-card">
  119. <div className="visible-xs pt-2 pb-3">
  120. <div className="clearfix">
  121. <NewProjectButton
  122. id="new-project-button-projects-table"
  123. className="pull-left me-2"
  124. showAddAffiliationWidget
  125. />
  126. <SearchForm
  127. inputValue={searchText}
  128. setInputValue={setSearchText}
  129. filter={filter}
  130. selectedTag={selectedTag}
  131. className="overflow-hidden"
  132. formGroupProps={{ className: 'mb-0' }}
  133. />
  134. </div>
  135. </div>
  136. <ProjectListTable />
  137. </div>
  138. </Col>
  139. </Row>
  140. <Row className="row-spaced">
  141. <Col xs={12}>
  142. <LoadMore />
  143. </Col>
  144. </Row>
  145. </div>
  146. </>
  147. ) : (
  148. <div className="project-list-welcome-wrapper">
  149. {error ? <DashApiError /> : ''}
  150. <Row className="row-spaced">
  151. <Col
  152. sm={10}
  153. smOffset={1}
  154. md={8}
  155. mdOffset={2}
  156. className="project-list-empty-col"
  157. >
  158. <Row>
  159. <Col xs={12}>
  160. <UserNotifications />
  161. </Col>
  162. </Row>
  163. {welcomePageRedesignVariant === 'enabled' ? (
  164. <WelcomeMessageNew />
  165. ) : (
  166. <WelcomeMessage />
  167. )}
  168. </Col>
  169. </Row>
  170. </div>
  171. )}
  172. </div>
  173. </>
  174. )
  175. }
  176. function DashApiError() {
  177. const { t } = useTranslation()
  178. return (
  179. <Row className="row-spaced">
  180. <Col xs={8} xsOffset={2} aria-live="polite" className="text-center">
  181. <div className="alert alert-danger">
  182. {t('generic_something_went_wrong')}
  183. </div>
  184. </Col>
  185. </Row>
  186. )
  187. }
  188. export default withErrorBoundary(ProjectListRoot, GenericErrorBoundaryFallback)