project-list-root.tsx 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  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 Sidebar from './sidebar/sidebar'
  23. import LoadMore from './load-more'
  24. import { useEffect } from 'react'
  25. function ProjectListRoot() {
  26. const { isReady } = useWaitForI18n()
  27. return isReady ? (
  28. <ProjectListProvider>
  29. <ColorPickerProvider>
  30. <ProjectListPageContent />
  31. </ColorPickerProvider>
  32. </ProjectListProvider>
  33. ) : null
  34. }
  35. function ProjectListPageContent() {
  36. const {
  37. totalProjectsCount,
  38. error,
  39. isLoading,
  40. loadProgress,
  41. searchText,
  42. setSearchText,
  43. selectedProjects,
  44. } = useProjectListContext()
  45. useEffect(() => {
  46. eventTracking.sendMB('loads_v2_dash', {})
  47. }, [])
  48. return isLoading ? (
  49. <div className="loading-container">
  50. <LoadingBranded loadProgress={loadProgress} />
  51. </div>
  52. ) : (
  53. <>
  54. <SystemMessages />
  55. <div className="project-list-wrapper clearfix">
  56. {totalProjectsCount > 0 ? (
  57. <>
  58. <Sidebar />
  59. <div className="project-list-main-react">
  60. {error ? <DashApiError /> : ''}
  61. <Row>
  62. <Col xs={12}>
  63. <UserNotifications />
  64. </Col>
  65. </Row>
  66. <Row>
  67. <Col md={7} className="hidden-xs">
  68. <SearchForm
  69. inputValue={searchText}
  70. setInputValue={setSearchText}
  71. />
  72. </Col>
  73. <Col md={5}>
  74. <div className="project-tools">
  75. <div className="hidden-xs">
  76. {selectedProjects.length === 0 ? (
  77. <CurrentPlanWidget />
  78. ) : (
  79. <ProjectTools />
  80. )}
  81. </div>
  82. <div className="visible-xs">
  83. <CurrentPlanWidget />
  84. </div>
  85. </div>
  86. </Col>
  87. </Row>
  88. <div className="project-list-sidebar-survey-wrapper visible-xs">
  89. <SurveyWidget />
  90. </div>
  91. <div className="visible-xs mt-1">
  92. <div role="toolbar" className="projects-toolbar">
  93. <ProjectsDropdown />
  94. <SortByDropdown />
  95. </div>
  96. </div>
  97. <Row className="row-spaced">
  98. <Col xs={12}>
  99. <div className="card project-list-card">
  100. <div className="visible-xs pt-2 pb-3">
  101. <div className="clearfix">
  102. <NewProjectButton
  103. id="new-project-button-projects-table"
  104. className="pull-left me-2"
  105. showAddAffiliationWidget
  106. />
  107. <SearchForm
  108. inputValue={searchText}
  109. setInputValue={setSearchText}
  110. className="overflow-hidden"
  111. formGroupProps={{ className: 'mb-0' }}
  112. />
  113. </div>
  114. </div>
  115. <ProjectListTable />
  116. </div>
  117. </Col>
  118. </Row>
  119. <Row className="row-spaced">
  120. <Col xs={12}>
  121. <LoadMore />
  122. </Col>
  123. </Row>
  124. </div>
  125. </>
  126. ) : (
  127. <div className="project-list-welcome-wrapper">
  128. {error ? <DashApiError /> : ''}
  129. <Row className="row-spaced">
  130. <Col
  131. sm={10}
  132. smOffset={1}
  133. md={8}
  134. mdOffset={2}
  135. className="project-list-empty-col"
  136. >
  137. <Row>
  138. <Col xs={12}>
  139. <UserNotifications />
  140. </Col>
  141. </Row>
  142. <WelcomeMessage />
  143. </Col>
  144. </Row>
  145. </div>
  146. )}
  147. </div>
  148. </>
  149. )
  150. }
  151. function DashApiError() {
  152. const { t } = useTranslation()
  153. return (
  154. <Row className="row-spaced">
  155. <Col xs={8} xsOffset={2} aria-live="polite" className="text-center">
  156. <div className="alert alert-danger">
  157. {t('generic_something_went_wrong')}
  158. </div>
  159. </Col>
  160. </Row>
  161. )
  162. }
  163. export default ProjectListRoot