import React, { Component, Fragment } from 'react'; import { withRouter } from 'react-router-dom'; import { I18n, i18nMark } from '@lingui/react'; import { Trans, t } from '@lingui/macro'; import { Card, EmptyState, EmptyStateIcon, EmptyStateBody, Modal, PageSection, PageSectionVariants, Title, Button, Progress, ProgressVariant } from '@patternfly/react-core'; import { CubesIcon } from '@patternfly/react-icons'; import DataListToolbar from '../../../components/DataListToolbar'; import OrganizationListItem from '../components/OrganizationListItem'; import Pagination from '../../../components/Pagination'; import { encodeQueryString, parseQueryString, } from '../../../qs'; class OrganizationsList extends Component { columns = [ { name: i18nMark('Name'), key: 'name', isSortable: true }, { name: i18nMark('Modified'), key: 'modified', isSortable: true, isNumeric: true }, { name: i18nMark('Created'), key: 'created', isSortable: true, isNumeric: true }, ]; defaultParams = { page: 1, page_size: 5, order_by: 'name', }; constructor (props) { super(props); const { page, page_size } = this.getQueryParams(); this.state = { page, page_size, sortedColumnKey: 'name', sortOrder: 'ascending', count: null, error: null, loading: true, results: [], selected: [], isModalOpen: false, orgsToDelete: [], orgsDeleted: [], deleteSuccess: false, }; this.onSearch = this.onSearch.bind(this); this.getQueryParams = this.getQueryParams.bind(this); this.onSort = this.onSort.bind(this); this.onSetPage = this.onSetPage.bind(this); this.onSelectAll = this.onSelectAll.bind(this); this.onSelect = this.onSelect.bind(this); this.updateUrl = this.updateUrl.bind(this); this.fetchOrganizations = this.fetchOrganizations.bind(this); this.handleOrgDelete = this.handleOrgDelete.bind(this); this.handleOpenOrgDeleteModal = this.handleOpenOrgDeleteModal.bind(this); this.handleClearOrgsToDelete = this.handleClearOrgsToDelete.bind(this); } componentDidMount () { const queryParams = this.getQueryParams(); this.fetchOrganizations(queryParams); } onSearch () { const { sortedColumnKey, sortOrder } = this.state; this.onSort(sortedColumnKey, sortOrder); } onSort (sortedColumnKey, sortOrder) { const { page_size } = this.state; let order_by = sortedColumnKey; if (sortOrder === 'descending') { order_by = `-${order_by}`; } const queryParams = this.getQueryParams({ order_by, page_size }); this.fetchOrganizations(queryParams); } onSetPage (pageNumber, pageSize) { const page = parseInt(pageNumber, 10); const page_size = parseInt(pageSize, 10); const queryParams = this.getQueryParams({ page, page_size }); this.fetchOrganizations(queryParams); } onSelectAll (isSelected) { const { results } = this.state; const selected = isSelected ? results.map(o => o.id) : []; this.setState({ selected }); } onSelect (id) { const { selected } = this.state; const isSelected = selected.includes(id); if (isSelected) { this.setState({ selected: selected.filter(s => s !== id) }); } else { this.setState({ selected: selected.concat(id) }); } } getQueryParams (overrides = {}) { const { location } = this.props; const { search } = location; const searchParams = parseQueryString(search.substring(1)); return Object.assign({}, this.defaultParams, searchParams, overrides); } handleClearOrgsToDelete () { this.setState({ isModalOpen: false, orgsDeleted: [], deleteSuccess: false, orgsToDelete: [], deleteStarted: false }); this.onSelectAll(); } handleOpenOrgDeleteModal () { const { results, selected } = this.state; const warningTitle = i18nMark('Delete Organization'); const warningMsg = i18nMark('Are you sure you want to delete:'); const orgsToDelete = []; results.forEach((result) => { selected.forEach((selectedOrg) => { if (result.id === selectedOrg) { orgsToDelete.push({ name: result.name, id: selectedOrg }); } }); }); this.setState({ orgsToDelete, isModalOpen: true, warningTitle, warningMsg, loading: false }); } async handleOrgDelete (event) { const { orgsToDelete, orgsDeleted } = this.state; const { api } = this.props; this.setState({ deleteStarted: true }); orgsToDelete.forEach(async (org) => { try { const res = await api.destroyOrganization(org.id); this.setState({ orgsDeleted: orgsDeleted.concat(res) }); } catch { this.setState({ deleteSuccess: false }); } finally { this.setState({ deleteSuccess: true }); const queryParams = this.getQueryParams(); this.fetchOrganizations(queryParams); } }); event.preventDefault(); } updateUrl (queryParams) { const { history, location } = this.props; const pathname = '/organizations'; const search = `?${encodeQueryString(queryParams)}`; if (search !== location.search) { history.replace({ pathname, search }); } } async fetchOrganizations (queryParams) { const { api } = this.props; const { page, page_size, order_by } = queryParams; let sortOrder = 'ascending'; let sortedColumnKey = order_by; if (order_by.startsWith('-')) { sortOrder = 'descending'; sortedColumnKey = order_by.substring(1); } this.setState({ error: false, loading: true }); try { const { data } = await api.getOrganizations(queryParams); const { count, results } = data; const pageCount = Math.ceil(count / page_size); const stateToUpdate = { count, page, pageCount, page_size, sortOrder, sortedColumnKey, results, selected: [], }; // This is in place to track whether or not the initial request // return any results. If it did not, we show the empty state. // This will become problematic once search is in play because // the first load may have query params (think bookmarked search) if (typeof noInitialResults === 'undefined') { stateToUpdate.noInitialResults = results.length === 0; } this.setState(stateToUpdate); this.updateUrl(queryParams); } catch (err) { this.setState({ error: true }); } finally { this.setState({ loading: false }); } } render () { const { medium, } = PageSectionVariants; const { count, error, deleteSuccess, deleteStarted, loading, noInitialResults, orgsToDelete, orgsDeleted, page, pageCount, page_size, selected, sortedColumnKey, sortOrder, results, isModalOpen, warningTitle, warningMsg, } = this.state; const { match } = this.props; return ( { isModalOpen && ( {warningMsg}
{orgsToDelete.map((org) => ( {org.name}
))}

{orgsDeleted.length ? : ( )}
)} {noInitialResults && ( <Trans>No Organizations Found</Trans> Please add an organization to populate this list ) || ( {({ i18n }) => (
    { results.map(o => ( this.onSelect(o.id, o.name)} onOpenOrgDeleteModal={this.handleOpenOrgDeleteModal} /> ))}
)}
{ loading ?
loading...
: '' } { error ?
error
: '' }
)}
); } } export default withRouter(OrganizationsList);